diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index a2e766fc3506d..027ce11564ede 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -240,6 +240,10 @@ impl BorderStyleColor { Self::new(border.border_left_style, border.border_left_color.clone()), ) } + + pub(crate) fn hidden() -> Self { + Self::new(BorderStyle::Hidden, Color::TRANSPARENT_BLACK) + } } impl Default for BorderStyleColor { diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index da7d03f0fb45e..dcc3a6edd0085 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -149,6 +149,11 @@ impl CollapsedBorder { collapsed_border.max_assign(self) } } + + fn hide(&mut self) { + self.style_color = BorderStyleColor::hidden(); + self.width = Au::zero(); + } } /// @@ -185,6 +190,8 @@ impl PartialOrd for CollapsedBorder { impl Eq for CollapsedBorder {} +type CollapsedBorders = LogicalVec2>; + /// A helper struct that performs the layout of the box tree version /// of a table into the fragment tree version. This implements /// @@ -208,7 +215,7 @@ pub(crate) struct TableLayout<'a> { cells_laid_out: Vec>>, basis_for_cell_padding_percentage: Au, /// Information about collapsed borders. - collapsed_borders: Option>>, + collapsed_borders: Option, } #[derive(Clone, Debug)] @@ -2110,22 +2117,38 @@ impl<'a> TableLayout<'a> { ], }; - let mut apply_border = - |layout_style: &LayoutStyle, block: &Range, inline: &Range| { - let border = CollapsedBorder::from_layout_style(layout_style, writing_mode); - border - .block_start - .max_assign_to_slice(&mut collapsed_borders.block[block.start][inline.clone()]); - border - .block_end - .max_assign_to_slice(&mut collapsed_borders.block[block.end][inline.clone()]); - border.inline_start.max_assign_to_slice( - &mut collapsed_borders.inline[inline.start][block.clone()], - ); - border - .inline_end - .max_assign_to_slice(&mut collapsed_borders.inline[inline.end][block.clone()]); - }; + let apply_border = |collapsed_borders: &mut CollapsedBorders, + layout_style: &LayoutStyle, + block: &Range, + inline: &Range| { + let border = CollapsedBorder::from_layout_style(layout_style, writing_mode); + border + .block_start + .max_assign_to_slice(&mut collapsed_borders.block[block.start][inline.clone()]); + border + .block_end + .max_assign_to_slice(&mut collapsed_borders.block[block.end][inline.clone()]); + border + .inline_start + .max_assign_to_slice(&mut collapsed_borders.inline[inline.start][block.clone()]); + border + .inline_end + .max_assign_to_slice(&mut collapsed_borders.inline[inline.end][block.clone()]); + }; + let hide_inner_borders = |collapsed_borders: &mut CollapsedBorders, + block: &Range, + inline: &Range| { + for x in inline.clone() { + for y in block.clone() { + if x != inline.start { + collapsed_borders.inline[x][y].hide(); + } + if y != block.start { + collapsed_borders.block[y][x].hide(); + } + } + } + }; let all_rows = 0..self.table.size.height; let all_columns = 0..self.table.size.width; for row_index in all_rows.clone() { @@ -2134,16 +2157,20 @@ impl<'a> TableLayout<'a> { TableSlot::Cell(ref cell) => cell, _ => continue, }; - + let block_range = row_index..row_index + cell.rowspan; + let inline_range = column_index..column_index + cell.colspan; + hide_inner_borders(&mut collapsed_borders, &block_range, &inline_range); apply_border( + &mut collapsed_borders, &cell.layout_style(), - &(row_index..row_index + cell.rowspan), - &(column_index..column_index + cell.colspan), + &block_range, + &inline_range, ); } } for (row_index, row) in self.table.rows.iter().enumerate() { apply_border( + &mut collapsed_borders, &row.layout_style(), &(row_index..row_index + 1), &all_columns, @@ -2151,6 +2178,7 @@ impl<'a> TableLayout<'a> { } for row_group in &self.table.row_groups { apply_border( + &mut collapsed_borders, &row_group.layout_style(), &row_group.track_range, &all_columns, @@ -2158,6 +2186,7 @@ impl<'a> TableLayout<'a> { } for (column_index, column) in self.table.columns.iter().enumerate() { apply_border( + &mut collapsed_borders, &column.layout_style(), &all_rows, &(column_index..column_index + 1), @@ -2165,12 +2194,18 @@ impl<'a> TableLayout<'a> { } for column_group in &self.table.column_groups { apply_border( + &mut collapsed_borders, &column_group.layout_style(), &all_rows, &column_group.track_range, ); } - apply_border(&self.table.layout_style_for_grid(), &all_rows, &all_columns); + apply_border( + &mut collapsed_borders, + &self.table.layout_style_for_grid(), + &all_rows, + &all_columns, + ); self.collapsed_borders = Some(collapsed_borders); } diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index bedcc95fde1d8..44ffe0105ecfe 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -247576,6 +247576,58 @@ ] ], "tentative": { + "border-collapse-spanning-cells-001.html": [ + "47d5c634f8396d674f56a1bd046462201d5ac48a", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "border-collapse-spanning-cells-002.html": [ + "83543b0708bfbcae732d7883bd28f46fe856fa7b", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "border-collapse-spanning-cells-003.html": [ + "9d28d4c730e79e6e858137483eb25d4d4bcde880", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "border-collapse-spanning-cells-004.html": [ + "1eb77891053aba7ce65afd3f4965a3ab1d7d45e3", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], "padding-percentage.html": [ "67f8009de365a32275232b5c5b008072a0c8fc17", [ diff --git a/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-001.html b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-001.html new file mode 100644 index 0000000000000..47d5c634f8396 --- /dev/null +++ b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-001.html @@ -0,0 +1,44 @@ + + +CSS Test (Tables): spanning cells crossing collapsed track borders + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ + + + + + + + + + + + + + + + + + + + + +
XXXX
X X X X
XXXX
X X X X
diff --git a/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-002.html b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-002.html new file mode 100644 index 0000000000000..83543b0708bfb --- /dev/null +++ b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-002.html @@ -0,0 +1,44 @@ + + +CSS Test (Tables): spanning cells crossing collapsed track borders + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ + + + + + + + + + + + + + + + + + + + + +
XX

X

X

X
XX

X

X

X
XX
XX
XX
diff --git a/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-003.html b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-003.html new file mode 100644 index 0000000000000..9d28d4c730e79 --- /dev/null +++ b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-003.html @@ -0,0 +1,47 @@ + + +CSS Test (Tables): spanning cells crossing collapsed track borders + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ + + + + + + + + + + + + + + + + + + + + + + + +
XXXX
XX X

X X
X
XX
XXXX
diff --git a/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-004.html b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-004.html new file mode 100644 index 0000000000000..1eb77891053ab --- /dev/null +++ b/tests/wpt/tests/css/css-tables/tentative/border-collapse-spanning-cells-004.html @@ -0,0 +1,43 @@ + + +CSS Test (Tables): spanning cells crossing collapsed track borders + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ + + + + + + + + + + + + + + + + + + +
XX

X

X

X
XX

X

X

X
X X X X
XX
X X X X