diff options
author | Martin Robinson <mrobinson@igalia.com> | 2024-12-08 09:54:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-08 08:54:40 +0000 |
commit | 1b1a4eca55e37b794a432836c378e3ba858e976c (patch) | |
tree | 428d056adb38dc6bd74ac4874ed9e29c69952a1d | |
parent | bc7fe41a02b044b52a54c7347f347557a4bd0e8d (diff) | |
download | servo-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.rs | 6 | ||||
-rw-r--r-- | components/layout_2020/table/layout.rs | 59 | ||||
-rw-r--r-- | components/layout_2020/table/mod.rs | 20 |
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) } } |