aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_2020
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout_2020')
-rw-r--r--components/layout_2020/style_ext.rs22
-rw-r--r--components/layout_2020/table/layout.rs121
2 files changed, 128 insertions, 15 deletions
diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs
index 53bf9e6df33..21283395789 100644
--- a/components/layout_2020/style_ext.rs
+++ b/components/layout_2020/style_ext.rs
@@ -16,7 +16,9 @@ use style::properties::ComputedValues;
use style::servo::selector_parser::PseudoElement;
use style::values::computed::basic_shape::ClipPath;
use style::values::computed::image::Image as ComputedImageLayer;
-use style::values::computed::{AlignItems, LengthPercentage, NonNegativeLengthPercentage, Size};
+use style::values::computed::{
+ AlignItems, BorderStyle, LengthPercentage, NonNegativeLengthPercentage, Size,
+};
use style::values::generics::box_::Perspective;
use style::values::generics::length::MaxSize;
use style::values::generics::position::{GenericAspectRatio, PreferredRatio};
@@ -250,6 +252,8 @@ pub(crate) trait ComputedValuesExt {
&self,
containing_block_writing_mode: WritingMode,
) -> LogicalSides<&LengthPercentage>;
+ fn border_style(&self, containing_block_writing_mode: WritingMode)
+ -> LogicalSides<BorderStyle>;
fn border_width(&self, containing_block_writing_mode: WritingMode) -> LogicalSides<Au>;
fn margin(
&self,
@@ -553,6 +557,22 @@ impl ComputedValuesExt for ComputedValues {
)
}
+ fn border_style(
+ &self,
+ containing_block_writing_mode: WritingMode,
+ ) -> LogicalSides<BorderStyle> {
+ let border = self.get_border();
+ LogicalSides::from_physical(
+ &PhysicalSides::new(
+ border.border_top_style,
+ border.border_right_style,
+ border.border_bottom_style,
+ border.border_left_style,
+ ),
+ containing_block_writing_mode,
+ )
+ }
+
fn border_width(&self, containing_block_writing_mode: WritingMode) -> LogicalSides<Au> {
let border = self.get_border();
LogicalSides::from_physical(
diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs
index e52bab12400..ed4aef17bf4 100644
--- a/components/layout_2020/table/layout.rs
+++ b/components/layout_2020/table/layout.rs
@@ -2,6 +2,7 @@
* 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 core::cmp::Ordering;
use std::ops::Range;
use app_units::{Au, MAX_AU};
@@ -16,7 +17,9 @@ use style::computed_values::table_layout::T as TableLayoutMode;
use style::computed_values::visibility::T as Visibility;
use style::logical_geometry::WritingMode;
use style::properties::ComputedValues;
-use style::values::computed::{LengthPercentage as ComputedLengthPercentage, Percentage};
+use style::values::computed::{
+ BorderStyle, LengthPercentage as ComputedLengthPercentage, Percentage,
+};
use style::values::generics::box_::{GenericVerticalAlign as VerticalAlign, VerticalAlignKeyword};
use style::values::generics::length::GenericLengthPercentageOrAuto::{Auto, LengthPercentage};
use style::Zero;
@@ -92,11 +95,79 @@ struct ColumnLayout {
has_originating_cells: bool,
}
+/// A calculated collapsed border.
+#[derive(Clone, Debug, Eq, PartialEq)]
+struct CollapsedBorder {
+ style: BorderStyle,
+ width: Au,
+}
+
+impl Default for CollapsedBorder {
+ fn default() -> Self {
+ Self::new(BorderStyle::None, Au::zero())
+ }
+}
+
+impl CollapsedBorder {
+ fn new(style: BorderStyle, width: Au) -> Self {
+ Self { style, width }
+ }
+
+ fn from_style(style: &ComputedValues, writing_mode: WritingMode) -> LogicalSides<Self> {
+ let border_style = style.border_style(writing_mode);
+ let border_width = style.border_width(writing_mode);
+ LogicalSides {
+ inline_start: Self::new(border_style.inline_start, border_width.inline_start),
+ inline_end: Self::new(border_style.inline_end, border_width.inline_end),
+ block_start: Self::new(border_style.block_start, border_width.block_start),
+ block_end: Self::new(border_style.block_end, border_width.block_end),
+ }
+ }
+
+ fn max_assign(&mut self, other: Self) {
+ if *self < other {
+ *self = other;
+ }
+ }
+}
+
+/// <https://drafts.csswg.org/css-tables/#border-specificity>
+/// > Given two borders styles, the border style having the most specificity is the border style which…
+/// > 1. … has the value "hidden" as border-style, if only one does
+/// > 2. … has the biggest border-width, once converted into css pixels
+/// > 3. … has the border-style which comes first in the following list:
+/// > double, solid, dashed, dotted, ridge, outset, groove, inset, none
+impl Ord for CollapsedBorder {
+ fn cmp(&self, other: &Self) -> Ordering {
+ let style_specificity = |border: &Self| match border.style {
+ BorderStyle::None => 0,
+ BorderStyle::Inset => 1,
+ BorderStyle::Groove => 2,
+ BorderStyle::Outset => 3,
+ BorderStyle::Ridge => 4,
+ BorderStyle::Dotted => 5,
+ BorderStyle::Dashed => 6,
+ BorderStyle::Solid => 7,
+ BorderStyle::Double => 8,
+ BorderStyle::Hidden => 9,
+ };
+ ((self.style == BorderStyle::Hidden).cmp(&(other.style == BorderStyle::Hidden)))
+ .then_with(|| self.width.cmp(&other.width))
+ .then_with(|| style_specificity(self).cmp(&style_specificity(other)))
+ }
+}
+
+impl PartialOrd for CollapsedBorder {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
/// The calculated collapsed borders.
#[derive(Clone, Debug, Default)]
struct CollapsedBorders {
- block: Vec<Au>,
- inline: Vec<Au>,
+ block: Vec<CollapsedBorder>,
+ inline: Vec<CollapsedBorder>,
}
/// A helper struct that performs the layout of the box tree version
@@ -2149,10 +2220,32 @@ impl<'a> TableLayout<'a> {
}
let mut collapsed_borders = CollapsedBorders {
- block: vec![Au::zero(); self.table.size.height + 1],
- inline: vec![Au::zero(); self.table.size.width + 1],
+ block: vec![Default::default(); self.table.size.height + 1],
+ inline: vec![Default::default(); self.table.size.width + 1],
};
+ let mut apply_border =
+ |style: &ComputedValues, block: &Range<usize>, inline: &Range<usize>| {
+ let border = CollapsedBorder::from_style(style, writing_mode);
+ collapsed_borders.block[block.start].max_assign(border.block_start);
+ collapsed_borders.block[block.end].max_assign(border.block_end);
+ collapsed_borders.inline[inline.start].max_assign(border.inline_start);
+ collapsed_borders.inline[inline.end].max_assign(border.inline_end);
+ };
+ let all_rows = 0..self.table.size.height;
+ let all_columns = 0..self.table.size.width;
+ for column_group in &self.table.column_groups {
+ apply_border(&column_group.style, &all_rows, &column_group.track_range);
+ }
+ for (column_index, column) in self.table.columns.iter().enumerate() {
+ apply_border(&column.style, &all_rows, &(column_index..column_index + 1));
+ }
+ for row_group in &self.table.row_groups {
+ apply_border(&row_group.style, &row_group.track_range, &all_columns);
+ }
+ for (row_index, row) in self.table.rows.iter().enumerate() {
+ apply_border(&row.style, &(row_index..row_index + 1), &all_columns);
+ }
for row_index in 0..self.table.size.height {
for column_index in 0..self.table.size.width {
let cell = match self.table.slots[row_index][column_index] {
@@ -2160,11 +2253,11 @@ impl<'a> TableLayout<'a> {
_ => continue,
};
- let border = cell.style.border_width(writing_mode);
- collapsed_borders.block[row_index].max_assign(border.block_start);
- collapsed_borders.block[row_index + cell.rowspan].max_assign(border.block_end);
- collapsed_borders.inline[column_index].max_assign(border.inline_start);
- collapsed_borders.inline[column_index + cell.colspan].max_assign(border.inline_end);
+ apply_border(
+ &cell.style,
+ &(row_index..row_index + cell.rowspan),
+ &(column_index..column_index + cell.colspan),
+ );
}
}
@@ -2180,10 +2273,10 @@ impl<'a> TableLayout<'a> {
let end_x = coordinates.x + cell.colspan;
let end_y = coordinates.y + cell.rowspan;
let mut result = LogicalSides {
- inline_start: collapsed_borders.inline[coordinates.x],
- inline_end: collapsed_borders.inline[end_x],
- block_start: collapsed_borders.block[coordinates.y],
- block_end: collapsed_borders.block[end_y],
+ inline_start: collapsed_borders.inline[coordinates.x].width,
+ inline_end: collapsed_borders.inline[end_x].width,
+ block_start: collapsed_borders.block[coordinates.y].width,
+ block_end: collapsed_borders.block[end_y].width,
};
if coordinates.x != 0 {