From 122d847720ffac5e554963245a2c4e36352bd6e3 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sun, 22 Oct 2023 18:48:35 +0200 Subject: [PATCH] LibWeb: Fix building of areas spanning multiple rows in GFC Rewrites the grid area building to accurately identify areas that span multiple rows. Also now we can recognize invalid areas but do not handle them yet. --- .../Layout/expected/grid/template-areas-1.txt | 23 +++++++++ .../Layout/expected/grid/template-areas-2.txt | 23 +++++++++ .../Layout/expected/grid/template-areas-3.txt | 44 ++++++++++++++++ .../Layout/input/grid/template-areas-1.html | 22 ++++++++ .../Layout/input/grid/template-areas-2.html | 22 ++++++++ .../Layout/input/grid/template-areas-3.html | 33 ++++++++++++ .../LibWeb/Layout/GridFormattingContext.cpp | 50 ++++++++++--------- .../LibWeb/Layout/GridFormattingContext.h | 1 + 8 files changed, 194 insertions(+), 24 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/grid/template-areas-1.txt create mode 100644 Tests/LibWeb/Layout/expected/grid/template-areas-2.txt create mode 100644 Tests/LibWeb/Layout/expected/grid/template-areas-3.txt create mode 100644 Tests/LibWeb/Layout/input/grid/template-areas-1.html create mode 100644 Tests/LibWeb/Layout/input/grid/template-areas-2.html create mode 100644 Tests/LibWeb/Layout/input/grid/template-areas-3.html diff --git a/Tests/LibWeb/Layout/expected/grid/template-areas-1.txt b/Tests/LibWeb/Layout/expected/grid/template-areas-1.txt new file mode 100644 index 0000000000..fa1e19f2f2 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/template-areas-1.txt @@ -0,0 +1,23 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x320 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x302 children: not-inline + Box at (11,11) content-size 778x300 [GFC] children: not-inline + BlockContainer at (12,12) content-size 298x198 [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: [12,12 9.34375x17.46875] + "a" + TextNode <#text> + BlockContainer at (12,212) content-size 298x98 [BFC] children: inline + line 0 width: 9.46875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [12,212 9.46875x17.46875] + "b" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x322] + PaintableWithLines (BlockContainer) [9,9 782x304] + PaintableBox (Box
.grid) [10,10 780x302] + PaintableWithLines (BlockContainer
.a) [11,11 300x200] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.b) [11,211 300x100] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/template-areas-2.txt b/Tests/LibWeb/Layout/expected/grid/template-areas-2.txt new file mode 100644 index 0000000000..0762a2cb2c --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/template-areas-2.txt @@ -0,0 +1,23 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x320 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x302 children: not-inline + Box at (11,11) content-size 778x300 [GFC] children: not-inline + BlockContainer at (12,12) content-size 198x298 [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: [12,12 9.34375x17.46875] + "a" + TextNode <#text> + BlockContainer at (212,12) content-size 98x298 [BFC] children: inline + line 0 width: 9.46875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [212,12 9.46875x17.46875] + "b" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x322] + PaintableWithLines (BlockContainer) [9,9 782x304] + PaintableBox (Box
.grid) [10,10 780x302] + PaintableWithLines (BlockContainer
.a) [11,11 200x300] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.b) [211,11 100x300] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/template-areas-3.txt b/Tests/LibWeb/Layout/expected/grid/template-areas-3.txt new file mode 100644 index 0000000000..23cd14b7f0 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/template-areas-3.txt @@ -0,0 +1,44 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x692 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x674 children: not-inline + Box at (11,11) content-size 778x672 [GFC] children: not-inline + BlockContainer at (12,12) content-size 775.984375x334 [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: [12,12 9.34375x17.46875] + "a" + TextNode <#text> + BlockContainer at (12,348) content-size 257.328125x334 [BFC] children: inline + line 0 width: 9.46875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [12,348 9.46875x17.46875] + "b" + TextNode <#text> + BlockContainer at (271.328125,348) content-size 257.328125x334 [BFC] children: inline + line 0 width: 8.890625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [271.328125,348 8.890625x17.46875] + "c" + TextNode <#text> + BlockContainer at (530.65625,348) content-size 257.328125x166 [BFC] children: inline + line 0 width: 7.859375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [530.65625,348 7.859375x17.46875] + "d" + TextNode <#text> + BlockContainer at (530.65625,516) content-size 257.328125x166 [BFC] children: inline + line 0 width: 8.71875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [530.65625,516 8.71875x17.46875] + "e" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x694] + PaintableWithLines (BlockContainer) [0,0 800x694] + PaintableWithLines (BlockContainer) [9,9 782x676] + PaintableBox (Box
.grid) [10,10 780x674] + PaintableWithLines (BlockContainer
.a) [11,11 777.984375x336] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.b) [11,347 259.328125x336] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.c) [270.328125,347 259.328125x336] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.d) [529.65625,347 259.328125x168] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.e) [529.65625,515 259.328125x168] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/input/grid/template-areas-1.html b/Tests/LibWeb/Layout/input/grid/template-areas-1.html new file mode 100644 index 0000000000..5c99a7336c --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/template-areas-1.html @@ -0,0 +1,22 @@ +
a
b
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/template-areas-2.html b/Tests/LibWeb/Layout/input/grid/template-areas-2.html new file mode 100644 index 0000000000..dcc0aafbb8 --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/template-areas-2.html @@ -0,0 +1,22 @@ +
a
b
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/template-areas-3.html b/Tests/LibWeb/Layout/input/grid/template-areas-3.html new file mode 100644 index 0000000000..8d1e81e6e3 --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/template-areas-3.html @@ -0,0 +1,33 @@ +
a
b
c
d
e
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 9da529b99c..bd8d940c49 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -1323,33 +1323,35 @@ void GridFormattingContext::build_grid_areas() // https://www.w3.org/TR/css-grid-2/#grid-template-areas-property // If a named grid area spans multiple grid cells, but those cells do not form a single // filled-in rectangle, the declaration is invalid. - for (size_t y = 0; y < grid_container().computed_values().grid_template_areas().size(); y++) { - for (size_t x = 0; x < grid_container().computed_values().grid_template_areas()[y].size(); x++) { - auto grid_area_name = grid_container().computed_values().grid_template_areas()[y][x]; - auto maybe_grid_area = m_grid_areas.get(grid_area_name); - if (!maybe_grid_area.has_value()) { - m_grid_areas.set(grid_area_name, { grid_area_name, y, y + 1, x, x + 1 }); - } else { - auto& grid_area = maybe_grid_area.value(); - if (grid_area.row_start == y) { - if (grid_area.column_end == x) - grid_area.column_end = grid_area.column_end + 1; - else - return; - } else { - if (grid_area.row_end == y) { - if (grid_area.column_start != x) - return; - grid_area.row_end = grid_area.row_end + 1; - } else if (grid_area.row_end == y + 1) { - if (grid_area.column_end < x || grid_area.column_end > x + 1) - return; - } else { - return; - } + auto const& rows = grid_container().computed_values().grid_template_areas(); + + auto find_area_rectangle = [&](size_t x_start, size_t y_start, String const& name) { + bool invalid = false; + size_t x_end = x_start; + size_t y_end = y_start; + while (x_end < rows[y_start].size() && rows[y_start][x_end] == name) + x_end++; + while (y_end < rows.size() && rows[y_end][x_start] == name) + y_end++; + for (size_t y = y_start; y < y_end; y++) { + for (size_t x = x_start; x < x_end; x++) { + if (rows[y][x] != name) { + // If a named grid area spans multiple grid cells, but those cells do not form a single filled-in rectangle, the declaration is invalid. + invalid = true; + break; } } } + m_grid_areas.set(name, { name, y_start, y_end, x_start, x_end, invalid }); + }; + + for (size_t y = 0; y < rows.size(); y++) { + for (size_t x = 0; x < rows[y].size(); x++) { + auto name = rows[y][x]; + if (auto grid_area = m_grid_areas.get(name); grid_area.has_value()) + continue; + find_area_rectangle(x, y, name); + } } } diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index bf57e4ca03..3b67325e3d 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -142,6 +142,7 @@ private: size_t row_end { 1 }; size_t column_start { 0 }; size_t column_end { 1 }; + bool invalid { false }; /* FIXME: Ignore ignore invalid areas during layout */ }; HashMap m_grid_areas;