Explorar o código

LibWeb: Adjust border widths for tables using collapsing borders

When using the collapsing border model, cells on either side of the edge
get half the specified width of the border for their box model.
Andi Gallo %!s(int64=2) %!d(string=hai) anos
pai
achega
4c81d39483

+ 18 - 18
Tests/LibWeb/Layout/expected/table/border-conflict-resolution-with-col.txt

@@ -1,63 +1,63 @@
 Viewport <#document> at (0,0) content-size 800x600 children: not-inline
-  BlockContainer <html> at (0,0) content-size 800x181.875 [BFC] children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x177.875 [BFC] children: not-inline
     BlockContainer <(anonymous)> at (0,0) content-size 800x0 children: inline
       TextNode <#text>
-    BlockContainer <body> at (8,8) content-size 784x165.875 children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x161.875 children: not-inline
       BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
         TextNode <#text>
-      TableWrapper <(anonymous)> at (8,8) content-size 64.265625x165.875 [BFC] children: not-inline
-        Box <table> at (8,8) content-size 64.265625x165.875 table-box [TFC] children: not-inline
+      TableWrapper <(anonymous)> at (8,8) content-size 60.265625x161.875 [BFC] children: not-inline
+        Box <table> at (8,8) content-size 60.265625x161.875 table-box [TFC] children: not-inline
           BlockContainer <(anonymous)> (not painted) children: inline
             TextNode <#text>
           BlockContainer <colgroup> (not painted) table-column-group children: not-inline
             BlockContainer <col> (not painted) children: not-inline
           BlockContainer <(anonymous)> (not painted) children: inline
             TextNode <#text>
-          Box <tbody> at (8,8) content-size 64.265625x165.875 table-row-group children: not-inline
+          Box <tbody> at (8,8) content-size 60.265625x161.875 table-row-group children: not-inline
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            Box <tr> at (8,8) content-size 64.265625x43.46875 table-row children: not-inline
+            Box <tr> at (8,8) content-size 60.265625x41.468749 table-row children: not-inline
               BlockContainer <(anonymous)> (not painted) children: inline
                 TextNode <#text>
-              BlockContainer <td> at (33,23) content-size 14.265625x17.46875 table-cell [BFC] children: inline
+              BlockContainer <td> at (31,20.999999) content-size 14.265625x17.46875 table-cell [BFC] children: inline
                 line 0 width: 14.265625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                  frag 0 from TextNode start: 0, length: 1, rect: [33,23 14.265625x17.46875]
+                  frag 0 from TextNode start: 0, length: 1, rect: [31,20.999999 14.265625x17.46875]
                     "A"
                 TextNode <#text>
               BlockContainer <(anonymous)> (not painted) children: inline
                 TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            Box <tr> at (8,51.46875) content-size 64.265625x39.46875 table-row children: not-inline
+            Box <tr> at (8,49.468749) content-size 60.265625x39.46875 table-row children: not-inline
               BlockContainer <(anonymous)> (not painted) children: inline
                 TextNode <#text>
-              BlockContainer <td> at (33,62.46875) content-size 14.265625x17.46875 table-cell [BFC] children: inline
+              BlockContainer <td> at (31,60.468749) content-size 14.265625x17.46875 table-cell [BFC] children: inline
                 line 0 width: 9.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                  frag 0 from TextNode start: 0, length: 1, rect: [33,62.46875 9.34375x17.46875]
+                  frag 0 from TextNode start: 0, length: 1, rect: [31,60.468749 9.34375x17.46875]
                     "B"
                 TextNode <#text>
               BlockContainer <(anonymous)> (not painted) children: inline
                 TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            Box <tr> at (8,90.9375) content-size 64.265625x39.46875 table-row children: not-inline
+            Box <tr> at (8,88.9375) content-size 60.265625x39.46875 table-row children: not-inline
               BlockContainer <(anonymous)> (not painted) children: inline
                 TextNode <#text>
-              BlockContainer <td> at (33,101.9375) content-size 14.265625x17.46875 table-cell [BFC] children: inline
+              BlockContainer <td> at (31,99.9375) content-size 14.265625x17.46875 table-cell [BFC] children: inline
                 line 0 width: 10.3125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                  frag 0 from TextNode start: 0, length: 1, rect: [33,101.9375 10.3125x17.46875]
+                  frag 0 from TextNode start: 0, length: 1, rect: [31,99.9375 10.3125x17.46875]
                     "C"
                 TextNode <#text>
               BlockContainer <(anonymous)> (not painted) children: inline
                 TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            Box <tr> at (8,130.40625) content-size 64.265625x43.46875 table-row children: not-inline
+            Box <tr> at (8,128.40625) content-size 60.265625x41.468749 table-row children: not-inline
               BlockContainer <(anonymous)> (not painted) children: inline
                 TextNode <#text>
-              BlockContainer <td> at (33,141.40625) content-size 14.265625x17.46875 table-cell [BFC] children: inline
+              BlockContainer <td> at (31,139.40625) content-size 14.265625x17.46875 table-cell [BFC] children: inline
                 line 0 width: 11.140625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                  frag 0 from TextNode start: 0, length: 1, rect: [33,141.40625 11.140625x17.46875]
+                  frag 0 from TextNode start: 0, length: 1, rect: [31,139.40625 11.140625x17.46875]
                     "D"
                 TextNode <#text>
               BlockContainer <(anonymous)> (not painted) children: inline
@@ -66,5 +66,5 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
               TextNode <#text>
           BlockContainer <(anonymous)> (not painted) children: inline
             TextNode <#text>
-      BlockContainer <(anonymous)> at (8,173.875) content-size 784x0 children: inline
+      BlockContainer <(anonymous)> at (8,169.875) content-size 784x0 children: inline
         TextNode <#text>

+ 17 - 17
Tests/LibWeb/Layout/expected/table/borders.txt

@@ -1,6 +1,6 @@
 Viewport <#document> at (0,0) content-size 800x600 children: not-inline
   BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
-    BlockContainer <body> at (8,8) content-size 784x285.625 children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x265.625 children: not-inline
       TableWrapper <(anonymous)> at (8,8) content-size 174.296875x74.40625 [BFC] children: not-inline
         Box <table.table-border-black> at (9,9) content-size 172.296875x72.40625 table-box [TFC] children: not-inline
           BlockContainer <(anonymous)> (not painted) children: inline
@@ -195,11 +195,11 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
       BlockContainer <(anonymous)> at (8,201.21875) content-size 784x0 children: inline
         TextNode <#text>
         TextNode <#text>
-      TableWrapper <(anonymous)> at (8,201.21875) content-size 178.296875x92.40625 [BFC] children: not-inline
-        Box <div.table.thick-border-black> at (8,201.21875) content-size 178.296875x92.40625 table-box [TFC] children: not-inline
+      TableWrapper <(anonymous)> at (8,201.21875) content-size 168.296875x72.40625 [BFC] children: not-inline
+        Box <div.table.thick-border-black> at (8,201.21875) content-size 168.296875x72.40625 table-box [TFC] children: not-inline
           BlockContainer <(anonymous)> (not painted) children: inline
             TextNode <#text>
-          Box <div.table-row.thick-border-black> at (8,201.21875) content-size 178.296875x27.46875 table-row children: not-inline
+          Box <div.table-row.thick-border-black> at (8,201.21875) content-size 168.296875x22.46875 table-row children: not-inline
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
             BlockContainer <div.table-cell.thick-border-black> at (8,201.21875) content-size 82.015625x17.46875 table-cell [BFC] children: inline
@@ -209,52 +209,52 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
               TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            BlockContainer <div.table-cell.thick-border-black> at (110.015625,201.21875) content-size 76.28125x17.46875 table-cell [BFC] children: inline
+            BlockContainer <div.table-cell.thick-border-black> at (100.015625,201.21875) content-size 76.28125x17.46875 table-cell [BFC] children: inline
               line 0 width: 76.28125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                frag 0 from TextNode start: 0, length: 8, rect: [110.015625,201.21875 76.28125x17.46875]
+                frag 0 from TextNode start: 0, length: 8, rect: [100.015625,201.21875 76.28125x17.46875]
                   "Lastname"
               TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
           BlockContainer <(anonymous)> (not painted) children: inline
             TextNode <#text>
-          Box <div.table-row.thick-border-black> at (8,228.6875) content-size 178.296875x37.46875 table-row children: not-inline
+          Box <div.table-row.thick-border-black> at (8,223.6875) content-size 168.296875x27.46875 table-row children: not-inline
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            BlockContainer <div.table-cell.thick-border-black> at (8,238.6875) content-size 82.015625x17.46875 table-cell [BFC] children: inline
+            BlockContainer <div.table-cell.thick-border-black> at (8,228.6875) content-size 82.015625x17.46875 table-cell [BFC] children: inline
               line 0 width: 44.65625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                frag 0 from TextNode start: 0, length: 5, rect: [8,238.6875 44.65625x17.46875]
+                frag 0 from TextNode start: 0, length: 5, rect: [8,228.6875 44.65625x17.46875]
                   "Peter"
               TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            BlockContainer <div.table-cell.thick-border-black> at (110.015625,238.6875) content-size 76.28125x17.46875 table-cell [BFC] children: inline
+            BlockContainer <div.table-cell.thick-border-black> at (100.015625,228.6875) content-size 76.28125x17.46875 table-cell [BFC] children: inline
               line 0 width: 53.671875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                frag 0 from TextNode start: 0, length: 7, rect: [110.015625,238.6875 53.671875x17.46875]
+                frag 0 from TextNode start: 0, length: 7, rect: [100.015625,228.6875 53.671875x17.46875]
                   "Griffin"
               TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
           BlockContainer <(anonymous)> (not painted) children: inline
             TextNode <#text>
-          Box <div.table-row.thick-border-black> at (8,266.15625) content-size 178.296875x27.46875 table-row children: not-inline
+          Box <div.table-row.thick-border-black> at (8,251.15625) content-size 168.296875x22.46875 table-row children: not-inline
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            BlockContainer <div.table-cell.thick-border-black> at (8,276.15625) content-size 82.015625x17.46875 table-cell [BFC] children: inline
+            BlockContainer <div.table-cell.thick-border-black> at (8,256.15625) content-size 82.015625x17.46875 table-cell [BFC] children: inline
               line 0 width: 35.125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                frag 0 from TextNode start: 0, length: 4, rect: [8,276.15625 35.125x17.46875]
+                frag 0 from TextNode start: 0, length: 4, rect: [8,256.15625 35.125x17.46875]
                   "Lois"
               TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
-            BlockContainer <div.table-cell.thick-border-black> at (110.015625,276.15625) content-size 76.28125x17.46875 table-cell [BFC] children: inline
+            BlockContainer <div.table-cell.thick-border-black> at (100.015625,256.15625) content-size 76.28125x17.46875 table-cell [BFC] children: inline
               line 0 width: 53.671875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
-                frag 0 from TextNode start: 0, length: 7, rect: [110.015625,276.15625 53.671875x17.46875]
+                frag 0 from TextNode start: 0, length: 7, rect: [100.015625,256.15625 53.671875x17.46875]
                   "Griffin"
               TextNode <#text>
             BlockContainer <(anonymous)> (not painted) children: inline
               TextNode <#text>
           BlockContainer <(anonymous)> (not painted) children: inline
             TextNode <#text>
-      BlockContainer <(anonymous)> at (8,293.625) content-size 784x0 children: inline
+      BlockContainer <(anonymous)> at (8,273.625) content-size 784x0 children: inline
         TextNode <#text>

+ 15 - 8
Userland/Libraries/LibWeb/Layout/LayoutState.h

@@ -98,18 +98,18 @@ struct LayoutState {
 
         Vector<LineBox> line_boxes;
 
-        CSSPixels margin_box_left() const { return margin_left + border_left + padding_left; }
-        CSSPixels margin_box_right() const { return margin_right + border_right + padding_right; }
-        CSSPixels margin_box_top() const { return margin_top + border_top + padding_top; }
-        CSSPixels margin_box_bottom() const { return margin_bottom + border_bottom + padding_bottom; }
+        CSSPixels margin_box_left() const { return margin_left + border_left_collapsed() + padding_left; }
+        CSSPixels margin_box_right() const { return margin_right + border_right_collapsed() + padding_right; }
+        CSSPixels margin_box_top() const { return margin_top + border_top_collapsed() + padding_top; }
+        CSSPixels margin_box_bottom() const { return margin_bottom + border_bottom_collapsed() + padding_bottom; }
 
         CSSPixels margin_box_width() const { return margin_box_left() + content_width() + margin_box_right(); }
         CSSPixels margin_box_height() const { return margin_box_top() + content_height() + margin_box_bottom(); }
 
-        CSSPixels border_box_left() const { return border_left + padding_left; }
-        CSSPixels border_box_right() const { return border_right + padding_right; }
-        CSSPixels border_box_top() const { return border_top + padding_top; }
-        CSSPixels border_box_bottom() const { return border_bottom + padding_bottom; }
+        CSSPixels border_box_left() const { return border_left_collapsed() + padding_left; }
+        CSSPixels border_box_right() const { return border_right_collapsed() + padding_right; }
+        CSSPixels border_box_top() const { return border_top_collapsed() + padding_top; }
+        CSSPixels border_box_bottom() const { return border_bottom_collapsed() + padding_bottom; }
 
         CSSPixels border_box_width() const { return border_box_left() + content_width() + border_box_right(); }
         CSSPixels border_box_height() const { return border_box_top() + content_height() + border_box_bottom(); }
@@ -129,6 +129,13 @@ struct LayoutState {
         AvailableSize available_width_inside() const;
         AvailableSize available_height_inside() const;
 
+        bool use_collapsing_borders_model() const { return m_override_borders_data.has_value(); }
+        // Implement the collapsing border model https://www.w3.org/TR/CSS22/tables.html#collapsing-borders.
+        CSSPixels border_left_collapsed() const { return use_collapsing_borders_model() ? round(border_left / 2) : border_left; }
+        CSSPixels border_right_collapsed() const { return use_collapsing_borders_model() ? round(border_right / 2) : border_right; }
+        CSSPixels border_top_collapsed() const { return use_collapsing_borders_model() ? round(border_top / 2) : border_top; }
+        CSSPixels border_bottom_collapsed() const { return use_collapsing_borders_model() ? round(border_bottom / 2) : border_bottom; }
+
         JS::GCPtr<Layout::NodeWithStyleAndBoxModelMetrics> m_node { nullptr };
 
         CSSPixels m_content_width { 0 };

+ 6 - 5
Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp

@@ -174,11 +174,12 @@ void TableFormattingContext::compute_cell_measures(AvailableSpace const& availab
         CSSPixels padding_right = computed_values.padding().right().to_px(cell.box, containing_block.content_width());
 
         auto const& cell_state = m_state.get(cell.box);
-        auto is_collapse = cell.box->computed_values().border_collapse() == CSS::BorderCollapse::Collapse;
-        CSSPixels border_top = is_collapse ? cell_state.border_top : computed_values.border_top().width;
-        CSSPixels border_bottom = is_collapse ? cell_state.border_bottom : computed_values.border_bottom().width;
-        CSSPixels border_left = is_collapse ? cell_state.border_left : computed_values.border_left().width;
-        CSSPixels border_right = is_collapse ? cell_state.border_right : computed_values.border_right().width;
+        auto use_collapsing_borders_model = cell_state.override_borders_data().has_value();
+        // Implement the collapsing border model https://www.w3.org/TR/CSS22/tables.html#collapsing-borders.
+        CSSPixels border_top = use_collapsing_borders_model ? round(cell_state.border_top / 2) : computed_values.border_top().width;
+        CSSPixels border_bottom = use_collapsing_borders_model ? round(cell_state.border_bottom / 2) : computed_values.border_bottom().width;
+        CSSPixels border_left = use_collapsing_borders_model ? round(cell_state.border_left / 2) : computed_values.border_left().width;
+        CSSPixels border_right = use_collapsing_borders_model ? round(cell_state.border_right / 2) : computed_values.border_right().width;
 
         auto height = computed_values.height().to_px(cell.box, containing_block.content_height());
         auto width = (computed_values.width().is_length() || !table_width_is_auto) ? computed_values.width().to_px(cell.box, containing_block.content_width()) : 0;

+ 11 - 5
Userland/Libraries/LibWeb/Painting/PaintableBox.h

@@ -64,10 +64,16 @@ public:
     {
         auto padded_rect = this->absolute_padding_box_rect();
         CSSPixelRect rect;
-        rect.set_x(padded_rect.x() - box_model().border.left);
-        rect.set_width(padded_rect.width() + box_model().border.left + box_model().border.right);
-        rect.set_y(padded_rect.y() - box_model().border.top);
-        rect.set_height(padded_rect.height() + box_model().border.top + box_model().border.bottom);
+        auto use_collapsing_borders_model = override_borders_data().has_value();
+        // Implement the collapsing border model https://www.w3.org/TR/CSS22/tables.html#collapsing-borders.
+        auto border_top = use_collapsing_borders_model ? round(box_model().border.top / 2) : box_model().border.top;
+        auto border_bottom = use_collapsing_borders_model ? round(box_model().border.bottom / 2) : box_model().border.bottom;
+        auto border_left = use_collapsing_borders_model ? round(box_model().border.left / 2) : box_model().border.left;
+        auto border_right = use_collapsing_borders_model ? round(box_model().border.right / 2) : box_model().border.right;
+        rect.set_x(padded_rect.x() - border_left);
+        rect.set_width(padded_rect.width() + border_left + border_right);
+        rect.set_y(padded_rect.y() - border_top);
+        rect.set_height(padded_rect.height() + border_top + border_bottom);
         return rect;
     }
 
@@ -124,7 +130,7 @@ public:
     bool is_out_of_view(PaintContext&) const;
 
     void set_override_borders_data(BordersData const& override_borders_data) { m_override_borders_data = override_borders_data; }
-    auto const& override_borders_data() const { return m_override_borders_data; }
+    Optional<BordersData> const& override_borders_data() const { return m_override_borders_data; }
 
     struct TableCellCoordinates {
         size_t row_index;