aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-12-08 09:54:40 +0100
committerGitHub <noreply@github.com>2024-12-08 08:54:40 +0000
commit1b1a4eca55e37b794a432836c378e3ba858e976c (patch)
tree428d056adb38dc6bd74ac4874ed9e29c69952a1d
parentbc7fe41a02b044b52a54c7347f347557a4bd0e8d (diff)
downloadservo-1b1a4eca55e37b794a432836c378e3ba858e976c.tar.gz
servo-1b1a4eca55e37b794a432836c378e3ba858e976c.zip
layout: Add `LayoutBox` to `TableSlotCell` (#34513)
This allows cells to cache their inline content size and will eventually allow them to participate in incremental layout. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
-rw-r--r--components/layout_2020/table/construct.rs6
-rw-r--r--components/layout_2020/table/layout.rs59
-rw-r--r--components/layout_2020/table/mod.rs20
3 files changed, 48 insertions, 37 deletions
diff --git a/components/layout_2020/table/construct.rs b/components/layout_2020/table/construct.rs
index 8eb754d8df5..8f9b5a484d8 100644
--- a/components/layout_2020/table/construct.rs
+++ b/components/layout_2020/table/construct.rs
@@ -979,11 +979,10 @@ where
let block_container = builder.finish();
self.table_traversal.builder.add_cell(TableSlotCell {
+ base: LayoutBoxBase::new(BaseFragmentInfo::anonymous(), anonymous_info.style),
contents: BlockFormattingContext::from_block_container(block_container),
colspan: 1,
rowspan: 1,
- style: anonymous_info.style,
- base_fragment_info: BaseFragmentInfo::anonymous(),
});
}
}
@@ -1041,11 +1040,10 @@ where
self.finish_current_anonymous_cell_if_needed();
self.table_traversal.builder.add_cell(TableSlotCell {
+ base: LayoutBoxBase::new(info.into(), info.style.clone()),
contents,
colspan,
rowspan,
- style: info.style.clone(),
- base_fragment_info: info.into(),
});
// We are doing this until we have actually set a Box for this `BoxSlot`.
diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs
index ea7714207dd..1434cfbeaad 100644
--- a/components/layout_2020/table/layout.rs
+++ b/components/layout_2020/table/layout.rs
@@ -263,6 +263,7 @@ impl<'a> TableLayout<'a> {
};
let padding = cell
+ .base
.style
.padding(writing_mode)
.percentages_relative_to(Au::zero());
@@ -272,7 +273,7 @@ impl<'a> TableLayout<'a> {
cell,
TableSlotCoordinates::new(column_index, row_index),
)
- .unwrap_or_else(|| cell.style.border_width(writing_mode));
+ .unwrap_or_else(|| cell.base.style.border_width(writing_mode));
let padding_border_sums = LogicalVec2 {
inline: padding.inline_sum() + border.inline_sum(),
@@ -281,7 +282,7 @@ impl<'a> TableLayout<'a> {
let (size, min_size, max_size, inline_size_is_auto, percentage_contribution) =
get_outer_sizes_for_measurement(
- &cell.style,
+ &cell.base.style,
writing_mode,
&padding_border_sums,
);
@@ -293,18 +294,8 @@ impl<'a> TableLayout<'a> {
let inline_measure = if is_in_fixed_mode && row_index > 0 {
CellOrTrackMeasure::zero()
} else {
- let mut inline_content_sizes = if is_in_fixed_mode {
- ContentSizes::zero()
- } else {
- let constraint_space = ConstraintSpace::new_for_style_and_ratio(
- &cell.style,
- None, /* TODO: support preferred aspect ratios on non-replaced boxes */
- );
- cell.contents
- .contents
- .inline_content_sizes(layout_context, &constraint_space)
- .sizes
- };
+ let mut inline_content_sizes =
+ cell.inline_content_sizes(layout_context, is_in_fixed_mode);
inline_content_sizes.min_content += padding_border_sums.inline;
inline_content_sizes.max_content += padding_border_sums.inline;
assert!(
@@ -420,7 +411,7 @@ impl<'a> TableLayout<'a> {
let coords = TableSlotCoordinates::new(column_index, row_index);
let cell_constrained = match self.table.resolve_first_cell(coords) {
Some(cell) if cell.colspan == 1 => {
- cell.style.box_size(writing_mode).map(is_length)
+ cell.base.style.box_size(writing_mode).map(is_length)
},
_ => LogicalVec2::default(),
};
@@ -1223,11 +1214,13 @@ impl<'a> TableLayout<'a> {
let border: LogicalSides<Au> = self
.get_collapsed_borders_for_cell(cell, coordinates)
.unwrap_or_else(|| {
- cell.style
+ cell.base
+ .style
.border_width(containing_block_for_table.style.writing_mode)
});
let padding: LogicalSides<Au> = cell
+ .base
.style
.padding(containing_block_for_table.style.writing_mode)
.percentages_relative_to(self.basis_for_cell_padding_percentage);
@@ -1242,7 +1235,7 @@ impl<'a> TableLayout<'a> {
let containing_block_for_children = ContainingBlock {
inline_size: total_cell_width,
block_size: AuOrAuto::Auto,
- style: &cell.style,
+ style: &cell.base.style,
};
let mut positioning_context = PositioningContext::new_for_subtree(
@@ -2247,7 +2240,7 @@ impl<'a> TableLayout<'a> {
};
apply_border(
- &cell.style,
+ &cell.base.style,
&(row_index..row_index + cell.rowspan),
&(column_index..column_index + cell.colspan),
);
@@ -2737,7 +2730,7 @@ impl Table {
impl TableSlotCell {
fn effective_vertical_align(&self) -> VerticalAlignKeyword {
- match self.style.clone_vertical_align() {
+ match self.base.style.clone_vertical_align() {
VerticalAlign::Keyword(VerticalAlignKeyword::Top) => VerticalAlignKeyword::Top,
VerticalAlign::Keyword(VerticalAlignKeyword::Bottom) => VerticalAlignKeyword::Bottom,
VerticalAlign::Keyword(VerticalAlignKeyword::Middle) => VerticalAlignKeyword::Middle,
@@ -2745,6 +2738,28 @@ impl TableSlotCell {
}
}
+ fn inline_content_sizes(
+ &self,
+ layout_context: &LayoutContext,
+ is_in_fixed_mode: bool,
+ ) -> ContentSizes {
+ if is_in_fixed_mode {
+ return ContentSizes::zero();
+ };
+
+ let constraint_space = ConstraintSpace::new_for_style_and_ratio(
+ &self.base.style,
+ None, /* TODO: support preferred aspect ratios on non-replaced boxes */
+ );
+ self.base
+ .inline_content_sizes(&constraint_space, || {
+ self.contents
+ .contents
+ .inline_content_sizes(layout_context, &constraint_space)
+ })
+ .sizes
+ }
+
fn create_fragment(
&self,
mut layout: CellLayout,
@@ -2772,8 +2787,8 @@ impl TableSlotCell {
},
};
- let mut base_fragment_info = self.base_fragment_info;
- if self.style.get_inherited_table().empty_cells == EmptyCells::Hide &&
+ let mut base_fragment_info = self.base.base_fragment_info;
+ if self.base.style.get_inherited_table().empty_cells == EmptyCells::Hide &&
table_style.get_inherited_table().border_collapse != BorderCollapse::Collapse &&
layout.is_empty_for_empty_cells()
{
@@ -2809,7 +2824,7 @@ impl TableSlotCell {
BoxFragment::new(
base_fragment_info,
- self.style.clone(),
+ self.base.style.clone(),
vec![Fragment::Positioning(vertical_align_fragment)],
physical_cell_rect,
layout.padding.to_physical(table_style.writing_mode),
diff --git a/components/layout_2020/table/mod.rs b/components/layout_2020/table/mod.rs
index 5a2c335875d..50e9d5d59eb 100644
--- a/components/layout_2020/table/mod.rs
+++ b/components/layout_2020/table/mod.rs
@@ -84,6 +84,7 @@ use crate::cell::ArcRefCell;
use crate::flow::BlockContainer;
use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::BaseFragmentInfo;
+use crate::layout_box_base::LayoutBoxBase;
pub type TableSize = Size2D<usize, UnknownUnit>;
@@ -189,6 +190,9 @@ pub type TableSlotOffset = Vector2D<usize, UnknownUnit>;
#[derive(Debug, Serialize)]
pub struct TableSlotCell {
+ /// The [`LayoutBoxBase`] of this table cell.
+ base: LayoutBoxBase,
+
/// The contents of this cell, with its own layout.
contents: BlockFormattingContext,
@@ -198,33 +202,27 @@ pub struct TableSlotCell {
/// Number of rows that the cell is to span. Zero means that the cell is to span all
/// the remaining rows in the row group.
rowspan: usize,
-
- /// The style of this table cell.
- #[serde(skip_serializing)]
- style: Arc<ComputedValues>,
-
- /// The [`BaseFragmentInfo`] of this cell.
- base_fragment_info: BaseFragmentInfo,
}
impl TableSlotCell {
pub fn mock_for_testing(id: usize, colspan: usize, rowspan: usize) -> Self {
Self {
+ base: LayoutBoxBase::new(
+ BaseFragmentInfo::new_for_node(OpaqueNode(id)),
+ ComputedValues::initial_values_with_font_override(Font::initial_values()).to_arc(),
+ ),
contents: BlockFormattingContext {
contents: BlockContainer::BlockLevelBoxes(Vec::new()),
contains_floats: false,
},
colspan,
rowspan,
- style: ComputedValues::initial_values_with_font_override(Font::initial_values())
- .to_arc(),
- base_fragment_info: BaseFragmentInfo::new_for_node(OpaqueNode(id)),
}
}
/// Get the node id of this cell's [`BaseFragmentInfo`]. This is used for unit tests.
pub fn node_id(&self) -> usize {
- self.base_fragment_info.tag.map_or(0, |tag| tag.node.0)
+ self.base.base_fragment_info.tag.map_or(0, |tag| tag.node.0)
}
}