瀏覽代碼

LibWeb: Use CSSNumericType for CalculatedStyleValue resolved type

Sam Atkins 2 年之前
父節點
當前提交
f21a30e45f

+ 32 - 38
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -3407,32 +3407,12 @@ ErrorOr<RefPtr<CalculatedStyleValue>> Parser::parse_calculated_value(Vector<Comp
         }
     }
 
-    auto calc_type = calculation_tree->resolved_type();
+    auto calc_type = calculation_tree->determine_type(m_context.current_property_id());
     if (!calc_type.has_value()) {
         dbgln_if(CSS_PARSER_DEBUG, "calc() resolved as invalid!!!");
         return nullptr;
     }
-
-    [[maybe_unused]] auto to_string = [](CalculatedStyleValue::ResolvedType type) {
-        switch (type) {
-        case CalculatedStyleValue::ResolvedType::Angle:
-            return "Angle"sv;
-        case CalculatedStyleValue::ResolvedType::Frequency:
-            return "Frequency"sv;
-        case CalculatedStyleValue::ResolvedType::Integer:
-            return "Integer"sv;
-        case CalculatedStyleValue::ResolvedType::Length:
-            return "Length"sv;
-        case CalculatedStyleValue::ResolvedType::Number:
-            return "Number"sv;
-        case CalculatedStyleValue::ResolvedType::Percentage:
-            return "Percentage"sv;
-        case CalculatedStyleValue::ResolvedType::Time:
-            return "Time"sv;
-        }
-        VERIFY_NOT_REACHED();
-    };
-    dbgln_if(CSS_PARSER_DEBUG, "Deduced calc() resolved type as: {}", to_string(calc_type.value()));
+    dbgln_if(CSS_PARSER_DEBUG, "Deduced calc() resolved type as: {}", calc_type->dump());
 
     return CalculatedStyleValue::create(calculation_tree.release_nonnull(), calc_type.release_value());
 }
@@ -4127,7 +4107,7 @@ ErrorOr<RefPtr<StyleValue>> Parser::parse_dynamic_value(ComponentValue const& co
         if (!function_node)
             return nullptr;
 
-        auto function_type = function_node->resolved_type();
+        auto function_type = function_node->determine_type(m_context.current_property_id());
         if (!function_type.has_value())
             return nullptr;
 
@@ -8266,6 +8246,13 @@ ErrorOr<Parser::PropertyAndValue> Parser::parse_css_value_for_properties(Readonl
         }
         return {};
     };
+    auto any_property_accepts_type_percentage = [](ReadonlySpan<PropertyID> property_ids, ValueType value_type) -> Optional<PropertyID> {
+        for (auto const& property : property_ids) {
+            if (property_accepts_type(property, value_type) && property_accepts_type(property, ValueType::Percentage))
+                return property;
+        }
+        return {};
+    };
     auto any_property_accepts_identifier = [](ReadonlySpan<PropertyID> property_ids, ValueID identifier) -> Optional<PropertyID> {
         for (auto const& property : property_ids) {
             if (property_accepts_identifier(property, identifier))
@@ -8416,34 +8403,41 @@ ErrorOr<Parser::PropertyAndValue> Parser::parse_css_value_for_properties(Readonl
         if (auto maybe_dynamic = TRY(parse_dynamic_value(peek_token)); maybe_dynamic && maybe_dynamic->is_calculated()) {
             (void)tokens.next_token();
             auto& calculated = maybe_dynamic->as_calculated();
-            switch (calculated.resolved_type()) {
-            case CalculatedStyleValue::ResolvedType::Angle:
+            if (calculated.resolves_to_angle_percentage()) {
+                if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Angle); property.has_value())
+                    return PropertyAndValue { *property, calculated };
+            } else if (calculated.resolves_to_angle()) {
                 if (auto property = any_property_accepts_type(property_ids, ValueType::Angle); property.has_value())
                     return PropertyAndValue { *property, calculated };
-                break;
-            case CalculatedStyleValue::ResolvedType::Frequency:
+            } else if (calculated.resolves_to_frequency_percentage()) {
+                if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Frequency); property.has_value())
+                    return PropertyAndValue { *property, calculated };
+            } else if (calculated.resolves_to_frequency()) {
                 if (auto property = any_property_accepts_type(property_ids, ValueType::Frequency); property.has_value())
                     return PropertyAndValue { *property, calculated };
-                break;
-            case CalculatedStyleValue::ResolvedType::Integer:
-            case CalculatedStyleValue::ResolvedType::Number:
+            } else if (calculated.resolves_to_number_percentage()) {
+                if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Number); property.has_value())
+                    return PropertyAndValue { *property, calculated };
+            } else if (calculated.resolves_to_number()) {
                 if (property_accepts_numeric) {
                     auto property_or_resolved = property_accepting_integer.value_or_lazy_evaluated([property_accepting_number]() { return property_accepting_number.value(); });
                     return PropertyAndValue { property_or_resolved, calculated };
                 }
-                break;
-            case CalculatedStyleValue::ResolvedType::Length:
+            } else if (calculated.resolves_to_length_percentage()) {
+                if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Length); property.has_value())
+                    return PropertyAndValue { *property, calculated };
+            } else if (calculated.resolves_to_length()) {
                 if (auto property = any_property_accepts_type(property_ids, ValueType::Length); property.has_value())
                     return PropertyAndValue { *property, calculated };
-                break;
-            case CalculatedStyleValue::ResolvedType::Percentage:
-                if (auto property = any_property_accepts_type(property_ids, ValueType::Percentage); property.has_value())
+            } else if (calculated.resolves_to_time_percentage()) {
+                if (auto property = any_property_accepts_type_percentage(property_ids, ValueType::Time); property.has_value())
                     return PropertyAndValue { *property, calculated };
-                break;
-            case CalculatedStyleValue::ResolvedType::Time:
+            } else if (calculated.resolves_to_time()) {
                 if (auto property = any_property_accepts_type(property_ids, ValueType::Time); property.has_value())
                     return PropertyAndValue { *property, calculated };
-                break;
+            } else if (calculated.resolves_to_percentage()) {
+                if (auto property = any_property_accepts_type(property_ids, ValueType::Percentage); property.has_value())
+                    return PropertyAndValue { *property, calculated };
             }
         }
     }

+ 6 - 9
Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

@@ -820,7 +820,7 @@ bool StyleComputer::expand_variables(DOM::Element& element, Optional<CSS::Select
 {
     // Arbitrary large value chosen to avoid the billion-laughs attack.
     // https://www.w3.org/TR/css-variables-1/#long-variables
-    const size_t MAX_VALUE_COUNT = 16384;
+    size_t const MAX_VALUE_COUNT = 16384;
     if (source.remaining_token_count() + dest.size() > MAX_VALUE_COUNT) {
         dbgln("Stopped expanding CSS variables: maximum length reached.");
         return false;
@@ -952,23 +952,20 @@ bool StyleComputer::expand_unresolved_values(DOM::Element& element, StringView p
                 return false;
             }
 
+            // FIXME: Handle all math functions.
             if (value.function().name().equals_ignoring_ascii_case("calc"sv)) {
                 auto const& calc_function = value.function();
                 if (auto calc_value = Parser::Parser::parse_calculated_value({}, Parser::ParsingContext { document() }, calc_function.values()).release_value_but_fixme_should_propagate_errors()) {
-                    switch (calc_value->resolved_type()) {
-                    case CalculatedStyleValue::ResolvedType::Integer: {
-                        auto resolved_value = calc_value->resolve_integer();
+                    if (calc_value->resolves_to_number()) {
+                        auto resolved_value = calc_value->resolve_number();
                         dest.empend(Parser::Token::create_number(resolved_value.value()));
                         continue;
-                    }
-                    case CalculatedStyleValue::ResolvedType::Percentage: {
+                    } else if (calc_value->resolves_to_percentage()) {
                         auto resolved_value = calc_value->resolve_percentage();
                         dest.empend(Parser::Token::create_percentage(resolved_value.value().value()));
                         continue;
-                    }
-                    default:
+                    } else {
                         dbgln_if(LIBWEB_CSS_DEBUG, "FIXME: Unimplemented calc() expansion: {}", calc_value->to_string());
-                        break;
                     }
                 }
             }

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

@@ -265,13 +265,13 @@ static float resolve_opacity_value(CSS::StyleValue const& value)
         unclamped_opacity = value.as_number().number();
     } else if (value.is_calculated()) {
         auto& calculated = value.as_calculated();
-        if (calculated.resolved_type() == CalculatedStyleValue::ResolvedType::Percentage) {
+        if (calculated.resolves_to_percentage()) {
             auto maybe_percentage = value.as_calculated().resolve_percentage();
             if (maybe_percentage.has_value())
                 unclamped_opacity = maybe_percentage->as_fraction();
             else
                 dbgln("Unable to resolve calc() as opacity (percentage): {}", value.to_string());
-        } else {
+        } else if (calculated.resolves_to_number()) {
             auto maybe_number = const_cast<CalculatedStyleValue&>(value.as_calculated()).resolve_number();
             if (maybe_number.has_value())
                 unclamped_opacity = maybe_number.value();

+ 14 - 11
Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h

@@ -65,51 +65,54 @@ public:
         Value m_value;
     };
 
-    static ErrorOr<ValueComparingNonnullRefPtr<CalculatedStyleValue>> create(NonnullOwnPtr<CalculationNode> calculation, ResolvedType resolved_type)
+    static ErrorOr<ValueComparingNonnullRefPtr<CalculatedStyleValue>> create(NonnullOwnPtr<CalculationNode> calculation, CSSNumericType resolved_type)
     {
         return adopt_nonnull_ref_or_enomem(new (nothrow) CalculatedStyleValue(move(calculation), resolved_type));
     }
 
     ErrorOr<String> to_string() const override;
     virtual bool equals(StyleValue const& other) const override;
-    ResolvedType resolved_type() const { return m_resolved_type; }
 
-    bool resolves_to_angle() const { return m_resolved_type == ResolvedType::Angle; }
+    bool resolves_to_angle() const { return m_resolved_type.matches_angle(); }
+    bool resolves_to_angle_percentage() const { return m_resolved_type.matches_angle_percentage(); }
     Optional<Angle> resolve_angle() const;
     Optional<Angle> resolve_angle_percentage(Angle const& percentage_basis) const;
 
-    bool resolves_to_frequency() const { return m_resolved_type == ResolvedType::Frequency; }
+    bool resolves_to_frequency() const { return m_resolved_type.matches_frequency(); }
+    bool resolves_to_frequency_percentage() const { return m_resolved_type.matches_frequency_percentage(); }
     Optional<Frequency> resolve_frequency() const;
     Optional<Frequency> resolve_frequency_percentage(Frequency const& percentage_basis) const;
 
-    bool resolves_to_length() const { return m_resolved_type == ResolvedType::Length; }
+    bool resolves_to_length() const { return m_resolved_type.matches_length(); }
+    bool resolves_to_length_percentage() const { return m_resolved_type.matches_length_percentage(); }
     [[nodiscard]] Optional<Length> resolve_length(Length::ResolutionContext const&) const;
     Optional<Length> resolve_length(Layout::Node const& layout_node) const;
     Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
 
-    bool resolves_to_percentage() const { return m_resolved_type == ResolvedType::Percentage; }
+    bool resolves_to_percentage() const { return m_resolved_type.matches_percentage(); }
     Optional<Percentage> resolve_percentage() const;
 
-    bool resolves_to_time() const { return m_resolved_type == ResolvedType::Time; }
+    bool resolves_to_time() const { return m_resolved_type.matches_time(); }
+    bool resolves_to_time_percentage() const { return m_resolved_type.matches_time_percentage(); }
     Optional<Time> resolve_time() const;
     Optional<Time> resolve_time_percentage(Time const& percentage_basis) const;
 
-    bool resolves_to_integer() const { return m_resolved_type == ResolvedType::Integer; }
-    bool resolves_to_number() const { return resolves_to_integer() || m_resolved_type == ResolvedType::Number; }
+    bool resolves_to_number() const { return m_resolved_type.matches_number(); }
+    bool resolves_to_number_percentage() const { return m_resolved_type.matches_number_percentage(); }
     Optional<double> resolve_number() const;
     Optional<i64> resolve_integer();
 
     bool contains_percentage() const;
 
 private:
-    explicit CalculatedStyleValue(NonnullOwnPtr<CalculationNode> calculation, ResolvedType resolved_type)
+    explicit CalculatedStyleValue(NonnullOwnPtr<CalculationNode> calculation, CSSNumericType resolved_type)
         : StyleValue(Type::Calculated)
         , m_resolved_type(resolved_type)
         , m_calculation(move(calculation))
     {
     }
 
-    ResolvedType m_resolved_type;
+    CSSNumericType m_resolved_type;
     NonnullOwnPtr<CalculationNode> m_calculation;
 };