layout: Add method to retrieve only the first LayoutBoxBase of a box (#39165)

A LayoutBox typically has one LayoutBoxBase, or none in the case of
`LayoutBox::DisplayContents`. However, `LayoutBox::InlineLevel` can
contain multiple inline items, each one with its base. But since things
like the style or the fragment flags should be the same for all of them,
getting the first base is sometimes enough.

Testing: not needed, no change in behavior.

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2025-09-05 18:19:58 +02:00 committed by GitHub
parent 0f9f507b46
commit 5b9a23ebdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 23 additions and 11 deletions

View file

@ -140,6 +140,22 @@ impl LayoutBox {
} }
} }
pub(crate) fn with_first_base<T>(
&self,
callback: impl FnOnce(&LayoutBoxBase) -> T,
) -> Option<T> {
Some(match self {
LayoutBox::DisplayContents(..) => return None,
LayoutBox::BlockLevel(block_level_box) => block_level_box.borrow().with_base(callback),
LayoutBox::InlineLevel(inline_items) => {
inline_items.first()?.borrow().with_base(callback)
},
LayoutBox::FlexLevel(flex_level_box) => flex_level_box.borrow().with_base(callback),
LayoutBox::TaffyItemBox(taffy_item_box) => taffy_item_box.borrow().with_base(callback),
LayoutBox::TableLevelBox(table_box) => table_box.with_base(callback),
})
}
pub(crate) fn with_base_flat<T>(&self, callback: impl Fn(&LayoutBoxBase) -> Vec<T>) -> Vec<T> { pub(crate) fn with_base_flat<T>(&self, callback: impl Fn(&LayoutBoxBase) -> Vec<T>) -> Vec<T> {
match self { match self {
LayoutBox::DisplayContents(..) => vec![], LayoutBox::DisplayContents(..) => vec![],

View file

@ -191,7 +191,7 @@ impl FlexLevelBox {
} }
} }
pub(crate) fn with_base<T>(&self, callback: impl Fn(&LayoutBoxBase) -> T) -> T { pub(crate) fn with_base<T>(&self, callback: impl FnOnce(&LayoutBoxBase) -> T) -> T {
match self { match self {
FlexLevelBox::FlexItem(flex_item_box) => { FlexLevelBox::FlexItem(flex_item_box) => {
callback(&flex_item_box.independent_formatting_context.base) callback(&flex_item_box.independent_formatting_context.base)

View file

@ -274,7 +274,7 @@ impl InlineItem {
} }
} }
pub(crate) fn with_base<T>(&self, callback: impl Fn(&LayoutBoxBase) -> T) -> T { pub(crate) fn with_base<T>(&self, callback: impl FnOnce(&LayoutBoxBase) -> T) -> T {
match self { match self {
InlineItem::StartInlineBox(inline_box) => callback(&inline_box.borrow().base), InlineItem::StartInlineBox(inline_box) => callback(&inline_box.borrow().base),
InlineItem::EndInlineBox | InlineItem::TextRun(..) => { InlineItem::EndInlineBox | InlineItem::TextRun(..) => {

View file

@ -139,7 +139,7 @@ impl BlockLevelBox {
self.with_base(|base| base.clear_fragment_layout_cache()); self.with_base(|base| base.clear_fragment_layout_cache());
} }
pub(crate) fn with_base<T>(&self, callback: impl Fn(&LayoutBoxBase) -> T) -> T { pub(crate) fn with_base<T>(&self, callback: impl FnOnce(&LayoutBoxBase) -> T) -> T {
match self { match self {
BlockLevelBox::Independent(independent_formatting_context) => { BlockLevelBox::Independent(independent_formatting_context) => {
callback(&independent_formatting_context.base) callback(&independent_formatting_context.base)

View file

@ -661,9 +661,7 @@ pub(crate) fn process_scroll_parent_query(
let layout_box = layout_box.as_ref()?; let layout_box = layout_box.as_ref()?;
let (mut current_position_value, flags) = layout_box let (mut current_position_value, flags) = layout_box
.with_base_flat(|base| vec![(base.style.clone_position(), base.base_fragment_info.flags)]) .with_first_base(|base| (base.style.clone_position(), base.base_fragment_info.flags))?;
.first()
.cloned()?;
// - The element is the root element. // - The element is the root element.
// - The element is the body element. // - The element is the body element.
@ -702,9 +700,7 @@ pub(crate) fn process_scroll_parent_query(
}; };
let Some((ancestor_style, ancestor_flags)) = ancestor_layout_box let Some((ancestor_style, ancestor_flags)) = ancestor_layout_box
.with_base_flat(|base| vec![(base.style.clone(), base.base_fragment_info.flags)]) .with_first_base(|base| (base.style.clone(), base.base_fragment_info.flags))
.first()
.cloned()
else { else {
continue; continue;
}; };

View file

@ -412,7 +412,7 @@ impl TableLevelBox {
} }
} }
pub(crate) fn with_base<T>(&self, callback: impl Fn(&LayoutBoxBase) -> T) -> T { pub(crate) fn with_base<T>(&self, callback: impl FnOnce(&LayoutBoxBase) -> T) -> T {
match self { match self {
TableLevelBox::Caption(caption) => callback(&caption.borrow().context.base), TableLevelBox::Caption(caption) => callback(&caption.borrow().context.base),
TableLevelBox::Cell(cell) => callback(&cell.borrow().base), TableLevelBox::Cell(cell) => callback(&cell.borrow().base),

View file

@ -147,7 +147,7 @@ impl TaffyItemBox {
} }
} }
pub(crate) fn with_base<T>(&self, callback: impl Fn(&LayoutBoxBase) -> T) -> T { pub(crate) fn with_base<T>(&self, callback: impl FnOnce(&LayoutBoxBase) -> T) -> T {
match self.taffy_level_box { match self.taffy_level_box {
TaffyItemBoxInner::InFlowBox(ref independent_formatting_context) => { TaffyItemBoxInner::InFlowBox(ref independent_formatting_context) => {
callback(&independent_formatting_context.base) callback(&independent_formatting_context.base)