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>
This commit is contained in:
Martin Robinson 2025-04-18 11:40:29 +02:00 committed by GitHub
parent fc201927ae
commit 2ee8427665
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 387 additions and 222 deletions

View file

@ -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());
}
}
}