layout: Move BoxFragment's block-level info into a dedicated struct (#37938)

`BoxFragment` had 2 fields that are only relevant for block-level boxes:
`clearance` and a boxed `block_margins_collapsed_with_children`.

This moves both pieces of data into a new `BlockLevelLayoutInfo` struct,
which is boxed.

As a result, the size of `BoxFragment` is reduced from 272 to 264 bytes.

Testing: Unneeded (no behavior change)

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2025-07-09 17:04:57 +02:00 committed by GitHub
parent 26f4da8249
commit d2ccf419c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 37 additions and 37 deletions

View file

@ -32,7 +32,8 @@ use crate::formatting_contexts::{
Baselines, IndependentFormattingContext, IndependentFormattingContextContents, Baselines, IndependentFormattingContext, IndependentFormattingContextContents,
}; };
use crate::fragment_tree::{ use crate::fragment_tree::{
BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, BaseFragmentInfo, BlockLevelLayoutInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin,
Fragment, FragmentFlags,
}; };
use crate::geom::{ use crate::geom::{
AuOrAuto, LazySize, LogicalRect, LogicalSides, LogicalSides1D, LogicalVec2, PhysicalPoint, AuOrAuto, LazySize, LogicalRect, LogicalSides, LogicalSides1D, LogicalVec2, PhysicalPoint,
@ -1175,8 +1176,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
flow_layout.specific_layout_info, flow_layout.specific_layout_info,
) )
.with_baselines(flow_layout.baselines) .with_baselines(flow_layout.baselines)
.with_block_margins_collapsed_with_children(block_margins_collapsed_with_children) .with_block_level_layout_info(block_margins_collapsed_with_children, clearance)
.with_clearance(clearance)
} }
impl IndependentFormattingContext { impl IndependentFormattingContext {
@ -1288,7 +1288,7 @@ impl IndependentFormattingContext {
layout.specific_layout_info, layout.specific_layout_info,
) )
.with_baselines(layout.baselines) .with_baselines(layout.baselines)
.with_block_margins_collapsed_with_children(block_margins_collapsed_with_children) .with_block_level_layout_info(block_margins_collapsed_with_children, None)
} }
/// Lay out a normal in flow non-replaced block that establishes an independent /// Lay out a normal in flow non-replaced block that establishes an independent
@ -1605,8 +1605,7 @@ impl IndependentFormattingContext {
layout.specific_layout_info, layout.specific_layout_info,
) )
.with_baselines(layout.baselines) .with_baselines(layout.baselines)
.with_block_margins_collapsed_with_children(CollapsedBlockMargins::from_margin(&margin)) .with_block_level_layout_info(CollapsedBlockMargins::from_margin(&margin), clearance)
.with_clearance(clearance)
} }
} }
@ -2076,7 +2075,13 @@ impl<'container> PlacementState<'container> {
return; return;
} }
let fragment_block_margins = fragment.block_margins_collapsed_with_children(); let BlockLevelLayoutInfo {
clearance,
block_margins_collapsed_with_children: fragment_block_margins,
} = &**fragment
.block_level_layout_info
.as_ref()
.expect("A block-level fragment should have a BlockLevelLayoutInfo.");
let mut fragment_block_size = fragment let mut fragment_block_size = fragment
.border_rect() .border_rect()
.size .size
@ -2088,7 +2093,7 @@ impl<'container> PlacementState<'container> {
// > If the top and bottom margins of an element with clearance are adjoining, // > If the top and bottom margins of an element with clearance are adjoining,
// > its margins collapse with the adjoining margins of following siblings but that // > its margins collapse with the adjoining margins of following siblings but that
// > resulting margin does not collapse with the bottom margin of the parent block. // > resulting margin does not collapse with the bottom margin of the parent block.
if let Some(clearance) = fragment.clearance { if let Some(clearance) = *clearance {
fragment_block_size += clearance; fragment_block_size += clearance;
// Margins can't be adjoining if they are separated by clearance. // Margins can't be adjoining if they are separated by clearance.
// Setting `next_in_flow_margin_collapses_with_parent_start_margin` to false // Setting `next_in_flow_margin_collapses_with_parent_start_margin` to false

View file

@ -54,6 +54,19 @@ pub(crate) enum SpecificLayoutInfo {
TableWrapper, TableWrapper,
} }
#[derive(MallocSizeOf)]
pub(crate) struct BlockLevelLayoutInfo {
/// When the `clear` property is not set to `none`, it may introduce clearance.
/// Clearance is some extra spacing that is added above the top margin,
/// so that the element doesn't overlap earlier floats in the same BFC.
/// The presence of clearance prevents the top margin from collapsing with
/// earlier margins or with the bottom margin of the parent block.
/// <https://drafts.csswg.org/css2/#clearance>
pub clearance: Option<Au>,
pub block_margins_collapsed_with_children: CollapsedBlockMargins,
}
#[derive(MallocSizeOf)] #[derive(MallocSizeOf)]
pub(crate) struct BoxFragment { pub(crate) struct BoxFragment {
pub base: BaseFragment, pub base: BaseFragment,
@ -73,21 +86,11 @@ pub(crate) struct BoxFragment {
pub border: PhysicalSides<Au>, pub border: PhysicalSides<Au>,
pub margin: PhysicalSides<Au>, pub margin: PhysicalSides<Au>,
/// When the `clear` property is not set to `none`, it may introduce clearance.
/// Clearance is some extra spacing that is added above the top margin,
/// so that the element doesn't overlap earlier floats in the same BFC.
/// The presence of clearance prevents the top margin from collapsing with
/// earlier margins or with the bottom margin of the parent block.
/// <https://drafts.csswg.org/css2/#clearance>
pub clearance: Option<Au>,
/// When this [`BoxFragment`] is for content that has a baseline, this tracks /// When this [`BoxFragment`] is for content that has a baseline, this tracks
/// the first and last baselines of that content. This is used to propagate baselines /// the first and last baselines of that content. This is used to propagate baselines
/// to things such as tables and inline formatting contexts. /// to things such as tables and inline formatting contexts.
baselines: Baselines, baselines: Baselines,
block_margins_collapsed_with_children: Option<Box<CollapsedBlockMargins>>,
/// The scrollable overflow of this box fragment in the same coordiante system as /// The scrollable overflow of this box fragment in the same coordiante system as
/// [`Self::content_rect`] ie a rectangle within the parent fragment's content /// [`Self::content_rect`] ie a rectangle within the parent fragment's content
/// rectangle. This does not take into account any transforms this fragment applies. /// rectangle. This does not take into account any transforms this fragment applies.
@ -103,6 +106,9 @@ pub(crate) struct BoxFragment {
/// Additional information of from layout that could be used by Javascripts and devtools. /// Additional information of from layout that could be used by Javascripts and devtools.
pub specific_layout_info: Option<SpecificLayoutInfo>, pub specific_layout_info: Option<SpecificLayoutInfo>,
/// Additional information for block-level boxes.
pub block_level_layout_info: Option<Box<BlockLevelLayoutInfo>>,
} }
impl BoxFragment { impl BoxFragment {
@ -126,13 +132,12 @@ impl BoxFragment {
padding, padding,
border, border,
margin, margin,
clearance: None,
baselines: Baselines::default(), baselines: Baselines::default(),
block_margins_collapsed_with_children: None,
scrollable_overflow: None, scrollable_overflow: None,
resolved_sticky_insets: AtomicRefCell::default(), resolved_sticky_insets: AtomicRefCell::default(),
background_mode: BackgroundMode::Normal, background_mode: BackgroundMode::Normal,
specific_layout_info, specific_layout_info,
block_level_layout_info: None,
} }
} }
@ -185,16 +190,15 @@ impl BoxFragment {
self.background_mode = BackgroundMode::None; self.background_mode = BackgroundMode::None;
} }
pub fn with_block_margins_collapsed_with_children( pub fn with_block_level_layout_info(
mut self, mut self,
collapsed_margins: CollapsedBlockMargins, block_margins_collapsed_with_children: CollapsedBlockMargins,
clearance: Option<Au>,
) -> Self { ) -> Self {
self.block_margins_collapsed_with_children = Some(collapsed_margins.into()); self.block_level_layout_info = Some(Box::new(BlockLevelLayoutInfo {
self block_margins_collapsed_with_children,
} clearance,
}));
pub fn with_clearance(mut self, clearance: Option<Au>) -> Self {
self.clearance = clearance;
self self
} }
@ -300,7 +304,6 @@ impl BoxFragment {
\npadding rect={:?}\ \npadding rect={:?}\
\nborder rect={:?}\ \nborder rect={:?}\
\nmargin={:?}\ \nmargin={:?}\
\nclearance={:?}\
\nscrollable_overflow={:?}\ \nscrollable_overflow={:?}\
\nbaselines={:?}\ \nbaselines={:?}\
\noverflow={:?}", \noverflow={:?}",
@ -309,7 +312,6 @@ impl BoxFragment {
self.padding_rect(), self.padding_rect(),
self.border_rect(), self.border_rect(),
self.margin, self.margin,
self.clearance,
self.scrollable_overflow(), self.scrollable_overflow(),
self.baselines, self.baselines,
self.style.effective_overflow(self.base.flags), self.style.effective_overflow(self.base.flags),
@ -513,11 +515,4 @@ impl BoxFragment {
_ => false, _ => false,
} }
} }
pub(crate) fn block_margins_collapsed_with_children(&self) -> CollapsedBlockMargins {
match self.block_margins_collapsed_with_children.as_ref() {
Some(collapsed_block_margins) => *(collapsed_block_margins).clone(),
_ => CollapsedBlockMargins::zero(),
}
}
} }