Commit bfded3cd authored by Ian Kilpatrick's avatar Ian Kilpatrick Committed by Commit Bot

[TableNG] Fix basic cache-misses.

This patch unifies creates the constraint-space for table-cells. Before
we had two different code-paths leading to subtle differences in
construction causing various types of cache misses.

This unifies the code-paths ensuring that they can remain as similar as
possible.

Bug: 958381
Change-Id: I59d7252ba3db52c36b2118d9695cea106326a1e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2498836
Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821770}
parent 0d944e3e
...@@ -111,7 +111,7 @@ NGConstraintSpace NGConstraintSpace::CreateFromLayoutObject( ...@@ -111,7 +111,7 @@ NGConstraintSpace NGConstraintSpace::CreateFromLayoutObject(
builder.SetHideTableCellIfEmpty( builder.SetHideTableCellIfEmpty(
cell_style.EmptyCells() == EEmptyCells::kHide && cell_style.EmptyCells() == EEmptyCells::kHide &&
table_style.BorderCollapse() == EBorderCollapse::kSeparate); table_style.BorderCollapse() == EBorderCollapse::kSeparate);
builder.SetHasTableCellCollapsedBorder( builder.SetIsTableCellWithCollapsedBorders(
cell_block.Parent()->Parent()->Parent()->StyleRef().BorderCollapse() == cell_block.Parent()->Parent()->Parent()->StyleRef().BorderCollapse() ==
EBorderCollapse::kCollapse); EBorderCollapse::kCollapse);
} }
......
...@@ -977,11 +977,11 @@ class CORE_EXPORT NGConstraintSpace final { ...@@ -977,11 +977,11 @@ class CORE_EXPORT NGConstraintSpace final {
bool IsTableCellWithCollapsedBorders() const { bool IsTableCellWithCollapsedBorders() const {
return data_union_type == kTableCellData && return data_union_type == kTableCellData &&
table_cell_data_.has_collapsed_border; table_cell_data_.has_collapsed_borders;
} }
void SetIsTableCellWithCollapsedBorders(bool has_collapsed_border) { void SetIsTableCellWithCollapsedBorders(bool has_collapsed_borders) {
EnsureTableCellData()->has_collapsed_border = has_collapsed_border; EnsureTableCellData()->has_collapsed_borders = has_collapsed_borders;
} }
void SetTableRowData( void SetTableRowData(
...@@ -1095,25 +1095,24 @@ class CORE_EXPORT NGConstraintSpace final { ...@@ -1095,25 +1095,24 @@ class CORE_EXPORT NGConstraintSpace final {
struct TableCellData { struct TableCellData {
bool MaySkipLayout(const TableCellData& other) const { bool MaySkipLayout(const TableCellData& other) const {
// NOTE: We don't compare |table_cell_alignment_baseline| as it is
// still possible to hit the cache if this differs.
return table_cell_borders == other.table_cell_borders && return table_cell_borders == other.table_cell_borders &&
table_cell_intrinsic_padding_block_start == table_cell_intrinsic_padding_block_start ==
other.table_cell_intrinsic_padding_block_start && other.table_cell_intrinsic_padding_block_start &&
table_cell_intrinsic_padding_block_end == table_cell_intrinsic_padding_block_end ==
other.table_cell_intrinsic_padding_block_end && other.table_cell_intrinsic_padding_block_end &&
table_cell_alignment_baseline ==
other.table_cell_alignment_baseline &&
table_cell_column_index == other.table_cell_column_index && table_cell_column_index == other.table_cell_column_index &&
is_hidden_for_paint == other.is_hidden_for_paint && is_hidden_for_paint == other.is_hidden_for_paint &&
has_collapsed_border == other.has_collapsed_border; has_collapsed_borders == other.has_collapsed_borders;
} }
bool IsInitialForMaySkipLayout() const { bool IsInitialForMaySkipLayout() const {
return table_cell_borders == NGBoxStrut() && return table_cell_borders == NGBoxStrut() &&
table_cell_intrinsic_padding_block_start == LayoutUnit() && table_cell_intrinsic_padding_block_start == LayoutUnit() &&
table_cell_intrinsic_padding_block_end == LayoutUnit() && table_cell_intrinsic_padding_block_end == LayoutUnit() &&
table_cell_column_index == kNotFound && table_cell_column_index == kNotFound && !is_hidden_for_paint &&
table_cell_alignment_baseline == base::nullopt && !has_collapsed_borders;
!is_hidden_for_paint && !has_collapsed_border;
} }
NGBoxStrut table_cell_borders; NGBoxStrut table_cell_borders;
...@@ -1122,13 +1121,13 @@ class CORE_EXPORT NGConstraintSpace final { ...@@ -1122,13 +1121,13 @@ class CORE_EXPORT NGConstraintSpace final {
wtf_size_t table_cell_column_index = kNotFound; wtf_size_t table_cell_column_index = kNotFound;
base::Optional<LayoutUnit> table_cell_alignment_baseline; base::Optional<LayoutUnit> table_cell_alignment_baseline;
bool is_hidden_for_paint = false; bool is_hidden_for_paint = false;
bool has_collapsed_border = false; bool has_collapsed_borders = false;
}; };
struct TableRowData { struct TableRowData {
bool MaySkipLayout(const TableRowData& other) const { bool MaySkipLayout(const TableRowData& other) const {
return table_data->EqualTableSpecificData(other.table_data.get()) && return table_data->IsTableSpecificDataEqual(*other.table_data) &&
table_data->MaySkipRowLayout(other.table_data.get(), row_index); table_data->MaySkipRowLayout(*other.table_data, row_index);
} }
bool IsInitialForMaySkipLayout() const { bool IsInitialForMaySkipLayout() const {
return !table_data && row_index == kNotFound; return !table_data && row_index == kNotFound;
...@@ -1140,8 +1139,8 @@ class CORE_EXPORT NGConstraintSpace final { ...@@ -1140,8 +1139,8 @@ class CORE_EXPORT NGConstraintSpace final {
struct TableSectionData { struct TableSectionData {
bool MaySkipLayout(const TableSectionData& other) const { bool MaySkipLayout(const TableSectionData& other) const {
return table_data->EqualTableSpecificData(other.table_data.get()) && return table_data->IsTableSpecificDataEqual(*other.table_data) &&
table_data->MaySkipSectionLayout(other.table_data.get(), table_data->MaySkipSectionLayout(*other.table_data,
section_index); section_index);
} }
bool IsInitialForMaySkipLayout() const { bool IsInitialForMaySkipLayout() const {
......
...@@ -328,16 +328,21 @@ class CORE_EXPORT NGConstraintSpaceBuilder final { ...@@ -328,16 +328,21 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
DCHECK(!is_table_cell_hidden_for_paint_set_); DCHECK(!is_table_cell_hidden_for_paint_set_);
is_table_cell_hidden_for_paint_set_ = true; is_table_cell_hidden_for_paint_set_ = true;
#endif #endif
space_.EnsureRareData()->SetIsTableCellHiddenForPaint(is_hidden_for_paint); if (is_hidden_for_paint) {
space_.EnsureRareData()->SetIsTableCellHiddenForPaint(
is_hidden_for_paint);
}
} }
void SetHasTableCellCollapsedBorder(bool is_collapsed_border) { void SetIsTableCellWithCollapsedBorders(bool has_collapsed_borders) {
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
DCHECK(!is_table_cell_collapsed_border_set_); DCHECK(!is_table_cell_with_collapsed_borders_set_);
is_table_cell_collapsed_border_set_ = true; is_table_cell_with_collapsed_borders_set_ = true;
#endif #endif
space_.EnsureRareData()->SetIsTableCellWithCollapsedBorders( if (has_collapsed_borders) {
is_collapsed_border); space_.EnsureRareData()->SetIsTableCellWithCollapsedBorders(
has_collapsed_borders);
}
} }
void SetTableCellChildLayoutMode( void SetTableCellChildLayoutMode(
...@@ -463,7 +468,7 @@ class CORE_EXPORT NGConstraintSpaceBuilder final { ...@@ -463,7 +468,7 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
bool is_table_cell_alignment_baseline_set_ = false; bool is_table_cell_alignment_baseline_set_ = false;
bool is_table_cell_column_index_set_ = false; bool is_table_cell_column_index_set_ = false;
bool is_table_cell_hidden_for_paint_set_ = false; bool is_table_cell_hidden_for_paint_set_ = false;
bool is_table_cell_collapsed_border_set_ = false; bool is_table_cell_with_collapsed_borders_set_ = false;
bool is_custom_layout_data_set_ = false; bool is_custom_layout_data_set_ = false;
bool is_lines_until_clamp_set_ = false; bool is_lines_until_clamp_set_ = false;
bool is_table_row_data_set_ = false; bool is_table_row_data_set_ = false;
......
...@@ -1699,5 +1699,39 @@ TEST_F(NGLayoutResultCachingTest, HitOrthogonalRoot) { ...@@ -1699,5 +1699,39 @@ TEST_F(NGLayoutResultCachingTest, HitOrthogonalRoot) {
EXPECT_NE(result.get(), nullptr); EXPECT_NE(result.get(), nullptr);
} }
TEST_F(NGLayoutResultCachingTest, SimpleTable) {
ScopedLayoutNGTableForTest table_ng(true);
SetBodyInnerHTML(R"HTML(
<table>
<td id="target1">abc</td>
<td id="target2">abc</td>
</table>
)HTML");
auto* target1 = To<LayoutBlock>(GetLayoutObjectByElementId("target1"));
auto* target2 = To<LayoutBlock>(GetLayoutObjectByElementId("target2"));
// Both "target1", and "target1" should have only had one "measure" pass
// performed.
scoped_refptr<const NGLayoutResult> result1 =
target1->GetCachedLayoutResult();
scoped_refptr<const NGLayoutResult> measure1 =
target1->GetCachedMeasureResult();
EXPECT_EQ(result1->GetConstraintSpaceForCaching().CacheSlot(),
NGCacheSlot::kMeasure);
EXPECT_NE(result1.get(), nullptr);
EXPECT_EQ(result1.get(), measure1.get());
scoped_refptr<const NGLayoutResult> result2 =
target2->GetCachedLayoutResult();
scoped_refptr<const NGLayoutResult> measure2 =
target2->GetCachedMeasureResult();
EXPECT_EQ(result2->GetConstraintSpaceForCaching().CacheSlot(),
NGCacheSlot::kMeasure);
EXPECT_NE(result2.get(), nullptr);
EXPECT_EQ(result2.get(), measure2.get());
}
} // namespace } // namespace
} // namespace blink } // namespace blink
...@@ -104,36 +104,36 @@ class NGTableConstraintSpaceData ...@@ -104,36 +104,36 @@ class NGTableConstraintSpaceData
bool is_constrained; bool is_constrained;
}; };
bool EqualTableSpecificData(const NGTableConstraintSpaceData* other) const { bool IsTableSpecificDataEqual(const NGTableConstraintSpaceData& other) const {
return table_inline_size == other->table_inline_size && return table_inline_size == other.table_inline_size &&
table_writing_direction == other->table_writing_direction && table_writing_direction == other.table_writing_direction &&
table_border_spacing == other->table_border_spacing && table_border_spacing == other.table_border_spacing &&
treat_table_block_size_as_constrained == is_table_block_size_specified ==
other->treat_table_block_size_as_constrained && other.is_table_block_size_specified &&
hide_table_cell_if_empty == other->hide_table_cell_if_empty && hide_table_cell_if_empty == other.hide_table_cell_if_empty &&
column_locations == other->column_locations; column_locations == other.column_locations;
} }
bool MaySkipRowLayout(const NGTableConstraintSpaceData* other, bool MaySkipRowLayout(const NGTableConstraintSpaceData& other,
wtf_size_t row_index) const { wtf_size_t row_index) const {
if (other->rows.size() <= row_index) if (other.rows.size() <= row_index)
return false; return false;
if (rows[row_index] != other->rows[row_index]) if (rows[row_index] != other.rows[row_index])
return false; return false;
DCHECK_LT(row_index, rows.size()); DCHECK_LT(row_index, rows.size());
wtf_size_t end_index = wtf_size_t end_index =
rows[row_index].start_cell_index + rows[row_index].cell_count; rows[row_index].start_cell_index + rows[row_index].cell_count;
for (wtf_size_t cell_index = rows[row_index].start_cell_index; for (wtf_size_t cell_index = rows[row_index].start_cell_index;
cell_index < end_index; ++cell_index) { cell_index < end_index; ++cell_index) {
if (cells[cell_index] != other->cells[cell_index]) if (cells[cell_index] != other.cells[cell_index])
return false; return false;
} }
return true; return true;
} }
bool MaySkipSectionLayout(const NGTableConstraintSpaceData* other, bool MaySkipSectionLayout(const NGTableConstraintSpaceData& other,
wtf_size_t section_index) const { wtf_size_t section_index) const {
if (other->sections.size() <= section_index) if (other.sections.size() <= section_index)
return false; return false;
DCHECK_LT(section_index, sections.size()); DCHECK_LT(section_index, sections.size());
wtf_size_t end_index = sections[section_index].start_row_index + wtf_size_t end_index = sections[section_index].start_row_index +
...@@ -154,7 +154,9 @@ class NGTableConstraintSpaceData ...@@ -154,7 +154,9 @@ class NGTableConstraintSpaceData
WritingDirectionMode table_writing_direction = WritingDirectionMode table_writing_direction =
WritingDirectionMode(WritingMode::kHorizontalTb, TextDirection::kLtr); WritingDirectionMode(WritingMode::kHorizontalTb, TextDirection::kLtr);
LogicalSize table_border_spacing; LogicalSize table_border_spacing;
bool treat_table_block_size_as_constrained;
// If the block-size of the table is specified (not 'auto').
bool is_table_block_size_specified;
bool hide_table_cell_if_empty; // currently on regular constraint space. bool hide_table_cell_if_empty; // currently on regular constraint space.
bool has_collapsed_borders; bool has_collapsed_borders;
}; };
......
...@@ -124,7 +124,7 @@ LayoutUnit ComputeEmptyTableInlineSize( ...@@ -124,7 +124,7 @@ LayoutUnit ComputeEmptyTableInlineSize(
const LayoutUnit undistributable_space, const LayoutUnit undistributable_space,
const NGTableTypes::Caption& caption_constraint, const NGTableTypes::Caption& caption_constraint,
const NGBoxStrut& table_border_padding, const NGBoxStrut& table_border_padding,
const bool is_collapsed) { const bool has_collapsed_borders) {
// If table has a css inline size, use that. // If table has a css inline size, use that.
if (space.IsFixedInlineSize() || !table_style.LogicalWidth().IsAuto() || if (space.IsFixedInlineSize() || !table_style.LogicalWidth().IsAuto() ||
!table_style.LogicalMinWidth().IsAuto()) { !table_style.LogicalMinWidth().IsAuto()) {
...@@ -136,7 +136,7 @@ LayoutUnit ComputeEmptyTableInlineSize( ...@@ -136,7 +136,7 @@ LayoutUnit ComputeEmptyTableInlineSize(
table_border_padding.InlineSum()); table_border_padding.InlineSum());
} }
// Table is defined by its border/padding. // Table is defined by its border/padding.
if (is_collapsed) { if (has_collapsed_borders) {
return LayoutUnit(); return LayoutUnit();
} }
return assignable_table_inline_size + table_border_padding.InlineSum(); return assignable_table_inline_size + table_border_padding.InlineSum();
...@@ -150,8 +150,7 @@ LayoutUnit ComputeAssignableTableInlineSize( ...@@ -150,8 +150,7 @@ LayoutUnit ComputeAssignableTableInlineSize(
const NGTableTypes::Caption& caption_constraint, const NGTableTypes::Caption& caption_constraint,
const LayoutUnit undistributable_space, const LayoutUnit undistributable_space,
const NGBoxStrut& table_border_padding, const NGBoxStrut& table_border_padding,
const bool is_fixed_layout, const bool is_fixed_layout) {
const bool is_collapsed) {
if (space.IsFixedInlineSize()) { if (space.IsFixedInlineSize()) {
return (space.AvailableSize().inline_size - undistributable_space) return (space.AvailableSize().inline_size - undistributable_space)
.ClampNegativeToZero(); .ClampNegativeToZero();
...@@ -243,7 +242,7 @@ scoped_refptr<NGTableConstraintSpaceData> CreateConstraintSpaceData( ...@@ -243,7 +242,7 @@ scoped_refptr<NGTableConstraintSpaceData> CreateConstraintSpaceData(
data->table_inline_size = table_inline_size; data->table_inline_size = table_inline_size;
data->table_writing_direction = style.GetWritingDirection(); data->table_writing_direction = style.GetWritingDirection();
data->table_border_spacing = border_spacing; data->table_border_spacing = border_spacing;
data->treat_table_block_size_as_constrained = !style.LogicalHeight().IsAuto(); data->is_table_block_size_specified = !style.LogicalHeight().IsAuto();
data->hide_table_cell_if_empty = data->hide_table_cell_if_empty =
style.EmptyCells() == EEmptyCells::kHide && style.EmptyCells() == EEmptyCells::kHide &&
style.BorderCollapse() == EBorderCollapse::kSeparate; style.BorderCollapse() == EBorderCollapse::kSeparate;
...@@ -434,8 +433,7 @@ LayoutUnit NGTableLayoutAlgorithm::ComputeTableInlineSize( ...@@ -434,8 +433,7 @@ LayoutUnit NGTableLayoutAlgorithm::ComputeTableInlineSize(
const LayoutUnit assignable_table_inline_size = const LayoutUnit assignable_table_inline_size =
ComputeAssignableTableInlineSize( ComputeAssignableTableInlineSize(
table, space, *column_constraints, caption_constraint, table, space, *column_constraints, caption_constraint,
undistributable_space, table_border_padding, is_fixed_layout, undistributable_space, table_border_padding, is_fixed_layout);
table_borders->IsCollapsed());
if (column_constraints->data.IsEmpty()) { if (column_constraints->data.IsEmpty()) {
return ComputeEmptyTableInlineSize( return ComputeEmptyTableInlineSize(
space, table.Style(), assignable_table_inline_size, space, table.Style(), assignable_table_inline_size,
...@@ -499,8 +497,7 @@ scoped_refptr<const NGLayoutResult> NGTableLayoutAlgorithm::Layout() { ...@@ -499,8 +497,7 @@ scoped_refptr<const NGLayoutResult> NGTableLayoutAlgorithm::Layout() {
const LayoutUnit assignable_table_inline_size = const LayoutUnit assignable_table_inline_size =
ComputeAssignableTableInlineSize( ComputeAssignableTableInlineSize(
Node(), ConstraintSpace(), *column_constraints, caption_constraint, Node(), ConstraintSpace(), *column_constraints, caption_constraint,
undistributable_space, border_padding, is_fixed_layout, undistributable_space, border_padding, is_fixed_layout);
table_borders->IsCollapsed());
// Distribute assignable table width. // Distribute assignable table width.
const Vector<LayoutUnit> column_sizes = const Vector<LayoutUnit> column_sizes =
...@@ -673,13 +670,12 @@ void NGTableLayoutAlgorithm::ComputeRows( ...@@ -673,13 +670,12 @@ void NGTableLayoutAlgorithm::ComputeRows(
ConstraintSpace(), Style(), table_border_padding, kIndefiniteSize, ConstraintSpace(), Style(), table_border_padding, kIndefiniteSize,
table_grid_inline_size); table_grid_inline_size);
const bool is_table_block_size_specified = !Style().LogicalHeight().IsAuto();
LayoutUnit total_table_block_size; LayoutUnit total_table_block_size;
wtf_size_t section_index = 0; wtf_size_t section_index = 0;
for (const NGBlockNode& section : grouped_children) { for (const NGBlockNode& section : grouped_children) {
NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes( NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes(
section, table_grid_inline_size, section, table_grid_inline_size, is_table_block_size_specified,
/* is_restricted_block_size_table */ css_table_block_size !=
kIndefiniteSize,
column_locations, table_borders, border_spacing.block_size, column_locations, table_borders, border_spacing.block_size,
section_index++, sections, rows, cell_block_constraints); section_index++, sections, rows, cell_block_constraints);
total_table_block_size += sections->back().block_size; total_table_block_size += sections->back().block_size;
......
...@@ -103,7 +103,7 @@ NGTableTypes::CellInlineConstraint NGTableTypes::CreateCellInlineConstraint( ...@@ -103,7 +103,7 @@ NGTableTypes::CellInlineConstraint NGTableTypes::CreateCellInlineConstraint(
bool is_fixed_layout, bool is_fixed_layout,
const NGBoxStrut& cell_border, const NGBoxStrut& cell_border,
const NGBoxStrut& cell_padding, const NGBoxStrut& cell_padding,
bool is_collapsed) { bool has_collapsed_borders) {
base::Optional<LayoutUnit> css_inline_size; base::Optional<LayoutUnit> css_inline_size;
base::Optional<LayoutUnit> css_min_inline_size; base::Optional<LayoutUnit> css_min_inline_size;
base::Optional<LayoutUnit> css_max_inline_size; base::Optional<LayoutUnit> css_max_inline_size;
...@@ -120,7 +120,7 @@ NGTableTypes::CellInlineConstraint NGTableTypes::CreateCellInlineConstraint( ...@@ -120,7 +120,7 @@ NGTableTypes::CellInlineConstraint NGTableTypes::CreateCellInlineConstraint(
MinMaxSizesInput input(kIndefiniteSize, MinMaxSizesType::kIntrinsic); MinMaxSizesInput input(kIndefiniteSize, MinMaxSizesType::kIntrinsic);
MinMaxSizesResult min_max_size; MinMaxSizesResult min_max_size;
bool need_constraint_space = is_collapsed || !is_parallel; bool need_constraint_space = has_collapsed_borders || !is_parallel;
if (need_constraint_space) { if (need_constraint_space) {
NGConstraintSpaceBuilder builder(table_writing_mode, NGConstraintSpaceBuilder builder(table_writing_mode,
node.Style().GetWritingMode(), node.Style().GetWritingMode(),
......
...@@ -188,7 +188,7 @@ class CORE_EXPORT NGTableTypes { ...@@ -188,7 +188,7 @@ class CORE_EXPORT NGTableTypes {
bool is_fixed_layout, bool is_fixed_layout,
const NGBoxStrut& cell_border, const NGBoxStrut& cell_border,
const NGBoxStrut& cell_padding, const NGBoxStrut& cell_padding,
bool is_collapsed); bool has_collapsed_borders);
static Section CreateSection(const NGLayoutInputNode&, static Section CreateSection(const NGLayoutInputNode&,
wtf_size_t start_row, wtf_size_t start_row,
......
...@@ -72,7 +72,7 @@ void ApplyCellConstraintsToColumnConstraints( ...@@ -72,7 +72,7 @@ void ApplyCellConstraintsToColumnConstraints(
NGTableTypes::Row ComputeMinimumRowBlockSize( NGTableTypes::Row ComputeMinimumRowBlockSize(
const NGBlockNode& row, const NGBlockNode& row,
const LayoutUnit cell_percentage_inline_size, const LayoutUnit cell_percentage_inline_size,
const bool is_restricted_block_size_table, const bool is_table_block_size_specified,
const NGTableTypes::ColumnLocations& column_locations, const NGTableTypes::ColumnLocations& column_locations,
const NGTableBorders& table_borders, const NGTableBorders& table_borders,
wtf_size_t row_index, wtf_size_t row_index,
...@@ -83,51 +83,35 @@ NGTableTypes::Row ComputeMinimumRowBlockSize( ...@@ -83,51 +83,35 @@ NGTableTypes::Row ComputeMinimumRowBlockSize(
NGColspanCellTabulator* colspan_cell_tabulator) { NGColspanCellTabulator* colspan_cell_tabulator) {
const WritingDirectionMode table_writing_direction = const WritingDirectionMode table_writing_direction =
row.Style().GetWritingDirection(); row.Style().GetWritingDirection();
const bool has_collapsed_borders = table_borders.IsCollapsed();
auto CreateCellConstraintSpace = [&column_locations, &table_writing_direction, auto CreateCellConstraintSpace = [&column_locations, &table_writing_direction,
&is_restricted_block_size_table, &is_table_block_size_specified,
&has_collapsed_borders,
&cell_percentage_inline_size]( &cell_percentage_inline_size](
const NGBlockNode& cell, const NGBlockNode& cell,
wtf_size_t start_column_index, wtf_size_t start_column_index,
const NGBoxStrut& cell_borders) { const NGBoxStrut& cell_borders) {
wtf_size_t start_column = start_column_index; const wtf_size_t start_column = start_column_index;
wtf_size_t end_column = std::min(start_column + cell.TableCellColspan() - 1, const wtf_size_t end_column =
column_locations.size() - 1); std::min(start_column + cell.TableCellColspan() - 1,
LayoutUnit cell_inline_size = column_locations[end_column].offset + column_locations.size() - 1);
column_locations[end_column].size - const LayoutUnit cell_inline_size = column_locations[end_column].offset +
column_locations[start_column].offset; column_locations[end_column].size -
// TODO(crbug.com/736072): Support orthogonal table cells. column_locations[start_column].offset;
// See http://wpt.live/css/css-writing-modes/table-cell-001.html
NGConstraintSpaceBuilder builder(table_writing_direction.GetWritingMode(), // Typically we want these values to match the "layout" pass as close as
cell.Style().GetWritingMode(), // possible. The one exception is "is_hidden_for_paint". This is set to
/* is_new_fc */ true); // true if a cell should be hidden within a collapsed column. If this is
builder.SetTextDirection(cell.Style().Direction()); // the case, the size is almost certainly different causing a second layout.
builder.SetTableCellBorders(cell_borders); return NGTableAlgorithmUtils::CreateTableCellConstraintSpace(
if (!IsParallelWritingMode(table_writing_direction.GetWritingMode(), table_writing_direction, cell, cell_borders,
cell.Style().GetWritingMode())) { {cell_inline_size, kIndefiniteSize}, cell_percentage_inline_size,
PhysicalSize icb_size = cell.InitialContainingBlockSize(); /* alignment_baseline */ base::nullopt, start_column,
builder.SetOrthogonalFallbackInlineSize( /* is_fixed_block_size_indefinite */ false,
IsHorizontalWritingMode(table_writing_direction.GetWritingMode()) is_table_block_size_specified,
? icb_size.height /* is_hidden_for_paint */ false, has_collapsed_borders,
: icb_size.width); NGCacheSlot::kMeasure);
builder.SetIsShrinkToFit(cell.Style().LogicalWidth().IsAuto());
}
builder.SetAvailableSize(LogicalSize(cell_inline_size, kIndefiniteSize));
// Standard:
// https://www.w3.org/TR/css-tables-3/#computing-the-table-height "the
// computed height (if definite, percentages being considered 0px)"
LogicalSize percentage_resolution_size(cell_percentage_inline_size,
kIndefiniteSize);
builder.SetPercentageResolutionSize(percentage_resolution_size);
builder.SetReplacedPercentageResolutionSize(percentage_resolution_size);
builder.SetIsFixedInlineSize(true);
builder.SetIsTableCell(true, /* is_legacy_table_cell */ false);
builder.SetIsRestrictedBlockSizeTableCell(is_restricted_block_size_table);
builder.SetNeedsBaseline(true);
builder.SetCacheSlot(NGCacheSlot::kMeasure);
return builder.ToConstraintSpace();
}; };
// TODO(layout-ng) Scrollbars should be frozen when computing row sizes. // TODO(layout-ng) Scrollbars should be frozen when computing row sizes.
...@@ -389,6 +373,63 @@ void ComputeSectionInlineConstraints( ...@@ -389,6 +373,63 @@ void ComputeSectionInlineConstraints(
} // namespace } // namespace
// static
NGConstraintSpace NGTableAlgorithmUtils::CreateTableCellConstraintSpace(
const WritingDirectionMode table_writing_direction,
const NGBlockNode cell,
const NGBoxStrut& cell_borders,
LogicalSize cell_size,
LayoutUnit percentage_inline_size,
base::Optional<LayoutUnit> alignment_baseline,
wtf_size_t column_index,
bool is_fixed_block_size_indefinite,
bool is_table_block_size_specified,
bool is_hidden_for_paint,
bool has_collapsed_borders,
NGCacheSlot cache_slot) {
const auto& cell_style = cell.Style();
const auto table_writing_mode = table_writing_direction.GetWritingMode();
const auto cell_writing_mode = cell_style.GetWritingMode();
NGConstraintSpaceBuilder builder(table_writing_mode, cell_writing_mode,
/* is_new_fc */ true);
builder.SetIsTableCell(true, /* is_legacy_table_cell */ false);
builder.SetTextDirection(cell_style.Direction());
if (!IsParallelWritingMode(table_writing_mode, cell_writing_mode)) {
const PhysicalSize icb_size = cell.InitialContainingBlockSize();
builder.SetOrthogonalFallbackInlineSize(
table_writing_direction.IsHorizontal() ? icb_size.height
: icb_size.width);
builder.SetIsShrinkToFit(cell.Style().LogicalWidth().IsAuto());
}
builder.SetAvailableSize(cell_size);
builder.SetIsFixedInlineSize(true);
if (cell_size.block_size != kIndefiniteSize) {
builder.SetIsFixedBlockSize(true);
builder.SetIsFixedBlockSizeIndefinite(is_fixed_block_size_indefinite);
}
// Standard:
// https://www.w3.org/TR/css-tables-3/#computing-the-table-height "the
// computed height (if definite, percentages being considered 0px)"
builder.SetPercentageResolutionSize(
{percentage_inline_size, kIndefiniteSize});
builder.SetTableCellBorders(cell_borders);
builder.SetTableCellAlignmentBaseline(alignment_baseline);
builder.SetTableCellColumnIndex(column_index);
builder.SetIsRestrictedBlockSizeTableCell(is_table_block_size_specified);
builder.SetIsTableCellHiddenForPaint(is_hidden_for_paint);
builder.SetIsTableCellWithCollapsedBorders(has_collapsed_borders);
builder.SetHideTableCellIfEmpty(
!has_collapsed_borders && cell_style.EmptyCells() == EEmptyCells::kHide);
builder.SetNeedsBaseline(true);
builder.SetCacheSlot(cache_slot);
return builder.ToConstraintSpace();
}
scoped_refptr<NGTableTypes::Columns> scoped_refptr<NGTableTypes::Columns>
NGTableAlgorithmUtils::ComputeColumnConstraints( NGTableAlgorithmUtils::ComputeColumnConstraints(
const NGBlockNode& table, const NGBlockNode& table,
...@@ -431,7 +472,7 @@ NGTableAlgorithmUtils::ComputeColumnConstraints( ...@@ -431,7 +472,7 @@ NGTableAlgorithmUtils::ComputeColumnConstraints(
void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes( void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes(
const NGBlockNode& section, const NGBlockNode& section,
const LayoutUnit cell_percentage_inline_size, const LayoutUnit cell_percentage_inline_size,
const bool is_restricted_block_size_table, const bool is_table_block_size_restricted,
const NGTableTypes::ColumnLocations& column_locations, const NGTableTypes::ColumnLocations& column_locations,
const NGTableBorders& table_borders, const NGTableBorders& table_borders,
const LayoutUnit block_border_spacing, const LayoutUnit block_border_spacing,
...@@ -452,7 +493,7 @@ void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes( ...@@ -452,7 +493,7 @@ void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes(
row = To<NGBlockNode>(row.NextSibling())) { row = To<NGBlockNode>(row.NextSibling())) {
colspan_cell_tabulator.StartRow(); colspan_cell_tabulator.StartRow();
NGTableTypes::Row row_constraint = ComputeMinimumRowBlockSize( NGTableTypes::Row row_constraint = ComputeMinimumRowBlockSize(
row, cell_percentage_inline_size, is_restricted_block_size_table, row, cell_percentage_inline_size, is_table_block_size_restricted,
column_locations, table_borders, current_row++, section_index, column_locations, table_borders, current_row++, section_index,
/* is_section_collapsed */ section.Style().Visibility() == /* is_section_collapsed */ section.Style().Visibility() ==
EVisibility::kCollapse, EVisibility::kCollapse,
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
namespace blink { namespace blink {
struct LogicalSize;
enum class NGCacheSlot;
class NGConstraintSpace;
class NGTableBorders; class NGTableBorders;
class NGBlockNode; class NGBlockNode;
...@@ -25,6 +28,24 @@ class NGTableAlgorithmUtils { ...@@ -25,6 +28,24 @@ class NGTableAlgorithmUtils {
align == EVerticalAlign::kLength; align == EVerticalAlign::kLength;
} }
// Creates a constraint-space for a table-cell.
//
// In order to make the cache as effective as possible, we try and keep
// creating the constraint-space for table-cells as consistent as possible.
static NGConstraintSpace CreateTableCellConstraintSpace(
const WritingDirectionMode table_writing_direction,
const NGBlockNode cell,
const NGBoxStrut& cell_borders,
LogicalSize cell_size,
LayoutUnit percentage_inline_size,
base::Optional<LayoutUnit> alignment_baseline,
wtf_size_t column_index,
bool is_fixed_block_size_indefinite,
bool is_restricted_block_size_table,
bool is_hidden_for_paint,
bool has_collapsed_borders,
NGCacheSlot);
static scoped_refptr<NGTableTypes::Columns> ComputeColumnConstraints( static scoped_refptr<NGTableTypes::Columns> ComputeColumnConstraints(
const NGBlockNode& table, const NGBlockNode& table,
const NGTableGroupedChildren&, const NGTableGroupedChildren&,
......
...@@ -33,9 +33,10 @@ scoped_refptr<const NGLayoutResult> NGTableRowLayoutAlgorithm::Layout() { ...@@ -33,9 +33,10 @@ scoped_refptr<const NGLayoutResult> NGTableRowLayoutAlgorithm::Layout() {
base::Optional<LayoutUnit> row_baseline, base::Optional<LayoutUnit> row_baseline,
bool row_is_collapsed, bool row_is_collapsed,
wtf_size_t* cell_location_start_column) { wtf_size_t* cell_location_start_column) {
wtf_size_t start_column = table_data.cells[cell_index].start_column; const wtf_size_t start_column = table_data.cells[cell_index].start_column;
wtf_size_t end_column = std::min(start_column + cell.TableCellColspan() - 1, const wtf_size_t end_column =
table_data.column_locations.size() - 1); std::min(start_column + cell.TableCellColspan() - 1,
table_data.column_locations.size() - 1);
*cell_location_start_column = start_column; *cell_location_start_column = start_column;
// When columns spanned by the cell are collapsed, cell geometry is defined // When columns spanned by the cell are collapsed, cell geometry is defined
// by: // by:
...@@ -56,53 +57,28 @@ scoped_refptr<const NGLayoutResult> NGTableRowLayoutAlgorithm::Layout() { ...@@ -56,53 +57,28 @@ scoped_refptr<const NGLayoutResult> NGTableRowLayoutAlgorithm::Layout() {
const NGTableConstraintSpaceData::Cell& cell_data = const NGTableConstraintSpaceData::Cell& cell_data =
table_data.cells[cell_index]; table_data.cells[cell_index];
LayoutUnit cell_inline_size = const LayoutUnit cell_inline_size =
table_data.column_locations[cell_location_end_column].offset + table_data.column_locations[cell_location_end_column].offset +
table_data.column_locations[cell_location_end_column].inline_size - table_data.column_locations[cell_location_end_column].inline_size -
table_data.column_locations[*cell_location_start_column].offset; table_data.column_locations[*cell_location_start_column].offset;
LayoutUnit cell_block_size = const LayoutUnit cell_block_size =
row_is_collapsed ? LayoutUnit() : cell_data.block_size; row_is_collapsed ? LayoutUnit() : cell_data.block_size;
NGConstraintSpaceBuilder builder( // Percentage block resolution size is only valid if cell block-size is
table_data.table_writing_direction.GetWritingMode(), // specified, or the table block-size is specified.
cell.Style().GetWritingMode(), /* is_new_fc */ true); const bool is_fixed_block_size_indefinite =
builder.SetAvailableSize({cell_inline_size, cell_block_size}); !cell_data.is_constrained && !table_data.is_table_block_size_specified;
builder.SetIsFixedInlineSize(true);
builder.SetIsFixedBlockSize(true);
builder.SetTextDirection(Style().Direction());
PhysicalSize icb_size = Node().InitialContainingBlockSize();
builder.SetOrthogonalFallbackInlineSize(
IsHorizontalWritingMode(
table_data.table_writing_direction.GetWritingMode())
? icb_size.height
: icb_size.width);
builder.SetPercentageResolutionSize(
LogicalSize(container_builder_.InlineSize(), kIndefiniteSize));
// Percentage block resolution size is only valid if
// cell height is specified, or table height is specified.
bool is_block_size_indefinite =
!cell_data.is_constrained &&
!table_data.treat_table_block_size_as_constrained;
if (is_block_size_indefinite)
builder.SetIsFixedBlockSizeIndefinite(true);
builder.SetIsTableCell(/* is_table_cell */ true,
/* is_legacy_table_cell */ false);
builder.SetTableCellBorders(cell_data.border_box_borders);
builder.SetTableCellAlignmentBaseline(row_baseline);
builder.SetTableCellColumnIndex(start_column);
builder.SetHasTableCellCollapsedBorder(table_data.has_collapsed_borders);
builder.SetNeedsBaseline(true);
builder.SetIsTableCellHiddenForPaint(
table_data.column_locations[*cell_location_start_column].is_collapsed &&
*cell_location_start_column == cell_location_end_column);
builder.SetHideTableCellIfEmpty(!table_data.has_collapsed_borders &&
cell.Style().EmptyCells() ==
EEmptyCells::kHide);
return builder.ToConstraintSpace(); const bool is_hidden_for_paint =
table_data.column_locations[*cell_location_start_column].is_collapsed &&
*cell_location_start_column == cell_location_end_column;
return NGTableAlgorithmUtils::CreateTableCellConstraintSpace(
table_data.table_writing_direction, cell, cell_data.border_box_borders,
{cell_inline_size, cell_block_size}, container_builder_.InlineSize(),
row_baseline, start_column, is_fixed_block_size_indefinite,
table_data.is_table_block_size_specified, is_hidden_for_paint,
table_data.has_collapsed_borders, NGCacheSlot::kLayout);
}; };
const NGTableConstraintSpaceData::Row& row = table_data.rows[row_index]; const NGTableConstraintSpaceData::Row& row = table_data.rows[row_index];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment