Browse Source

LibWeb: Calculate valid grid areas

When starting the GridFormattingContext, calculate the valid grid areas
as declared in the `grid-template-areas` property. Since this doesn't
change, are able to do this once and store the results.
martinfalisse 2 years ago
parent
commit
47c77858b6

+ 49 - 0
Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp

@@ -1591,6 +1591,53 @@ void GridFormattingContext::calculate_sizes_of_rows(Box const& box)
     }
     }
 }
 }
 
 
+void GridFormattingContext::build_valid_grid_areas(Box const& box)
+{
+    Vector<GridArea> found_grid_areas;
+
+    auto get_index_of_found_grid_area = [&](String needle) -> int {
+        for (size_t x = 0; x < found_grid_areas.size(); x++) {
+            if (found_grid_areas[x].name == needle)
+                return static_cast<int>(x);
+        }
+        return -1;
+    };
+
+    // 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 (int y = 0; y < static_cast<int>(box.computed_values().grid_template_areas().size()); y++) {
+        for (int x = 0; x < static_cast<int>(box.computed_values().grid_template_areas()[y].size()); x++) {
+            auto grid_area_idx = get_index_of_found_grid_area(box.computed_values().grid_template_areas()[y][x]);
+            if (grid_area_idx == -1) {
+                found_grid_areas.append({ box.computed_values().grid_template_areas()[y][x], y, y + 1, x, x + 1 });
+            } else {
+                auto& grid_area = found_grid_areas[grid_area_idx];
+                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;
+                    }
+                }
+            }
+        }
+    }
+
+    for (auto const& checked_grid_area : found_grid_areas)
+        m_valid_grid_areas.append(checked_grid_area);
+}
+
 void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& available_space)
 void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& available_space)
 {
 {
     auto grid_template_columns = box.computed_values().grid_template_columns();
     auto grid_template_columns = box.computed_values().grid_template_columns();
@@ -1614,6 +1661,8 @@ void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const
 
 
     m_occupation_grid = OccupationGrid(column_count, row_count);
     m_occupation_grid = OccupationGrid(column_count, row_count);
 
 
+    build_valid_grid_areas(box);
+
     // https://drafts.csswg.org/css-grid/#auto-placement-algo
     // https://drafts.csswg.org/css-grid/#auto-placement-algo
     // 8.5. Grid Item Placement Algorithm
     // 8.5. Grid Item Placement Algorithm
 
 

+ 11 - 0
Userland/Libraries/LibWeb/Layout/GridFormattingContext.h

@@ -89,6 +89,15 @@ private:
         }
         }
     };
     };
 
 
+    struct GridArea {
+        String name;
+        int row_start { 0 };
+        int row_end { 1 };
+        int column_start { 0 };
+        int column_end { 1 };
+    };
+    Vector<GridArea> m_valid_grid_areas;
+
     Vector<TemporaryTrack> m_grid_rows;
     Vector<TemporaryTrack> m_grid_rows;
     Vector<TemporaryTrack> m_grid_columns;
     Vector<TemporaryTrack> m_grid_columns;
 
 
@@ -107,6 +116,8 @@ private:
     int count_of_repeated_auto_fill_or_fit_tracks(Vector<CSS::ExplicitGridTrack> const& track_list, AvailableSpace const&, Box const&);
     int count_of_repeated_auto_fill_or_fit_tracks(Vector<CSS::ExplicitGridTrack> const& track_list, AvailableSpace const&, Box const&);
     int get_count_of_tracks(Vector<CSS::ExplicitGridTrack> const&, AvailableSpace const&, Box const&);
     int get_count_of_tracks(Vector<CSS::ExplicitGridTrack> const&, AvailableSpace const&, Box const&);
 
 
+    void build_valid_grid_areas(Box const&);
+
     void place_item_with_row_and_column_position(Box const& box, Box const& child_box);
     void place_item_with_row_and_column_position(Box const& box, Box const& child_box);
     void place_item_with_row_position(Box const& box, Box const& child_box);
     void place_item_with_row_position(Box const& box, Box const& child_box);
     void place_item_with_column_position(Box const& box, Box const& child_box, int& auto_placement_cursor_x, int& auto_placement_cursor_y);
     void place_item_with_column_position(Box const& box, Box const& child_box, int& auto_placement_cursor_x, int& auto_placement_cursor_y);