From 7ea15a6e726e4d59e18602e7dee81f3a8b4324f8 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:08:56 +0200 Subject: [PATCH 01/12] LibWeb: Add Ref tests for collapsed table border painting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin the visual behavior of the collapsing border model ahead of a painter rewrite: joint arbitration between crossing borders of unequal widths, 'hidden' suppressing its line without claiming the crossings, row borders staying out of rowspan interiors, and the ยง17.6.2.1 step-4 tie precedence (cell > row > table; leftmost/topmost cell first). --- ...collapsed-borders-hidden-at-joint-ref.html | 27 +++++++++ ...le-collapsed-borders-joint-widths-ref.html | 21 +++++++ ...e-collapsed-borders-span-interior-ref.html | 25 ++++++++ ...-collapsed-borders-tie-precedence-ref.html | 13 ++++ ...ble-collapsed-borders-hidden-at-joint.html | 25 ++++++++ .../table-collapsed-borders-joint-widths.html | 39 ++++++++++++ ...table-collapsed-borders-span-interior.html | 26 ++++++++ ...able-collapsed-borders-tie-precedence.html | 60 +++++++++++++++++++ 8 files changed, 236 insertions(+) create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-hidden-at-joint-ref.html create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-span-interior-ref.html create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-hidden-at-joint.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-joint-widths.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-span-interior.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-tie-precedence.html diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-hidden-at-joint-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-hidden-at-joint-ref.html new file mode 100644 index 0000000000000..bd4e5179ec43b --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-hidden-at-joint-ref.html @@ -0,0 +1,27 @@ + + + + + +
diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html new file mode 100644 index 0000000000000..f75cb9f14f47d --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html @@ -0,0 +1,21 @@ + + +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-span-interior-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-span-interior-ref.html new file mode 100644 index 0000000000000..746c7dec79e51 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-span-interior-ref.html @@ -0,0 +1,25 @@ + + + + + + +
diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html new file mode 100644 index 0000000000000..f16bcc1895728 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html @@ -0,0 +1,13 @@ + + +
+
+
+
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-hidden-at-joint.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-hidden-at-joint.html new file mode 100644 index 0000000000000..41ad777c7dc80 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-hidden-at-joint.html @@ -0,0 +1,25 @@ + + + + + + +
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-joint-widths.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-joint-widths.html new file mode 100644 index 0000000000000..09a2f2e00d50e --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-joint-widths.html @@ -0,0 +1,39 @@ + + + + + + +
+ + + +
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-span-interior.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-span-interior.html new file mode 100644 index 0000000000000..9a7720f43b5a8 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-span-interior.html @@ -0,0 +1,26 @@ + + + + + + + +
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-tie-precedence.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-tie-precedence.html new file mode 100644 index 0000000000000..4d093b66149e3 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-tie-precedence.html @@ -0,0 +1,60 @@ + + + + + +
+ + + +
+ + +
+ + +
From b00e347251ecd4dd7b584a35f3c127bf0418be2f Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:11:31 +0200 Subject: [PATCH 02/12] LibWeb: Paint collapsed table borders from every painting root The TableCollapsedBorder phase only fired during the BackgroundAndBorders descendant sweep and (too early) in the inline-level path. Tables that are themselves a painting root - stacking context roots, positioned pseudo stacking contexts, and floats - never received the phase on their own paintable and currently render collapsed borders only because the dispatch condition erroneously matches every descendant of a collapsing table (border-collapse is inherited). Fire the phase from all painting roots, right after the descendant background/border sweep so borders land on top of cell backgrounds, and move the inline-level call after the descendant sweep for the same reason. This is a prerequisite for tightening the dispatch condition to the table's own paintable. --- Libraries/LibWeb/Painting/StackingContext.cpp | 23 +++++++------ .../table-collapsed-borders-float-ref.html | 21 ++++++++++++ ...apsed-borders-in-stacking-context-ref.html | 25 ++++++++++++++ .../input/table-collapsed-borders-float.html | 23 +++++++++++++ ...collapsed-borders-in-stacking-context.html | 33 +++++++++++++++++++ 5 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-float-ref.html create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-in-stacking-context-ref.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-float.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-in-stacking-context.html diff --git a/Libraries/LibWeb/Painting/StackingContext.cpp b/Libraries/LibWeb/Painting/StackingContext.cpp index fb5c4a83d9526..3cbf96aab6891 100644 --- a/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Libraries/LibWeb/Painting/StackingContext.cpp @@ -248,17 +248,22 @@ static bool is_pure_inline_box(Paintable const& paintable) && !paintable.is_positioned(); } -static void paint_inline_level_non_positioned_descendant(DisplayListRecordingContext& context, Paintable const& paintable) +static void paint_subtree_backgrounds_and_borders(DisplayListRecordingContext& context, Paintable const& paintable) { paint_node(paintable, context, PaintPhase::Background); paint_node(paintable, context, PaintPhase::Border); - paint_node(paintable, context, PaintPhase::TableCollapsedBorder); // A pure inline paintable paints its own background/border in the inline-level phase. Its block descendants, if // any, are painted by the earlier BackgroundAndBorders descent through pure inline boxes. In today's layout trees, // this subtree sweep is a no-op for InlineNodes: it can only find inline children, floats, or positioned boxes, // all of which are skipped by the BackgroundAndBorders phase. if (!is_pure_inline_box(paintable)) StackingContext::paint_descendants(context, paintable, StackingContext::StackingContextPaintPhase::BackgroundAndBorders); + paint_node(paintable, context, PaintPhase::TableCollapsedBorder); +} + +static void paint_inline_level_non_positioned_descendant(DisplayListRecordingContext& context, Paintable const& paintable) +{ + paint_subtree_backgrounds_and_borders(context, paintable); // https://drafts.csswg.org/css2/#elaborate-stacking-contexts // "For inline-block and inline-table elements: [...] treat the element as if it created a new stacking context, @@ -275,9 +280,7 @@ void StackingContext::paint_node_as_stacking_context(Paintable const& paintable, return; } - paint_node(paintable, context, PaintPhase::Background); - paint_node(paintable, context, PaintPhase::Border); - paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBorders); + paint_subtree_backgrounds_and_borders(context, paintable); paint_descendants(context, paintable, StackingContextPaintPhase::Floats); paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced); paint_node(paintable, context, PaintPhase::Foreground); @@ -344,19 +347,14 @@ void StackingContext::paint_descendants(DisplayListRecordingContext& context, Pa switch (phase) { case StackingContextPaintPhase::BackgroundAndBorders: if (!child_is_inline_or_replaced && !child.is_floating()) { - paint_node(child, context, PaintPhase::Background); - paint_node(child, context, PaintPhase::Border); - paint_descendants(context, child, phase); - paint_node(child, context, PaintPhase::TableCollapsedBorder); + paint_subtree_backgrounds_and_borders(context, child); } else if (is_pure_inline_box(child)) { paint_descendants(context, child, phase); } break; case StackingContextPaintPhase::Floats: if (child.is_floating()) { - paint_node(child, context, PaintPhase::Background); - paint_node(child, context, PaintPhase::Border); - paint_descendants(context, child, StackingContextPaintPhase::BackgroundAndBorders); + paint_subtree_backgrounds_and_borders(context, child); } // Atomic inline-level descendants such as inline-blocks and inline tables participate in the parent's // inline-level painting step, so their internal floats must not be painted early during the ancestor's @@ -429,6 +427,7 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Draw the background and borders for block-level children (step 4) paint_descendants(context, paintable_box(), StackingContextPaintPhase::BackgroundAndBorders); + paint_node(paintable_box(), context, PaintPhase::TableCollapsedBorder); // Draw the non-positioned floats (step 5) if (!m_non_positioned_floating_descendants.is_empty()) paint_descendants(context, paintable_box(), StackingContextPaintPhase::Floats); diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-float-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-float-ref.html new file mode 100644 index 0000000000000..d1a3af5313fc0 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-float-ref.html @@ -0,0 +1,21 @@ + + + + + +
diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-in-stacking-context-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-in-stacking-context-ref.html new file mode 100644 index 0000000000000..467e2f4f86fd3 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-in-stacking-context-ref.html @@ -0,0 +1,25 @@ + + + + + +
+ + + +
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-float.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-float.html new file mode 100644 index 0000000000000..c4686c7bc7174 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-float.html @@ -0,0 +1,23 @@ + + + + + + +
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-in-stacking-context.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-in-stacking-context.html new file mode 100644 index 0000000000000..9fdef48173d7d --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-in-stacking-context.html @@ -0,0 +1,33 @@ + + + + + + +
+ + + +
From 4e7afb5b843e0de8c32ab66f477d2d5c1ad295c4 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:13:20 +0200 Subject: [PATCH 03/12] LibWeb: Only paint table borders from the table's own paintable The dispatch condition also matched any paintable whose computed border-collapse is 'collapse' - but border-collapse is inherited, so every row and cell of a collapsing table ran paint_table_borders over the whole grid again, and a cell containing a nested table collected the inner table's cells and painted their borders through the collapsing-model path on top of the inner table's own rendering. Now that every painting root fires the TableCollapsedBorder phase on the table itself, restrict the dispatch to table boxes. --- Libraries/LibWeb/Painting/Paintable.cpp | 2 +- ...le-collapsed-borders-nested-table-ref.html | 35 +++++++++++++++++++ .../table-collapsed-borders-nested-table.html | 35 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-nested-table-ref.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-nested-table.html diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index 3c7eace64c215..73a5123d4cc87 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -1907,7 +1907,7 @@ void Paintable::paint(DisplayListRecordingContext& context, PaintPhase phase) co paint_border(context); } - if ((display().is_table_inside() || layout_node().border_collapse() == CSS::BorderCollapse::Collapse) && phase == PaintPhase::TableCollapsedBorder) { + if (display().is_table_inside() && phase == PaintPhase::TableCollapsedBorder) { paint_table_borders(context, *this); } diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-nested-table-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-nested-table-ref.html new file mode 100644 index 0000000000000..896825bda1b01 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-nested-table-ref.html @@ -0,0 +1,35 @@ + + + + + + +
+ + + +
+
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-nested-table.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-nested-table.html new file mode 100644 index 0000000000000..7d71b723f8c22 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-nested-table.html @@ -0,0 +1,35 @@ + + + + + + + +
+ + + +
+
From 74af1b15d7c21272f3f44452c89389f036b3f948 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:15:01 +0200 Subject: [PATCH 04/12] LibWeb: Stop double-painting separate-borders cells with radii The border-radius fallback loop at the end of paint_table_borders ran for both border models, but the separated-borders path had already painted every cell's borders (radii included), so any separate-mode cell with a border-radius was painted twice - visibly darker with semi-transparent border colors. It also ignored empty-cells: hide. In the collapsing model border-radius does not apply, so the loop served no purpose there either. --- .../LibWeb/Painting/TableBordersPainting.cpp | 19 --------------- .../table-separate-borders-radius-ref.html | 18 ++++++++++++++ .../input/table-separate-borders-radius.html | 24 +++++++++++++++++++ 3 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 Tests/LibWeb/Ref/expected/table-separate-borders-radius-ref.html create mode 100644 Tests/LibWeb/Ref/input/table-separate-borders-radius.html diff --git a/Libraries/LibWeb/Painting/TableBordersPainting.cpp b/Libraries/LibWeb/Painting/TableBordersPainting.cpp index c8039fc24ec3f..ee4a97bc9f0dc 100644 --- a/Libraries/LibWeb/Painting/TableBordersPainting.cpp +++ b/Libraries/LibWeb/Painting/TableBordersPainting.cpp @@ -456,25 +456,6 @@ void paint_table_borders(DisplayListRecordingContext& context, Paintable const& } paint_collected_edges(context, border_edge_painting_info_list); - - for (auto const& cell_box : cell_boxes) { - auto const& border_radii_data = cell_box.normalized_border_radii_data(); - auto top_left = border_radii_data.top_left.as_corner(context.device_pixel_converter()); - auto top_right = border_radii_data.top_right.as_corner(context.device_pixel_converter()); - auto bottom_right = border_radii_data.bottom_right.as_corner(context.device_pixel_converter()); - auto bottom_left = border_radii_data.bottom_left.as_corner(context.device_pixel_converter()); - if (!top_left && !top_right && !bottom_left && !bottom_right) { - continue; - } else { - auto borders_data = cell_box.override_borders_data().has_value() ? Paintable::remove_element_kind_from_borders_data(cell_box.override_borders_data().value()) : BordersData { - .top = cell_box.box_model().border.top == 0 ? CSS::BorderData() : cell_box.layout_node().border_top(), - .right = cell_box.box_model().border.right == 0 ? CSS::BorderData() : cell_box.layout_node().border_right(), - .bottom = cell_box.box_model().border.bottom == 0 ? CSS::BorderData() : cell_box.layout_node().border_bottom(), - .left = cell_box.box_model().border.left == 0 ? CSS::BorderData() : cell_box.layout_node().border_left(), - }; - paint_all_borders(context.display_list_recorder(), context.rounded_device_rect(cell_box.absolute_border_box_rect()), cell_box.normalized_border_radii_data().as_corners(context.device_pixel_converter()), borders_data.to_device_pixels(context)); - } - } } } diff --git a/Tests/LibWeb/Ref/expected/table-separate-borders-radius-ref.html b/Tests/LibWeb/Ref/expected/table-separate-borders-radius-ref.html new file mode 100644 index 0000000000000..c6b90112db311 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-separate-borders-radius-ref.html @@ -0,0 +1,18 @@ + + +
+
+
+
diff --git a/Tests/LibWeb/Ref/input/table-separate-borders-radius.html b/Tests/LibWeb/Ref/input/table-separate-borders-radius.html new file mode 100644 index 0000000000000..b2bfc8878e776 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-separate-borders-radius.html @@ -0,0 +1,24 @@ + + + + + + +
From 184e7eb4b7fb38840358b698d7498e2f32f785a4 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:18:02 +0200 Subject: [PATCH 05/12] LibWeb: Commit the collapsed-borders flag instead of inferring it compute_absolute_border_box_rect() halves the used border widths of boxes laid out with the collapsing border model, and detected them by whether override_borders_data is present. Commit the flag layout already tracks as a bit on the paintable instead, so the paint-side geometry no longer depends on the per-cell override payload - which a following change removes in favor of a per-table edge grid. No behavior change: the flag and the override data are only ever set together during table border conflict resolution. --- Libraries/LibWeb/Layout/LayoutRustBridge.cpp | 3 ++- Libraries/LibWeb/Painting/Paintable.cpp | 3 ++- Libraries/LibWeb/Painting/Paintable.h | 4 ++++ Libraries/LibWeb/Rust/src/layout/commit.rs | 2 ++ Libraries/LibWeb/Rust/src/layout/fragment_tree.rs | 2 ++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Libraries/LibWeb/Layout/LayoutRustBridge.cpp b/Libraries/LibWeb/Layout/LayoutRustBridge.cpp index b4300bb486ed2..a987b6b604ba6 100644 --- a/Libraries/LibWeb/Layout/LayoutRustBridge.cpp +++ b/Libraries/LibWeb/Layout/LayoutRustBridge.cpp @@ -833,7 +833,8 @@ RustFFI::FfiCommitSink LayoutRustBridge::commit_sink() CSSPixels::from_raw(metrics.content_offset.y), }); if (metrics.has_containing_line_box_index) - paintable.set_containing_line_box_index(metrics.containing_line_box_index); }, + paintable.set_containing_line_box_index(metrics.containing_line_box_index); + paintable.set_uses_collapsing_borders_model(metrics.uses_collapsing_borders_model); }, .set_override_borders = [](void*, void* paintable_pointer, RustFFI::FfiBordersData borders) { static_cast(paintable_pointer)->set_override_borders_data({ .top = from_ffi_border_data_with_element_kind(borders.top), .right = from_ffi_border_data_with_element_kind(borders.right), diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index 73a5123d4cc87..3db1a4cbcde13 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -1157,6 +1157,7 @@ void Paintable::reset_for_relayout() m_overflow_data.clear(); m_override_borders_data.clear(); m_table_cell_coordinates.clear(); + m_uses_collapsing_borders_model = false; m_containing_line_box_index.clear(); m_sticky_insets = nullptr; @@ -1514,7 +1515,7 @@ CSSPixelRect Paintable::compute_absolute_border_box_rect() const { auto padded_rect = this->absolute_padding_box_rect(); CSSPixelRect rect; - auto use_collapsing_borders_model = override_borders_data().has_value(); + auto use_collapsing_borders_model = uses_collapsing_borders_model(); // Implement the collapsing border model https://www.w3.org/TR/CSS22/tables.html#collapsing-borders. auto border_top = box_model().border.top; auto border_bottom = box_model().border.bottom; diff --git a/Libraries/LibWeb/Painting/Paintable.h b/Libraries/LibWeb/Painting/Paintable.h index 15f016f33547c..c376cc2b5863d 100644 --- a/Libraries/LibWeb/Painting/Paintable.h +++ b/Libraries/LibWeb/Painting/Paintable.h @@ -390,6 +390,9 @@ class WEB_API Paintable void set_table_cell_coordinates(TableCellCoordinates const& table_cell_coordinates) { m_table_cell_coordinates = table_cell_coordinates; } auto const& table_cell_coordinates() const { return m_table_cell_coordinates; } + void set_uses_collapsing_borders_model(bool value) { m_uses_collapsing_borders_model = value; } + bool uses_collapsing_borders_model() const { return m_uses_collapsing_borders_model; } + enum class ShrinkRadiiForBorders { Yes, No @@ -560,6 +563,7 @@ class WEB_API Paintable bool m_absolutely_positioned : 1 { false }; bool m_floating : 1 { false }; bool m_inline : 1 { false }; + bool m_uses_collapsing_borders_model : 1 { false }; CSS::Display m_display; RefPtr m_stacking_context; diff --git a/Libraries/LibWeb/Rust/src/layout/commit.rs b/Libraries/LibWeb/Rust/src/layout/commit.rs index 433fb9cb0fab3..07444774a5ec7 100644 --- a/Libraries/LibWeb/Rust/src/layout/commit.rs +++ b/Libraries/LibWeb/Rust/src/layout/commit.rs @@ -39,6 +39,7 @@ pub struct FfiCommittedBoxMetrics { pub inset_bottom: crate::layout::CssPixels, pub containing_line_box_index: usize, pub has_containing_line_box_index: bool, + pub uses_collapsing_borders_model: bool, } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] @@ -203,6 +204,7 @@ fn commit_subtree( inset_bottom: link.inset_bottom, containing_line_box_index: link.containing_line_box_index.unwrap_or(0), has_containing_line_box_index: link.containing_line_box_index.is_some(), + uses_collapsing_borders_model: fragment.uses_collapsing_borders_model, }, ); } diff --git a/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs b/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs index 8e4e447fba45a..4fba1268b6769 100644 --- a/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs +++ b/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs @@ -21,6 +21,7 @@ pub(crate) struct Fragment { pub(crate) padding_right: CssPixels, pub(crate) padding_top: CssPixels, pub(crate) padding_bottom: CssPixels, + pub(crate) uses_collapsing_borders_model: bool, pub(crate) table_cell_coordinates: Option, pub(crate) override_borders_data: Option, pub(crate) line_data: Option>, @@ -199,6 +200,7 @@ fn snapshot_fragment( padding_right: used.padding_right.get(), padding_top: used.padding_top.get(), padding_bottom: used.padding_bottom.get(), + uses_collapsing_borders_model: used.uses_collapsing_borders_model.get(), table_cell_coordinates, override_borders_data, line_data, From f34db23f96c5ce7a11f3a93600a11cca1d5719cb Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:22:17 +0200 Subject: [PATCH 06/12] LibWeb: Paint separate-borders table cell borders in the border phase Cells were unconditionally excluded from the border paint phase, so the table's TableCollapsedBorder pass carried a separated-borders side path that reimplemented cell border painting against device-snapped grid rects. The snapping was needed when rounded_device_rect() rounded widths independently; it rounds edges nowadays, and adjacent cells share bit-exact CSS coordinates, so the regular border phase produces the same pixels - plus border-image support the side path lacked. Suppress the border phase only for boxes resolved by the collapsing model (and for empty cells hidden by empty-cells, matching the background suppression), and drop the separated-borders path from paint_table_borders. --- Libraries/LibWeb/Painting/Paintable.cpp | 2 +- .../LibWeb/Painting/TableBordersPainting.cpp | 21 +++------------ ...able-separate-borders-empty-cells-ref.html | 27 +++++++++++++++++++ .../table-separate-borders-empty-cells.html | 26 ++++++++++++++++++ 4 files changed, 57 insertions(+), 19 deletions(-) create mode 100644 Tests/LibWeb/Ref/expected/table-separate-borders-empty-cells-ref.html create mode 100644 Tests/LibWeb/Ref/input/table-separate-borders-empty-cells.html diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index 3db1a4cbcde13..f3a8c022c2263 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -1904,7 +1904,7 @@ void Paintable::paint(DisplayListRecordingContext& context, PaintPhase phase) co } auto const is_table_with_collapsed_borders = display().is_table_inside() && layout_node().border_collapse() == CSS::BorderCollapse::Collapse; - if (!display().is_table_cell() && !is_table_with_collapsed_borders && phase == PaintPhase::Border) { + if (phase == PaintPhase::Border && !uses_collapsing_borders_model() && !is_table_with_collapsed_borders && !empty_cells_property_applies()) { paint_border(context); } diff --git a/Libraries/LibWeb/Painting/TableBordersPainting.cpp b/Libraries/LibWeb/Painting/TableBordersPainting.cpp index ee4a97bc9f0dc..e405562a9b577 100644 --- a/Libraries/LibWeb/Painting/TableBordersPainting.cpp +++ b/Libraries/LibWeb/Painting/TableBordersPainting.cpp @@ -376,20 +376,11 @@ static DeviceBorderDataWithElementKind device_border_data_from_css_border_data(P }; } -static void paint_separate_cell_borders(Paintable const& cell_box, HashMap const& cell_coordinates_to_device_rect, DisplayListRecordingContext& context) -{ - auto borders_data = cell_box.override_borders_data().has_value() ? Paintable::remove_element_kind_from_borders_data(cell_box.override_borders_data().value()) : BordersData { - .top = cell_box.box_model().border.top == 0 ? CSS::BorderData() : cell_box.layout_node().border_top(), - .right = cell_box.box_model().border.right == 0 ? CSS::BorderData() : cell_box.layout_node().border_right(), - .bottom = cell_box.box_model().border.bottom == 0 ? CSS::BorderData() : cell_box.layout_node().border_bottom(), - .left = cell_box.box_model().border.left == 0 ? CSS::BorderData() : cell_box.layout_node().border_left(), - }; - auto cell_rect = cell_coordinates_to_device_rect.get({ cell_box.table_cell_coordinates()->row_index, cell_box.table_cell_coordinates()->column_index }).value(); - paint_all_borders(context.display_list_recorder(), cell_rect, cell_box.normalized_border_radii_data().as_corners(context.device_pixel_converter()), borders_data.to_device_pixels(context)); -} - void paint_table_borders(DisplayListRecordingContext& context, Paintable const& table_paintable) { + if (table_paintable.layout_node().border_collapse() == CSS::BorderCollapse::Separate) + return; + // Partial implementation of painting according to the collapsing border model: // https://www.w3.org/TR/CSS22/tables.html#collapsing-borders Vector cell_boxes; @@ -408,12 +399,6 @@ void paint_table_borders(DisplayListRecordingContext& context, Paintable const& } auto cell_coordinates_to_device_rect = snap_cells_to_device_coordinates(cell_coordinates_to_box, row_count, column_count, context); for (auto const& cell_box : cell_boxes) { - if (table_paintable.layout_node().border_collapse() == CSS::BorderCollapse::Separate) { - if (cell_box.layout_node().empty_cells() == CSS::EmptyCells::Hide && !cell_box.has_children()) - continue; - paint_separate_cell_borders(cell_box, cell_coordinates_to_device_rect, context); - continue; - } auto css_borders_data = cell_box.override_borders_data().has_value() ? cell_box.override_borders_data().value() : Paintable::BordersDataWithElementKind { .top = { .border_data = cell_box.box_model().border.top == 0 ? CSS::BorderData() : cell_box.layout_node().border_top(), .element_kind = Paintable::ConflictingElementKind::Cell }, .right = { .border_data = cell_box.box_model().border.right == 0 ? CSS::BorderData() : cell_box.layout_node().border_right(), .element_kind = Paintable::ConflictingElementKind::Cell }, diff --git a/Tests/LibWeb/Ref/expected/table-separate-borders-empty-cells-ref.html b/Tests/LibWeb/Ref/expected/table-separate-borders-empty-cells-ref.html new file mode 100644 index 0000000000000..4c4d3f8ab21c6 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-separate-borders-empty-cells-ref.html @@ -0,0 +1,27 @@ + + + + + +
x
diff --git a/Tests/LibWeb/Ref/input/table-separate-borders-empty-cells.html b/Tests/LibWeb/Ref/input/table-separate-borders-empty-cells.html new file mode 100644 index 0000000000000..5de86f58b1c92 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-separate-borders-empty-cells.html @@ -0,0 +1,26 @@ + + + + + + +
x
From 947f261d7912380486585619981b66450e0bb52b Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:25:24 +0200 Subject: [PATCH 07/12] LibWeb: Let colgroup borders participate in border conflict resolution The column pass walked column groups only to find their columns; the groups' own borders were never applied, even though the C++ side has always had a ConflictingElementKind::ColumnGroup. Record each group's column range while walking its columns and apply the group borders across the whole range after the columns, matching the CSS 2.2 precedence (below columns, above the table). A column group's extent is defined by its columns - a group without any is not part of the grid, matching column counting during grid formation (the span attribute on a childless colgroup remains unsupported there too). --- .../src/layout/table_formatting_context.rs | 10 +++++ .../table-collapsed-borders-colgroup-ref.html | 39 +++++++++++++++++++ .../table-collapsed-borders-colgroup.html | 29 ++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 Tests/LibWeb/Ref/expected/table-collapsed-borders-colgroup-ref.html create mode 100644 Tests/LibWeb/Ref/input/table-collapsed-borders-colgroup.html diff --git a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs index 9dbd97f7f604f..da537f620272e 100644 --- a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs @@ -8,6 +8,7 @@ pub(crate) const ELEMENT_CELL: u8 = 0; pub(crate) const ELEMENT_ROW: u8 = 1; pub(crate) const ELEMENT_ROW_GROUP: u8 = 2; pub(crate) const ELEMENT_COLUMN: u8 = 3; +pub(crate) const ELEMENT_COLUMN_GROUP: u8 = 4; pub(crate) const ELEMENT_TABLE: u8 = 5; pub(crate) const LINE_STYLE_NONE: u8 = 0; @@ -1044,7 +1045,9 @@ impl TableFormattingContext { // Column () elements. let mut column_index = 0usize; + let mut column_group_ranges = Vec::new(); for column_group in self.matching_children(self.table_box, |facts| facts.is_table_column_group()) { + let group_start = column_index; for column in self.matching_children(column_group, |facts| facts.is_table_column()) { let span = self.table_column_span(column); let end = (column_index + span).min(column_count); @@ -1054,6 +1057,13 @@ impl TableFormattingContext { column_index += 1; } } + column_group_ranges.push((column_group, group_start, column_index)); + } + for (column_group, group_start, group_end) in column_group_ranges { + if group_start < group_end { + let borders = self.element_borders(column_group); + grid.apply_borders(borders, 0, row_count, group_start, group_end, ELEMENT_COLUMN_GROUP); + } } let table_borders = self.element_borders(self.table_box); grid.apply_borders(table_borders, 0, row_count, 0, column_count, ELEMENT_TABLE); diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-colgroup-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-colgroup-ref.html new file mode 100644 index 0000000000000..d245c8e1ff37c --- /dev/null +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-colgroup-ref.html @@ -0,0 +1,39 @@ + + + + + +
diff --git a/Tests/LibWeb/Ref/input/table-collapsed-borders-colgroup.html b/Tests/LibWeb/Ref/input/table-collapsed-borders-colgroup.html new file mode 100644 index 0000000000000..58affed166966 --- /dev/null +++ b/Tests/LibWeb/Ref/input/table-collapsed-borders-colgroup.html @@ -0,0 +1,29 @@ + + + + + + + + +
From 5a1cfd0b564b1b801bcf0678094b50b0c06ead82 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:27:14 +0200 Subject: [PATCH 08/12] LibWeb: Record a joint-arbitration ordinal in the collapsed border grid Give every source element applied during border conflict resolution a monotonically increasing order and store it on the winning segment. Since sources are applied in decreasing precedence with a strictly- improving replacement test, the stored order is minimal among equally specific candidates - exactly the tiebreaker a painter needs to decide which of the edges meeting at a border intersection covers the crossing when width and style are equal. No behavior change yet; the order is consumed once painting reads the resolved edge grid directly. --- .../src/layout/table_formatting_context.rs | 59 ++++++++++++++----- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs index da537f620272e..b261c8ad386ad 100644 --- a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs @@ -109,16 +109,23 @@ pub(crate) struct ElementBorders { // first. A candidate border only replaces the current winner of a segment when it is strictly more // specific (steps 1-3 of the border conflict resolution algorithm), so ties resolve towards the // earlier-applied part, which implements step 4 without tracking element kinds or coordinates. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub(crate) struct CollapsedBorderSegment { + pub(crate) border_data: FfiBorderData, + pub(crate) element_kind: u8, + pub(crate) source_order: u32, +} + pub(crate) struct CollapsedBorderGrid { - horizontal_lines: Vec>, - vertical_lines: Vec>, + horizontal_lines: Vec>, + vertical_lines: Vec>, } impl CollapsedBorderGrid { pub(crate) fn new(row_count: usize, column_count: usize) -> Self { Self { - horizontal_lines: vec![vec![FfiBorderDataWithElementKind::default(); column_count]; row_count + 1], - vertical_lines: vec![vec![FfiBorderDataWithElementKind::default(); row_count]; column_count + 1], + horizontal_lines: vec![vec![CollapsedBorderSegment::default(); column_count]; row_count + 1], + vertical_lines: vec![vec![CollapsedBorderSegment::default(); row_count]; column_count + 1], } } @@ -130,6 +137,7 @@ impl CollapsedBorderGrid { column_start: usize, column_end: usize, element_kind: u8, + source_order: u32, ) { Self::apply_to_segments( &mut self.horizontal_lines[row_start], @@ -137,6 +145,7 @@ impl CollapsedBorderGrid { column_end, borders.top, element_kind, + source_order, ); Self::apply_to_segments( &mut self.horizontal_lines[row_end], @@ -144,6 +153,7 @@ impl CollapsedBorderGrid { column_end, borders.bottom, element_kind, + source_order, ); Self::apply_to_segments( &mut self.vertical_lines[column_start], @@ -151,6 +161,7 @@ impl CollapsedBorderGrid { row_end, borders.left, element_kind, + source_order, ); Self::apply_to_segments( &mut self.vertical_lines[column_end], @@ -158,6 +169,7 @@ impl CollapsedBorderGrid { row_end, borders.right, element_kind, + source_order, ); } @@ -167,16 +179,18 @@ impl CollapsedBorderGrid { row_end: usize, column_start: usize, column_end: usize, + source_order: u32, ) { // Segments strictly inside a spanning cell are not borders of any element; mark them as hidden // so that borders of rows and columns crossing the span cannot win there. - let hidden = FfiBorderDataWithElementKind { + let hidden = CollapsedBorderSegment { border_data: FfiBorderData { color: 0, line_style: LINE_STYLE_HIDDEN, width: CssPixels::default(), }, element_kind: ELEMENT_CELL, + source_order, }; for row in row_start + 1..row_end { for column in column_start..column_end { @@ -198,7 +212,7 @@ impl CollapsedBorderGrid { column_end: usize, own: ElementBorders, ) -> FfiBordersData { - let harvest = |winner: FfiBorderDataWithElementKind, own_border: FfiBorderData| { + let harvest = |winner: CollapsedBorderSegment, own_border: FfiBorderData| { // A winner whose style is 'none' means every border meeting at this edge is 'none'; fall // back to the cell's own (invisible) border so the stored winner matches the cell. if winner.border_data.line_style == LINE_STYLE_NONE { @@ -207,7 +221,10 @@ impl CollapsedBorderGrid { element_kind: ELEMENT_CELL, } } else { - winner + FfiBorderDataWithElementKind { + border_data: winner.border_data, + element_kind: winner.element_kind, + } } }; FfiBordersData { @@ -231,26 +248,28 @@ impl CollapsedBorderGrid { } fn apply_to_segments( - line: &mut [FfiBorderDataWithElementKind], + line: &mut [CollapsedBorderSegment], start: usize, end: usize, data: FfiBorderData, element_kind: u8, + source_order: u32, ) { if data.line_style == LINE_STYLE_NONE { return; } for segment in &mut line[start..end] { if candidate_wins(data, segment.border_data) { - *segment = FfiBorderDataWithElementKind { + *segment = CollapsedBorderSegment { border_data: data, element_kind, + source_order, }; } } } - fn most_specific(line: &[FfiBorderDataWithElementKind], start: usize, end: usize) -> FfiBorderDataWithElementKind { + fn most_specific(line: &[CollapsedBorderSegment], start: usize, end: usize) -> CollapsedBorderSegment { let mut winner = line[start]; for segment in &line[start + 1..end] { if candidate_wins(segment.border_data, winner.border_data) { @@ -993,17 +1012,25 @@ impl TableFormattingContext { let row_count = self.rows.len(); let column_count = self.columns.len(); let mut grid = CollapsedBorderGrid::new(row_count, column_count); + let mut next_source_order = 0u32; + let mut take_source_order = move || { + let source_order = next_source_order; + next_source_order += 1; + source_order + }; // Cells, column by column so that on ties the cell further to the left, then further to the // top, wins. TableCell spans are already clipped to the table end by TableGrid. let mut cells = self.cells.clone(); cells.sort_by_key(|cell| (cell.column_index, cell.row_index)); for cell in cells { + let source_order = take_source_order(); if cell.row_span > 1 || cell.column_span > 1 { grid.hide_segments_inside_span( cell.row_index, cell.row_index + cell.row_span, cell.column_index, cell.column_index + cell.column_span, + source_order, ); } let borders = self.element_borders(cell.box_); @@ -1014,12 +1041,13 @@ impl TableFormattingContext { cell.column_index, cell.column_index + cell.column_span, ELEMENT_CELL, + source_order, ); } for row_index in 0..row_count { let row_box = self.rows[row_index].box_; let borders = self.element_borders(row_box); - grid.apply_borders(borders, row_index, row_index + 1, 0, column_count, ELEMENT_ROW); + grid.apply_borders(borders, row_index, row_index + 1, 0, column_count, ELEMENT_ROW, take_source_order()); } // Row groups, in the order their rows appear in the grid. Rows of a group are contiguous in // m_rows, since TableGrid collects them in tree order. @@ -1040,7 +1068,7 @@ impl TableFormattingContext { row_index += 1; } let borders = self.element_borders(group); - grid.apply_borders(borders, start, row_index, 0, column_count, ELEMENT_ROW_GROUP); + grid.apply_borders(borders, start, row_index, 0, column_count, ELEMENT_ROW_GROUP, take_source_order()); } // Column () elements. @@ -1052,8 +1080,9 @@ impl TableFormattingContext { let span = self.table_column_span(column); let end = (column_index + span).min(column_count); let borders = self.element_borders(column); + let source_order = take_source_order(); while column_index < end { - grid.apply_borders(borders, 0, row_count, column_index, column_index + 1, ELEMENT_COLUMN); + grid.apply_borders(borders, 0, row_count, column_index, column_index + 1, ELEMENT_COLUMN, source_order); column_index += 1; } } @@ -1062,11 +1091,11 @@ impl TableFormattingContext { for (column_group, group_start, group_end) in column_group_ranges { if group_start < group_end { let borders = self.element_borders(column_group); - grid.apply_borders(borders, 0, row_count, group_start, group_end, ELEMENT_COLUMN_GROUP); + grid.apply_borders(borders, 0, row_count, group_start, group_end, ELEMENT_COLUMN_GROUP, take_source_order()); } } let table_borders = self.element_borders(self.table_box); - grid.apply_borders(table_borders, 0, row_count, 0, column_count, ELEMENT_TABLE); + grid.apply_borders(table_borders, 0, row_count, 0, column_count, ELEMENT_TABLE, take_source_order()); for cell_index in 0..self.cells.len() { let cell = self.cells[cell_index]; From 83a512d23484b5a89f9b5081eee3d246c119cad1 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:33:52 +0200 Subject: [PATCH 09/12] LibWeb: Commit resolved collapsed table borders onto the table paintable Border conflict resolution builds a per-grid-line-segment winner grid but threw it away after harvesting per-cell maxima, forcing painting to reconstruct the grid topology and geometry from per-cell data and to re-arbitrate intersections by re-implementing the specificity rules. Keep the resolved grid and, once column and row sizes are final, flatten it into a per-table payload: the winning edge of every grid line segment plus the grid line offsets relative to the table's content box. It travels to the table's paintable through the usual rare-payload commit path (like grid layout data), and is skipped entirely for separated-borders tables and collapsed tables with no paintable edge, so most tables ship nothing. Not consumed yet; the collapsed border painter switches to it next. --- Libraries/LibWeb/Layout/LayoutRustBridge.cpp | 28 +++++ .../LibWeb/Painting/CollapsedTableBorders.h | 30 ++++++ Libraries/LibWeb/Painting/Paintable.cpp | 1 + Libraries/LibWeb/Painting/Paintable.h | 5 + Libraries/LibWeb/Rust/src/layout/commit.rs | 6 ++ .../LibWeb/Rust/src/layout/fragment_tree.rs | 4 + .../src/layout/table_formatting_context.rs | 101 ++++++++++++++++++ .../LibWeb/Rust/src/layout/used_values.rs | 6 ++ 8 files changed, 181 insertions(+) create mode 100644 Libraries/LibWeb/Painting/CollapsedTableBorders.h diff --git a/Libraries/LibWeb/Layout/LayoutRustBridge.cpp b/Libraries/LibWeb/Layout/LayoutRustBridge.cpp index a987b6b604ba6..82a7928db2786 100644 --- a/Libraries/LibWeb/Layout/LayoutRustBridge.cpp +++ b/Libraries/LibWeb/Layout/LayoutRustBridge.cpp @@ -274,6 +274,31 @@ static OwnPtr build_grid_layout_data(RustFFI::FfiGridLayoutData return data; } +static CSS::BorderData from_ffi_border_data(RustFFI::FfiBorderData const&); + +static OwnPtr build_collapsed_table_borders(RustFFI::FfiCollapsedTableBorders const& ffi_borders) +{ + auto borders = make(); + borders->row_offsets.ensure_capacity(ffi_borders.row_count + 1); + for (size_t i = 0; i <= ffi_borders.row_count; ++i) + borders->row_offsets.unchecked_append(CSSPixels::from_raw(ffi_borders.row_offsets[i])); + borders->column_offsets.ensure_capacity(ffi_borders.column_count + 1); + for (size_t i = 0; i <= ffi_borders.column_count; ++i) + borders->column_offsets.unchecked_append(CSSPixels::from_raw(ffi_borders.column_offsets[i])); + auto build_edges = [](Vector& edges, RustFFI::FfiCollapsedBorderEdge const* ffi_edges, size_t count) { + edges.ensure_capacity(count); + for (size_t i = 0; i < count; ++i) { + edges.unchecked_append({ + .border = from_ffi_border_data(ffi_edges[i].border_data), + .source_order = ffi_edges[i].source_order, + }); + } + }; + build_edges(borders->horizontal_edges, ffi_borders.horizontal_edges, (ffi_borders.row_count + 1) * ffi_borders.column_count); + build_edges(borders->vertical_edges, ffi_borders.vertical_edges, (ffi_borders.column_count + 1) * ffi_borders.row_count); + return borders; +} + static RustFFI::FfiAffineTransform to_ffi_affine_transform(Gfx::AffineTransform const& transform) { return { @@ -966,6 +991,9 @@ RustFFI::FfiCommitSink LayoutRustBridge::commit_sink() auto& paintable = *static_cast(paintable_pointer); paintable.set_used_values_for_grid_template_columns(build_used_grid_track_list(*columns)); paintable.set_used_values_for_grid_template_rows(build_used_grid_track_list(*rows)); }, + .set_collapsed_table_borders = [](void*, void* paintable_pointer, RustFFI::FfiCollapsedTableBorders const* borders) { + VERIFY(borders); + static_cast(paintable_pointer)->set_collapsed_table_borders(build_collapsed_table_borders(*borders)); }, .finish_node = [](void*, void* node_pointer, void* paintable_pointer, void* parent_paintable_pointer, void* insert_before_paintable_pointer) { auto& node = *static_cast(node_pointer); auto* paintable = static_cast(paintable_pointer); diff --git a/Libraries/LibWeb/Painting/CollapsedTableBorders.h b/Libraries/LibWeb/Painting/CollapsedTableBorders.h new file mode 100644 index 0000000000000..8a10196321e24 --- /dev/null +++ b/Libraries/LibWeb/Painting/CollapsedTableBorders.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::Painting { + +struct CollapsedBorderEdge { + CSS::BorderData border; + u32 source_order { 0 }; +}; + +struct CollapsedTableBorders { + Vector row_offsets; + Vector column_offsets; + Vector horizontal_edges; + Vector vertical_edges; + + size_t row_count() const { return row_offsets.size() - 1; } + size_t column_count() const { return column_offsets.size() - 1; } +}; + +} diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index f3a8c022c2263..deaed53652331 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -1157,6 +1157,7 @@ void Paintable::reset_for_relayout() m_overflow_data.clear(); m_override_borders_data.clear(); m_table_cell_coordinates.clear(); + m_collapsed_table_borders = nullptr; m_uses_collapsing_borders_model = false; m_containing_line_box_index.clear(); m_sticky_insets = nullptr; diff --git a/Libraries/LibWeb/Painting/Paintable.h b/Libraries/LibWeb/Painting/Paintable.h index c376cc2b5863d..199faff80cbb7 100644 --- a/Libraries/LibWeb/Painting/Paintable.h +++ b/Libraries/LibWeb/Painting/Paintable.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -393,6 +394,9 @@ class WEB_API Paintable void set_uses_collapsing_borders_model(bool value) { m_uses_collapsing_borders_model = value; } bool uses_collapsing_borders_model() const { return m_uses_collapsing_borders_model; } + void set_collapsed_table_borders(OwnPtr collapsed_table_borders) { m_collapsed_table_borders = move(collapsed_table_borders); } + CollapsedTableBorders const* collapsed_table_borders() const { return m_collapsed_table_borders.ptr(); } + enum class ShrinkRadiiForBorders { Yes, No @@ -589,6 +593,7 @@ class WEB_API Paintable Optional m_override_borders_data; Optional m_table_cell_coordinates; + OwnPtr m_collapsed_table_borders; Optional m_containing_line_box_index; ResolvedCSSFilter m_filter; diff --git a/Libraries/LibWeb/Rust/src/layout/commit.rs b/Libraries/LibWeb/Rust/src/layout/commit.rs index 07444774a5ec7..2f6387f03f61a 100644 --- a/Libraries/LibWeb/Rust/src/layout/commit.rs +++ b/Libraries/LibWeb/Rust/src/layout/commit.rs @@ -103,6 +103,7 @@ pub struct FfiCommitSink { pub set_flex_layout_data: unsafe extern "C" fn(*mut c_void, *mut c_void, *const FfiFlexLayoutData), pub set_used_grid_tracks: unsafe extern "C" fn(*mut c_void, *mut c_void, *const FfiUsedGridTrackList, *const FfiUsedGridTrackList), + pub set_collapsed_table_borders: unsafe extern "C" fn(*mut c_void, *mut c_void, *const FfiCollapsedTableBorders), pub finish_node: unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void, *mut c_void, *mut c_void) -> FfiCommitNodeResult, pub assign_inline_box_geometry: unsafe extern "C" fn(*mut c_void, *mut c_void), @@ -278,6 +279,11 @@ fn commit_subtree( unsafe { (sink.set_used_grid_tracks)(sink.context, paintable, columns, rows) }; }); } + if !reuses_committed_subtree && let Some(borders) = &fragment.collapsed_table_borders { + borders.with_ffi_view(|view| { + unsafe { (sink.set_collapsed_table_borders)(sink.context, paintable, view) }; + }); + } } // SAFETY: Wiring uses only live layout and paintable pointers for this diff --git a/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs b/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs index 4fba1268b6769..de6ba6e4138a2 100644 --- a/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs +++ b/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs @@ -24,6 +24,7 @@ pub(crate) struct Fragment { pub(crate) uses_collapsing_borders_model: bool, pub(crate) table_cell_coordinates: Option, pub(crate) override_borders_data: Option, + pub(crate) collapsed_table_borders: Option>, pub(crate) line_data: Option>, pub(crate) grid_layout_data: Option>, pub(crate) flex_layout_data: Option>, @@ -165,6 +166,7 @@ fn snapshot_fragment( ( rare.table_cell_coordinates, rare.override_borders_data, + rare.collapsed_table_borders.take(), rare.grid_layout_data.take(), rare.flex_layout_data.take(), rare.used_grid_tracks.take(), @@ -176,6 +178,7 @@ fn snapshot_fragment( let ( table_cell_coordinates, override_borders_data, + collapsed_table_borders, grid_layout_data, flex_layout_data, used_grid_tracks, @@ -203,6 +206,7 @@ fn snapshot_fragment( uses_collapsing_borders_model: used.uses_collapsing_borders_model.get(), table_cell_coordinates, override_borders_data, + collapsed_table_borders, line_data, grid_layout_data, flex_layout_data, diff --git a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs index b261c8ad386ad..953b187da173d 100644 --- a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs @@ -116,6 +116,57 @@ pub(crate) struct CollapsedBorderSegment { pub(crate) source_order: u32, } +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[repr(C)] +pub struct FfiCollapsedBorderEdge { + pub border_data: FfiBorderData, + pub source_order: u32, +} + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct FfiCollapsedTableBorders { + pub row_count: usize, + pub column_count: usize, + pub row_offsets: *const CssPixels, + pub column_offsets: *const CssPixels, + pub horizontal_edges: *const FfiCollapsedBorderEdge, + pub vertical_edges: *const FfiCollapsedBorderEdge, +} + +#[derive(PartialEq, Eq)] +pub(crate) struct OwnedCollapsedTableBorders { + pub(crate) row_offsets: Vec, + pub(crate) column_offsets: Vec, + pub(crate) horizontal_edges: Vec, + pub(crate) vertical_edges: Vec, +} + +impl OwnedCollapsedTableBorders { + pub(crate) fn with_ffi_view(&self, callback: impl FnOnce(&FfiCollapsedTableBorders)) { + let view = FfiCollapsedTableBorders { + row_count: self.row_offsets.len() - 1, + column_count: self.column_offsets.len() - 1, + row_offsets: self.row_offsets.as_ptr(), + column_offsets: self.column_offsets.as_ptr(), + horizontal_edges: self.horizontal_edges.as_ptr(), + vertical_edges: self.vertical_edges.as_ptr(), + }; + callback(&view); + } +} + +fn grid_line_offsets(sizes: impl ExactSizeIterator) -> Vec { + let mut offsets = Vec::with_capacity(sizes.len() + 1); + let mut offset = CssPixels::default(); + offsets.push(offset); + for size in sizes { + offset += size; + offsets.push(offset); + } + offsets +} + pub(crate) struct CollapsedBorderGrid { horizontal_lines: Vec>, vertical_lines: Vec>, @@ -269,6 +320,26 @@ impl CollapsedBorderGrid { } } + pub(crate) fn has_paintable_edges(&self) -> bool { + let paints = |segment: &CollapsedBorderSegment| { + segment.border_data.width > CssPixels::default() + && segment.border_data.line_style != LINE_STYLE_NONE + && segment.border_data.line_style != LINE_STYLE_HIDDEN + }; + self.horizontal_lines.iter().flatten().any(paints) || self.vertical_lines.iter().flatten().any(paints) + } + + pub(crate) fn take_edges(self) -> (Vec, Vec) { + let to_edge = |segment: &CollapsedBorderSegment| FfiCollapsedBorderEdge { + border_data: segment.border_data, + source_order: segment.source_order, + }; + ( + self.horizontal_lines.iter().flatten().map(to_edge).collect(), + self.vertical_lines.iter().flatten().map(to_edge).collect(), + ) + } + fn most_specific(line: &[CollapsedBorderSegment], start: usize, end: usize) -> CollapsedBorderSegment { let mut winner = line[start]; for segment in &line[start + 1..end] { @@ -823,6 +894,7 @@ struct TableFormattingContext { deferred_cell_inside_layouts: Vec, columns: Vec, rows: Vec, + collapsed_border_grid: Option, derived_baselines_of_root_box: Cell, } @@ -889,6 +961,7 @@ impl TableFormattingContext { deferred_cell_inside_layouts: Vec::new(), columns: Vec::new(), rows: Vec::new(), + collapsed_border_grid: None, derived_baselines_of_root_box: Cell::new(DerivedBaselines::default()), } } @@ -1114,6 +1187,33 @@ impl TableFormattingContext { .rare_data_mut() .override_borders_data = Some(resolved); } + self.collapsed_border_grid = Some(grid); + } + + fn materialize_collapsed_table_borders(&mut self) { + let Some(grid) = self.collapsed_border_grid.take() else { + return; + }; + if self.purpose.is_measurement() { + return; + } + if !grid.has_paintable_edges() { + return; + } + let column_offsets = grid_line_offsets(self.columns.iter().map(|column| column.used_inline_size)); + let row_offsets = grid_line_offsets( + self.rows + .iter() + .map(|row| if row.is_collapsed { CssPixels::default() } else { row.final_block_size }), + ); + let (horizontal_edges, vertical_edges) = grid.take_edges(); + self.used_values(self.table_box).rare_data_mut().collapsed_table_borders = + Some(std::rc::Rc::new(OwnedCollapsedTableBorders { + row_offsets, + column_offsets, + horizontal_edges, + vertical_edges, + })); } fn seed_table_participant_used_values(&mut self) { @@ -2594,6 +2694,7 @@ impl TableFormattingContext { self.position_row_boxes(); self.layout_deferred_cells_inside(run); self.position_cell_boxes(); + self.materialize_collapsed_table_borders(); table_used.set_content_block_size(self.table_block_size); // Derive baselines for the table internals bottom-up (rows, then row groups, then the table box) // now that all offsets are final, so the table exports its baseline to outside consumers diff --git a/Libraries/LibWeb/Rust/src/layout/used_values.rs b/Libraries/LibWeb/Rust/src/layout/used_values.rs index 332fa25b27036..9d33db7e019b9 100644 --- a/Libraries/LibWeb/Rust/src/layout/used_values.rs +++ b/Libraries/LibWeb/Rust/src/layout/used_values.rs @@ -130,6 +130,7 @@ pub(crate) struct UsedValuesRareData { pub(crate) flex_layout_data: Option>, pub(crate) used_grid_tracks: Option>, pub(crate) override_borders_data: Option, + pub(crate) collapsed_table_borders: Option>, pub(crate) abspos_layout_inputs: Option, } @@ -144,6 +145,7 @@ impl UsedValuesRareData { flex_layout_data, used_grid_tracks, override_borders_data, + collapsed_table_borders, abspos_layout_inputs, } = self; debug_assert!( @@ -156,6 +158,7 @@ impl UsedValuesRareData { && grid_layout_data.is_none() && flex_layout_data.is_none() && used_grid_tracks.is_none() + && collapsed_table_borders.is_none() { return; } @@ -178,6 +181,9 @@ impl UsedValuesRareData { if let Some(tracks) = used_grid_tracks { rare.used_grid_tracks = Some(tracks); } + if let Some(borders) = collapsed_table_borders { + rare.collapsed_table_borders = Some(borders); + } } } From 8ed0d2fd82c1c06fb56b4e3a8dd06f7cb475d2ef Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:38:02 +0200 Subject: [PATCH 10/12] LibWeb: Rewrite collapsed table border painting over the border grid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The painter reconstructed everything from per-cell paintable data on every paint: it re-collected cells by tree walk, rebuilt the grid topology in hash maps, re-derived device-snapped grid lines from cell rects, duplicated the ยง17.6.2.1 specificity rules, and resolved border intersections by sorting deliberately overlapping edge rects so more specific edges paint over less specific ones - an order-emergent scheme the spec doesn't describe. Layout now commits the resolved winner of every grid line segment plus the grid line offsets, so painting becomes a flat scan: snap each grid line once, walk the edges, and settle each crossing geometrically by comparing the four meeting edges (width, then style, then resolution order; 'hidden' wins resolution but paints nothing, so it loses crossings). The winner's rect covers the crossing square and the losers stop at its boundary, making all rects disjoint - no sorting, no overdraw, and exact ties (same source element) overlap in the same color instead of staggering corners, matching other engines. --- Libraries/LibWeb/Painting/Paintable.cpp | 2 +- Libraries/LibWeb/Painting/StackingContext.cpp | 6 +- .../LibWeb/Painting/TableBordersPainting.cpp | 528 +++++------------- 3 files changed, 146 insertions(+), 390 deletions(-) diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index deaed53652331..d03b88ebdc878 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -1909,7 +1909,7 @@ void Paintable::paint(DisplayListRecordingContext& context, PaintPhase phase) co paint_border(context); } - if (display().is_table_inside() && phase == PaintPhase::TableCollapsedBorder) { + if (phase == PaintPhase::TableCollapsedBorder && collapsed_table_borders()) { paint_table_borders(context, *this); } diff --git a/Libraries/LibWeb/Painting/StackingContext.cpp b/Libraries/LibWeb/Painting/StackingContext.cpp index 3cbf96aab6891..b92202b80b434 100644 --- a/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Libraries/LibWeb/Painting/StackingContext.cpp @@ -258,7 +258,8 @@ static void paint_subtree_backgrounds_and_borders(DisplayListRecordingContext& c // all of which are skipped by the BackgroundAndBorders phase. if (!is_pure_inline_box(paintable)) StackingContext::paint_descendants(context, paintable, StackingContext::StackingContextPaintPhase::BackgroundAndBorders); - paint_node(paintable, context, PaintPhase::TableCollapsedBorder); + if (paintable.collapsed_table_borders()) + paint_node(paintable, context, PaintPhase::TableCollapsedBorder); } static void paint_inline_level_non_positioned_descendant(DisplayListRecordingContext& context, Paintable const& paintable) @@ -427,7 +428,8 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Draw the background and borders for block-level children (step 4) paint_descendants(context, paintable_box(), StackingContextPaintPhase::BackgroundAndBorders); - paint_node(paintable_box(), context, PaintPhase::TableCollapsedBorder); + if (paintable_box().collapsed_table_borders()) + paint_node(paintable_box(), context, PaintPhase::TableCollapsedBorder); // Draw the non-positioned floats (step 5) if (!m_non_positioned_floating_descendants.is_empty()) paint_descendants(context, paintable_box(), StackingContextPaintPhase::Floats); diff --git a/Libraries/LibWeb/Painting/TableBordersPainting.cpp b/Libraries/LibWeb/Painting/TableBordersPainting.cpp index e405562a9b577..2c3018513fde6 100644 --- a/Libraries/LibWeb/Painting/TableBordersPainting.cpp +++ b/Libraries/LibWeb/Painting/TableBordersPainting.cpp @@ -1,446 +1,200 @@ /* * Copyright (c) 2023, the SerenityOS developers. + * Copyright (c) 2026, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include -#include -#include +#include +#include #include #include #include #include -struct CellCoordinates { - size_t row_index; - size_t column_index; - - bool operator==(CellCoordinates const& other) const - { - return row_index == other.row_index && column_index == other.column_index; - } -}; - -namespace AK { - -template<> -struct Traits : public DefaultTraits { - static unsigned hash(CellCoordinates const& key) { return pair_int_hash(key.row_index, key.column_index); } -}; - -} - namespace Web::Painting { -static void collect_cell_boxes(Vector& cell_boxes, Paintable const& table_paintable) -{ - table_paintable.for_each_child_of_type([&](auto& child) { - if (child.display().is_table_cell()) { - cell_boxes.append(child); - } else { - collect_cell_boxes(cell_boxes, child); - } - return IterationDecision::Continue; - }); -} - enum class EdgeDirection { Horizontal, Vertical, }; -struct DeviceBorderData { - Color color { Color::Transparent }; - CSS::LineStyle line_style { CSS::LineStyle::None }; - DevicePixels width { 0 }; +struct DeviceEdge { + BorderDataDevicePixels data; + u32 source_order { 0 }; + + bool paints() const { return data.width > 0 && data.line_style != CSS::LineStyle::None && data.line_style != CSS::LineStyle::Hidden; } }; -static unsigned line_style_score(CSS::LineStyle line_style) +static int edge_style_score(CSS::LineStyle style) { - switch (line_style) { + switch (style) { case CSS::LineStyle::Inset: - return 0; - case CSS::LineStyle::Groove: return 1; - case CSS::LineStyle::Outset: + case CSS::LineStyle::Groove: return 2; - case CSS::LineStyle::Ridge: + case CSS::LineStyle::Outset: return 3; - case CSS::LineStyle::Dotted: + case CSS::LineStyle::Ridge: return 4; - case CSS::LineStyle::Dashed: + case CSS::LineStyle::Dotted: return 5; - case CSS::LineStyle::Solid: + case CSS::LineStyle::Dashed: return 6; - case CSS::LineStyle::Double: + case CSS::LineStyle::Solid: return 7; + case CSS::LineStyle::Double: + return 8; default: - VERIFY_NOT_REACHED(); + return 0; } } -static bool border_is_less_specific(DeviceBorderData const& a, DeviceBorderData const& b) +static bool beats_at_joint(DeviceEdge const& a, DeviceEdge const& b) { - // Implements criteria for steps 1, 2 and 3 of border conflict resolution algorithm, as described in - // https://www.w3.org/TR/CSS22/tables.html#border-conflict-resolution. - if (a.line_style == CSS::LineStyle::Hidden) + if (a.paints() != b.paints()) + return a.paints(); + if (!a.paints()) return false; - if (b.line_style == CSS::LineStyle::Hidden) - return true; - if (a.line_style == CSS::LineStyle::None) - return true; - if (b.line_style == CSS::LineStyle::None) - return false; - if (a.width != b.width) - return a.width < b.width; - return line_style_score(a.line_style) < line_style_score(b.line_style); -} - -struct DeviceBorderDataWithElementKind { - DeviceBorderData border_data; - Painting::Paintable::ConflictingElementKind element_kind { Painting::Paintable::ConflictingElementKind::Cell }; + if (a.data.width != b.data.width) + return a.data.width > b.data.width; + auto a_score = edge_style_score(a.data.line_style); + auto b_score = edge_style_score(b.data.line_style); + if (a_score != b_score) + return a_score > b_score; + return a.source_order < b.source_order; +} + +struct JointOutcome { + bool survives { false }; + DevicePixels crossing_size { 0 }; }; -struct DeviceBordersDataWithElementKind { - DeviceBorderDataWithElementKind top; - DeviceBorderDataWithElementKind right; - DeviceBorderDataWithElementKind bottom; - DeviceBorderDataWithElementKind left; -}; - -struct BorderEdgePaintingInfo { - DevicePixelRect rect; - DeviceBorderDataWithElementKind border_data_with_element_kind; - EdgeDirection direction; - Optional row; - Optional column; -}; - -static Optional row_index_for_element_kind(size_t index, Painting::Paintable::ConflictingElementKind element_kind) -{ - switch (element_kind) { - case Painting::Paintable::ConflictingElementKind::Cell: - case Painting::Paintable::ConflictingElementKind::Row: - case Painting::Paintable::ConflictingElementKind::RowGroup: { - return index; - } - default: - return {}; - } -} - -static Optional column_index_for_element_kind(size_t index, Painting::Paintable::ConflictingElementKind element_kind) -{ - switch (element_kind) { - case Painting::Paintable::ConflictingElementKind::Cell: - case Painting::Paintable::ConflictingElementKind::Column: - case Painting::Paintable::ConflictingElementKind::ColumnGroup: { - return index; - } - default: - return {}; - } -} - -static DevicePixels half_ceil(DevicePixels width) -{ - return ceil(static_cast(width.value()) / 2); -} - -static DevicePixels half_floor(DevicePixels width) -{ - return floor(static_cast(width.value()) / 2); -} - -static BorderEdgePaintingInfo make_right_cell_edge( - DevicePixelRect const& right_cell_rect, - DevicePixelRect const& cell_rect, - DeviceBordersDataWithElementKind const& borders_data, - CellCoordinates const& coordinates) -{ - auto connect_top_offset = half_ceil(borders_data.top.border_data.width); - auto connect_excess_height = connect_top_offset + half_floor(borders_data.bottom.border_data.width); - DevicePixelRect right_border_rect = { - right_cell_rect.x() - half_ceil(borders_data.right.border_data.width), - cell_rect.y() - connect_top_offset, - borders_data.right.border_data.width, - max(cell_rect.height(), right_cell_rect.height()) + connect_excess_height, - }; - return BorderEdgePaintingInfo { - .rect = right_border_rect, - .border_data_with_element_kind = borders_data.right, - .direction = EdgeDirection::Vertical, - .row = row_index_for_element_kind(coordinates.row_index, borders_data.right.element_kind), - .column = column_index_for_element_kind(coordinates.column_index, borders_data.right.element_kind), - }; -} - -static BorderEdgePaintingInfo make_down_cell_edge( - DevicePixelRect const& down_cell_rect, - DevicePixelRect const& cell_rect, - DeviceBordersDataWithElementKind const& borders_data, - CellCoordinates const& coordinates) -{ - auto connect_left_offset = half_ceil(borders_data.left.border_data.width); - auto connect_excess_width = connect_left_offset + half_floor(borders_data.right.border_data.width); - DevicePixelRect down_border_rect = { - cell_rect.x() - connect_left_offset, - down_cell_rect.y() - half_ceil(borders_data.bottom.border_data.width), - max(cell_rect.width(), down_cell_rect.width()) + connect_excess_width, - borders_data.bottom.border_data.width, - }; - return BorderEdgePaintingInfo { - .rect = down_border_rect, - .border_data_with_element_kind = borders_data.bottom, - .direction = EdgeDirection::Horizontal, - .row = row_index_for_element_kind(coordinates.row_index, borders_data.bottom.element_kind), - .column = column_index_for_element_kind(coordinates.column_index, borders_data.bottom.element_kind), - }; -} - -static BorderEdgePaintingInfo make_first_row_top_cell_edge(DevicePixelRect const& cell_rect, DeviceBordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates) +static JointOutcome resolve_joint(DeviceEdge const& self, DeviceEdge const& collinear, DeviceEdge const& perpendicular_a, DeviceEdge const& perpendicular_b) { - auto connect_left_offset = half_ceil(borders_data.left.border_data.width.value()); - auto connect_excess_width = connect_left_offset + half_floor(borders_data.right.border_data.width.value()); - DevicePixelRect top_border_rect = { - cell_rect.x() - connect_left_offset, - cell_rect.y() - half_ceil(borders_data.top.border_data.width.value()), - cell_rect.width() + connect_excess_width, - borders_data.top.border_data.width, - }; - return BorderEdgePaintingInfo { - .rect = top_border_rect, - .border_data_with_element_kind = borders_data.top, - .direction = EdgeDirection::Horizontal, - .row = row_index_for_element_kind(coordinates.row_index, borders_data.top.element_kind), - .column = column_index_for_element_kind(coordinates.column_index, borders_data.top.element_kind), - }; + bool survives = !beats_at_joint(collinear, self) + && !beats_at_joint(perpendicular_a, self) + && !beats_at_joint(perpendicular_b, self); + auto const& crossing = beats_at_joint(perpendicular_b, perpendicular_a) ? perpendicular_b : perpendicular_a; + return { survives, crossing.paints() ? crossing.data.width : DevicePixels(0) }; } -static BorderEdgePaintingInfo make_last_row_bottom_cell_edge(DevicePixelRect const& cell_rect, DeviceBordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates) +static DevicePixels joint_start_coordinate(DevicePixels line, JointOutcome const& joint) { - auto connect_left_offset = half_ceil(borders_data.left.border_data.width); - auto connect_excess_width = connect_left_offset + half_floor(borders_data.right.border_data.width); - DevicePixelRect bottom_border_rect = { - cell_rect.x() - connect_left_offset, - cell_rect.y() + cell_rect.height() - half_ceil(borders_data.bottom.border_data.width), - cell_rect.width() + connect_excess_width, - borders_data.bottom.border_data.width, - }; - return BorderEdgePaintingInfo { - .rect = bottom_border_rect, - .border_data_with_element_kind = borders_data.bottom, - .direction = EdgeDirection::Horizontal, - .row = row_index_for_element_kind(coordinates.row_index, borders_data.bottom.element_kind), - .column = column_index_for_element_kind(coordinates.column_index, borders_data.bottom.element_kind), - }; + auto half = joint.crossing_size.value() / 2; + if (joint.survives) + return line - half; + return line + (joint.crossing_size.value() - half); } -static BorderEdgePaintingInfo make_first_column_left_cell_edge(DevicePixelRect const& cell_rect, DeviceBordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates) +static DevicePixels joint_end_coordinate(DevicePixels line, JointOutcome const& joint) { - auto connect_top_offset = half_ceil(borders_data.top.border_data.width); - auto connect_excess_height = connect_top_offset + half_floor(borders_data.bottom.border_data.width); - DevicePixelRect left_border_rect = { - cell_rect.x() - half_ceil(borders_data.left.border_data.width), - cell_rect.y() - connect_top_offset, - borders_data.left.border_data.width, - cell_rect.height() + connect_excess_height, - }; - return BorderEdgePaintingInfo { - .rect = left_border_rect, - .border_data_with_element_kind = borders_data.left, - .direction = EdgeDirection::Vertical, - .row = row_index_for_element_kind(coordinates.row_index, borders_data.left.element_kind), - .column = column_index_for_element_kind(coordinates.column_index, borders_data.left.element_kind), - }; + auto half = joint.crossing_size.value() / 2; + if (joint.survives) + return line + (joint.crossing_size.value() - half); + return line - half; } -static BorderEdgePaintingInfo make_last_column_right_cell_edge(DevicePixelRect const& cell_rect, DeviceBordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates) +static void paint_edge(DisplayListRecordingContext& context, DevicePixelRect const& rect, DeviceEdge const& edge, EdgeDirection direction) { - auto connect_top_offset = half_ceil(borders_data.top.border_data.width); - auto connect_excess_height = connect_top_offset + half_floor(borders_data.bottom.border_data.width); - DevicePixelRect right_border_rect = { - cell_rect.x() + cell_rect.width() - half_ceil(borders_data.right.border_data.width), - cell_rect.y() - connect_top_offset, - borders_data.right.border_data.width, - cell_rect.height() + connect_excess_height, - }; - return BorderEdgePaintingInfo { - .rect = right_border_rect, - .border_data_with_element_kind = borders_data.right, - .direction = EdgeDirection::Vertical, - .row = row_index_for_element_kind(coordinates.row_index, borders_data.right.element_kind), - .column = column_index_for_element_kind(coordinates.column_index, borders_data.right.element_kind), - }; -} - -static void paint_collected_edges(DisplayListRecordingContext& context, Vector& border_edge_painting_info_list) -{ - // This sorting step isn't part of the specification, but it matches the behavior of other browsers at border intersections, which aren't - // part of border conflict resolution in the specification but it's still desirable to handle them in a way which is consistent with it. - // See https://www.w3.org/TR/CSS22/tables.html#border-conflict-resolution for reference. - quick_sort(border_edge_painting_info_list, [](auto const& a, auto const& b) { - auto const& a_border_data = a.border_data_with_element_kind.border_data; - auto const& b_border_data = b.border_data_with_element_kind.border_data; - if (a_border_data.line_style == b_border_data.line_style && a_border_data.width == b_border_data.width) { - if (b.border_data_with_element_kind.element_kind < a.border_data_with_element_kind.element_kind) { - return true; - } else if (b.border_data_with_element_kind.element_kind > a.border_data_with_element_kind.element_kind) { - return false; - } - // Here the element kind is the same, thus the coordinates are either both set or not set. - VERIFY(a.column.has_value() == b.column.has_value()); - VERIFY(a.row.has_value() == b.row.has_value()); - if (a.column.has_value()) { - if (b.column.value() < a.column.value()) { - return true; - } else if (b.column.value() > a.column.value()) { - return false; - } - } - return a.row.has_value() ? b.row.value() < a.row.value() : false; - } - return border_is_less_specific(a_border_data, b_border_data); - }); - - for (auto const& border_edge_painting_info : border_edge_painting_info_list) { - auto const& border_data_with_element_kind = border_edge_painting_info.border_data_with_element_kind; - auto width = border_data_with_element_kind.border_data.width; - if (width <= 0) - continue; - auto color = border_data_with_element_kind.border_data.color; - auto border_style = border_data_with_element_kind.border_data.line_style; - auto p1 = border_edge_painting_info.rect.top_left(); - auto p2 = border_edge_painting_info.direction == EdgeDirection::Horizontal - ? border_edge_painting_info.rect.top_right() - : border_edge_painting_info.rect.bottom_left(); - - if (border_style == CSS::LineStyle::Dotted) { - context.display_list_recorder().draw_line(p1.to_type(), p2.to_type(), color, width.value(), Gfx::LineStyle::Dotted); - } else if (border_style == CSS::LineStyle::Dashed) { - context.display_list_recorder().draw_line(p1.to_type(), p2.to_type(), color, width.value(), Gfx::LineStyle::Dashed); - } else { - // FIXME: Support the remaining line styles instead of rendering them as solid. - context.display_list_recorder().fill_rect(Gfx::IntRect(border_edge_painting_info.rect.location(), border_edge_painting_info.rect.size()), color); - } - } -} - -static HashMap snap_cells_to_device_coordinates(HashMap> const& cell_coordinates_to_box, size_t row_count, size_t column_count, DisplayListRecordingContext const& context) -{ - Vector y_line_start_coordinates; - Vector y_line_end_coordinates; - y_line_start_coordinates.resize(row_count + 1); - y_line_end_coordinates.resize(row_count + 1); - Vector x_line_start_coordinates; - Vector x_line_end_coordinates; - x_line_start_coordinates.resize(column_count + 1); - x_line_end_coordinates.resize(column_count + 1); - for (auto const& kv : cell_coordinates_to_box) { - auto const& cell_box = kv.value; - auto start_row_index = cell_box->table_cell_coordinates()->row_index; - auto end_row_index = start_row_index + cell_box->table_cell_coordinates()->row_span; - auto cell_rect = cell_box->absolute_border_box_rect(); - y_line_start_coordinates[start_row_index] = max(context.rounded_device_pixels(cell_rect.y()), y_line_start_coordinates[start_row_index]); - y_line_end_coordinates[end_row_index] = max(context.rounded_device_pixels(cell_rect.y() + cell_rect.height()), y_line_end_coordinates[end_row_index]); - auto start_column_index = cell_box->table_cell_coordinates()->column_index; - auto end_column_index = start_column_index + cell_box->table_cell_coordinates()->column_span; - x_line_start_coordinates[start_column_index] = max(context.rounded_device_pixels(cell_rect.x()), x_line_start_coordinates[start_column_index]); - x_line_end_coordinates[end_column_index] = max(context.rounded_device_pixels(cell_rect.x() + cell_rect.width()), x_line_end_coordinates[end_column_index]); - } - HashMap cell_coordinates_to_device_rect; - for (auto const& kv : cell_coordinates_to_box) { - auto const& cell_box = kv.value; - auto start_row_index = cell_box->table_cell_coordinates()->row_index; - auto end_row_index = start_row_index + cell_box->table_cell_coordinates()->row_span; - auto height = y_line_end_coordinates[end_row_index] - y_line_start_coordinates[start_row_index]; - auto start_column_index = cell_box->table_cell_coordinates()->column_index; - auto end_column_index = start_column_index + cell_box->table_cell_coordinates()->column_span; - auto width = x_line_end_coordinates[end_column_index] - x_line_start_coordinates[start_column_index]; - cell_coordinates_to_device_rect.set(kv.key, DevicePixelRect { x_line_start_coordinates[start_column_index], y_line_start_coordinates[start_row_index], width, height }); + if (edge.data.line_style == CSS::LineStyle::Dotted || edge.data.line_style == CSS::LineStyle::Dashed) { + auto p1 = rect.top_left(); + auto p2 = direction == EdgeDirection::Horizontal ? rect.top_right() : rect.bottom_left(); + auto line_style = edge.data.line_style == CSS::LineStyle::Dotted ? Gfx::LineStyle::Dotted : Gfx::LineStyle::Dashed; + context.display_list_recorder().draw_line(p1.to_type(), p2.to_type(), edge.data.color, edge.data.width.value(), line_style); + return; } - return cell_coordinates_to_device_rect; -} - -static DeviceBorderDataWithElementKind device_border_data_from_css_border_data(Painting::Paintable::BorderDataWithElementKind const& border_data_with_element_kind, DisplayListRecordingContext const& context) -{ - return DeviceBorderDataWithElementKind { - .border_data = { - .color = border_data_with_element_kind.border_data.color, - .line_style = border_data_with_element_kind.border_data.line_style, - .width = context.rounded_device_pixels(border_data_with_element_kind.border_data.width), - }, - .element_kind = border_data_with_element_kind.element_kind, - }; + // FIXME: Support the remaining line styles instead of rendering them as solid. + context.display_list_recorder().fill_rect(Gfx::IntRect(rect.location(), rect.size()), edge.data.color); } void paint_table_borders(DisplayListRecordingContext& context, Paintable const& table_paintable) { - if (table_paintable.layout_node().border_collapse() == CSS::BorderCollapse::Separate) + // Painting according to the collapsing border model: + // https://www.w3.org/TR/CSS22/tables.html#collapsing-borders + auto const* borders = table_paintable.collapsed_table_borders(); + if (!borders) + return; + auto const rows = borders->row_count(); + auto const columns = borders->column_count(); + if (rows == 0 || columns == 0) return; - // Partial implementation of painting according to the collapsing border model: - // https://www.w3.org/TR/CSS22/tables.html#collapsing-borders - Vector cell_boxes; - collect_cell_boxes(cell_boxes, table_paintable); - Vector border_edge_painting_info_list; - HashMap> cell_coordinates_to_box; - size_t row_count = 0; - size_t column_count = 0; - for (auto const& cell_box : cell_boxes) { - cell_coordinates_to_box.set(CellCoordinates { - .row_index = cell_box.table_cell_coordinates()->row_index, - .column_index = cell_box.table_cell_coordinates()->column_index }, - cell_box); - row_count = max(row_count, cell_box.table_cell_coordinates()->row_index + cell_box.table_cell_coordinates()->row_span); - column_count = max(column_count, cell_box.table_cell_coordinates()->column_index + cell_box.table_cell_coordinates()->column_span); - } - auto cell_coordinates_to_device_rect = snap_cells_to_device_coordinates(cell_coordinates_to_box, row_count, column_count, context); - for (auto const& cell_box : cell_boxes) { - auto css_borders_data = cell_box.override_borders_data().has_value() ? cell_box.override_borders_data().value() : Paintable::BordersDataWithElementKind { - .top = { .border_data = cell_box.box_model().border.top == 0 ? CSS::BorderData() : cell_box.layout_node().border_top(), .element_kind = Paintable::ConflictingElementKind::Cell }, - .right = { .border_data = cell_box.box_model().border.right == 0 ? CSS::BorderData() : cell_box.layout_node().border_right(), .element_kind = Paintable::ConflictingElementKind::Cell }, - .bottom = { .border_data = cell_box.box_model().border.bottom == 0 ? CSS::BorderData() : cell_box.layout_node().border_bottom(), .element_kind = Paintable::ConflictingElementKind::Cell }, - .left = { .border_data = cell_box.box_model().border.left == 0 ? CSS::BorderData() : cell_box.layout_node().border_left(), .element_kind = Paintable::ConflictingElementKind::Cell }, - }; - DeviceBordersDataWithElementKind borders_data = { - .top = device_border_data_from_css_border_data(css_borders_data.top, context), - .right = device_border_data_from_css_border_data(css_borders_data.right, context), - .bottom = device_border_data_from_css_border_data(css_borders_data.bottom, context), - .left = device_border_data_from_css_border_data(css_borders_data.left, context), - }; - auto cell_rect = cell_coordinates_to_device_rect.get({ cell_box.table_cell_coordinates()->row_index, cell_box.table_cell_coordinates()->column_index }).value(); - CellCoordinates right_cell_coordinates { - .row_index = cell_box.table_cell_coordinates()->row_index, - .column_index = cell_box.table_cell_coordinates()->column_index + cell_box.table_cell_coordinates()->column_span + auto origin = table_paintable.absolute_rect().location(); + Vector xs; + xs.ensure_capacity(columns + 1); + for (auto offset : borders->column_offsets) + xs.unchecked_append(context.rounded_device_pixels(origin.x() + offset)); + Vector ys; + ys.ensure_capacity(rows + 1); + for (auto offset : borders->row_offsets) + ys.unchecked_append(context.rounded_device_pixels(origin.y() + offset)); + + auto to_device_edge = [&](CollapsedBorderEdge const& edge) { + return DeviceEdge { + .data = { + .color = edge.border.color, + .line_style = edge.border.line_style, + .width = context.rounded_device_pixels(edge.border.width), + }, + .source_order = edge.source_order, }; - auto maybe_right_cell = cell_coordinates_to_device_rect.get(right_cell_coordinates); - CellCoordinates down_cell_coordinates { - .row_index = cell_box.table_cell_coordinates()->row_index + cell_box.table_cell_coordinates()->row_span, - .column_index = cell_box.table_cell_coordinates()->column_index - }; - auto maybe_down_cell = cell_coordinates_to_device_rect.get(down_cell_coordinates); - if (maybe_right_cell.has_value()) - border_edge_painting_info_list.append(make_right_cell_edge(maybe_right_cell.value(), cell_rect, borders_data, right_cell_coordinates)); - if (maybe_down_cell.has_value()) - border_edge_painting_info_list.append(make_down_cell_edge(maybe_down_cell.value(), cell_rect, borders_data, down_cell_coordinates)); - if (cell_box.table_cell_coordinates()->row_index == 0) - border_edge_painting_info_list.append(make_first_row_top_cell_edge(cell_rect, borders_data, - { .row_index = 0, .column_index = cell_box.table_cell_coordinates()->column_index })); - if (cell_box.table_cell_coordinates()->row_index + cell_box.table_cell_coordinates()->row_span == row_count) - border_edge_painting_info_list.append(make_last_row_bottom_cell_edge(cell_rect, borders_data, - { .row_index = row_count - 1, .column_index = cell_box.table_cell_coordinates()->column_index })); - if (cell_box.table_cell_coordinates()->column_index == 0) - border_edge_painting_info_list.append(make_first_column_left_cell_edge(cell_rect, borders_data, - { .row_index = cell_box.table_cell_coordinates()->row_index, .column_index = 0 })); - if (cell_box.table_cell_coordinates()->column_index + cell_box.table_cell_coordinates()->column_span == column_count) - border_edge_painting_info_list.append(make_last_column_right_cell_edge(cell_rect, borders_data, - { .row_index = cell_box.table_cell_coordinates()->row_index, .column_index = column_count - 1 })); + }; + Vector horizontal_edges; + horizontal_edges.ensure_capacity(borders->horizontal_edges.size()); + for (auto const& edge : borders->horizontal_edges) + horizontal_edges.unchecked_append(to_device_edge(edge)); + Vector vertical_edges; + vertical_edges.ensure_capacity(borders->vertical_edges.size()); + for (auto const& edge : borders->vertical_edges) + vertical_edges.unchecked_append(to_device_edge(edge)); + + static DeviceEdge const no_edge {}; + auto horizontal = [&](size_t line, size_t column) -> DeviceEdge const& { return horizontal_edges[line * columns + column]; }; + auto vertical = [&](size_t line, size_t row) -> DeviceEdge const& { return vertical_edges[line * rows + row]; }; + + for (size_t i = 0; i <= rows; ++i) { + for (size_t j = 0; j < columns; ++j) { + auto const& self = horizontal(i, j); + if (!self.paints()) + continue; + auto start_joint = resolve_joint(self, + j > 0 ? horizontal(i, j - 1) : no_edge, + i > 0 ? vertical(j, i - 1) : no_edge, + i < rows ? vertical(j, i) : no_edge); + auto end_joint = resolve_joint(self, + j + 1 < columns ? horizontal(i, j + 1) : no_edge, + i > 0 ? vertical(j + 1, i - 1) : no_edge, + i < rows ? vertical(j + 1, i) : no_edge); + auto x0 = joint_start_coordinate(xs[j], start_joint); + auto x1 = joint_end_coordinate(xs[j + 1], end_joint); + if (x1 <= x0) + continue; + DevicePixelRect rect { x0, ys[i] - self.data.width.value() / 2, x1 - x0, self.data.width }; + paint_edge(context, rect, self, EdgeDirection::Horizontal); + } + } + for (size_t j = 0; j <= columns; ++j) { + for (size_t i = 0; i < rows; ++i) { + auto const& self = vertical(j, i); + if (!self.paints()) + continue; + auto start_joint = resolve_joint(self, + i > 0 ? vertical(j, i - 1) : no_edge, + j > 0 ? horizontal(i, j - 1) : no_edge, + j < columns ? horizontal(i, j) : no_edge); + auto end_joint = resolve_joint(self, + i + 1 < rows ? vertical(j, i + 1) : no_edge, + j > 0 ? horizontal(i + 1, j - 1) : no_edge, + j < columns ? horizontal(i + 1, j) : no_edge); + auto y0 = joint_start_coordinate(ys[i], start_joint); + auto y1 = joint_end_coordinate(ys[i + 1], end_joint); + if (y1 <= y0) + continue; + DevicePixelRect rect { xs[j] - self.data.width.value() / 2, y0, self.data.width, y1 - y0 }; + paint_edge(context, rect, self, EdgeDirection::Vertical); + } } - - paint_collected_edges(context, border_edge_painting_info_list); } } From c6e0a9b9e4a0cc26acd62f036c70105480f3452b Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 18:43:08 +0200 Subject: [PATCH 11/12] LibWeb: Drop the per-cell collapsed border payloads With painting driven by the per-table resolved edge grid, the per-cell override borders and table cell coordinates have no consumers left. Remove them from the rare-payload pipeline, the commit sink, and every paintable (they were members of all paintables, not just cells), along with ConflictingElementKind and its FFI mirror types. The per-cell harvest in border conflict resolution shrinks to assigning the winning used border widths. --- Libraries/LibWeb/Layout/LayoutRustBridge.cpp | 28 ---- Libraries/LibWeb/Painting/Paintable.cpp | 14 +- Libraries/LibWeb/Painting/Paintable.h | 38 ----- Libraries/LibWeb/Rust/src/layout/commit.rs | 22 --- .../LibWeb/Rust/src/layout/fc_run_cache.rs | 3 +- .../Rust/src/layout/formatting_context.rs | 16 -- .../LibWeb/Rust/src/layout/fragment_tree.rs | 8 - .../src/layout/table_formatting_context.rs | 139 +++++------------- .../LibWeb/Rust/src/layout/used_values.rs | 6 +- 9 files changed, 36 insertions(+), 238 deletions(-) diff --git a/Libraries/LibWeb/Layout/LayoutRustBridge.cpp b/Libraries/LibWeb/Layout/LayoutRustBridge.cpp index 82a7928db2786..c0f82fa4d85c0 100644 --- a/Libraries/LibWeb/Layout/LayoutRustBridge.cpp +++ b/Libraries/LibWeb/Layout/LayoutRustBridge.cpp @@ -734,16 +734,6 @@ struct LayoutRustBridge::LineCommitContext { Vector pieces; }; -static CSS::BorderData from_ffi_border_data(RustFFI::FfiBorderData const&); - -static Painting::Paintable::BorderDataWithElementKind from_ffi_border_data_with_element_kind(RustFFI::FfiBorderDataWithElementKind const& border) -{ - return { - .border_data = from_ffi_border_data(border.border_data), - .element_kind = static_cast(border.element_kind), - }; -} - RustFFI::FfiCommitSink LayoutRustBridge::commit_sink() { return { @@ -860,18 +850,6 @@ RustFFI::FfiCommitSink LayoutRustBridge::commit_sink() if (metrics.has_containing_line_box_index) paintable.set_containing_line_box_index(metrics.containing_line_box_index); paintable.set_uses_collapsing_borders_model(metrics.uses_collapsing_borders_model); }, - .set_override_borders = [](void*, void* paintable_pointer, RustFFI::FfiBordersData borders) { static_cast(paintable_pointer)->set_override_borders_data({ - .top = from_ffi_border_data_with_element_kind(borders.top), - .right = from_ffi_border_data_with_element_kind(borders.right), - .bottom = from_ffi_border_data_with_element_kind(borders.bottom), - .left = from_ffi_border_data_with_element_kind(borders.left), - }); }, - .set_table_cell_coordinates = [](void*, void* paintable_pointer, RustFFI::FfiTableCellCoordinates coordinates) { static_cast(paintable_pointer)->set_table_cell_coordinates({ - .row_index = coordinates.row_index, - .column_index = coordinates.column_index, - .row_span = coordinates.row_span, - .column_span = coordinates.column_span, - }); }, .begin_line_data = [](void* context, void* paintable_pointer) { auto& bridge = *static_cast(context); VERIFY(!bridge.m_line_commit_context); @@ -1066,12 +1044,6 @@ bool can_replay_saved_abspos_layout_inputs_after_style_change(Box const& box) RustFFI::FfiLayoutFcCallbacks LayoutRustBridge::formatting_context_callbacks() { - static_assert(to_underlying(Painting::Paintable::ConflictingElementKind::Cell) == 0); - static_assert(to_underlying(Painting::Paintable::ConflictingElementKind::Row) == 1); - static_assert(to_underlying(Painting::Paintable::ConflictingElementKind::RowGroup) == 2); - static_assert(to_underlying(Painting::Paintable::ConflictingElementKind::Column) == 3); - static_assert(to_underlying(Painting::Paintable::ConflictingElementKind::ColumnGroup) == 4); - static_assert(to_underlying(Painting::Paintable::ConflictingElementKind::Table) == 5); static_assert(to_underlying(FlexLayoutGrowthState::Growing) == 0); static_assert(to_underlying(FlexLayoutGrowthState::Shrinking) == 1); static_assert(to_underlying(FlexLayoutClampState::Unclamped) == 0); diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index d03b88ebdc878..98c941cec81dd 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -1155,8 +1155,6 @@ void Paintable::reset_for_relayout() m_box_model = {}; m_overflow_data.clear(); - m_override_borders_data.clear(); - m_table_cell_coordinates.clear(); m_collapsed_table_borders = nullptr; m_uses_collapsing_borders_model = false; m_containing_line_box_index.clear(); @@ -2286,16 +2284,6 @@ Optional Paintable::effective_z_index() const return {}; } -BordersData Paintable::remove_element_kind_from_borders_data(Paintable::BordersDataWithElementKind borders_data) -{ - return { - .top = borders_data.top.border_data, - .right = borders_data.right.border_data, - .bottom = borders_data.bottom.border_data, - .left = borders_data.left.border_data, - }; -} - enum class BorderImageTrack { Start, Center, @@ -2635,7 +2623,7 @@ static bool paint_border_image(DisplayListRecordingContext& context, Paintable c void Paintable::paint_border(DisplayListRecordingContext& context) const { - auto borders_data = m_override_borders_data.has_value() ? remove_element_kind_from_borders_data(m_override_borders_data.value()) : BordersData { + BordersData borders_data { .top = box_model().border.top == 0 ? CSS::BorderData() : layout_node().border_top(), .right = box_model().border.right == 0 ? CSS::BorderData() : layout_node().border_right(), .bottom = box_model().border.bottom == 0 ? CSS::BorderData() : layout_node().border_bottom(), diff --git a/Libraries/LibWeb/Painting/Paintable.h b/Libraries/LibWeb/Painting/Paintable.h index 199faff80cbb7..513bf01381acc 100644 --- a/Libraries/LibWeb/Painting/Paintable.h +++ b/Libraries/LibWeb/Painting/Paintable.h @@ -355,42 +355,6 @@ class WEB_API Paintable RefPtr scrollbar(ScrollDirection) const; NonnullRefPtr ensure_scrollbar(ScrollDirection); - enum class ConflictingElementKind { - Cell, - Row, - RowGroup, - Column, - ColumnGroup, - Table, - }; - - struct BorderDataWithElementKind { - CSS::BorderData border_data; - ConflictingElementKind element_kind; - }; - - struct BordersDataWithElementKind { - BorderDataWithElementKind top; - BorderDataWithElementKind right; - BorderDataWithElementKind bottom; - BorderDataWithElementKind left; - }; - - void set_override_borders_data(BordersDataWithElementKind const& override_borders_data) { m_override_borders_data = override_borders_data; } - Optional const& override_borders_data() const { return m_override_borders_data; } - - static BordersData remove_element_kind_from_borders_data(Paintable::BordersDataWithElementKind borders_data); - - struct TableCellCoordinates { - size_t row_index; - size_t column_index; - size_t row_span; - size_t column_span; - }; - - void set_table_cell_coordinates(TableCellCoordinates const& table_cell_coordinates) { m_table_cell_coordinates = table_cell_coordinates; } - auto const& table_cell_coordinates() const { return m_table_cell_coordinates; } - void set_uses_collapsing_borders_model(bool value) { m_uses_collapsing_borders_model = value; } bool uses_collapsing_borders_model() const { return m_uses_collapsing_borders_model; } @@ -591,8 +555,6 @@ class WEB_API Paintable size_t m_visual_context_nodes_begin { 0 }; size_t m_visual_context_nodes_end { 0 }; - Optional m_override_borders_data; - Optional m_table_cell_coordinates; OwnPtr m_collapsed_table_borders; Optional m_containing_line_box_index; diff --git a/Libraries/LibWeb/Rust/src/layout/commit.rs b/Libraries/LibWeb/Rust/src/layout/commit.rs index 2f6387f03f61a..b3d62fda68b09 100644 --- a/Libraries/LibWeb/Rust/src/layout/commit.rs +++ b/Libraries/LibWeb/Rust/src/layout/commit.rs @@ -4,15 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -#[repr(C)] -pub struct FfiTableCellCoordinates { - pub row_index: usize, - pub column_index: usize, - pub row_span: usize, - pub column_span: usize, -} - #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[repr(C)] pub struct FfiCommittedBoxMetrics { @@ -89,8 +80,6 @@ pub struct FfiCommitSink { pub finish_commit: unsafe extern "C" fn(*mut c_void), pub prepare_node: unsafe extern "C" fn(*mut c_void, *mut c_void, bool, bool) -> *mut c_void, pub set_box_metrics: unsafe extern "C" fn(*mut c_void, *mut c_void, FfiCommittedBoxMetrics), - pub set_override_borders: unsafe extern "C" fn(*mut c_void, *mut c_void, FfiBordersData), - pub set_table_cell_coordinates: unsafe extern "C" fn(*mut c_void, *mut c_void, FfiTableCellCoordinates), pub begin_line_data: unsafe extern "C" fn(*mut c_void, *mut c_void) -> bool, pub begin_line: unsafe extern "C" fn(*mut c_void, FfiLineRecord), pub emit_fragment: unsafe extern "C" fn(*mut c_void, FfiCommittedFragment), @@ -210,17 +199,6 @@ fn commit_subtree( ); } - if !reuses_committed_subtree { - unsafe { - if let Some(borders) = fragment.override_borders_data { - (sink.set_override_borders)(sink.context, paintable, borders); - } - if let Some(coordinates) = fragment.table_cell_coordinates { - (sink.set_table_cell_coordinates)(sink.context, paintable, coordinates); - } - } - } - if !reuses_committed_subtree && let Some(line_data) = &fragment.line_data { // SAFETY: The sink keeps one line accumulator live between // begin_line_data() and finish_line_data(). diff --git a/Libraries/LibWeb/Rust/src/layout/fc_run_cache.rs b/Libraries/LibWeb/Rust/src/layout/fc_run_cache.rs index f1dfbb5c770c3..09987ae86d23e 100644 --- a/Libraries/LibWeb/Rust/src/layout/fc_run_cache.rs +++ b/Libraries/LibWeb/Rust/src/layout/fc_run_cache.rs @@ -476,14 +476,13 @@ fn verify_cached_entry_against_fresh_run(root_slot: u32, cached: &FcRunCacheEntr macro_rules! shadow_comparable_rare_payloads { ($carrier:expr) => { ( - $carrier.table_cell_coordinates, - $carrier.override_borders_data, $carrier.svg_viewport_transform, $carrier.svg_viewport_size, &$carrier.computed_svg_path, &$carrier.grid_layout_data, &$carrier.flex_layout_data, &$carrier.used_grid_tracks, + &$carrier.collapsed_table_borders, ) }; } diff --git a/Libraries/LibWeb/Rust/src/layout/formatting_context.rs b/Libraries/LibWeb/Rust/src/layout/formatting_context.rs index 44c5464969063..5d76d1144c25d 100644 --- a/Libraries/LibWeb/Rust/src/layout/formatting_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/formatting_context.rs @@ -763,22 +763,6 @@ pub struct FfiBorderData { pub width: CssPixels, } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -#[repr(C)] -pub struct FfiBorderDataWithElementKind { - pub border_data: FfiBorderData, - pub element_kind: u8, -} - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -#[repr(C)] -pub struct FfiBordersData { - pub top: FfiBorderDataWithElementKind, - pub right: FfiBorderDataWithElementKind, - pub bottom: FfiBorderDataWithElementKind, - pub left: FfiBorderDataWithElementKind, -} - #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub(crate) struct ChildLayoutResult { pub automatic_content_inline_size: CssPixels, diff --git a/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs b/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs index de6ba6e4138a2..f87392dd27481 100644 --- a/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs +++ b/Libraries/LibWeb/Rust/src/layout/fragment_tree.rs @@ -22,8 +22,6 @@ pub(crate) struct Fragment { pub(crate) padding_top: CssPixels, pub(crate) padding_bottom: CssPixels, pub(crate) uses_collapsing_borders_model: bool, - pub(crate) table_cell_coordinates: Option, - pub(crate) override_borders_data: Option, pub(crate) collapsed_table_borders: Option>, pub(crate) line_data: Option>, pub(crate) grid_layout_data: Option>, @@ -164,8 +162,6 @@ fn snapshot_fragment( let rare_payloads = used.rare_data.get().map(|cell| { let mut rare = cell.borrow_mut(); ( - rare.table_cell_coordinates, - rare.override_borders_data, rare.collapsed_table_borders.take(), rare.grid_layout_data.take(), rare.flex_layout_data.take(), @@ -176,8 +172,6 @@ fn snapshot_fragment( ) }); let ( - table_cell_coordinates, - override_borders_data, collapsed_table_borders, grid_layout_data, flex_layout_data, @@ -204,8 +198,6 @@ fn snapshot_fragment( padding_top: used.padding_top.get(), padding_bottom: used.padding_bottom.get(), uses_collapsing_borders_model: used.uses_collapsing_borders_model.get(), - table_cell_coordinates, - override_borders_data, collapsed_table_borders, line_data, grid_layout_data, diff --git a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs index 953b187da173d..f68f55a663887 100644 --- a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs @@ -4,13 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -pub(crate) const ELEMENT_CELL: u8 = 0; -pub(crate) const ELEMENT_ROW: u8 = 1; -pub(crate) const ELEMENT_ROW_GROUP: u8 = 2; -pub(crate) const ELEMENT_COLUMN: u8 = 3; -pub(crate) const ELEMENT_COLUMN_GROUP: u8 = 4; -pub(crate) const ELEMENT_TABLE: u8 = 5; - pub(crate) const LINE_STYLE_NONE: u8 = 0; pub(crate) const LINE_STYLE_HIDDEN: u8 = 1; pub(crate) const LINE_STYLE_DOTTED: u8 = 2; @@ -110,10 +103,11 @@ pub(crate) struct ElementBorders { // specific (steps 1-3 of the border conflict resolution algorithm), so ties resolve towards the // earlier-applied part, which implements step 4 without tracking element kinds or coordinates. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub(crate) struct CollapsedBorderSegment { - pub(crate) border_data: FfiBorderData, - pub(crate) element_kind: u8, - pub(crate) source_order: u32, +pub(crate) struct BorderWidths { + pub(crate) top: CssPixels, + pub(crate) right: CssPixels, + pub(crate) bottom: CssPixels, + pub(crate) left: CssPixels, } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] @@ -168,15 +162,15 @@ fn grid_line_offsets(sizes: impl ExactSizeIterator) -> Vec>, - vertical_lines: Vec>, + horizontal_lines: Vec>, + vertical_lines: Vec>, } impl CollapsedBorderGrid { pub(crate) fn new(row_count: usize, column_count: usize) -> Self { Self { - horizontal_lines: vec![vec![CollapsedBorderSegment::default(); column_count]; row_count + 1], - vertical_lines: vec![vec![CollapsedBorderSegment::default(); row_count]; column_count + 1], + horizontal_lines: vec![vec![FfiCollapsedBorderEdge::default(); column_count]; row_count + 1], + vertical_lines: vec![vec![FfiCollapsedBorderEdge::default(); row_count]; column_count + 1], } } @@ -187,7 +181,6 @@ impl CollapsedBorderGrid { row_end: usize, column_start: usize, column_end: usize, - element_kind: u8, source_order: u32, ) { Self::apply_to_segments( @@ -195,7 +188,6 @@ impl CollapsedBorderGrid { column_start, column_end, borders.top, - element_kind, source_order, ); Self::apply_to_segments( @@ -203,7 +195,6 @@ impl CollapsedBorderGrid { column_start, column_end, borders.bottom, - element_kind, source_order, ); Self::apply_to_segments( @@ -211,7 +202,6 @@ impl CollapsedBorderGrid { row_start, row_end, borders.left, - element_kind, source_order, ); Self::apply_to_segments( @@ -219,7 +209,6 @@ impl CollapsedBorderGrid { row_start, row_end, borders.right, - element_kind, source_order, ); } @@ -234,13 +223,12 @@ impl CollapsedBorderGrid { ) { // Segments strictly inside a spanning cell are not borders of any element; mark them as hidden // so that borders of rows and columns crossing the span cannot win there. - let hidden = CollapsedBorderSegment { + let hidden = FfiCollapsedBorderEdge { border_data: FfiBorderData { color: 0, line_style: LINE_STYLE_HIDDEN, width: CssPixels::default(), }, - element_kind: ELEMENT_CELL, source_order, }; for row in row_start + 1..row_end { @@ -255,65 +243,29 @@ impl CollapsedBorderGrid { } } - pub(crate) fn resolve_for_cell( + pub(crate) fn resolve_used_widths_for_cell( &self, row_start: usize, row_end: usize, column_start: usize, column_end: usize, - own: ElementBorders, - ) -> FfiBordersData { - let harvest = |winner: CollapsedBorderSegment, own_border: FfiBorderData| { - // A winner whose style is 'none' means every border meeting at this edge is 'none'; fall - // back to the cell's own (invisible) border so the stored winner matches the cell. - if winner.border_data.line_style == LINE_STYLE_NONE { - FfiBorderDataWithElementKind { - border_data: own_border, - element_kind: ELEMENT_CELL, - } - } else { - FfiBorderDataWithElementKind { - border_data: winner.border_data, - element_kind: winner.element_kind, - } - } - }; - FfiBordersData { - top: harvest( - Self::most_specific(&self.horizontal_lines[row_start], column_start, column_end), - own.top, - ), - right: harvest( - Self::most_specific(&self.vertical_lines[column_end], row_start, row_end), - own.right, - ), - bottom: harvest( - Self::most_specific(&self.horizontal_lines[row_end], column_start, column_end), - own.bottom, - ), - left: harvest( - Self::most_specific(&self.vertical_lines[column_start], row_start, row_end), - own.left, - ), + ) -> BorderWidths { + BorderWidths { + top: Self::most_specific(&self.horizontal_lines[row_start], column_start, column_end).border_data.width, + right: Self::most_specific(&self.vertical_lines[column_end], row_start, row_end).border_data.width, + bottom: Self::most_specific(&self.horizontal_lines[row_end], column_start, column_end).border_data.width, + left: Self::most_specific(&self.vertical_lines[column_start], row_start, row_end).border_data.width, } } - fn apply_to_segments( - line: &mut [CollapsedBorderSegment], - start: usize, - end: usize, - data: FfiBorderData, - element_kind: u8, - source_order: u32, - ) { + fn apply_to_segments(line: &mut [FfiCollapsedBorderEdge], start: usize, end: usize, data: FfiBorderData, source_order: u32) { if data.line_style == LINE_STYLE_NONE { return; } for segment in &mut line[start..end] { if candidate_wins(data, segment.border_data) { - *segment = CollapsedBorderSegment { + *segment = FfiCollapsedBorderEdge { border_data: data, - element_kind, source_order, }; } @@ -321,7 +273,7 @@ impl CollapsedBorderGrid { } pub(crate) fn has_paintable_edges(&self) -> bool { - let paints = |segment: &CollapsedBorderSegment| { + let paints = |segment: &FfiCollapsedBorderEdge| { segment.border_data.width > CssPixels::default() && segment.border_data.line_style != LINE_STYLE_NONE && segment.border_data.line_style != LINE_STYLE_HIDDEN @@ -330,17 +282,13 @@ impl CollapsedBorderGrid { } pub(crate) fn take_edges(self) -> (Vec, Vec) { - let to_edge = |segment: &CollapsedBorderSegment| FfiCollapsedBorderEdge { - border_data: segment.border_data, - source_order: segment.source_order, - }; ( - self.horizontal_lines.iter().flatten().map(to_edge).collect(), - self.vertical_lines.iter().flatten().map(to_edge).collect(), + self.horizontal_lines.iter().flatten().copied().collect(), + self.vertical_lines.iter().flatten().copied().collect(), ) } - fn most_specific(line: &[CollapsedBorderSegment], start: usize, end: usize) -> CollapsedBorderSegment { + fn most_specific(line: &[FfiCollapsedBorderEdge], start: usize, end: usize) -> FfiCollapsedBorderEdge { let mut winner = line[start]; for segment in &line[start + 1..end] { if candidate_wins(segment.border_data, winner.border_data) { @@ -1010,17 +958,6 @@ impl TableFormattingContext { self.records.create_used_values(&self.callbacks, node, constraints) } - fn set_cell_coordinates(&self, cell: TableCell) { - self.used_values(cell.box_) - .rare_data_mut() - .table_cell_coordinates = Some(crate::layout::FfiTableCellCoordinates { - row_index: cell.row_index, - column_index: cell.column_index, - row_span: cell.row_span, - column_span: cell.column_span, - }); - } - fn place_child(&self, node: Node, x: CssPixels, y: CssPixels) { crate::layout::place_child(&self.formatting_context_run(), node, FfiCssPixelPoint { x, y }, None); } @@ -1075,10 +1012,6 @@ impl TableFormattingContext { fn border_conflict_resolution(&mut self) { if self.style(self.table_box).border_collapse() == BORDER_COLLAPSE_SEPARATE { - for cell_index in 0..self.cells.len() { - let cell = self.cells[cell_index]; - self.set_cell_coordinates(cell); - } return; } @@ -1113,14 +1046,13 @@ impl TableFormattingContext { cell.row_index + cell.row_span, cell.column_index, cell.column_index + cell.column_span, - ELEMENT_CELL, source_order, ); } for row_index in 0..row_count { let row_box = self.rows[row_index].box_; let borders = self.element_borders(row_box); - grid.apply_borders(borders, row_index, row_index + 1, 0, column_count, ELEMENT_ROW, take_source_order()); + grid.apply_borders(borders, row_index, row_index + 1, 0, column_count, take_source_order()); } // Row groups, in the order their rows appear in the grid. Rows of a group are contiguous in // m_rows, since TableGrid collects them in tree order. @@ -1141,7 +1073,7 @@ impl TableFormattingContext { row_index += 1; } let borders = self.element_borders(group); - grid.apply_borders(borders, start, row_index, 0, column_count, ELEMENT_ROW_GROUP, take_source_order()); + grid.apply_borders(borders, start, row_index, 0, column_count, take_source_order()); } // Column () elements. @@ -1155,7 +1087,7 @@ impl TableFormattingContext { let borders = self.element_borders(column); let source_order = take_source_order(); while column_index < end { - grid.apply_borders(borders, 0, row_count, column_index, column_index + 1, ELEMENT_COLUMN, source_order); + grid.apply_borders(borders, 0, row_count, column_index, column_index + 1, source_order); column_index += 1; } } @@ -1164,28 +1096,23 @@ impl TableFormattingContext { for (column_group, group_start, group_end) in column_group_ranges { if group_start < group_end { let borders = self.element_borders(column_group); - grid.apply_borders(borders, 0, row_count, group_start, group_end, ELEMENT_COLUMN_GROUP, take_source_order()); + grid.apply_borders(borders, 0, row_count, group_start, group_end, take_source_order()); } } let table_borders = self.element_borders(self.table_box); - grid.apply_borders(table_borders, 0, row_count, 0, column_count, ELEMENT_TABLE, take_source_order()); + grid.apply_borders(table_borders, 0, row_count, 0, column_count, take_source_order()); for cell_index in 0..self.cells.len() { let cell = self.cells[cell_index]; - let own = self.element_borders(cell.box_); let row_end = cell.row_index + cell.row_span; let column_end = cell.column_index + cell.column_span; - let resolved = grid.resolve_for_cell(cell.row_index, row_end, cell.column_index, column_end, own); - self.set_cell_coordinates(cell); + let widths = grid.resolve_used_widths_for_cell(cell.row_index, row_end, cell.column_index, column_end); let used = self.used_values(cell.box_); - used.border_top.set(resolved.top.border_data.width); - used.border_right.set(resolved.right.border_data.width); - used.border_bottom.set(resolved.bottom.border_data.width); - used.border_left.set(resolved.left.border_data.width); + used.border_top.set(widths.top); + used.border_right.set(widths.right); + used.border_bottom.set(widths.bottom); + used.border_left.set(widths.left); used.uses_collapsing_borders_model.set(true); - self.used_values(cell.box_) - .rare_data_mut() - .override_borders_data = Some(resolved); } self.collapsed_border_grid = Some(grid); } diff --git a/Libraries/LibWeb/Rust/src/layout/used_values.rs b/Libraries/LibWeb/Rust/src/layout/used_values.rs index 9d33db7e019b9..975e352d25b85 100644 --- a/Libraries/LibWeb/Rust/src/layout/used_values.rs +++ b/Libraries/LibWeb/Rust/src/layout/used_values.rs @@ -122,14 +122,12 @@ pub(crate) struct LineData { #[derive(Clone, Default)] pub(crate) struct UsedValuesRareData { - pub(crate) table_cell_coordinates: Option, pub(crate) computed_svg_path: Option>, pub(crate) svg_viewport_transform: Option, pub(crate) svg_viewport_size: Option, pub(crate) grid_layout_data: Option>, pub(crate) flex_layout_data: Option>, pub(crate) used_grid_tracks: Option>, - pub(crate) override_borders_data: Option, pub(crate) collapsed_table_borders: Option>, pub(crate) abspos_layout_inputs: Option, } @@ -137,19 +135,17 @@ pub(crate) struct UsedValuesRareData { impl UsedValuesRareData { pub(crate) fn install_present_payloads_into(self, record: &UsedValues) { let Self { - table_cell_coordinates, computed_svg_path, svg_viewport_transform, svg_viewport_size, grid_layout_data, flex_layout_data, used_grid_tracks, - override_borders_data, collapsed_table_borders, abspos_layout_inputs, } = self; debug_assert!( - table_cell_coordinates.is_none() && override_borders_data.is_none() && abspos_layout_inputs.is_none(), + abspos_layout_inputs.is_none(), "a run authored a parent-owned rare payload on its root record" ); if computed_svg_path.is_none() From 459bbdada80fd930c77d1c215d773009344c71f3 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 17 Aug 2026 19:11:47 +0200 Subject: [PATCH 12/12] LibWeb: Give collapsed-borders tables their resolved grid border MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per CSS 2.2 ยง17.6.2 a table in the collapsing model has no border of its own: its used border is the winning border of the outer grid edges, and only the inner half of every collapsed border lies inside the table's border box. We kept the table's computed border widths, so a collapsed table reserved its full style border even though nothing painted there, and the outer border halves spilled into the margin area instead of the border box. Border conflict resolution now overwrites the table's used border with the outer grid winners and marks the table as using the collapsing model, so the existing halved-border geometry applies to it just as it does to cells. The parent resolved the table's content offset and inline space from the computed widths before the run, so the run rebases its row offsets and available inline space, and the parent shifts the pending position after the run; the remaining consumers of the table's box metrics become collapsing-model aware. The table's padding still applies in collapsed mode, which CSS 2.2 also disallows; that divergence is unchanged here. --- Libraries/LibWeb/Painting/Paintable.cpp | 3 +- .../src/layout/block_formatting_context.rs | 29 +++- .../LibWeb/Rust/src/layout/sizing_context.rs | 2 +- .../src/layout/table_formatting_context.rs | 41 ++++- .../css-table-cell-verticalalign-text-top.txt | 36 ++--- .../table/border-collapse-is-inherited.txt | 150 +++++++++--------- .../border-conflict-resolution-with-cell.txt | 66 ++++---- .../border-conflict-resolution-with-col.txt | 66 ++++---- ...ict-resolution-with-multiple-colgroups.txt | 42 ++--- .../border-conflict-resolution-with-row.txt | 70 ++++---- ...rder-conflict-resolution-with-rowgroup.txt | 74 ++++----- .../table/clip-spans-to-table-end.txt | 74 ++++----- .../expected/table/line-breaking-in-cells.txt | 46 +++--- .../percentage-width-max-width-columns.txt | 44 ++--- ...th-distribution-of-max-width-increment.txt | 44 ++--- .../scrollable-contains-table-ref.html | 17 +- ...le-collapsed-borders-joint-widths-ref.html | 24 +-- ...-collapsed-borders-tie-precedence-ref.html | 2 +- 18 files changed, 447 insertions(+), 383 deletions(-) diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index 98c941cec81dd..89a6112e451f0 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -1902,8 +1902,7 @@ void Paintable::paint(DisplayListRecordingContext& context, PaintPhase phase) co paint_box_shadow(context); } - auto const is_table_with_collapsed_borders = display().is_table_inside() && layout_node().border_collapse() == CSS::BorderCollapse::Collapse; - if (phase == PaintPhase::Border && !uses_collapsing_borders_model() && !is_table_with_collapsed_borders && !empty_cells_property_applies()) { + if (phase == PaintPhase::Border && !uses_collapsing_borders_model() && !empty_cells_property_applies()) { paint_border(context); } diff --git a/Libraries/LibWeb/Rust/src/layout/block_formatting_context.rs b/Libraries/LibWeb/Rust/src/layout/block_formatting_context.rs index 2d8f2c14d2e4e..30d26ed9b6975 100644 --- a/Libraries/LibWeb/Rust/src/layout/block_formatting_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/block_formatting_context.rs @@ -1817,11 +1817,22 @@ impl BlockFormattingContext { }, participation: ParticipationInParentFormattingContext::BlockLevel, }; + let pre_run_table_border_box = is_table_formatting_context.then(|| { + let used = self.used(node); + (used.border_box_left(false), used.border_box_top(false)) + }); let child_layout = self.layout_inside(run, node, inside_layout_input, true); if container_facts.is_table_wrapper() && style.display().is_table_inside() && child_layout.is_some() { let used = self.used(node); self.table_box_in_wrapper_border_box_block_size .set(Some(used.border_box_block_size(used.uses_collapsing_borders_model.get()))); + if used.uses_collapsing_borders_model.get() + && let Some(position) = pending_position.as_mut() + && let Some((pre_run_border_box_left, pre_run_border_box_top)) = pre_run_table_border_box + { + position.x += used.border_box_left(true) - pre_run_border_box_left; + position.y += used.border_box_top(true) - pre_run_border_box_top; + } } child_layout } else { @@ -1933,7 +1944,9 @@ impl BlockFormattingContext { drop(margin_state); let used = self.used(node); self.block_offset_of_current_block_container.set(Some( - used.content_offset.get().y + used.content_block_size.get() + used.border_box_bottom(false), + used.content_offset.get().y + + used.content_block_size.get() + + used.border_box_bottom(used.uses_collapsing_borders_model.get()), )); } self.margin_state @@ -1945,8 +1958,11 @@ impl BlockFormattingContext { self.margin_state.borrow_mut().update_open_top_margin_group(); let used = self.used(node); - *bottom_of_lowest_margin_box = (*bottom_of_lowest_margin_box) - .max(used.content_offset.get().y + used.content_block_size.get() + used.margin_box_bottom(false)); + *bottom_of_lowest_margin_box = (*bottom_of_lowest_margin_box).max( + used.content_offset.get().y + + used.content_block_size.get() + + used.margin_box_bottom(used.uses_collapsing_borders_model.get()), + ); } fn layout_block_level_children( @@ -2710,7 +2726,7 @@ impl BlockFormattingContext { } return (child_used.content_offset.get().y + child_used.content_block_size.get() - + child_used.border_box_bottom(false) + + child_used.border_box_bottom(child_used.uses_collapsing_borders_model.get()) + margin_bottom) .max(CssPixels::default()); } @@ -2835,7 +2851,8 @@ impl BlockFormattingContext { while let Some(node) = stack.pop() { let facts = self.facts(node); if facts.is_box() && self.style(node).display().is_table_inside() { - return self.used(node).border_box_inline_size(false); + let used = self.used(node); + return used.border_box_inline_size(used.uses_collapsing_borders_model.get()); } let mut children = Vec::new(); let mut child = self.first_child(node); @@ -2966,7 +2983,7 @@ pub(crate) fn automatic_block_size_for_bfc_root( }; let child_bottom = child_used.content_offset.get().y + child_used.content_block_size.get() - + child_used.border_box_bottom(false) + + child_used.border_box_bottom(child_used.uses_collapsing_borders_model.get()) + margin_bottom; bottom = Some(bottom.map_or(child_bottom, |value: CssPixels| value.max(child_bottom))); } diff --git a/Libraries/LibWeb/Rust/src/layout/sizing_context.rs b/Libraries/LibWeb/Rust/src/layout/sizing_context.rs index 7f8c611a6bec7..c27f4ba51bc31 100644 --- a/Libraries/LibWeb/Rust/src/layout/sizing_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/sizing_context.rs @@ -1970,7 +1970,7 @@ impl SizingContext { true, ); - let table_used_inline_size = table_used.border_box_inline_size(false); + let table_used_inline_size = table_used.border_box_inline_size(table_used.uses_collapsing_borders_model.get()); if table_wrapper_inline_size_mode == TableWrapperInlineSizeMode::UseTableUsedInlineSizeIfNotAuto && !table_style.width().is_auto() { diff --git a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs index f68f55a663887..74d0b735b0386 100644 --- a/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs +++ b/Libraries/LibWeb/Rust/src/layout/table_formatting_context.rs @@ -272,6 +272,20 @@ impl CollapsedBorderGrid { } } + pub(crate) fn outer_edge_widths(&self) -> BorderWidths { + let max_width = |segments: &[FfiCollapsedBorderEdge]| { + segments + .iter() + .fold(CssPixels::default(), |max, segment| max.max(segment.border_data.width)) + }; + BorderWidths { + top: max_width(&self.horizontal_lines[0]), + right: max_width(self.vertical_lines.last().expect("grid has vertical lines")), + bottom: max_width(self.horizontal_lines.last().expect("grid has horizontal lines")), + left: max_width(&self.vertical_lines[0]), + } + } + pub(crate) fn has_paintable_edges(&self) -> bool { let paints = |segment: &FfiCollapsedBorderEdge| { segment.border_data.width > CssPixels::default() @@ -1102,6 +1116,21 @@ impl TableFormattingContext { let table_borders = self.element_borders(self.table_box); grid.apply_borders(table_borders, 0, row_count, 0, column_count, take_source_order()); + let outer = grid.outer_edge_widths(); + let table_used = self.used_values(self.table_box); + let old_border_box_top = table_used.border_box_top(false); + let old_inline_borders = table_used.border_box_left(false) + table_used.border_box_right(false); + table_used.border_top.set(outer.top); + table_used.border_right.set(outer.right); + table_used.border_bottom.set(outer.bottom); + table_used.border_left.set(outer.left); + table_used.uses_collapsing_borders_model.set(true); + self.table_box_content_block_offset_in_wrapper += table_used.border_box_top(true) - old_border_box_top; + let freed_inline = old_inline_borders - (table_used.border_box_left(true) + table_used.border_box_right(true)); + if let AvailableSize::Definite(available) = self.available_space.inline_size { + self.available_space.inline_size = AvailableSize::definite(available + freed_inline); + } + for cell_index in 0..self.cells.len() { let cell = self.cells[cell_index]; let row_end = cell.row_index + cell.row_span; @@ -1812,7 +1841,8 @@ impl TableFormattingContext { let mut resolved = constraint.to_px(basis); if self.style(self.table_box).box_sizing() == box_sizing::BORDER_BOX { let used = self.used_values(self.table_box); - resolved -= used.border_box_left(false) + used.border_box_right(false); + let collapsed = used.uses_collapsing_borders_model.get(); + resolved -= used.border_box_left(collapsed) + used.border_box_right(collapsed); } resolved.max(CssPixels::default()) } @@ -2245,7 +2275,8 @@ impl TableFormattingContext { .fold(CssPixels::default(), |sum, row| sum + row.base_block_size); if let Some(minimum) = self.min_border_box_block_size_from_flex_item { let used = self.used_values(self.table_box); - let content_min = minimum - used.border_box_top(false) - used.border_box_bottom(false); + let collapsed = used.uses_collapsing_borders_model.get(); + let content_min = minimum - used.border_box_top(collapsed) - used.border_box_bottom(collapsed); self.table_block_size = self.table_block_size.max(content_min); } let table_style = self.style(self.table_box); @@ -2255,7 +2286,8 @@ impl TableFormattingContext { let mut specified = table_style.height().to_px(self.table_constraints.block_basis()); if table_style.box_sizing() == box_sizing::BORDER_BOX { let used = self.used_values(self.table_box); - specified -= used.border_box_top(false) + used.border_box_bottom(false); + let collapsed = used.uses_collapsing_borders_model.get(); + specified -= used.border_box_top(collapsed) + used.border_box_bottom(collapsed); } self.table_block_size = self.table_block_size.max(specified); } @@ -2382,7 +2414,8 @@ impl TableFormattingContext { let table_used = self.used_values(self.table_box); let block_spacing = self.border_spacing_block(); let inline_spacing = self.border_spacing_inline(); - let inline_offset = table_used.border_left.get() + table_used.padding_left.get() + inline_spacing; + let inline_offset = + table_used.border_box_left(table_used.uses_collapsing_borders_model.get()) + inline_spacing; let mut row_block_offset = self.table_box_content_block_offset_in_wrapper + block_spacing; for row_index in 0..self.rows.len() { let row = &self.rows[row_index]; diff --git a/Tests/LibWeb/Layout/expected/css-table-cell-verticalalign-text-top.txt b/Tests/LibWeb/Layout/expected/css-table-cell-verticalalign-text-top.txt index 7b0cd5b3c393c..e25d457999729 100644 --- a/Tests/LibWeb/Layout/expected/css-table-cell-verticalalign-text-top.txt +++ b/Tests/LibWeb/Layout/expected/css-table-cell-verticalalign-text-top.txt @@ -1,32 +1,32 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 116 0+0+0] [BFC] children: not-inline + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 118 0+0+0] [BFC] children: not-inline BlockContainer <(anonymous)> at [0,0] [0+0+0 800 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 100 0+0+8] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 102 0+0+8] children: not-inline BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) - TableWrapper <(anonymous)> at [8,8] [0+0+0 204 0+0+580] [0+0+0 100 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 204 0+0+0] [0+0+0 100 0+0+0] [TFC] children: not-inline - Box at [8,8] table-row-group [0+0+0 204 0+0+0] [0+0+0 100 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 204 0+0+0] [0+0+0 100 0+0+0] children: not-inline - BlockContainer
at [10,10] table-cell [0+1+1 200 1+1+0] [0+1+1 16 81+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 15, rect: [10,10 129.296875x16] baseline: 12.796875 + TableWrapper <(anonymous)> at [8,8] [0+0+0 206 0+0+578] [0+0+0 102 0+0+0] [BFC] children: not-inline + Box at [9,9] table-box [0+1+0 204 0+1+0] [0+1+0 100 0+1+0] [TFC] children: not-inline + Box at [9,9] table-row-group [0+0+0 204 0+0+0] [0+0+0 100 0+0+0] children: not-inline + Box at [9,9] table-row [0+0+0 204 0+0+0] [0+0+0 100 0+0+0] children: not-inline + BlockContainer
at [11,11] table-cell [0+1+1 200 1+1+0] [0+1+1 16 81+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 15, rect: [11,11 129.296875x16] baseline: 12.796875 "Text at the top" TextNode <#text> (not painted) - BlockContainer <(anonymous)> at [8,108] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline + BlockContainer <(anonymous)> at [8,110] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x116] + PaintableWithLines (BlockContainer) [0,0 800x118] PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0] - PaintableWithLines (BlockContainer) [8,8 784x100] + PaintableWithLines (BlockContainer) [8,8 784x102] PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0] - PaintableWithLines (TableWrapper(anonymous)) [8,8 204x100] - Paintable (Box) [8,8 204x100] - Paintable (Box) [8,8 204x100] - Paintable (Box) [8,8 204x100] - PaintableWithLines (BlockContainer
) [8,8 204x100] - PaintableWithLines (BlockContainer(anonymous)) [8,108 784x0] + PaintableWithLines (TableWrapper(anonymous)) [8,8 206x102] + Paintable (Box) [8,8 206x102] + Paintable (Box) [9,9 204x100] + Paintable (Box) [9,9 204x100] + PaintableWithLines (BlockContainer
) [9,9 204x100] + PaintableWithLines (BlockContainer(anonymous)) [8,110 784x0] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x116] (z-index: auto) + SC for BlockContainer [0,0 800x118] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/border-collapse-is-inherited.txt b/Tests/LibWeb/Layout/expected/table/border-collapse-is-inherited.txt index bf34ed285048c..583b76d0dc135 100644 --- a/Tests/LibWeb/Layout/expected/table/border-collapse-is-inherited.txt +++ b/Tests/LibWeb/Layout/expected/table/border-collapse-is-inherited.txt @@ -1,150 +1,150 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 208 0+0+0] [BFC] children: not-inline + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 210 0+0+0] [BFC] children: not-inline BlockContainer <(anonymous)> at [0,0] [0+0+0 800 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 192 0+0+8] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 194 0+0+8] children: not-inline BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) - BlockContainer at [8,8] [0+0+0 784 0+0+0] [0+0+0 192 0+0+0] children: inline - frag 0 from BlockContainer start: 0, length: 0, rect: [9,9 161.90625x190] baseline: 100.296875 + BlockContainer at [8,8] [0+0+0 784 0+0+0] [0+0+0 194 0+0+0] children: inline + frag 0 from BlockContainer start: 0, length: 0, rect: [9,9 163.90625x192] baseline: 102.296875 TextNode <#text> (not painted) - BlockContainer at [9,9] inline-block [0+1+0 161.90625 0+1+0] [0+1+0 190 0+1+0] [BFC] children: not-inline - BlockContainer <(anonymous)> at [9,9] [0+0+0 161.90625 0+0+0] [0+0+0 0 0+0+0] children: inline + BlockContainer
at [9,9] inline-block [0+1+0 163.90625 0+1+0] [0+1+0 192 0+1+0] [BFC] children: not-inline + BlockContainer <(anonymous)> at [9,9] [0+0+0 163.90625 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) - TableWrapper <(anonymous)> at [9,9] inline-block [0+0+0 161.90625 0+0+0] [0+0+0 190 0+0+0] [BFC] children: not-inline - Box <(anonymous)> at [9,9] inline-table table-box [0+0+0 161.90625 0+0+0] [0+0+0 190 0+0+0] [TFC] children: not-inline - Box at [9,9] table-row-group [0+0+0 161.90625 0+0+0] [0+0+0 190 0+0+0] children: not-inline - Box at [9,9] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [10,10] table-row-group [0+0+0 161.90625 0+0+0] [0+0+0 190 0+0+0] children: not-inline + Box at [10,10] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [9,47] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [10,48] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [9,85] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [10,86] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [9,123] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [10,124] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [9,161] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [10,162] table-row [0+0+0 161.90625 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer
at [30,20] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [30,20 14.265625x16] baseline: 12.796875 + TableWrapper <(anonymous)> at [9,9] inline-block [0+0+0 163.90625 0+0+0] [0+0+0 192 0+0+0] [BFC] children: not-inline + Box <(anonymous)> at [10,10] inline-table table-box [0+1+0 161.90625 0+1+0] [0+1+0 190 0+1+0] [TFC] children: not-inline + Box
at [31,21] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [31,21 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [86.265625,20] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.859375,20 9.34375x16] baseline: 12.796875 + BlockContainer at [87.265625,21] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [88.859375,21 9.34375x16] baseline: 12.796875 "B" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [140.8125,20] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [142.1875,20 6.34375x16] baseline: 12.796875 + BlockContainer at [141.8125,21] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [143.1875,21 6.34375x16] baseline: 12.796875 "1" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [30,58] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31.96875,58 10.3125x16] baseline: 12.796875 + Box
at [31,59] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [32.96875,59 10.3125x16] baseline: 12.796875 "C" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [86.265625,58] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [86.96875,58 11.140625x16] baseline: 12.796875 + BlockContainer at [87.265625,59] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [87.96875,59 11.140625x16] baseline: 12.796875 "D" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [140.8125,58] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [140.953125,58 8.8125x16] baseline: 12.796875 + BlockContainer at [141.8125,59] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [141.953125,59 8.8125x16] baseline: 12.796875 "2" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [30,96] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31.203125,96 11.859375x16] baseline: 12.796875 + Box
at [31,97] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [32.203125,97 11.859375x16] baseline: 12.796875 "E" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [86.265625,96] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [86.265625,96 12.546875x16] baseline: 12.796875 + BlockContainer at [87.265625,97] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [87.265625,97 12.546875x16] baseline: 12.796875 "F" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [140.8125,96] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [140.8125,96 9.09375x16] baseline: 12.796875 + BlockContainer at [141.8125,97] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [141.8125,97 9.09375x16] baseline: 12.796875 "3" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [30,134] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [30.515625,134 13.234375x16] baseline: 12.796875 + Box
at [31,135] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [31.515625,135 13.234375x16] baseline: 12.796875 "G" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [86.265625,134] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [86.421875,134 12.234375x16] baseline: 12.796875 + BlockContainer at [87.265625,135] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [87.421875,135 12.234375x16] baseline: 12.796875 "H" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [140.8125,134] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [141.484375,134 7.75x16] baseline: 12.796875 + BlockContainer at [141.8125,135] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [142.484375,135 7.75x16] baseline: 12.796875 "4" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [30,172] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [34.828125,172 4.59375x16] baseline: 12.796875 + Box
at [31,173] table-cell [0+1+20 14.265625 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [35.828125,173 4.59375x16] baseline: 12.796875 "I" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [86.265625,172] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [88.078125,172 8.90625x16] baseline: 12.796875 + BlockContainer at [87.265625,173] table-cell [0+1+20 12.546875 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [89.078125,173 8.90625x16] baseline: 12.796875 "J" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [140.8125,172] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [141.125,172 8.453125x16] baseline: 12.796875 + BlockContainer at [141.8125,173] table-cell [0+1+20 9.09375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [142.125,173 8.453125x16] baseline: 12.796875 "5" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) TextNode <#text> (not painted) - BlockContainer <(anonymous)> at [8,200] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline + BlockContainer <(anonymous)> at [8,202] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x208] + PaintableWithLines (BlockContainer) [0,0 800x210] PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0] - PaintableWithLines (BlockContainer) [8,8 784x192] + PaintableWithLines (BlockContainer) [8,8 784x194] PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0] - PaintableWithLines (BlockContainer
.horizontal) [8,8 784x192] - PaintableWithLines (BlockContainer) [8,8 163.90625x192] - PaintableWithLines (BlockContainer(anonymous)) [9,9 161.90625x0] - PaintableWithLines (TableWrapper(anonymous)) [9,9 161.90625x190] - Paintable (Box(anonymous)) [9,9 161.90625x190] - Paintable (Box) [9,9 161.90625x190] - Paintable (Box) [9,9 161.90625x38] - PaintableWithLines (BlockContainer) [9,47 161.90625x38] - PaintableWithLines (BlockContainer) [9,85 161.90625x38] - PaintableWithLines (BlockContainer) [9,123 161.90625x38] - PaintableWithLines (BlockContainer) [9,161 161.90625x38] - PaintableWithLines (BlockContainer
) [9,9 56.265625x38] - PaintableWithLines (BlockContainer) [65.265625,9 54.546875x38] - PaintableWithLines (BlockContainer) [119.8125,9 51.09375x38] - Paintable (Box
) [9,47 56.265625x38] - PaintableWithLines (BlockContainer) [65.265625,47 54.546875x38] - PaintableWithLines (BlockContainer) [119.8125,47 51.09375x38] - Paintable (Box
) [9,85 56.265625x38] - PaintableWithLines (BlockContainer) [65.265625,85 54.546875x38] - PaintableWithLines (BlockContainer) [119.8125,85 51.09375x38] - Paintable (Box
) [9,123 56.265625x38] - PaintableWithLines (BlockContainer) [65.265625,123 54.546875x38] - PaintableWithLines (BlockContainer) [119.8125,123 51.09375x38] - Paintable (Box
) [9,161 56.265625x38] - PaintableWithLines (BlockContainer) [65.265625,161 54.546875x38] - PaintableWithLines (BlockContainer) [119.8125,161 51.09375x38] - PaintableWithLines (BlockContainer(anonymous)) [8,200 784x0] + PaintableWithLines (BlockContainer
.horizontal) [8,8 784x194] + PaintableWithLines (BlockContainer) [8,8 165.90625x194] + PaintableWithLines (BlockContainer(anonymous)) [9,9 163.90625x0] + PaintableWithLines (TableWrapper(anonymous)) [9,9 163.90625x192] + Paintable (Box(anonymous)) [9,9 163.90625x192] + Paintable (Box) [10,10 161.90625x190] + Paintable (Box) [10,10 161.90625x38] + PaintableWithLines (BlockContainer) [10,48 161.90625x38] + PaintableWithLines (BlockContainer) [10,86 161.90625x38] + PaintableWithLines (BlockContainer) [10,124 161.90625x38] + PaintableWithLines (BlockContainer) [10,162 161.90625x38] + PaintableWithLines (BlockContainer
) [10,10 56.265625x38] + PaintableWithLines (BlockContainer) [66.265625,10 54.546875x38] + PaintableWithLines (BlockContainer) [120.8125,10 51.09375x38] + Paintable (Box
) [10,48 56.265625x38] + PaintableWithLines (BlockContainer) [66.265625,48 54.546875x38] + PaintableWithLines (BlockContainer) [120.8125,48 51.09375x38] + Paintable (Box
) [10,86 56.265625x38] + PaintableWithLines (BlockContainer) [66.265625,86 54.546875x38] + PaintableWithLines (BlockContainer) [120.8125,86 51.09375x38] + Paintable (Box
) [10,124 56.265625x38] + PaintableWithLines (BlockContainer) [66.265625,124 54.546875x38] + PaintableWithLines (BlockContainer) [120.8125,124 51.09375x38] + Paintable (Box
) [10,162 56.265625x38] + PaintableWithLines (BlockContainer) [66.265625,162 54.546875x38] + PaintableWithLines (BlockContainer) [120.8125,162 51.09375x38] + PaintableWithLines (BlockContainer(anonymous)) [8,202 784x0] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x208] (z-index: auto) + SC for BlockContainer [0,0 800x210] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-cell.txt b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-cell.txt index f939fcb3c23a4..247a9c17f6843 100644 --- a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-cell.txt +++ b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-cell.txt @@ -1,60 +1,60 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 100 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 84 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 172.671875 0+0+611.328125] [0+0+0 84 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 172.671875 0+0+0] [0+0+0 84 0+0+0] [TFC] children: not-inline - Box at [8,8] table-row-group [0+0+0 172.671875 0+0+0] [0+0+0 84 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 172.671875 0+0+0] [0+0+0 42 0+0+0] children: not-inline - BlockContainer
at [29,21] table-cell [0+1+20 14.265625 20+5+0] [0+1+12 16 12+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [29,21 14.265625x16] baseline: 12.796875 + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 106 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 90 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 176.671875 0+0+607.328125] [0+0+0 90 0+0+0] [BFC] children: not-inline + Box at [9,11] table-box [0+1+0 172.671875 0+5+0] [0+5+0 84 0+5+0] [TFC] children: not-inline + Box at [9,11] table-row-group [0+0+0 172.671875 0+0+0] [0+0+0 84 0+0+0] children: not-inline + Box at [9,11] table-row [0+0+0 172.671875 0+0+0] [0+0+0 42 0+0+0] children: not-inline + BlockContainer at [8,50] table-row [0+0+0 172.671875 0+0+0] [0+0+0 42 0+0+0] children: not-inline - BlockContainer at [9,53] table-row [0+0+0 172.671875 0+0+0] [0+0+0 42 0+0+0] children: not-inline + BlockContainer
at [30,24] table-cell [0+1+20 14.265625 20+5+0] [0+1+12 16 12+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [30,24 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [89.265625,21] table-cell [0+5+20 9.859375 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [89.265625,21 9.34375x16] baseline: 12.796875 + BlockContainer at [90.265625,24] table-cell [0+5+20 9.859375 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [90.265625,24 9.34375x16] baseline: 12.796875 "B" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [145.125,20] table-cell [0+5+20 14.546875 20+1+0] [0+1+11 16 11+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [145.125,20 10.3125x16] baseline: 12.796875 + BlockContainer at [146.125,23] table-cell [0+5+20 14.546875 20+1+0] [0+1+11 16 11+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [146.125,23 10.3125x16] baseline: 12.796875 "C" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [29,63] table-cell [0+1+20 16.265625 20+1+0] [0+1+12 16 12+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [29,63 11.140625x16] baseline: 12.796875 + Box
at [30,66] table-cell [0+1+20 16.265625 20+1+0] [0+1+12 16 12+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [30,66 11.140625x16] baseline: 12.796875 "D" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [87.265625,64] table-cell [0+1+20 11.859375 20+5+0] [0+5+11 16 11+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.265625,64 11.859375x16] baseline: 12.796875 + BlockContainer at [88.265625,67] table-cell [0+1+20 11.859375 20+5+0] [0+5+11 16 11+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [88.265625,67 11.859375x16] baseline: 12.796875 "E" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [145.125,63] table-cell [0+5+20 12.546875 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [145.125,63 12.546875x16] baseline: 12.796875 + BlockContainer at [146.125,66] table-cell [0+5+20 12.546875 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [146.125,66 12.546875x16] baseline: 12.796875 "F" TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x100] - PaintableWithLines (BlockContainer) [8,8 784x84] - PaintableWithLines (TableWrapper(anonymous)) [8,8 172.671875x84] - Paintable (Box) [8,8 172.671875x84] - Paintable (Box) [8,8 172.671875x84] - Paintable (Box) [8,8 172.671875x42] - PaintableWithLines (BlockContainer) [8,50 172.671875x42] - PaintableWithLines (BlockContainer
) [8,8 58.265625x42] - PaintableWithLines (BlockContainer.td-thick-border) [66.265625,8 55.859375x42] - PaintableWithLines (BlockContainer) [122.125,8 58.546875x42] - Paintable (Box
) [8,50 58.265625x42] - PaintableWithLines (BlockContainer) [66.265625,50 55.859375x42] - PaintableWithLines (BlockContainer.td-thick-border) [122.125,50 58.546875x42] + PaintableWithLines (BlockContainer) [0,0 800x106] + PaintableWithLines (BlockContainer) [8,8 784x90] + PaintableWithLines (TableWrapper(anonymous)) [8,8 176.671875x90] + Paintable (Box) [8,8 176.671875x90] + Paintable (Box) [9,11 172.671875x84] + Paintable (Box) [9,11 172.671875x42] + PaintableWithLines (BlockContainer) [9,53 172.671875x42] + PaintableWithLines (BlockContainer
) [9,11 58.265625x42] + PaintableWithLines (BlockContainer.td-thick-border) [67.265625,11 55.859375x42] + PaintableWithLines (BlockContainer) [123.125,11 58.546875x42] + Paintable (Box
) [9,53 58.265625x42] + PaintableWithLines (BlockContainer) [67.265625,53 55.859375x42] + PaintableWithLines (BlockContainer.td-thick-border) [123.125,53 58.546875x42] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x100] (z-index: auto) + SC for BlockContainer [0,0 800x106] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-col.txt b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-col.txt index a79320ffe4387..1963384fa02a0 100644 --- a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-col.txt +++ b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-col.txt @@ -1,63 +1,63 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 172 0+0+0] [BFC] children: not-inline + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 178 0+0+0] [BFC] children: not-inline BlockContainer <(anonymous)> at [0,0] [0+0+0 800 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 156 0+0+8] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 162 0+0+8] children: not-inline BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) - TableWrapper <(anonymous)> at [8,8] [0+0+0 60.265625 0+0+723.734375] [0+0+0 156 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 60.265625 0+0+0] [0+0+0 156 0+0+0] [TFC] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 66.265625 0+0+717.734375] [0+0+0 162 0+0+0] [BFC] children: not-inline + Box
at [11,11] table-box [0+5+0 60.265625 0+5+0] [0+5+0 156 0+5+0] [TFC] children: not-inline BlockContainer (not painted) table-column-group children: not-inline BlockContainer (not painted) children: not-inline BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box at [8,8] table-row-group [0+0+0 60.265625 0+0+0] [0+0+0 156 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 60.265625 0+0+0] [0+0+0 40 0+0+0] children: not-inline - BlockContainer at [11,11] table-row-group [0+0+0 60.265625 0+0+0] [0+0+0 156 0+0+0] children: not-inline + Box at [11,11] table-row [0+0+0 60.265625 0+0+0] [0+0+0 40 0+0+0] children: not-inline + BlockContainer at [8,48] table-row [0+0+0 60.265625 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [11,51] table-row [0+0+0 60.265625 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [8,86] table-row [0+0+0 60.265625 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [11,89] table-row [0+0+0 60.265625 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [8,124] table-row [0+0+0 60.265625 0+0+0] [0+0+0 40 0+0+0] children: not-inline - BlockContainer at [11,127] table-row [0+0+0 60.265625 0+0+0] [0+0+0 40 0+0+0] children: not-inline + BlockContainer
at [31,21] table-cell [0+5+20 14.265625 20+5+0] [0+5+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,21 14.265625x16] baseline: 12.796875 + Box
at [34,24] table-cell [0+5+20 14.265625 20+5+0] [0+5+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,24 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [31,59] table-cell [0+5+20 14.265625 20+5+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,59 9.34375x16] baseline: 12.796875 + Box
at [34,62] table-cell [0+5+20 14.265625 20+5+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,62 9.34375x16] baseline: 12.796875 "B" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [31,97] table-cell [0+5+20 14.265625 20+5+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,97 10.3125x16] baseline: 12.796875 + Box
at [34,100] table-cell [0+5+20 14.265625 20+5+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,100 10.3125x16] baseline: 12.796875 "C" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [31,135] table-cell [0+5+20 14.265625 20+5+0] [0+1+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,135 11.140625x16] baseline: 12.796875 + Box
at [34,138] table-cell [0+5+20 14.265625 20+5+0] [0+1+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,138 11.140625x16] baseline: 12.796875 "D" TextNode <#text> (not painted) - BlockContainer <(anonymous)> at [8,164] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline + BlockContainer <(anonymous)> at [8,170] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x172] + PaintableWithLines (BlockContainer) [0,0 800x178] PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0] - PaintableWithLines (BlockContainer) [8,8 784x156] + PaintableWithLines (BlockContainer) [8,8 784x162] PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0] - PaintableWithLines (TableWrapper(anonymous)) [8,8 60.265625x156] - Paintable (Box) [8,8 60.265625x156] - Paintable (Box) [8,8 60.265625x156] - Paintable (Box) [8,8 60.265625x40] - PaintableWithLines (BlockContainer) [8,48 60.265625x38] - PaintableWithLines (BlockContainer) [8,86 60.265625x38] - PaintableWithLines (BlockContainer) [8,124 60.265625x40] - PaintableWithLines (BlockContainer
) [8,8 60.265625x40] - Paintable (Box
) [8,48 60.265625x38] - Paintable (Box
) [8,86 60.265625x38] - Paintable (Box
) [8,124 60.265625x40] - PaintableWithLines (BlockContainer(anonymous)) [8,164 784x0] + PaintableWithLines (TableWrapper(anonymous)) [8,8 66.265625x162] + Paintable (Box) [8,8 66.265625x162] + Paintable (Box) [11,11 60.265625x156] + Paintable (Box) [11,11 60.265625x40] + PaintableWithLines (BlockContainer) [11,51 60.265625x38] + PaintableWithLines (BlockContainer) [11,89 60.265625x38] + PaintableWithLines (BlockContainer) [11,127 60.265625x40] + PaintableWithLines (BlockContainer
) [11,11 60.265625x40] + Paintable (Box
) [11,51 60.265625x38] + Paintable (Box
) [11,89 60.265625x38] + Paintable (Box
) [11,127 60.265625x40] + PaintableWithLines (BlockContainer(anonymous)) [8,170 784x0] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x172] (z-index: auto) + SC for BlockContainer [0,0 800x178] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-multiple-colgroups.txt b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-multiple-colgroups.txt index 7e9c5cb418b21..af3d04fa014a6 100644 --- a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-multiple-colgroups.txt +++ b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-multiple-colgroups.txt @@ -1,8 +1,8 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 54 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 38 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 113.609375 0+0+670.390625] [0+0+0 38 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 113.609375 0+0+0] [0+0+0 38 0+0+0] [TFC] children: not-inline + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 56 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 40 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 115.609375 0+0+668.390625] [0+0+0 40 0+0+0] [BFC] children: not-inline + Box
at [9,9] table-box [0+1+0 113.609375 0+1+0] [0+1+0 38 0+1+0] [TFC] children: not-inline BlockContainer (not painted) table-column-group children: not-inline BlockContainer (not painted) children: not-inline BlockContainer <(anonymous)> (not painted) children: inline @@ -11,31 +11,31 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children BlockContainer (not painted) children: not-inline BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box at [8,8] table-row-group [0+0+0 113.609375 0+0+0] [0+0+0 38 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 113.609375 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [9,9] table-row-group [0+0+0 113.609375 0+0+0] [0+0+0 38 0+0+0] children: not-inline + Box at [9,9] table-row [0+0+0 113.609375 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer
at [29,19] table-cell [0+1+20 14.265625 20+8+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [29,19 14.265625x16] baseline: 12.796875 + Box
at [30,20] table-cell [0+1+20 14.265625 20+8+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [30,20 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [91.265625,19] table-cell [0+8+20 9.34375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [91.265625,19 9.34375x16] baseline: 12.796875 + BlockContainer at [92.265625,20] table-cell [0+8+20 9.34375 20+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [92.265625,20 9.34375x16] baseline: 12.796875 "B" TextNode <#text> (not painted) - BlockContainer <(anonymous)> at [8,46] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline + BlockContainer <(anonymous)> at [8,48] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x54] - PaintableWithLines (BlockContainer) [8,8 784x38] - PaintableWithLines (TableWrapper(anonymous)) [8,8 113.609375x38] - Paintable (Box) [8,8 113.609375x38] - Paintable (Box) [8,8 113.609375x38] - Paintable (Box) [8,8 113.609375x38] - PaintableWithLines (BlockContainer
) [8,8 59.265625x38] - PaintableWithLines (BlockContainer) [67.265625,8 54.34375x38] - PaintableWithLines (BlockContainer(anonymous)) [8,46 784x0] + PaintableWithLines (BlockContainer) [0,0 800x56] + PaintableWithLines (BlockContainer) [8,8 784x40] + PaintableWithLines (TableWrapper(anonymous)) [8,8 115.609375x40] + Paintable (Box) [8,8 115.609375x40] + Paintable (Box) [9,9 113.609375x38] + Paintable (Box) [9,9 113.609375x38] + PaintableWithLines (BlockContainer
) [9,9 59.265625x38] + PaintableWithLines (BlockContainer) [68.265625,9 54.34375x38] + PaintableWithLines (BlockContainer(anonymous)) [8,48 784x0] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x54] (z-index: auto) + SC for BlockContainer [0,0 800x56] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-row.txt b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-row.txt index f47427a970208..bfa4e80bca5cd 100644 --- a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-row.txt +++ b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-row.txt @@ -1,62 +1,62 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 142 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 126 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 114.8125 0+0+669.1875] [0+0+0 126 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 114.8125 0+0+0] [0+0+0 126 0+0+0] [TFC] children: not-inline - Box at [8,8] table-row-group [0+0+0 114.8125 0+0+0] [0+0+0 126 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 114.8125 0+0+0] [0+0+0 42 0+0+0] children: not-inline - BlockContainer
at [31,21] table-cell [0+5+20 14.265625 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,21 14.265625x16] baseline: 12.796875 + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 148 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 132 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 120.8125 0+0+663.1875] [0+0+0 132 0+0+0] [BFC] children: not-inline + Box at [11,11] table-box [0+5+0 114.8125 0+5+0] [0+5+0 126 0+5+0] [TFC] children: not-inline + Box at [11,11] table-row-group [0+0+0 114.8125 0+0+0] [0+0+0 126 0+0+0] children: not-inline + Box at [11,11] table-row [0+0+0 114.8125 0+0+0] [0+0+0 42 0+0+0] children: not-inline + BlockContainer at [8,50] table-row [0+0+0 114.8125 0+0+0] [0+0+0 42 0+0+0] children: not-inline - BlockContainer at [11,53] table-row [0+0+0 114.8125 0+0+0] [0+0+0 42 0+0+0] children: not-inline + BlockContainer
at [34,24] table-cell [0+5+20 14.265625 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,24 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [87.265625,21] table-cell [0+1+20 12.546875 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.265625,21 9.34375x16] baseline: 12.796875 + BlockContainer at [90.265625,24] table-cell [0+1+20 12.546875 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [90.265625,24 9.34375x16] baseline: 12.796875 "B" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [29,63] table-cell [0+1+20 16.265625 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [29,63 10.3125x16] baseline: 12.796875 + Box
at [32,66] table-cell [0+1+20 16.265625 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [32,66 10.3125x16] baseline: 12.796875 "C" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [87.265625,63] table-cell [0+1+20 14.546875 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.265625,63 11.140625x16] baseline: 12.796875 + BlockContainer at [90.265625,66] table-cell [0+1+20 14.546875 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [90.265625,66 11.140625x16] baseline: 12.796875 "D" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box at [8,92] table-row [0+0+0 114.8125 0+0+0] [0+0+0 42 0+0+0] children: not-inline - BlockContainer at [31,105] table-cell [0+5+20 14.265625 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,105 11.859375x16] baseline: 12.796875 + Box at [11,95] table-row [0+0+0 114.8125 0+0+0] [0+0+0 42 0+0+0] children: not-inline + BlockContainer at [34,108] table-cell [0+5+20 14.265625 20+1+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,108 11.859375x16] baseline: 12.796875 "E" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [87.265625,105] table-cell [0+1+20 12.546875 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.265625,105 12.546875x16] baseline: 12.796875 + BlockContainer at [90.265625,108] table-cell [0+1+20 12.546875 20+5+0] [0+5+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [90.265625,108 12.546875x16] baseline: 12.796875 "F" TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x142] - PaintableWithLines (BlockContainer) [8,8 784x126] - PaintableWithLines (TableWrapper(anonymous)) [8,8 114.8125x126] - Paintable (Box) [8,8 114.8125x126] - Paintable (Box) [8,8 114.8125x126] - Paintable (Box.td-thick-border) [8,8 114.8125x42] - PaintableWithLines (BlockContainer) [8,50 114.8125x42] - PaintableWithLines (BlockContainer.td-thick-border) [8,92 114.8125x42] - PaintableWithLines (BlockContainer
) [8,8 58.265625x42] - PaintableWithLines (BlockContainer) [66.265625,8 56.546875x42] - Paintable (Box
) [8,50 58.265625x42] - PaintableWithLines (BlockContainer) [66.265625,50 56.546875x42] - Paintable (Box
) [8,92 58.265625x42] - PaintableWithLines (BlockContainer) [66.265625,92 56.546875x42] + PaintableWithLines (BlockContainer) [0,0 800x148] + PaintableWithLines (BlockContainer) [8,8 784x132] + PaintableWithLines (TableWrapper(anonymous)) [8,8 120.8125x132] + Paintable (Box) [8,8 120.8125x132] + Paintable (Box) [11,11 114.8125x126] + Paintable (Box.td-thick-border) [11,11 114.8125x42] + PaintableWithLines (BlockContainer) [11,53 114.8125x42] + PaintableWithLines (BlockContainer.td-thick-border) [11,95 114.8125x42] + PaintableWithLines (BlockContainer
) [11,11 58.265625x42] + PaintableWithLines (BlockContainer) [69.265625,11 56.546875x42] + Paintable (Box
) [11,53 58.265625x42] + PaintableWithLines (BlockContainer) [69.265625,53 56.546875x42] + Paintable (Box
) [11,95 58.265625x42] + PaintableWithLines (BlockContainer) [69.265625,95 56.546875x42] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x142] (z-index: auto) + SC for BlockContainer [0,0 800x148] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-rowgroup.txt b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-rowgroup.txt index c6ccd8ed38b41..d821bf2156f77 100644 --- a/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-rowgroup.txt +++ b/Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-rowgroup.txt @@ -1,64 +1,64 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 136 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 120 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 113.40625 0+0+670.59375] [0+0+0 120 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 113.40625 0+0+0] [0+0+0 120 0+0+0] [TFC] children: not-inline - Box at [8,8] table-header-group [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline - BlockContainer
at [29,19] table-cell [0+1+20 16.265625 20+1+0] [0+1+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [29,19 9.59375x16] baseline: 12.796875 + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 140 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 124 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 119.40625 0+0+664.59375] [0+0+0 124 0+0+0] [BFC] children: not-inline + Box at [11,9] table-box [0+5+0 113.40625 0+5+0] [0+1+0 120 0+5+0] [TFC] children: not-inline + Box at [11,9] table-header-group [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline + Box at [11,9] table-row [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline + BlockContainer at [8,48] table-row [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline - BlockContainer at [11,49] table-row [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline + BlockContainer at [8,88] table-row [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline - BlockContainer at [11,89] table-row [0+0+0 113.40625 0+0+0] [0+0+0 40 0+0+0] children: not-inline + BlockContainer
at [32,20] table-cell [0+1+20 16.265625 20+1+0] [0+1+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [32,20 9.59375x16] baseline: 12.796875 "0" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [87.265625,19] table-cell [0+1+20 13.140625 20+1+0] [0+1+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.265625,19 6.34375x16] baseline: 12.796875 + BlockContainer at [90.265625,20] table-cell [0+1+20 13.140625 20+1+0] [0+1+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [90.265625,20 6.34375x16] baseline: 12.796875 "1" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box at [8,48] table-row-group [0+0+0 113.40625 0+0+0] [0+0+0 80 0+0+0] children: not-inline - Box
at [31,61] table-cell [0+5+20 14.265625 20+1+0] [0+5+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,61 14.265625x16] baseline: 12.796875 + Box at [11,49] table-row-group [0+0+0 113.40625 0+0+0] [0+0+0 80 0+0+0] children: not-inline + Box
at [34,62] table-cell [0+5+20 14.265625 20+1+0] [0+5+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,62 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [87.265625,61] table-cell [0+1+20 11.140625 20+5+0] [0+5+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.265625,61 9.34375x16] baseline: 12.796875 + BlockContainer at [90.265625,62] table-cell [0+1+20 11.140625 20+5+0] [0+5+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [90.265625,62 9.34375x16] baseline: 12.796875 "B" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [31,99] table-cell [0+5+20 14.265625 20+1+0] [0+1+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [31,99 10.3125x16] baseline: 12.796875 + Box
at [34,100] table-cell [0+5+20 14.265625 20+1+0] [0+1+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [34,100 10.3125x16] baseline: 12.796875 "C" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [87.265625,99] table-cell [0+1+20 11.140625 20+5+0] [0+1+10 16 10+5+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [87.265625,99 11.140625x16] baseline: 12.796875 + BlockContainer at [90.265625,100] table-cell [0+1+20 11.140625 20+5+0] [0+1+10 16 10+5+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [90.265625,100 11.140625x16] baseline: 12.796875 "D" TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x136] - PaintableWithLines (BlockContainer) [8,8 784x120] - PaintableWithLines (TableWrapper(anonymous)) [8,8 113.40625x120] - Paintable (Box) [8,8 113.40625x120] - Paintable (Box) [8,8 113.40625x40] - Paintable (Box) [8,8 113.40625x40] - PaintableWithLines (BlockContainer.thick-border) [8,48 113.40625x80] - Paintable (Box) [8,48 113.40625x40] - PaintableWithLines (BlockContainer) [8,88 113.40625x40] - PaintableWithLines (BlockContainer
) [8,8 58.265625x40] - PaintableWithLines (BlockContainer) [66.265625,8 55.140625x40] - Paintable (Box
) [8,48 58.265625x40] - PaintableWithLines (BlockContainer) [66.265625,48 55.140625x40] - Paintable (Box
) [8,88 58.265625x40] - PaintableWithLines (BlockContainer) [66.265625,88 55.140625x40] + PaintableWithLines (BlockContainer) [0,0 800x140] + PaintableWithLines (BlockContainer) [8,8 784x124] + PaintableWithLines (TableWrapper(anonymous)) [8,8 119.40625x124] + Paintable (Box) [8,8 119.40625x124] + Paintable (Box) [11,9 113.40625x40] + Paintable (Box) [11,9 113.40625x40] + PaintableWithLines (BlockContainer.thick-border) [11,49 113.40625x80] + Paintable (Box) [11,49 113.40625x40] + PaintableWithLines (BlockContainer) [11,89 113.40625x40] + PaintableWithLines (BlockContainer
) [11,9 58.265625x40] + PaintableWithLines (BlockContainer) [69.265625,9 55.140625x40] + Paintable (Box
) [11,49 58.265625x40] + PaintableWithLines (BlockContainer) [69.265625,49 55.140625x40] + Paintable (Box
) [11,89 58.265625x40] + PaintableWithLines (BlockContainer) [69.265625,89 55.140625x40] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x136] (z-index: auto) + SC for BlockContainer [0,0 800x140] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/clip-spans-to-table-end.txt b/Tests/LibWeb/Layout/expected/table/clip-spans-to-table-end.txt index c118b92a22948..6e5ab42f7fd79 100644 --- a/Tests/LibWeb/Layout/expected/table/clip-spans-to-table-end.txt +++ b/Tests/LibWeb/Layout/expected/table/clip-spans-to-table-end.txt @@ -1,64 +1,64 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 130 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 114 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 93.359375 0+0+690.640625] [0+0+0 114 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 93.359375 0+0+0] [0+0+0 114 0+0+0] [TFC] children: not-inline - Box at [8,8] table-row-group [0+0+0 93.359375 0+0+0] [0+0+0 114 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 93.359375 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer
at [19,19] table-cell [0+1+10 8.453125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [19,19 6.34375x16] baseline: 12.796875 + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 132 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 116 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 95.359375 0+0+688.640625] [0+0+0 116 0+0+0] [BFC] children: not-inline + Box at [9,9] table-box [0+1+0 93.359375 0+1+0] [0+1+0 114 0+1+0] [TFC] children: not-inline + Box at [9,9] table-row-group [0+0+0 93.359375 0+0+0] [0+0+0 114 0+0+0] children: not-inline + Box at [9,9] table-row [0+0+0 93.359375 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [8,46] table-row [0+0+0 93.359375 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [9,47] table-row [0+0+0 93.359375 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer at [8,84] table-row [0+0+0 93.359375 0+0+0] [0+0+0 38 0+0+0] children: not-inline - BlockContainer at [9,85] table-row [0+0+0 93.359375 0+0+0] [0+0+0 38 0+0+0] children: not-inline + BlockContainer
at [20,20] table-cell [0+1+10 8.453125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [20,20 6.34375x16] baseline: 12.796875 "1" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [49.453125,19] table-cell [0+1+10 8.8125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [49.453125,19 8.8125x16] baseline: 12.796875 + BlockContainer at [50.453125,20] table-cell [0+1+10 8.8125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [50.453125,20 8.8125x16] baseline: 12.796875 "2" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [80.265625,19] table-cell [0+1+10 9.09375 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [80.265625,19 9.09375x16] baseline: 12.796875 + BlockContainer at [81.265625,20] table-cell [0+1+10 9.09375 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [81.265625,20 9.09375x16] baseline: 12.796875 "3" TextNode <#text> (not painted) - BlockContainer <(anonymous)> at [101.359375,26.5] table-cell [0+1+0 0 0+0+0] [0+0+18.5 0 18.5+1+0] [BFC] children: not-inline + BlockContainer <(anonymous)> at [102.359375,27.5] table-cell [0+1+0 0 0+0+0] [0+0+18.5 0 18.5+1+0] [BFC] children: not-inline BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [19,57] table-cell [0+1+10 8.453125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [19,57 7.75x16] baseline: 12.796875 + Box
at [20,58] table-cell [0+1+10 8.453125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [20,58 7.75x16] baseline: 12.796875 "4" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [49.453125,76] table-cell [0+1+10 40.90625 10+1+0] [0+1+29 16 29+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 3, rect: [49.453125,76 24.046875x16] baseline: 12.796875 + BlockContainer at [50.453125,77] table-cell [0+1+10 40.90625 10+1+0] [0+1+29 16 29+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 3, rect: [50.453125,77 24.046875x16] baseline: 12.796875 "6-9" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - Box
at [19,95] table-cell [0+1+10 8.453125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [19,95 8.453125x16] baseline: 12.796875 + Box
at [20,96] table-cell [0+1+10 8.453125 10+1+0] [0+1+10 16 10+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [20,96 8.453125x16] baseline: 12.796875 "5" TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x130] - PaintableWithLines (BlockContainer) [8,8 784x114] - PaintableWithLines (TableWrapper(anonymous)) [8,8 93.359375x114] - Paintable (Box) [8,8 93.359375x114] - Paintable (Box) [8,8 93.359375x114] - Paintable (Box) [8,8 93.359375x38] - PaintableWithLines (BlockContainer) [8,46 93.359375x38] - PaintableWithLines (BlockContainer) [8,84 93.359375x38] - PaintableWithLines (BlockContainer
) [8,8 30.453125x38] - PaintableWithLines (BlockContainer) [38.453125,8 30.8125x38] - PaintableWithLines (BlockContainer) [69.265625,8 31.09375x38] - PaintableWithLines (BlockContainer(anonymous)) [100.359375,8 1x38] - Paintable (Box
) [8,46 30.453125x38] - PaintableWithLines (BlockContainer) [38.453125,46 62.90625x76] - Paintable (Box
) [8,84 30.453125x38] + PaintableWithLines (BlockContainer) [0,0 800x132] + PaintableWithLines (BlockContainer) [8,8 784x116] + PaintableWithLines (TableWrapper(anonymous)) [8,8 95.359375x116] + Paintable (Box) [8,8 95.359375x116] + Paintable (Box) [9,9 93.359375x114] + Paintable (Box) [9,9 93.359375x38] + PaintableWithLines (BlockContainer) [9,47 93.359375x38] + PaintableWithLines (BlockContainer) [9,85 93.359375x38] + PaintableWithLines (BlockContainer
) [9,9 30.453125x38] + PaintableWithLines (BlockContainer) [39.453125,9 30.8125x38] + PaintableWithLines (BlockContainer) [70.265625,9 31.09375x38] + PaintableWithLines (BlockContainer(anonymous)) [101.359375,9 1x38] + Paintable (Box
) [9,47 30.453125x38] + PaintableWithLines (BlockContainer) [39.453125,47 62.90625x76] + Paintable (Box
) [9,85 30.453125x38] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x130] (z-index: auto) + SC for BlockContainer [0,0 800x132] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/line-breaking-in-cells.txt b/Tests/LibWeb/Layout/expected/table/line-breaking-in-cells.txt index 5cc3f1d3ff75c..0c04ac260c41d 100644 --- a/Tests/LibWeb/Layout/expected/table/line-breaking-in-cells.txt +++ b/Tests/LibWeb/Layout/expected/table/line-breaking-in-cells.txt @@ -1,41 +1,41 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 52 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 36 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 61 0+0+723] [0+0+0 36 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 61 0+0+0] [0+0+0 36 0+0+0] [TFC] children: not-inline - Box at [8,8] table-row-group [0+0+0 61 0+0+0] [0+0+0 36 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 61 0+0+0] [0+0+0 36 0+0+0] children: not-inline - BlockContainer
at [10,18] table-cell [0+1+1 14.296875 1+1+0] [0+1+9 16 9+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [10,18 14.265625x16] baseline: 12.796875 + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 54 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 38 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 63 0+0+721] [0+0+0 38 0+0+0] [BFC] children: not-inline + Box at [9,9] table-box [0+1+0 61 0+1+0] [0+1+0 36 0+1+0] [TFC] children: not-inline + Box at [9,9] table-row-group [0+0+0 61 0+0+0] [0+0+0 36 0+0+0] children: not-inline + Box at [9,9] table-row [0+0+0 61 0+0+0] [0+0+0 36 0+0+0] children: not-inline + BlockContainer
at [11,19] table-cell [0+1+1 14.296875 1+1+0] [0+1+9 16 9+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [11,19 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [28.296875,10] table-cell [0+1+1 20.40625 1+1+0] [0+1+1 32 1+1+0] [BFC] children: inline - frag 0 from TextNode start: 5, length: 1, rect: [28.296875,10 9.34375x16] baseline: 12.796875 + BlockContainer at [29.296875,11] table-cell [0+1+1 20.40625 1+1+0] [0+1+1 32 1+1+0] [BFC] children: inline + frag 0 from TextNode start: 5, length: 1, rect: [29.296875,11 9.34375x16] baseline: 12.796875 "B" - frag 1 from TextNode start: 0, length: 1, rect: [28.296875,26 10.3125x16] baseline: 12.796875 + frag 1 from TextNode start: 0, length: 1, rect: [29.296875,27 10.3125x16] baseline: 12.796875 "C" TextNode <#text> (not painted) BreakNode
(not painted) TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer
at [52.703125,18] table-cell [0+1+1 14.296875 1+1+0] [0+1+9 16 9+1+0] [BFC] children: inline - frag 0 from TextNode start: 5, length: 1, rect: [52.703125,18 11.140625x16] baseline: 12.796875 + BlockContainer at [53.703125,19] table-cell [0+1+1 14.296875 1+1+0] [0+1+9 16 9+1+0] [BFC] children: inline + frag 0 from TextNode start: 5, length: 1, rect: [53.703125,19 11.140625x16] baseline: 12.796875 "D" TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x52] - PaintableWithLines (BlockContainer) [8,8 784x36] - PaintableWithLines (TableWrapper(anonymous)) [8,8 61x36] - Paintable (Box) [8,8 61x36] - Paintable (Box) [8,8 61x36] - Paintable (Box) [8,8 61x36] - PaintableWithLines (BlockContainer
) [8,8 18.296875x36] - PaintableWithLines (BlockContainer) [26.296875,8 24.40625x36] - PaintableWithLines (BlockContainer) [50.703125,8 18.296875x36] + PaintableWithLines (BlockContainer) [0,0 800x54] + PaintableWithLines (BlockContainer) [8,8 784x38] + PaintableWithLines (TableWrapper(anonymous)) [8,8 63x38] + Paintable (Box) [8,8 63x38] + Paintable (Box) [9,9 61x36] + Paintable (Box) [9,9 61x36] + PaintableWithLines (BlockContainer
) [9,9 18.296875x36] + PaintableWithLines (BlockContainer) [27.296875,9 24.40625x36] + PaintableWithLines (BlockContainer) [51.703125,9 18.296875x36] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x52] (z-index: auto) + SC for BlockContainer [0,0 800x54] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/percentage-width-max-width-columns.txt b/Tests/LibWeb/Layout/expected/table/percentage-width-max-width-columns.txt index de366120d5e59..83ad05565dea7 100644 --- a/Tests/LibWeb/Layout/expected/table/percentage-width-max-width-columns.txt +++ b/Tests/LibWeb/Layout/expected/table/percentage-width-max-width-columns.txt @@ -1,37 +1,37 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 36 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 20 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 119 0+0+665] [0+0+0 20 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 119 0+0+0] [0+0+0 20 0+0+0] [TFC] children: not-inline - Box at [8,8] table-row-group [0+0+0 119 0+0+0] [0+0+0 20 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 119 0+0+0] [0+0+0 20 0+0+0] children: not-inline - BlockContainer
at [10,10] table-cell [0+1+1 31.703125 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 3, rect: [10,10 31.609375x16] baseline: 12.796875 + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 38 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 22 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 121 0+0+663] [0+0+0 22 0+0+0] [BFC] children: not-inline + Box at [9,9] table-box [0+1+0 119 0+1+0] [0+1+0 20 0+1+0] [TFC] children: not-inline + Box at [9,9] table-row-group [0+0+0 119 0+0+0] [0+0+0 20 0+0+0] children: not-inline + Box at [9,9] table-row [0+0+0 119 0+0+0] [0+0+0 20 0+0+0] children: not-inline + BlockContainer
at [11,11] table-cell [0+1+1 31.703125 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 3, rect: [11,11 31.609375x16] baseline: 12.796875 "A B" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [45.703125,10] table-cell [0+1+1 43.59375 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [45.703125,10 10.3125x16] baseline: 12.796875 + BlockContainer at [46.703125,11] table-cell [0+1+1 43.59375 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [46.703125,11 10.3125x16] baseline: 12.796875 "C" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [93.296875,10] table-cell [0+1+1 31.703125 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline - frag 0 from TextNode start: 0, length: 1, rect: [93.296875,10 11.140625x16] baseline: 12.796875 + BlockContainer at [94.296875,11] table-cell [0+1+1 31.703125 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [94.296875,11 11.140625x16] baseline: 12.796875 "D" TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x36] - PaintableWithLines (BlockContainer) [8,8 784x20] - PaintableWithLines (TableWrapper(anonymous)) [8,8 119x20] - Paintable (Box) [8,8 119x20] - Paintable (Box) [8,8 119x20] - Paintable (Box) [8,8 119x20] - PaintableWithLines (BlockContainer
) [8,8 35.703125x20] - PaintableWithLines (BlockContainer) [43.703125,8 47.59375x20] - PaintableWithLines (BlockContainer) [91.296875,8 35.703125x20] + PaintableWithLines (BlockContainer) [0,0 800x38] + PaintableWithLines (BlockContainer) [8,8 784x22] + PaintableWithLines (TableWrapper(anonymous)) [8,8 121x22] + Paintable (Box) [8,8 121x22] + Paintable (Box) [9,9 119x20] + Paintable (Box) [9,9 119x20] + PaintableWithLines (BlockContainer
) [9,9 35.703125x20] + PaintableWithLines (BlockContainer) [44.703125,9 47.59375x20] + PaintableWithLines (BlockContainer) [92.296875,9 35.703125x20] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x36] (z-index: auto) + SC for BlockContainer [0,0 800x38] (z-index: auto) diff --git a/Tests/LibWeb/Layout/expected/table/width-distribution-of-max-width-increment.txt b/Tests/LibWeb/Layout/expected/table/width-distribution-of-max-width-increment.txt index 5a743623a5a6e..2eb13b52f0b7a 100644 --- a/Tests/LibWeb/Layout/expected/table/width-distribution-of-max-width-increment.txt +++ b/Tests/LibWeb/Layout/expected/table/width-distribution-of-max-width-increment.txt @@ -1,37 +1,37 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline - BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 36 0+0+0] [BFC] children: not-inline - BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 20 0+0+8] children: not-inline - TableWrapper <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 20 0+0+0] [BFC] children: not-inline - Box at [8,8] table-box [0+0+0 784 0+0+0] [0+0+0 20 0+0+0] [TFC] children: not-inline - Box at [8,8] table-row-group [0+0+0 784 0+0+0] [0+0+0 20 0+0+0] children: not-inline - Box at [8,8] table-row [0+0+0 784 0+0+0] [0+0+0 20 0+0+0] children: not-inline - BlockContainer
at [10,10] table-cell [0+1+1 216.09375 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline - frag 0 from TextNode start: 17, length: 1, rect: [10,10 14.265625x16] baseline: 12.796875 + BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 38 0+0+0] [BFC] children: not-inline + BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 22 0+0+8] children: not-inline + TableWrapper <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 22 0+0+0] [BFC] children: not-inline + Box at [9,9] table-box [0+1+0 782 0+1+0] [0+1+0 20 0+1+0] [TFC] children: not-inline + Box at [9,9] table-row-group [0+0+0 781.984375 0+0+0] [0+0+0 20 0+0+0] children: not-inline + Box at [9,9] table-row [0+0+0 781.984375 0+0+0] [0+0+0 20 0+0+0] children: not-inline + BlockContainer
at [11,11] table-cell [0+1+1 215.53125 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline + frag 0 from TextNode start: 17, length: 1, rect: [11,11 14.265625x16] baseline: 12.796875 "A" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [230.09375,10] table-cell [0+1+1 156.796875 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline - frag 0 from TextNode start: 17, length: 1, rect: [230.09375,10 9.34375x16] baseline: 12.796875 + BlockContainer at [230.53125,11] table-cell [0+1+1 156.375 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline + frag 0 from TextNode start: 17, length: 1, rect: [230.53125,11 9.34375x16] baseline: 12.796875 "B" TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) children: inline TextNode <#text> (not painted) - BlockContainer at [390.890625,10] table-cell [0+1+1 399.109375 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline - frag 0 from TextNode start: 17, length: 3, rect: [390.890625,10 29.453125x16] baseline: 12.796875 + BlockContainer at [390.90625,11] table-cell [0+1+1 398.078125 1+1+0] [0+1+1 16 1+1+0] [BFC] children: inline + frag 0 from TextNode start: 17, length: 3, rect: [390.90625,11 29.453125x16] baseline: 12.796875 "C D" TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x36] - PaintableWithLines (BlockContainer) [8,8 784x20] - PaintableWithLines (TableWrapper(anonymous)) [8,8 784x20] - Paintable (Box) [8,8 784x20] - Paintable (Box) [8,8 784x20] - Paintable (Box) [8,8 784x20] - PaintableWithLines (BlockContainer
) [8,8 220.09375x20] - PaintableWithLines (BlockContainer) [228.09375,8 160.796875x20] - PaintableWithLines (BlockContainer) [388.890625,8 403.109375x20] + PaintableWithLines (BlockContainer) [0,0 800x38] + PaintableWithLines (BlockContainer) [8,8 784x22] + PaintableWithLines (TableWrapper(anonymous)) [8,8 784x22] + Paintable (Box) [8,8 784x22] + Paintable (Box) [9,9 781.984375x20] + Paintable (Box) [9,9 781.984375x20] + PaintableWithLines (BlockContainer
) [9,9 219.53125x20] + PaintableWithLines (BlockContainer) [228.53125,9 160.375x20] + PaintableWithLines (BlockContainer) [388.90625,9 402.078125x20] SC for Viewport<#document> [0,0 800x600] (z-index: auto) - SC for BlockContainer [0,0 800x36] (z-index: auto) + SC for BlockContainer [0,0 800x38] (z-index: auto) diff --git a/Tests/LibWeb/Ref/expected/scrollable-contains-table-ref.html b/Tests/LibWeb/Ref/expected/scrollable-contains-table-ref.html index a2394f7bbc369..67d303a7c1786 100644 --- a/Tests/LibWeb/Ref/expected/scrollable-contains-table-ref.html +++ b/Tests/LibWeb/Ref/expected/scrollable-contains-table-ref.html @@ -7,12 +7,13 @@ #scrollable-div { width: 300px; height: 300px; - overflow: auto; + overflow: hidden; border: 1px solid #000; } table { width: 100%; border-collapse: collapse; + margin-top: -100px; } th, td { @@ -27,7 +28,21 @@
+ + + + + + + + + + + + + + diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html index f75cb9f14f47d..e5966b340f8fd 100644 --- a/Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-joint-widths-ref.html @@ -7,15 +7,15 @@ position: absolute; } -
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html b/Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html index f16bcc1895728..d160e23e78954 100644 --- a/Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html +++ b/Tests/LibWeb/Ref/expected/table-collapsed-borders-tie-precedence-ref.html @@ -10,4 +10,4 @@
-
+
TH 1TH 2TH 3TH 4
Row 1, Cell 1Row 1, Cell 2Row 1, Cell 3Row 1, Cell 4
Row 2, Cell 1 Row 2, Cell 2