diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 9fbde739a3..0acbb61dac 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -3407,32 +3407,12 @@ ErrorOr> Parser::parse_calculated_value(Vectorresolved_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> 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::parse_css_value_for_properties(Readonl } return {}; }; + auto any_property_accepts_type_percentage = [](ReadonlySpan property_ids, ValueType value_type) -> Optional { + 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 property_ids, ValueID identifier) -> Optional { for (auto const& property : property_ids) { if (property_accepts_identifier(property, identifier)) @@ -8416,34 +8403,41 @@ ErrorOr 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 }; } } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index c794fa2902..b130816090 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -820,7 +820,7 @@ bool StyleComputer::expand_variables(DOM::Element& element, Optional 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; } } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index 1ac07b7c94..5ebf433559 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/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(value.as_calculated()).resolve_number(); if (maybe_number.has_value()) unclamped_opacity = maybe_number.value(); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h index e715a96d37..e56de48f8f 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h @@ -65,51 +65,54 @@ public: Value m_value; }; - static ErrorOr> create(NonnullOwnPtr calculation, ResolvedType resolved_type) + static ErrorOr> create(NonnullOwnPtr calculation, CSSNumericType resolved_type) { return adopt_nonnull_ref_or_enomem(new (nothrow) CalculatedStyleValue(move(calculation), resolved_type)); } ErrorOr 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 resolve_angle() const; Optional 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 resolve_frequency() const; Optional 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 resolve_length(Length::ResolutionContext const&) const; Optional resolve_length(Layout::Node const& layout_node) const; Optional 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 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