From b4f605eb6bbf41f02f0a5e1543ea19d0fb2b1bf1 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Fri, 16 Feb 2024 18:32:31 +0100 Subject: [PATCH] layout: Add initial support for row height distribution This change adds a version of row height distribution that follows the distribtuion algorithm used for tables in Blink's LayoutNG. This is just an intermediate step toward implementing a distribution algorithm for both rows and columns more similar to Layout NG. The CSS Table 3 specification is often wrong with regard to web compatability, which is why we have abandoned it in favor of the Layout NG algorithm for row height distribution. this work. Co-authored-by: Oriol Brufau --- components/layout_2020/sizing.rs | 20 +- components/layout_2020/table/layout.rs | 655 ++++++++++++++---- .../floats-clear/clear-applies-to-001.xht.ini | 2 - .../floats-clear/clear-applies-to-002.xht.ini | 2 - .../floats-clear/clear-applies-to-003.xht.ini | 2 - .../floats-clear/clear-applies-to-004.xht.ini | 2 - .../floats-clear/clear-applies-to-005.xht.ini | 2 - .../floats-clear/clear-applies-to-006.xht.ini | 2 - .../floats-clear/clear-applies-to-007.xht.ini | 2 - .../floats-clear/clear-applies-to-013.xht.ini | 2 - .../floats-clear/clear-applies-to-014.xht.ini | 2 - .../floats-clear/float-applies-to-013.xht.ini | 2 - .../floats-clear/float-applies-to-014.xht.ini | 2 - .../CSS2/tables/height-table-cell-001.xht.ini | 2 - .../tables/padding-applies-to-013a.xht.ini | 2 - .../CSS2/tables/row-visibility-002.xht.ini | 2 - .../separated-border-model-004e.xht.ini | 2 - .../css/CSS2/tables/table-cell-001.xht.ini | 2 - .../table-height-algorithm-008a.xht.ini | 2 - .../table-height-algorithm-008b.xht.ini | 2 - .../table-height-algorithm-008c.xht.ini | 2 - .../tables/table-visual-layout-026a.xht.ini | 2 - .../tables/table-visual-layout-026b.xht.ini | 2 - .../tables/table-visual-layout-026c.xht.ini | 2 - .../tables/table-visual-layout-026d.xht.ini | 2 - ...der-spacing-included-in-sizes-001.html.ini | 12 - .../bounding-box-computation-1.html.ini | 15 - .../css-tables/chrome-rowspan-bug.html.ini | 3 - .../css-tables/column-track-merging.html.ini | 6 +- ...fixup-dynamic-anonymous-table-001.html.ini | 2 - .../computing-row-measure-0.html.ini | 6 - .../computing-row-measure-1.html.ini | 6 +- .../html5-table-formatting-2.html.ini | 12 - ...l-change-span-bg-invalidation-002.html.ini | 2 - .../subpixel-table-cell-height-001.html.ini | 2 - .../subpixel-table-cell-width-002.html.ini | 2 - .../table-cell-scroll-height.html.ini | 3 - .../css/css-tables/table-model-fixup.html.ini | 3 - .../css-tables/tentative/baseline-td.html.ini | 9 - .../tentative/colspan-redistribution.html.ini | 6 +- .../rowspan-height-redistribution.html.ini | 37 +- .../table-height-redistribution.html.ini | 3 - ...idth-redistribution-fixed-padding.html.ini | 6 +- .../table-width-redistribution-fixed.html.ini | 6 +- .../tbody-height-redistribution.html.ini | 3 - .../tentative/td-box-sizing-001.html.ini | 3 - .../tentative/td-box-sizing-003.html.ini | 3 - .../visibility-collapse-row-005.html.ini | 6 + .../computing-column-measure-1.html.ini | 8 +- 49 files changed, 587 insertions(+), 298 deletions(-) delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-001.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-002.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-003.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-004.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-005.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-006.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-007.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-013.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-014.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-013.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-014.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/height-table-cell-001.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/padding-applies-to-013a.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/row-visibility-002.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/separated-border-model-004e.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-cell-001.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008a.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008b.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008c.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-visual-layout-026a.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-visual-layout-026b.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-visual-layout-026c.xht.ini delete mode 100644 tests/wpt/meta/css/CSS2/tables/table-visual-layout-026d.xht.ini delete mode 100644 tests/wpt/meta/css/css-tables/border-spacing-included-in-sizes-001.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/bounding-box-computation-1.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/chrome-rowspan-bug.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/fixup-dynamic-anonymous-table-001.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/paint/col-change-span-bg-invalidation-002.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/subpixel-table-cell-height-001.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/subpixel-table-cell-width-002.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/table-cell-scroll-height.html.ini create mode 100644 tests/wpt/meta/css/css-tables/visibility-collapse-row-005.html.ini diff --git a/components/layout_2020/sizing.rs b/components/layout_2020/sizing.rs index a5748eb9eb8f..20b9192cd3a4 100644 --- a/components/layout_2020/sizing.rs +++ b/components/layout_2020/sizing.rs @@ -24,13 +24,6 @@ pub(crate) struct ContentSizes { /// impl ContentSizes { - pub fn zero() -> Self { - Self { - min_content: Au::zero(), - max_content: Au::zero(), - } - } - pub fn map(&self, f: impl Fn(Au) -> Au) -> Self { Self { min_content: f(self.min_content), @@ -57,6 +50,19 @@ impl ContentSizes { } } +impl Zero for ContentSizes { + fn zero() -> Self { + Self { + min_content: Au::zero(), + max_content: Au::zero(), + } + } + + fn is_zero(&self) -> bool { + self.min_content.is_zero() && self.max_content.is_zero() + } +} + impl Add for ContentSizes { type Output = Self; diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index f34a1139bc27..6404b3a9ff74 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::ops::Range; + use app_units::{Au, MAX_AU}; use log::warn; use servo_arc::Arc; @@ -52,17 +54,32 @@ impl CellLayout { } } +/// Information stored during the layout of rows. +#[derive(Clone, Debug, Default)] +struct RowLayout { + constrained: bool, + has_cell_with_span_greater_than_one: bool, + percent: Percentage, +} + +/// Information stored during the layout of columns. +#[derive(Clone, Debug, Default)] +struct ColumnLayout { + constrained: bool, + has_originating_cells: bool, +} + /// A helper struct that performs the layout of the box tree version /// of a table into the fragment tree version. This implements /// struct TableLayout<'a> { table: &'a Table, pbm: PaddingBorderMargin, - column_constrainedness: Vec, - column_has_originating_cell: Vec, - cell_measures: Vec>, + rows: Vec, + columns: Vec, + cell_measures: Vec>>, assignable_width: Au, - column_measures: Vec, + column_measures: Vec, distributed_column_widths: Vec, row_sizes: Vec, row_baselines: Vec, @@ -71,18 +88,22 @@ struct TableLayout<'a> { } #[derive(Clone, Debug)] -struct CellOrColumnMeasure { +struct CellOrTrackMeasure { content_sizes: ContentSizes, - percentage_width: Percentage, + percentage: Percentage, } -impl CellOrColumnMeasure { +impl Zero for CellOrTrackMeasure { fn zero() -> Self { Self { content_sizes: ContentSizes::zero(), - percentage_width: Percentage(0.), + percentage: Percentage(0.), } } + + fn is_zero(&self) -> bool { + self.content_sizes.is_zero() && self.percentage.is_zero() + } } impl<'a> TableLayout<'a> { @@ -90,8 +111,8 @@ impl<'a> TableLayout<'a> { Self { table, pbm: PaddingBorderMargin::zero(), - column_constrainedness: Vec::new(), - column_has_originating_cell: Vec::new(), + rows: Vec::new(), + columns: Vec::new(), cell_measures: Vec::new(), assignable_width: Au::zero(), column_measures: Vec::new(), @@ -112,13 +133,15 @@ impl<'a> TableLayout<'a> { containing_block: &ContainingBlock, ) { let writing_mode = containing_block.style.writing_mode; - self.compute_column_constrainedness_and_has_originating_cells(writing_mode); + self.compute_track_constrainedness_and_has_originating_cells(writing_mode); self.compute_cell_measures(layout_context, containing_block); self.compute_column_measures(containing_block.style.writing_mode); self.compute_table_width(containing_block); self.distributed_column_widths = self.distribute_width_to_columns(); - self.do_row_layout_first_pass(layout_context, containing_block, positioning_context); - self.distribute_height_to_rows(); + + self.layout_cells_in_row(layout_context, containing_block, positioning_context); + let first_layout_row_heights = self.do_first_row_layout(writing_mode); + self.compute_table_height_and_final_row_heights(first_layout_row_heights, containing_block); } /// This is an implementation of *Computing Cell Measures* from @@ -128,10 +151,11 @@ impl<'a> TableLayout<'a> { layout_context: &LayoutContext, containing_block: &ContainingBlock, ) { + let row_measures = vec![LogicalVec2::zero(); self.table.size.width]; + self.cell_measures = vec![row_measures; self.table.size.height]; + let writing_mode = containing_block.style.writing_mode; for row_index in 0..self.table.size.height { - let mut row_measures = vec![CellOrColumnMeasure::zero(); self.table.size.width]; - for column_index in 0..self.table.size.width { let cell = match self.table.slots[row_index][column_index] { TableSlot::Cell(ref cell) => cell, @@ -139,7 +163,7 @@ impl<'a> TableLayout<'a> { }; let (size, min_size, max_size) = get_sizes_from_style(&cell.style, writing_mode); - let content_sizes = cell + let inline_content_sizes = cell .contents .contents .inline_content_sizes(layout_context, writing_mode); @@ -148,16 +172,17 @@ impl<'a> TableLayout<'a> { // > The outer min-content width of a table-cell is max(min-width, min-content width) // > adjusted by the cell intrinsic offsets. - let mut outer_min_content_width = content_sizes.min_content.max(min_size.inline); - let mut outer_max_content_width = if !self.column_constrainedness[column_index] { + let mut outer_min_content_width = + inline_content_sizes.min_content.max(min_size.inline); + let mut outer_max_content_width = if !self.columns[column_index].constrained { // > The outer max-content width of a table-cell in a non-constrained column is // > max(min-width, width, min-content width, min(max-width, max-content width)) // > adjusted by the cell intrinsic offsets. min_size .inline .max(size.inline) - .max(content_sizes.min_content) - .max(max_size.inline.min(content_sizes.max_content)) + .max(inline_content_sizes.min_content) + .max(max_size.inline.min(inline_content_sizes.max_content)) } else { // > The outer max-content width of a table-cell in a constrained column is // > max(min-width, width, min-content width, min(max-width, width)) adjusted by the @@ -165,30 +190,63 @@ impl<'a> TableLayout<'a> { min_size .inline .max(size.inline) - .max(content_sizes.min_content) + .max(inline_content_sizes.min_content) .max(max_size.inline.min(size.inline)) }; - let inline_padding_border_sum = Au::from( - cell.style - .padding(writing_mode) - .percentages_relative_to(Length::zero()) - .inline_sum() + - cell.style.border_width(writing_mode).inline_sum(), - ); + let padding = cell + .style + .padding(writing_mode) + .percentages_relative_to(Length::zero()); + let border = cell.style.border_width(writing_mode); + + let inline_padding_border_sum = + Au::from(padding.inline_sum() + border.inline_sum()); outer_min_content_width += inline_padding_border_sum; outer_max_content_width += inline_padding_border_sum; - row_measures[column_index] = CellOrColumnMeasure { + let inline_measure = CellOrTrackMeasure { content_sizes: ContentSizes { min_content: outer_min_content_width, max_content: outer_max_content_width, }, - percentage_width: percentage_contribution.inline, + percentage: percentage_contribution.inline, + }; + + // These calculations do not take into account the `min-content` and `max-content` + // sizes. These sizes are incorporated after the first row layout pass, when the + // block size of the layout is known. + // + // TODO: Is it correct to use the block size as the minimum of the `outer min + // content height` here? The specification doesn't mention this, but it does cause + // a test to pass. + let mut outer_min_content_height = min_size.block.max(size.block); + let mut outer_max_content_height = if !self.rows[row_index].constrained { + min_size.block.max(size.block) + } else { + min_size + .block + .max(size.block) + .max(max_size.block.min(size.block)) }; - } - self.cell_measures.push(row_measures); + let block_padding_border_sum = Au::from(padding.block_sum() + border.block_sum()); + outer_min_content_height += block_padding_border_sum; + outer_max_content_height += block_padding_border_sum; + + let block_measure = CellOrTrackMeasure { + content_sizes: ContentSizes { + min_content: outer_min_content_height, + max_content: outer_max_content_height, + }, + percentage: percentage_contribution.block, + }; + + self.cell_measures[row_index][column_index] = LogicalVec2 { + inline: inline_measure, + block: block_measure, + }; + } } } @@ -197,14 +255,48 @@ impl<'a> TableLayout<'a> { /// > A column is constrained if its corresponding table-column-group (if any), its /// > corresponding table-column (if any), or any of the cells spanning only that /// > column has a computed width that is not "auto", and is not a percentage. - fn compute_column_constrainedness_and_has_originating_cells( + fn compute_track_constrainedness_and_has_originating_cells( &mut self, writing_mode: WritingMode, ) { + self.rows = vec![RowLayout::default(); self.table.size.height]; + self.columns = vec![ColumnLayout::default(); self.table.size.width]; + for column_index in 0..self.table.size.width { - let mut column_constrained = false; - let mut column_has_originating_cell = false; + if let Some(column) = self.table.columns.get(column_index) { + if !column.style.box_size(writing_mode).inline.is_auto() { + self.columns[column_index].constrained = true; + continue; + } + if let Some(column_group_index) = column.group_index { + let column_group = &self.table.column_groups[column_group_index]; + if !column_group.style.box_size(writing_mode).inline.is_auto() { + self.columns[column_index].constrained = true; + continue; + } + } + self.columns[column_index].constrained = false; + } + } + for row_index in 0..self.table.size.height { + if let Some(row) = self.table.rows.get(row_index) { + if !row.style.box_size(writing_mode).block.is_auto() { + self.rows[row_index].constrained = true; + continue; + } + if let Some(row_group_index) = row.group_index { + let row_group = &self.table.row_groups[row_group_index]; + if !row_group.style.box_size(writing_mode).block.is_auto() { + self.rows[row_index].constrained = true; + continue; + } + } + } + self.rows[row_index].constrained = false; + } + + for column_index in 0..self.table.size.width { for row_index in 0..self.table.size.height { let coords = TableSlotCoordinates::new(column_index, row_index); let cell_constrained = match self.table.resolve_first_cell(coords) { @@ -217,13 +309,20 @@ impl<'a> TableLayout<'a> { .unwrap_or(false), _ => false, }; - column_has_originating_cell = column_has_originating_cell || + + let rowspan_greater_than_1 = match self.table.slots[row_index][column_index] { + TableSlot::Cell(ref cell) => cell.rowspan > 1, + _ => false, + }; + + self.rows[row_index].has_cell_with_span_greater_than_one |= rowspan_greater_than_1; + self.rows[row_index].constrained |= cell_constrained; + + let has_originating_cell = matches!(self.table.get_slot(coords), Some(TableSlot::Cell(_))); - column_constrained = column_constrained || cell_constrained; + self.columns[column_index].has_originating_cells |= has_originating_cell; + self.columns[column_index].constrained |= cell_constrained; } - self.column_constrainedness.push(column_constrained); - self.column_has_originating_cell - .push(column_has_originating_cell); } } @@ -281,16 +380,12 @@ impl<'a> TableLayout<'a> { // This takes the max of `min_content`, `max_content`, and // intrinsic percentage width as described above. - let cell_measure = &self.cell_measures[row_index][column_index]; + let cell_measure = &self.cell_measures[row_index][column_index].inline; column_measure .content_sizes .max_assign(cell_measure.content_sizes); - column_measure.percentage_width = Percentage( - column_measure - .percentage_width - .0 - .max(cell_measure.percentage_width.0), - ); + column_measure.percentage = + Percentage(column_measure.percentage.0.max(cell_measure.percentage.0)); } column_measures.push(column_measure); @@ -314,11 +409,11 @@ impl<'a> TableLayout<'a> { for column_index in 0..self.table.size.width { let column_measure = &mut column_measures[column_index]; let final_intrinsic_percentage_width = column_measure - .percentage_width + .percentage .0 .min(100. - total_intrinsic_percentage_width); total_intrinsic_percentage_width += final_intrinsic_percentage_width; - column_measure.percentage_width = Percentage(final_intrinsic_percentage_width); + column_measure.percentage = Percentage(final_intrinsic_percentage_width); } self.column_measures = column_measures; @@ -327,8 +422,8 @@ impl<'a> TableLayout<'a> { fn compute_content_sizes_for_columns_with_span_up_to_n( &self, n: usize, - old_column_measures: &[CellOrColumnMeasure], - ) -> (usize, Vec) { + old_column_measures: &[CellOrTrackMeasure], + ) -> (usize, Vec) { let mut next_span_n = usize::MAX; let mut new_content_sizes_for_columns = Vec::new(); let border_spacing = self.table.border_spacing(); @@ -354,7 +449,8 @@ impl<'a> TableLayout<'a> { _ => continue, }; - let cell_measures = &self.cell_measures[resolved_coords.y][resolved_coords.x]; + let cell_measures = + &self.cell_measures[resolved_coords.y][resolved_coords.x].inline; let cell_inline_content_sizes = cell_measures.content_sizes; let columns_spanned = resolved_coords.x..resolved_coords.x + cell.colspan; @@ -485,9 +581,7 @@ impl<'a> TableLayout<'a> { // > Otherwise, it is the largest of the contributions of the cells in the column // > whose colSpan is N, where the contribution of a cell is the result of taking // > the following steps: - if old_column_measure.percentage_width.0 <= 0. && - cell_measures.percentage_width.0 != 0. - { + if old_column_measure.percentage.0 <= 0. && cell_measures.percentage.0 != 0. { // > 1. Start with the percentage contribution of the cell. // > 2. Subtract the intrinsic percentage width of the column based on cells // > of span up to N-1 of all columns that the cell spans. If this gives a @@ -496,13 +590,13 @@ impl<'a> TableLayout<'a> { let other_column_percentages_sum = (columns_spanned).fold(0., |sum, spanned_column_index| { let spanned_column_percentage = - old_column_measures[spanned_column_index].percentage_width; + old_column_measures[spanned_column_index].percentage; if spanned_column_percentage.0 == 0. { spanned_columns_with_zero += 1; } sum + spanned_column_percentage.0 }); - let step_2 = (cell_measures.percentage_width - + let step_2 = (cell_measures.percentage - Percentage(other_column_percentages_sum)) .clamp_to_non_negative(); @@ -521,9 +615,9 @@ impl<'a> TableLayout<'a> { Percentage(new_column_intrinsic_percentage_width.0.max(step_3)); } } - new_content_sizes_for_columns.push(CellOrColumnMeasure { + new_content_sizes_for_columns.push(CellOrTrackMeasure { content_sizes: new_column_content_sizes, - percentage_width: new_column_intrinsic_percentage_width, + percentage: new_column_intrinsic_percentage_width, }); } (next_span_n, new_content_sizes_for_columns) @@ -636,16 +730,14 @@ impl<'a> TableLayout<'a> { let column_measure = &self.column_measures[column_idx]; let min_content_width = column_measure.content_sizes.min_content; let max_content_width = column_measure.content_sizes.max_content; - let constrained = self.column_constrainedness[column_idx]; + let constrained = self.columns[column_idx].constrained; let ( min_content_percentage_sizing_guess, min_content_specified_sizing_guess, max_content_sizing_guess, - ) = if !column_measure.percentage_width.is_zero() { - let resolved = self - .assignable_width - .scale_by(column_measure.percentage_width.0); + ) = if !column_measure.percentage.is_zero() { + let resolved = self.assignable_width.scale_by(column_measure.percentage.0); let percent_guess = min_content_width.max(resolved); (percent_guess, percent_guess, percent_guess) } else if constrained { @@ -746,11 +838,11 @@ impl<'a> TableLayout<'a> { let extra_inline_size = self.assignable_width - column_sizes_sum; let has_originating_cells = - |column_index: &usize| self.column_has_originating_cell[*column_index]; - let is_constrained = |column_index: &usize| self.column_constrainedness[*column_index]; + |column_index: &usize| self.columns[*column_index].has_originating_cells; + let is_constrained = |column_index: &usize| self.columns[*column_index].constrained; let is_unconstrained = |column_index: &usize| !is_constrained(column_index); let has_percent_greater_than_zero = - |column_index: &usize| self.column_measures[*column_index].percentage_width.0 > 0.; + |column_index: &usize| self.column_measures[*column_index].percentage.0 > 0.; let has_percent_zero = |column_index: &usize| !has_percent_greater_than_zero(column_index); let has_max_content = |column_index: &usize| { self.column_measures[*column_index] @@ -846,13 +938,12 @@ impl<'a> TableLayout<'a> { let columns_with_percentage = all_columns.clone().filter(has_percent_greater_than_zero); let total_percent = columns_with_percentage .clone() - .map(|column_index| self.column_measures[column_index].percentage_width.0) + .map(|column_index| self.column_measures[column_index].percentage.0) .sum::(); if total_percent > 0. { for column_index in columns_with_percentage { - column_sizes[column_index] += extra_inline_size.scale_by( - self.column_measures[column_index].percentage_width.0 / total_percent, - ); + column_sizes[column_index] += extra_inline_size + .scale_by(self.column_measures[column_index].percentage.0 / total_percent); } return; } @@ -882,7 +973,7 @@ impl<'a> TableLayout<'a> { /// This is an implementation of *Row layout (first pass)* from /// . - fn do_row_layout_first_pass( + fn layout_cells_in_row( &mut self, layout_context: &LayoutContext, containing_block: &ContainingBlock, @@ -930,86 +1021,349 @@ impl<'a> TableLayout<'a> { &mut positioning_context, &containing_block_for_children, ); + + let content_size_from_layout = ContentSizes { + min_content: layout.content_block_size, + max_content: layout.content_block_size, + }; + self.cell_measures[row_index][column_index] + .block + .content_sizes + .max_assign(content_size_from_layout); + cells_laid_out_row.push(Some(CellLayout { layout, padding, border, positioning_context, - })) + })); } self.cells_laid_out.push(cells_laid_out_row); } } - fn distribute_height_to_rows(&mut self) { + /// Do the first layout of a table row, after laying out the cells themselves. This is + /// more or less and implementation of . + fn do_first_row_layout(&mut self, writing_mode: WritingMode) -> Vec { + let mut row_sizes = (0..self.table.size.height) + .map(|row_index| { + let (mut max_ascent, mut max_descent, mut max_row_height) = + (Au::zero(), Au::zero(), Au::zero()); + + for column_index in 0..self.table.size.width { + let cell = match self.table.slots[row_index][column_index] { + TableSlot::Cell(ref cell) => cell, + _ => continue, + }; + + let layout = match self.cells_laid_out[row_index][column_index] { + Some(ref layout) => layout, + None => { + warn!( + "Did not find a layout at a slot index with an originating cell." + ); + continue; + }, + }; + + let outer_block_size = layout.outer_block_size(); + if cell.rowspan == 1 { + max_row_height = max_row_height.max(outer_block_size); + } + + if cell.effective_vertical_align() == VerticalAlignKeyword::Baseline { + let ascent = layout.ascent(); + let border_padding_start = + layout.border.block_start + layout.padding.block_start; + let border_padding_end = layout.border.block_end + layout.padding.block_end; + max_ascent = max_ascent.max(ascent + border_padding_start.into()); + + // Only take into account the descent of this cell if doesn't span + // rows. The descent portion of the cell in cells that do span rows + // may extend into other rows. + if cell.rowspan == 1 { + max_descent = max_descent.max( + layout.layout.content_block_size - ascent + + border_padding_end.into(), + ); + } + } + } + self.row_baselines.push(max_ascent); + max_row_height.max(max_ascent + max_descent) + }) + .collect(); + self.calculate_row_sizes_after_first_layout(&mut row_sizes, writing_mode); + row_sizes + } + + /// After doing layout of table rows, calculate final row size and distribute space across + /// rowspanned cells. This follows the implementation of LayoutNG and the priority + /// agorithm described at . + fn calculate_row_sizes_after_first_layout( + &mut self, + row_sizes: &mut Vec, + writing_mode: WritingMode, + ) { + let mut cells_to_distribute = Vec::new(); + let mut total_percentage = 0.; for row_index in 0..self.table.size.height { - let (mut max_ascent, mut max_descent, mut max_row_height) = - (Au::zero(), Au::zero(), Au::zero()); + let row_measure = self + .table + .get_row_measure_for_row_at_index(writing_mode, row_index); + row_sizes[row_index] = row_sizes[row_index].max(row_measure.content_sizes.min_content); + let mut percentage = match self.table.rows.get(row_index) { + Some(row) => { + get_size_percentage_contribution_from_style(&row.style, writing_mode) + .block + .0 + }, + None => 0., + }; for column_index in 0..self.table.size.width { - let coords = TableSlotCoordinates::new(column_index, row_index); + let cell_percentage = self.cell_measures[row_index][column_index] + .block + .percentage + .0; + percentage = percentage.max(cell_percentage); + let cell_measure = &self.cell_measures[row_index][column_index].block; let cell = match self.table.slots[row_index][column_index] { - TableSlot::Cell(ref cell) => cell, - TableSlot::Spanned(ref spanned_cells) if spanned_cells[0].y != 0 => { - let offset = spanned_cells[0]; - let origin = coords - offset; - - // We only allocate the remaining space for the last row of the rowspanned cell. - if let Some(TableSlot::Cell(origin_cell)) = self.table.get_slot(origin) { - if origin_cell.rowspan != offset.y + 1 { - continue; - } - } - - // This is all of the rows that are spanned except this one. - let used_block_size = (origin.y..coords.y) - .map(|row_index| self.row_sizes[row_index]) - .fold(Au::zero(), |sum, size| sum + size); - if let Some(layout) = &self.cells_laid_out[origin.y][origin.x] { - max_row_height = - max_row_height.max(layout.outer_block_size() - used_block_size); - } + TableSlot::Cell(ref cell) if cell.rowspan > 1 => cell, + TableSlot::Cell(_) => { + // If this is an originating cell, that isn't spanning, then we make sure the row is + // at least big enough to hold the cell. + row_sizes[row_index] = + row_sizes[row_index].max(cell_measure.content_sizes.max_content); continue; }, _ => continue, }; - let layout = match self.cells_laid_out[row_index][column_index] { - Some(ref layout) => layout, - None => { - warn!("Did not find a layout at a slot index with an originating cell."); - continue; - }, - }; + cells_to_distribute.push(RowspanToDistribute { + coordinates: TableSlotCoordinates::new(column_index, row_index), + cell, + measure: cell_measure, + }); + } - let outer_block_size = layout.outer_block_size(); - if cell.rowspan == 1 { - max_row_height = max_row_height.max(outer_block_size); - } + self.rows[row_index].percent = Percentage(percentage.min(100. - total_percentage)); + total_percentage += self.rows[row_index].percent.0; + } - if cell.effective_vertical_align() == VerticalAlignKeyword::Baseline { - let ascent = layout.ascent(); - let border_padding_start = - layout.border.block_start + layout.padding.block_start; - let border_padding_end = layout.border.block_end + layout.padding.block_end; - max_ascent = max_ascent.max(ascent + border_padding_start.into()); - - // Only take into account the descent of this cell if doesn't span - // rows. The descent portion of the cell in cells that do span rows - // will be allocated to the other rows that it spans. - if cell.rowspan == 1 { - max_descent = max_descent.max( - layout.layout.content_block_size - ascent + border_padding_end.into(), - ); + cells_to_distribute.sort_by(|a, b| { + if a.range() == b.range() { + return a + .measure + .content_sizes + .min_content + .cmp(&b.measure.content_sizes.min_content); + } + if a.fully_encloses(b) { + return std::cmp::Ordering::Greater; + } + if b.fully_encloses(a) { + return std::cmp::Ordering::Less; + } + a.coordinates.y.cmp(&b.coordinates.y) + }); + + for rowspan_to_distribute in cells_to_distribute { + let rows_spanned = rowspan_to_distribute.range(); + let current_rows_size: Au = rows_spanned.clone().map(|index| row_sizes[index]).sum(); + let border_spacing_spanned = + self.table.border_spacing().block * (rows_spanned.len() - 1) as i32; + let excess_size = (rowspan_to_distribute.measure.content_sizes.min_content - + current_rows_size - + border_spacing_spanned) + .max(Au::zero()); + + self.distribute_extra_size_to_rows( + excess_size, + rows_spanned, + row_sizes, + None, + true, /* rowspan_distribution */ + ); + } + } + + /// An implementation of the same extra block size distribution algorithm used in + /// LayoutNG and described at . + fn distribute_extra_size_to_rows( + &self, + mut excess_size: Au, + track_range: Range, + track_sizes: &mut Vec, + percentage_resolution_size: Option, + rowspan_distribution: bool, + ) { + if excess_size.is_zero() { + return; + } + + let is_constrained = |track_index: &usize| self.rows[*track_index].constrained; + let is_unconstrained = |track_index: &usize| !is_constrained(track_index); + let is_empty: Vec = track_sizes.iter().map(|size| size.is_zero()).collect(); + let is_not_empty = |track_index: &usize| !is_empty[*track_index]; + let other_row_that_starts_a_rowspan = |track_index: &usize| { + *track_index != track_range.start && + self.rows[*track_index].has_cell_with_span_greater_than_one + }; + + // If we have a table height (not during rowspan distribution), first distribute to rows + // that have percentage sizes proportionally to the size missing to reach the percentage + // of table height required. + if let Some(percentage_resolution_size) = percentage_resolution_size { + let get_percent_block_size_deficit = |row_index: usize, track_size: Au| { + let size_needed_for_percent = + percentage_resolution_size.scale_by(self.rows[row_index].percent.0 / 100.); + (size_needed_for_percent - track_size).max(Au::zero()) + }; + let percent_block_size_deficit: Au = track_range + .clone() + .map(|index| get_percent_block_size_deficit(index, track_sizes[index])) + .sum(); + let percent_distributable_block_size = percent_block_size_deficit.min(excess_size); + if percent_distributable_block_size > Au::zero() { + for track_index in track_range.clone() { + let row_deficit = + get_percent_block_size_deficit(track_index, track_sizes[track_index]); + if row_deficit > Au::zero() { + let ratio = + row_deficit.to_f32_px() / percent_block_size_deficit.to_f32_px(); + let size = percent_distributable_block_size.scale_by(ratio); + track_sizes[track_index] += size; + excess_size -= size; } } } + } + + // If this is rowspan distribution and there are rows other than the first row that have a + // cell with rowspan > 1, distribute the extra space equally to those rows. + if rowspan_distribution { + let rows_that_start_rowspan: Vec = track_range + .clone() + .filter(other_row_that_starts_a_rowspan) + .collect(); + if !rows_that_start_rowspan.is_empty() { + let scale = 1.0 / rows_that_start_rowspan.len() as f32; + for track_index in rows_that_start_rowspan.iter() { + track_sizes[*track_index] += excess_size.scale_by(scale); + } + return; + } + } + + // If there are unconstrained non-empty rows, grow them all proportionally to their current size. + let unconstrained_non_empty_rows: Vec = track_range + .clone() + .filter(is_unconstrained) + .filter(is_not_empty) + .collect(); + if !unconstrained_non_empty_rows.is_empty() { + let total_size: Au = unconstrained_non_empty_rows + .iter() + .map(|index| track_sizes[*index]) + .sum(); + for track_index in unconstrained_non_empty_rows.iter() { + let scale = track_sizes[*track_index].to_f32_px() / total_size.to_f32_px(); + track_sizes[*track_index] += excess_size.scale_by(scale); + } + return; + } + + let (non_empty_rows, empty_rows): (Vec, Vec) = + track_range.clone().partition(is_not_empty); + let only_have_empty_rows = empty_rows.len() == track_range.len(); + if !empty_rows.is_empty() { + // If this is rowspan distribution and there are only empty rows, just grow the + // last one. + if rowspan_distribution && only_have_empty_rows { + track_sizes[*empty_rows.last().unwrap()] += excess_size; + return; + } + + // Otherwise, if we only have empty rows or if all the non-empty rows are constrained, + // then grow the empty rows. + let non_empty_rows_all_constrained = !non_empty_rows.iter().any(is_unconstrained); + if only_have_empty_rows || non_empty_rows_all_constrained { + // If there are both unconstrained and constrained empty rows, only increase the + // size of the unconstrained ones, otherwise increase the size of all empty rows. + let mut rows_to_grow = &empty_rows; + let unconstrained_empty_rows: Vec = rows_to_grow + .iter() + .copied() + .filter(is_unconstrained) + .collect(); + if !unconstrained_empty_rows.is_empty() { + rows_to_grow = &unconstrained_empty_rows; + } + + // All empty rows that will grow equally. + let scale = 1.0 / rows_to_grow.len() as f32; + for track_index in rows_to_grow.iter() { + track_sizes[*track_index] += excess_size.scale_by(scale); + } + return; + } + } + + // If there are non-empty rows, they all grow in proportion to their current size, + // whether or not they are constrained. + if !non_empty_rows.is_empty() { + let total_size: Au = non_empty_rows.iter().map(|index| track_sizes[*index]).sum(); + for track_index in non_empty_rows.iter() { + let scale = track_sizes[*track_index].to_f32_px() / total_size.to_f32_px(); + track_sizes[*track_index] += excess_size.scale_by(scale); + } + } + } + + /// Given computed row sizes, compute the final block size of the table and distribute extra + /// block size to table rows. + fn compute_table_height_and_final_row_heights( + &mut self, + mut row_sizes: Vec, + containing_block: &ContainingBlock, + ) { + // The table content height is the maximum of the computed table height from style and the + // sum of computed row heights from row layout plus size from borders and spacing. + let table_height_from_style = self + .table + .style + .content_box_size(containing_block, &self.pbm) + .block + .auto_is(Length::zero) + .into(); - self.row_baselines.push(max_ascent); - self.row_sizes - .push(max_row_height.max(max_ascent + max_descent)); + let border_spacing = self.table.border_spacing(); + let border_and_spacing = self.pbm.border.block_sum() + + border_spacing.block * (self.table.size.height as i32 + 1); + let table_height_from_rows = row_sizes.iter().sum::() + border_and_spacing; + let final_table_height = table_height_from_rows.max(table_height_from_style); + + // If the table height is defined by the rows sizes, there is no extra space to distribute + // to rows. + if final_table_height == table_height_from_rows { + self.row_sizes = row_sizes; + return; } + + // There was extra block size added to the table from the table style, so distribute this + // extra space to rows using the same distribution algorithm used for distributing rowspan + // space. + // TODO: This should first distribute space to row groups and then to rows. + self.distribute_extra_size_to_rows( + final_table_height - table_height_from_rows, + 0..self.table.size.height, + &mut row_sizes, + Some(final_table_height), + false, /* rowspan_distribution */ + ); + self.row_sizes = row_sizes; } /// Lay out the table of this [`TableLayout`] into fragments. This should only be be called @@ -1372,17 +1726,17 @@ impl Table { &self, writing_mode: WritingMode, column_index: usize, - ) -> CellOrColumnMeasure { + ) -> CellOrTrackMeasure { let column = match self.columns.get(column_index) { Some(column) => column, - None => return CellOrColumnMeasure::zero(), + None => return CellOrTrackMeasure::zero(), }; let (size, min_size, max_size) = get_sizes_from_style(&column.style, writing_mode); let percentage_contribution = get_size_percentage_contribution_from_style(&column.style, writing_mode); - CellOrColumnMeasure { + CellOrTrackMeasure { content_sizes: ContentSizes { // > The outer min-content width of a table-column or table-column-group is // > max(min-width, width). @@ -1391,7 +1745,34 @@ impl Table { // > max(min-width, min(max-width, width)). max_content: min_size.inline.max(max_size.inline.min(size.inline)), }, - percentage_width: percentage_contribution.inline, + percentage: percentage_contribution.inline, + } + } + + fn get_row_measure_for_row_at_index( + &self, + writing_mode: WritingMode, + row_index: usize, + ) -> CellOrTrackMeasure { + let row = match self.rows.get(row_index) { + Some(row) => row, + None => return CellOrTrackMeasure::zero(), + }; + + let (size, min_size, max_size) = get_sizes_from_style(&row.style, writing_mode); + let percentage_contribution = + get_size_percentage_contribution_from_style(&row.style, writing_mode); + + CellOrTrackMeasure { + content_sizes: ContentSizes { + // > The outer min-content width of a table-column or table-column-group is + // > max(min-width, width). + min_content: min_size.inline.max(size.block), + // > The outer max-content width of a table-column or table-column-group is + // > max(min-width, min(max-width, width)). + max_content: min_size.inline.max(max_size.block.min(size.block)), + }, + percentage: percentage_contribution.block, } } @@ -1579,3 +1960,19 @@ fn get_sizes_from_style( (size, min_size, max_size) } + +struct RowspanToDistribute<'a> { + coordinates: TableSlotCoordinates, + cell: &'a TableSlotCell, + measure: &'a CellOrTrackMeasure, +} + +impl<'a> RowspanToDistribute<'a> { + fn range(&self) -> Range { + self.coordinates.y..self.coordinates.y + self.cell.rowspan + } + + fn fully_encloses(&self, other: &RowspanToDistribute) -> bool { + other.coordinates.y > self.coordinates.y && other.range().end < self.range().end + } +} diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-001.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-001.xht.ini deleted file mode 100644 index 6dd55ac5822f..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-001.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-001.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-002.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-002.xht.ini deleted file mode 100644 index a629c41c3ff3..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-002.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-002.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-003.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-003.xht.ini deleted file mode 100644 index 17c8547f40f9..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-003.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-003.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-004.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-004.xht.ini deleted file mode 100644 index c5691d934363..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-004.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-004.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-005.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-005.xht.ini deleted file mode 100644 index 5aac3a9de697..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-005.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-005.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-006.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-006.xht.ini deleted file mode 100644 index 02c70e63d3c7..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-006.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-006.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-007.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-007.xht.ini deleted file mode 100644 index c8380380f45a..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-007.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-007.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-013.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-013.xht.ini deleted file mode 100644 index 0825ac0e6356..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-013.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-013.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-014.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-014.xht.ini deleted file mode 100644 index a165964fbb84..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/clear-applies-to-014.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[clear-applies-to-014.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-013.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-013.xht.ini deleted file mode 100644 index 1ffb70c7a958..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-013.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[float-applies-to-013.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-014.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-014.xht.ini deleted file mode 100644 index c661f560878e..000000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/float-applies-to-014.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[float-applies-to-014.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/height-table-cell-001.xht.ini b/tests/wpt/meta/css/CSS2/tables/height-table-cell-001.xht.ini deleted file mode 100644 index 6fea2a4bc5e4..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/height-table-cell-001.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[height-table-cell-001.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/padding-applies-to-013a.xht.ini b/tests/wpt/meta/css/CSS2/tables/padding-applies-to-013a.xht.ini deleted file mode 100644 index a2a55d1df7cf..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/padding-applies-to-013a.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[padding-applies-to-013a.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/row-visibility-002.xht.ini b/tests/wpt/meta/css/CSS2/tables/row-visibility-002.xht.ini deleted file mode 100644 index 61fbc5acc76c..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/row-visibility-002.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[row-visibility-002.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/separated-border-model-004e.xht.ini b/tests/wpt/meta/css/CSS2/tables/separated-border-model-004e.xht.ini deleted file mode 100644 index 74c677d679b4..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/separated-border-model-004e.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[separated-border-model-004e.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-cell-001.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-cell-001.xht.ini deleted file mode 100644 index 95737952dc8d..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-cell-001.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-cell-001.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008a.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008a.xht.ini deleted file mode 100644 index c8bbd0b7d36f..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008a.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-height-algorithm-008a.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008b.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008b.xht.ini deleted file mode 100644 index 389f61f0eaf8..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008b.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-height-algorithm-008b.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008c.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008c.xht.ini deleted file mode 100644 index aa34e356889b..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-height-algorithm-008c.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-height-algorithm-008c.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026a.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026a.xht.ini deleted file mode 100644 index 40d8743719eb..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026a.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-visual-layout-026a.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026b.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026b.xht.ini deleted file mode 100644 index d9f68cbf35fb..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026b.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-visual-layout-026b.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026c.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026c.xht.ini deleted file mode 100644 index 478352f6c0bc..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026c.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-visual-layout-026c.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026d.xht.ini b/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026d.xht.ini deleted file mode 100644 index 20361d0b6b1e..000000000000 --- a/tests/wpt/meta/css/CSS2/tables/table-visual-layout-026d.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[table-visual-layout-026d.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/border-spacing-included-in-sizes-001.html.ini b/tests/wpt/meta/css/css-tables/border-spacing-included-in-sizes-001.html.ini deleted file mode 100644 index 39c19148310c..000000000000 --- a/tests/wpt/meta/css/css-tables/border-spacing-included-in-sizes-001.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[border-spacing-included-in-sizes-001.html] - [tbody 1] - expected: FAIL - - [tbody 2] - expected: FAIL - - [tbody 3] - expected: FAIL - - [tfoot tr 4] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/bounding-box-computation-1.html.ini b/tests/wpt/meta/css/css-tables/bounding-box-computation-1.html.ini deleted file mode 100644 index 9f6ca8b767fe..000000000000 --- a/tests/wpt/meta/css/css-tables/bounding-box-computation-1.html.ini +++ /dev/null @@ -1,15 +0,0 @@ -[bounding-box-computation-1.html] - [Table-cell is 100px tall] - expected: FAIL - - [Table-row is 100px tall] - expected: FAIL - - [Table-row-group is 100px tall] - expected: FAIL - - [Table-column is 100px tall] - expected: FAIL - - [Table-column-group is 100px tall] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/chrome-rowspan-bug.html.ini b/tests/wpt/meta/css/css-tables/chrome-rowspan-bug.html.ini deleted file mode 100644 index c96dbebfd6d2..000000000000 --- a/tests/wpt/meta/css/css-tables/chrome-rowspan-bug.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[chrome-rowspan-bug.html] - [table tracks correct use of rowspan] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/column-track-merging.html.ini b/tests/wpt/meta/css/css-tables/column-track-merging.html.ini index 4a4c2714d9c5..8d744aaf5eaf 100644 --- a/tests/wpt/meta/css/css-tables/column-track-merging.html.ini +++ b/tests/wpt/meta/css/css-tables/column-track-merging.html.ini @@ -2,9 +2,6 @@ [main table 1] expected: FAIL - [main table 2] - expected: FAIL - [main table 4] expected: FAIL @@ -31,3 +28,6 @@ [main table 3] expected: FAIL + + [main table 2] + expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/fixup-dynamic-anonymous-table-001.html.ini b/tests/wpt/meta/css/css-tables/fixup-dynamic-anonymous-table-001.html.ini deleted file mode 100644 index 1854edfa10fc..000000000000 --- a/tests/wpt/meta/css/css-tables/fixup-dynamic-anonymous-table-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[fixup-dynamic-anonymous-table-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-0.html.ini b/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-0.html.ini index d64e763c0457..946a14914ea8 100644 --- a/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-0.html.ini +++ b/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-0.html.ini @@ -1,10 +1,4 @@ [computing-row-measure-0.html] - [Checking intermediate min-content height for span 1 (1)] - expected: FAIL - - [Checking intermediate min-content height for span 1 (3)] - expected: FAIL - [Checking intermediate min-content height for span 1 (2)] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-1.html.ini b/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-1.html.ini index 1d47684a4eac..026517a0c8fe 100644 --- a/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-1.html.ini +++ b/tests/wpt/meta/css/css-tables/height-distribution/computing-row-measure-1.html.ini @@ -1,9 +1,9 @@ [computing-row-measure-1.html] - [Checking intermediate min-content width for span 2 (1)] + [Checking intermediate min-content width for span 2 (4)] expected: FAIL - [Checking intermediate min-content width for span 2 (2)] + [Checking intermediate min-content width for span 2 (1)] expected: FAIL - [Checking intermediate min-content width for span 2 (4)] + [Checking intermediate min-content width for span 2 (2)] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/html5-table-formatting-2.html.ini b/tests/wpt/meta/css/css-tables/html5-table-formatting-2.html.ini index cba3da031314..14db94c0dff0 100644 --- a/tests/wpt/meta/css/css-tables/html5-table-formatting-2.html.ini +++ b/tests/wpt/meta/css/css-tables/html5-table-formatting-2.html.ini @@ -11,26 +11,14 @@ [Border-spacing is added between any two unmerged columns (2)] expected: FAIL - [Border-spacing is added between any two unmerged rows (2)] - expected: FAIL - [Border-spacing is added between any two unmerged columns (3)] expected: FAIL - [Border-spacing is added between any two unmerged rows (3)] - expected: FAIL - [Border-spacing is added between any two unmerged columns (4)] expected: FAIL - [Border-spacing is added between any two unmerged rows (4)] - expected: FAIL - [Border-spacing is added between any two unmerged columns (5)] expected: FAIL - [Border-spacing is added between any two unmerged rows (5)] - expected: FAIL - [Explicitely defined rows are not merged] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/paint/col-change-span-bg-invalidation-002.html.ini b/tests/wpt/meta/css/css-tables/paint/col-change-span-bg-invalidation-002.html.ini deleted file mode 100644 index 32206aee5389..000000000000 --- a/tests/wpt/meta/css/css-tables/paint/col-change-span-bg-invalidation-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[col-change-span-bg-invalidation-002.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/subpixel-table-cell-height-001.html.ini b/tests/wpt/meta/css/css-tables/subpixel-table-cell-height-001.html.ini deleted file mode 100644 index 7bf39a62f637..000000000000 --- a/tests/wpt/meta/css/css-tables/subpixel-table-cell-height-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[subpixel-table-cell-height-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/subpixel-table-cell-width-002.html.ini b/tests/wpt/meta/css/css-tables/subpixel-table-cell-width-002.html.ini deleted file mode 100644 index aef4e406cdb9..000000000000 --- a/tests/wpt/meta/css/css-tables/subpixel-table-cell-width-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[subpixel-table-cell-width-002.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/table-cell-scroll-height.html.ini b/tests/wpt/meta/css/css-tables/table-cell-scroll-height.html.ini deleted file mode 100644 index 343fc4d9bad5..000000000000 --- a/tests/wpt/meta/css/css-tables/table-cell-scroll-height.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[table-cell-scroll-height.html] - [scrollHeight on scrollable table cell] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/table-model-fixup.html.ini b/tests/wpt/meta/css/css-tables/table-model-fixup.html.ini index cc92bd8ce4a0..481c9dbffee4 100644 --- a/tests/wpt/meta/css/css-tables/table-model-fixup.html.ini +++ b/tests/wpt/meta/css/css-tables/table-model-fixup.html.ini @@ -2,9 +2,6 @@ [2.1. An anonymous table-row box must be generated around each sequence of consecutive children of a table-root box which are not proper table child boxes. (1/2)] expected: FAIL - [2.1. An anonymous table-row box must be generated around each sequence of consecutive children of a table-root box which are not proper table child boxes. (2/2)] - expected: FAIL - [2.2. An anonymous table-row box must be generated around each sequence of consecutive children of a table-row-grouping box which are not table-row boxes. (1/3)] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/baseline-td.html.ini b/tests/wpt/meta/css/css-tables/tentative/baseline-td.html.ini index b5553b3d6211..194bf59ed5b5 100644 --- a/tests/wpt/meta/css/css-tables/tentative/baseline-td.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/baseline-td.html.ini @@ -2,14 +2,5 @@ [table, .display-table 1] expected: FAIL - [table, .display-table 2] - expected: FAIL - [table, .display-table 3] expected: FAIL - - [table, .display-table 4] - expected: FAIL - - [table, .display-table 5] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/colspan-redistribution.html.ini b/tests/wpt/meta/css/css-tables/tentative/colspan-redistribution.html.ini index 56f4a2c45afe..318cca02b300 100644 --- a/tests/wpt/meta/css/css-tables/tentative/colspan-redistribution.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/colspan-redistribution.html.ini @@ -14,9 +14,6 @@ [table 6] expected: FAIL - [table 7] - expected: FAIL - [table 9] expected: FAIL @@ -85,3 +82,6 @@ [table 8] expected: FAIL + + [table 7] + expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/rowspan-height-redistribution.html.ini b/tests/wpt/meta/css/css-tables/tentative/rowspan-height-redistribution.html.ini index 97ade62c85ae..c415da3c2c6f 100644 --- a/tests/wpt/meta/css/css-tables/tentative/rowspan-height-redistribution.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/rowspan-height-redistribution.html.ini @@ -1,4 +1,16 @@ [rowspan-height-redistribution.html] + [table 7] + expected: FAIL + + [table 8] + expected: FAIL + + [table 22] + expected: FAIL + + [table 23] + expected: FAIL + [table 2] expected: FAIL @@ -14,13 +26,19 @@ [table 6] expected: FAIL - [table 7] + [table 9] expected: FAIL - [table 8] + [table 10] expected: FAIL - [table 9] + [table 11] + expected: FAIL + + [table 12] + expected: FAIL + + [table 13] expected: FAIL [table 14] @@ -29,23 +47,20 @@ [table 15] expected: FAIL + [table 16] + expected: FAIL + [table 17] expected: FAIL [table 18] expected: FAIL - [table 19] + [table 20] expected: FAIL [table 21] expected: FAIL - [table 22] - expected: FAIL - - [table 23] - expected: FAIL - - [table 20] + [table 24] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/table-height-redistribution.html.ini b/tests/wpt/meta/css/css-tables/tentative/table-height-redistribution.html.ini index 0f1ce3b5b1dd..99e920f9e6c5 100644 --- a/tests/wpt/meta/css/css-tables/tentative/table-height-redistribution.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/table-height-redistribution.html.ini @@ -56,9 +56,6 @@ [table 23] expected: FAIL - [table 24] - expected: FAIL - [table 25] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed-padding.html.ini b/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed-padding.html.ini index 97ea3536a7ec..a7dad566c57c 100644 --- a/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed-padding.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed-padding.html.ini @@ -14,9 +14,6 @@ [table 6] expected: FAIL - [table 7] - expected: FAIL - [table 9] expected: FAIL @@ -37,3 +34,6 @@ [table 15] expected: FAIL + + [table 7] + expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed.html.ini b/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed.html.ini index 4d7a4167346d..3e041fb7d4f6 100644 --- a/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/table-width-redistribution-fixed.html.ini @@ -26,9 +26,6 @@ [table 11] expected: FAIL - [table 12] - expected: FAIL - [table 14] expected: FAIL @@ -58,3 +55,6 @@ [table 26] expected: FAIL + + [table 12] + expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/tbody-height-redistribution.html.ini b/tests/wpt/meta/css/css-tables/tentative/tbody-height-redistribution.html.ini index 78a97083bfc2..5051e659e62d 100644 --- a/tests/wpt/meta/css/css-tables/tentative/tbody-height-redistribution.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/tbody-height-redistribution.html.ini @@ -14,9 +14,6 @@ [table 5] expected: FAIL - [table 6] - expected: FAIL - [table 7] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-001.html.ini b/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-001.html.ini index 554b536e7b8d..3bfa8522de13 100644 --- a/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-001.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-001.html.ini @@ -11,9 +11,6 @@ [table 6] expected: FAIL - [table 7] - expected: FAIL - [table 8] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-003.html.ini b/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-003.html.ini index 67959ec278c8..6764cfe02041 100644 --- a/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-003.html.ini +++ b/tests/wpt/meta/css/css-tables/tentative/td-box-sizing-003.html.ini @@ -5,9 +5,6 @@ [table 9] expected: FAIL - [table 11] - expected: FAIL - [table 5] expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/visibility-collapse-row-005.html.ini b/tests/wpt/meta/css/css-tables/visibility-collapse-row-005.html.ini new file mode 100644 index 000000000000..b2665eaf5908 --- /dev/null +++ b/tests/wpt/meta/css/css-tables/visibility-collapse-row-005.html.ini @@ -0,0 +1,6 @@ +[visibility-collapse-row-005.html] + [collapsed row should not contribute to overflow] + expected: FAIL + + [collapsed section should not contribute to overflow] + expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/width-distribution/computing-column-measure-1.html.ini b/tests/wpt/meta/css/css-tables/width-distribution/computing-column-measure-1.html.ini index c64ccb63ba95..5753a6028792 100644 --- a/tests/wpt/meta/css/css-tables/width-distribution/computing-column-measure-1.html.ini +++ b/tests/wpt/meta/css/css-tables/width-distribution/computing-column-measure-1.html.ini @@ -1,12 +1,6 @@ [computing-column-measure-1.html] - [Checking intermediate min-content height for span 2 (1)] + [Checking intermediate min-content height for span 2 (4)] expected: FAIL [Checking intermediate min-content height for span 2 (2)] expected: FAIL - - [Checking intermediate min-content height for span 2 (3)] - expected: FAIL - - [Checking intermediate min-content height for span 2 (4)] - expected: FAIL