layout: Share styles to inline box children via SharedInlineStyles (#36896)

`TextRun`s use their parent style to render. Previously, these styles
were cloned and stored directly in the box tree `TextRun` and resulting
`TextFragment`s. This presents a problem for incremental layout.
Wrapping the style in another layer of shared ownership and mutability
will allow updating all `TextFragment`s during repaint-only incremental
layout by simply updating the box tree styles of the original text
parents.

This adds a new set of borrows when accessing text styles, but also
makes it so that during box tree block construction
`InlineFormattingContext`s are created lazily and now
`InlineFormattingContextBuilder::finish` consumes the builder, making
the API make a bit more sense. This should also improve performance of
box tree block construction slightly.

Testing: This should not change observable behavior and thus is covered
by existing WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2025-05-12 11:38:50 +02:00 committed by GitHub
parent db83601b62
commit a0dd2c1beb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 369 additions and 187 deletions

View file

@ -26,7 +26,7 @@ use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::flexbox::FlexLevelBox;
use crate::flow::BlockLevelBox;
use crate::flow::inline::InlineItem;
use crate::flow::inline::{InlineItem, SharedInlineStyles};
use crate::fragment_tree::Fragment;
use crate::geom::PhysicalSize;
use crate::replaced::CanvasInfo;
@ -59,7 +59,7 @@ impl InnerDOMLayoutData {
/// A box that is stored in one of the `DOMLayoutData` slots.
#[derive(MallocSizeOf)]
pub(super) enum LayoutBox {
DisplayContents,
DisplayContents(SharedInlineStyles),
BlockLevel(ArcRefCell<BlockLevelBox>),
InlineLevel(Vec<ArcRefCell<InlineItem>>),
FlexLevel(ArcRefCell<FlexLevelBox>),
@ -70,7 +70,7 @@ pub(super) enum LayoutBox {
impl LayoutBox {
fn invalidate_cached_fragment(&self) {
match self {
LayoutBox::DisplayContents => {},
LayoutBox::DisplayContents(..) => {},
LayoutBox::BlockLevel(block_level_box) => {
block_level_box.borrow().invalidate_cached_fragment()
},
@ -91,7 +91,7 @@ impl LayoutBox {
pub(crate) fn fragments(&self) -> Vec<Fragment> {
match self {
LayoutBox::DisplayContents => vec![],
LayoutBox::DisplayContents(..) => vec![],
LayoutBox::BlockLevel(block_level_box) => block_level_box.borrow().fragments(),
LayoutBox::InlineLevel(inline_items) => inline_items
.iter()