diff --git a/Tests/LibWeb/Layout/expected/grid/placement-10.txt b/Tests/LibWeb/Layout/expected/grid/placement-10.txt new file mode 100644 index 0000000000..dca0802ac6 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/placement-10.txt @@ -0,0 +1,33 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x516 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x500 children: not-inline + Box at (8,8) content-size 500x500 [GFC] children: not-inline + BlockContainer at (8,8) content-size 100x300 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [8,8 6.34375x17] baseline: 13.296875 + "1" + TextNode <#text> + BlockContainer at (108,8) content-size 100x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [108,8 8.8125x17] baseline: 13.296875 + "2" + TextNode <#text> + BlockContainer at (108,108) content-size 100x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [108,108 9.09375x17] baseline: 13.296875 + "3" + TextNode <#text> + BlockContainer at (108,208) content-size 100x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [108,208 7.75x17] baseline: 13.296875 + "4" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x516] + PaintableWithLines (BlockContainer) [8,8 784x500] + PaintableBox (Box
.grid) [8,8 500x500] + PaintableWithLines (BlockContainer
#a) [8,8 100x300] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [108,8 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#c) [108,108 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#d) [108,208 100x100] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/placement-5.txt b/Tests/LibWeb/Layout/expected/grid/placement-5.txt new file mode 100644 index 0000000000..b74c249bc6 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/placement-5.txt @@ -0,0 +1,33 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x220 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x202 children: not-inline + Box at (11,11) content-size 778x200 [GFC] children: not-inline + BlockContainer at (12,12) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [12,12 6.34375x17] baseline: 13.296875 + "1" + TextNode <#text> + BlockContainer at (12,112) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [12,112 8.8125x17] baseline: 13.296875 + "2" + TextNode <#text> + BlockContainer at (112,12) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [112,12 9.09375x17] baseline: 13.296875 + "3" + TextNode <#text> + BlockContainer at (112,112) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [112,112 7.75x17] baseline: 13.296875 + "4" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x222] + PaintableWithLines (BlockContainer) [9,9 782x204] + PaintableBox (Box
.grid) [10,10 780x202] + PaintableWithLines (BlockContainer
#a) [11,11 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [11,111 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#a) [111,11 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [111,111 100x100] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/placement-6.txt b/Tests/LibWeb/Layout/expected/grid/placement-6.txt new file mode 100644 index 0000000000..fe00cba465 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/placement-6.txt @@ -0,0 +1,33 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x220 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x202 children: not-inline + Box at (11,11) content-size 778x200 [GFC] children: not-inline + BlockContainer at (12,12) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [12,12 6.34375x17] baseline: 13.296875 + "1" + TextNode <#text> + BlockContainer at (112,12) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [112,12 8.8125x17] baseline: 13.296875 + "2" + TextNode <#text> + BlockContainer at (12,112) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [12,112 9.09375x17] baseline: 13.296875 + "3" + TextNode <#text> + BlockContainer at (112,112) content-size 98x98 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [112,112 7.75x17] baseline: 13.296875 + "4" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x222] + PaintableWithLines (BlockContainer) [9,9 782x204] + PaintableBox (Box
.grid) [10,10 780x202] + PaintableWithLines (BlockContainer
#a) [11,11 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [111,11 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#a) [11,111 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [111,111 100x100] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/placement-7.txt b/Tests/LibWeb/Layout/expected/grid/placement-7.txt new file mode 100644 index 0000000000..8bc68d82ab --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/placement-7.txt @@ -0,0 +1,33 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x216 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x200 children: not-inline + Box at (8,8) content-size 784x200 [GFC] children: not-inline + BlockContainer at (8,8) content-size 100x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [8,8 6.34375x17] baseline: 13.296875 + "1" + TextNode <#text> + BlockContainer at (108,8) content-size 387.453125x200 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [108,8 8.8125x17] baseline: 13.296875 + "2" + TextNode <#text> + BlockContainer at (495.453125,8) content-size 296.546875x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [495.453125,8 9.09375x17] baseline: 13.296875 + "3" + TextNode <#text> + BlockContainer at (495.453125,108) content-size 296.546875x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [495.453125,108 7.75x17] baseline: 13.296875 + "4" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x216] + PaintableWithLines (BlockContainer) [8,8 784x200] + PaintableBox (Box
.grid) [8,8 784x200] + PaintableWithLines (BlockContainer
#a) [8,8 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [108,8 387.453125x200] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#c) [495.453125,8 296.546875x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#d) [495.453125,108 296.546875x100] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/placement-8.txt b/Tests/LibWeb/Layout/expected/grid/placement-8.txt new file mode 100644 index 0000000000..59e8e2305d --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/placement-8.txt @@ -0,0 +1,33 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x520 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x502 children: not-inline + Box at (11,11) content-size 500x500 [GFC] children: not-inline + BlockContainer at (12,12) content-size 98x105.59375 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [12,12 6.34375x17] baseline: 13.296875 + "1" + TextNode <#text> + BlockContainer at (12,119.59375) content-size 498x282.78125 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [12,119.59375 8.8125x17] baseline: 13.296875 + "2" + TextNode <#text> + BlockContainer at (12,404.375) content-size 98x105.59375 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [12,404.375 9.09375x17] baseline: 13.296875 + "3" + TextNode <#text> + BlockContainer at (112,404.375) content-size 98x105.59375 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [112,404.375 7.75x17] baseline: 13.296875 + "4" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x522] + PaintableWithLines (BlockContainer) [9,9 782x504] + PaintableBox (Box
.grid) [10,10 502x502] + PaintableWithLines (BlockContainer
#a) [11,11 100x107.59375] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [11,118.59375 500x284.78125] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#c) [11,403.375 100x107.59375] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#d) [111,403.375 100x107.59375] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/placement-9.txt b/Tests/LibWeb/Layout/expected/grid/placement-9.txt new file mode 100644 index 0000000000..dca0802ac6 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/placement-9.txt @@ -0,0 +1,33 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x516 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x500 children: not-inline + Box at (8,8) content-size 500x500 [GFC] children: not-inline + BlockContainer at (8,8) content-size 100x300 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [8,8 6.34375x17] baseline: 13.296875 + "1" + TextNode <#text> + BlockContainer at (108,8) content-size 100x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [108,8 8.8125x17] baseline: 13.296875 + "2" + TextNode <#text> + BlockContainer at (108,108) content-size 100x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [108,108 9.09375x17] baseline: 13.296875 + "3" + TextNode <#text> + BlockContainer at (108,208) content-size 100x100 [BFC] children: inline + frag 0 from TextNode start: 0, length: 1, rect: [108,208 7.75x17] baseline: 13.296875 + "4" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x516] + PaintableWithLines (BlockContainer) [8,8 784x500] + PaintableBox (Box
.grid) [8,8 500x500] + PaintableWithLines (BlockContainer
#a) [8,8 100x300] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#b) [108,8 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#c) [108,108 100x100] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
#d) [108,208 100x100] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/input/grid/placement-10.html b/Tests/LibWeb/Layout/input/grid/placement-10.html new file mode 100644 index 0000000000..ea9f464e58 --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/placement-10.html @@ -0,0 +1,19 @@ +
1
2
3
4
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/placement-5.html b/Tests/LibWeb/Layout/input/grid/placement-5.html new file mode 100644 index 0000000000..69ee3815de --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/placement-5.html @@ -0,0 +1,12 @@ +
1
2
3
4
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/placement-6.html b/Tests/LibWeb/Layout/input/grid/placement-6.html new file mode 100644 index 0000000000..014b34299d --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/placement-6.html @@ -0,0 +1,12 @@ +
1
2
3
4
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/placement-7.html b/Tests/LibWeb/Layout/input/grid/placement-7.html new file mode 100644 index 0000000000..b0fb6ef7d6 --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/placement-7.html @@ -0,0 +1,17 @@ +
1
2
3
4
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/placement-8.html b/Tests/LibWeb/Layout/input/grid/placement-8.html new file mode 100644 index 0000000000..2affb2c2a1 --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/placement-8.html @@ -0,0 +1,18 @@ +
1
2
3
4
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/placement-9.html b/Tests/LibWeb/Layout/input/grid/placement-9.html new file mode 100644 index 0000000000..86da04fc7b --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/placement-9.html @@ -0,0 +1,19 @@ +
1
2
3
4
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 5f39fa0033..5d1b8b942a 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -558,17 +558,43 @@ void GridFormattingContext::place_item_with_column_position(Box const& child_box .column_span = column_span }); } +FoundUnoccupiedPlace OccupationGrid::find_unoccupied_place(GridDimension dimension, int& column_index, int& row_index, int column_span, int row_span) const +{ + if (dimension == GridDimension::Column) { + while (row_index <= max_row_index()) { + while (column_index <= max_column_index()) { + auto enough_span_for_span = column_index + column_span - 1 <= max_column_index(); + if (enough_span_for_span && !is_occupied(column_index, row_index)) + return FoundUnoccupiedPlace::Yes; + column_index++; + } + row_index++; + column_index = min_column_index(); + } + } else { + while (column_index <= max_column_index()) { + while (row_index <= max_row_index()) { + auto enough_span_for_span = row_index + row_span - 1 <= max_row_index(); + if (enough_span_for_span && !is_occupied(column_index, row_index)) + return FoundUnoccupiedPlace::Yes; + row_index++; + } + column_index++; + row_index = min_row_index(); + } + } + + return FoundUnoccupiedPlace::No; +} + void GridFormattingContext::place_item_with_no_declared_position(Box const& child_box, int& auto_placement_cursor_x, int& auto_placement_cursor_y) { - auto const& grid_row_start = child_box.computed_values().grid_row_start(); - auto const& grid_row_end = child_box.computed_values().grid_row_end(); - auto const& grid_column_start = child_box.computed_values().grid_column_start(); - auto const& grid_column_end = child_box.computed_values().grid_column_end(); + auto const& computed_values = child_box.computed_values(); + auto const& grid_row_start = computed_values.grid_row_start(); + auto const& grid_row_end = computed_values.grid_row_end(); + auto const& grid_column_start = computed_values.grid_column_start(); + auto const& grid_column_end = computed_values.grid_column_end(); - // 4.1.2.1. Increment the column position of the auto-placement cursor until either this item's grid - // area does not overlap any occupied grid cells, or the cursor's column position, plus the item's - // column span, overflow the number of columns in the implicit grid, as determined earlier in this - // algorithm. auto column_start = 0; size_t column_span = 1; if (grid_column_start.is_span()) @@ -581,47 +607,40 @@ void GridFormattingContext::place_item_with_no_declared_position(Box const& chil row_span = grid_row_start.span(); else if (grid_row_end.is_span()) row_span = grid_row_end.span(); - auto found_unoccupied_area = false; auto const& auto_flow = grid_container().computed_values().grid_auto_flow(); + auto dimension = auto_flow.row ? GridDimension::Column : GridDimension::Row; - while (true) { - while (auto_placement_cursor_x <= m_occupation_grid.max_column_index()) { - if (auto_placement_cursor_x + static_cast(column_span) <= m_occupation_grid.max_column_index() + 1) { - auto found_all_available = true; - for (size_t span_index = 0; span_index < column_span; span_index++) { - if (m_occupation_grid.is_occupied(auto_placement_cursor_x + span_index, auto_placement_cursor_y)) - found_all_available = false; - } - if (found_all_available) { - found_unoccupied_area = true; - column_start = auto_placement_cursor_x; - row_start = auto_placement_cursor_y; - break; - } - } + // 4.1.2.1. Increment the column position of the auto-placement cursor until either this item's grid + // area does not overlap any occupied grid cells, or the cursor's column position, plus the item's + // column span, overflow the number of columns in the implicit grid, as determined earlier in this + // algorithm. + auto found_unoccupied_area = m_occupation_grid.find_unoccupied_place(dimension, auto_placement_cursor_x, auto_placement_cursor_y, column_span, row_span); + // 4.1.2.2. If a non-overlapping position was found in the previous step, set the item's row-start + // and column-start lines to the cursor's position. Otherwise, increment the auto-placement cursor's + // row position (creating new rows in the implicit grid as necessary), set its column position to the + // start-most column line in the implicit grid, and return to the previous step. + if (found_unoccupied_area == FoundUnoccupiedPlace::Yes) { + column_start = auto_placement_cursor_x; + row_start = auto_placement_cursor_y; + + auto_placement_cursor_x += column_span - 1; + auto_placement_cursor_y += row_span - 1; + + if (dimension == GridDimension::Column) { auto_placement_cursor_x++; + auto_placement_cursor_y = m_occupation_grid.min_row_index(); + } else { + auto_placement_cursor_y++; + auto_placement_cursor_x = m_occupation_grid.min_column_index(); } + } else { + column_start = auto_placement_cursor_x; + row_start = auto_placement_cursor_y; - if (found_unoccupied_area) { - break; - } - - // 4.1.2.2. If a non-overlapping position was found in the previous step, set the item's row-start - // and column-start lines to the cursor's position. Otherwise, increment the auto-placement cursor's - // row position (creating new rows in the implicit grid as necessary), set its column position to the - // start-most column line in the implicit grid, and return to the previous step. - if (!found_unoccupied_area) { - if (auto_flow.row) { - auto_placement_cursor_x = m_occupation_grid.min_column_index(); - auto_placement_cursor_y++; - } else { - m_occupation_grid.set_max_column_index(auto_placement_cursor_x); - auto_placement_cursor_x = 0; - auto_placement_cursor_y = m_occupation_grid.min_row_index(); - } - } + auto_placement_cursor_x += column_span - 1; + auto_placement_cursor_y += row_span - 1; } m_occupation_grid.set_occupied(column_start, column_start + column_span, row_start, row_start + row_span); diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index 1c93b3dcf9..298b9b53ce 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -53,6 +53,11 @@ struct GridItem { [[nodiscard]] int gap_adjusted_column(Box const& grid_box) const; }; +enum class FoundUnoccupiedPlace { + No, + Yes +}; + class OccupationGrid { public: OccupationGrid(size_t columns_count, size_t rows_count) @@ -83,6 +88,8 @@ public: bool is_occupied(int column_index, int row_index) const; + FoundUnoccupiedPlace find_unoccupied_place(GridDimension dimension, int& column_index, int& row_index, int column_span, int row_span) const; + private: HashTable m_occupation_grid;