diff options
author | Oriol Brufau <obrufau@igalia.com> | 2025-01-21 05:10:27 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-21 13:10:27 +0000 |
commit | d00d76c1e8f1ef435fa7559b19b88f8934474395 (patch) | |
tree | 29f2ac65127354c70a30b1617ff52ae22daef45a /components/layout_2020/table/layout.rs | |
parent | e43baed585a4a2b1ffa74df9da7f126cf4309e2a (diff) | |
download | servo-d00d76c1e8f1ef435fa7559b19b88f8934474395.tar.gz servo-d00d76c1e8f1ef435fa7559b19b88f8934474395.zip |
layout: Paint collapsed table borders on their own (#35075)
We were previously splitting collapsed borders into two halves, and then
paint each one as part of the corresponding cell. This looked wrong when
the border style wasn't solid, or when a cell spanned multiple tracks
and the border wasn't the same for all of them.
Now the borders of a table wrapper, table grid or table cell aren't
painted in collapsed borders mode. Instead, the resulting collapsed
borders are painted on their own.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Diffstat (limited to 'components/layout_2020/table/layout.rs')
-rw-r--r-- | components/layout_2020/table/layout.rs | 117 |
1 files changed, 43 insertions, 74 deletions
diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index 5d6c27d1796..49521baaa05 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use core::cmp::Ordering; +use std::mem; use std::ops::Range; use app_units::{Au, MAX_AU}; @@ -24,7 +25,8 @@ use style::values::generics::box_::{GenericVerticalAlign as VerticalAlign, Verti use style::Zero; use super::{ - ArcRefCell, Table, TableCaption, TableSlot, TableSlotCell, TableTrack, TableTrackGroup, + ArcRefCell, CollapsedBorder, CollapsedBorderLine, SpecificTableGridInfo, Table, TableCaption, + TableSlot, TableSlotCell, TableSlotCoordinates, TableTrack, TableTrackGroup, }; use crate::context::LayoutContext; use crate::formatting_contexts::{Baselines, IndependentLayout}; @@ -34,29 +36,17 @@ use crate::fragment_tree::{ }; use crate::geom::{ AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, - Size, SizeConstraint, ToLogical, ToLogicalWithContainingBlock, + PhysicalVec, Size, SizeConstraint, ToLogical, ToLogicalWithContainingBlock, }; use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength}; use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult}; use crate::style_ext::{ BorderStyleColor, Clamp, ComputedValuesExt, LayoutStyle, PaddingBorderMargin, }; -use crate::table::{SpecificTableGridOrTableCellInfo, TableSlotCoordinates}; use crate::{ ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock, WritingMode, }; -fn detailed_layout_info( - border_style_color: Option<LogicalSides<BorderStyleColor>>, - writing_mode: WritingMode, -) -> Option<SpecificLayoutInfo> { - Some(SpecificLayoutInfo::TableGridOrTableCell(Box::new( - SpecificTableGridOrTableCellInfo { - border_style_color: border_style_color?.to_physical(writing_mode), - }, - ))) -} - /// A result of a final or speculative layout of a single cell in /// the table. Note that this is only done for slots that are not /// covered by spans or empty. @@ -64,7 +54,6 @@ struct CellLayout { layout: IndependentLayout, padding: LogicalSides<Au>, border: LogicalSides<Au>, - detailed_layout_info: Option<SpecificLayoutInfo>, positioning_context: PositioningContext, } @@ -113,13 +102,6 @@ struct ColumnLayout { percentage: Percentage, } -/// A calculated collapsed border. -#[derive(Clone, Debug, Default, PartialEq)] -struct CollapsedBorder { - style_color: BorderStyleColor, - width: Au, -} - impl CollapsedBorder { fn new(style_color: BorderStyleColor, width: Au) -> Self { Self { style_color, width } @@ -180,13 +162,6 @@ impl PartialOrd for CollapsedBorder { impl Eq for CollapsedBorder {} -/// Represents a piecewise sequence of collapsed borders along a line. -#[derive(Clone, Debug, Default)] -struct CollapsedBorderLine { - max_width: Au, - list: Vec<CollapsedBorder>, -} - impl CollapsedBorderLine { fn max_assign(&mut self, collapsed_border: &CollapsedBorder, range: &Range<usize>) { self.max_width.max_assign(collapsed_border.width); @@ -196,9 +171,6 @@ impl CollapsedBorderLine { } } -/// The calculated collapsed borders. -type CollapsedBorders = LogicalVec2<Vec<CollapsedBorderLine>>; - /// A helper struct that performs the layout of the box tree version /// of a table into the fragment tree version. This implements /// <https://drafts.csswg.org/css-tables/#table-layout-algorithm> @@ -222,7 +194,7 @@ pub(crate) struct TableLayout<'a> { cells_laid_out: Vec<Vec<Option<CellLayout>>>, basis_for_cell_padding_percentage: Au, /// Information about collapsed borders. - collapsed_borders: Option<CollapsedBorders>, + collapsed_borders: Option<LogicalVec2<Vec<CollapsedBorderLine>>>, } #[derive(Clone, Debug)] @@ -1213,10 +1185,6 @@ impl<'a> TableLayout<'a> { block_start: row_index, block_end: row_index + cell.rowspan, }; - let detailed_layout_info = detailed_layout_info( - self.get_collapsed_border_style_colors_for_area(area), - self.table.style.writing_mode, - ); let layout_style = cell.layout_style(); let border = self .get_collapsed_border_widths_for_area(area) @@ -1257,7 +1225,6 @@ impl<'a> TableLayout<'a> { layout, padding, border, - detailed_layout_info, positioning_context, }) }) @@ -1870,14 +1837,6 @@ impl<'a> TableLayout<'a> { assert_eq!(self.table.size.height, self.row_sizes.len()); assert_eq!(self.table.size.width, self.distributed_column_widths.len()); - let border_style_color = self.get_collapsed_border_style_colors_for_area(LogicalSides { - inline_start: 0, - inline_end: self.table.size.width, - block_start: 0, - block_end: self.table.size.height, - }); - let detailed_layout_info = detailed_layout_info(border_style_color, table_writing_mode); - if self.table.size.width == 0 && self.table.size.height == 0 { let content_rect = LogicalRect { start_corner: LogicalVec2::zero(), @@ -1898,7 +1857,7 @@ impl<'a> TableLayout<'a> { None, /* clearance */ CollapsedBlockMargins::zero(), ) - .with_detailed_layout_info(detailed_layout_info); + .with_detailed_layout_info(self.specific_layout_info_for_grid()); } let mut table_fragments = Vec::new(); @@ -2025,7 +1984,37 @@ impl<'a> TableLayout<'a> { CollapsedBlockMargins::zero(), ) .with_baselines(baselines) - .with_detailed_layout_info(detailed_layout_info) + .with_detailed_layout_info(self.specific_layout_info_for_grid()) + } + + fn specific_layout_info_for_grid(&mut self) -> Option<SpecificLayoutInfo> { + mem::take(&mut self.collapsed_borders).map(|mut collapsed_borders| { + let writing_mode = self.table.style.writing_mode; + let mut track_sizes = LogicalVec2 { + inline: mem::take(&mut self.distributed_column_widths), + block: mem::take(&mut self.row_sizes), + }; + if !writing_mode.is_bidi_ltr() { + track_sizes.inline.reverse(); + collapsed_borders.inline.reverse(); + for border_line in &mut collapsed_borders.block { + border_line.list.reverse(); + } + } + SpecificLayoutInfo::TableGridWithCollapsedBorders(Box::new(SpecificTableGridInfo { + collapsed_borders: if writing_mode.is_horizontal() { + PhysicalVec::new(collapsed_borders.inline, collapsed_borders.block) + } else { + PhysicalVec::new(collapsed_borders.block, collapsed_borders.inline) + }, + track_sizes: if writing_mode.is_horizontal() { + PhysicalVec::new(track_sizes.inline, track_sizes.block) + } else { + PhysicalVec::new(track_sizes.block, track_sizes.inline) + }, + wrapper_border: self.pbm.border.to_physical(writing_mode), + })) + }) } fn is_row_collapsed(&self, row_index: usize) -> bool { @@ -2212,7 +2201,7 @@ impl<'a> TableLayout<'a> { return; } - let mut collapsed_borders = CollapsedBorders { + let mut collapsed_borders = LogicalVec2 { block: vec![ CollapsedBorderLine { max_width: Au::zero(), @@ -2318,30 +2307,6 @@ impl<'a> TableLayout<'a> { }, }) } - - fn get_collapsed_border_style_colors_for_area( - &self, - area: LogicalSides<usize>, - ) -> Option<LogicalSides<BorderStyleColor>> { - let collapsed_borders = self.collapsed_borders.as_ref()?; - if self.table.size.width == 0 || self.table.size.height == 0 { - return Some(LogicalSides::default()); - } - let inline_start = &collapsed_borders.inline[area.inline_start]; - let inline_end = &collapsed_borders.inline[area.inline_end]; - let block_start = &collapsed_borders.block[area.block_start]; - let block_end = &collapsed_borders.block[area.block_end]; - - // This area may span multiple rows and columns, each of which can have different - // collapsed borders. However, we don't have support for one side of a box to have - // a piecewise border. Therefore, we just pick the first piece for the entire side. - Some(LogicalSides { - inline_start: inline_start.list[area.block_start].style_color.clone(), - inline_end: inline_end.list[area.block_start].style_color.clone(), - block_start: block_start.list[area.inline_start].style_color.clone(), - block_end: block_end.list[area.inline_start].style_color.clone(), - }) - } } struct RowFragmentLayout<'a> { @@ -2922,6 +2887,10 @@ impl TableSlotCell { ); positioning_context.append(layout.positioning_context); + let detailed_layout_info = (table_style.get_inherited_table().border_collapse == + BorderCollapse::Collapse) + .then_some(SpecificLayoutInfo::TableCellWithCollapsedBorders); + BoxFragment::new( base_fragment_info, self.base.style.clone(), @@ -2934,7 +2903,7 @@ impl TableSlotCell { CollapsedBlockMargins::zero(), ) .with_baselines(layout.layout.baselines) - .with_detailed_layout_info(layout.detailed_layout_info) + .with_detailed_layout_info(detailed_layout_info) } } |