layout: Add a LayoutBoxBase to inline boxes (#36513)

`LayoutBoxBase` will soon contain laid out `Fragment`s of a box tree
node in order to facilitate incremental layout and also layout queries.
This is currently missing for inline boxes, so this change adds a
`LayoutBoxBase` to them.

Testing: This should not change any observable behavior, so existing
WPT suites should suffice for testing.

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-14 18:02:37 +02:00 committed by GitHub
parent 440739090f
commit d46a17a487
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 29 additions and 24 deletions

View file

@ -163,7 +163,7 @@ impl InlineFormattingContextBuilder {
} }
pub(crate) fn start_inline_box(&mut self, inline_box: InlineBox) -> ArcRefCell<InlineItem> { 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.base.style.bidi_control_chars().0);
let (identifier, inline_box) = self.inline_boxes.start_inline_box(inline_box); let (identifier, inline_box) = self.inline_boxes.start_inline_box(inline_box);
let inline_level_box = ArcRefCell::new(InlineItem::StartInlineBox(inline_box)); let inline_level_box = ArcRefCell::new(InlineItem::StartInlineBox(inline_box));
@ -177,7 +177,9 @@ impl InlineFormattingContextBuilder {
let inline_level_box = self.inline_boxes.get(&identifier); let inline_level_box = self.inline_boxes.get(&identifier);
inline_level_box.borrow_mut().is_last_fragment = true; inline_level_box.borrow_mut().is_last_fragment = true;
self.push_control_character_string(inline_level_box.borrow().style.bidi_control_chars().1); self.push_control_character_string(
inline_level_box.borrow().base.style.bidi_control_chars().1,
);
inline_level_box inline_level_box
} }

View file

@ -6,8 +6,6 @@ use std::vec::IntoIter;
use app_units::Au; use app_units::Au;
use fonts::FontMetrics; use fonts::FontMetrics;
use servo_arc::Arc;
use style::properties::ComputedValues;
use super::{InlineContainerState, InlineContainerStateFlags, inline_container_needs_strut}; use super::{InlineContainerState, InlineContainerStateFlags, inline_container_needs_strut};
use crate::ContainingBlock; use crate::ContainingBlock;
@ -16,12 +14,12 @@ use crate::context::LayoutContext;
use crate::dom::NodeExt; use crate::dom::NodeExt;
use crate::dom_traversal::NodeAndStyleInfo; use crate::dom_traversal::NodeAndStyleInfo;
use crate::fragment_tree::BaseFragmentInfo; use crate::fragment_tree::BaseFragmentInfo;
use crate::layout_box_base::LayoutBoxBase;
use crate::style_ext::{LayoutStyle, PaddingBorderMargin}; use crate::style_ext::{LayoutStyle, PaddingBorderMargin};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct InlineBox { pub(crate) struct InlineBox {
pub base_fragment_info: BaseFragmentInfo, pub base: LayoutBoxBase,
pub style: Arc<ComputedValues>,
/// The identifier of this inline box in the containing [`super::InlineFormattingContext`]. /// The identifier of this inline box in the containing [`super::InlineFormattingContext`].
pub(super) identifier: InlineBoxIdentifier, pub(super) identifier: InlineBoxIdentifier,
pub is_first_fragment: bool, pub is_first_fragment: bool,
@ -34,8 +32,7 @@ pub(crate) struct InlineBox {
impl InlineBox { impl InlineBox {
pub(crate) fn new<'dom, Node: NodeExt<'dom>>(info: &NodeAndStyleInfo<Node>) -> Self { pub(crate) fn new<'dom, Node: NodeExt<'dom>>(info: &NodeAndStyleInfo<Node>) -> Self {
Self { Self {
base_fragment_info: info.into(), base: LayoutBoxBase::new(info.into(), info.style.clone()),
style: info.style.clone(),
// This will be assigned later, when the box is actually added to the IFC. // This will be assigned later, when the box is actually added to the IFC.
identifier: InlineBoxIdentifier::default(), identifier: InlineBoxIdentifier::default(),
is_first_fragment: true, is_first_fragment: true,
@ -46,7 +43,7 @@ impl InlineBox {
pub(crate) fn split_around_block(&self) -> Self { pub(crate) fn split_around_block(&self) -> Self {
Self { Self {
style: self.style.clone(), base: LayoutBoxBase::new(self.base.base_fragment_info, self.base.style.clone()),
is_first_fragment: false, is_first_fragment: false,
is_last_fragment: false, is_last_fragment: false,
..*self ..*self
@ -55,7 +52,7 @@ impl InlineBox {
#[inline] #[inline]
pub(crate) fn layout_style(&self) -> LayoutStyle { pub(crate) fn layout_style(&self) -> LayoutStyle {
LayoutStyle::Default(&self.style) LayoutStyle::Default(&self.base.style)
} }
} }
@ -218,7 +215,7 @@ impl InlineBoxContainerState {
is_last_fragment: bool, is_last_fragment: bool,
font_metrics: Option<&FontMetrics>, font_metrics: Option<&FontMetrics>,
) -> Self { ) -> Self {
let style = inline_box.style.clone(); let style = inline_box.base.style.clone();
let pbm = inline_box let pbm = inline_box
.layout_style() .layout_style()
.padding_border_margin(containing_block); .padding_border_margin(containing_block);
@ -237,7 +234,7 @@ impl InlineBoxContainerState {
font_metrics, font_metrics,
), ),
identifier: inline_box.identifier, identifier: inline_box.identifier,
base_fragment_info: inline_box.base_fragment_info, base_fragment_info: inline_box.base.base_fragment_info,
pbm, pbm,
is_last_fragment, is_last_fragment,
} }

View file

@ -326,7 +326,7 @@ impl LineItemLayout<'_, '_> {
let inline_box = self.layout.ifc.inline_boxes.get(identifier); let inline_box = self.layout.ifc.inline_boxes.get(identifier);
let inline_box = &*(inline_box.borrow()); let inline_box = &*(inline_box.borrow());
let style = &inline_box.style; let style = &inline_box.base.style;
let space_above_baseline = inline_box_state.calculate_space_above_baseline(); let space_above_baseline = inline_box_state.calculate_space_above_baseline();
let block_start_offset = let block_start_offset =
self.calculate_inline_box_block_start(inline_box_state, space_above_baseline); self.calculate_inline_box_block_start(inline_box_state, space_above_baseline);
@ -378,7 +378,7 @@ impl LineItemLayout<'_, '_> {
let containing_block_writing_mode = self.layout.containing_block.style.writing_mode; let containing_block_writing_mode = self.layout.containing_block.style.writing_mode;
if containing_block_writing_mode.is_bidi_ltr() != if containing_block_writing_mode.is_bidi_ltr() !=
inline_box.style.writing_mode.is_bidi_ltr() inline_box.base.style.writing_mode.is_bidi_ltr()
{ {
std::mem::swap(&mut had_start, &mut had_end) std::mem::swap(&mut had_start, &mut had_end)
} }
@ -418,7 +418,7 @@ impl LineItemLayout<'_, '_> {
// Relative adjustment should not affect the rest of line layout, so we can // Relative adjustment should not affect the rest of line layout, so we can
// do it right before creating the Fragment. // do it right before creating the Fragment.
let style = &inline_box.style; let style = &inline_box.base.style;
if style.get_box().position == Position::Relative { if style.get_box().position == Position::Relative {
content_rect.start_corner += relative_adjustement(style, self.layout.containing_block); content_rect.start_corner += relative_adjustement(style, self.layout.containing_block);
} }
@ -455,7 +455,7 @@ impl LineItemLayout<'_, '_> {
// but they need to be made relative to this fragment. // but they need to be made relative to this fragment.
let physical_content_rect = content_rect.as_physical(Some(self.layout.containing_block)); let physical_content_rect = content_rect.as_physical(Some(self.layout.containing_block));
let mut fragment = BoxFragment::new( let mut fragment = BoxFragment::new(
inline_box.base_fragment_info, inline_box.base.base_fragment_info,
style.clone(), style.clone(),
fragments, fragments,
physical_content_rect, physical_content_rect,

View file

@ -200,8 +200,10 @@ pub(crate) enum InlineItem {
impl InlineItem { impl InlineItem {
pub(crate) fn invalidate_cached_fragment(&self) { pub(crate) fn invalidate_cached_fragment(&self) {
match self { match self {
InlineItem::StartInlineBox(..) | InlineItem::EndInlineBox | InlineItem::TextRun(..) => { InlineItem::StartInlineBox(inline_box) => {
inline_box.borrow().base.invalidate_cached_fragment()
}, },
InlineItem::EndInlineBox | InlineItem::TextRun(..) => {},
InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => { InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => {
positioned_box positioned_box
.borrow() .borrow()
@ -732,6 +734,7 @@ impl InlineFormattingContextLayout<'_> {
); );
self.depends_on_block_constraints |= inline_box self.depends_on_block_constraints |= inline_box
.base
.style .style
.depends_on_block_constraints_due_to_relative_positioning( .depends_on_block_constraints_due_to_relative_positioning(
self.containing_block.style.writing_mode, self.containing_block.style.writing_mode,
@ -1603,7 +1606,7 @@ impl InlineFormattingContext {
InlineItem::StartInlineBox(inline_box) => { InlineItem::StartInlineBox(inline_box) => {
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.base.style,
&layout_context.font_context, &layout_context.font_context,
) { ) {
inline_box.default_font_index = Some(add_or_get_font( inline_box.default_font_index = Some(add_or_get_font(
@ -2309,6 +2312,7 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
.percentages_relative_to(zero); .percentages_relative_to(zero);
let border = layout_style.border_width(writing_mode); let border = layout_style.border_width(writing_mode);
let margin = inline_box let margin = inline_box
.base
.style .style
.margin(writing_mode) .margin(writing_mode)
.percentages_relative_to(zero) .percentages_relative_to(zero)

View file

@ -275,6 +275,7 @@ impl IndependentNonReplacedContents {
depends_on_block_constraints: bool, depends_on_block_constraints: bool,
) -> CacheableLayoutResult { ) -> CacheableLayoutResult {
if let Some(cache) = base.cached_layout_result.borrow().as_ref() { if let Some(cache) = base.cached_layout_result.borrow().as_ref() {
let cache = &**cache;
if cache.containing_block_for_children_size.inline == if cache.containing_block_for_children_size.inline ==
containing_block_for_children.size.inline && containing_block_for_children.size.inline &&
(cache.containing_block_for_children_size.block == (cache.containing_block_for_children_size.block ==
@ -305,11 +306,11 @@ impl IndependentNonReplacedContents {
depends_on_block_constraints, depends_on_block_constraints,
); );
*base.cached_layout_result.borrow_mut() = Some(CacheableLayoutResultAndInputs { *base.cached_layout_result.borrow_mut() = Some(Box::new(CacheableLayoutResultAndInputs {
result: result.clone(), result: result.clone(),
positioning_context: child_positioning_context.clone(), positioning_context: child_positioning_context.clone(),
containing_block_for_children_size: containing_block_for_children.size.clone(), containing_block_for_children_size: containing_block_for_children.size.clone(),
}); }));
positioning_context.append(child_positioning_context); positioning_context.append(child_positioning_context);
result result

View file

@ -27,8 +27,8 @@ pub(crate) struct LayoutBoxBase {
pub base_fragment_info: BaseFragmentInfo, pub base_fragment_info: BaseFragmentInfo,
pub style: Arc<ComputedValues>, pub style: Arc<ComputedValues>,
pub cached_inline_content_size: pub cached_inline_content_size:
AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>, AtomicRefCell<Option<Box<(SizeConstraint, InlineContentSizesResult)>>>,
pub cached_layout_result: AtomicRefCell<Option<CacheableLayoutResultAndInputs>>, pub cached_layout_result: AtomicRefCell<Option<Box<CacheableLayoutResultAndInputs>>>,
} }
impl LayoutBoxBase { impl LayoutBoxBase {
@ -50,7 +50,8 @@ impl LayoutBoxBase {
layout_box: &impl ComputeInlineContentSizes, layout_box: &impl ComputeInlineContentSizes,
) -> InlineContentSizesResult { ) -> InlineContentSizesResult {
let mut cache = self.cached_inline_content_size.borrow_mut(); let mut cache = self.cached_inline_content_size.borrow_mut();
if let Some((previous_cb_block_size, result)) = *cache { if let Some(cached_inline_content_size) = cache.as_ref() {
let (previous_cb_block_size, result) = **cached_inline_content_size;
if !result.depends_on_block_constraints || if !result.depends_on_block_constraints ||
previous_cb_block_size == constraint_space.block_size previous_cb_block_size == constraint_space.block_size
{ {
@ -60,7 +61,7 @@ impl LayoutBoxBase {
} }
let result = layout_box.compute_inline_content_sizes(layout_context, constraint_space); let result = layout_box.compute_inline_content_sizes(layout_context, constraint_space);
*cache = Some((constraint_space.block_size, result)); *cache = Some(Box::new((constraint_space.block_size, result)));
result result
} }