layout: Improve painting of collapsed borders in table layout (#34933)

This is still not the right approach, because we are not painting
collapsed borders as a single thing. Instead, we are splitting them
into two halves and paint each half on a different cell. This only
looks good for solid borders.

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2025-01-10 16:38:31 -08:00 committed by GitHub
parent 25a94efcdf
commit e2be55b873
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
88 changed files with 181 additions and 256 deletions

View file

@ -22,7 +22,7 @@ use style::properties::style_structs::Border;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::image::Image; use style::values::computed::image::Image;
use style::values::computed::{ use style::values::computed::{
BorderImageSideWidth, BorderImageWidth, BorderStyle, Color, LengthPercentage, BorderImageSideWidth, BorderImageWidth, BorderStyle, LengthPercentage,
NonNegativeLengthOrNumber, NumberOrPercentage, OutlineStyle, NonNegativeLengthOrNumber, NumberOrPercentage, OutlineStyle,
}; };
use style::values::generics::rect::Rect; use style::values::generics::rect::Rect;
@ -44,11 +44,12 @@ use crate::context::LayoutContext;
use crate::display_list::conversions::ToWebRender; use crate::display_list::conversions::ToWebRender;
use crate::display_list::stacking_context::StackingContextSection; use crate::display_list::stacking_context::StackingContextSection;
use crate::fragment_tree::{ use crate::fragment_tree::{
BackgroundMode, BoxFragment, Fragment, FragmentFlags, FragmentTree, Tag, TextFragment, BackgroundMode, BoxFragment, Fragment, FragmentFlags, FragmentTree, SpecificLayoutInfo, Tag,
TextFragment,
}; };
use crate::geom::{LengthPercentageOrAuto, PhysicalPoint, PhysicalRect}; use crate::geom::{LengthPercentageOrAuto, PhysicalPoint, PhysicalRect};
use crate::replaced::NaturalSizes; use crate::replaced::NaturalSizes;
use crate::style_ext::ComputedValuesExt; use crate::style_ext::{BorderStyleColor, ComputedValuesExt};
mod background; mod background;
mod clip_path; mod clip_path;
@ -863,10 +864,10 @@ impl<'a> BuilderForBoxFragment<'a> {
} }
} }
fn build_border_side(&mut self, style: BorderStyle, color: Color) -> wr::BorderSide { fn build_border_side(&mut self, style_color: BorderStyleColor) -> wr::BorderSide {
wr::BorderSide { wr::BorderSide {
color: rgba(self.fragment.style.resolve_color(color)), color: rgba(self.fragment.style.resolve_color(style_color.color)),
style: match style { style: match style_color.style {
BorderStyle::None => wr::BorderStyle::None, BorderStyle::None => wr::BorderStyle::None,
BorderStyle::Solid => wr::BorderStyle::Solid, BorderStyle::Solid => wr::BorderStyle::Solid,
BorderStyle::Double => wr::BorderStyle::Double, BorderStyle::Double => wr::BorderStyle::Double,
@ -895,16 +896,17 @@ impl<'a> BuilderForBoxFragment<'a> {
return; return;
} }
let style_color = match &self.fragment.detailed_layout_info {
Some(SpecificLayoutInfo::TableOrTableCell(table_info)) => {
table_info.border_style_color.clone()
},
_ => BorderStyleColor::from_border(border),
};
let details = wr::BorderDetails::Normal(wr::NormalBorder { let details = wr::BorderDetails::Normal(wr::NormalBorder {
top: self.build_border_side(border.border_top_style, border.border_top_color.clone()), top: self.build_border_side(style_color.top),
right: self right: self.build_border_side(style_color.right),
.build_border_side(border.border_right_style, border.border_right_color.clone()), bottom: self.build_border_side(style_color.bottom),
bottom: self.build_border_side( left: self.build_border_side(style_color.left),
border.border_bottom_style,
border.border_bottom_color.clone(),
),
left: self
.build_border_side(border.border_left_style, border.border_left_color.clone()),
radius: self.border_radius, radius: self.border_radius,
do_aa: true, do_aa: true,
}); });
@ -1028,7 +1030,10 @@ impl<'a> BuilderForBoxFragment<'a> {
OutlineStyle::Auto => BorderStyle::Solid, OutlineStyle::Auto => BorderStyle::Solid,
OutlineStyle::BorderStyle(s) => s, OutlineStyle::BorderStyle(s) => s,
}; };
let side = self.build_border_side(style, outline.outline_color.clone()); let side = self.build_border_side(BorderStyleColor {
style,
color: outline.outline_color.clone(),
});
let details = wr::BorderDetails::Normal(wr::NormalBorder { let details = wr::BorderDetails::Normal(wr::NormalBorder {
top: side, top: side,
right: side, right: side,

View file

@ -20,6 +20,7 @@ use crate::geom::{
AuOrAuto, LengthPercentageOrAuto, PhysicalPoint, PhysicalRect, PhysicalSides, ToLogical, AuOrAuto, LengthPercentageOrAuto, PhysicalPoint, PhysicalRect, PhysicalSides, ToLogical,
}; };
use crate::style_ext::ComputedValuesExt; use crate::style_ext::ComputedValuesExt;
use crate::table::SpecificTableOrTableCellInfo;
use crate::taffy::SpecificTaffyGridInfo; use crate::taffy::SpecificTaffyGridInfo;
/// Describes how a [`BoxFragment`] paints its background. /// Describes how a [`BoxFragment`] paints its background.
@ -43,6 +44,7 @@ pub(crate) struct ExtraBackground {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) enum SpecificLayoutInfo { pub(crate) enum SpecificLayoutInfo {
Grid(Box<SpecificTaffyGridInfo>), Grid(Box<SpecificTaffyGridInfo>),
TableOrTableCell(Box<SpecificTableOrTableCellInfo>),
} }
#[derive(Serialize)] #[derive(Serialize)]

View file

@ -13,11 +13,12 @@ use style::logical_geometry::{Direction as AxisDirection, WritingMode};
use style::properties::longhands::backface_visibility::computed_value::T as BackfaceVisiblity; use style::properties::longhands::backface_visibility::computed_value::T as BackfaceVisiblity;
use style::properties::longhands::box_sizing::computed_value::T as BoxSizing; use style::properties::longhands::box_sizing::computed_value::T as BoxSizing;
use style::properties::longhands::column_span::computed_value::T as ColumnSpan; use style::properties::longhands::column_span::computed_value::T as ColumnSpan;
use style::properties::style_structs::Border;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::servo::selector_parser::PseudoElement; use style::servo::selector_parser::PseudoElement;
use style::values::computed::basic_shape::ClipPath; use style::values::computed::basic_shape::ClipPath;
use style::values::computed::image::Image as ComputedImageLayer; use style::values::computed::image::Image as ComputedImageLayer;
use style::values::computed::{AlignItems, BorderStyle, Inset, LengthPercentage, Margin}; use style::values::computed::{AlignItems, BorderStyle, Color, Inset, LengthPercentage, Margin};
use style::values::generics::box_::Perspective; use style::values::generics::box_::Perspective;
use style::values::generics::position::{GenericAspectRatio, PreferredRatio}; use style::values::generics::position::{GenericAspectRatio, PreferredRatio};
use style::values::specified::align::AlignFlags; use style::values::specified::align::AlignFlags;
@ -217,6 +218,36 @@ pub(crate) struct ContentBoxSizesAndPBMDeprecated {
pub depends_on_block_constraints: bool, pub depends_on_block_constraints: bool,
} }
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct BorderStyleColor {
pub style: BorderStyle,
pub color: Color,
}
impl BorderStyleColor {
pub(crate) fn new(style: BorderStyle, color: Color) -> Self {
Self { style, color }
}
pub(crate) fn from_border(border: &Border) -> PhysicalSides<Self> {
PhysicalSides::<Self>::new(
Self::new(border.border_top_style, border.border_top_color.clone()),
Self::new(border.border_right_style, border.border_right_color.clone()),
Self::new(
border.border_bottom_style,
border.border_bottom_color.clone(),
),
Self::new(border.border_left_style, border.border_left_color.clone()),
)
}
}
impl Default for BorderStyleColor {
fn default() -> Self {
Self::new(BorderStyle::None, Color::TRANSPARENT_BLACK)
}
}
pub(crate) trait ComputedValuesExt { pub(crate) trait ComputedValuesExt {
fn physical_box_offsets(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>>; fn physical_box_offsets(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>>;
fn box_offsets(&self, writing_mode: WritingMode) -> LogicalSides<LengthPercentageOrAuto<'_>>; fn box_offsets(&self, writing_mode: WritingMode) -> LogicalSides<LengthPercentageOrAuto<'_>>;
@ -279,8 +310,10 @@ pub(crate) trait ComputedValuesExt {
) -> PaddingBorderMargin; ) -> PaddingBorderMargin;
fn padding(&self, containing_block_writing_mode: WritingMode) fn padding(&self, containing_block_writing_mode: WritingMode)
-> LogicalSides<LengthPercentage>; -> LogicalSides<LengthPercentage>;
fn border_style(&self, containing_block_writing_mode: WritingMode) fn border_style_color(
-> LogicalSides<BorderStyle>; &self,
containing_block_writing_mode: WritingMode,
) -> LogicalSides<BorderStyleColor>;
fn border_width(&self, containing_block_writing_mode: WritingMode) -> LogicalSides<Au>; fn border_width(&self, containing_block_writing_mode: WritingMode) -> LogicalSides<Au>;
fn physical_margin(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>>; fn physical_margin(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>>;
fn margin( fn margin(
@ -598,18 +631,12 @@ impl ComputedValuesExt for ComputedValues {
) )
} }
fn border_style( fn border_style_color(
&self, &self,
containing_block_writing_mode: WritingMode, containing_block_writing_mode: WritingMode,
) -> LogicalSides<BorderStyle> { ) -> LogicalSides<BorderStyleColor> {
let border = self.get_border();
LogicalSides::from_physical( LogicalSides::from_physical(
&PhysicalSides::new( &BorderStyleColor::from_border(self.get_border()),
border.border_top_style,
border.border_right_style,
border.border_bottom_style,
border.border_left_style,
),
containing_block_writing_mode, containing_block_writing_mode,
) )
} }

View file

@ -29,7 +29,7 @@ use crate::context::LayoutContext;
use crate::formatting_contexts::{Baselines, IndependentLayout}; use crate::formatting_contexts::{Baselines, IndependentLayout};
use crate::fragment_tree::{ use crate::fragment_tree::{
BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, FragmentFlags, BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, FragmentFlags,
PositioningFragment, PositioningFragment, SpecificLayoutInfo,
}; };
use crate::geom::{ use crate::geom::{
AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides,
@ -37,12 +37,22 @@ use crate::geom::{
}; };
use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength}; use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength};
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult}; use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin}; use crate::style_ext::{BorderStyleColor, Clamp, ComputedValuesExt, PaddingBorderMargin};
use crate::table::TableSlotCoordinates; use crate::table::{SpecificTableOrTableCellInfo, TableSlotCoordinates};
use crate::{ use crate::{
ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock, WritingMode, ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock, WritingMode,
}; };
fn detailed_layout_info(
border_style_color: Option<PhysicalSides<BorderStyleColor>>,
) -> Option<SpecificLayoutInfo> {
Some(SpecificLayoutInfo::TableOrTableCell(Box::new(
SpecificTableOrTableCellInfo {
border_style_color: border_style_color?,
},
)))
}
/// A result of a final or speculative layout of a single cell in /// 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 /// the table. Note that this is only done for slots that are not
/// covered by spans or empty. /// covered by spans or empty.
@ -50,6 +60,7 @@ struct CellLayout {
layout: IndependentLayout, layout: IndependentLayout,
padding: LogicalSides<Au>, padding: LogicalSides<Au>,
border: LogicalSides<Au>, border: LogicalSides<Au>,
detailed_layout_info: Option<SpecificLayoutInfo>,
positioning_context: PositioningContext, positioning_context: PositioningContext,
} }
@ -97,31 +108,25 @@ struct ColumnLayout {
} }
/// A calculated collapsed border. /// A calculated collapsed border.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
struct CollapsedBorder { struct CollapsedBorder {
style: BorderStyle, style_color: BorderStyleColor,
width: Au, width: Au,
} }
impl Default for CollapsedBorder {
fn default() -> Self {
Self::new(BorderStyle::None, Au::zero())
}
}
impl CollapsedBorder { impl CollapsedBorder {
fn new(style: BorderStyle, width: Au) -> Self { fn new(style_color: BorderStyleColor, width: Au) -> Self {
Self { style, width } Self { style_color, width }
} }
fn from_style(style: &ComputedValues, writing_mode: WritingMode) -> LogicalSides<Self> { fn from_style(style: &ComputedValues, writing_mode: WritingMode) -> LogicalSides<Self> {
let border_style = style.border_style(writing_mode); let border_style_color = style.border_style_color(writing_mode);
let border_width = style.border_width(writing_mode); let border_width = style.border_width(writing_mode);
LogicalSides { LogicalSides {
inline_start: Self::new(border_style.inline_start, border_width.inline_start), inline_start: Self::new(border_style_color.inline_start, border_width.inline_start),
inline_end: Self::new(border_style.inline_end, border_width.inline_end), inline_end: Self::new(border_style_color.inline_end, border_width.inline_end),
block_start: Self::new(border_style.block_start, border_width.block_start), block_start: Self::new(border_style_color.block_start, border_width.block_start),
block_end: Self::new(border_style.block_end, border_width.block_end), block_end: Self::new(border_style_color.block_end, border_width.block_end),
} }
} }
@ -138,9 +143,10 @@ impl CollapsedBorder {
/// > 2. … has the biggest border-width, once converted into css pixels /// > 2. … has the biggest border-width, once converted into css pixels
/// > 3. … has the border-style which comes first in the following list: /// > 3. … has the border-style which comes first in the following list:
/// > double, solid, dashed, dotted, ridge, outset, groove, inset, none /// > double, solid, dashed, dotted, ridge, outset, groove, inset, none
impl Ord for CollapsedBorder { impl PartialOrd for CollapsedBorder {
fn cmp(&self, other: &Self) -> Ordering { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let style_specificity = |border: &Self| match border.style { let is_hidden = |border: &Self| border.style_color.style == BorderStyle::Hidden;
let style_specificity = |border: &Self| match border.style_color.style {
BorderStyle::None => 0, BorderStyle::None => 0,
BorderStyle::Inset => 1, BorderStyle::Inset => 1,
BorderStyle::Groove => 2, BorderStyle::Groove => 2,
@ -152,17 +158,18 @@ impl Ord for CollapsedBorder {
BorderStyle::Double => 8, BorderStyle::Double => 8,
BorderStyle::Hidden => 9, BorderStyle::Hidden => 9,
}; };
((self.style == BorderStyle::Hidden).cmp(&(other.style == BorderStyle::Hidden))) let candidate = (is_hidden(self).cmp(&is_hidden(other)))
.then_with(|| self.width.cmp(&other.width)) .then_with(|| self.width.cmp(&other.width))
.then_with(|| style_specificity(self).cmp(&style_specificity(other))) .then_with(|| style_specificity(self).cmp(&style_specificity(other)));
if !candidate.is_eq() || self.style_color.color == other.style_color.color {
Some(candidate)
} else {
None
}
} }
} }
impl PartialOrd for CollapsedBorder { impl Eq for CollapsedBorder {}
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
/// The calculated collapsed borders. /// The calculated collapsed borders.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
@ -275,7 +282,10 @@ impl<'a> TableLayout<'a> {
cell, cell,
TableSlotCoordinates::new(column_index, row_index), TableSlotCoordinates::new(column_index, row_index),
) )
.unwrap_or_else(|| cell.base.style.border_width(writing_mode)); .map_or_else(
|| cell.base.style.border_width(writing_mode),
|(border, _)| border,
);
let padding_border_sums = LogicalVec2 { let padding_border_sums = LogicalVec2 {
inline: padding.inline_sum() + border.inline_sum(), inline: padding.inline_sum() + border.inline_sum(),
@ -1185,13 +1195,20 @@ impl<'a> TableLayout<'a> {
}; };
let coordinates = TableSlotCoordinates::new(column_index, row_index); let coordinates = TableSlotCoordinates::new(column_index, row_index);
let border: LogicalSides<Au> = self let (border, detailed_layout_info) =
.get_collapsed_borders_for_cell(cell, coordinates) match self.get_collapsed_borders_for_cell(cell, coordinates) {
.unwrap_or_else(|| { Some((border_width, border_style_color)) => {
cell.base let border_style_color = border_style_color
.style .to_physical(self.table.style.writing_mode);
.border_width(containing_block_for_table.style.writing_mode) (border_width, detailed_layout_info(Some(border_style_color)))
}); },
None => (
cell.base.style.border_width(
containing_block_for_table.style.writing_mode,
),
None,
),
};
let padding: LogicalSides<Au> = cell let padding: LogicalSides<Au> = cell
.base .base
@ -1228,6 +1245,7 @@ impl<'a> TableLayout<'a> {
layout, layout,
padding, padding,
border, border,
detailed_layout_info,
positioning_context, positioning_context,
}) })
}) })
@ -1852,6 +1870,21 @@ impl<'a> TableLayout<'a> {
assert_eq!(self.table.size.height, self.row_sizes.len()); assert_eq!(self.table.size.height, self.row_sizes.len());
assert_eq!(self.table.size.width, self.distributed_column_widths.len()); assert_eq!(self.table.size.width, self.distributed_column_widths.len());
let border_style_color = self.collapsed_borders.as_ref().map(|collapsed_borders| {
LogicalSides {
inline_start: collapsed_borders.inline[0].style_color.clone(),
inline_end: collapsed_borders.inline[self.table.size.width]
.style_color
.clone(),
block_start: collapsed_borders.block[0].style_color.clone(),
block_end: collapsed_borders.block[self.table.size.height]
.style_color
.clone(),
}
.to_physical(table_writing_mode)
});
let detailed_layout_info = detailed_layout_info(border_style_color);
if self.table.size.width == 0 && self.table.size.height == 0 { if self.table.size.width == 0 && self.table.size.height == 0 {
let content_rect = LogicalRect { let content_rect = LogicalRect {
start_corner: LogicalVec2::zero(), start_corner: LogicalVec2::zero(),
@ -1871,7 +1904,8 @@ impl<'a> TableLayout<'a> {
PhysicalSides::zero(), PhysicalSides::zero(),
None, /* clearance */ None, /* clearance */
CollapsedBlockMargins::zero(), CollapsedBlockMargins::zero(),
); )
.with_detailed_layout_info(detailed_layout_info);
} }
let mut table_fragments = Vec::new(); let mut table_fragments = Vec::new();
@ -1998,6 +2032,7 @@ impl<'a> TableLayout<'a> {
CollapsedBlockMargins::zero(), CollapsedBlockMargins::zero(),
) )
.with_baselines(baselines) .with_baselines(baselines)
.with_detailed_layout_info(detailed_layout_info)
} }
fn is_row_collapsed(&self, row_index: usize) -> bool { fn is_row_collapsed(&self, row_index: usize) -> bool {
@ -2232,39 +2267,43 @@ impl<'a> TableLayout<'a> {
&self, &self,
cell: &TableSlotCell, cell: &TableSlotCell,
coordinates: TableSlotCoordinates, coordinates: TableSlotCoordinates,
) -> Option<LogicalSides<Au>> { ) -> Option<(LogicalSides<Au>, LogicalSides<BorderStyleColor>)> {
let collapsed_borders = self.collapsed_borders.as_ref()?; let collapsed_borders = self.collapsed_borders.as_ref()?;
let end_x = coordinates.x + cell.colspan; let end_x = coordinates.x + cell.colspan;
let end_y = coordinates.y + cell.rowspan; let end_y = coordinates.y + cell.rowspan;
let mut result = LogicalSides { let inline_start = &collapsed_borders.inline[coordinates.x];
inline_start: collapsed_borders.inline[coordinates.x].width, let inline_end = &collapsed_borders.inline[end_x];
inline_end: collapsed_borders.inline[end_x].width, let block_start = &collapsed_borders.block[coordinates.y];
block_start: collapsed_borders.block[coordinates.y].width, let block_end = &collapsed_borders.block[end_y];
block_end: collapsed_borders.block[end_y].width, let border_width = LogicalSides {
inline_start: if coordinates.x == 0 {
inline_start.width - self.pbm.border.inline_start
} else {
inline_start.width / 2
},
inline_end: if end_x == self.table.size.width {
inline_end.width - self.pbm.border.inline_end
} else {
inline_end.width / 2
},
block_start: if coordinates.y == 0 {
block_start.width - self.pbm.border.block_start
} else {
block_start.width / 2
},
block_end: if end_y == self.table.size.height {
block_end.width - self.pbm.border.block_end
} else {
block_end.width / 2
},
}; };
let border_style_color = LogicalSides {
if coordinates.x == 0 { inline_start: inline_start.style_color.clone(),
result.inline_start -= self.pbm.border.inline_start; inline_end: inline_end.style_color.clone(),
} else { block_start: block_start.style_color.clone(),
result.inline_start /= 2; block_end: block_end.style_color.clone(),
} };
if coordinates.y == 0 { Some((border_width, border_style_color))
result.block_start -= self.pbm.border.block_start;
} else {
result.block_start /= 2;
}
if end_x == self.table.size.width {
result.inline_end -= self.pbm.border.inline_end;
} else {
result.inline_end /= 2;
}
if end_y == self.table.size.height {
result.block_end -= self.pbm.border.block_end;
} else {
result.block_end /= 2;
}
Some(result)
} }
} }
@ -2828,6 +2867,7 @@ impl TableSlotCell {
CollapsedBlockMargins::zero(), CollapsedBlockMargins::zero(),
) )
.with_baselines(layout.layout.baselines) .with_baselines(layout.layout.baselines)
.with_detailed_layout_info(layout.detailed_layout_info)
} }
} }

View file

@ -84,7 +84,9 @@ use crate::cell::ArcRefCell;
use crate::flow::BlockContainer; use crate::flow::BlockContainer;
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::BaseFragmentInfo; use crate::fragment_tree::BaseFragmentInfo;
use crate::geom::PhysicalSides;
use crate::layout_box_base::LayoutBoxBase; use crate::layout_box_base::LayoutBoxBase;
use crate::style_ext::BorderStyleColor;
pub type TableSize = Size2D<usize, UnknownUnit>; pub type TableSize = Size2D<usize, UnknownUnit>;
@ -320,3 +322,10 @@ pub struct TableCaption {
/// The contents of this cell, with its own layout. /// The contents of this cell, with its own layout.
context: ArcRefCell<IndependentFormattingContext>, context: ArcRefCell<IndependentFormattingContext>,
} }
#[derive(Clone, Debug)]
pub(crate) struct SpecificTableOrTableCellInfo {
/// For tables is in collapsed-borders mode, this is used as an override for the
/// style and color of the border of the table and table cells.
pub border_style_color: PhysicalSides<BorderStyleColor>,
}

View file

@ -1,2 +0,0 @@
[border-bottom-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-color-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-color-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-color-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-color-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-color-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-width-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-width-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-width-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-width-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-bottom-width-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-applies-to-006.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-color-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-color-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-color-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-color-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-color-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-color-applies-to-006.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-width-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-width-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-width-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-width-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-width-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-left-width-applies-to-006.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-applies-to-006.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-color-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-color-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-color-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-color-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-color-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-color-applies-to-006.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-width-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-width-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-width-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-width-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-width-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-right-width-applies-to-006.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-color-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-color-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-color-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-color-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-color-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-width-applies-to-001.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-width-applies-to-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-width-applies-to-003.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-width-applies-to-004.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-top-width-applies-to-005.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[blocks-025.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[border-collapse-dynamic-cell-002.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-conflict-element-001a.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-conflict-element-001b.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-conflict-element-001c.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003e01.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003e02.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003e03.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003e04.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003e05.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003e06.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003f01.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[fixed-table-layout-003f02.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-collapse-dynamic-oof.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border-conflict-resolution.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[collapsed-border-remove-cell.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[border_collapse_row_a.html]
expected: FAIL