layout: Clean up inline layout data types a bit (#34563)

- Remove the `LayoutBox::InlineBox` variant that was only used for
  inline level boxes. Now they are stored in `LayoutBox::InlineLevel`
  along with other kinds of out-of-flow and atomic inline items.
- Reduce the size of `InlineItem` by 260 bytes per item by using atomic
  indirection / pointers. This adds a bit of overhead to access items in
  exchange for a lot of memory saved.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2024-12-11 15:40:34 +01:00 committed by GitHub
parent f1b8d49e77
commit 9d11d584f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 35 additions and 35 deletions

View file

@ -22,7 +22,6 @@ use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom_traversal::WhichPseudoElement;
use crate::flexbox::FlexLevelBox;
use crate::flow::inline::inline_box::InlineBox;
use crate::flow::inline::InlineItem;
use crate::flow::BlockLevelBox;
use crate::geom::PhysicalSize;
@ -41,8 +40,6 @@ pub struct InnerDOMLayoutData {
pub(super) enum LayoutBox {
DisplayContents,
BlockLevel(ArcRefCell<BlockLevelBox>),
#[allow(dead_code)]
InlineBox(ArcRefCell<InlineBox>),
InlineLevel(ArcRefCell<InlineItem>),
FlexLevel(ArcRefCell<FlexLevelBox>),
TaffyItemBox(ArcRefCell<TaffyItemBox>),

View file

@ -448,7 +448,8 @@ where
// Otherwise, this is just a normal inline box. Whatever happened before, all we need to do
// before recurring is to remember this ongoing inline level box.
self.inline_formatting_context_builder
let inline_item = self
.inline_formatting_context_builder
.start_inline_box(InlineBox::new(info));
if is_list_item {
@ -467,9 +468,8 @@ where
self.finish_anonymous_table_if_needed();
box_slot.set(LayoutBox::InlineBox(
self.inline_formatting_context_builder.end_inline_box(),
));
self.inline_formatting_context_builder.end_inline_box();
box_slot.set(LayoutBox::InlineLevel(inline_item));
}
fn handle_block_level_element(

View file

@ -6,6 +6,7 @@ use std::borrow::Cow;
use std::char::{ToLowercase, ToUppercase};
use icu_segmenter::WordSegmenter;
use servo_arc::Arc;
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
use style::values::computed::TextDecorationLine;
use style::values::specified::text::TextTransformCase;
@ -124,7 +125,7 @@ impl InlineFormattingContextBuilder {
independent_formatting_context: IndependentFormattingContext,
) -> ArcRefCell<InlineItem> {
let inline_level_box = ArcRefCell::new(InlineItem::Atomic(
independent_formatting_context,
Arc::new(independent_formatting_context),
self.current_text_offset,
Level::ltr(), /* This will be assigned later if necessary. */
));
@ -155,19 +156,20 @@ impl InlineFormattingContextBuilder {
}
pub(crate) fn push_float_box(&mut self, float_box: FloatBox) -> ArcRefCell<InlineItem> {
let inline_level_box = ArcRefCell::new(InlineItem::OutOfFlowFloatBox(float_box));
let inline_level_box = ArcRefCell::new(InlineItem::OutOfFlowFloatBox(Arc::new(float_box)));
self.inline_items.push(inline_level_box.clone());
self.contains_floats = true;
inline_level_box
}
pub(crate) fn start_inline_box(&mut self, inline_box: InlineBox) {
pub(crate) fn start_inline_box(&mut self, inline_box: InlineBox) -> ArcRefCell<InlineItem> {
self.push_control_character_string(inline_box.style.bidi_control_chars().0);
let identifier = self.inline_boxes.start_inline_box(inline_box);
self.inline_items
.push(ArcRefCell::new(InlineItem::StartInlineBox(identifier)));
let (identifier, inline_box) = self.inline_boxes.start_inline_box(inline_box);
let inline_level_box = ArcRefCell::new(InlineItem::StartInlineBox(inline_box));
self.inline_items.push(inline_level_box.clone());
self.inline_box_stack.push(identifier);
inline_level_box
}
pub(crate) fn end_inline_box(&mut self) -> ArcRefCell<InlineBox> {
@ -256,16 +258,14 @@ impl InlineFormattingContextBuilder {
if let Some(inline_item) = self.inline_items.last() {
if let InlineItem::TextRun(text_run) = &mut *inline_item.borrow_mut() {
text_run.text_range.end = new_range.end;
text_run.borrow_mut().text_range.end = new_range.end;
return;
}
}
self.inline_items
.push(ArcRefCell::new(InlineItem::TextRun(TextRun::new(
info.into(),
info.style.clone(),
new_range,
.push(ArcRefCell::new(InlineItem::TextRun(ArcRefCell::new(
TextRun::new(info.into(), info.style.clone(), new_range),
))));
}

View file

@ -82,7 +82,10 @@ impl InlineBoxes {
.push(InlineBoxTreePathToken::End(identifier));
}
pub(super) fn start_inline_box(&mut self, mut inline_box: InlineBox) -> InlineBoxIdentifier {
pub(super) fn start_inline_box(
&mut self,
mut inline_box: InlineBox,
) -> (InlineBoxIdentifier, ArcRefCell<InlineBox>) {
assert!(self.inline_boxes.len() <= u32::MAX as usize);
assert!(self.inline_box_tree.len() <= u32::MAX as usize);
@ -94,11 +97,13 @@ impl InlineBoxes {
index_in_inline_boxes,
};
inline_box.identifier = identifier;
let inline_box = ArcRefCell::new(inline_box);
self.inline_boxes.push(ArcRefCell::new(inline_box));
self.inline_boxes.push(inline_box.clone());
self.inline_box_tree
.push(InlineBoxTreePathToken::Start(identifier));
identifier
(identifier, inline_box)
}
pub(super) fn get_path(

View file

@ -180,16 +180,16 @@ pub(crate) struct FontKeyAndMetrics {
#[derive(Debug, Serialize)]
pub(crate) enum InlineItem {
StartInlineBox(InlineBoxIdentifier),
StartInlineBox(ArcRefCell<InlineBox>),
EndInlineBox,
TextRun(TextRun),
TextRun(ArcRefCell<TextRun>),
OutOfFlowAbsolutelyPositionedBox(
ArcRefCell<AbsolutelyPositionedBox>,
usize, /* offset_in_text */
),
OutOfFlowFloatBox(FloatBox),
OutOfFlowFloatBox(Arc<FloatBox>),
Atomic(
IndependentFormattingContext,
Arc<IndependentFormattingContext>,
usize, /* offset_in_text */
Level, /* bidi_level */
),
@ -1536,7 +1536,7 @@ impl InlineFormattingContext {
for item in builder.inline_items.iter() {
match &mut *item.borrow_mut() {
InlineItem::TextRun(ref mut text_run) => {
text_run.segment_and_shape(
text_run.borrow_mut().segment_and_shape(
&text_content,
&layout_context.font_context,
&mut new_linebreaker,
@ -1544,8 +1544,7 @@ impl InlineFormattingContext {
&bidi_info,
);
},
InlineItem::StartInlineBox(identifier) => {
let inline_box = builder.inline_boxes.get(identifier);
InlineItem::StartInlineBox(inline_box) => {
let inline_box = &mut *inline_box.borrow_mut();
if let Some(font) = get_font_for_first_font_for_style(
&inline_box.style,
@ -1676,11 +1675,11 @@ impl InlineFormattingContext {
}
match item {
InlineItem::StartInlineBox(identifier) => {
layout.start_inline_box(&self.inline_boxes.get(identifier).borrow());
InlineItem::StartInlineBox(inline_box) => {
layout.start_inline_box(&inline_box.borrow());
},
InlineItem::EndInlineBox => layout.finish_inline_box(),
InlineItem::TextRun(run) => run.layout_into_line_items(&mut layout),
InlineItem::TextRun(run) => run.borrow().layout_into_line_items(&mut layout),
InlineItem::Atomic(atomic_formatting_context, offset_in_text, bidi_level) => {
atomic_formatting_context.layout_into_line_items(
&mut layout,
@ -2237,12 +2236,11 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
inline_formatting_context: &InlineFormattingContext,
) {
match inline_item {
InlineItem::StartInlineBox(identifier) => {
InlineItem::StartInlineBox(inline_box) => {
// For margins and paddings, a cyclic percentage is resolved against zero
// for determining intrinsic size contributions.
// https://drafts.csswg.org/css-sizing-3/#min-percentage-contribution
let inline_box = inline_formatting_context.inline_boxes.get(identifier);
let inline_box = (*inline_box).borrow();
let inline_box = inline_box.borrow();
let zero = Au::zero();
let writing_mode = self.constraint_space.writing_mode;
let padding = inline_box
@ -2271,6 +2269,7 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
self.add_inline_size(length);
},
InlineItem::TextRun(text_run) => {
let text_run = &*text_run.borrow();
for segment in text_run.shaped_text.iter() {
let style_text = text_run.parent_style.get_inherited_text();
let can_wrap = style_text.text_wrap_mode == TextWrapMode::Wrap;

View file

@ -185,7 +185,6 @@ impl BoxTree {
},
_ => return None,
},
LayoutBox::InlineBox(_) => return None,
LayoutBox::InlineLevel(inline_level_box) => match &*inline_level_box.borrow() {
InlineItem::OutOfFlowAbsolutelyPositionedBox(_, text_offset_index)
if box_style.position.is_absolutely_positioned() =>