mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-26 19:32:06 -05:00
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.
This commit is contained in:
parent
8eab44896a
commit
122d847720
8 changed files with 194 additions and 24 deletions
23
Tests/LibWeb/Layout/expected/grid/template-areas-1.txt
Normal file
23
Tests/LibWeb/Layout/expected/grid/template-areas-1.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (1,1) content-size 798x320 [BFC] children: not-inline
|
||||
BlockContainer <body> at (10,10) content-size 780x302 children: not-inline
|
||||
Box <div.grid> at (11,11) content-size 778x300 [GFC] children: not-inline
|
||||
BlockContainer <div.a> 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 <div.b> 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<HTML>) [0,0 800x322]
|
||||
PaintableWithLines (BlockContainer<BODY>) [9,9 782x304]
|
||||
PaintableBox (Box<DIV>.grid) [10,10 780x302]
|
||||
PaintableWithLines (BlockContainer<DIV>.a) [11,11 300x200]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.b) [11,211 300x100]
|
||||
TextPaintable (TextNode<#text>)
|
23
Tests/LibWeb/Layout/expected/grid/template-areas-2.txt
Normal file
23
Tests/LibWeb/Layout/expected/grid/template-areas-2.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (1,1) content-size 798x320 [BFC] children: not-inline
|
||||
BlockContainer <body> at (10,10) content-size 780x302 children: not-inline
|
||||
Box <div.grid> at (11,11) content-size 778x300 [GFC] children: not-inline
|
||||
BlockContainer <div.a> 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 <div.b> 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<HTML>) [0,0 800x322]
|
||||
PaintableWithLines (BlockContainer<BODY>) [9,9 782x304]
|
||||
PaintableBox (Box<DIV>.grid) [10,10 780x302]
|
||||
PaintableWithLines (BlockContainer<DIV>.a) [11,11 200x300]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.b) [211,11 100x300]
|
||||
TextPaintable (TextNode<#text>)
|
44
Tests/LibWeb/Layout/expected/grid/template-areas-3.txt
Normal file
44
Tests/LibWeb/Layout/expected/grid/template-areas-3.txt
Normal file
|
@ -0,0 +1,44 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (1,1) content-size 798x692 [BFC] children: not-inline
|
||||
BlockContainer <body> at (10,10) content-size 780x674 children: not-inline
|
||||
Box <div.grid> at (11,11) content-size 778x672 [GFC] children: not-inline
|
||||
BlockContainer <div.a> 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 <div.b> 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 <div.c> 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 <div.d> 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 <div.e> 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<HTML>) [0,0 800x694]
|
||||
PaintableWithLines (BlockContainer<BODY>) [9,9 782x676]
|
||||
PaintableBox (Box<DIV>.grid) [10,10 780x674]
|
||||
PaintableWithLines (BlockContainer<DIV>.a) [11,11 777.984375x336]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.b) [11,347 259.328125x336]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.c) [270.328125,347 259.328125x336]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.d) [529.65625,347 259.328125x168]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.e) [529.65625,515 259.328125x168]
|
||||
TextPaintable (TextNode<#text>)
|
22
Tests/LibWeb/Layout/input/grid/template-areas-1.html
Normal file
22
Tests/LibWeb/Layout/input/grid/template-areas-1.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html><head><style type="text/css">
|
||||
* {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-rows: 100px 100px 100px;
|
||||
grid-template-columns: 100px 100px 100px;
|
||||
grid-template-areas: "a a a" "a a a" "b b b";
|
||||
}
|
||||
|
||||
.a {
|
||||
grid-area: a / a / a / a;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.b {
|
||||
grid-area: b / b / b / b;
|
||||
background-color: blueviolet;
|
||||
}
|
||||
</style></head><body><div class="grid"><div class="a">a</div><div class="b">b</div>
|
22
Tests/LibWeb/Layout/input/grid/template-areas-2.html
Normal file
22
Tests/LibWeb/Layout/input/grid/template-areas-2.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html><head><style type="text/css">
|
||||
* {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-rows: 100px 100px 100px;
|
||||
grid-template-columns: 100px 100px 100px;
|
||||
grid-template-areas: "a a b" "a a b" "a a b";
|
||||
}
|
||||
|
||||
.a {
|
||||
grid-area: a / a / a / a;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.b {
|
||||
grid-area: b / b / b / b;
|
||||
background-color: blueviolet;
|
||||
}
|
||||
</style></head><body><div class="grid"><div class="a">a</div><div class="b">b</div>
|
33
Tests/LibWeb/Layout/input/grid/template-areas-3.html
Normal file
33
Tests/LibWeb/Layout/input/grid/template-areas-3.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html><head><style type="text/css">
|
||||
* {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-rows: repeat(4, 25%);
|
||||
grid-template-columns: repeat(3, 33.3333%);
|
||||
height: 672px;
|
||||
grid-template-areas: "a a a" "a a a" "b c d" "b c e";
|
||||
}
|
||||
|
||||
.a {
|
||||
grid-area: a / a / a / a;
|
||||
}
|
||||
|
||||
.b {
|
||||
grid-area: b / b / b / b;
|
||||
}
|
||||
|
||||
.c {
|
||||
grid-area: c / c / c / c;
|
||||
}
|
||||
|
||||
.d {
|
||||
grid-area: d / d / d / d;
|
||||
}
|
||||
|
||||
.e {
|
||||
grid-area: e / e / e / e;
|
||||
}
|
||||
</style></head><body><div class="grid"><div class="a">a</div><div class="b">b</div><div class="c">c</div><div class="d">d</div><div class="e">e</div></div></body>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String, GridArea> m_grid_areas;
|
||||
|
|
Loading…
Add table
Reference in a new issue