mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
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:
parent
f1b8d49e77
commit
9d11d584f6
6 changed files with 35 additions and 35 deletions
|
@ -22,7 +22,6 @@ use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::WhichPseudoElement;
|
use crate::dom_traversal::WhichPseudoElement;
|
||||||
use crate::flexbox::FlexLevelBox;
|
use crate::flexbox::FlexLevelBox;
|
||||||
use crate::flow::inline::inline_box::InlineBox;
|
|
||||||
use crate::flow::inline::InlineItem;
|
use crate::flow::inline::InlineItem;
|
||||||
use crate::flow::BlockLevelBox;
|
use crate::flow::BlockLevelBox;
|
||||||
use crate::geom::PhysicalSize;
|
use crate::geom::PhysicalSize;
|
||||||
|
@ -41,8 +40,6 @@ pub struct InnerDOMLayoutData {
|
||||||
pub(super) enum LayoutBox {
|
pub(super) enum LayoutBox {
|
||||||
DisplayContents,
|
DisplayContents,
|
||||||
BlockLevel(ArcRefCell<BlockLevelBox>),
|
BlockLevel(ArcRefCell<BlockLevelBox>),
|
||||||
#[allow(dead_code)]
|
|
||||||
InlineBox(ArcRefCell<InlineBox>),
|
|
||||||
InlineLevel(ArcRefCell<InlineItem>),
|
InlineLevel(ArcRefCell<InlineItem>),
|
||||||
FlexLevel(ArcRefCell<FlexLevelBox>),
|
FlexLevel(ArcRefCell<FlexLevelBox>),
|
||||||
TaffyItemBox(ArcRefCell<TaffyItemBox>),
|
TaffyItemBox(ArcRefCell<TaffyItemBox>),
|
||||||
|
|
|
@ -448,7 +448,8 @@ where
|
||||||
|
|
||||||
// Otherwise, this is just a normal inline box. Whatever happened before, all we need to do
|
// 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.
|
// 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));
|
.start_inline_box(InlineBox::new(info));
|
||||||
|
|
||||||
if is_list_item {
|
if is_list_item {
|
||||||
|
@ -467,9 +468,8 @@ where
|
||||||
|
|
||||||
self.finish_anonymous_table_if_needed();
|
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(
|
fn handle_block_level_element(
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::borrow::Cow;
|
||||||
use std::char::{ToLowercase, ToUppercase};
|
use std::char::{ToLowercase, ToUppercase};
|
||||||
|
|
||||||
use icu_segmenter::WordSegmenter;
|
use icu_segmenter::WordSegmenter;
|
||||||
|
use servo_arc::Arc;
|
||||||
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
|
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
|
||||||
use style::values::computed::TextDecorationLine;
|
use style::values::computed::TextDecorationLine;
|
||||||
use style::values::specified::text::TextTransformCase;
|
use style::values::specified::text::TextTransformCase;
|
||||||
|
@ -124,7 +125,7 @@ impl InlineFormattingContextBuilder {
|
||||||
independent_formatting_context: IndependentFormattingContext,
|
independent_formatting_context: IndependentFormattingContext,
|
||||||
) -> ArcRefCell<InlineItem> {
|
) -> ArcRefCell<InlineItem> {
|
||||||
let inline_level_box = ArcRefCell::new(InlineItem::Atomic(
|
let inline_level_box = ArcRefCell::new(InlineItem::Atomic(
|
||||||
independent_formatting_context,
|
Arc::new(independent_formatting_context),
|
||||||
self.current_text_offset,
|
self.current_text_offset,
|
||||||
Level::ltr(), /* This will be assigned later if necessary. */
|
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> {
|
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.inline_items.push(inline_level_box.clone());
|
||||||
self.contains_floats = true;
|
self.contains_floats = true;
|
||||||
inline_level_box
|
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);
|
self.push_control_character_string(inline_box.style.bidi_control_chars().0);
|
||||||
|
|
||||||
let identifier = self.inline_boxes.start_inline_box(inline_box);
|
let (identifier, inline_box) = self.inline_boxes.start_inline_box(inline_box);
|
||||||
self.inline_items
|
let inline_level_box = ArcRefCell::new(InlineItem::StartInlineBox(inline_box));
|
||||||
.push(ArcRefCell::new(InlineItem::StartInlineBox(identifier)));
|
self.inline_items.push(inline_level_box.clone());
|
||||||
self.inline_box_stack.push(identifier);
|
self.inline_box_stack.push(identifier);
|
||||||
|
inline_level_box
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn end_inline_box(&mut self) -> ArcRefCell<InlineBox> {
|
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 Some(inline_item) = self.inline_items.last() {
|
||||||
if let InlineItem::TextRun(text_run) = &mut *inline_item.borrow_mut() {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inline_items
|
self.inline_items
|
||||||
.push(ArcRefCell::new(InlineItem::TextRun(TextRun::new(
|
.push(ArcRefCell::new(InlineItem::TextRun(ArcRefCell::new(
|
||||||
info.into(),
|
TextRun::new(info.into(), info.style.clone(), new_range),
|
||||||
info.style.clone(),
|
|
||||||
new_range,
|
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,10 @@ impl InlineBoxes {
|
||||||
.push(InlineBoxTreePathToken::End(identifier));
|
.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_boxes.len() <= u32::MAX as usize);
|
||||||
assert!(self.inline_box_tree.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,
|
index_in_inline_boxes,
|
||||||
};
|
};
|
||||||
inline_box.identifier = identifier;
|
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
|
self.inline_box_tree
|
||||||
.push(InlineBoxTreePathToken::Start(identifier));
|
.push(InlineBoxTreePathToken::Start(identifier));
|
||||||
identifier
|
|
||||||
|
(identifier, inline_box)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_path(
|
pub(super) fn get_path(
|
||||||
|
|
|
@ -180,16 +180,16 @@ pub(crate) struct FontKeyAndMetrics {
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub(crate) enum InlineItem {
|
pub(crate) enum InlineItem {
|
||||||
StartInlineBox(InlineBoxIdentifier),
|
StartInlineBox(ArcRefCell<InlineBox>),
|
||||||
EndInlineBox,
|
EndInlineBox,
|
||||||
TextRun(TextRun),
|
TextRun(ArcRefCell<TextRun>),
|
||||||
OutOfFlowAbsolutelyPositionedBox(
|
OutOfFlowAbsolutelyPositionedBox(
|
||||||
ArcRefCell<AbsolutelyPositionedBox>,
|
ArcRefCell<AbsolutelyPositionedBox>,
|
||||||
usize, /* offset_in_text */
|
usize, /* offset_in_text */
|
||||||
),
|
),
|
||||||
OutOfFlowFloatBox(FloatBox),
|
OutOfFlowFloatBox(Arc<FloatBox>),
|
||||||
Atomic(
|
Atomic(
|
||||||
IndependentFormattingContext,
|
Arc<IndependentFormattingContext>,
|
||||||
usize, /* offset_in_text */
|
usize, /* offset_in_text */
|
||||||
Level, /* bidi_level */
|
Level, /* bidi_level */
|
||||||
),
|
),
|
||||||
|
@ -1536,7 +1536,7 @@ impl InlineFormattingContext {
|
||||||
for item in builder.inline_items.iter() {
|
for item in builder.inline_items.iter() {
|
||||||
match &mut *item.borrow_mut() {
|
match &mut *item.borrow_mut() {
|
||||||
InlineItem::TextRun(ref mut text_run) => {
|
InlineItem::TextRun(ref mut text_run) => {
|
||||||
text_run.segment_and_shape(
|
text_run.borrow_mut().segment_and_shape(
|
||||||
&text_content,
|
&text_content,
|
||||||
&layout_context.font_context,
|
&layout_context.font_context,
|
||||||
&mut new_linebreaker,
|
&mut new_linebreaker,
|
||||||
|
@ -1544,8 +1544,7 @@ impl InlineFormattingContext {
|
||||||
&bidi_info,
|
&bidi_info,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
InlineItem::StartInlineBox(identifier) => {
|
InlineItem::StartInlineBox(inline_box) => {
|
||||||
let inline_box = builder.inline_boxes.get(identifier);
|
|
||||||
let inline_box = &mut *inline_box.borrow_mut();
|
let inline_box = &mut *inline_box.borrow_mut();
|
||||||
if let Some(font) = get_font_for_first_font_for_style(
|
if let Some(font) = get_font_for_first_font_for_style(
|
||||||
&inline_box.style,
|
&inline_box.style,
|
||||||
|
@ -1676,11 +1675,11 @@ impl InlineFormattingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
InlineItem::StartInlineBox(identifier) => {
|
InlineItem::StartInlineBox(inline_box) => {
|
||||||
layout.start_inline_box(&self.inline_boxes.get(identifier).borrow());
|
layout.start_inline_box(&inline_box.borrow());
|
||||||
},
|
},
|
||||||
InlineItem::EndInlineBox => layout.finish_inline_box(),
|
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) => {
|
InlineItem::Atomic(atomic_formatting_context, offset_in_text, bidi_level) => {
|
||||||
atomic_formatting_context.layout_into_line_items(
|
atomic_formatting_context.layout_into_line_items(
|
||||||
&mut layout,
|
&mut layout,
|
||||||
|
@ -2237,12 +2236,11 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
||||||
inline_formatting_context: &InlineFormattingContext,
|
inline_formatting_context: &InlineFormattingContext,
|
||||||
) {
|
) {
|
||||||
match inline_item {
|
match inline_item {
|
||||||
InlineItem::StartInlineBox(identifier) => {
|
InlineItem::StartInlineBox(inline_box) => {
|
||||||
// For margins and paddings, a cyclic percentage is resolved against zero
|
// For margins and paddings, a cyclic percentage is resolved against zero
|
||||||
// for determining intrinsic size contributions.
|
// for determining intrinsic size contributions.
|
||||||
// https://drafts.csswg.org/css-sizing-3/#min-percentage-contribution
|
// 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 zero = Au::zero();
|
||||||
let writing_mode = self.constraint_space.writing_mode;
|
let writing_mode = self.constraint_space.writing_mode;
|
||||||
let padding = inline_box
|
let padding = inline_box
|
||||||
|
@ -2271,6 +2269,7 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
||||||
self.add_inline_size(length);
|
self.add_inline_size(length);
|
||||||
},
|
},
|
||||||
InlineItem::TextRun(text_run) => {
|
InlineItem::TextRun(text_run) => {
|
||||||
|
let text_run = &*text_run.borrow();
|
||||||
for segment in text_run.shaped_text.iter() {
|
for segment in text_run.shaped_text.iter() {
|
||||||
let style_text = text_run.parent_style.get_inherited_text();
|
let style_text = text_run.parent_style.get_inherited_text();
|
||||||
let can_wrap = style_text.text_wrap_mode == TextWrapMode::Wrap;
|
let can_wrap = style_text.text_wrap_mode == TextWrapMode::Wrap;
|
||||||
|
|
|
@ -185,7 +185,6 @@ impl BoxTree {
|
||||||
},
|
},
|
||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
LayoutBox::InlineBox(_) => return None,
|
|
||||||
LayoutBox::InlineLevel(inline_level_box) => match &*inline_level_box.borrow() {
|
LayoutBox::InlineLevel(inline_level_box) => match &*inline_level_box.borrow() {
|
||||||
InlineItem::OutOfFlowAbsolutelyPositionedBox(_, text_offset_index)
|
InlineItem::OutOfFlowAbsolutelyPositionedBox(_, text_offset_index)
|
||||||
if box_style.position.is_absolutely_positioned() =>
|
if box_style.position.is_absolutely_positioned() =>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue