/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Tobias Christiansen * Copyright (c) 2021-2025, Sam Atkins * Copyright (c) 2022-2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace Web::CSS { class CalculationNode; // https://drafts.csswg.org/css-values-4/#ref-for-calc-calculation%E2%91%A2%E2%91%A7 // Contains the context available at parse-time. struct CalculationContext { Optional percentages_resolve_as {}; bool resolve_numbers_as_integers = false; }; // Contains the context for resolving the calculation. struct CalculationResolutionContext { Variant percentage_basis {}; Optional length_resolution_context; }; class CalculatedStyleValue : public CSSStyleValue { public: class CalculationResult { public: using Value = Variant; static CalculationResult from_value(Value const&, CalculationResolutionContext const&, Optional); CalculationResult(double value, Optional type) : m_value(value) , m_type(move(type)) { } void add(CalculationResult const& other); void subtract(CalculationResult const& other); void multiply_by(CalculationResult const& other); void divide_by(CalculationResult const& other); void negate(); void invert(); double value() const { return m_value; } Optional const& type() const { return m_type; } [[nodiscard]] bool operator==(CalculationResult const&) const = default; private: double m_value; Optional m_type; }; static ValueComparingNonnullRefPtr create(NonnullRefPtr calculation, CSSNumericType resolved_type, CalculationContext context) { return adopt_ref(*new (nothrow) CalculatedStyleValue(move(calculation), move(resolved_type), move(context))); } virtual String to_string(SerializationMode) const override; virtual bool equals(CSSStyleValue const& other) const override; bool resolves_to_angle() const { return m_resolved_type.matches_angle(m_context.percentages_resolve_as); } bool resolves_to_angle_percentage() const { return m_resolved_type.matches_angle_percentage(m_context.percentages_resolve_as); } Optional resolve_angle(CalculationResolutionContext const&) const; bool resolves_to_flex() const { return m_resolved_type.matches_flex(m_context.percentages_resolve_as); } Optional resolve_flex(CalculationResolutionContext const&) const; bool resolves_to_frequency() const { return m_resolved_type.matches_frequency(m_context.percentages_resolve_as); } bool resolves_to_frequency_percentage() const { return m_resolved_type.matches_frequency_percentage(m_context.percentages_resolve_as); } Optional resolve_frequency(CalculationResolutionContext const&) const; bool resolves_to_length() const { return m_resolved_type.matches_length(m_context.percentages_resolve_as); } bool resolves_to_length_percentage() const { return m_resolved_type.matches_length_percentage(m_context.percentages_resolve_as); } Optional resolve_length(CalculationResolutionContext const&) const; bool resolves_to_percentage() const { return m_resolved_type.matches_percentage(); } Optional resolve_percentage(CalculationResolutionContext const&) const; bool resolves_to_resolution() const { return m_resolved_type.matches_resolution(m_context.percentages_resolve_as); } Optional resolve_resolution(CalculationResolutionContext const&) const; bool resolves_to_time() const { return m_resolved_type.matches_time(m_context.percentages_resolve_as); } bool resolves_to_time_percentage() const { return m_resolved_type.matches_time_percentage(m_context.percentages_resolve_as); } Optional