Commit 4c36a7b2 authored by Aleks Totic's avatar Aleks Totic Committed by Commit Bot

[TablesNG] Box order for painting

Use box order to resolve intersection edge precedence.

Makes 9 additional tests pass:

css2.1/20110323/border-conflict-element-001d.htm
external/wpt/css/CSS2/tables/border-conflict-element-001d.xht
external/wpt/css/CSS2/tables/border-conflict-element-001e.xht
fast/css/table-rules-attribute-groups-with-frame.html
fast/table/colgroup-spanning-groups-rules.html
fast/table/border-collapsing/002-vertical.html
fast/table/border-collapsing/002.html
tables/mozilla/core/table_rules.html
tables/mozilla/marvin/x_table_rules_groups.xml

Bug: 958381
Change-Id: I53f87d716aada00edec5f06129842fc1fc10eb68
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2519882
Commit-Queue: Aleks Totic <atotic@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824701}
parent 09dd36ac
...@@ -120,8 +120,8 @@ class ColBordersMarker { ...@@ -120,8 +120,8 @@ class ColBordersMarker {
for (wtf_size_t i = 0; i < span; ++i) { for (wtf_size_t i = 0; i < span; ++i) {
wtf_size_t current_column_index = start_column_index + i; wtf_size_t current_column_index = start_column_index + i;
borders.MergeBorders(0, current_column_index, table_row_count, 1, borders.MergeBorders(0, current_column_index, table_row_count, 1,
&column.Style(), NGTableBorders::EdgeSource::kColumn, column.Style(), NGTableBorders::EdgeSource::kColumn,
table_writing_direction); box_order, table_writing_direction);
} }
} }
void EnterColgroup(const NGLayoutInputNode& colgroup, void EnterColgroup(const NGLayoutInputNode& colgroup,
...@@ -131,13 +131,16 @@ class ColBordersMarker { ...@@ -131,13 +131,16 @@ class ColBordersMarker {
wtf_size_t span, wtf_size_t span,
bool has_children) {} bool has_children) {}
ColBordersMarker(wtf_size_t table_row_count, ColBordersMarker(wtf_size_t table_row_count,
wtf_size_t box_order,
WritingDirectionMode table_writing_direction, WritingDirectionMode table_writing_direction,
NGTableBorders& borders) NGTableBorders& borders)
: table_row_count(table_row_count), : table_row_count(table_row_count),
box_order(box_order),
table_writing_direction(table_writing_direction), table_writing_direction(table_writing_direction),
borders(borders) {} borders(borders) {}
wtf_size_t table_row_count; const wtf_size_t table_row_count;
WritingDirectionMode table_writing_direction; const wtf_size_t box_order;
const WritingDirectionMode table_writing_direction;
NGTableBorders& borders; NGTableBorders& borders;
}; };
...@@ -155,17 +158,20 @@ class ColgroupBordersMarker { ...@@ -155,17 +158,20 @@ class ColgroupBordersMarker {
wtf_size_t span, wtf_size_t span,
bool has_children) { bool has_children) {
borders.MergeBorders(0, start_column_index, table_row_count, span, borders.MergeBorders(0, start_column_index, table_row_count, span,
&colgroup.Style(), NGTableBorders::EdgeSource::kColumn, colgroup.Style(), NGTableBorders::EdgeSource::kColumn,
table_writing_direction); box_order, table_writing_direction);
} }
ColgroupBordersMarker(wtf_size_t table_row_count, ColgroupBordersMarker(wtf_size_t table_row_count,
wtf_size_t box_order,
WritingDirectionMode table_writing_direction, WritingDirectionMode table_writing_direction,
NGTableBorders& borders) NGTableBorders& borders)
: table_row_count(table_row_count), : table_row_count(table_row_count),
box_order(box_order),
table_writing_direction(table_writing_direction), table_writing_direction(table_writing_direction),
borders(borders) {} borders(borders) {}
wtf_size_t table_row_count; const wtf_size_t table_row_count;
WritingDirectionMode table_writing_direction; const wtf_size_t box_order;
const WritingDirectionMode table_writing_direction;
NGTableBorders& borders; NGTableBorders& borders;
}; };
...@@ -188,6 +194,7 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders( ...@@ -188,6 +194,7 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders(
bool hide_empty_cells = table_style.EmptyCells() == EEmptyCells::kHide; bool hide_empty_cells = table_style.EmptyCells() == EEmptyCells::kHide;
WritingDirectionMode table_writing_direction = WritingDirectionMode table_writing_direction =
table.Style().GetWritingDirection(); table.Style().GetWritingDirection();
wtf_size_t box_order = 0;
wtf_size_t table_column_count = 0; wtf_size_t table_column_count = 0;
wtf_size_t table_row_index = 0; wtf_size_t table_row_index = 0;
...@@ -220,8 +227,9 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders( ...@@ -220,8 +227,9 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders(
if (!found_multispan_cells) { if (!found_multispan_cells) {
table_borders->MergeBorders( table_borders->MergeBorders(
table_row_index, tabulator.CurrentColumn(), table_row_index, tabulator.CurrentColumn(),
cell.TableCellRowspan(), cell_colspan, &cell.Style(), cell.TableCellRowspan(), cell_colspan, cell.Style(),
NGTableBorders::EdgeSource::kCell, table_writing_direction); NGTableBorders::EdgeSource::kCell, ++box_order,
table_writing_direction);
} }
tabulator.ProcessCell(cell); tabulator.ProcessCell(cell);
} }
...@@ -254,9 +262,9 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders( ...@@ -254,9 +262,9 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders(
} }
table_borders->MergeBorders( table_borders->MergeBorders(
table_row_index, tabulator.CurrentColumn(), table_row_index, tabulator.CurrentColumn(),
cell.TableCellRowspan(), cell.TableCellColspan(), &cell.Style(), cell.TableCellRowspan(), cell.TableCellColspan(), cell.Style(),
NGTableBorders::EdgeSource::kCell, table_writing_direction, NGTableBorders::EdgeSource::kCell, ++box_order,
section_index); table_writing_direction, section_index);
tabulator.ProcessCell(cell); tabulator.ProcessCell(cell);
} }
tabulator.EndRow(); tabulator.EndRow();
...@@ -271,9 +279,9 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders( ...@@ -271,9 +279,9 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders(
for (NGBlockNode section : grouped_children) { for (NGBlockNode section : grouped_children) {
for (NGBlockNode row = To<NGBlockNode>(section.FirstChild()); row; for (NGBlockNode row = To<NGBlockNode>(section.FirstChild()); row;
row = To<NGBlockNode>(row.NextSibling())) { row = To<NGBlockNode>(row.NextSibling())) {
table_borders->MergeBorders( table_borders->MergeBorders(table_row_index, 0, 1, table_column_count,
table_row_index, 0, 1, table_column_count, &row.Style(), row.Style(), NGTableBorders::EdgeSource::kRow,
NGTableBorders::EdgeSource::kRow, table_writing_direction); ++box_order, table_writing_direction);
++table_row_index; ++table_row_index;
} }
} }
...@@ -287,7 +295,7 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders( ...@@ -287,7 +295,7 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders(
table_borders->GetSection(section_index); table_borders->GetSection(section_index);
table_borders->MergeBorders( table_borders->MergeBorders(
section_info.start_row, 0, section_info.row_count, table_column_count, section_info.start_row, 0, section_info.row_count, table_column_count,
&section.Style(), NGTableBorders::EdgeSource::kSection, section.Style(), NGTableBorders::EdgeSource::kSection, ++box_order,
table_writing_direction); table_writing_direction);
++section_index; ++section_index;
} }
...@@ -295,21 +303,23 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders( ...@@ -295,21 +303,23 @@ scoped_refptr<NGTableBorders> NGTableBorders::ComputeTableBorders(
// Mark column borders. // Mark column borders.
// COL borders have precedence over COLGROUP borders. // COL borders have precedence over COLGROUP borders.
// We have to traverse COL first, then COLGROUP. // We have to traverse COL first, then COLGROUP.
ColBordersMarker col_borders_marker(table_row_count, table_writing_direction, ColBordersMarker col_borders_marker(table_row_count, ++box_order,
table_writing_direction,
*table_borders.get()); *table_borders.get());
VisitLayoutNGTableColumn( VisitLayoutNGTableColumn(
const_cast<Vector<NGBlockNode>&>(grouped_children.columns), const_cast<Vector<NGBlockNode>&>(grouped_children.columns),
table_column_count, &col_borders_marker); table_column_count, &col_borders_marker);
ColgroupBordersMarker colgroup_borders_marker( ColgroupBordersMarker colgroup_borders_marker(table_row_count, ++box_order,
table_row_count, table_writing_direction, *table_borders.get()); table_writing_direction,
*table_borders.get());
VisitLayoutNGTableColumn( VisitLayoutNGTableColumn(
const_cast<Vector<NGBlockNode>&>(grouped_children.columns), const_cast<Vector<NGBlockNode>&>(grouped_children.columns),
table_column_count, &colgroup_borders_marker); table_column_count, &colgroup_borders_marker);
// Mark table borders. // Mark table borders.
table_borders->MergeBorders(0, 0, table_row_count, table_column_count, table_borders->MergeBorders(0, 0, table_row_count, table_column_count,
&table_style, NGTableBorders::EdgeSource::kTable, table_style, NGTableBorders::EdgeSource::kTable,
table_writing_direction); ++box_order, table_writing_direction);
table_borders->ComputeCollapsedTableBorderPadding(table_row_count, table_borders->ComputeCollapsedTableBorderPadding(table_row_count,
table_column_count); table_column_count);
...@@ -492,8 +502,9 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row, ...@@ -492,8 +502,9 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row,
wtf_size_t cell_start_column, wtf_size_t cell_start_column,
wtf_size_t rowspan, wtf_size_t rowspan,
wtf_size_t colspan, wtf_size_t colspan,
const ComputedStyle* source_style, const ComputedStyle& source_style,
EdgeSource source, EdgeSource source,
const wtf_size_t box_order,
WritingDirectionMode table_writing_direction, WritingDirectionMode table_writing_direction,
wtf_size_t section_index) { wtf_size_t section_index) {
DCHECK(is_collapsed_); DCHECK(is_collapsed_);
...@@ -514,9 +525,9 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row, ...@@ -514,9 +525,9 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row,
EnsureCellRowFits(cell_start_row + clamped_rowspan - 1); EnsureCellRowFits(cell_start_row + clamped_rowspan - 1);
} else { } else {
PhysicalToLogical<EBorderStyle> border_style( PhysicalToLogical<EBorderStyle> border_style(
table_writing_direction, source_style->BorderTopStyle(), table_writing_direction, source_style.BorderTopStyle(),
source_style->BorderRightStyle(), source_style->BorderBottomStyle(), source_style.BorderRightStyle(), source_style.BorderBottomStyle(),
source_style->BorderLeftStyle()); source_style.BorderLeftStyle());
if (border_style.InlineStart() == EBorderStyle::kNone && if (border_style.InlineStart() == EBorderStyle::kNone &&
border_style.InlineEnd() == EBorderStyle::kNone && border_style.InlineEnd() == EBorderStyle::kNone &&
border_style.BlockStart() == EBorderStyle::kNone && border_style.BlockStart() == EBorderStyle::kNone &&
...@@ -540,19 +551,19 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row, ...@@ -540,19 +551,19 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row,
} }
} }
MergeRowAxisBorder(cell_start_row, cell_start_column, clamped_colspan, MergeRowAxisBorder(cell_start_row, cell_start_column, clamped_colspan,
source_style, source_style, box_order,
LogicalEdgeToPhysical(LogicalEdgeSide::kBlockStart, LogicalEdgeToPhysical(LogicalEdgeSide::kBlockStart,
table_writing_direction)); table_writing_direction));
MergeRowAxisBorder(cell_start_row + clamped_rowspan, cell_start_column, MergeRowAxisBorder(cell_start_row + clamped_rowspan, cell_start_column,
clamped_colspan, source_style, clamped_colspan, source_style, box_order,
LogicalEdgeToPhysical(LogicalEdgeSide::kBlockEnd, LogicalEdgeToPhysical(LogicalEdgeSide::kBlockEnd,
table_writing_direction)); table_writing_direction));
MergeColumnAxisBorder(cell_start_row, cell_start_column, clamped_rowspan, MergeColumnAxisBorder(cell_start_row, cell_start_column, clamped_rowspan,
source_style, source_style, box_order,
LogicalEdgeToPhysical(LogicalEdgeSide::kInlineStart, LogicalEdgeToPhysical(LogicalEdgeSide::kInlineStart,
table_writing_direction)); table_writing_direction));
MergeColumnAxisBorder(cell_start_row, cell_start_column + clamped_colspan, MergeColumnAxisBorder(cell_start_row, cell_start_column + clamped_colspan,
clamped_rowspan, source_style, clamped_rowspan, source_style, box_order,
LogicalEdgeToPhysical(LogicalEdgeSide::kInlineEnd, LogicalEdgeToPhysical(LogicalEdgeSide::kInlineEnd,
table_writing_direction)); table_writing_direction));
if (mark_inner_borders) { if (mark_inner_borders) {
...@@ -564,12 +575,13 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row, ...@@ -564,12 +575,13 @@ void NGTableBorders::MergeBorders(wtf_size_t cell_start_row,
void NGTableBorders::MergeRowAxisBorder(wtf_size_t start_row, void NGTableBorders::MergeRowAxisBorder(wtf_size_t start_row,
wtf_size_t start_column, wtf_size_t start_column,
wtf_size_t colspan, wtf_size_t colspan,
const ComputedStyle* source_style, const ComputedStyle& source_style,
const wtf_size_t box_order,
EdgeSide physical_side) { EdgeSide physical_side) {
EBorderStyle source_border_style = BorderStyle(source_style, physical_side); EBorderStyle source_border_style = BorderStyle(&source_style, physical_side);
if (source_border_style == EBorderStyle::kNone) if (source_border_style == EBorderStyle::kNone)
return; return;
LayoutUnit source_border_width = BorderWidth(source_style, physical_side); LayoutUnit source_border_width = BorderWidth(&source_style, physical_side);
wtf_size_t start_edge = edges_per_row_ * start_row + start_column * 2 + 1; wtf_size_t start_edge = edges_per_row_ * start_row + start_column * 2 + 1;
wtf_size_t end_edge = start_edge + colspan * 2; wtf_size_t end_edge = start_edge + colspan * 2;
for (wtf_size_t current_edge = start_edge; current_edge < end_edge; for (wtf_size_t current_edge = start_edge; current_edge < end_edge;
...@@ -577,8 +589,9 @@ void NGTableBorders::MergeRowAxisBorder(wtf_size_t start_row, ...@@ -577,8 +589,9 @@ void NGTableBorders::MergeRowAxisBorder(wtf_size_t start_row,
// https://www.w3.org/TR/css-tables-3/#border-specificity // https://www.w3.org/TR/css-tables-3/#border-specificity
if (IsSourceMoreSpecificThanEdge(source_border_style, source_border_width, if (IsSourceMoreSpecificThanEdge(source_border_style, source_border_width,
edges_[current_edge])) { edges_[current_edge])) {
edges_[current_edge].style = source_style; edges_[current_edge].style = &source_style;
edges_[current_edge].edge_side = physical_side; edges_[current_edge].edge_side = physical_side;
edges_[current_edge].box_order = box_order;
} }
} }
} }
...@@ -586,12 +599,13 @@ void NGTableBorders::MergeRowAxisBorder(wtf_size_t start_row, ...@@ -586,12 +599,13 @@ void NGTableBorders::MergeRowAxisBorder(wtf_size_t start_row,
void NGTableBorders::MergeColumnAxisBorder(wtf_size_t start_row, void NGTableBorders::MergeColumnAxisBorder(wtf_size_t start_row,
wtf_size_t start_column, wtf_size_t start_column,
wtf_size_t rowspan, wtf_size_t rowspan,
const ComputedStyle* source_style, const ComputedStyle& source_style,
const wtf_size_t box_order,
EdgeSide physical_side) { EdgeSide physical_side) {
EBorderStyle source_border_style = BorderStyle(source_style, physical_side); EBorderStyle source_border_style = BorderStyle(&source_style, physical_side);
if (source_border_style == EBorderStyle::kNone) if (source_border_style == EBorderStyle::kNone)
return; return;
LayoutUnit source_border_width = BorderWidth(source_style, physical_side); LayoutUnit source_border_width = BorderWidth(&source_style, physical_side);
wtf_size_t start_edge = edges_per_row_ * start_row + start_column * 2; wtf_size_t start_edge = edges_per_row_ * start_row + start_column * 2;
wtf_size_t end_edge = start_edge + (rowspan * edges_per_row_); wtf_size_t end_edge = start_edge + (rowspan * edges_per_row_);
for (wtf_size_t current_edge = start_edge; current_edge < end_edge; for (wtf_size_t current_edge = start_edge; current_edge < end_edge;
...@@ -599,8 +613,9 @@ void NGTableBorders::MergeColumnAxisBorder(wtf_size_t start_row, ...@@ -599,8 +613,9 @@ void NGTableBorders::MergeColumnAxisBorder(wtf_size_t start_row,
// https://www.w3.org/TR/css-tables-3/#border-specificity // https://www.w3.org/TR/css-tables-3/#border-specificity
if (IsSourceMoreSpecificThanEdge(source_border_style, source_border_width, if (IsSourceMoreSpecificThanEdge(source_border_style, source_border_width,
edges_[current_edge])) { edges_[current_edge])) {
edges_[current_edge].style = source_style; edges_[current_edge].style = &source_style;
edges_[current_edge].edge_side = physical_side; edges_[current_edge].edge_side = physical_side;
edges_[current_edge].box_order = box_order;
} }
} }
} }
......
...@@ -80,6 +80,11 @@ class NGTableBorders : public RefCounted<NGTableBorders> { ...@@ -80,6 +80,11 @@ class NGTableBorders : public RefCounted<NGTableBorders> {
struct Edge { struct Edge {
scoped_refptr<const ComputedStyle> style; scoped_refptr<const ComputedStyle> style;
EdgeSide edge_side; EdgeSide edge_side;
// Box order is used to compute edge painting precedence.
// Lower box order has precedence.
// The order value is defined as "box visited index" while
// computing collapsed edges.
wtf_size_t box_order;
}; };
static LayoutUnit BorderWidth(const ComputedStyle* style, static LayoutUnit BorderWidth(const ComputedStyle* style,
...@@ -172,6 +177,10 @@ class NGTableBorders : public RefCounted<NGTableBorders> { ...@@ -172,6 +177,10 @@ class NGTableBorders : public RefCounted<NGTableBorders> {
edges_[edge_index].edge_side); edges_[edge_index].edge_side);
} }
wtf_size_t BoxOrder(wtf_size_t edge_index) const {
return edges_[edge_index].box_order;
}
using Edges = Vector<Edge>; using Edges = Vector<Edge>;
struct Section { struct Section {
...@@ -219,8 +228,9 @@ class NGTableBorders : public RefCounted<NGTableBorders> { ...@@ -219,8 +228,9 @@ class NGTableBorders : public RefCounted<NGTableBorders> {
wtf_size_t start_column, wtf_size_t start_column,
wtf_size_t rowspan, wtf_size_t rowspan,
wtf_size_t colspan, wtf_size_t colspan,
const ComputedStyle* source_style, const ComputedStyle& source_style,
EdgeSource source, EdgeSource source,
wtf_size_t box_order,
WritingDirectionMode table_writing_direction, WritingDirectionMode table_writing_direction,
wtf_size_t section_index = kNotFound); wtf_size_t section_index = kNotFound);
...@@ -297,13 +307,15 @@ class NGTableBorders : public RefCounted<NGTableBorders> { ...@@ -297,13 +307,15 @@ class NGTableBorders : public RefCounted<NGTableBorders> {
void MergeRowAxisBorder(wtf_size_t start_row, void MergeRowAxisBorder(wtf_size_t start_row,
wtf_size_t start_column, wtf_size_t start_column,
wtf_size_t colspan, wtf_size_t colspan,
const ComputedStyle* source_style, const ComputedStyle& source_style,
wtf_size_t box_order,
EdgeSide side); EdgeSide side);
void MergeColumnAxisBorder(wtf_size_t start_row, void MergeColumnAxisBorder(wtf_size_t start_row,
wtf_size_t start_column, wtf_size_t start_column,
wtf_size_t rowspan, wtf_size_t rowspan,
const ComputedStyle* source_style, const ComputedStyle& source_style,
wtf_size_t box_order,
EdgeSide side); EdgeSide side);
void MarkInnerBordersAsDoNotFill(wtf_size_t start_row, void MarkInnerBordersAsDoNotFill(wtf_size_t start_row,
......
...@@ -69,6 +69,16 @@ class NGTableCollapsedEdge { ...@@ -69,6 +69,16 @@ class NGTableCollapsedEdge {
Color BorderColor() const { return borders_.BorderColor(edge_index_); } Color BorderColor() const { return borders_.BorderColor(edge_index_); }
int CompareBoxOrder(wtf_size_t other_edge_index) const {
wtf_size_t box_order = borders_.BoxOrder(edge_index_);
wtf_size_t other_box_order = borders_.BoxOrder(other_edge_index);
if (box_order < other_box_order)
return 1;
if (box_order > other_box_order)
return -1;
return 0;
}
bool IsInlineAxis() const { bool IsInlineAxis() const {
DCHECK(Exists()); DCHECK(Exists());
DCHECK_NE(edge_index_, UINT_MAX); DCHECK_NE(edge_index_, UINT_MAX);
...@@ -103,7 +113,7 @@ class NGTableCollapsedEdge { ...@@ -103,7 +113,7 @@ class NGTableCollapsedEdge {
// Paint border style comparison for paint has different // Paint border style comparison for paint has different
// rules than for winning edge border (hidden does not win). // rules than for winning edge border (hidden does not win).
if (lhs.border_style_ == rhs.border_style_) if (lhs.border_style_ == rhs.border_style_)
return 0; return lhs.CompareBoxOrder(rhs.edge_index_);
if (rhs.border_style_ == EBorderStyle::kHidden) if (rhs.border_style_ == EBorderStyle::kHidden)
return 1; return 1;
if (lhs.border_style_ == EBorderStyle::kHidden) if (lhs.border_style_ == EBorderStyle::kHidden)
......
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