From 78fe461ff28ea800994686b68878d4825016b5f3 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 14 Mar 2024 11:33:42 +0100 Subject: [PATCH] layout: Properly parent table-row and table-row-group (#31619) Put table cell content fragments into a hieararchy of fragments that include their table row and table row group fragments. This ensures that things like relative positioning and transforms set on rows and row groups properly affect cells and cell content. Co-authored-by: Oriol Brufau --- components/layout_2020/display_list/mod.rs | 40 +- .../layout_2020/fragment_tree/box_fragment.rs | 26 +- components/layout_2020/geom.rs | 32 +- components/layout_2020/table/construct.rs | 32 +- components/layout_2020/table/layout.rs | 428 +++++++++++++----- .../CSS2/tables/row-visibility-002.xht.ini | 2 + .../position-relative-012.html.ini | 2 - .../css-tables/table-model-fixup-2.html.ini | 3 + ...ction-no-tbody-fixed-distribution.html.ini | 2 - ...ion-no-tbody-percent-distribution.html.ini | 2 - ...-transformable-table-footer-group.html.ini | 2 - ...-transformable-table-header-group.html.ini | 2 - ...orm-transformable-table-row-group.html.ini | 2 - ...transform-transformable-table-row.html.ini | 2 - ...med-tbody-contains-fixed-position.html.ini | 2 - ...med-tfoot-contains-fixed-position.html.ini | 2 - ...med-thead-contains-fixed-position.html.ini | 2 - ...formed-tr-contains-fixed-position.html.ini | 2 - ...ansformed-tr-percent-height-child.html.ini | 2 - .../css/css-ui/text-overflow-025.html.ini | 2 + .../elementsFromPoint-table.html.ini | 6 + .../tr-transform-and-will-change.html.ini | 2 + ...ble-cell-width-calculation-abspos.html.ini | 2 + 23 files changed, 439 insertions(+), 160 deletions(-) create mode 100644 tests/wpt/meta/css/CSS2/tables/row-visibility-002.xht.ini delete mode 100644 tests/wpt/meta/css/css-position/position-relative-012.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/tentative/section-no-tbody-fixed-distribution.html.ini delete mode 100644 tests/wpt/meta/css/css-tables/tentative/section-no-tbody-percent-distribution.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformable-table-footer-group.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformable-table-header-group.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformable-table-row-group.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformable-table-row.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformed-tbody-contains-fixed-position.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformed-tfoot-contains-fixed-position.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformed-thead-contains-fixed-position.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformed-tr-contains-fixed-position.html.ini delete mode 100644 tests/wpt/meta/css/css-transforms/transform-transformed-tr-percent-height-child.html.ini create mode 100644 tests/wpt/meta/css/css-ui/text-overflow-025.html.ini create mode 100644 tests/wpt/meta/html/rendering/non-replaced-elements/tables/tr-transform-and-will-change.html.ini create mode 100644 tests/wpt/meta/quirks/table-cell-width-calculation-abspos.html.ini diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs index d755faae1cd..76e2a5fd78d 100644 --- a/components/layout_2020/display_list/mod.rs +++ b/components/layout_2020/display_list/mod.rs @@ -30,7 +30,9 @@ use wr::{BoxShadowClipMode, ScrollSensitivity}; use crate::context::LayoutContext; use crate::display_list::conversions::ToWebRender; use crate::display_list::stacking_context::StackingContextSection; -use crate::fragment_tree::{BoxFragment, Fragment, FragmentTree, Tag, TextFragment}; +use crate::fragment_tree::{ + BackgroundMode, BoxFragment, Fragment, FragmentTree, Tag, TextFragment, +}; use crate::geom::{LogicalRect, PhysicalPoint, PhysicalRect}; use crate::replaced::IntrinsicSizes; use crate::style_ext::ComputedValuesExt; @@ -611,19 +613,29 @@ impl<'a> BuilderForBoxFragment<'a> { return; } - for extra_background in self.fragment.extra_backgrounds.iter() { - let positioning_area: LogicalRect = extra_background.rect.clone().into(); - let painter = BackgroundPainter { - style: &extra_background.style, - painting_area_override: None, - positioning_area_override: Some( - positioning_area - .to_physical(self.fragment.style.writing_mode, self.containing_block) - .translate(self.containing_block.origin.to_vector()) - .to_webrender(), - ), - }; - self.build_background_for_painter(builder, &painter); + // If this BoxFragment does not paint a background, do nothing. + if let BackgroundMode::None = self.fragment.background_mode { + return; + } + + // Paint all extra backgrounds for this BoxFragment. These are painted first, as that's + // the order that they are expected to be painted for table cells (where this feature + // is used). + if let BackgroundMode::Extra(ref extra_backgrounds) = self.fragment.background_mode { + for extra_background in extra_backgrounds { + let positioning_area: LogicalRect = extra_background.rect.clone().into(); + let painter = BackgroundPainter { + style: &extra_background.style, + painting_area_override: None, + positioning_area_override: Some( + positioning_area + .to_physical(self.fragment.style.writing_mode, self.containing_block) + .translate(self.containing_block.origin.to_vector()) + .to_webrender(), + ), + }; + self.build_background_for_painter(builder, &painter); + } } let painter = BackgroundPainter { diff --git a/components/layout_2020/fragment_tree/box_fragment.rs b/components/layout_2020/fragment_tree/box_fragment.rs index 6f191b25a58..ad1b743242b 100644 --- a/components/layout_2020/fragment_tree/box_fragment.rs +++ b/components/layout_2020/fragment_tree/box_fragment.rs @@ -21,6 +21,19 @@ use crate::geom::{ }; use crate::style_ext::ComputedValuesExt; +/// Describes how a [`BoxFragment`] paints its background. +pub(crate) enum BackgroundMode { + /// Draw the normal [`BoxFragment`] background as well as the extra backgrounds + /// based on the style and positioning rectangles in this data structure. + Extra(Vec), + /// Do not draw a background for this Fragment. This is used for elements like + /// table tracks and table track groups, which rely on cells to paint their + /// backgrounds. + None, + /// Draw the background normally, getting information from the Fragment style. + Normal, +} + pub(crate) struct ExtraBackground { pub style: ServoArc, pub rect: LogicalRect, @@ -70,7 +83,7 @@ pub(crate) struct BoxFragment { pub(crate) resolved_sticky_insets: Option>, #[serde(skip_serializing)] - pub extra_backgrounds: Vec, + pub background_mode: BackgroundMode, } impl BoxFragment { @@ -160,7 +173,7 @@ impl BoxFragment { scrollable_overflow_from_children, overconstrained, resolved_sticky_insets: None, - extra_backgrounds: Vec::new(), + background_mode: BackgroundMode::Normal, } } @@ -178,7 +191,14 @@ impl BoxFragment { } pub fn add_extra_background(&mut self, extra_background: ExtraBackground) { - self.extra_backgrounds.push(extra_background); + match self.background_mode { + BackgroundMode::Extra(ref mut backgrounds) => backgrounds.push(extra_background), + _ => self.background_mode = BackgroundMode::Extra(vec![extra_background]), + } + } + + pub fn set_does_not_paint_background(&mut self) { + self.background_mode = BackgroundMode::None; } pub fn scrollable_overflow( diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index 6c6f6c849c4..6a57b3c997b 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -4,7 +4,7 @@ use std::convert::From; use std::fmt; -use std::ops::{Add, AddAssign, Sub}; +use std::ops::{Add, AddAssign, Sub, SubAssign}; use app_units::Au; use serde::Serialize; @@ -26,7 +26,7 @@ pub type LengthOrAuto = AutoOr; pub type AuOrAuto = AutoOr; pub type LengthPercentageOrAuto<'a> = AutoOr<&'a LengthPercentage>; -#[derive(Clone, Serialize)] +#[derive(Clone, Copy, Serialize)] pub struct LogicalVec2 { pub inline: T, pub block: T, @@ -117,6 +117,34 @@ where } } +impl AddAssign> for LogicalVec2 +where + T: AddAssign + Copy, +{ + fn add_assign(&mut self, other: LogicalVec2) { + self.add_assign(&other); + } +} + +impl SubAssign<&'_ LogicalVec2> for LogicalVec2 +where + T: SubAssign + Copy, +{ + fn sub_assign(&mut self, other: &'_ LogicalVec2) { + self.inline -= other.inline; + self.block -= other.block; + } +} + +impl SubAssign> for LogicalVec2 +where + T: SubAssign + Copy, +{ + fn sub_assign(&mut self, other: LogicalVec2) { + self.sub_assign(&other); + } +} + impl LogicalVec2 { pub fn zero() -> Self { Self { diff --git a/components/layout_2020/table/construct.rs b/components/layout_2020/table/construct.rs index 5aff025c1ce..79b6ad6f44b 100644 --- a/components/layout_2020/table/construct.rs +++ b/components/layout_2020/table/construct.rs @@ -639,10 +639,10 @@ where .stylist .style_for_anonymous::( &context.shared_context().guards, - &PseudoElement::ServoAnonymousTableCell, + &PseudoElement::ServoAnonymousTableRow, &self.info.style, ); - let anonymous_info = self.info.new_anonymous(anonymous_style); + let anonymous_info = self.info.new_anonymous(anonymous_style.clone()); let mut row_builder = TableRowBuilder::new(self, &anonymous_info, self.current_text_decoration_line); @@ -663,6 +663,23 @@ where } row_builder.finish(); + + self.push_table_row(TableTrack { + base_fragment_info: (&anonymous_info).into(), + style: anonymous_style, + group_index: self.current_row_group_index, + is_anonymous: true, + }); + } + + fn push_table_row(&mut self, table_track: TableTrack) { + self.builder.table.rows.push(table_track); + + let last_row = self.builder.table.rows.len(); + if let Some(index) = self.current_row_group_index { + let row_group = &mut self.builder.table.row_groups[index]; + row_group.track_range.end = last_row; + } } } @@ -714,6 +731,7 @@ where info, self, ); + self.finish_anonymous_row_if_needed(); self.current_row_group_index = None; self.current_text_decoration_line = previous_text_decoration_line; @@ -736,21 +754,13 @@ where ); row_builder.finish(); - self.builder.table.rows.push(TableTrack { + self.push_table_row(TableTrack { base_fragment_info: info.into(), style: info.style.clone(), group_index: self.current_row_group_index, is_anonymous: false, }); - let last_row = self.builder.table.rows.len(); - let row_group = self - .current_row_group_index - .map(|index| &mut self.builder.table.row_groups[index]); - if let Some(row_group) = row_group { - row_group.track_range.end = last_row; - } - // We are doing this until we have actually set a Box for this `BoxSlot`. ::std::mem::forget(box_slot) }, diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index 1ecc1baa447..e7f2c9f63f5 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -18,14 +18,15 @@ use style::values::generics::box_::{GenericVerticalAlign as VerticalAlign, Verti use style::values::generics::length::GenericLengthPercentageOrAuto::{Auto, LengthPercentage}; use style::Zero; -use super::{Table, TableSlot, TableSlotCell, TableTrackGroup}; +use super::{Table, TableSlot, TableSlotCell, TableTrack, TableTrackGroup}; use crate::context::LayoutContext; use crate::formatting_contexts::{Baselines, IndependentLayout}; use crate::fragment_tree::{ - BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, PositioningFragment, + BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, + PositioningFragment, }; use crate::geom::{AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2}; -use crate::positioned::{PositioningContext, PositioningContextLength}; +use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength}; use crate::sizing::ContentSizes; use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin}; use crate::table::TableSlotCoordinates; @@ -84,6 +85,7 @@ pub(crate) struct TableLayout<'a> { column_measures: Vec, distributed_column_widths: Vec, row_sizes: Vec, + /// The accumulated baseline of each row, relative to the top of the row. row_baselines: Vec, cells_laid_out: Vec>>, basis_for_cell_padding_percentage: Au, @@ -968,9 +970,25 @@ impl<'a> TableLayout<'a> { parent_positioning_context: &mut PositioningContext, ) { for row_index in 0..self.table.slots.len() { - let row = &self.table.slots[row_index]; + // When building the PositioningContext for this cell, we want it to have the same + // configuration for whatever PositioningContext the contents are ultimately added to. + let collect_for_nearest_positioned_ancestor = parent_positioning_context + .collects_for_nearest_positioned_ancestor() || + self.table.rows.get(row_index).map_or(false, |row| { + let row_group_collects_for_nearest_positioned_ancestor = + row.group_index.map_or(false, |group_index| { + self.table.row_groups[group_index] + .style + .establishes_containing_block_for_absolute_descendants() + }); + row_group_collects_for_nearest_positioned_ancestor || + row.style + .establishes_containing_block_for_absolute_descendants() + }); + let mut cells_laid_out_row = Vec::new(); - for (column_index, slot) in row.iter().enumerate() { + let slots = &self.table.slots[row_index]; + for (column_index, slot) in slots.iter().enumerate() { let cell = match slot { TableSlot::Cell(cell) => cell, _ => { @@ -1001,8 +1019,7 @@ impl<'a> TableLayout<'a> { block_size: AuOrAuto::Auto, style: &cell.style, }; - let collect_for_nearest_positioned_ancestor = - parent_positioning_context.collects_for_nearest_positioned_ancestor(); + let mut positioning_context = PositioningContext::new_for_subtree(collect_for_nearest_positioned_ancestor); @@ -1398,21 +1415,52 @@ impl<'a> TableLayout<'a> { assert_eq!(self.table.size.width, self.distributed_column_widths.len()); let mut baselines = Baselines::default(); - let mut fragments = Vec::new(); + let mut table_fragments = Vec::new(); if self.table.size.width == 0 || self.table.size.height == 0 { return IndependentLayout { - fragments, + fragments: table_fragments, content_block_size: self.final_table_height, content_inline_size_for_table: Some(self.assignable_width), baselines, }; } - let dimensions = TableAndTrackDimensions::new(&self); - self.make_fragments_for_columns_rows_and_groups(&dimensions, &mut fragments); + let table_and_track_dimensions = TableAndTrackDimensions::new(&self); + self.make_fragments_for_columns_and_column_groups( + &table_and_track_dimensions, + &mut table_fragments, + ); + let mut row_group_fragment_layout = None; for row_index in 0..self.table.size.height { + let table_row = &self.table.rows[row_index]; + let mut row_fragment_layout = + RowFragmentLayout::new(table_row, row_index, &table_and_track_dimensions); + + let old_row_group_index = row_group_fragment_layout + .as_ref() + .map(|layout: &RowGroupFragmentLayout| layout.index); + if table_row.group_index != old_row_group_index { + // First create the Fragment for any existing RowGroupFragmentLayout. + if let Some(old_row_group_layout) = row_group_fragment_layout.take() { + table_fragments.push(Fragment::Box(old_row_group_layout.finish( + layout_context, + positioning_context, + containing_block_for_children, + ))); + } + + // Then, create a new RowGroupFragmentLayout for the current and potentially subsequent rows. + if let Some(new_group_index) = table_row.group_index { + row_group_fragment_layout = Some(RowGroupFragmentLayout::new( + &self.table.row_groups[new_group_index], + new_group_index, + &table_and_track_dimensions, + )); + } + } + // From // > If any cells in the row participate in first baseline/last baseline alignment along // > the inline axis, the first/last baseline set of the row is generated from their @@ -1423,86 +1471,57 @@ impl<'a> TableLayout<'a> { // If any cell below has baseline alignment, these values will be overwritten, // but they are initialized to the content edge of the first row. if row_index == 0 { - let row_end = dimensions.get_row_rect(0).max_block_position(); + let row_end = table_and_track_dimensions + .get_row_rect(0) + .max_block_position(); baselines.first = Some(row_end); baselines.last = Some(row_end); } - for column_index in 0..self.table.size.width { - let layout = match self.cells_laid_out[row_index][column_index].take() { - Some(layout) => layout, - None => { - continue; - }, - }; + let column_indices = 0..self.table.size.width.clone(); + row_fragment_layout.fragments.reserve(self.table.size.width); + for column_index in column_indices { + // The PositioningContext for cells is, in order or preference, the PositioningContext of the row, + // the PositioningContext of the row group, or the PositioningContext of the table. + let row_group_positioning_context = row_group_fragment_layout + .as_mut() + .and_then(|layout| layout.positioning_context.as_mut()); + let positioning_context_for_cells = row_fragment_layout + .positioning_context + .as_mut() + .or(row_group_positioning_context) + .unwrap_or(positioning_context); - let cell = match self.table.slots[row_index][column_index] { - TableSlot::Cell(ref cell) => cell, - _ => { - warn!("Did not find a non-spanned cell at index with layout."); - continue; - }, - }; - - let cell_rect = dimensions.get_cell_rect( - TableSlotCoordinates::new(column_index, row_index), - cell.rowspan, - cell.colspan, + self.do_final_cell_layout( + row_index, + column_index, + &table_and_track_dimensions, + &row_fragment_layout.rect, + positioning_context_for_cells, + &mut baselines, + &mut row_fragment_layout.fragments, ); - - // If this cell has baseline alignment, it can adjust the table's overall baseline. - let row_baseline = self.row_baselines[row_index]; - if cell.effective_vertical_align() == VerticalAlignKeyword::Baseline { - let baseline = cell_rect.start_corner.block + row_baseline; - if row_index == 0 { - baselines.first = Some(baseline); - } - baselines.last = Some(baseline); - } - - let mut fragment = - cell.create_fragment(layout, cell_rect, row_baseline, positioning_context); - - let column = self.table.columns.get(column_index); - let column_group = column - .and_then(|column| column.group_index) - .and_then(|index| self.table.column_groups.get(index)); - if let Some(column_group) = column_group { - fragment.add_extra_background(ExtraBackground { - style: column_group.style.clone(), - rect: dimensions.get_column_group_rect(column_group), - }) - } - - if let Some(column) = column { - if !column.is_anonymous { - fragment.add_extra_background(ExtraBackground { - style: column.style.clone(), - rect: dimensions.get_column_rect(column_index), - }) - } - } - - let row = self.table.rows.get(row_index); - let row_group = row - .and_then(|row| row.group_index) - .and_then(|index| self.table.row_groups.get(index)); - if let Some(row_group) = row_group { - fragment.add_extra_background(ExtraBackground { - style: row_group.style.clone(), - rect: dimensions.get_row_group_rect(row_group), - }) - } - - if let Some(row) = row { - fragment.add_extra_background(ExtraBackground { - style: row.style.clone(), - rect: dimensions.get_row_rect(row_index), - }) - } - - fragments.push(Fragment::Box(fragment)); } + + let row_fragment = Fragment::Box(row_fragment_layout.finish( + layout_context, + positioning_context, + containing_block_for_children, + &mut row_group_fragment_layout, + )); + + match row_group_fragment_layout.as_mut() { + Some(layout) => layout.fragments.push(row_fragment), + None => table_fragments.push(row_fragment), + } + } + + if let Some(row_group_layout) = row_group_fragment_layout.take() { + table_fragments.push(Fragment::Box(row_group_layout.finish( + layout_context, + positioning_context, + containing_block_for_children, + ))); } if self.table.anonymous { @@ -1511,14 +1530,109 @@ impl<'a> TableLayout<'a> { } IndependentLayout { - fragments, - content_block_size: dimensions.table_rect.max_block_position(), - content_inline_size_for_table: Some(dimensions.table_rect.max_inline_position()), + fragments: table_fragments, + content_block_size: table_and_track_dimensions.table_rect.max_block_position(), + content_inline_size_for_table: Some( + table_and_track_dimensions.table_rect.max_inline_position(), + ), baselines, } } - fn make_fragments_for_columns_rows_and_groups( + fn do_final_cell_layout( + &mut self, + row_index: usize, + column_index: usize, + dimensions: &TableAndTrackDimensions, + row_rect: &LogicalRect, + positioning_context: &mut PositioningContext, + baselines: &mut Baselines, + cell_fragments: &mut Vec, + ) { + let layout = match self.cells_laid_out[row_index][column_index].take() { + Some(layout) => layout, + None => { + return; + }, + }; + let cell = match self.table.slots[row_index][column_index] { + TableSlot::Cell(ref cell) => cell, + _ => { + warn!("Did not find a non-spanned cell at index with layout."); + return; + }, + }; + + let row_block_offset = row_rect.start_corner.block; + let row_baseline = self.row_baselines[row_index]; + if cell.effective_vertical_align() == VerticalAlignKeyword::Baseline { + let baseline = row_block_offset + row_baseline; + if row_index == 0 { + baselines.first = Some(baseline); + } + baselines.last = Some(baseline); + } + let mut row_relative_cell_rect = dimensions.get_cell_rect( + TableSlotCoordinates::new(column_index, row_index), + cell.rowspan, + cell.colspan, + ); + row_relative_cell_rect.start_corner = + &row_relative_cell_rect.start_corner - &row_rect.start_corner; + let mut fragment = cell.create_fragment( + layout, + row_relative_cell_rect, + row_baseline, + positioning_context, + ); + let column = self.table.columns.get(column_index); + let column_group = column + .and_then(|column| column.group_index) + .and_then(|index| self.table.column_groups.get(index)); + if let Some(column_group) = column_group { + let mut rect = dimensions.get_column_group_rect(column_group); + rect.start_corner -= row_rect.start_corner; + fragment.add_extra_background(ExtraBackground { + style: column_group.style.clone(), + rect, + }) + } + if let Some(column) = column { + if !column.is_anonymous { + let mut rect = dimensions.get_column_rect(column_index); + rect.start_corner -= row_rect.start_corner; + fragment.add_extra_background(ExtraBackground { + style: column.style.clone(), + rect, + }) + } + } + let row = self.table.rows.get(row_index); + let row_group = row + .and_then(|row| row.group_index) + .and_then(|index| self.table.row_groups.get(index)); + if let Some(row_group) = row_group { + let mut rect = dimensions.get_row_group_rect(row_group); + rect.start_corner -= row_rect.start_corner; + fragment.add_extra_background(ExtraBackground { + style: row_group.style.clone(), + rect, + }) + } + if let Some(row) = row { + let mut rect = row_rect.clone(); + rect.start_corner = LogicalVec2::zero(); + fragment.add_extra_background(ExtraBackground { + style: row.style.clone(), + rect, + }) + } + cell_fragments.push(Fragment::Box(fragment)); + + // If this cell has baseline alignment, it can adjust the table's overall baseline. + } + + fn make_fragments_for_columns_and_column_groups( &mut self, dimensions: &TableAndTrackDimensions, fragments: &mut Vec, @@ -1540,27 +1654,129 @@ impl<'a> TableLayout<'a> { column.style.clone(), ))); } - - for row_group in self.table.row_groups.iter() { - if !row_group.is_empty() { - fragments.push(Fragment::Positioning(PositioningFragment::new_empty( - row_group.base_fragment_info, - dimensions.get_row_group_rect(row_group).into(), - row_group.style.clone(), - ))); - } - } - - for (row_index, row) in self.table.rows.iter().enumerate() { - fragments.push(Fragment::Positioning(PositioningFragment::new_empty( - row.base_fragment_info, - dimensions.get_row_rect(row_index).into(), - row.style.clone(), - ))); - } } } +struct RowFragmentLayout<'a> { + row: &'a TableTrack, + rect: LogicalRect, + positioning_context: Option, + fragments: Vec, +} + +impl<'a> RowFragmentLayout<'a> { + fn new(table_row: &'a TableTrack, index: usize, dimensions: &TableAndTrackDimensions) -> Self { + Self { + row: table_row, + rect: dimensions.get_row_rect(index), + positioning_context: PositioningContext::new_for_style(&table_row.style), + fragments: Vec::new(), + } + } + fn finish( + mut self, + layout_context: &LayoutContext, + table_positioning_context: &mut PositioningContext, + containing_block: &ContainingBlock, + row_group_fragment_layout: &mut Option, + ) -> BoxFragment { + let mut row_rect: LogicalRect = self.rect.into(); + if self.positioning_context.is_some() { + row_rect.start_corner += relative_adjustement(&self.row.style, containing_block); + } + + if let Some(ref row_group_layout) = row_group_fragment_layout { + let row_group_start_corner: LogicalVec2 = + row_group_layout.rect.start_corner.into(); + row_rect.start_corner -= row_group_start_corner; + } + + let mut row_fragment = BoxFragment::new( + self.row.base_fragment_info, + self.row.style.clone(), + self.fragments, + row_rect, + LogicalSides::zero(), /* padding */ + LogicalSides::zero(), /* border */ + LogicalSides::zero(), /* margin */ + None, /* clearance */ + CollapsedBlockMargins::zero(), + ); + row_fragment.set_does_not_paint_background(); + + if let Some(mut row_positioning_context) = self.positioning_context.take() { + row_positioning_context.layout_collected_children(layout_context, &mut row_fragment); + + let positioning_context = row_group_fragment_layout + .as_mut() + .and_then(|layout| layout.positioning_context.as_mut()) + .unwrap_or(table_positioning_context); + positioning_context.append(row_positioning_context); + } + + row_fragment + } +} + +struct RowGroupFragmentLayout { + base_fragment_info: BaseFragmentInfo, + style: Arc, + rect: LogicalRect, + positioning_context: Option, + index: usize, + fragments: Vec, +} + +impl RowGroupFragmentLayout { + fn new( + row_group: &TableTrackGroup, + index: usize, + dimensions: &TableAndTrackDimensions, + ) -> Self { + let rect = dimensions.get_row_group_rect(row_group); + Self { + base_fragment_info: row_group.base_fragment_info, + style: row_group.style.clone(), + rect, + positioning_context: PositioningContext::new_for_style(&row_group.style), + index, + fragments: Vec::new(), + } + } + + fn finish( + mut self, + layout_context: &LayoutContext, + table_positioning_context: &mut PositioningContext, + containing_block: &ContainingBlock, + ) -> BoxFragment { + let mut content_rect: LogicalRect = self.rect.into(); + if self.positioning_context.is_some() { + content_rect.start_corner += relative_adjustement(&self.style, containing_block); + } + + let mut row_group_fragment = BoxFragment::new( + self.base_fragment_info, + self.style, + self.fragments, + content_rect, + LogicalSides::zero(), /* padding */ + LogicalSides::zero(), /* border */ + LogicalSides::zero(), /* margin */ + None, /* clearance */ + CollapsedBlockMargins::zero(), + ); + row_group_fragment.set_does_not_paint_background(); + + if let Some(mut row_positioning_context) = self.positioning_context.take() { + row_positioning_context + .layout_collected_children(layout_context, &mut row_group_fragment); + table_positioning_context.append(row_positioning_context); + } + + row_group_fragment + } +} struct TableAndTrackDimensions { /// The rect of the full table, not counting for borders, padding, and margin. table_rect: LogicalRect, 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 new file mode 100644 index 00000000000..61fbc5acc76 --- /dev/null +++ b/tests/wpt/meta/css/CSS2/tables/row-visibility-002.xht.ini @@ -0,0 +1,2 @@ +[row-visibility-002.xht] + expected: FAIL diff --git a/tests/wpt/meta/css/css-position/position-relative-012.html.ini b/tests/wpt/meta/css/css-position/position-relative-012.html.ini deleted file mode 100644 index 9546059bb73..00000000000 --- a/tests/wpt/meta/css/css-position/position-relative-012.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[position-relative-012.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/table-model-fixup-2.html.ini b/tests/wpt/meta/css/css-tables/table-model-fixup-2.html.ini index 55d8e50706f..11894142d26 100644 --- a/tests/wpt/meta/css/css-tables/table-model-fixup-2.html.ini +++ b/tests/wpt/meta/css/css-tables/table-model-fixup-2.html.ini @@ -16,3 +16,6 @@ [Replaced elements outside a table cannot be table-row and are considered inline -- input=file elements] expected: FAIL + + [Replaced elements outside a table cannot be table-row-group and are considered inline -- input=file elements] + expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/section-no-tbody-fixed-distribution.html.ini b/tests/wpt/meta/css/css-tables/tentative/section-no-tbody-fixed-distribution.html.ini deleted file mode 100644 index 1d7367396c1..00000000000 --- a/tests/wpt/meta/css/css-tables/tentative/section-no-tbody-fixed-distribution.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[section-no-tbody-fixed-distribution.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-tables/tentative/section-no-tbody-percent-distribution.html.ini b/tests/wpt/meta/css/css-tables/tentative/section-no-tbody-percent-distribution.html.ini deleted file mode 100644 index a8688988e28..00000000000 --- a/tests/wpt/meta/css/css-tables/tentative/section-no-tbody-percent-distribution.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[section-no-tbody-percent-distribution.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformable-table-footer-group.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformable-table-footer-group.html.ini deleted file mode 100644 index ad54394e650..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformable-table-footer-group.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformable-table-footer-group.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformable-table-header-group.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformable-table-header-group.html.ini deleted file mode 100644 index 671baa449d8..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformable-table-header-group.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformable-table-header-group.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformable-table-row-group.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformable-table-row-group.html.ini deleted file mode 100644 index d3924eabf59..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformable-table-row-group.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformable-table-row-group.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformable-table-row.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformable-table-row.html.ini deleted file mode 100644 index 15dd5cb56dd..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformable-table-row.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformable-table-row.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformed-tbody-contains-fixed-position.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformed-tbody-contains-fixed-position.html.ini deleted file mode 100644 index 9a5907e66b6..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformed-tbody-contains-fixed-position.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformed-tbody-contains-fixed-position.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformed-tfoot-contains-fixed-position.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformed-tfoot-contains-fixed-position.html.ini deleted file mode 100644 index 7d397b381e0..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformed-tfoot-contains-fixed-position.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformed-tfoot-contains-fixed-position.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformed-thead-contains-fixed-position.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformed-thead-contains-fixed-position.html.ini deleted file mode 100644 index af984ec334d..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformed-thead-contains-fixed-position.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformed-thead-contains-fixed-position.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformed-tr-contains-fixed-position.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformed-tr-contains-fixed-position.html.ini deleted file mode 100644 index 5ecc5feccaf..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformed-tr-contains-fixed-position.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformed-tr-contains-fixed-position.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transforms/transform-transformed-tr-percent-height-child.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformed-tr-percent-height-child.html.ini deleted file mode 100644 index e26a0479b33..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform-transformed-tr-percent-height-child.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-transformed-tr-percent-height-child.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-ui/text-overflow-025.html.ini b/tests/wpt/meta/css/css-ui/text-overflow-025.html.ini new file mode 100644 index 00000000000..a7d356084b2 --- /dev/null +++ b/tests/wpt/meta/css/css-ui/text-overflow-025.html.ini @@ -0,0 +1,2 @@ +[text-overflow-025.html] + expected: FAIL diff --git a/tests/wpt/meta/css/cssom-view/elementsFromPoint-table.html.ini b/tests/wpt/meta/css/cssom-view/elementsFromPoint-table.html.ini index 3d47b4502fd..9c1ba781b58 100644 --- a/tests/wpt/meta/css/cssom-view/elementsFromPoint-table.html.ini +++ b/tests/wpt/meta/css/cssom-view/elementsFromPoint-table.html.ini @@ -4,3 +4,9 @@ [elementsFromPoint for points inside cells in a flipped (writing-mode:vertical-lr) table] expected: FAIL + + [elementsFromPoint for points inside table cells] + expected: FAIL + + [elementsFromPoint for points between table cells] + expected: FAIL diff --git a/tests/wpt/meta/html/rendering/non-replaced-elements/tables/tr-transform-and-will-change.html.ini b/tests/wpt/meta/html/rendering/non-replaced-elements/tables/tr-transform-and-will-change.html.ini new file mode 100644 index 00000000000..069c8c56315 --- /dev/null +++ b/tests/wpt/meta/html/rendering/non-replaced-elements/tables/tr-transform-and-will-change.html.ini @@ -0,0 +1,2 @@ +[tr-transform-and-will-change.html] + expected: FAIL diff --git a/tests/wpt/meta/quirks/table-cell-width-calculation-abspos.html.ini b/tests/wpt/meta/quirks/table-cell-width-calculation-abspos.html.ini new file mode 100644 index 00000000000..7e664cb5b56 --- /dev/null +++ b/tests/wpt/meta/quirks/table-cell-width-calculation-abspos.html.ini @@ -0,0 +1,2 @@ +[table-cell-width-calculation-abspos.html] + expected: FAIL