mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-10 01:59:31 +00:00
LibWeb: Fix grid placement with named lines
This commit is contained in:
parent
6fc9de7aab
commit
852e8ff12f
Notes:
github-actions[bot]
2025-04-05 19:31:34 +00:00
Author: https://github.com/Schottkyc137
Commit: 852e8ff12f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3907
Reviewed-by: https://github.com/kalenikaliaksandr ✅
8 changed files with 277 additions and 12 deletions
|
@ -316,9 +316,9 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
||||||
result.end = m_occupation_grid.column_count() + result.end + 2;
|
result.end = m_occupation_grid.column_count() + result.end + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (placement_start.has_line_number() && placement_end.is_span())
|
if (placement_end.is_span())
|
||||||
result.span = placement_end.span();
|
result.span = placement_end.span();
|
||||||
if (placement_end.has_line_number() && placement_start.is_span()) {
|
if (placement_start.is_span()) {
|
||||||
result.span = placement_start.span();
|
result.span = placement_start.span();
|
||||||
result.start = result.end - result.span;
|
result.start = result.end - result.span;
|
||||||
// FIXME: Remove me once have implemented spans overflowing into negative indexes, e.g., grid-row: span 2 / 1
|
// FIXME: Remove me once have implemented spans overflowing into negative indexes, e.g., grid-row: span 2 / 1
|
||||||
|
@ -328,9 +328,10 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
||||||
|
|
||||||
if (placement_end.has_identifier()) {
|
if (placement_end.has_identifier()) {
|
||||||
auto area_end_line_name = MUST(String::formatted("{}-end", placement_end.identifier()));
|
auto area_end_line_name = MUST(String::formatted("{}-end", placement_end.identifier()));
|
||||||
if (auto area_end_line_index = get_line_index_by_line_name(dimension, area_end_line_name); area_end_line_index.has_value()) {
|
auto line_number = placement_end.has_line_number() ? placement_end.line_number() : 1;
|
||||||
|
if (auto area_end_line_index = get_nth_line_index_by_line_name(dimension, area_end_line_name, line_number); area_end_line_index.has_value()) {
|
||||||
result.end = area_end_line_index.value();
|
result.end = area_end_line_index.value();
|
||||||
} else if (auto line_name_index = get_line_index_by_line_name(dimension, placement_end.identifier()); line_name_index.has_value()) {
|
} else if (auto line_name_index = get_nth_line_index_by_line_name(dimension, placement_end.identifier(), line_number); line_name_index.has_value()) {
|
||||||
result.end = line_name_index.value();
|
result.end = line_name_index.value();
|
||||||
} else {
|
} else {
|
||||||
result.end = 1;
|
result.end = 1;
|
||||||
|
@ -340,9 +341,10 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
||||||
|
|
||||||
if (placement_start.has_identifier()) {
|
if (placement_start.has_identifier()) {
|
||||||
auto area_start_line_name = MUST(String::formatted("{}-start", placement_start.identifier()));
|
auto area_start_line_name = MUST(String::formatted("{}-start", placement_start.identifier()));
|
||||||
if (auto area_start_line_index = get_line_index_by_line_name(dimension, area_start_line_name); area_start_line_index.has_value()) {
|
auto line_number = placement_start.has_line_number() ? placement_start.line_number() : 1;
|
||||||
|
if (auto area_start_line_index = get_nth_line_index_by_line_name(dimension, area_start_line_name, line_number); area_start_line_index.has_value()) {
|
||||||
result.start = area_start_line_index.value();
|
result.start = area_start_line_index.value();
|
||||||
} else if (auto line_name_index = get_line_index_by_line_name(dimension, placement_start.identifier()); line_name_index.has_value()) {
|
} else if (auto line_name_index = get_nth_line_index_by_line_name(dimension, placement_start.identifier(), line_number); line_name_index.has_value()) {
|
||||||
result.start = line_name_index.value();
|
result.start = line_name_index.value();
|
||||||
} else {
|
} else {
|
||||||
result.start = 0;
|
result.start = 0;
|
||||||
|
@ -2266,13 +2268,23 @@ AvailableSize GridFormattingContext::get_free_space(AvailableSpace const& availa
|
||||||
return available_size;
|
return available_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<int> GridFormattingContext::get_line_index_by_line_name(GridDimension dimension, String const& line_name)
|
Optional<int> GridFormattingContext::get_nth_line_index_by_line_name(GridDimension dimension, String const& line_name, int nth_line)
|
||||||
{
|
{
|
||||||
auto const& lines = dimension == GridDimension::Column ? m_column_lines : m_row_lines;
|
auto const& lines = dimension == GridDimension::Column ? m_column_lines : m_row_lines;
|
||||||
for (size_t line_index = 0; line_index < lines.size(); line_index++) {
|
size_t line_index = nth_line < 0 ? lines.size() + nth_line : nth_line - 1;
|
||||||
for (auto const& name : lines[line_index].names) {
|
// FIXME: If not enough lines with the name exist, all implicit grid lines on the side
|
||||||
if (name == line_name)
|
// of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.
|
||||||
return static_cast<int>(line_index);
|
// Source: https://drafts.csswg.org/css-grid/#line-placement
|
||||||
|
for (size_t actual_line_index = 0; actual_line_index < lines.size(); actual_line_index++) {
|
||||||
|
for (auto const& name : lines[actual_line_index].names) {
|
||||||
|
if (name == line_name) {
|
||||||
|
// https://drafts.csswg.org/css-grid/#line-placement
|
||||||
|
// Contributes the nth grid line to the grid item’s placement.
|
||||||
|
if (line_index == 0)
|
||||||
|
return static_cast<int>(actual_line_index);
|
||||||
|
else
|
||||||
|
line_index--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -328,7 +328,7 @@ private:
|
||||||
|
|
||||||
AvailableSize get_free_space(AvailableSpace const&, GridDimension) const;
|
AvailableSize get_free_space(AvailableSpace const&, GridDimension) const;
|
||||||
|
|
||||||
Optional<int> get_line_index_by_line_name(GridDimension dimension, String const&);
|
Optional<int> get_nth_line_index_by_line_name(GridDimension dimension, String const&, int line_number);
|
||||||
CSSPixels resolve_definite_track_size(CSS::GridSize const&, AvailableSpace const&);
|
CSSPixels resolve_definite_track_size(CSS::GridSize const&, AvailableSpace const&);
|
||||||
int count_of_repeated_auto_fill_or_fit_tracks(GridDimension, CSS::ExplicitGridTrack const& repeated_track);
|
int count_of_repeated_auto_fill_or_fit_tracks(GridDimension, CSS::ExplicitGridTrack const& repeated_track);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x168 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x152 children: not-inline
|
||||||
|
BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
Box <div.wrapper> at (8,8) content-size 784x152 [GFC] children: not-inline
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.a> at (28,38) content-size 60x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,38 21.40625x26] baseline: 20.1875
|
||||||
|
"A"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.b> at (28,114) content-size 60x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,114 14.015625x26] baseline: 20.1875
|
||||||
|
"B"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x168]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x152]
|
||||||
|
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
||||||
|
PaintableBox (Box<DIV>.wrapper) [8,8 784x152]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.a) [8,18 100x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.b) [8,94 100x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
|
@ -0,0 +1,54 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x234 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x218 children: not-inline
|
||||||
|
BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
Box <div.wrapper> at (8,8) content-size 784x218 [GFC] children: not-inline
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.a> at (28,28) content-size 170x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,28 21.40625x26] baseline: 20.1875
|
||||||
|
"A"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.b> at (248,28) content-size 170x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [248,28 14.015625x26] baseline: 20.1875
|
||||||
|
"B"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.c> at (28,104) content-size 60x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,104 15.46875x26] baseline: 20.1875
|
||||||
|
"C"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.d> at (138,104) content-size 280x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [138,104 16.71875x26] baseline: 20.1875
|
||||||
|
"D"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.e> at (28,180) content-size 390x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,180 17.796875x26] baseline: 20.1875
|
||||||
|
"E"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x234]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x218]
|
||||||
|
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
||||||
|
PaintableBox (Box<DIV>.wrapper) [8,8 784x218]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.a) [8,8 210x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.b) [228,8 210x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.c) [8,84 100x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.d) [118,84 320x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.e) [8,160 430x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
54
Tests/LibWeb/Layout/expected/grid/line-based-with-repeat.txt
Normal file
54
Tests/LibWeb/Layout/expected/grid/line-based-with-repeat.txt
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x234 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x218 children: not-inline
|
||||||
|
BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
Box <div.wrapper> at (8,8) content-size 784x218 [GFC] children: not-inline
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.a> at (28,28) content-size 170x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,28 21.40625x26] baseline: 20.1875
|
||||||
|
"A"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.b> at (248,28) content-size 170x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [248,28 14.015625x26] baseline: 20.1875
|
||||||
|
"B"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.c> at (28,104) content-size 60x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,104 15.46875x26] baseline: 20.1875
|
||||||
|
"C"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.d> at (138,104) content-size 280x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [138,104 16.71875x26] baseline: 20.1875
|
||||||
|
"D"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <div.box.e> at (28,180) content-size 390x26 [BFC] children: inline
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [28,180 17.796875x26] baseline: 20.1875
|
||||||
|
"E"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||||
|
TextNode <#text>
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x234]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x218]
|
||||||
|
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
||||||
|
PaintableBox (Box<DIV>.wrapper) [8,8 784x218]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.a) [8,8 210x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.b) [228,8 210x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.c) [8,84 100x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.d) [118,84 320x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<DIV>.box.e) [8,160 430x66]
|
||||||
|
TextPaintable (TextNode<#text>)
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
.wrapper {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 10px;
|
||||||
|
grid-template-columns: [col] 100px [col] 100px [col] 100px [col] 100px;
|
||||||
|
grid-template-rows: [row] auto [row] auto [row];
|
||||||
|
background-color: #fff;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
background-color: #444;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 150%;
|
||||||
|
}
|
||||||
|
.a {
|
||||||
|
grid-row: row -2 ;
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
grid-row: row -1 ;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="box a">A</div>
|
||||||
|
<div class="box b">B</div>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
.wrapper {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 10px;
|
||||||
|
grid-template-columns: [col] 100px [col] 100px [col] 100px [col] 100px;
|
||||||
|
grid-template-rows: [row] auto [row] auto [row];
|
||||||
|
background-color: #fff;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
background-color: #444;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 150%;
|
||||||
|
}
|
||||||
|
.a {
|
||||||
|
grid-column: col / span 2;
|
||||||
|
grid-row: row ;
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
grid-column: col 3 / span 2 ;
|
||||||
|
grid-row: row ;
|
||||||
|
}
|
||||||
|
.c {
|
||||||
|
grid-column: col ;
|
||||||
|
grid-row: row 2 ;
|
||||||
|
}
|
||||||
|
.d {
|
||||||
|
grid-column: col 2 / span 3 ;
|
||||||
|
grid-row: row 2 ;
|
||||||
|
}
|
||||||
|
.e {
|
||||||
|
grid-column: col / span 4;
|
||||||
|
grid-row: row 3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="box a">A</div>
|
||||||
|
<div class="box b">B</div>
|
||||||
|
<div class="box c">C</div>
|
||||||
|
<div class="box d">D</div>
|
||||||
|
<div class="box e">E</div>
|
44
Tests/LibWeb/Layout/input/grid/line-based-with-repeat.html
Normal file
44
Tests/LibWeb/Layout/input/grid/line-based-with-repeat.html
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
.wrapper {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 10px;
|
||||||
|
grid-template-columns: repeat(4, [col] 100px) ;
|
||||||
|
grid-template-rows: repeat(3, [row] auto);
|
||||||
|
background-color: #fff;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
background-color: #444;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 150%;
|
||||||
|
}
|
||||||
|
.a {
|
||||||
|
grid-column: col / span 2;
|
||||||
|
grid-row: row ;
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
grid-column: col 3 / span 2 ;
|
||||||
|
grid-row: row ;
|
||||||
|
}
|
||||||
|
.c {
|
||||||
|
grid-column: col ;
|
||||||
|
grid-row: row 2 ;
|
||||||
|
}
|
||||||
|
.d {
|
||||||
|
grid-column: col 2 / span 3 ;
|
||||||
|
grid-row: row 2 ;
|
||||||
|
}
|
||||||
|
.e {
|
||||||
|
grid-column: col / span 4;
|
||||||
|
grid-row: row 3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="box a">A</div>
|
||||||
|
<div class="box b">B</div>
|
||||||
|
<div class="box c">C</div>
|
||||||
|
<div class="box d">D</div>
|
||||||
|
<div class="box e">E</div>
|
Loading…
Add table
Add a link
Reference in a new issue