mirror of
https://github.com/servo/servo.git
synced 2025-06-08 00:23:30 +00:00
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>
This commit is contained in:
parent
bc7fe41a02
commit
1b1a4eca55
3 changed files with 48 additions and 37 deletions
|
@ -979,11 +979,10 @@ where
|
||||||
|
|
||||||
let block_container = builder.finish();
|
let block_container = builder.finish();
|
||||||
self.table_traversal.builder.add_cell(TableSlotCell {
|
self.table_traversal.builder.add_cell(TableSlotCell {
|
||||||
|
base: LayoutBoxBase::new(BaseFragmentInfo::anonymous(), anonymous_info.style),
|
||||||
contents: BlockFormattingContext::from_block_container(block_container),
|
contents: BlockFormattingContext::from_block_container(block_container),
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
rowspan: 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.finish_current_anonymous_cell_if_needed();
|
||||||
self.table_traversal.builder.add_cell(TableSlotCell {
|
self.table_traversal.builder.add_cell(TableSlotCell {
|
||||||
|
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
||||||
contents,
|
contents,
|
||||||
colspan,
|
colspan,
|
||||||
rowspan,
|
rowspan,
|
||||||
style: info.style.clone(),
|
|
||||||
base_fragment_info: info.into(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
||||||
|
|
|
@ -263,6 +263,7 @@ impl<'a> TableLayout<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let padding = cell
|
let padding = cell
|
||||||
|
.base
|
||||||
.style
|
.style
|
||||||
.padding(writing_mode)
|
.padding(writing_mode)
|
||||||
.percentages_relative_to(Au::zero());
|
.percentages_relative_to(Au::zero());
|
||||||
|
@ -272,7 +273,7 @@ impl<'a> TableLayout<'a> {
|
||||||
cell,
|
cell,
|
||||||
TableSlotCoordinates::new(column_index, row_index),
|
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 {
|
let padding_border_sums = LogicalVec2 {
|
||||||
inline: padding.inline_sum() + border.inline_sum(),
|
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) =
|
let (size, min_size, max_size, inline_size_is_auto, percentage_contribution) =
|
||||||
get_outer_sizes_for_measurement(
|
get_outer_sizes_for_measurement(
|
||||||
&cell.style,
|
&cell.base.style,
|
||||||
writing_mode,
|
writing_mode,
|
||||||
&padding_border_sums,
|
&padding_border_sums,
|
||||||
);
|
);
|
||||||
|
@ -293,18 +294,8 @@ impl<'a> TableLayout<'a> {
|
||||||
let inline_measure = if is_in_fixed_mode && row_index > 0 {
|
let inline_measure = if is_in_fixed_mode && row_index > 0 {
|
||||||
CellOrTrackMeasure::zero()
|
CellOrTrackMeasure::zero()
|
||||||
} else {
|
} else {
|
||||||
let mut inline_content_sizes = if is_in_fixed_mode {
|
let mut inline_content_sizes =
|
||||||
ContentSizes::zero()
|
cell.inline_content_sizes(layout_context, is_in_fixed_mode);
|
||||||
} 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
|
|
||||||
};
|
|
||||||
inline_content_sizes.min_content += padding_border_sums.inline;
|
inline_content_sizes.min_content += padding_border_sums.inline;
|
||||||
inline_content_sizes.max_content += padding_border_sums.inline;
|
inline_content_sizes.max_content += padding_border_sums.inline;
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -420,7 +411,7 @@ impl<'a> TableLayout<'a> {
|
||||||
let coords = TableSlotCoordinates::new(column_index, row_index);
|
let coords = TableSlotCoordinates::new(column_index, row_index);
|
||||||
let cell_constrained = match self.table.resolve_first_cell(coords) {
|
let cell_constrained = match self.table.resolve_first_cell(coords) {
|
||||||
Some(cell) if cell.colspan == 1 => {
|
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(),
|
_ => LogicalVec2::default(),
|
||||||
};
|
};
|
||||||
|
@ -1223,11 +1214,13 @@ impl<'a> TableLayout<'a> {
|
||||||
let border: LogicalSides<Au> = self
|
let border: LogicalSides<Au> = self
|
||||||
.get_collapsed_borders_for_cell(cell, coordinates)
|
.get_collapsed_borders_for_cell(cell, coordinates)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
cell.style
|
cell.base
|
||||||
|
.style
|
||||||
.border_width(containing_block_for_table.style.writing_mode)
|
.border_width(containing_block_for_table.style.writing_mode)
|
||||||
});
|
});
|
||||||
|
|
||||||
let padding: LogicalSides<Au> = cell
|
let padding: LogicalSides<Au> = cell
|
||||||
|
.base
|
||||||
.style
|
.style
|
||||||
.padding(containing_block_for_table.style.writing_mode)
|
.padding(containing_block_for_table.style.writing_mode)
|
||||||
.percentages_relative_to(self.basis_for_cell_padding_percentage);
|
.percentages_relative_to(self.basis_for_cell_padding_percentage);
|
||||||
|
@ -1242,7 +1235,7 @@ impl<'a> TableLayout<'a> {
|
||||||
let containing_block_for_children = ContainingBlock {
|
let containing_block_for_children = ContainingBlock {
|
||||||
inline_size: total_cell_width,
|
inline_size: total_cell_width,
|
||||||
block_size: AuOrAuto::Auto,
|
block_size: AuOrAuto::Auto,
|
||||||
style: &cell.style,
|
style: &cell.base.style,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut positioning_context = PositioningContext::new_for_subtree(
|
let mut positioning_context = PositioningContext::new_for_subtree(
|
||||||
|
@ -2247,7 +2240,7 @@ impl<'a> TableLayout<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
apply_border(
|
apply_border(
|
||||||
&cell.style,
|
&cell.base.style,
|
||||||
&(row_index..row_index + cell.rowspan),
|
&(row_index..row_index + cell.rowspan),
|
||||||
&(column_index..column_index + cell.colspan),
|
&(column_index..column_index + cell.colspan),
|
||||||
);
|
);
|
||||||
|
@ -2737,7 +2730,7 @@ impl Table {
|
||||||
|
|
||||||
impl TableSlotCell {
|
impl TableSlotCell {
|
||||||
fn effective_vertical_align(&self) -> VerticalAlignKeyword {
|
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::Top) => VerticalAlignKeyword::Top,
|
||||||
VerticalAlign::Keyword(VerticalAlignKeyword::Bottom) => VerticalAlignKeyword::Bottom,
|
VerticalAlign::Keyword(VerticalAlignKeyword::Bottom) => VerticalAlignKeyword::Bottom,
|
||||||
VerticalAlign::Keyword(VerticalAlignKeyword::Middle) => VerticalAlignKeyword::Middle,
|
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(
|
fn create_fragment(
|
||||||
&self,
|
&self,
|
||||||
mut layout: CellLayout,
|
mut layout: CellLayout,
|
||||||
|
@ -2772,8 +2787,8 @@ impl TableSlotCell {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut base_fragment_info = self.base_fragment_info;
|
let mut base_fragment_info = self.base.base_fragment_info;
|
||||||
if self.style.get_inherited_table().empty_cells == EmptyCells::Hide &&
|
if self.base.style.get_inherited_table().empty_cells == EmptyCells::Hide &&
|
||||||
table_style.get_inherited_table().border_collapse != BorderCollapse::Collapse &&
|
table_style.get_inherited_table().border_collapse != BorderCollapse::Collapse &&
|
||||||
layout.is_empty_for_empty_cells()
|
layout.is_empty_for_empty_cells()
|
||||||
{
|
{
|
||||||
|
@ -2809,7 +2824,7 @@ impl TableSlotCell {
|
||||||
|
|
||||||
BoxFragment::new(
|
BoxFragment::new(
|
||||||
base_fragment_info,
|
base_fragment_info,
|
||||||
self.style.clone(),
|
self.base.style.clone(),
|
||||||
vec![Fragment::Positioning(vertical_align_fragment)],
|
vec![Fragment::Positioning(vertical_align_fragment)],
|
||||||
physical_cell_rect,
|
physical_cell_rect,
|
||||||
layout.padding.to_physical(table_style.writing_mode),
|
layout.padding.to_physical(table_style.writing_mode),
|
||||||
|
|
|
@ -84,6 +84,7 @@ use crate::cell::ArcRefCell;
|
||||||
use crate::flow::BlockContainer;
|
use crate::flow::BlockContainer;
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragment_tree::BaseFragmentInfo;
|
use crate::fragment_tree::BaseFragmentInfo;
|
||||||
|
use crate::layout_box_base::LayoutBoxBase;
|
||||||
|
|
||||||
pub type TableSize = Size2D<usize, UnknownUnit>;
|
pub type TableSize = Size2D<usize, UnknownUnit>;
|
||||||
|
|
||||||
|
@ -189,6 +190,9 @@ pub type TableSlotOffset = Vector2D<usize, UnknownUnit>;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct TableSlotCell {
|
pub struct TableSlotCell {
|
||||||
|
/// The [`LayoutBoxBase`] of this table cell.
|
||||||
|
base: LayoutBoxBase,
|
||||||
|
|
||||||
/// The contents of this cell, with its own layout.
|
/// The contents of this cell, with its own layout.
|
||||||
contents: BlockFormattingContext,
|
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
|
/// 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.
|
/// the remaining rows in the row group.
|
||||||
rowspan: usize,
|
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 {
|
impl TableSlotCell {
|
||||||
pub fn mock_for_testing(id: usize, colspan: usize, rowspan: usize) -> Self {
|
pub fn mock_for_testing(id: usize, colspan: usize, rowspan: usize) -> Self {
|
||||||
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: BlockFormattingContext {
|
||||||
contents: BlockContainer::BlockLevelBoxes(Vec::new()),
|
contents: BlockContainer::BlockLevelBoxes(Vec::new()),
|
||||||
contains_floats: false,
|
contains_floats: false,
|
||||||
},
|
},
|
||||||
colspan,
|
colspan,
|
||||||
rowspan,
|
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.
|
/// Get the node id of this cell's [`BaseFragmentInfo`]. This is used for unit tests.
|
||||||
pub fn node_id(&self) -> usize {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue