diff options
Diffstat (limited to 'components/layout_2020')
-rw-r--r-- | components/layout_2020/Cargo.toml | 1 | ||||
-rw-r--r-- | components/layout_2020/display_list/stacking_context.rs | 495 |
2 files changed, 352 insertions, 144 deletions
diff --git a/components/layout_2020/Cargo.toml b/components/layout_2020/Cargo.toml index c44c8ef635d..31f7214be25 100644 --- a/components/layout_2020/Cargo.toml +++ b/components/layout_2020/Cargo.toml @@ -38,6 +38,7 @@ script_traits = { path = "../script_traits" } serde = { workspace = true } serde_json = { workspace = true } servo_arc = { path = "../servo_arc" } +servo_config = { path = "../config" } servo_url = { path = "../url" } style = { path = "../style", features = ["servo"] } style_traits = { path = "../style_traits" } diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs index e38d5894705..f526b195012 100644 --- a/components/layout_2020/display_list/stacking_context.rs +++ b/components/layout_2020/display_list/stacking_context.rs @@ -2,12 +2,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::cmp::Ordering; +use std::cell::RefCell; use std::mem; use euclid::default::Rect; +use gfx_traits::print_tree::PrintTree; +use log::warn; use script_traits::compositor::{ScrollTreeNodeId, ScrollableNodeInfo}; use servo_arc::Arc as ServoArc; +use servo_config::opts::DebugOptions; use style::computed_values::float::T as ComputedFloat; use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode; use style::computed_values::overflow_x::T as ComputedOverflow; @@ -70,14 +73,18 @@ pub(crate) type ContainingBlockInfo<'a> = ContainingBlockManager<'a, ContainingB #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub(crate) enum StackingContextSection { - BackgroundsAndBorders, - BlockBackgroundsAndBorders, - Content, + OwnBackgroundsAndBorders, + DescendantBackgroundsAndBorders, + Foreground, Outline, } impl DisplayList { - pub fn build_stacking_context_tree(&mut self, fragment_tree: &FragmentTree) -> StackingContext { + pub fn build_stacking_context_tree( + &mut self, + fragment_tree: &FragmentTree, + debug: &DebugOptions, + ) -> StackingContext { let root_clip_chain_id = self .wr .define_clip_chain(None, [wr::ClipId::root(self.wr.pipeline_id)]); @@ -105,7 +112,7 @@ impl DisplayList { for_absolute_and_fixed_descendants: &cb_for_fixed_descendants, }; - let mut root_stacking_context = StackingContext::create_root(&self.wr); + let mut root_stacking_context = StackingContext::create_root(&self.wr, debug); for fragment in &fragment_tree.root_fragments { fragment.borrow().build_stacking_context_tree( fragment, @@ -192,37 +199,73 @@ impl DisplayList { } } -pub(crate) struct StackingContextFragment { - scroll_node_id: ScrollTreeNodeId, - clip_chain_id: wr::ClipChainId, - section: StackingContextSection, - containing_block: PhysicalRect<Length>, - fragment: ArcRefCell<Fragment>, +/// A piece of content that directly belongs to a section of a stacking context. +/// +/// This is generally part of a fragment, like its borders or foreground, but it +/// can also be a stacking container that needs to be painted in fragment order. +pub(crate) enum StackingContextContent { + /// A fragment that does not generate a stacking context or stacking container. + Fragment { + scroll_node_id: ScrollTreeNodeId, + clip_chain_id: wr::ClipChainId, + section: StackingContextSection, + containing_block: PhysicalRect<Length>, + fragment: ArcRefCell<Fragment>, + }, + + /// An index into [StackingContext::atomic_inline_stacking_containers]. + /// + /// There is no section field, because these are always in [StackingContextSection::Foreground]. + AtomicInlineStackingContainer { index: usize }, } -impl StackingContextFragment { - fn build_display_list(&self, builder: &mut DisplayListBuilder) { - builder.current_scroll_node_id = self.scroll_node_id; - builder.current_clip_chain_id = self.clip_chain_id; - self.fragment - .borrow() - .build_display_list(builder, &self.containing_block, self.section); +impl StackingContextContent { + fn section(&self) -> StackingContextSection { + match self { + Self::Fragment { section, .. } => *section, + Self::AtomicInlineStackingContainer { .. } => StackingContextSection::Foreground, + } + } + + fn build_display_list( + &self, + builder: &mut DisplayListBuilder, + inline_stacking_containers: &[StackingContext], + ) { + match self { + Self::Fragment { + scroll_node_id, + clip_chain_id, + section, + containing_block, + fragment, + } => { + builder.current_scroll_node_id = *scroll_node_id; + builder.current_clip_chain_id = *clip_chain_id; + fragment + .borrow() + .build_display_list(builder, containing_block, *section); + }, + Self::AtomicInlineStackingContainer { index } => { + inline_stacking_containers[*index].build_display_list(builder); + }, + } } } -#[derive(Clone, Copy, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub(crate) enum StackingContextType { - Real, - PseudoPositioned, - PseudoFloat, - PseudoAtomicInline, + RealStackingContext, + PositionedStackingContainer, + FloatStackingContainer, + AtomicInlineStackingContainer, } -/// A [StackingContext] represents either a stacking context or a stacking -/// container according to the definitions outlined in -/// <https://drafts.csswg.org/css-position-4/#painting-order> -/// Stacking containers are sometimes called "pseudo-stacking contexts" -/// in the Servo source. +/// Either a stacking context or a stacking container, per the definitions in +/// <https://drafts.csswg.org/css-position-4/#painting-order>. +/// +/// We use the term “real stacking context” in situations that call for a +/// stacking context but not a stacking container. pub struct StackingContext { /// The spatial id of this fragment. This is used to properly handle /// things like preserve-3d. @@ -231,34 +274,61 @@ pub struct StackingContext { /// The fragment that established this stacking context. initializing_fragment_style: Option<ServoArc<ComputedValues>>, - /// The type of this StackingContext. Used for collecting and sorting. + /// The type of this stacking context. Used for collecting and sorting. context_type: StackingContextType, - /// Fragments that make up the content of this stacking context. - fragments: Vec<StackingContextFragment>, - - /// All non-float stacking context and pseudo stacking context children - /// of this stacking context. - stacking_contexts: Vec<StackingContext>, + /// The contents that need to be painted in fragment order. + contents: Vec<StackingContextContent>, - /// All float stacking container children of this stacking context. - /// These are stored separately because they should not be passed up to - /// their real stacking context ancestors. From the definition of stacking - /// containers from <https://drafts.csswg.org/css-position-4#painting-order>: - /// + /// Stacking contexts that need to be stolen by the parent stacking context + /// if this is a stacking container, that is, real stacking contexts and + /// positioned stacking containers (where ‘z-index’ is auto). + /// <https://drafts.csswg.org/css-position-4/#paint-a-stacking-container> /// > To paint a stacking container, given a box root and a canvas canvas: /// > 1. Paint a stacking context given root and canvas, treating root as /// > if it created a new stacking context, but omitting any positioned /// > descendants or descendants that actually create a stacking context /// > (letting the parent stacking context paint them, instead). - /// - /// Note that all stacking containers / pseudo stacking contexts are passed up - /// to parent stacking contexts, except in the case of floats. - float_stacking_contexts: Vec<StackingContext>, + real_stacking_contexts_and_positioned_stacking_containers: Vec<StackingContext>, + + /// Float stacking containers. + /// Separate from real_stacking_contexts_or_positioned_stacking_containers + /// because they should never be stolen by the parent stacking context. + /// <https://drafts.csswg.org/css-position-4/#paint-a-stacking-container> + float_stacking_containers: Vec<StackingContext>, + + /// Atomic inline stacking containers. + /// Separate from real_stacking_contexts_or_positioned_stacking_containers + /// because they should never be stolen by the parent stacking context, and + /// separate from float_stacking_containers so that [StackingContextContent] + /// can index into this vec to paint them in fragment order. + /// <https://drafts.csswg.org/css-position-4/#paint-a-stacking-container> + /// <https://drafts.csswg.org/css-position-4/#paint-a-box-in-a-line-box> + atomic_inline_stacking_containers: Vec<StackingContext>, + + /// Information gathered about the painting order, for [Self::debug_print]. + debug_print_items: Option<RefCell<Vec<DebugPrintItem>>>, +} + +/// Refers to one of the child contents or stacking contexts of a [StackingContext]. +#[derive(Clone, Copy)] +pub struct DebugPrintItem { + field: DebugPrintField, + index: usize, +} + +/// Refers to one of the vecs of a [StackingContext]. +#[derive(Clone, Copy)] +pub enum DebugPrintField { + Contents, + RealStackingContextsAndPositionedStackingContainers, + FloatStackingContainers, + AtomicInlineStackingContainers, } impl StackingContext { - pub(crate) fn new( + fn create_descendant( + &self, spatial_id: wr::SpatialId, initializing_fragment_style: ServoArc<ComputedValues>, context_type: StackingContextType, @@ -267,30 +337,42 @@ impl StackingContext { spatial_id, initializing_fragment_style: Some(initializing_fragment_style), context_type, - fragments: vec![], - stacking_contexts: vec![], - float_stacking_contexts: vec![], + contents: vec![], + real_stacking_contexts_and_positioned_stacking_containers: vec![], + float_stacking_containers: vec![], + atomic_inline_stacking_containers: vec![], + debug_print_items: self.debug_print_items.is_some().then(|| vec![].into()), } } - pub(crate) fn create_root(wr: &wr::DisplayListBuilder) -> Self { + pub(crate) fn create_root(wr: &wr::DisplayListBuilder, debug: &DebugOptions) -> Self { Self { spatial_id: wr::SpaceAndClipInfo::root_scroll(wr.pipeline_id).spatial_id, initializing_fragment_style: None, - context_type: StackingContextType::Real, - fragments: vec![], - stacking_contexts: vec![], - float_stacking_contexts: vec![], + context_type: StackingContextType::RealStackingContext, + contents: vec![], + real_stacking_contexts_and_positioned_stacking_containers: vec![], + float_stacking_containers: vec![], + atomic_inline_stacking_containers: vec![], + debug_print_items: debug.dump_stacking_context_tree.then(|| vec![].into()), } } /// Add a child stacking context to this stacking context. fn add_stacking_context(&mut self, stacking_context: StackingContext) { - if stacking_context.context_type == StackingContextType::PseudoFloat { - self.float_stacking_contexts.push(stacking_context); - } else { - self.stacking_contexts.push(stacking_context); + match stacking_context.context_type { + StackingContextType::RealStackingContext => { + &mut self.real_stacking_contexts_and_positioned_stacking_containers + }, + StackingContextType::PositionedStackingContainer => { + &mut self.real_stacking_contexts_and_positioned_stacking_containers + }, + StackingContextType::FloatStackingContainer => &mut self.float_stacking_containers, + StackingContextType::AtomicInlineStackingContainer => { + &mut self.atomic_inline_stacking_containers + }, } + .push(stacking_context) } fn z_index(&self) -> i32 { @@ -300,24 +382,32 @@ impl StackingContext { } pub(crate) fn sort(&mut self) { - self.fragments.sort_by(|a, b| a.section.cmp(&b.section)); - - self.stacking_contexts.sort_by(|a, b| { - let a_z_index = a.z_index(); - let b_z_index = b.z_index(); - if a_z_index != 0 || b_z_index != 0 { - return a_z_index.cmp(&b_z_index); - } + self.contents.sort_by(|a, b| a.section().cmp(&b.section())); + self.real_stacking_contexts_and_positioned_stacking_containers + .sort_by(|a, b| a.z_index().cmp(&b.z_index())); - match (a.context_type, b.context_type) { - (StackingContextType::PseudoFloat, StackingContextType::PseudoFloat) => { - Ordering::Equal - }, - (StackingContextType::PseudoFloat, _) => Ordering::Less, - (_, StackingContextType::PseudoFloat) => Ordering::Greater, - (_, _) => Ordering::Equal, - } - }); + debug_assert!(self + .real_stacking_contexts_and_positioned_stacking_containers + .iter() + .all(|c| match c.context_type { + StackingContextType::RealStackingContext | + StackingContextType::PositionedStackingContainer => true, + _ => false, + })); + debug_assert!(self + .float_stacking_containers + .iter() + .all( + |c| c.context_type == StackingContextType::FloatStackingContainer && + c.z_index() == 0 + )); + debug_assert!(self + .atomic_inline_stacking_containers + .iter() + .all( + |c| c.context_type == StackingContextType::AtomicInlineStackingContainer && + c.z_index() == 0 + )); } fn push_webrender_stacking_context_if_necessary( @@ -421,20 +511,23 @@ impl StackingContext { // Let’s find the corresponding fragment. // The fragment generated by the root element is the first one here, unless… - let first_if_any = self.fragments.first().or_else(|| { + let first_if_any = self.contents.first().or_else(|| { // There wasn’t any `StackingContextFragment` in the root `StackingContext`, // because the root element generates a stacking context. Let’s find that one. - self.stacking_contexts + self.real_stacking_contexts_and_positioned_stacking_containers .first() .and_then(|first_child_stacking_context| { - first_child_stacking_context.fragments.first() + first_child_stacking_context.contents.first() }) }); macro_rules! debug_panic { ($msg: expr) => { if cfg!(debug_assertions) { - panic!($msg) + panic!($msg); + } else { + warn!($msg); + return; } }; } @@ -444,15 +537,17 @@ impl StackingContext { } else { // This should only happen if the root element has `display: none` debug_panic!("`CanvasBackground::for_root_element` should have returned `style: None`"); - return; }; - let fragment = first_stacking_context_fragment.fragment.borrow(); + let StackingContextContent::Fragment { fragment, scroll_node_id, containing_block, .. } + = first_stacking_context_fragment else { + debug_panic!("Expected a fragment, not a stacking container"); + }; + let fragment = fragment.borrow(); let box_fragment = match &*fragment { Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => box_fragment, _ => { debug_panic!("Expected a box-generated fragment"); - return; }, }; @@ -465,7 +560,7 @@ impl StackingContext { // The root element may have a CSS transform, and we want the canvas’ // background image to be transformed. To do so, take its `SpatialId` // (but not its `ClipId`) - builder.current_scroll_node_id = first_stacking_context_fragment.scroll_node_id; + builder.current_scroll_node_id = *scroll_node_id; // Now we need express the painting area rectangle in the local coordinate system, // which differs from the top-level coordinate system based on… @@ -487,10 +582,8 @@ impl StackingContext { } } - let mut fragment_builder = super::BuilderForBoxFragment::new( - box_fragment, - &first_stacking_context_fragment.containing_block, - ); + let mut fragment_builder = + super::BuilderForBoxFragment::new(box_fragment, containing_block); let source = super::background::Source::Canvas { style, painting_area, @@ -501,63 +594,159 @@ impl StackingContext { pub(crate) fn build_display_list(&self, builder: &mut DisplayListBuilder) { let pushed_context = self.push_webrender_stacking_context_if_necessary(builder); - // Properly order display items that make up a stacking context. "Steps" here - // refer to the steps in CSS 2.1 Appendix E. + // Properly order display items that make up a stacking context. + // “Steps” here refer to the steps in CSS 2.1 Appendix E. + // Note that “positioned descendants” is generalised to include all descendants that + // generate stacking contexts (csswg-drafts#2717), except in the phrase “any positioned + // descendants or descendants that actually create a stacking context”, where the term + // means positioned descendants that do not generate stacking contexts. // Steps 1 and 2: Borders and background for the root - let mut child_fragments = self.fragments.iter().peekable(); - while child_fragments.peek().map_or(false, |child| { - child.section == StackingContextSection::BackgroundsAndBorders + let mut contents = self.contents.iter().enumerate().peekable(); + while contents.peek().map_or(false, |(_, child)| { + child.section() == StackingContextSection::OwnBackgroundsAndBorders }) { - child_fragments.next().unwrap().build_display_list(builder); + let (i, child) = contents.next().unwrap(); + self.debug_push_print_item(DebugPrintField::Contents, i); + child.build_display_list(builder, &self.atomic_inline_stacking_containers); } - // Step 3: Positioned descendants with negative z-indices - let mut child_stacking_contexts = self.stacking_contexts.iter().peekable(); - while child_stacking_contexts + // Step 3: Stacking contexts with negative ‘z-index’ + let mut real_stacking_contexts_and_positioned_stacking_containers = self + .real_stacking_contexts_and_positioned_stacking_containers + .iter() + .enumerate() + .peekable(); + while real_stacking_contexts_and_positioned_stacking_containers .peek() - .map_or(false, |child| child.z_index() < 0) + .map_or(false, |(_, child)| child.z_index() < 0) { - let child_context = child_stacking_contexts.next().unwrap(); - child_context.build_display_list(builder); + let (i, child) = real_stacking_contexts_and_positioned_stacking_containers + .next() + .unwrap(); + self.debug_push_print_item( + DebugPrintField::RealStackingContextsAndPositionedStackingContainers, + i, + ); + child.build_display_list(builder); } // Step 4: Block backgrounds and borders - while child_fragments.peek().map_or(false, |child| { - child.section == StackingContextSection::BlockBackgroundsAndBorders + while contents.peek().map_or(false, |(_, child)| { + child.section() == StackingContextSection::DescendantBackgroundsAndBorders }) { - child_fragments.next().unwrap().build_display_list(builder); + let (i, child) = contents.next().unwrap(); + self.debug_push_print_item(DebugPrintField::Contents, i); + child.build_display_list(builder, &self.atomic_inline_stacking_containers); } - // Step 5: Floats - for child_context in &self.float_stacking_contexts { - child_context.build_display_list(builder); + // Step 5: Float stacking containers + for (i, child) in self.float_stacking_containers.iter().enumerate() { + self.debug_push_print_item(DebugPrintField::FloatStackingContainers, i); + child.build_display_list(builder); } - // Step 6: Content - while child_fragments.peek().map_or(false, |child| { - child.section == StackingContextSection::Content + // Steps 6 and 7: Fragments and inline stacking containers + while contents.peek().map_or(false, |(_, child)| { + child.section() == StackingContextSection::Foreground }) { - child_fragments.next().unwrap().build_display_list(builder); + let (i, child) = contents.next().unwrap(); + self.debug_push_print_item(DebugPrintField::Contents, i); + child.build_display_list(builder, &self.atomic_inline_stacking_containers); } - // Step 7, 8 & 9: Inlines that generate stacking contexts and positioned - // descendants with nonnegative, numeric z-indices - for child_context in child_stacking_contexts { - child_context.build_display_list(builder); + // Steps 8 and 9: Stacking contexts with non-negative ‘z-index’, and + // positioned stacking containers (where ‘z-index’ is auto) + for (i, child) in real_stacking_contexts_and_positioned_stacking_containers { + self.debug_push_print_item( + DebugPrintField::RealStackingContextsAndPositionedStackingContainers, + i, + ); + child.build_display_list(builder); } // Step 10: Outline - while child_fragments.peek().map_or(false, |child| { - child.section == StackingContextSection::Outline + while contents.peek().map_or(false, |(_, child)| { + child.section() == StackingContextSection::Outline }) { - child_fragments.next().unwrap().build_display_list(builder); + let (i, child) = contents.next().unwrap(); + self.debug_push_print_item(DebugPrintField::Contents, i); + child.build_display_list(builder, &self.atomic_inline_stacking_containers); } if pushed_context { builder.display_list.wr.pop_stacking_context(); } } + + /// Store the fact that something was painted, if [Self::debug_print_items] is not None. + /// + /// This is used to help reconstruct the original painting order in [Self::debug_print] without + /// duplicating our painting order logic, since that could fall out of sync with the real logic. + fn debug_push_print_item(&self, field: DebugPrintField, index: usize) { + if let Some(items) = self.debug_print_items.as_ref() { + items.borrow_mut().push(DebugPrintItem { field, index }); + } + } + + /// Print the stacking context tree. + pub fn debug_print(&self) { + if self.debug_print_items.is_none() { + warn!("failed to print stacking context tree: debug_print_items was None"); + return; + } + let mut tree = PrintTree::new("Stacking context tree".to_owned()); + self.debug_print_with_tree(&mut tree); + } + + /// Print a subtree with the given [PrintTree], or panic if [Self::debug_print_items] is None. + fn debug_print_with_tree(&self, tree: &mut PrintTree) { + match self.context_type { + StackingContextType::RealStackingContext => { + tree.new_level(format!("{:?} z={}", self.context_type, self.z_index())); + }, + StackingContextType::AtomicInlineStackingContainer => { + // do nothing; we print the heading with its index in DebugPrintField::Contents + }, + _ => { + tree.new_level(format!("{:?}", self.context_type)); + }, + } + for DebugPrintItem { field, index } in + self.debug_print_items.as_ref().unwrap().borrow().iter() + { + match field { + DebugPrintField::Contents => match self.contents[*index] { + StackingContextContent::Fragment { section, .. } => { + tree.add_item(format!("{:?}", section)); + }, + StackingContextContent::AtomicInlineStackingContainer { index } => { + tree.new_level(format!("AtomicInlineStackingContainer #{}", index)); + self.atomic_inline_stacking_containers[index].debug_print_with_tree(tree); + tree.end_level(); + }, + }, + DebugPrintField::RealStackingContextsAndPositionedStackingContainers => { + self.real_stacking_contexts_and_positioned_stacking_containers[*index] + .debug_print_with_tree(tree); + }, + DebugPrintField::FloatStackingContainers => { + self.float_stacking_containers[*index].debug_print_with_tree(tree); + }, + DebugPrintField::AtomicInlineStackingContainers => { + // do nothing; we print these in DebugPrintField::Contents + }, + } + } + match self.context_type { + StackingContextType::AtomicInlineStackingContainer => { + // do nothing; we print the heading with its index in DebugPrintField::Contents + }, + _ => { + tree.end_level(); + }, + } + } } #[derive(PartialEq)] @@ -624,13 +813,15 @@ impl Fragment { ); }, Fragment::Text(_) | Fragment::Image(_) | Fragment::IFrame(_) => { - stacking_context.fragments.push(StackingContextFragment { - section: StackingContextSection::Content, - scroll_node_id: containing_block.scroll_node_id, - clip_chain_id: containing_block.clip_chain_id, - containing_block: containing_block.rect, - fragment: fragment_ref.clone(), - }); + stacking_context + .contents + .push(StackingContextContent::Fragment { + section: StackingContextSection::Foreground, + scroll_node_id: containing_block.scroll_node_id, + clip_chain_id: containing_block.clip_chain_id, + containing_block: containing_block.rect, + fragment: fragment_ref.clone(), + }); }, } } @@ -645,20 +836,20 @@ struct ReferenceFrameData { impl BoxFragment { fn get_stacking_context_type(&self) -> Option<StackingContextType> { if self.style.establishes_stacking_context() { - return Some(StackingContextType::Real); + return Some(StackingContextType::RealStackingContext); } let box_style = &self.style.get_box(); if box_style.position != ComputedPosition::Static { - return Some(StackingContextType::PseudoPositioned); + return Some(StackingContextType::PositionedStackingContainer); } if box_style.float != ComputedFloat::None { - return Some(StackingContextType::PseudoFloat); + return Some(StackingContextType::FloatStackingContainer); } if box_style.display.is_atomic_inline_level() { - return Some(StackingContextType::PseudoAtomicInline); + return Some(StackingContextType::AtomicInlineStackingContainer); } None @@ -666,14 +857,14 @@ impl BoxFragment { fn get_stacking_context_section(&self) -> StackingContextSection { if self.get_stacking_context_type().is_some() { - return StackingContextSection::BackgroundsAndBorders; + return StackingContextSection::OwnBackgroundsAndBorders; } if self.style.get_box().display.outside() == DisplayOutside::Inline { - return StackingContextSection::Content; + return StackingContextSection::Foreground; } - StackingContextSection::BlockBackgroundsAndBorders + StackingContextSection::DescendantBackgroundsAndBorders } fn build_stacking_context_tree( @@ -778,7 +969,18 @@ impl BoxFragment { }, }; - let mut child_stacking_context = StackingContext::new( + if context_type == StackingContextType::AtomicInlineStackingContainer { + // Push a dummy fragment that indicates when the new stacking context should be painted. + parent_stacking_context.contents.push( + StackingContextContent::AtomicInlineStackingContainer { + index: parent_stacking_context + .atomic_inline_stacking_containers + .len(), + }, + ); + } + + let mut child_stacking_context = parent_stacking_context.create_descendant( containing_block.scroll_node_id.spatial_id, self.style.clone(), context_type, @@ -792,9 +994,10 @@ impl BoxFragment { ); let mut stolen_children = vec![]; - if context_type != StackingContextType::Real { + if context_type != StackingContextType::RealStackingContext { stolen_children = mem::replace( - &mut child_stacking_context.stacking_contexts, + &mut child_stacking_context + .real_stacking_contexts_and_positioned_stacking_containers, stolen_children, ); } @@ -802,7 +1005,7 @@ impl BoxFragment { child_stacking_context.sort(); parent_stacking_context.add_stacking_context(child_stacking_context); parent_stacking_context - .stacking_contexts + .real_stacking_contexts_and_positioned_stacking_containers .append(&mut stolen_children); } @@ -825,21 +1028,25 @@ impl BoxFragment { new_clip_chain_id = clip_chain_id; } - stacking_context.fragments.push(StackingContextFragment { - scroll_node_id: new_scroll_node_id, - clip_chain_id: new_clip_chain_id, - section: self.get_stacking_context_section(), - containing_block: containing_block.rect, - fragment: fragment.clone(), - }); - if self.style.get_outline().outline_width.px() > 0.0 { - stacking_context.fragments.push(StackingContextFragment { + stacking_context + .contents + .push(StackingContextContent::Fragment { scroll_node_id: new_scroll_node_id, clip_chain_id: new_clip_chain_id, - section: StackingContextSection::Outline, + section: self.get_stacking_context_section(), containing_block: containing_block.rect, fragment: fragment.clone(), }); + if self.style.get_outline().outline_width.px() > 0.0 { + stacking_context + .contents + .push(StackingContextContent::Fragment { + scroll_node_id: new_scroll_node_id, + clip_chain_id: new_clip_chain_id, + section: StackingContextSection::Outline, + containing_block: containing_block.rect, + fragment: fragment.clone(), + }); } // We want to build the scroll frame after the background and border, because |