diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index a420ac4fdac..4e0ccc459e9 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -55,7 +55,6 @@ struct FlexContext<'a> { /// A flex item with some intermediate results struct FlexItem<'a> { box_: &'a mut IndependentFormattingContext, - tree_rank: usize, content_box_size: FlexRelativeVec2, content_min_size: FlexRelativeVec2, content_max_size: FlexRelativeVec2>, @@ -92,7 +91,7 @@ struct FlexItemLayoutResult { /// Return type of `FlexLine::layout` struct FlexLineLayoutResult { cross_size: Length, - item_fragments: Vec, // One per flex item, in the given order + item_fragments: Vec<(BoxFragment, PositioningContext)>, // One per flex item, in the given order } impl FlexContext<'_> { @@ -150,7 +149,6 @@ impl FlexContainer { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - tree_rank: usize, ) -> IndependentLayout { // Actual length may be less, but we guess that usually not by a lot let mut flex_items = Vec::with_capacity(self.children.len()); @@ -161,8 +159,7 @@ impl FlexContainer { let original_order_with_absolutely_positioned = self .children .iter() - .enumerate() - .map(|(tree_rank, arcrefcell)| { + .map(|arcrefcell| { let borrowed = arcrefcell.borrow_mut(); match &*borrowed { FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(absolutely_positioned) => { @@ -173,56 +170,54 @@ impl FlexContainer { FlexLevelBox::FlexItem(item) => item, _ => unreachable!(), }); - flex_items.push((tree_rank, item)); + flex_items.push(item); Err(()) }, } }) .collect::>(); - let mut content_block_size_option_dance = None; - let fragments = - positioning_context.adjust_static_positions(tree_rank, |positioning_context| { - let (mut flex_item_fragments, content_block_size) = layout( - layout_context, - positioning_context, - containing_block, - flex_items - .iter_mut() - .map(|(tree_rank, child)| (*tree_rank, &mut **child)), - ); - content_block_size_option_dance = Some(content_block_size); - let fragments = original_order_with_absolutely_positioned - .into_iter() - .enumerate() - .map(|(tree_rank, child_as_abspos)| match child_as_abspos { - Err(()) => { - // The `()` here is a place-holder for a flex item. - // The `flex_item_fragments` iterator yields one fragment - // per flex item, in the original order. - Fragment::Box(flex_item_fragments.next().unwrap()) - }, - Ok(absolutely_positioned) => { - let hoisted_box = AbsolutelyPositionedBox::to_hoisted( - absolutely_positioned, - Vec2::zero(), - tree_rank, - containing_block, - ); - let hoisted_fragment = hoisted_box.fragment.clone(); - positioning_context.push(hoisted_box); - Fragment::AbsoluteOrFixedPositioned(hoisted_fragment) - }, - }) - .collect::>(); - // There should be no more flex items - assert!(flex_item_fragments.next().is_none()); - fragments - }); + let (mut flex_item_fragments, content_block_size) = layout( + layout_context, + positioning_context, + containing_block, + flex_items.iter_mut().map(|child| &mut **child), + ); + + let fragments = original_order_with_absolutely_positioned + .into_iter() + .map(|child_as_abspos| match child_as_abspos { + Err(()) => { + // The `()` here is a place-holder for a flex item. + // The `flex_item_fragments` iterator yields one fragment + // per flex item, in the original order. + let (fragment, mut child_positioning_context) = + flex_item_fragments.next().unwrap(); + let fragment = Fragment::Box(fragment); + child_positioning_context + .adjust_static_position_of_hoisted_fragments(&fragment); + positioning_context.append(child_positioning_context); + fragment + }, + Ok(absolutely_positioned) => { + let hoisted_box = AbsolutelyPositionedBox::to_hoisted( + absolutely_positioned, + Vec2::zero(), + containing_block, + ); + let hoisted_fragment = hoisted_box.fragment.clone(); + positioning_context.push(hoisted_box); + Fragment::AbsoluteOrFixedPositioned(hoisted_fragment) + }, + }) + .collect::>(); + + // There should be no more flex items + assert!(flex_item_fragments.next().is_none()); IndependentLayout { fragments, - content_block_size: content_block_size_option_dance.unwrap(), + content_block_size, } } } @@ -232,8 +227,11 @@ fn layout<'context, 'boxes>( layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - flex_item_boxes: impl Iterator, -) -> (impl Iterator, Length) { + flex_item_boxes: impl Iterator, +) -> ( + impl Iterator, + Length, +) { // FIXME: get actual min/max cross size for the flex container. // We have access to style for the flex container in `containing_block.style`, // but resolving percentages there requires access @@ -290,7 +288,7 @@ fn layout<'context, 'boxes>( }; let mut flex_items = flex_item_boxes - .map(|(tree_rank, box_)| FlexItem::new(&flex_context, box_, tree_rank)) + .map(|box_| FlexItem::new(&flex_context, box_)) .collect::>(); // “Determine the main size of the flex container” @@ -387,7 +385,7 @@ fn layout<'context, 'boxes>( container_main_size }, }; - let fragments = flex_lines + let fragments_and_positioning_contexts = flex_lines .into_iter() .zip(line_cross_start_positions) .flat_map(move |(mut line, line_cross_start_position)| { @@ -409,21 +407,17 @@ fn layout<'context, 'boxes>( inline: container_cross_size - line_cross_start_position - line.cross_size, }, }; - for fragment in &mut line.item_fragments { + for (fragment, _) in &mut line.item_fragments { fragment.content_rect.start_corner += &flow_relative_line_position } line.item_fragments }) .into_iter(); - (fragments, content_block_size) + (fragments_and_positioning_contexts, content_block_size) } impl<'a> FlexItem<'a> { - fn new( - flex_context: &FlexContext, - box_: &'a mut IndependentFormattingContext, - tree_rank: usize, - ) -> Self { + fn new(flex_context: &FlexContext, box_: &'a mut IndependentFormattingContext) -> Self { let containing_block = flex_context.containing_block; let box_style = box_.style(); @@ -543,7 +537,6 @@ impl<'a> FlexItem<'a> { Self { box_, - tree_rank, content_box_size, content_min_size, content_max_size, @@ -730,7 +723,7 @@ impl FlexLine<'_> { // Determine the used cross size of each flex item // https://drafts.csswg.org/css-flexbox/#algo-stretch - let (item_used_cross_sizes, item_fragments): (Vec<_>, Vec<_>) = self + let (item_used_cross_sizes, item_results): (Vec<_>, Vec<_>) = self .items .iter_mut() .zip(item_layout_results) @@ -754,10 +747,7 @@ impl FlexLine<'_> { // so that percentage-sized children can be resolved.” item_result = item.layout(used_main_size, flex_context, Some(cross_size)); } - flex_context - .positioning_context - .append(item_result.positioning_context); - (cross_size, item_result.fragments) + (cross_size, item_result) }) .unzip(); @@ -838,7 +828,7 @@ impl FlexLine<'_> { let item_fragments = self .items .iter() - .zip(item_fragments) + .zip(item_results) .zip( item_used_main_sizes .iter() @@ -852,20 +842,23 @@ impl FlexLine<'_> { .map(|(size, start_corner)| FlexRelativeRect { size, start_corner }), ) .zip(&item_margins) - .map(|(((item, fragments), content_rect), margin)| { + .map(|(((item, item_result), content_rect), margin)| { let content_rect = flex_context.rect_to_flow_relative(line_size, content_rect); let margin = flex_context.sides_to_flow_relative(*margin); let collapsed_margin = CollapsedBlockMargins::from_margin(&margin); - BoxFragment::new( - item.box_.base_fragment_info(), - item.box_.style().clone(), - fragments, - content_rect, - flex_context.sides_to_flow_relative(item.padding), - flex_context.sides_to_flow_relative(item.border), - margin, - Length::zero(), - collapsed_margin, + ( + BoxFragment::new( + item.box_.base_fragment_info(), + item.box_.style().clone(), + item_result.fragments, + content_rect, + flex_context.sides_to_flow_relative(item.padding), + flex_context.sides_to_flow_relative(item.border), + margin, + Length::zero(), + collapsed_margin, + ), + item_result.positioning_context, ) }) .collect(); @@ -1048,7 +1041,7 @@ impl<'a> FlexItem<'a> { flex_context: &mut FlexContext, used_cross_size_override: Option, ) -> FlexItemLayoutResult { - let mut positioning_context = PositioningContext::new_for_rayon( + let mut positioning_context = PositioningContext::new_for_subtree( flex_context .positioning_context .collects_for_nearest_positioned_ancestor(), @@ -1109,7 +1102,6 @@ impl<'a> FlexItem<'a> { flex_context.layout_context, &mut positioning_context, &item_as_containing_block, - self.tree_rank, ); let hypothetical_cross_size = self diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index 5750ed6039d..dabf033c6e3 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -739,7 +739,6 @@ impl FloatBox { layout_context, &mut positioning_context, &containing_block_for_children, - 0, ); content_size = Vec2 { inline: inline_size, diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 7d447c492db..aba8790987a 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -271,7 +271,6 @@ impl InlineFormattingContext { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - tree_rank: usize, sequential_layout_state: Option<&mut SequentialLayoutState>, ) -> FlowLayout { let mut ifc = InlineFormattingContextState { @@ -342,7 +341,6 @@ impl InlineFormattingContext { let hoisted_box = AbsolutelyPositionedBox::to_hoisted( box_.clone(), initial_start_corner, - tree_rank, ifc.containing_block, ); let hoisted_fragment = hoisted_box.fragment.clone(); @@ -661,14 +659,12 @@ fn layout_atomic( containing_block_for_children.style.writing_mode, "Mixed writing modes are not supported yet" ); - // FIXME is this correct? - let dummy_tree_rank = 0; - // FIXME: Do we need to call `adjust_static_positions` somewhere near here? + // FIXME: Do we need to adjust the static position of the hoisted fragments in the positioning + // context somewhere near here? let independent_layout = non_replaced.layout( layout_context, ifc.positioning_context, &containing_block_for_children, - dummy_tree_rank, ); // https://drafts.csswg.org/css2/visudet.html#block-root-margin diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 94b1727b15a..f040d2eb0db 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -22,8 +22,7 @@ use crate::replaced::ReplacedContent; use crate::sizing::{self, ContentSizes}; use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin}; use crate::ContainingBlock; -use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; -use rayon_croissant::ParallelIteratorExt; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use servo_arc::Arc; use style::computed_values::clear::T as Clear; use style::computed_values::float::T as Float; @@ -79,7 +78,6 @@ impl BlockFormattingContext { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - tree_rank: usize, ) -> IndependentLayout { let mut sequential_layout_state = if self.contains_floats || !layout_context.use_rayon { Some(SequentialLayoutState::new()) @@ -91,7 +89,6 @@ impl BlockFormattingContext { layout_context, positioning_context, containing_block, - tree_rank, sequential_layout_state.as_mut(), CollapsibleWithParentStartMargin(false), ); @@ -208,7 +205,6 @@ impl BlockContainer { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - tree_rank: usize, sequential_layout_state: Option<&mut SequentialLayoutState>, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, ) -> FlowLayout { @@ -218,7 +214,6 @@ impl BlockContainer { positioning_context, child_boxes, containing_block, - tree_rank, sequential_layout_state, collapsible_with_parent_start_margin, ), @@ -226,7 +221,6 @@ impl BlockContainer { layout_context, positioning_context, containing_block, - tree_rank, sequential_layout_state, ), } @@ -255,7 +249,6 @@ fn layout_block_level_children( positioning_context: &mut PositioningContext, child_boxes: &[ArcRefCell], containing_block: &ContainingBlock, - tree_rank: usize, mut sequential_layout_state: Option<&mut SequentialLayoutState>, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, ) -> FlowLayout { @@ -265,7 +258,6 @@ fn layout_block_level_children( positioning_context, child_boxes, containing_block, - tree_rank, sequential_layout_state, collapsible_with_parent_start_margin, ), @@ -274,7 +266,6 @@ fn layout_block_level_children( positioning_context, child_boxes, containing_block, - tree_rank, collapsible_with_parent_start_margin, ), } @@ -285,37 +276,35 @@ fn layout_block_level_children_in_parallel( positioning_context: &mut PositioningContext, child_boxes: &[ArcRefCell], containing_block: &ContainingBlock, - tree_rank: usize, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, ) -> FlowLayout { - let mut placement_state = PlacementState::new(collapsible_with_parent_start_margin); + let collects_for_nearest_positioned_ancestor = + positioning_context.collects_for_nearest_positioned_ancestor(); + let layout_results: Vec<(Fragment, PositioningContext)> = child_boxes + .par_iter() + .map(|child_box| { + let mut child_positioning_context = + PositioningContext::new_for_subtree(collects_for_nearest_positioned_ancestor); + let fragment = child_box.borrow_mut().layout( + layout_context, + &mut child_positioning_context, + containing_block, + /* sequential_layout_state = */ None, + ); + (fragment, child_positioning_context) + }) + .collect(); - let fragments = positioning_context.adjust_static_positions(tree_rank, |positioning_context| { - let collects_for_nearest_positioned_ancestor = - positioning_context.collects_for_nearest_positioned_ancestor(); - let mut fragments: Vec = child_boxes - .par_iter() - .enumerate() - .mapfold_reduce_into( - positioning_context, - |positioning_context, (tree_rank, box_)| { - box_.borrow_mut().layout( - layout_context, - positioning_context, - containing_block, - tree_rank, - /* sequential_layout_state = */ None, - ) - }, - || PositioningContext::new_for_rayon(collects_for_nearest_positioned_ancestor), - PositioningContext::append, - ) - .collect(); - for fragment in fragments.iter_mut() { - placement_state.place_fragment(fragment); - } - fragments - }); + let mut placement_state = PlacementState::new(collapsible_with_parent_start_margin); + let fragments = layout_results + .into_iter() + .map(|(mut fragment, mut child_positioning_context)| { + placement_state.place_fragment(&mut fragment); + child_positioning_context.adjust_static_position_of_hoisted_fragments(&fragment); + positioning_context.append(child_positioning_context); + fragment + }) + .collect(); FlowLayout { fragments, @@ -329,35 +318,36 @@ fn layout_block_level_children_sequentially( positioning_context: &mut PositioningContext, child_boxes: &[ArcRefCell], containing_block: &ContainingBlock, - tree_rank: usize, sequential_layout_state: &mut SequentialLayoutState, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, ) -> FlowLayout { let mut placement_state = PlacementState::new(collapsible_with_parent_start_margin); + let collects_for_nearest_positioned_ancestor = + positioning_context.collects_for_nearest_positioned_ancestor(); - let fragments = positioning_context.adjust_static_positions(tree_rank, |positioning_context| { - // Because floats are involved, we do layout for this block formatting context in tree - // order without parallelism. This enables mutable access to a `SequentialLayoutState` that - // tracks every float encountered so far (again in tree order). - child_boxes - .iter() - .enumerate() - .map(|(tree_rank, child_box)| { - let mut fragment = child_box.borrow_mut().layout( - layout_context, - positioning_context, - containing_block, - tree_rank, - Some(&mut *sequential_layout_state), - ); + // Because floats are involved, we do layout for this block formatting context in tree + // order without parallelism. This enables mutable access to a `SequentialLayoutState` that + // tracks every float encountered so far (again in tree order). + let fragments = child_boxes + .iter() + .map(|child_box| { + let mut child_positioning_context = + PositioningContext::new_for_subtree(collects_for_nearest_positioned_ancestor); + let mut fragment = child_box.borrow_mut().layout( + layout_context, + &mut child_positioning_context, + containing_block, + Some(&mut *sequential_layout_state), + ); - placement_state.place_fragment(&mut fragment); - placement_state - .adjust_positions_of_float_children(&mut fragment, sequential_layout_state); - fragment - }) - .collect() - }); + placement_state.place_fragment(&mut fragment); + placement_state + .adjust_positions_of_float_children(&mut fragment, sequential_layout_state); + child_positioning_context.adjust_static_position_of_hoisted_fragments(&fragment); + positioning_context.append(child_positioning_context); + fragment + }) + .collect(); FlowLayout { fragments, @@ -372,7 +362,6 @@ impl BlockLevelBox { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - tree_rank: usize, sequential_layout_state: Option<&mut SequentialLayoutState>, ) -> Fragment { match self { @@ -392,7 +381,6 @@ impl BlockLevelBox { *tag, style, NonReplacedContents::SameFormattingContextBlock(contents), - tree_rank, sequential_layout_state, ) }, @@ -429,7 +417,6 @@ impl BlockLevelBox { NonReplacedContents::EstablishesAnIndependentFormattingContext( non_replaced, ), - tree_rank, sequential_layout_state, ) }, @@ -443,7 +430,6 @@ impl BlockLevelBox { // correct positioning until later, in place_block_level_fragment, // and this value will be adjusted there Vec2::zero(), - tree_rank, containing_block, ); let hoisted_fragment = hoisted_box.fragment.clone(); @@ -494,7 +480,6 @@ fn layout_in_flow_non_replaced_block_level( base_fragment_info: BaseFragmentInfo, style: &Arc, block_level_kind: NonReplacedContents, - tree_rank: usize, mut sequential_layout_state: Option<&mut SequentialLayoutState>, ) -> BoxFragment { let pbm = style.padding_border_margin(containing_block); @@ -623,7 +608,6 @@ fn layout_in_flow_non_replaced_block_level( layout_context, positioning_context, &containing_block_for_children, - tree_rank, sequential_layout_state.as_mut().map(|x| &mut **x), CollapsibleWithParentStartMargin(start_margin_can_collapse_with_children), ); @@ -665,7 +649,6 @@ fn layout_in_flow_non_replaced_block_level( layout_context, positioning_context, &containing_block_for_children, - tree_rank, ); fragments = independent_layout.fragments; content_block_size = independent_layout.content_block_size; diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index e30577c3c09..1262f7408aa 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -289,14 +289,12 @@ impl BoxTree { style, }; - let dummy_tree_rank = 0; let mut positioning_context = PositioningContext::new_for_containing_block_for_all_descendants(); let independent_layout = self.root.layout( layout_context, &mut positioning_context, &(&initial_containing_block).into(), - dummy_tree_rank, ); let mut root_fragments = independent_layout diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 494d7822fd9..aa920936b77 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -192,21 +192,14 @@ impl NonReplacedFormattingContext { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - tree_rank: usize, ) -> IndependentLayout { match &self.contents { - NonReplacedFormattingContextContents::Flow(bfc) => bfc.layout( - layout_context, - positioning_context, - containing_block, - tree_rank, - ), - NonReplacedFormattingContextContents::Flex(fc) => fc.layout( - layout_context, - positioning_context, - containing_block, - tree_rank, - ), + NonReplacedFormattingContextContents::Flow(bfc) => { + bfc.layout(layout_context, positioning_context, containing_block) + }, + NonReplacedFormattingContextContents::Flex(fc) => { + fc.layout(layout_context, positioning_context, containing_block) + }, } } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 282046456e2..446bef4811d 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -39,11 +39,6 @@ pub(crate) struct PositioningContext { pub(crate) struct HoistedAbsolutelyPositionedBox { absolutely_positioned_box: ArcRefCell, - /// The rank of the child from which this absolutely positioned fragment - /// came from, when doing the layout of a block container. Used to compute - /// static positions when going up the tree. - pub(crate) tree_rank: usize, - /// A reference to a Fragment which is shared between this `HoistedAbsolutelyPositionedBox` /// and its placeholder `AbsoluteOrFixedPositionedFragment` in the original tree position. /// This will be used later in order to paint this hoisted box in tree order. @@ -72,7 +67,6 @@ impl AbsolutelyPositionedBox { pub(crate) fn to_hoisted( self_: ArcRefCell, initial_start_corner: Vec2, - tree_rank: usize, containing_block: &ContainingBlock, ) -> HoistedAbsolutelyPositionedBox { fn absolute_box_offsets( @@ -112,7 +106,6 @@ impl AbsolutelyPositionedBox { } }; HoistedAbsolutelyPositionedBox { - tree_rank, fragment: ArcRefCell::new(HoistedSharedFragment::new(box_offsets)), absolutely_positioned_box: self_, } @@ -127,7 +120,11 @@ impl PositioningContext { } } - pub(crate) fn new_for_rayon(collects_for_nearest_positioned_ancestor: bool) -> Self { + /// Create a [PositioninContext] to use for laying out a subtree. The idea is that + /// when subtree layout is finished, the newly hoisted boxes can be processed + /// (normally adjusting their static insets) and then appended to the parent + /// [PositioningContext]. + pub(crate) fn new_for_subtree(collects_for_nearest_positioned_ancestor: bool) -> Self { Self { for_nearest_positioned_ancestor: if collects_for_nearest_positioned_ancestor { Some(Vec::new()) @@ -155,6 +152,47 @@ impl PositioningContext { } } + /// Absolute and fixed position fragments are hoisted up to their containing blocks + /// from their tree position. When these fragments have static inset start positions, + /// that position (relative to the ancestor containing block) needs to be included + /// with the hoisted fragment so that it can be laid out properly at the containing + /// block. + /// + /// This function is used to update that static position at every level of the + /// fragment tree as the hoisted fragments move back up to their containing blocks. + /// Once an ancestor fragment is laid out, this function can be used to aggregate its + /// offset on the way back up. + pub(crate) fn adjust_static_position_of_hoisted_fragments( + &mut self, + parent_fragment: &Fragment, + ) { + let fragment_rect = match &parent_fragment { + Fragment::Box(b) => &b.content_rect, + Fragment::AbsoluteOrFixedPositioned(_) | Fragment::Float(_) => return, + Fragment::Anonymous(a) => &a.rect, + _ => unreachable!(), + }; + + let update_fragment_if_needed = |hoisted_fragment: &mut HoistedAbsolutelyPositionedBox| { + let mut fragment = hoisted_fragment.fragment.borrow_mut(); + if let AbsoluteBoxOffsets::StaticStart { start } = &mut fragment.box_offsets.inline { + *start += fragment_rect.start_corner.inline; + } + if let AbsoluteBoxOffsets::StaticStart { start } = &mut fragment.box_offsets.block { + *start += fragment_rect.start_corner.block; + } + }; + + self.for_nearest_positioned_ancestor + .as_mut() + .map(|hoisted_boxes| { + hoisted_boxes.iter_mut().for_each(update_fragment_if_needed); + }); + self.for_nearest_containing_block_for_all_descendants + .iter_mut() + .for_each(update_fragment_if_needed); + } + /// Given `fragment_layout_fn`, a closure which lays out a fragment in a provided /// `PositioningContext`, create a new positioning context if necessary for the fragment and /// lay out the fragment and all its children. Returns the newly created `BoxFragment`. @@ -267,36 +305,6 @@ impl PositioningContext { } } - pub(crate) fn adjust_static_positions( - &mut self, - tree_rank_in_parent: usize, - f: impl FnOnce(&mut Self) -> Vec, - ) -> Vec { - let for_containing_block_for_all_descendants = - self.for_nearest_containing_block_for_all_descendants.len(); - let for_nearest_so_far = self - .for_nearest_positioned_ancestor - .as_ref() - .map(|v| v.len()); - - let fragments = f(self); - - adjust_static_positions( - &mut self.for_nearest_containing_block_for_all_descendants - [for_containing_block_for_all_descendants..], - &fragments, - tree_rank_in_parent, - ); - if let Some(nearest) = &mut self.for_nearest_positioned_ancestor { - adjust_static_positions( - &mut nearest[for_nearest_so_far.unwrap()..], - &fragments, - tree_rank_in_parent, - ); - } - fragments - } - pub(crate) fn layout_initial_containing_block_children( &mut self, layout_context: &LayoutContext, @@ -512,7 +520,6 @@ impl HoistedAbsolutelyPositionedBox { containing_block_for_children.style.writing_mode, "Mixed writing modes are not supported yet" ); - let dummy_tree_rank = 0; // Clear the context since we will lay out the same descendants // more than once. Otherwise, absolute descendants will create @@ -524,7 +531,6 @@ impl HoistedAbsolutelyPositionedBox { layout_context, &mut positioning_context, &containing_block_for_children, - dummy_tree_rank, ); let block_size = size.auto_is(|| independent_layout.content_block_size); Result { @@ -739,34 +745,6 @@ impl<'a> AbsoluteAxisSolver<'a> { } } -fn adjust_static_positions( - absolutely_positioned_fragments: &mut [HoistedAbsolutelyPositionedBox], - child_fragments: &[Fragment], - tree_rank_in_parent: usize, -) { - for abspos_fragment in absolutely_positioned_fragments { - let original_tree_rank = abspos_fragment.tree_rank; - abspos_fragment.tree_rank = tree_rank_in_parent; - - let child_fragment_rect = match &child_fragments[original_tree_rank] { - Fragment::Box(b) => &b.content_rect, - Fragment::AbsoluteOrFixedPositioned(_) | Fragment::Float(_) => continue, - Fragment::Anonymous(a) => &a.rect, - _ => unreachable!(), - }; - - let mut shared_fragment = abspos_fragment.fragment.borrow_mut(); - - if let AbsoluteBoxOffsets::StaticStart { start } = &mut shared_fragment.box_offsets.inline { - *start += child_fragment_rect.start_corner.inline; - } - - if let AbsoluteBoxOffsets::StaticStart { start } = &mut shared_fragment.box_offsets.block { - *start += child_fragment_rect.start_corner.block; - } - } -} - fn vec_append_owned(a: &mut Vec, mut b: Vec) { if a.is_empty() { *a = b