ソースを参照

LibWeb: Add parent classes for managing GridTrackSizes

Add classes ExplicitTrackSizing and MetaGridTrackSize which will allow
for managing properties like auto-fill and minmax.

In the following CSS example there are 3 classes that will be used:
grid-template-column: repeat(auto-fill, minmax(50px, 1fr) 75px);

ExplicitTrackSizing - will contain the entire value. e.g.
repeat(auto-fill, minmax(50px, 1fr) 75px)

With a flag if it's a repeat, as well as references to the
MetaGridTrackSizes which is the next step down.

MetaGridTrackSize:
Contain the individual grid track sizes. Here there are two:
minmax(50px, 1fr) as well as 75px.

This way can keep track if it's a minmax function or not, and the
references to both GridTrackSizes in the case it is, or in just the one
if it is not.

GridTrackSize:
Is the most basic element, in this case there are three in total; two of
which are held by the first MetaGridTrackSize, and the third is held by
the second MetaGridTrackSize.
Examples: 50px, 1fr and 75px.
martinfalisse 2 年 前
コミット
f7af190de0

+ 8 - 8
Userland/Libraries/LibWeb/CSS/ComputedValues.h

@@ -64,8 +64,8 @@ public:
     static CSS::Size height() { return CSS::Size::make_auto(); }
     static CSS::Size min_height() { return CSS::Size::make_auto(); }
     static CSS::Size max_height() { return CSS::Size::make_none(); }
-    static Vector<CSS::GridTrackSize> grid_template_columns() { return Vector<CSS::GridTrackSize> {}; }
-    static Vector<CSS::GridTrackSize> grid_template_rows() { return Vector<CSS::GridTrackSize> {}; }
+    static CSS::ExplicitTrackSizing grid_template_columns() { return CSS::ExplicitTrackSizing::make_auto(); }
+    static CSS::ExplicitTrackSizing grid_template_rows() { return CSS::ExplicitTrackSizing::make_auto(); }
     static CSS::GridTrackPlacement grid_column_end() { return CSS::GridTrackPlacement::make_auto(); }
     static CSS::GridTrackPlacement grid_column_start() { return CSS::GridTrackPlacement::make_auto(); }
     static CSS::GridTrackPlacement grid_row_end() { return CSS::GridTrackPlacement::make_auto(); }
@@ -182,8 +182,8 @@ public:
     CSS::Size const& min_height() const { return m_noninherited.min_height; }
     CSS::Size const& max_height() const { return m_noninherited.max_height; }
     Variant<CSS::VerticalAlign, CSS::LengthPercentage> const& vertical_align() const { return m_noninherited.vertical_align; }
-    Vector<CSS::GridTrackSize> const& grid_template_columns() const { return m_noninherited.grid_template_columns; }
-    Vector<CSS::GridTrackSize> const& grid_template_rows() const { return m_noninherited.grid_template_rows; }
+    CSS::ExplicitTrackSizing const& grid_template_columns() const { return m_noninherited.grid_template_columns; }
+    CSS::ExplicitTrackSizing const& grid_template_rows() const { return m_noninherited.grid_template_rows; }
     CSS::GridTrackPlacement const& grid_column_end() const { return m_noninherited.grid_column_end; }
     CSS::GridTrackPlacement const& grid_column_start() const { return m_noninherited.grid_column_start; }
     CSS::GridTrackPlacement const& grid_row_end() const { return m_noninherited.grid_row_end; }
@@ -304,8 +304,8 @@ protected:
         CSS::BoxSizing box_sizing { InitialValues::box_sizing() };
         CSS::ContentData content;
         Variant<CSS::VerticalAlign, CSS::LengthPercentage> vertical_align { InitialValues::vertical_align() };
-        Vector<CSS::GridTrackSize> grid_template_columns;
-        Vector<CSS::GridTrackSize> grid_template_rows;
+        CSS::ExplicitTrackSizing grid_template_columns;
+        CSS::ExplicitTrackSizing grid_template_rows;
         CSS::GridTrackPlacement grid_column_end { InitialValues::grid_column_end() };
         CSS::GridTrackPlacement grid_column_start { InitialValues::grid_column_start() };
         CSS::GridTrackPlacement grid_row_end { InitialValues::grid_row_end() };
@@ -382,8 +382,8 @@ public:
     void set_box_sizing(CSS::BoxSizing value) { m_noninherited.box_sizing = value; }
     void set_vertical_align(Variant<CSS::VerticalAlign, CSS::LengthPercentage> value) { m_noninherited.vertical_align = move(value); }
     void set_visibility(CSS::Visibility value) { m_inherited.visibility = value; }
-    void set_grid_template_columns(Vector<CSS::GridTrackSize> value) { m_noninherited.grid_template_columns = move(value); }
-    void set_grid_template_rows(Vector<CSS::GridTrackSize> value) { m_noninherited.grid_template_rows = move(value); }
+    void set_grid_template_columns(CSS::ExplicitTrackSizing value) { m_noninherited.grid_template_columns = move(value); }
+    void set_grid_template_rows(CSS::ExplicitTrackSizing value) { m_noninherited.grid_template_rows = move(value); }
     void set_grid_column_end(CSS::GridTrackPlacement value) { m_noninherited.grid_column_end = value; }
     void set_grid_column_start(CSS::GridTrackPlacement value) { m_noninherited.grid_column_start = value; }
     void set_grid_row_end(CSS::GridTrackPlacement value) { m_noninherited.grid_row_end = value; }

+ 47 - 0
Userland/Libraries/LibWeb/CSS/GridTrackSize.cpp

@@ -57,4 +57,51 @@ Length GridTrackSize::length() const
     return m_length;
 }
 
+MetaGridTrackSize::MetaGridTrackSize(GridTrackSize grid_track_size)
+    : m_min_grid_track_size(grid_track_size)
+    , m_max_grid_track_size(grid_track_size)
+{
+}
+
+String MetaGridTrackSize::to_string() const
+{
+    return String::formatted("{}", m_min_grid_track_size.to_string());
+}
+
+ExplicitTrackSizing::ExplicitTrackSizing()
+{
+}
+
+ExplicitTrackSizing::ExplicitTrackSizing(Vector<CSS::MetaGridTrackSize> meta_grid_track_sizes)
+    : m_meta_grid_track_sizes(meta_grid_track_sizes)
+{
+}
+
+ExplicitTrackSizing::ExplicitTrackSizing(Vector<CSS::MetaGridTrackSize> meta_grid_track_sizes, int repeat_count)
+    : m_meta_grid_track_sizes(meta_grid_track_sizes)
+    , m_is_repeat(true)
+    , m_repeat_count(repeat_count)
+{
+}
+
+String ExplicitTrackSizing::to_string() const
+{
+    StringBuilder builder;
+    if (m_is_repeat) {
+        builder.append("repeat("sv);
+        builder.append(m_repeat_count);
+        builder.append(", "sv);
+    }
+    for (int _ = 0; _ < m_repeat_count; ++_) {
+        for (size_t y = 0; y < m_meta_grid_track_sizes.size(); ++y) {
+            builder.append(m_meta_grid_track_sizes[y].to_string());
+            if (y != m_meta_grid_track_sizes.size() - 1)
+                builder.append(" "sv);
+        }
+    }
+    if (m_is_repeat)
+        builder.append(")"sv);
+    return builder.to_string();
+}
+
 }

+ 45 - 0
Userland/Libraries/LibWeb/CSS/GridTrackSize.h

@@ -6,6 +6,7 @@
 
 #pragma once
 
+#include <AK/Vector.h>
 #include <LibWeb/CSS/Length.h>
 #include <LibWeb/CSS/Percentage.h>
 
@@ -64,4 +65,48 @@ private:
     float m_flexible_length { 0 };
 };
 
+class MetaGridTrackSize {
+public:
+    MetaGridTrackSize(CSS::GridTrackSize);
+
+    GridTrackSize grid_track_size() const& { return m_min_grid_track_size; }
+    GridTrackSize min_grid_track_size() const& { return m_min_grid_track_size; }
+    GridTrackSize max_grid_track_size() const& { return m_max_grid_track_size; }
+
+    String to_string() const;
+    bool operator==(MetaGridTrackSize const& other) const
+    {
+        return m_min_grid_track_size == other.min_grid_track_size()
+            && m_max_grid_track_size == other.max_grid_track_size();
+    }
+
+private:
+    GridTrackSize m_min_grid_track_size;
+    GridTrackSize m_max_grid_track_size;
+};
+
+class ExplicitTrackSizing {
+public:
+    ExplicitTrackSizing();
+    ExplicitTrackSizing(Vector<CSS::MetaGridTrackSize>);
+    ExplicitTrackSizing(Vector<CSS::MetaGridTrackSize>, int repeat_count);
+    static ExplicitTrackSizing make_auto() { return ExplicitTrackSizing(); };
+
+    bool is_repeat() const { return m_is_repeat; }
+    int repeat_count() const { return m_repeat_count; }
+
+    Vector<CSS::MetaGridTrackSize> meta_grid_track_sizes() const& { return m_meta_grid_track_sizes; }
+
+    String to_string() const;
+    bool operator==(ExplicitTrackSizing const& other) const
+    {
+        return m_meta_grid_track_sizes == other.meta_grid_track_sizes();
+    }
+
+private:
+    Vector<CSS::MetaGridTrackSize> m_meta_grid_track_sizes;
+    bool m_is_repeat { false };
+    int m_repeat_count { 0 };
+};
+
 }

+ 8 - 12
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -5409,7 +5409,7 @@ RefPtr<StyleValue> Parser::parse_as_css_value(PropertyID property_id)
 
 RefPtr<StyleValue> Parser::parse_grid_track_sizes(Vector<ComponentValue> const& component_values)
 {
-    Vector<CSS::GridTrackSize> params;
+    Vector<CSS::MetaGridTrackSize> params;
     for (auto const& component_value : component_values) {
         if (component_value.is_function()) {
             auto const& function_token = component_value.function();
@@ -5439,7 +5439,7 @@ RefPtr<StyleValue> Parser::parse_grid_track_sizes(Vector<ComponentValue> const&
                 if (!part_two_tokens.has_next_token())
                     continue;
 
-                Vector<CSS::GridTrackSize> repeat_params;
+                Vector<CSS::MetaGridTrackSize> repeat_params;
                 while (true) {
                     part_two_tokens.skip_whitespace();
                     auto current_component_value = part_two_tokens.next_token();
@@ -5469,13 +5469,8 @@ RefPtr<StyleValue> Parser::parse_grid_track_sizes(Vector<ComponentValue> const&
                         }
                     }
                     part_two_tokens.skip_whitespace();
-                    if (!part_two_tokens.has_next_token()) {
-                        for (int i = 0; i < repeat_count; ++i) {
-                            for (auto const& repeat_param : repeat_params)
-                                params.append(repeat_param);
-                        }
+                    if (!part_two_tokens.has_next_token())
                         break;
-                    }
                 }
 
                 // Automatic repetitions (auto-fill or auto-fit) cannot be combined with intrinsic or flexible sizes.
@@ -5499,17 +5494,18 @@ RefPtr<StyleValue> Parser::parse_grid_track_sizes(Vector<ComponentValue> const&
                 // If a repeat() function that is not a <name-repeat> ends up placing two <line-names> adjacent to
                 // each other, the name lists are merged. For example, repeat(2, [a] 1fr [b]) is equivalent to [a]
                 // 1fr [b a] 1fr [b].
+                return GridTrackSizeStyleValue::create(CSS::ExplicitTrackSizing(repeat_params, repeat_count));
             } else {
                 // FIXME: Implement MinMax, etc.
             }
             continue;
         }
         if (component_value.is_block()) {
-            params.append(Length::make_auto());
+            params.append(GridTrackSize(Length::make_auto()));
             continue;
         }
         if (component_value.is(Token::Type::Ident) && component_value.token().ident().equals_ignoring_case("auto"sv)) {
-            params.append(Length::make_auto());
+            params.append(GridTrackSize(Length::make_auto()));
             continue;
         }
         if (component_value.token().type() == Token::Type::Dimension) {
@@ -5525,9 +5521,9 @@ RefPtr<StyleValue> Parser::parse_grid_track_sizes(Vector<ComponentValue> const&
         if (!dimension.has_value())
             return GridTrackSizeStyleValue::create({});
         if (dimension->is_length())
-            params.append(dimension->length());
+            params.append(GridTrackSize(dimension->length()));
         if (dimension->is_percentage())
-            params.append(dimension->percentage());
+            params.append(GridTrackSize(dimension->percentage()));
     }
     return GridTrackSizeStyleValue::create(params);
 }

+ 4 - 4
Userland/Libraries/LibWeb/CSS/StyleProperties.cpp

@@ -705,16 +705,16 @@ Optional<CSS::FontVariant> StyleProperties::font_variant() const
     return value_id_to_font_variant(value->to_identifier());
 }
 
-Vector<CSS::GridTrackSize> StyleProperties::grid_template_columns() const
+CSS::ExplicitTrackSizing StyleProperties::grid_template_columns() const
 {
     auto value = property(CSS::PropertyID::GridTemplateColumns);
-    return value->as_grid_track_size().grid_track_size();
+    return value->as_explicit_track_sizing().explicit_track_sizing();
 }
 
-Vector<CSS::GridTrackSize> StyleProperties::grid_template_rows() const
+CSS::ExplicitTrackSizing StyleProperties::grid_template_rows() const
 {
     auto value = property(CSS::PropertyID::GridTemplateRows);
-    return value->as_grid_track_size().grid_track_size();
+    return value->as_explicit_track_sizing().explicit_track_sizing();
 }
 
 CSS::GridTrackPlacement StyleProperties::grid_column_end() const

+ 2 - 2
Userland/Libraries/LibWeb/CSS/StyleProperties.h

@@ -84,8 +84,8 @@ public:
     Optional<CSS::PointerEvents> pointer_events() const;
     Variant<CSS::VerticalAlign, CSS::LengthPercentage> vertical_align() const;
     Optional<CSS::FontVariant> font_variant() const;
-    Vector<CSS::GridTrackSize> grid_template_columns() const;
-    Vector<CSS::GridTrackSize> grid_template_rows() const;
+    CSS::ExplicitTrackSizing grid_template_columns() const;
+    CSS::ExplicitTrackSizing grid_template_rows() const;
     CSS::GridTrackPlacement grid_column_end() const;
     CSS::GridTrackPlacement grid_column_start() const;
     CSS::GridTrackPlacement grid_row_end() const;

+ 7 - 13
Userland/Libraries/LibWeb/CSS/StyleValue.cpp

@@ -168,9 +168,9 @@ LengthStyleValue const& StyleValue::as_length() const
     return static_cast<LengthStyleValue const&>(*this);
 }
 
-GridTrackSizeStyleValue const& StyleValue::as_grid_track_size() const
+GridTrackSizeStyleValue const& StyleValue::as_explicit_track_sizing() const
 {
-    VERIFY(is_grid_track_size());
+    VERIFY(is_explicit_track_sizing());
     return static_cast<GridTrackSizeStyleValue const&>(*this);
 }
 
@@ -1418,21 +1418,15 @@ bool GridTrackPlacementStyleValue::equals(StyleValue const& other) const
 
 String GridTrackSizeStyleValue::to_string() const
 {
-    StringBuilder builder;
-    for (size_t i = 0; i < m_grid_track.size(); i++) {
-        builder.append(m_grid_track[i].to_string());
-        if (i != m_grid_track.size() - 1)
-            builder.append(" "sv);
-    }
-    return builder.to_string();
+    return m_explicit_track_sizing.to_string();
 }
 
 bool GridTrackSizeStyleValue::equals(StyleValue const& other) const
 {
     if (type() != other.type())
         return false;
-    auto const& typed_other = other.as_grid_track_size();
-    return m_grid_track == typed_other.grid_track_size();
+    auto const& typed_other = other.as_explicit_track_sizing();
+    return m_explicit_track_sizing == typed_other.explicit_track_sizing();
 }
 
 String IdentifierStyleValue::to_string() const
@@ -2151,9 +2145,9 @@ NonnullRefPtr<GridTrackPlacementStyleValue> GridTrackPlacementStyleValue::create
     return adopt_ref(*new GridTrackPlacementStyleValue(grid_track_placement));
 }
 
-NonnullRefPtr<GridTrackSizeStyleValue> GridTrackSizeStyleValue::create(Vector<CSS::GridTrackSize> grid_track_size)
+NonnullRefPtr<GridTrackSizeStyleValue> GridTrackSizeStyleValue::create(CSS::ExplicitTrackSizing explicit_track_sizing)
 {
-    return adopt_ref(*new GridTrackSizeStyleValue(grid_track_size));
+    return adopt_ref(*new GridTrackSizeStyleValue(explicit_track_sizing));
 }
 
 NonnullRefPtr<RectStyleValue> RectStyleValue::create(EdgeRect rect)

+ 10 - 10
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -174,6 +174,7 @@ public:
         Calculated,
         Color,
         Content,
+        ExplicitTrackSizing,
         FilterValueList,
         Flex,
         FlexFlow,
@@ -181,7 +182,6 @@ public:
         Frequency,
         GridTrackPlacement,
         GridTrackPlacementShorthand,
-        GridTrackSize,
         Identifier,
         Image,
         Inherit,
@@ -226,7 +226,7 @@ public:
     bool is_frequency() const { return type() == Type::Frequency; }
     bool is_grid_track_placement() const { return type() == Type::GridTrackPlacement; }
     bool is_grid_track_placement_shorthand() const { return type() == Type::GridTrackPlacementShorthand; }
-    bool is_grid_track_size() const { return type() == Type::GridTrackSize; }
+    bool is_explicit_track_sizing() const { return type() == Type::ExplicitTrackSizing; }
     bool is_identifier() const { return type() == Type::Identifier; }
     bool is_image() const { return type() == Type::Image; }
     bool is_inherit() const { return type() == Type::Inherit; }
@@ -269,7 +269,7 @@ public:
     FrequencyStyleValue const& as_frequency() const;
     GridTrackPlacementShorthandStyleValue const& as_grid_track_placement_shorthand() const;
     GridTrackPlacementStyleValue const& as_grid_track_placement() const;
-    GridTrackSizeStyleValue const& as_grid_track_size() const;
+    GridTrackSizeStyleValue const& as_explicit_track_sizing() const;
     IdentifierStyleValue const& as_identifier() const;
     ImageStyleValue const& as_image() const;
     InheritStyleValue const& as_inherit() const;
@@ -310,7 +310,7 @@ public:
     FrequencyStyleValue& as_frequency() { return const_cast<FrequencyStyleValue&>(const_cast<StyleValue const&>(*this).as_frequency()); }
     GridTrackPlacementShorthandStyleValue& as_grid_track_placement_shorthand() { return const_cast<GridTrackPlacementShorthandStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_placement_shorthand()); }
     GridTrackPlacementStyleValue& as_grid_track_placement() { return const_cast<GridTrackPlacementStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_placement()); }
-    GridTrackSizeStyleValue& as_grid_track_size() { return const_cast<GridTrackSizeStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_size()); }
+    GridTrackSizeStyleValue& as_explicit_track_sizing() { return const_cast<GridTrackSizeStyleValue&>(const_cast<StyleValue const&>(*this).as_explicit_track_sizing()); }
     IdentifierStyleValue& as_identifier() { return const_cast<IdentifierStyleValue&>(const_cast<StyleValue const&>(*this).as_identifier()); }
     ImageStyleValue& as_image() { return const_cast<ImageStyleValue&>(const_cast<StyleValue const&>(*this).as_image()); }
     InheritStyleValue& as_inherit() { return const_cast<InheritStyleValue&>(const_cast<StyleValue const&>(*this).as_inherit()); }
@@ -1048,21 +1048,21 @@ private:
 
 class GridTrackSizeStyleValue final : public StyleValue {
 public:
-    static NonnullRefPtr<GridTrackSizeStyleValue> create(Vector<CSS::GridTrackSize> grid_track_size);
+    static NonnullRefPtr<GridTrackSizeStyleValue> create(CSS::ExplicitTrackSizing explicit_track_sizing);
     virtual ~GridTrackSizeStyleValue() override = default;
 
-    Vector<CSS::GridTrackSize> grid_track_size() const { return m_grid_track; }
+    CSS::ExplicitTrackSizing explicit_track_sizing() const { return m_explicit_track_sizing; }
     virtual String to_string() const override;
     virtual bool equals(StyleValue const& other) const override;
 
 private:
-    explicit GridTrackSizeStyleValue(Vector<CSS::GridTrackSize> grid_track_size)
-        : StyleValue(Type::GridTrackSize)
-        , m_grid_track(grid_track_size)
+    explicit GridTrackSizeStyleValue(CSS::ExplicitTrackSizing explicit_track_sizing)
+        : StyleValue(Type::ExplicitTrackSizing)
+        , m_explicit_track_sizing(explicit_track_sizing)
     {
     }
 
-    Vector<CSS::GridTrackSize> m_grid_track;
+    CSS::ExplicitTrackSizing m_explicit_track_sizing;
 };
 
 class IdentifierStyleValue final : public StyleValue {

+ 2 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -50,6 +50,7 @@ class CSSStyleSheet;
 class CSSSupportsRule;
 class Display;
 class ElementInlineCSSStyleDeclaration;
+class ExplicitTrackSizing;
 class FilterValueListStyleValue;
 class FlexFlowStyleValue;
 class FlexStyleValue;
@@ -78,6 +79,7 @@ class MediaList;
 class MediaQuery;
 class MediaQueryList;
 class MediaQueryListEvent;
+class MetaGridTrackSize;
 class Number;
 class NumericStyleValue;
 class OverflowStyleValue;

+ 11 - 5
Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp

@@ -57,7 +57,9 @@ void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const
         boxes_to_place.append(child_box);
         return IterationDecision::Continue;
     });
-    auto occupation_grid = OccupationGrid(static_cast<int>(box.computed_values().grid_template_columns().size()), static_cast<int>(box.computed_values().grid_template_rows().size()));
+    auto column_repeat_count = box.computed_values().grid_template_columns().is_repeat() ? box.computed_values().grid_template_columns().repeat_count() : 1;
+    auto row_repeat_count = box.computed_values().grid_template_rows().is_repeat() ? box.computed_values().grid_template_rows().repeat_count() : 1;
+    auto occupation_grid = OccupationGrid(column_repeat_count * box.computed_values().grid_template_columns().meta_grid_track_sizes().size(), row_repeat_count * box.computed_values().grid_template_rows().meta_grid_track_sizes().size());
 
     // https://drafts.csswg.org/css-grid/#auto-placement-algo
     // 8.5. Grid Item Placement Algorithm
@@ -521,10 +523,14 @@ void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const
     Vector<GridTrack> grid_rows;
     Vector<GridTrack> grid_columns;
 
-    for (auto& column_size : box.computed_values().grid_template_columns())
-        grid_columns.append({ column_size, column_size });
-    for (auto& row_size : box.computed_values().grid_template_rows())
-        grid_rows.append({ row_size, row_size });
+    for (int x = 0; x < column_repeat_count; ++x) {
+        for (auto& meta_grid_track_size : box.computed_values().grid_template_columns().meta_grid_track_sizes())
+            grid_columns.append({ meta_grid_track_size.min_grid_track_size(), meta_grid_track_size.max_grid_track_size() });
+    }
+    for (int x = 0; x < row_repeat_count; ++x) {
+        for (auto& meta_grid_track_size : box.computed_values().grid_template_rows().meta_grid_track_sizes())
+            grid_rows.append({ meta_grid_track_size.min_grid_track_size(), meta_grid_track_size.max_grid_track_size() });
+    }
 
     for (int column_index = grid_columns.size(); column_index < occupation_grid.column_count(); column_index++)
         grid_columns.append({ CSS::GridTrackSize::make_auto(), CSS::GridTrackSize::make_auto() });