Browse Source

LibWeb: Support auto-fill for rows in GFC

This change fixes the function that calculates the number of auto-fill
tracks, ensuring it uses height when applied to rows, instead of
assuming that it always operates on columns.
Aliaksandr Kalenik 1 year ago
parent
commit
903d3c92c8

+ 30 - 0
Tests/LibWeb/Layout/expected/grid/auto-fill-rows.txt

@@ -0,0 +1,30 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x250.9375 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x234.9375 children: not-inline
+      Box <div.grid-container> at (8,8) content-size 784x234.9375 [GFC] children: not-inline
+        BlockContainer <div> at (8,8) content-size 784x200 [BFC] children: inline
+          line 0 width: 46.71875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 6, rect: [8,8 46.71875x17.46875]
+              "Item 1"
+          TextNode <#text>
+        BlockContainer <div> at (8,208) content-size 784x17.46875 [BFC] children: inline
+          line 0 width: 49.1875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 6, rect: [8,208 49.1875x17.46875]
+              "Item 2"
+          TextNode <#text>
+        BlockContainer <div> at (8,225.46875) content-size 784x17.46875 [BFC] children: inline
+          line 0 width: 49.46875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+            frag 0 from TextNode start: 0, length: 6, rect: [8,225.46875 49.46875x17.46875]
+              "Item 3"
+          TextNode <#text>
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x250.9375]
+    PaintableWithLines (BlockContainer<BODY>) [8,8 784x234.9375]
+      PaintableBox (Box<DIV>.grid-container) [8,8 784x234.9375]
+        PaintableWithLines (BlockContainer<DIV>) [8,8 784x200]
+          TextPaintable (TextNode<#text>)
+        PaintableWithLines (BlockContainer<DIV>) [8,208 784x17.46875]
+          TextPaintable (TextNode<#text>)
+        PaintableWithLines (BlockContainer<DIV>) [8,225.46875 784x17.46875]
+          TextPaintable (TextNode<#text>)

+ 9 - 0
Tests/LibWeb/Layout/input/grid/auto-fill-rows.html

@@ -0,0 +1,9 @@
+<!DOCTYPE html><html><style>
+* {
+    outline: 1px solid black;
+}
+.grid-container {
+    display: grid;
+    grid-template-rows: repeat(auto-fill, 200px);
+}
+</style><div class="grid-container"><div>Item 1</div><div>Item 2</div><div>Item 3</div></html>

+ 22 - 8
Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp

@@ -71,7 +71,7 @@ CSSPixels GridFormattingContext::resolve_definite_track_size(CSS::GridSize const
     return 0;
 }
 
-int GridFormattingContext::count_of_repeated_auto_fill_or_fit_tracks(Vector<CSS::ExplicitGridTrack> const& track_list)
+int GridFormattingContext::count_of_repeated_auto_fill_or_fit_tracks(GridDimension dimension)
 {
     // https://www.w3.org/TR/css-grid-2/#auto-repeat
     // 7.2.3.2. Repeat-to-fill: auto-fill and auto-fit repetitions
@@ -84,6 +84,8 @@ int GridFormattingContext::count_of_repeated_auto_fill_or_fit_tracks(Vector<CSS:
     // repetitions is the largest possible positive integer that does not cause the grid to overflow the
     // content box of its grid container
 
+    auto const& grid_computed_values = grid_container().computed_values();
+    auto const& track_list = dimension == GridDimension::Row ? grid_computed_values.grid_template_rows().track_list() : grid_computed_values.grid_template_columns().track_list();
     CSSPixels sum_of_grid_track_sizes = 0;
     // (treating each track as its max track sizing function if that is definite or its minimum track sizing
     // function otherwise, flooring the max track sizing function by the min track sizing function if both
@@ -103,12 +105,24 @@ int GridFormattingContext::count_of_repeated_auto_fill_or_fit_tracks(Vector<CSS:
         }
     }
 
-    auto free_space = get_free_space(*m_available_space, GridDimension::Column).to_px_or_zero();
-    auto const& column_gap = grid_container().computed_values().column_gap();
-    free_space -= repeat_track_list.size() * column_gap.to_px(grid_container(), m_available_space->width.to_px_or_zero());
-    if (free_space <= 0 || sum_of_grid_track_sizes == 0)
+    if (sum_of_grid_track_sizes == 0)
         return 0;
-    return (free_space / sum_of_grid_track_sizes).to_int();
+
+    auto const& available_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height;
+    auto free_space = get_free_space(*m_available_space, dimension).to_px_or_zero();
+    auto const& gap = dimension == GridDimension::Column ? grid_computed_values.column_gap() : grid_computed_values.row_gap();
+    free_space -= repeat_track_list.size() * gap.to_px(grid_container(), available_size.to_px_or_zero());
+    // If any number of repetitions would overflow, then 1 repetition.
+    if (free_space <= sum_of_grid_track_sizes) {
+        return 1;
+    }
+    // Otherwise, if the grid container has a definite min size in the relevant axis, the number of repetitions is the
+    // smallest possible positive integer that fulfills that minimum requirement
+    else if (available_size.is_definite()) {
+        return max(1, (free_space / sum_of_grid_track_sizes).to_int());
+    }
+    // Otherwise, the specified track list repeats only once.
+    return 1;
 
     // For the purpose of finding the number of auto-repeated tracks in a standalone axis, the UA must
     // floor the track size to a UA-specified value to avoid division by zero. It is suggested that this
@@ -618,7 +632,7 @@ void GridFormattingContext::initialize_grid_tracks_from_definition(GridDimension
         int repeat_count = 1;
         if (track_definition.is_repeat()) {
             if (track_definition.repeat().is_auto_fill() || track_definition.repeat().is_auto_fit())
-                repeat_count = count_of_repeated_auto_fill_or_fit_tracks(tracks_definition);
+                repeat_count = count_of_repeated_auto_fill_or_fit_tracks(dimension);
             else
                 repeat_count = track_definition.repeat().repeat_count();
         }
@@ -2266,7 +2280,7 @@ void GridFormattingContext::init_grid_lines(GridDimension dimension)
                 } else if (explicit_track.is_repeat()) {
                     int repeat_count = 0;
                     if (explicit_track.repeat().is_auto_fill() || explicit_track.repeat().is_auto_fit())
-                        repeat_count = count_of_repeated_auto_fill_or_fit_tracks(lines_definition.track_list());
+                        repeat_count = count_of_repeated_auto_fill_or_fit_tracks(dimension);
                     else
                         repeat_count = explicit_track.repeat().repeat_count();
                     auto const& repeat_track = explicit_track.repeat();

+ 1 - 1
Userland/Libraries/LibWeb/Layout/GridFormattingContext.h

@@ -244,7 +244,7 @@ private:
 
     Optional<int> get_line_index_by_line_name(GridDimension dimension, String const&);
     CSSPixels resolve_definite_track_size(CSS::GridSize const&, AvailableSpace const&);
-    int count_of_repeated_auto_fill_or_fit_tracks(Vector<CSS::ExplicitGridTrack> const& track_list);
+    int count_of_repeated_auto_fill_or_fit_tracks(GridDimension);
 
     void build_grid_areas();