mirror of
https://github.com/servo/servo.git
synced 2025-08-10 07:55:33 +01:00
layout: Make Fragment
hold ArcRefCell
inside (#34923)
Push the interior mutability into enum variants of `Fragment`, so that they can be cloned. This saves memory in the `Fragment` tree as the `Fragment` enum is now a relatively wee 16 bytes and the interior parts can be a variety of sizes. Before, every `Fragment` was the size of the biggest kind (`BoxFragment` - 248 bytes). This a step on the way toward incremental layout. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
c936dd6c4e
commit
de780dcde4
18 changed files with 257 additions and 233 deletions
|
@ -292,9 +292,9 @@ impl LineItemLayout<'_, '_> {
|
|||
// We do not know the actual physical position of a logically laid out inline element, until
|
||||
// we know the width of the containing inline block. This step converts the logical rectangle
|
||||
// into a physical one based on the inline formatting context width.
|
||||
if let Some(content_rect) = fragment.content_rect_mut() {
|
||||
fragment.mutate_content_rect(|content_rect| {
|
||||
*content_rect = logical_rect.as_physical(Some(self.layout.containing_block))
|
||||
}
|
||||
});
|
||||
|
||||
fragment
|
||||
})
|
||||
|
@ -436,7 +436,7 @@ impl LineItemLayout<'_, '_> {
|
|||
.into_iter()
|
||||
.map(|(mut fragment, logical_rect)| {
|
||||
let is_float = matches!(fragment, Fragment::Float(_));
|
||||
if let Some(content_rect) = fragment.content_rect_mut() {
|
||||
fragment.mutate_content_rect(|content_rect| {
|
||||
if is_float {
|
||||
content_rect.origin -=
|
||||
pbm_sums.start_offset().to_physical_size(ifc_writing_mode);
|
||||
|
@ -446,7 +446,7 @@ impl LineItemLayout<'_, '_> {
|
|||
// into a physical one now that we've computed inline size of the containing inline block above.
|
||||
*content_rect = logical_rect.as_physical(Some(&inline_box_containing_block))
|
||||
}
|
||||
}
|
||||
});
|
||||
fragment
|
||||
})
|
||||
.collect();
|
||||
|
@ -495,7 +495,7 @@ impl LineItemLayout<'_, '_> {
|
|||
self.current_state.inline_advance += inner_state.inline_advance + pbm_sums.inline_sum();
|
||||
self.current_state
|
||||
.fragments
|
||||
.push((Fragment::Box(fragment), content_rect));
|
||||
.push((Fragment::Box(ArcRefCell::new(fragment)), content_rect));
|
||||
}
|
||||
|
||||
fn calculate_inline_box_block_start(
|
||||
|
@ -566,7 +566,7 @@ impl LineItemLayout<'_, '_> {
|
|||
|
||||
self.current_state.inline_advance += inline_advance;
|
||||
self.current_state.fragments.push((
|
||||
Fragment::Text(TextFragment {
|
||||
Fragment::Text(ArcRefCell::new(TextFragment {
|
||||
base: text_item.base_fragment_info.into(),
|
||||
parent_style: text_item.parent_style,
|
||||
rect: PhysicalRect::zero(),
|
||||
|
@ -575,7 +575,7 @@ impl LineItemLayout<'_, '_> {
|
|||
glyphs: text_item.text,
|
||||
text_decoration_line: text_item.text_decoration_line,
|
||||
justification_adjustment: self.justification_adjustment,
|
||||
}),
|
||||
})),
|
||||
content_rect,
|
||||
));
|
||||
}
|
||||
|
@ -627,9 +627,10 @@ impl LineItemLayout<'_, '_> {
|
|||
}
|
||||
|
||||
self.current_state.inline_advance += atomic.size.inline;
|
||||
self.current_state
|
||||
.fragments
|
||||
.push((Fragment::Box(atomic.fragment), content_rect));
|
||||
self.current_state.fragments.push((
|
||||
Fragment::Box(ArcRefCell::new(atomic.fragment)),
|
||||
content_rect,
|
||||
));
|
||||
}
|
||||
|
||||
fn layout_absolute(&mut self, absolute: AbsolutelyPositionedLineItem) {
|
||||
|
@ -706,9 +707,10 @@ impl LineItemLayout<'_, '_> {
|
|||
float.fragment.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(float.fragment), LogicalRect::zero()));
|
||||
self.current_state.fragments.push((
|
||||
Fragment::Float(ArcRefCell::new(float.fragment)),
|
||||
LogicalRect::zero(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -289,9 +289,9 @@ impl OutsideMarker {
|
|||
.fold(Au::zero(), |current_max, fragment| {
|
||||
current_max.max(
|
||||
match fragment {
|
||||
Fragment::Text(text) => text.rect,
|
||||
Fragment::Image(image) => image.rect,
|
||||
Fragment::Positioning(positioning) => positioning.rect,
|
||||
Fragment::Text(text) => text.borrow().rect,
|
||||
Fragment::Image(image) => image.borrow().rect,
|
||||
Fragment::Positioning(positioning) => positioning.borrow().rect,
|
||||
Fragment::Box(_) |
|
||||
Fragment::Float(_) |
|
||||
Fragment::AbsoluteOrFixedPositioned(_) |
|
||||
|
@ -331,7 +331,7 @@ impl OutsideMarker {
|
|||
let mut base_fragment_info = BaseFragmentInfo::anonymous();
|
||||
base_fragment_info.flags |= FragmentFlags::IS_OUTSIDE_LIST_ITEM_MARKER;
|
||||
|
||||
Fragment::Box(BoxFragment::new(
|
||||
Fragment::Box(ArcRefCell::new(BoxFragment::new(
|
||||
base_fragment_info,
|
||||
self.marker_style.clone(),
|
||||
flow_layout.fragments,
|
||||
|
@ -341,7 +341,7 @@ impl OutsideMarker {
|
|||
PhysicalSides::zero(),
|
||||
None,
|
||||
CollapsedBlockMargins::zero(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -724,8 +724,8 @@ impl BlockLevelBox {
|
|||
collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>,
|
||||
) -> Fragment {
|
||||
match self {
|
||||
BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => {
|
||||
Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
|
||||
BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => Fragment::Box(
|
||||
ArcRefCell::new(positioning_context.layout_maybe_position_relative_fragment(
|
||||
layout_context,
|
||||
containing_block,
|
||||
&base.style,
|
||||
|
@ -740,10 +740,10 @@ impl BlockLevelBox {
|
|||
collapsible_with_parent_start_margin,
|
||||
)
|
||||
},
|
||||
))
|
||||
},
|
||||
BlockLevelBox::Independent(independent) => {
|
||||
Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
|
||||
)),
|
||||
),
|
||||
BlockLevelBox::Independent(independent) => Fragment::Box(ArcRefCell::new(
|
||||
positioning_context.layout_maybe_position_relative_fragment(
|
||||
layout_context,
|
||||
containing_block,
|
||||
independent.style(),
|
||||
|
@ -755,8 +755,8 @@ impl BlockLevelBox {
|
|||
sequential_layout_state,
|
||||
)
|
||||
},
|
||||
))
|
||||
},
|
||||
),
|
||||
)),
|
||||
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
|
||||
// The static position of zero here is incorrect, however we do not know
|
||||
// the correct positioning until later, in place_block_level_fragment, and
|
||||
|
@ -777,10 +777,8 @@ impl BlockLevelBox {
|
|||
positioning_context.push(hoisted_box);
|
||||
Fragment::AbsoluteOrFixedPositioned(hoisted_fragment)
|
||||
},
|
||||
BlockLevelBox::OutOfFlowFloatBox(float_box) => Fragment::Float(float_box.layout(
|
||||
layout_context,
|
||||
positioning_context,
|
||||
containing_block,
|
||||
BlockLevelBox::OutOfFlowFloatBox(float_box) => Fragment::Float(ArcRefCell::new(
|
||||
float_box.layout(layout_context, positioning_context, containing_block),
|
||||
)),
|
||||
BlockLevelBox::OutsideMarker(outside_marker) => outside_marker.layout(
|
||||
layout_context,
|
||||
|
@ -1912,6 +1910,7 @@ impl<'container> PlacementState<'container> {
|
|||
Fragment::Box(box_fragment) => box_fragment,
|
||||
_ => return,
|
||||
};
|
||||
let box_fragment = box_fragment.borrow();
|
||||
|
||||
// From <https://drafts.csswg.org/css-align-3/#baseline-export>:
|
||||
// > When finding the first/last baseline set of an inline-block, any baselines
|
||||
|
@ -1955,6 +1954,7 @@ impl<'container> PlacementState<'container> {
|
|||
// between the marker and the item. For instance the marker should be positioned at
|
||||
// the baseline of list item content and the first line of the item content should
|
||||
// be at least as tall as the marker -- not the entire list item itself.
|
||||
let fragment = &mut *fragment.borrow_mut();
|
||||
let is_outside_marker = fragment
|
||||
.base
|
||||
.flags
|
||||
|
@ -2049,6 +2049,7 @@ impl<'container> PlacementState<'container> {
|
|||
.expect("Found float fragment without SequentialLayoutState");
|
||||
let block_offset_from_containing_block_top =
|
||||
self.current_block_direction_position + self.current_margin.solve();
|
||||
let box_fragment = &mut *box_fragment.borrow_mut();
|
||||
sequential_layout_state.place_float_fragment(
|
||||
box_fragment,
|
||||
self.containing_block,
|
||||
|
|
|
@ -357,11 +357,7 @@ impl BoxTree {
|
|||
&(&initial_containing_block).into(),
|
||||
);
|
||||
|
||||
let mut root_fragments = independent_layout
|
||||
.fragments
|
||||
.into_iter()
|
||||
.map(ArcRefCell::new)
|
||||
.collect::<Vec<_>>();
|
||||
let mut root_fragments = independent_layout.fragments.into_iter().collect::<Vec<_>>();
|
||||
|
||||
// Zero box for `:root { display: none }`, one for the root element otherwise.
|
||||
assert!(root_fragments.len() <= 1);
|
||||
|
@ -378,7 +374,7 @@ impl BoxTree {
|
|||
let scrollable_overflow = root_fragments
|
||||
.iter()
|
||||
.fold(PhysicalRect::zero(), |acc, child| {
|
||||
let child_overflow = child.borrow().scrollable_overflow();
|
||||
let child_overflow = child.scrollable_overflow();
|
||||
|
||||
// https://drafts.csswg.org/css-overflow/#scrolling-direction
|
||||
// We want to clip scrollable overflow on box-start and inline-start
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue