LibWeb: Support "order" property for items in GridFormattingContext

Closes https://github.com/SerenityOS/serenity/issues/20434
This commit is contained in:
Aliaksandr Kalenik 2023-08-09 15:04:48 +02:00 committed by Andreas Kling
parent 0a4b869233
commit 6354f950fd
Notes: sideshowbarker 2024-07-17 04:57:23 +09:00
3 changed files with 129 additions and 38 deletions

View File

@ -0,0 +1,41 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (1,1) content-size 798x600 [BFC] children: not-inline
BlockContainer <body> at (10,10) content-size 780x104 children: not-inline
Box <div.grid-container> at (11,11) content-size 778x102 [GFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item.item-1> at (271.328125,12) content-size 100x100 [BFC] children: inline
line 0 width: 7.9375, height: 21.84375, bottom: 21.84375, baseline: 16.921875
frag 0 from TextNode start: 0, length: 1, rect: [271.328125,12 7.9375x21.84375]
"1"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item.item-2> at (530.65625,12) content-size 100x100 [BFC] children: inline
line 0 width: 11.015625, height: 21.84375, bottom: 21.84375, baseline: 16.921875
frag 0 from TextNode start: 0, length: 1, rect: [530.65625,12 11.015625x21.84375]
"2"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item.item-3> at (12,12) content-size 100x100 [BFC] children: inline
line 0 width: 11.375, height: 21.84375, bottom: 21.84375, baseline: 16.921875
frag 0 from TextNode start: 0, length: 1, rect: [12,12 11.375x21.84375]
"3"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <(anonymous)> at (10,114) content-size 780x0 children: inline
TextNode <#text>
PaintableWithLines (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x602]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x602]
PaintableWithLines (BlockContainer<BODY>) [9,9 782x106]
PaintableBox (Box<DIV>.grid-container) [10,10 780x104]
PaintableWithLines (BlockContainer<DIV>.grid-item.item-1) [270.328125,11 102x102]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item.item-2) [529.65625,11 102x102]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item.item-3) [11,11 102x102]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [10,114 780x0]

View File

@ -0,0 +1,33 @@
<style>
* {
border: 1px solid black;
}
.grid-container {
display: grid;
grid-template-columns: repeat(3, auto);
}
.grid-item {
width: 100px;
height: 100px;
font-size: 20px;
}
.item-1 {
order: 2;
}
.item-2 {
order: 3;
}
.item-3 {
order: 1;
}
</style>
<div class="grid-container">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
</div>

View File

@ -1314,7 +1314,7 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
// flex items), which are then assigned to predefined areas in the grid. They can be explicitly
// placed using coordinates through the grid-placement properties or implicitly placed into
// empty areas using auto-placement.
Vector<JS::NonnullGCPtr<Box const>> boxes_to_place;
HashMap<int, Vector<JS::NonnullGCPtr<Box const>>> order_item_bucket;
grid_container().for_each_child_of_type<Box>([&](Box& child_box) {
if (can_skip_is_anonymous_text_run(child_box))
return IterationDecision::Continue;
@ -1322,7 +1322,9 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
if (child_box.is_out_of_flow(*this))
return IterationDecision::Continue;
boxes_to_place.append(child_box);
auto& order_bucket = order_item_bucket.ensure(child_box.computed_values().order());
order_bucket.append(child_box);
return IterationDecision::Continue;
});
@ -1333,28 +1335,37 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
// https://drafts.csswg.org/css-grid/#auto-placement-algo
// 8.5. Grid Item Placement Algorithm
auto keys = order_item_bucket.keys();
quick_sort(keys, [](auto& a, auto& b) { return a < b; });
// FIXME: 0. Generate anonymous grid items
// 1. Position anything that's not auto-positioned.
for (size_t i = 0; i < boxes_to_place.size(); i++) {
auto const& child_box = boxes_to_place[i];
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end())
|| is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
continue;
place_item_with_row_and_column_position(child_box);
boxes_to_place.remove(i);
i--;
for (auto key : keys) {
auto& boxes_to_place = order_item_bucket.get(key).value();
for (size_t i = 0; i < boxes_to_place.size(); i++) {
auto const& child_box = boxes_to_place[i];
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end())
|| is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
continue;
place_item_with_row_and_column_position(child_box);
boxes_to_place.remove(i);
i--;
}
}
// 2. Process the items locked to a given row.
// FIXME: Do "dense" packing
for (size_t i = 0; i < boxes_to_place.size(); i++) {
auto const& child_box = boxes_to_place[i];
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end()))
continue;
place_item_with_row_position(child_box);
boxes_to_place.remove(i);
i--;
for (auto key : keys) {
auto& boxes_to_place = order_item_bucket.get(key).value();
for (size_t i = 0; i < boxes_to_place.size(); i++) {
auto const& child_box = boxes_to_place[i];
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end()))
continue;
place_item_with_row_position(child_box);
boxes_to_place.remove(i);
i--;
}
}
// 3. Determine the columns in the implicit grid.
@ -1373,15 +1384,18 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
// 3.3. If the largest column span among all the items without a definite column position is larger
// than the width of the implicit grid, add columns to the end of the implicit grid to accommodate
// that column span.
for (auto const& child_box : boxes_to_place) {
int column_span = 1;
if (child_box->computed_values().grid_column_start().is_span())
column_span = child_box->computed_values().grid_column_start().raw_value();
else if (child_box->computed_values().grid_column_end().is_span())
column_span = child_box->computed_values().grid_column_end().raw_value();
for (auto key : keys) {
auto& boxes_to_place = order_item_bucket.get(key).value();
for (auto const& child_box : boxes_to_place) {
int column_span = 1;
if (child_box->computed_values().grid_column_start().is_span())
column_span = child_box->computed_values().grid_column_start().raw_value();
else if (child_box->computed_values().grid_column_end().is_span())
column_span = child_box->computed_values().grid_column_end().raw_value();
if (column_span - 1 > m_occupation_grid.max_column_index())
m_occupation_grid.set_max_column_index(column_span - 1);
if (column_span - 1 > m_occupation_grid.max_column_index())
m_occupation_grid.set_max_column_index(column_span - 1);
}
}
// 4. Position the remaining grid items.
@ -1389,23 +1403,26 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
// order:
auto auto_placement_cursor_x = 0;
auto auto_placement_cursor_y = 0;
for (size_t i = 0; i < boxes_to_place.size(); i++) {
auto const& child_box = boxes_to_place[i];
// 4.1. For sparse packing:
// FIXME: no distinction made. See #4.2
for (auto key : keys) {
auto& boxes_to_place = order_item_bucket.get(key).value();
for (size_t i = 0; i < boxes_to_place.size(); i++) {
auto const& child_box = boxes_to_place[i];
// 4.1. For sparse packing:
// FIXME: no distinction made. See #4.2
// 4.1.1. If the item has a definite column position:
if (!is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
place_item_with_column_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
// 4.1.1. If the item has a definite column position:
if (!is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
place_item_with_column_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
// 4.1.2. If the item has an automatic grid position in both axes:
else
place_item_with_no_declared_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
// 4.1.2. If the item has an automatic grid position in both axes:
else
place_item_with_no_declared_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
boxes_to_place.remove(i);
i--;
boxes_to_place.remove(i);
i--;
// FIXME: 4.2. For dense packing:
// FIXME: 4.2. For dense packing:
}
}
// NOTE: When final implicit grid sizes are known, we can offset their positions so leftmost grid track has 0 index.