/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Tobias Christiansen * Copyright (c) 2021-2024, 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 struct CalculationContext { Optional percentages_resolve_as {}; }; class CalculatedStyleValue : public CSSStyleValue { public: using PercentageBasis = Variant; class CalculationResult { public: using Value = Variant; static CalculationResult from_value(Value const&, Optional, Optional); CalculationResult(double value, Optional type) : m_value(value) , m_type(move(type)) { } void add(CalculationResult const& other, Optional, PercentageBasis const& percentage_basis); void subtract(CalculationResult const& other, Optional, PercentageBasis const& percentage_basis); void multiply_by(CalculationResult const& other, Optional); void divide_by(CalculationResult const& other, Optional); 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(NonnullOwnPtr 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() const; Optional resolve_angle(Layout::Node const& layout_node) const; Optional resolve_angle(Length::ResolutionContext const& context) const; Optional resolve_angle_percentage(Angle const& percentage_basis) const; bool resolves_to_flex() const { return m_resolved_type.matches_flex(m_context.percentages_resolve_as); } Optional resolve_flex() 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() const; Optional resolve_frequency_percentage(Frequency const& percentage_basis) 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(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; Optional resolve_length_percentage(Layout::Node const&, CSSPixels percentage_basis) const; Optional resolve_length_percentage(Length::ResolutionContext const&, Length const& percentage_basis) const; bool resolves_to_percentage() const { return m_resolved_type.matches_percentage(); } Optional resolve_percentage() const; bool resolves_to_resolution() const { return m_resolved_type.matches_resolution(m_context.percentages_resolve_as); } Optional resolve_resolution() 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