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> {
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 inline_level_box = ArcRefCell::new(InlineItem::StartInlineBox(inline_box));
@ -177,7 +177,9 @@ impl InlineFormattingContextBuilder {
let inline_level_box = self.inline_boxes.get(&identifier);
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
}

View file

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

View file

@ -326,7 +326,7 @@ impl LineItemLayout<'_, '_> {
let inline_box = self.layout.ifc.inline_boxes.get(identifier);
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 block_start_offset =
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;
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)
}
@ -418,7 +418,7 @@ impl LineItemLayout<'_, '_> {
// Relative adjustment should not affect the rest of line layout, so we can
// 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 {
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.
let physical_content_rect = content_rect.as_physical(Some(self.layout.containing_block));
let mut fragment = BoxFragment::new(
inline_box.base_fragment_info,
inline_box.base.base_fragment_info,
style.clone(),
fragments,
physical_content_rect,

View file

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

View file

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

View file

@ -27,8 +27,8 @@ pub(crate) struct LayoutBoxBase {
pub base_fragment_info: BaseFragmentInfo,
pub style: Arc<ComputedValues>,
pub cached_inline_content_size:
AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>,
pub cached_layout_result: AtomicRefCell<Option<CacheableLayoutResultAndInputs>>,
AtomicRefCell<Option<Box<(SizeConstraint, InlineContentSizesResult)>>>,
pub cached_layout_result: AtomicRefCell<Option<Box<CacheableLayoutResultAndInputs>>>,
}
impl LayoutBoxBase {
@ -50,7 +50,8 @@ impl LayoutBoxBase {
layout_box: &impl ComputeInlineContentSizes,
) -> InlineContentSizesResult {
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 ||
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);
*cache = Some((constraint_space.block_size, result));
*cache = Some(Box::new((constraint_space.block_size, result)));
result
}