diff options
author | Martin Robinson <mrobinson@igalia.com> | 2025-04-18 11:40:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-18 09:40:29 +0000 |
commit | 2ee8427665099987f715296d4d55b6388a480c08 (patch) | |
tree | a1c3595c8f6837abfcd01c729c2d8edcead26327 | |
parent | fc201927ae5bdf26f842f9d4e6e52c2255adcde2 (diff) | |
download | servo-2ee8427665099987f715296d4d55b6388a480c08.tar.gz servo-2ee8427665099987f715296d4d55b6388a480c08.zip |
layout: Store `Fragment` results in `LayoutBoxBase` and start using them for queries (#36583)
Start storing a link to laid-out `Fragment`s in `LayoutBoxBase`, so that
these are accessible for queries and eventually for incremental layout.
Some box tree data structures lacked a `LayoutBoxBase`, such as table
tracks and table track groups[^1].
In addition, start using these `Fragment`s for queries instead of
walking the entire `Fragment` tree. Currently, this isn't possible for
most queries as `Fragment`s do not cache their absolute offsets (which
are often necessary). This change uses the new box tree `Fragment`s for
most resolved style queries.
[^1]: Note that only rows and row groups store `Fragment`s as columsn
and
colgroups do not produce any.
Testing: This is covered by existing tests.
Fixes: This is part of #36525.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
-rw-r--r-- | components/layout_2020/dom.rs | 38 | ||||
-rw-r--r-- | components/layout_2020/flexbox/layout.rs | 14 | ||||
-rw-r--r-- | components/layout_2020/flexbox/mod.rs | 14 | ||||
-rw-r--r-- | components/layout_2020/flow/inline/inline_box.rs | 4 | ||||
-rw-r--r-- | components/layout_2020/flow/inline/line.rs | 83 | ||||
-rw-r--r-- | components/layout_2020/flow/inline/mod.rs | 41 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 32 | ||||
-rw-r--r-- | components/layout_2020/layout_box_base.rs | 18 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 15 | ||||
-rw-r--r-- | components/layout_2020/query.rs | 161 | ||||
-rw-r--r-- | components/layout_2020/table/construct.rs | 15 | ||||
-rw-r--r-- | components/layout_2020/table/layout.rs | 118 | ||||
-rw-r--r-- | components/layout_2020/table/mod.rs | 33 | ||||
-rw-r--r-- | components/layout_2020/taffy/layout.rs | 12 | ||||
-rw-r--r-- | components/layout_2020/taffy/mod.rs | 11 |
15 files changed, 387 insertions, 222 deletions
diff --git a/components/layout_2020/dom.rs b/components/layout_2020/dom.rs index c87c54d52ef..39cd74293c8 100644 --- a/components/layout_2020/dom.rs +++ b/components/layout_2020/dom.rs @@ -24,6 +24,7 @@ use crate::context::LayoutContext; use crate::flexbox::FlexLevelBox; use crate::flow::BlockLevelBox; use crate::flow::inline::InlineItem; +use crate::fragment_tree::Fragment; use crate::geom::PhysicalSize; use crate::replaced::{CanvasInfo, CanvasSource}; use crate::table::TableLevelBox; @@ -38,6 +39,20 @@ pub struct InnerDOMLayoutData { pub(super) pseudo_marker_box: ArcRefCell<Option<LayoutBox>>, } +impl InnerDOMLayoutData { + pub(crate) fn for_pseudo( + &self, + pseudo_element: Option<PseudoElement>, + ) -> AtomicRef<Option<LayoutBox>> { + match pseudo_element { + Some(PseudoElement::Before) => self.pseudo_before_box.borrow(), + Some(PseudoElement::After) => self.pseudo_after_box.borrow(), + Some(PseudoElement::Marker) => self.pseudo_marker_box.borrow(), + _ => self.self_box.borrow(), + } + } +} + /// A box that is stored in one of the `DOMLayoutData` slots. pub(super) enum LayoutBox { DisplayContents, @@ -67,6 +82,17 @@ impl LayoutBox { LayoutBox::TableLevelBox(table_box) => table_box.invalidate_cached_fragment(), } } + + pub(crate) fn fragments(&self) -> Vec<Fragment> { + match self { + LayoutBox::DisplayContents => vec![], + LayoutBox::BlockLevel(block_level_box) => block_level_box.borrow().fragments(), + LayoutBox::InlineLevel(inline_item) => inline_item.borrow().fragments(), + LayoutBox::FlexLevel(flex_level_box) => flex_level_box.borrow().fragments(), + LayoutBox::TaffyItemBox(taffy_item_box) => taffy_item_box.borrow().fragments(), + LayoutBox::TableLevelBox(table_box) => table_box.fragments(), + } + } } /// A wrapper for [`InnerDOMLayoutData`]. This is necessary to give the entire data @@ -138,6 +164,7 @@ pub(crate) trait NodeExt<'dom>: 'dom + LayoutNode<'dom> { /// Remove boxes for the element itself, and its `:before` and `:after` if any. fn unset_all_boxes(self); + fn fragments_for_pseudo(&self, pseudo_element: Option<PseudoElement>) -> Vec<Fragment>; fn invalidate_cached_fragment(self); } @@ -287,4 +314,15 @@ where data.invalidate_cached_fragment(); } } + + fn fragments_for_pseudo(&self, pseudo_element: Option<PseudoElement>) -> Vec<Fragment> { + NodeExt::layout_data(*self) + .and_then(|layout_data| { + layout_data + .for_pseudo(pseudo_element) + .as_ref() + .map(LayoutBox::fragments) + }) + .unwrap_or_default() + } } diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index 34904ae1053..77069236787 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -214,7 +214,7 @@ impl FlexLineItem<'_> { flex_context: &mut FlexContext, all_baselines: &mut Baselines, main_position_cursor: &mut Au, - ) -> (BoxFragment, PositioningContext) { + ) -> (ArcRefCell<BoxFragment>, PositioningContext) { // https://drafts.csswg.org/css-flexbox/#algo-main-align // “Align the items along the main-axis” *main_position_cursor += @@ -312,6 +312,12 @@ impl FlexLineItem<'_> { .to_physical_size(containing_block.style.writing_mode) } + let fragment = ArcRefCell::new(fragment); + self.item + .box_ + .independent_formatting_context + .base + .set_fragment(Fragment::Box(fragment.clone())); (fragment, self.layout_result.positioning_context) } } @@ -323,7 +329,7 @@ struct FinalFlexLineLayout { cross_size: Au, /// The [`BoxFragment`]s and [`PositioningContext`]s of all flex items, /// one per flex item in "order-modified document order." - item_fragments: Vec<(BoxFragment, PositioningContext)>, + item_fragments: Vec<(ArcRefCell<BoxFragment>, PositioningContext)>, /// The 'shared alignment baseline' of this flex line. This is the baseline used for /// baseline-aligned items if there are any, otherwise `None`. shared_alignment_baseline: Option<Au>, @@ -935,7 +941,7 @@ impl FlexContainer { let physical_line_position = flow_relative_line_position.to_physical_size(self.style.writing_mode); for (fragment, _) in &mut final_line_layout.item_fragments { - fragment.content_rect.origin += physical_line_position; + fragment.borrow_mut().content_rect.origin += physical_line_position; } final_line_layout.item_fragments }) @@ -957,7 +963,7 @@ impl FlexContainer { // per flex item, in the original order. let (fragment, mut child_positioning_context) = flex_item_fragments.next().unwrap(); - let fragment = Fragment::Box(ArcRefCell::new(fragment)); + let fragment = Fragment::Box(fragment); child_positioning_context.adjust_static_position_of_hoisted_fragments( &fragment, PositioningContextLength::zero(), diff --git a/components/layout_2020/flexbox/mod.rs b/components/layout_2020/flexbox/mod.rs index a69a9af5898..f51caca65e8 100644 --- a/components/layout_2020/flexbox/mod.rs +++ b/components/layout_2020/flexbox/mod.rs @@ -19,7 +19,7 @@ use crate::context::LayoutContext; use crate::dom::{LayoutBox, NodeExt}; use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents}; use crate::formatting_contexts::IndependentFormattingContext; -use crate::fragment_tree::BaseFragmentInfo; +use crate::fragment_tree::{BaseFragmentInfo, Fragment}; use crate::positioned::AbsolutelyPositionedBox; mod geom; @@ -157,6 +157,18 @@ impl FlexLevelBox { .invalidate_cached_fragment(), } } + + pub(crate) fn fragments(&self) -> Vec<Fragment> { + match self { + FlexLevelBox::FlexItem(flex_item_box) => flex_item_box + .independent_formatting_context + .base + .fragments(), + FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => { + positioned_box.borrow().context.base.fragments() + }, + } + } } pub(crate) struct FlexItemBox { diff --git a/components/layout_2020/flow/inline/inline_box.rs b/components/layout_2020/flow/inline/inline_box.rs index c14117b5651..2eceae944f2 100644 --- a/components/layout_2020/flow/inline/inline_box.rs +++ b/components/layout_2020/flow/inline/inline_box.rs @@ -73,6 +73,10 @@ impl InlineBoxes { self.inline_boxes.len() } + pub(super) fn iter(&self) -> impl Iterator<Item = &ArcRefCell<InlineBox>> { + self.inline_boxes.iter() + } + pub(super) fn get(&self, identifier: &InlineBoxIdentifier) -> ArcRefCell<InlineBox> { self.inline_boxes[identifier.index_in_inline_boxes as usize].clone() } diff --git a/components/layout_2020/flow/inline/line.rs b/components/layout_2020/flow/inline/line.rs index 145627a8f48..c42f32c9242 100644 --- a/components/layout_2020/flow/inline/line.rs +++ b/components/layout_2020/flow/inline/line.rs @@ -492,9 +492,11 @@ impl LineItemLayout<'_, '_> { } self.current_state.inline_advance += inner_state.inline_advance + pbm_sums.inline_sum(); - self.current_state - .fragments - .push((Fragment::Box(ArcRefCell::new(fragment)), content_rect)); + + let fragment = Fragment::Box(ArcRefCell::new(fragment)); + inline_box.base.add_fragment(fragment.clone()); + + self.current_state.fragments.push((fragment, content_rect)); } fn calculate_inline_box_block_start( @@ -587,32 +589,34 @@ impl LineItemLayout<'_, '_> { // This needs to be added to the calculated block and inline positions. // Make the final result relative to the parent box. let ifc_writing_mode = self.layout.containing_block.style.writing_mode; - let padding_border_margin_sides = atomic - .fragment - .padding_border_margin() - .to_logical(ifc_writing_mode); - - let mut atomic_offset = LogicalVec2 { - inline: self.current_state.inline_advance + padding_border_margin_sides.inline_start, - block: atomic.calculate_block_start(&self.line_metrics) - - self.current_state.parent_offset.block + - padding_border_margin_sides.block_start, - }; + let content_rect = { + let block_start = atomic.calculate_block_start(&self.line_metrics); + let atomic_fragment = atomic.fragment.borrow_mut(); + let padding_border_margin_sides = atomic_fragment + .padding_border_margin() + .to_logical(ifc_writing_mode); + + let mut atomic_offset = LogicalVec2 { + inline: self.current_state.inline_advance + + padding_border_margin_sides.inline_start, + block: block_start - self.current_state.parent_offset.block + + padding_border_margin_sides.block_start, + }; - if atomic.fragment.style.get_box().position == Position::Relative { - atomic_offset += - relative_adjustement(&atomic.fragment.style, self.layout.containing_block); - } + if atomic_fragment.style.get_box().position == Position::Relative { + atomic_offset += + relative_adjustement(&atomic_fragment.style, self.layout.containing_block); + } - // Reconstruct a logical rectangle relative to the inline box container that will be used - // after the inline box is procesed to find a final physical rectangle. - let content_rect = LogicalRect { - start_corner: atomic_offset, - size: atomic - .fragment - .content_rect - .size - .to_logical(ifc_writing_mode), + // Reconstruct a logical rectangle relative to the inline box container that will be used + // after the inline box is procesed to find a final physical rectangle. + LogicalRect { + start_corner: atomic_offset, + size: atomic_fragment + .content_rect + .size + .to_logical(ifc_writing_mode), + } }; if let Some(mut positioning_context) = atomic.positioning_context { @@ -628,10 +632,10 @@ impl LineItemLayout<'_, '_> { } self.current_state.inline_advance += atomic.size.inline; - self.current_state.fragments.push(( - Fragment::Box(ArcRefCell::new(atomic.fragment)), - content_rect, - )); + + self.current_state + .fragments + .push((Fragment::Box(atomic.fragment), content_rect)); } fn layout_absolute(&mut self, absolute: AbsolutelyPositionedLineItem) { @@ -691,7 +695,7 @@ impl LineItemLayout<'_, '_> { )); } - fn layout_float(&mut self, mut float: FloatLineItem) { + fn layout_float(&mut self, float: FloatLineItem) { self.current_state .flags .insert(LineLayoutInlineContainerFlags::HAD_ANY_FLOATS); @@ -705,13 +709,12 @@ impl LineItemLayout<'_, '_> { inline: self.current_state.parent_offset.inline, block: self.line_metrics.block_offset + self.current_state.parent_offset.block, }; - float.fragment.content_rect.origin -= distance_from_parent_to_ifc + float.fragment.borrow_mut().content_rect.origin -= distance_from_parent_to_ifc .to_physical_size(self.layout.containing_block.style.writing_mode); - self.current_state.fragments.push(( - Fragment::Float(ArcRefCell::new(float.fragment)), - LogicalRect::zero(), - )); + self.current_state + .fragments + .push((Fragment::Float(float.fragment), LogicalRect::zero())); } } @@ -829,7 +832,7 @@ impl TextRunLineItem { } pub(super) struct AtomicLineItem { - pub fragment: BoxFragment, + pub fragment: ArcRefCell<BoxFragment>, pub size: LogicalVec2<Au>, pub positioning_context: Option<PositioningContext>, @@ -849,7 +852,7 @@ impl AtomicLineItem { /// Given the metrics for a line, our vertical alignment, and our block size, find a block start /// position relative to the top of the line. fn calculate_block_start(&self, line_metrics: &LineMetrics) -> Au { - match self.fragment.style.clone_vertical_align() { + match self.fragment.borrow().style.clone_vertical_align() { GenericVerticalAlign::Keyword(VerticalAlignKeyword::Top) => Au::zero(), GenericVerticalAlign::Keyword(VerticalAlignKeyword::Bottom) => { line_metrics.block_size - self.size.block @@ -869,7 +872,7 @@ pub(super) struct AbsolutelyPositionedLineItem { } pub(super) struct FloatLineItem { - pub fragment: BoxFragment, + pub fragment: ArcRefCell<BoxFragment>, /// Whether or not this float Fragment has been placed yet. Fragments that /// do not fit on a line need to be placed after the hypothetical block start /// of the next line. diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index d864807aa45..7564b5004c6 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -221,6 +221,22 @@ impl InlineItem { }, } } + + pub(crate) fn fragments(&self) -> Vec<Fragment> { + match self { + InlineItem::StartInlineBox(inline_box) => inline_box.borrow().base.fragments(), + InlineItem::EndInlineBox | InlineItem::TextRun(..) => { + unreachable!("Should never have these kind of fragments attached to a DOM node") + }, + InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => { + positioned_box.borrow().context.base.fragments() + }, + InlineItem::OutOfFlowFloatBox(float_box) => float_box.contents.base.fragments(), + InlineItem::Atomic(independent_formatting_context, ..) => { + independent_formatting_context.base.fragments() + }, + } + } } /// Information about the current line under construction for a particular @@ -1081,8 +1097,8 @@ impl InlineFormattingContextLayout<'_> { float_item: &mut FloatLineItem, line_inline_size_without_trailing_whitespace: Au, ) { - let logical_margin_rect_size = float_item - .fragment + let mut float_fragment = float_item.fragment.borrow_mut(); + let logical_margin_rect_size = float_fragment .margin_rect() .size .to_logical(self.containing_block.style.writing_mode); @@ -1106,7 +1122,7 @@ impl InlineFormattingContextLayout<'_> { if needs_placement_later { self.current_line.has_floats_waiting_to_be_placed = true; } else { - self.place_float_fragment(&mut float_item.fragment); + self.place_float_fragment(&mut float_fragment); float_item.needs_placement = false; } @@ -1657,6 +1673,11 @@ impl InlineFormattingContext { Au::zero() }; + // Clear any cached inline fragments from previous layouts. + for inline_box in self.inline_boxes.iter() { + inline_box.borrow().base.clear_fragments(); + } + let style = containing_block.style; // It's unfortunate that it isn't possible to get this during IFC text processing, but in @@ -2055,6 +2076,10 @@ impl IndependentFormattingContext { size.inline, SegmentContentFlags::empty(), ); + + let fragment = ArcRefCell::new(fragment); + self.base.set_fragment(Fragment::Box(fragment.clone())); + layout.push_line_item_to_unbreakable_segment(LineItem::Atomic( layout.current_inline_box_identifier(), AtomicLineItem { @@ -2131,11 +2156,15 @@ impl IndependentFormattingContext { impl FloatBox { fn layout_into_line_items(&self, layout: &mut InlineFormattingContextLayout) { - let fragment = self.layout( + let fragment = ArcRefCell::new(self.layout( layout.layout_context, layout.positioning_context, layout.containing_block, - ); + )); + + self.contents + .base + .set_fragment(Fragment::Box(fragment.clone())); layout.push_line_item_to_unbreakable_segment(LineItem::Float( layout.current_inline_box_identifier(), FloatLineItem { @@ -2150,7 +2179,7 @@ fn place_pending_floats(ifc: &mut InlineFormattingContextLayout, line_items: &mu for item in line_items.iter_mut() { if let LineItem::Float(_, float_line_item) = item { if float_line_item.needs_placement { - ifc.place_float_fragment(&mut float_line_item.fragment); + ifc.place_float_fragment(&mut float_line_item.fragment.borrow_mut()); } } } diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 4254b4f671d..a45c0bcb9c1 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -91,23 +91,25 @@ pub(crate) enum BlockLevelBox { impl BlockLevelBox { pub(crate) fn invalidate_cached_fragment(&self) { + self.with_base(LayoutBoxBase::invalidate_cached_fragment); + } + + pub(crate) fn fragments(&self) -> Vec<Fragment> { + self.with_base(LayoutBoxBase::fragments) + } + + pub(crate) fn with_base<T>(&self, callback: impl Fn(&LayoutBoxBase) -> T) -> T { match self { BlockLevelBox::Independent(independent_formatting_context) => { - &independent_formatting_context.base + callback(&independent_formatting_context.base) }, BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => { - positioned_box - .borrow() - .context - .base - .invalidate_cached_fragment(); - return; + callback(&positioned_box.borrow().context.base) }, - BlockLevelBox::OutOfFlowFloatBox(float_box) => &float_box.contents.base, - BlockLevelBox::OutsideMarker(outside_marker) => &outside_marker.base, - BlockLevelBox::SameFormattingContextBlock { base, .. } => base, + BlockLevelBox::OutOfFlowFloatBox(float_box) => callback(&float_box.contents.base), + BlockLevelBox::OutsideMarker(outside_marker) => callback(&outside_marker.base), + BlockLevelBox::SameFormattingContextBlock { base, .. } => callback(base), } - .invalidate_cached_fragment(); } fn contains_floats(&self) -> bool { @@ -770,7 +772,7 @@ impl BlockLevelBox { collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>, ignore_block_margins_for_stretch: LogicalSides1D<bool>, ) -> Fragment { - match self { + let fragment = match self { BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => Fragment::Box( ArcRefCell::new(positioning_context.layout_maybe_position_relative_fragment( layout_context, @@ -836,7 +838,11 @@ impl BlockLevelBox { sequential_layout_state, collapsible_with_parent_start_margin, ), - } + }; + + self.with_base(|base| base.set_fragment(fragment.clone())); + + fragment } fn inline_content_sizes( diff --git a/components/layout_2020/layout_box_base.rs b/components/layout_2020/layout_box_base.rs index 8a88a5855dc..54f7575391c 100644 --- a/components/layout_2020/layout_box_base.rs +++ b/components/layout_2020/layout_box_base.rs @@ -29,6 +29,7 @@ pub(crate) struct LayoutBoxBase { pub cached_inline_content_size: AtomicRefCell<Option<Box<(SizeConstraint, InlineContentSizesResult)>>>, pub cached_layout_result: AtomicRefCell<Option<Box<CacheableLayoutResultAndInputs>>>, + pub fragments: AtomicRefCell<Vec<Fragment>>, } impl LayoutBoxBase { @@ -38,6 +39,7 @@ impl LayoutBoxBase { style, cached_inline_content_size: AtomicRefCell::default(), cached_layout_result: AtomicRefCell::default(), + fragments: AtomicRefCell::default(), } } @@ -69,6 +71,22 @@ impl LayoutBoxBase { pub(crate) fn invalidate_cached_fragment(&self) { let _ = self.cached_layout_result.borrow_mut().take(); } + + pub(crate) fn fragments(&self) -> Vec<Fragment> { + self.fragments.borrow().clone() + } + + pub(crate) fn add_fragment(&self, fragment: Fragment) { + self.fragments.borrow_mut().push(fragment); + } + + pub(crate) fn set_fragment(&self, fragment: Fragment) { + *self.fragments.borrow_mut() = vec![fragment]; + } + + pub(crate) fn clear_fragments(&self) { + self.fragments.borrow_mut().clear(); + } } impl Debug for LayoutBoxBase { diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 2032dae63bf..f345947416d 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -436,9 +436,8 @@ impl HoistedAbsolutelyPositionedBox { containing_block_padding, ); - hoisted_box.fragment.borrow_mut().fragment = - Some(Fragment::Box(new_fragment.clone())); - (Fragment::Box(new_fragment), new_hoisted_boxes) + hoisted_box.fragment.borrow_mut().fragment = Some(new_fragment.clone()); + (new_fragment, new_hoisted_boxes) }) .unzip_into_vecs(&mut new_fragments, &mut new_hoisted_boxes); @@ -454,8 +453,8 @@ impl HoistedAbsolutelyPositionedBox { containing_block_padding, ); - box_.fragment.borrow_mut().fragment = Some(Fragment::Box(new_fragment.clone())); - Fragment::Box(new_fragment) + box_.fragment.borrow_mut().fragment = Some(new_fragment.clone()); + new_fragment })) } } @@ -466,7 +465,7 @@ impl HoistedAbsolutelyPositionedBox { for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>, containing_block: &DefiniteContainingBlock, containing_block_padding: PhysicalSides<Au>, - ) -> ArcRefCell<BoxFragment> { + ) -> Fragment { let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; let containing_block_writing_mode = containing_block.style.writing_mode; @@ -714,7 +713,9 @@ impl HoistedAbsolutelyPositionedBox { for_nearest_containing_block_for_all_descendants .extend(positioning_context.for_nearest_containing_block_for_all_descendants); - ArcRefCell::new(new_fragment) + let fragment = Fragment::Box(ArcRefCell::new(new_fragment)); + context.base.set_fragment(fragment.clone()); + fragment } } diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs index f0fca77f4e5..08b264deea9 100644 --- a/components/layout_2020/query.rs +++ b/components/layout_2020/query.rs @@ -38,6 +38,7 @@ use style::values::specified::GenericGridTemplateComponent; use style::values::specified::box_::DisplayInside; use style_traits::{ParsingMode, ToCss}; +use crate::dom::NodeExt; use crate::flow::inline::construct::{TextTransformation, WhitespaceCollapse}; use crate::fragment_tree::{ BoxFragment, Fragment, FragmentFlags, FragmentTree, SpecificLayoutInfo, Tag, @@ -105,7 +106,7 @@ pub fn process_node_scroll_area_request( /// <https://drafts.csswg.org/cssom/#resolved-value> pub fn process_resolved_style_request<'dom>( context: &SharedStyleContext, - node: impl LayoutNode<'dom>, + node: impl LayoutNode<'dom> + 'dom, pseudo: &Option<PseudoElement>, property: &PropertyId, fragment_tree: Option<Arc<FragmentTree>>, @@ -190,90 +191,102 @@ pub fn process_resolved_style_request<'dom>( return computed_style(None); } - let resolve_for_fragment = |fragment: &Fragment, containing_block: &PhysicalRect<Au>| { - let (content_rect, margins, padding, specific_layout_info) = match fragment { - Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => { - let box_fragment = box_fragment.borrow(); - if style.get_box().position != Position::Static { - let resolved_insets = - || box_fragment.calculate_resolved_insets_if_positioned(containing_block); - match longhand_id { - LonghandId::Top => return resolved_insets().top.to_css_string(), - LonghandId::Right => { - return resolved_insets().right.to_css_string(); - }, - LonghandId::Bottom => { - return resolved_insets().bottom.to_css_string(); - }, - LonghandId::Left => { - return resolved_insets().left.to_css_string(); - }, - _ => {}, + let resolve_for_fragment = + |fragment: &Fragment, containing_block: Option<&PhysicalRect<Au>>| { + let (content_rect, margins, padding, specific_layout_info) = match fragment { + Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => { + let box_fragment = box_fragment.borrow(); + if style.get_box().position != Position::Static { + let resolved_insets = || { + box_fragment + .calculate_resolved_insets_if_positioned(containing_block.unwrap()) + }; + match longhand_id { + LonghandId::Top => return resolved_insets().top.to_css_string(), + LonghandId::Right => { + return resolved_insets().right.to_css_string(); + }, + LonghandId::Bottom => { + return resolved_insets().bottom.to_css_string(); + }, + LonghandId::Left => { + return resolved_insets().left.to_css_string(); + }, + _ => {}, + } } - } - let content_rect = box_fragment.content_rect; - let margins = box_fragment.margin; - let padding = box_fragment.padding; - let specific_layout_info = box_fragment.specific_layout_info.clone(); - (content_rect, margins, padding, specific_layout_info) - }, - Fragment::Positioning(positioning_fragment) => { - let content_rect = positioning_fragment.borrow().rect; - ( - content_rect, - SideOffsets2D::zero(), - SideOffsets2D::zero(), - None, - ) - }, - _ => return computed_style(Some(fragment)), - }; + let content_rect = box_fragment.content_rect; + let margins = box_fragment.margin; + let padding = box_fragment.padding; + let specific_layout_info = box_fragment.specific_layout_info.clone(); + (content_rect, margins, padding, specific_layout_info) + }, + Fragment::Positioning(positioning_fragment) => { + let content_rect = positioning_fragment.borrow().rect; + ( + content_rect, + SideOffsets2D::zero(), + SideOffsets2D::zero(), + None, + ) + }, + _ => return computed_style(Some(fragment)), + }; - // https://drafts.csswg.org/css-grid/#resolved-track-list - // > The grid-template-rows and grid-template-columns properties are - // > resolved value special case properties. - // - // > When an element generates a grid container box... - if display.inside() == DisplayInside::Grid { - if let Some(SpecificLayoutInfo::Grid(info)) = specific_layout_info { - if let Some(value) = resolve_grid_template(&info, style, longhand_id) { - return value; + // https://drafts.csswg.org/css-grid/#resolved-track-list + // > The grid-template-rows and grid-template-columns properties are + // > resolved value special case properties. + // + // > When an element generates a grid container box... + if display.inside() == DisplayInside::Grid { + if let Some(SpecificLayoutInfo::Grid(info)) = specific_layout_info { + if let Some(value) = resolve_grid_template(&info, style, longhand_id) { + return value; + } } } - } - // https://drafts.csswg.org/cssom/#resolved-value-special-case-property-like-height - // > If the property applies to the element or pseudo-element and the resolved value of the - // > display property is not none or contents, then the resolved value is the used value. - // > Otherwise the resolved value is the computed value. - // - // However, all browsers ignore that for margin and padding properties, and resolve to a length - // even if the property doesn't apply: https://github.com/w3c/csswg-drafts/issues/10391 - match longhand_id { - LonghandId::Width if resolved_size_should_be_used_value(fragment) => { - content_rect.size.width - }, - LonghandId::Height if resolved_size_should_be_used_value(fragment) => { - content_rect.size.height - }, - LonghandId::MarginBottom => margins.bottom, - LonghandId::MarginTop => margins.top, - LonghandId::MarginLeft => margins.left, - LonghandId::MarginRight => margins.right, - LonghandId::PaddingBottom => padding.bottom, - LonghandId::PaddingTop => padding.top, - LonghandId::PaddingLeft => padding.left, - LonghandId::PaddingRight => padding.right, - _ => return computed_style(Some(fragment)), + // https://drafts.csswg.org/cssom/#resolved-value-special-case-property-like-height + // > If the property applies to the element or pseudo-element and the resolved value of the + // > display property is not none or contents, then the resolved value is the used value. + // > Otherwise the resolved value is the computed value. + // + // However, all browsers ignore that for margin and padding properties, and resolve to a length + // even if the property doesn't apply: https://github.com/w3c/csswg-drafts/issues/10391 + match longhand_id { + LonghandId::Width if resolved_size_should_be_used_value(fragment) => { + content_rect.size.width + }, + LonghandId::Height if resolved_size_should_be_used_value(fragment) => { + content_rect.size.height + }, + LonghandId::MarginBottom => margins.bottom, + LonghandId::MarginTop => margins.top, + LonghandId::MarginLeft => margins.left, + LonghandId::MarginRight => margins.right, + LonghandId::PaddingBottom => padding.bottom, + LonghandId::PaddingTop => padding.top, + LonghandId::PaddingLeft => padding.left, + LonghandId::PaddingRight => padding.right, + _ => return computed_style(Some(fragment)), + } + .to_css_string() + }; + + if !matches!( + longhand_id, + LonghandId::Top | LonghandId::Bottom | LonghandId::Left | LonghandId::Right + ) { + if let Some(fragment) = node.fragments_for_pseudo(*pseudo).first() { + return resolve_for_fragment(fragment, None); } - .to_css_string() - }; + } fragment_tree .and_then(|fragment_tree| { fragment_tree.find(|fragment, _, containing_block| { if Some(tag_to_find) == fragment.tag() { - Some(resolve_for_fragment(fragment, containing_block)) + Some(resolve_for_fragment(fragment, Some(containing_block))) } else { None } diff --git a/components/layout_2020/table/construct.rs b/components/layout_2020/table/construct.rs index 13615183788..f20360d3b56 100644 --- a/components/layout_2020/table/construct.rs +++ b/components/layout_2020/table/construct.rs @@ -728,8 +728,7 @@ where let style = anonymous_info.style.clone(); self.push_table_row(ArcRefCell::new(TableTrack { - base_fragment_info: (&anonymous_info).into(), - style, + base: LayoutBoxBase::new((&anonymous_info).into(), style), group_index: self.current_row_group_index, is_anonymous: true, })); @@ -773,8 +772,7 @@ where let next_row_index = self.builder.table.rows.len(); let row_group = ArcRefCell::new(TableTrackGroup { - base_fragment_info: info.into(), - style: info.style.clone(), + base: LayoutBoxBase::new(info.into(), info.style.clone()), group_type: internal.into(), track_range: next_row_index..next_row_index, }); @@ -816,8 +814,7 @@ where row_builder.finish(); let row = ArcRefCell::new(TableTrack { - base_fragment_info: info.into(), - style: info.style.clone(), + base: LayoutBoxBase::new(info.into(), info.style.clone()), group_index: self.current_row_group_index, is_anonymous: false, }); @@ -862,8 +859,7 @@ where } let column_group = ArcRefCell::new(TableTrackGroup { - base_fragment_info: info.into(), - style: info.style.clone(), + base: LayoutBoxBase::new(info.into(), info.style.clone()), group_type: internal.into(), track_range: first_column..self.builder.table.columns.len(), }); @@ -1155,8 +1151,7 @@ fn add_column<'dom, Node: NodeExt<'dom>>( }; let column = ArcRefCell::new(TableTrack { - base_fragment_info: column_info.into(), - style: column_info.style.clone(), + base: LayoutBoxBase::new(column_info.into(), column_info.style.clone()), group_index, is_anonymous, }); diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index bc38c5e6227..57b48ae0bca 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -32,7 +32,7 @@ use super::{ use crate::context::LayoutContext; use crate::formatting_contexts::Baselines; use crate::fragment_tree::{ - BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, FragmentFlags, + BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, FragmentFlags, PositioningFragment, SpecificLayoutInfo, }; use crate::geom::{ @@ -396,13 +396,13 @@ impl<'a> TableLayout<'a> { for column_index in 0..self.table.size.width { if let Some(column) = self.table.columns.get(column_index) { let column = column.borrow(); - if is_length(&column.style.box_size(writing_mode).inline) { + if is_length(&column.base.style.box_size(writing_mode).inline) { self.columns[column_index].constrained = true; continue; } if let Some(column_group_index) = column.group_index { let column_group = self.table.column_groups[column_group_index].borrow(); - if is_length(&column_group.style.box_size(writing_mode).inline) { + if is_length(&column_group.base.style.box_size(writing_mode).inline) { self.columns[column_index].constrained = true; continue; } @@ -413,13 +413,13 @@ impl<'a> TableLayout<'a> { for row_index in 0..self.table.size.height { if let Some(row) = self.table.rows.get(row_index) { let row = row.borrow(); - if is_length(&row.style.box_size(writing_mode).block) { + if is_length(&row.base.style.box_size(writing_mode).block) { self.rows[row_index].constrained = true; continue; } if let Some(row_group_index) = row.group_index { let row_group = self.table.row_groups[row_group_index].borrow(); - if is_length(&row_group.style.box_size(writing_mode).block) { + if is_length(&row_group.base.style.box_size(writing_mode).block) { self.rows[row_index].constrained = true; continue; } @@ -1086,13 +1086,15 @@ impl<'a> TableLayout<'a> { row.group_index.is_some_and(|group_index| { self.table.row_groups[group_index] .borrow() + .base .style .establishes_containing_block_for_absolute_descendants( FragmentFlags::empty(), ) }); row_group_collects_for_nearest_positioned_ancestor || - row.style + row.base + .style .establishes_containing_block_for_absolute_descendants( FragmentFlags::empty(), ) @@ -1650,6 +1652,8 @@ impl<'a> TableLayout<'a> { &caption_fragment, original_positioning_context_length, ); + + caption.context.base.set_fragment(caption_fragment.clone()); Some(caption_fragment) })); @@ -1745,6 +1749,8 @@ impl<'a> TableLayout<'a> { &caption_fragment, original_positioning_context_length, ); + + caption.context.base.set_fragment(caption_fragment.clone()); Some(caption_fragment) })); @@ -1845,18 +1851,18 @@ impl<'a> TableLayout<'a> { if table_row.group_index != old_row_group_index { // First create the Fragment for any existing RowGroupFragmentLayout. if let Some(old_row_group_layout) = row_group_fragment_layout.take() { - table_fragments.push(Fragment::Box(old_row_group_layout.finish( + table_fragments.push(old_row_group_layout.finish( layout_context, positioning_context, containing_block_for_logical_conversion, containing_block_for_children, - ))); + )); } // Then, create a new RowGroupFragmentLayout for the current and potentially subsequent rows. if let Some(new_group_index) = table_row.group_index { row_group_fragment_layout = Some(RowGroupFragmentLayout::new( - &self.table.row_groups[new_group_index].borrow(), + self.table.row_groups[new_group_index].clone(), new_group_index, &table_and_track_dimensions, )); @@ -1881,13 +1887,13 @@ impl<'a> TableLayout<'a> { ); } - let row_fragment = Fragment::Box(row_fragment_layout.finish( + let row_fragment = row_fragment_layout.finish( layout_context, positioning_context, containing_block_for_logical_conversion, containing_block_for_children, &mut row_group_fragment_layout, - )); + ); match row_group_fragment_layout.as_mut() { Some(layout) => layout.fragments.push(row_fragment), @@ -1896,12 +1902,12 @@ impl<'a> TableLayout<'a> { } if let Some(row_group_layout) = row_group_fragment_layout.take() { - table_fragments.push(Fragment::Box(row_group_layout.finish( + table_fragments.push(row_group_layout.finish( layout_context, positioning_context, containing_block_for_logical_conversion, containing_block_for_children, - ))); + )); } let content_rect = LogicalRect { @@ -1973,14 +1979,14 @@ impl<'a> TableLayout<'a> { }; let row = row.borrow(); - if row.style.get_inherited_box().visibility == Visibility::Collapse { + if row.base.style.get_inherited_box().visibility == Visibility::Collapse { return true; } let row_group = match row.group_index { Some(group_index) => self.table.row_groups[group_index].borrow(), None => return false, }; - row_group.style.get_inherited_box().visibility == Visibility::Collapse + row_group.base.style.get_inherited_box().visibility == Visibility::Collapse } fn is_column_collapsed(&self, column_index: usize) -> bool { @@ -1988,14 +1994,14 @@ impl<'a> TableLayout<'a> { return false; }; let column = column.borrow(); - if column.style.get_inherited_box().visibility == Visibility::Collapse { + if column.base.style.get_inherited_box().visibility == Visibility::Collapse { return true; } let col_group = match column.group_index { Some(group_index) => self.table.column_groups[group_index].borrow(), None => return false, }; - col_group.style.get_inherited_box().visibility == Visibility::Collapse + col_group.base.style.get_inherited_box().visibility == Visibility::Collapse } #[allow(clippy::too_many_arguments)] @@ -2088,7 +2094,7 @@ impl<'a> TableLayout<'a> { let column_group = column_group.borrow(); let rect = make_relative_to_row_start(dimensions.get_column_group_rect(&column_group)); fragment.add_extra_background(ExtraBackground { - style: column_group.style.clone(), + style: column_group.base.style.clone(), rect, }) } @@ -2097,7 +2103,7 @@ impl<'a> TableLayout<'a> { if !column.is_anonymous { let rect = make_relative_to_row_start(dimensions.get_column_rect(column_index)); fragment.add_extra_background(ExtraBackground { - style: column.style.clone(), + style: column.base.style.clone(), rect, }) } @@ -2110,7 +2116,7 @@ impl<'a> TableLayout<'a> { let rect = make_relative_to_row_start(dimensions.get_row_group_rect(&row_group.borrow())); fragment.add_extra_background(ExtraBackground { - style: row_group.borrow().style.clone(), + style: row_group.borrow().base.style.clone(), rect, }) } @@ -2118,13 +2124,14 @@ impl<'a> TableLayout<'a> { let row = row.borrow(); let rect = make_relative_to_row_start(row_fragment_layout.rect); fragment.add_extra_background(ExtraBackground { - style: row.style.clone(), + style: row.base.style.clone(), rect, }) } - row_fragment_layout - .fragments - .push(Fragment::Box(ArcRefCell::new(fragment))); + + let fragment = Fragment::Box(ArcRefCell::new(fragment)); + cell.base.set_fragment(fragment.clone()); + row_fragment_layout.fragments.push(fragment); } fn make_fragments_for_columns_and_column_groups( @@ -2136,11 +2143,11 @@ impl<'a> TableLayout<'a> { let column_group = column_group.borrow(); if !column_group.is_empty() { fragments.push(Fragment::Positioning(PositioningFragment::new_empty( - column_group.base_fragment_info, + column_group.base.base_fragment_info, dimensions .get_column_group_rect(&column_group) .as_physical(None), - column_group.style.clone(), + column_group.base.style.clone(), ))); } } @@ -2148,9 +2155,9 @@ impl<'a> TableLayout<'a> { for (column_index, column) in self.table.columns.iter().enumerate() { let column = column.borrow(); fragments.push(Fragment::Positioning(PositioningFragment::new_empty( - column.base_fragment_info, + column.base.base_fragment_info, dimensions.get_column_rect(column_index).as_physical(None), - column.style.clone(), + column.base.style.clone(), ))); } } @@ -2314,7 +2321,7 @@ impl<'a> RowFragmentLayout<'a> { Self { row: table_row, rect, - positioning_context: PositioningContext::new_for_style(&table_row.style), + positioning_context: PositioningContext::new_for_style(&table_row.base.style), containing_block, fragments: Vec::new(), } @@ -2326,10 +2333,10 @@ impl<'a> RowFragmentLayout<'a> { containing_block_for_logical_conversion: &ContainingBlock, containing_block_for_children: &ContainingBlock, row_group_fragment_layout: &mut Option<RowGroupFragmentLayout>, - ) -> ArcRefCell<BoxFragment> { + ) -> Fragment { if self.positioning_context.is_some() { self.rect.start_corner += - relative_adjustement(&self.row.style, containing_block_for_children); + relative_adjustement(&self.row.base.style, containing_block_for_children); } let (inline_size, block_size) = if let Some(row_group_layout) = row_group_fragment_layout { @@ -2354,8 +2361,8 @@ impl<'a> RowFragmentLayout<'a> { }; let mut row_fragment = BoxFragment::new( - self.row.base_fragment_info, - self.row.style.clone(), + self.row.base.base_fragment_info, + self.row.base.style.clone(), self.fragments, self.rect.as_physical(Some(&row_group_containing_block)), PhysicalSides::zero(), /* padding */ @@ -2375,13 +2382,14 @@ impl<'a> RowFragmentLayout<'a> { positioning_context.append(row_positioning_context); } - ArcRefCell::new(row_fragment) + let fragment = Fragment::Box(ArcRefCell::new(row_fragment)); + self.row.base.set_fragment(fragment.clone()); + fragment } } struct RowGroupFragmentLayout { - base_fragment_info: BaseFragmentInfo, - style: Arc<ComputedValues>, + row_group: ArcRefCell<TableTrackGroup>, rect: LogicalRect<Au>, positioning_context: Option<PositioningContext>, index: usize, @@ -2390,16 +2398,21 @@ struct RowGroupFragmentLayout { impl RowGroupFragmentLayout { fn new( - row_group: &TableTrackGroup, + row_group: ArcRefCell<TableTrackGroup>, index: usize, dimensions: &TableAndTrackDimensions, ) -> Self { - let rect = dimensions.get_row_group_rect(row_group); + let (rect, positioning_context) = { + let row_group = row_group.borrow(); + ( + dimensions.get_row_group_rect(&row_group), + PositioningContext::new_for_style(&row_group.base.style), + ) + }; Self { - base_fragment_info: row_group.base_fragment_info, - style: row_group.style.clone(), + row_group, rect, - positioning_context: PositioningContext::new_for_style(&row_group.style), + positioning_context, index, fragments: Vec::new(), } @@ -2411,15 +2424,16 @@ impl RowGroupFragmentLayout { table_positioning_context: &mut PositioningContext, containing_block_for_logical_conversion: &ContainingBlock, containing_block_for_children: &ContainingBlock, - ) -> ArcRefCell<BoxFragment> { + ) -> Fragment { + let row_group = self.row_group.borrow(); if self.positioning_context.is_some() { self.rect.start_corner += - relative_adjustement(&self.style, containing_block_for_children); + relative_adjustement(&row_group.base.style, containing_block_for_children); } let mut row_group_fragment = BoxFragment::new( - self.base_fragment_info, - self.style, + row_group.base.base_fragment_info, + row_group.base.style.clone(), self.fragments, self.rect .as_physical(Some(containing_block_for_logical_conversion)), @@ -2436,7 +2450,9 @@ impl RowGroupFragmentLayout { table_positioning_context.append(row_positioning_context); } - ArcRefCell::new(row_group_fragment) + let fragment = Fragment::Box(ArcRefCell::new(row_group_fragment)); + row_group.base.set_fragment(fragment.clone()); + fragment } } @@ -2634,7 +2650,7 @@ impl Table { max: max_size, percentage: percentage_size, } = CellOrColumnOuterSizes::new( - &column.style, + &column.base.style, writing_mode, &Default::default(), is_in_fixed_mode, @@ -2672,8 +2688,8 @@ impl Table { // (except for new layout boxes like grid and flex containers). Note that // other browsers don't seem to use the min and max sizing properties here. let row = row.borrow(); - let size = row.style.box_size(writing_mode); - let max_size = row.style.max_box_size(writing_mode); + let size = row.base.style.box_size(writing_mode); + let max_size = row.base.style.max_box_size(writing_mode); let percentage_contribution = get_size_percentage_contribution(&size, &max_size); CellOrTrackMeasure { @@ -2769,14 +2785,14 @@ impl Table { impl TableTrack { #[inline] pub(crate) fn layout_style(&self) -> LayoutStyle { - LayoutStyle::Default(&self.style) + LayoutStyle::Default(&self.base.style) } } impl TableTrackGroup { #[inline] pub(crate) fn layout_style(&self) -> LayoutStyle { - LayoutStyle::Default(&self.style) + LayoutStyle::Default(&self.base.style) } } diff --git a/components/layout_2020/table/mod.rs b/components/layout_2020/table/mod.rs index 749c2fbac04..42978416a23 100644 --- a/components/layout_2020/table/mod.rs +++ b/components/layout_2020/table/mod.rs @@ -84,7 +84,7 @@ use super::flow::BlockFormattingContext; use crate::cell::ArcRefCell; use crate::flow::BlockContainer; use crate::formatting_contexts::IndependentFormattingContext; -use crate::fragment_tree::BaseFragmentInfo; +use crate::fragment_tree::{BaseFragmentInfo, Fragment}; use crate::geom::PhysicalVec; use crate::layout_box_base::LayoutBoxBase; use crate::style_ext::BorderStyleColor; @@ -272,13 +272,10 @@ impl TableSlot { } /// A row or column of a table. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct TableTrack { - /// The [`BaseFragmentInfo`] of this cell. - base_fragment_info: BaseFragmentInfo, - - /// The style of this table column. - style: Arc<ComputedValues>, + /// The [`LayoutBoxBase`] of this [`TableTrack`]. + base: LayoutBoxBase, /// The index of the table row or column group parent in the table's list of row or column /// groups. @@ -299,11 +296,8 @@ pub enum TableTrackGroupType { #[derive(Debug)] pub struct TableTrackGroup { - /// The [`BaseFragmentInfo`] of this [`TableTrackGroup`]. - base_fragment_info: BaseFragmentInfo, - - /// The style of this [`TableTrackGroup`]. - style: Arc<ComputedValues>, + /// The [`LayoutBoxBase`] of this [`TableTrackGroup`]. + base: LayoutBoxBase, /// The type of this [`TableTrackGroup`]. group_type: TableTrackGroupType, @@ -366,8 +360,19 @@ impl TableLevelBox { TableLevelBox::Cell(cell) => { cell.borrow().base.invalidate_cached_fragment(); }, - TableLevelBox::TrackGroup(..) => {}, - TableLevelBox::Track(..) => {}, + TableLevelBox::TrackGroup(track_group) => { + track_group.borrow().base.invalidate_cached_fragment() + }, + TableLevelBox::Track(track) => track.borrow().base.invalidate_cached_fragment(), + } + } + + pub(crate) fn fragments(&self) -> Vec<Fragment> { + match self { + TableLevelBox::Caption(caption) => caption.borrow().context.base.fragments(), + TableLevelBox::Cell(cell) => cell.borrow().base.fragments(), + TableLevelBox::TrackGroup(track_group) => track_group.borrow().base.fragments(), + TableLevelBox::Track(track) => track.borrow().base.fragments(), } } } diff --git a/components/layout_2020/taffy/layout.rs b/components/layout_2020/taffy/layout.rs index 7975a322ed7..6bb4f06dcd1 100644 --- a/components/layout_2020/taffy/layout.rs +++ b/components/layout_2020/taffy/layout.rs @@ -550,7 +550,7 @@ impl TaffyContainer { false }; - match &mut child.taffy_level_box { + let fragment = match &mut child.taffy_level_box { TaffyItemBoxInner::InFlowBox(independent_box) => { let mut fragment_info = independent_box.base_fragment_info(); fragment_info @@ -594,7 +594,6 @@ impl TaffyContainer { container_ctx .positioning_context .append(child_positioning_context); - fragment }, TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(abs_pos_box) => { @@ -628,7 +627,16 @@ impl TaffyContainer { container_ctx.positioning_context.push(hoisted_box); Fragment::AbsoluteOrFixedPositioned(hoisted_fragment) }, + }; + + if let TaffyItemBoxInner::InFlowBox(independent_formatting_context) = + &child.taffy_level_box + { + independent_formatting_context + .base + .set_fragment(fragment.clone()); } + fragment }) .collect(); diff --git a/components/layout_2020/taffy/mod.rs b/components/layout_2020/taffy/mod.rs index 81f2f347fe9..7aca7286bcd 100644 --- a/components/layout_2020/taffy/mod.rs +++ b/components/layout_2020/taffy/mod.rs @@ -131,6 +131,17 @@ impl TaffyItemBox { }, } } + + pub(crate) fn fragments(&self) -> Vec<Fragment> { + match self.taffy_level_box { + TaffyItemBoxInner::InFlowBox(ref independent_formatting_context) => { + independent_formatting_context.base.fragments() + }, + TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(ref positioned_box) => { + positioned_box.borrow().context.base.fragments() + }, + } + } } /// Details from Taffy grid layout that will be stored |