瀏覽代碼

LibWeb: Use LengthPercentage in CSS::GridSize

Using LengthPercentage instead of Length and Percentage separately
is going to allow GridSize to store calc() values. It also allows
to simplify some parts of layout code.
Aliaksandr Kalenik 2 年之前
父節點
當前提交
7fee05e18c

+ 20 - 24
Userland/Libraries/LibWeb/CSS/GridTrackSize.cpp

@@ -6,38 +6,31 @@
 
 
 #include "GridTrackSize.h"
 #include "GridTrackSize.h"
 #include <AK/String.h>
 #include <AK/String.h>
+#include <LibWeb/CSS/Size.h>
 
 
 namespace Web::CSS {
 namespace Web::CSS {
 
 
-GridSize::GridSize(Length length)
-    : m_type(Type::Length)
-    , m_length(length)
-{
-}
-
-GridSize::GridSize(Percentage percentage)
-    : m_type(Type::Percentage)
-    , m_length { Length::make_px(0) }
-    , m_percentage(percentage)
-{
-}
+GridSize::GridSize(LengthPercentage length_percentage)
+    : m_type(Type::LengthPercentage)
+    , m_length_percentage(length_percentage) {};
 
 
 GridSize::GridSize(float flexible_length)
 GridSize::GridSize(float flexible_length)
     : m_type(Type::FlexibleLength)
     : m_type(Type::FlexibleLength)
-    , m_length { Length::make_px(0) }
+    , m_length_percentage { Length::make_px(0) }
     , m_flexible_length(flexible_length)
     , m_flexible_length(flexible_length)
 {
 {
 }
 }
 
 
 GridSize::GridSize(Type type)
 GridSize::GridSize(Type type)
-    : m_length { Length::make_auto() }
+    : m_length_percentage { Length::make_auto() }
 {
 {
     VERIFY(type == Type::MinContent || type == Type::MaxContent);
     VERIFY(type == Type::MinContent || type == Type::MaxContent);
     m_type = type;
     m_type = type;
 }
 }
 
 
 GridSize::GridSize()
 GridSize::GridSize()
-    : m_length { Length::make_auto() }
+    : m_type(Type::LengthPercentage)
+    , m_length_percentage { Length::make_auto() }
 {
 {
 }
 }
 
 
@@ -48,13 +41,21 @@ GridSize GridSize::make_auto()
     return GridSize(CSS::Length::make_auto());
     return GridSize(CSS::Length::make_auto());
 }
 }
 
 
+Size GridSize::css_size() const
+{
+    VERIFY(m_type == Type::LengthPercentage);
+    if (m_length_percentage.is_auto())
+        return CSS::Size::make_auto();
+    if (m_length_percentage.is_length())
+        return CSS::Size::make_length(m_length_percentage.length());
+    return CSS::Size::make_percentage(m_length_percentage.percentage());
+}
+
 ErrorOr<String> GridSize::to_string() const
 ErrorOr<String> GridSize::to_string() const
 {
 {
     switch (m_type) {
     switch (m_type) {
-    case Type::Length:
-        return m_length.to_string();
-    case Type::Percentage:
-        return m_percentage.to_string();
+    case Type::LengthPercentage:
+        return m_length_percentage.to_string();
     case Type::FlexibleLength:
     case Type::FlexibleLength:
         return String::formatted("{}fr", m_flexible_length);
         return String::formatted("{}fr", m_flexible_length);
     case Type::MaxContent:
     case Type::MaxContent:
@@ -65,11 +66,6 @@ ErrorOr<String> GridSize::to_string() const
     VERIFY_NOT_REACHED();
     VERIFY_NOT_REACHED();
 }
 }
 
 
-Length GridSize::length() const
-{
-    return m_length;
-}
-
 GridMinMax::GridMinMax(GridSize min_grid_size, GridSize max_grid_size)
 GridMinMax::GridMinMax(GridSize min_grid_size, GridSize max_grid_size)
     : m_min_grid_size(min_grid_size)
     : m_min_grid_size(min_grid_size)
     , m_max_grid_size(max_grid_size)
     , m_max_grid_size(max_grid_size)

+ 12 - 18
Userland/Libraries/LibWeb/CSS/GridTrackSize.h

@@ -7,23 +7,20 @@
 #pragma once
 #pragma once
 
 
 #include <AK/Vector.h>
 #include <AK/Vector.h>
-#include <LibWeb/CSS/Length.h>
-#include <LibWeb/CSS/Percentage.h>
+#include <LibWeb/CSS/PercentageOr.h>
 
 
 namespace Web::CSS {
 namespace Web::CSS {
 
 
 class GridSize {
 class GridSize {
 public:
 public:
     enum class Type {
     enum class Type {
-        Length,
-        Percentage,
+        LengthPercentage,
         FlexibleLength,
         FlexibleLength,
         MaxContent,
         MaxContent,
         MinContent,
         MinContent,
     };
     };
 
 
-    GridSize(Length);
-    GridSize(Percentage);
+    GridSize(LengthPercentage);
     GridSize(float);
     GridSize(float);
     GridSize(Type);
     GridSize(Type);
     GridSize();
     GridSize();
@@ -33,14 +30,13 @@ public:
 
 
     Type type() const { return m_type; }
     Type type() const { return m_type; }
 
 
-    bool is_length() const { return m_type == Type::Length; }
-    bool is_percentage() const { return m_type == Type::Percentage; }
+    bool is_auto() const { return m_type == Type::LengthPercentage && m_length_percentage.is_auto(); }
+    bool is_length_percentage() const { return m_type == Type::LengthPercentage; }
     bool is_flexible_length() const { return m_type == Type::FlexibleLength; }
     bool is_flexible_length() const { return m_type == Type::FlexibleLength; }
     bool is_max_content() const { return m_type == Type::MaxContent; }
     bool is_max_content() const { return m_type == Type::MaxContent; }
     bool is_min_content() const { return m_type == Type::MinContent; }
     bool is_min_content() const { return m_type == Type::MinContent; }
 
 
-    Length length() const;
-    Percentage percentage() const { return m_percentage; }
+    LengthPercentage length_percentage() const { return m_length_percentage; };
     float flexible_length() const { return m_flexible_length; }
     float flexible_length() const { return m_flexible_length; }
 
 
     // https://www.w3.org/TR/css-grid-2/#layout-algorithm
     // https://www.w3.org/TR/css-grid-2/#layout-algorithm
@@ -48,29 +44,27 @@ public:
     // FIXME: Add missing properties once implemented.
     // FIXME: Add missing properties once implemented.
     bool is_intrinsic_track_sizing() const
     bool is_intrinsic_track_sizing() const
     {
     {
-        return (m_type == Type::Length && m_length.is_auto()) || m_type == Type::MaxContent || m_type == Type::MinContent;
+        return is_auto() || is_max_content() || is_min_content();
     }
     }
 
 
     bool is_definite() const
     bool is_definite() const
     {
     {
-        return (m_type == Type::Length && !m_length.is_auto()) || is_percentage();
+        return type() == Type::LengthPercentage && !m_length_percentage.is_auto();
     }
     }
 
 
+    Size css_size() const;
+
     ErrorOr<String> to_string() const;
     ErrorOr<String> to_string() const;
     bool operator==(GridSize const& other) const
     bool operator==(GridSize const& other) const
     {
     {
         return m_type == other.type()
         return m_type == other.type()
-            && m_length == other.length()
-            && m_percentage == other.percentage()
+            && m_length_percentage == other.length_percentage()
             && m_flexible_length == other.flexible_length();
             && m_flexible_length == other.flexible_length();
     }
     }
 
 
 private:
 private:
     Type m_type;
     Type m_type;
-    // Length includes a RefPtr<CalculatedStyleValue> member, but we can't include the header StyleValue.h as it includes
-    // this file already. To break the cyclic dependency, we must initialize m_length in the constructor.
-    Length m_length;
-    Percentage m_percentage { Percentage(0) };
+    LengthPercentage m_length_percentage;
     float m_flexible_length { 0 };
     float m_flexible_length { 0 };
 };
 };
 
 

+ 21 - 33
Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp

@@ -21,14 +21,12 @@ CSSPixels GridFormattingContext::resolve_definite_track_size(CSS::GridSize const
 {
 {
     VERIFY(grid_size.is_definite());
     VERIFY(grid_size.is_definite());
     switch (grid_size.type()) {
     switch (grid_size.type()) {
-    case CSS::GridSize::Type::Length:
-        if (grid_size.length().is_auto())
-            break;
-        return grid_size.length().to_px(grid_container());
-    case CSS::GridSize::Type::Percentage:
-        if (available_space.width.is_definite())
-            return grid_size.percentage().as_fraction() * available_space.width.to_px().value();
+    case CSS::GridSize::Type::LengthPercentage: {
+        if (!grid_size.length_percentage().is_auto()) {
+            return grid_size.css_size().to_px(grid_container(), available_space.width.to_px());
+        }
         break;
         break;
+    }
     default:
     default:
         VERIFY_NOT_REACHED();
         VERIFY_NOT_REACHED();
     }
     }
@@ -621,14 +619,11 @@ void GridFormattingContext::initialize_track_sizes(AvailableSize const& availabl
         switch (track.min_track_sizing_function.type()) {
         switch (track.min_track_sizing_function.type()) {
         // - A fixed sizing function
         // - A fixed sizing function
         // Resolve to an absolute length and use that size as the track’s initial base size.
         // Resolve to an absolute length and use that size as the track’s initial base size.
-        case CSS::GridSize::Type::Length: {
-            if (!track.min_track_sizing_function.length().is_auto())
-                track.base_size = track.min_track_sizing_function.length().to_px(grid_container());
-            break;
-        }
-        case CSS::GridSize::Type::Percentage: {
-            if (available_size.is_definite())
-                track.base_size = track.min_track_sizing_function.percentage().as_fraction() * available_size.to_px().value();
+        case CSS::GridSize::Type::LengthPercentage: {
+            if (!track.min_track_sizing_function.is_auto()) {
+                track.base_size = track.min_track_sizing_function.css_size().to_px(grid_container(), available_size.to_px());
+            }
+
             break;
             break;
         }
         }
         // - An intrinsic sizing function
         // - An intrinsic sizing function
@@ -647,18 +642,12 @@ void GridFormattingContext::initialize_track_sizes(AvailableSize const& availabl
         switch (track.max_track_sizing_function.type()) {
         switch (track.max_track_sizing_function.type()) {
         // - A fixed sizing function
         // - A fixed sizing function
         // Resolve to an absolute length and use that size as the track’s initial growth limit.
         // Resolve to an absolute length and use that size as the track’s initial growth limit.
-        case CSS::GridSize::Type::Length: {
-            if (!track.max_track_sizing_function.length().is_auto())
-                track.growth_limit = track.max_track_sizing_function.length().to_px(grid_container());
-            else
-                // - An intrinsic sizing function
-                // Use an initial growth limit of infinity.
+        case CSS::GridSize::Type::LengthPercentage: {
+            if (!track.max_track_sizing_function.is_auto()) {
+                track.growth_limit = track.max_track_sizing_function.css_size().to_px(grid_container(), available_size.to_px());
+            } else {
                 track.growth_limit = INFINITY;
                 track.growth_limit = INFINITY;
-            break;
-        }
-        case CSS::GridSize::Type::Percentage: {
-            if (available_size.is_definite())
-                track.growth_limit = track.max_track_sizing_function.percentage().as_fraction() * available_size.to_px().value();
+            }
             break;
             break;
         }
         }
         // - A flexible sizing function
         // - A flexible sizing function
@@ -766,9 +755,8 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(GridDimension const di
             }
             }
             track.base_size = base_size;
             track.base_size = base_size;
         } break;
         } break;
-        case CSS::GridSize::Type::Length:
-        case CSS::GridSize::Type::Percentage: {
-            if (track.min_track_sizing_function.length().is_auto() && available_size.is_intrinsic_sizing_constraint()) {
+        case CSS::GridSize::Type::LengthPercentage: {
+            if (track.min_track_sizing_function.is_auto() && available_size.is_intrinsic_sizing_constraint()) {
                 // If the track has an auto min track sizing function and the grid container is being sized under a
                 // If the track has an auto min track sizing function and the grid container is being sized under a
                 // min-/max-content constraint, set the track’s base size to the maximum of its items’ limited
                 // min-/max-content constraint, set the track’s base size to the maximum of its items’ limited
                 // min-/max-content contributions (respectively), floored at zero. The limited min-/max-content
                 // min-/max-content contributions (respectively), floored at zero. The limited min-/max-content
@@ -823,7 +811,7 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(GridDimension const di
                 growth_limit = max(growth_limit, calculate_item_min_content_contribution(item));
                 growth_limit = max(growth_limit, calculate_item_min_content_contribution(item));
             }
             }
             track.growth_limit = growth_limit;
             track.growth_limit = growth_limit;
-        } else if (max_track_sizing_function.is_max_content() || (max_track_sizing_function.is_length() && max_track_sizing_function.length().is_auto())) {
+        } else if (max_track_sizing_function.is_max_content() || max_track_sizing_function.is_auto()) {
             // If the track has a max-content max track sizing function, set its growth limit to the maximum of
             // If the track has a max-content max track sizing function, set its growth limit to the maximum of
             // the items’ max-content contributions. For fit-content() maximums, furthermore clamp this growth
             // the items’ max-content contributions. For fit-content() maximums, furthermore clamp this growth
             // limit by the fit-content() argument.
             // limit by the fit-content() argument.
@@ -1142,19 +1130,19 @@ void GridFormattingContext::stretch_auto_tracks(AvailableSize const& available_s
     // step instead.
     // step instead.
     CSSPixels used_space = 0;
     CSSPixels used_space = 0;
     for (auto& track : tracks) {
     for (auto& track : tracks) {
-        if (!(track.max_track_sizing_function.is_length() && track.max_track_sizing_function.length().is_auto()))
+        if (!track.max_track_sizing_function.is_auto())
             used_space += track.base_size;
             used_space += track.base_size;
     }
     }
 
 
     CSSPixels remaining_space = available_size.is_definite() ? available_size.to_px() - used_space : 0;
     CSSPixels remaining_space = available_size.is_definite() ? available_size.to_px() - used_space : 0;
     auto count_of_auto_max_sizing_tracks = 0;
     auto count_of_auto_max_sizing_tracks = 0;
     for (auto& track : tracks) {
     for (auto& track : tracks) {
-        if (track.max_track_sizing_function.is_length() && track.max_track_sizing_function.length().is_auto())
+        if (track.max_track_sizing_function.is_auto())
             count_of_auto_max_sizing_tracks++;
             count_of_auto_max_sizing_tracks++;
     }
     }
 
 
     for (auto& track : tracks) {
     for (auto& track : tracks) {
-        if (track.max_track_sizing_function.is_length() && track.max_track_sizing_function.length().is_auto())
+        if (track.max_track_sizing_function.is_auto())
             track.base_size = max(track.base_size, remaining_space / count_of_auto_max_sizing_tracks);
             track.base_size = max(track.base_size, remaining_space / count_of_auto_max_sizing_tracks);
     }
     }
 }
 }