/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Tobias Christiansen * Copyright (c) 2021-2023, Sam Atkins * Copyright (c) 2022-2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include namespace Web::CSS { class CalculatedStyleValue : public StyleValue { public: enum class ResolvedType { Angle, Frequency, Integer, Length, Number, Percentage, Time, }; enum class SumOperation { Add, Subtract, }; enum class ProductOperation { Multiply, Divide, }; using PercentageBasis = Variant; class CalculationResult { public: using Value = Variant; CalculationResult(Value value) : m_value(move(value)) { } void add(CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis); void subtract(CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis); void multiply_by(CalculationResult const& other, Layout::Node const*); void divide_by(CalculationResult const& other, Layout::Node const*); Value const& value() const { return m_value; } private: void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis); Value m_value; }; struct CalcSum; struct CalcSumPartWithOperator; struct CalcProduct; struct CalcProductPartWithOperator; struct CalcNumberSum; struct CalcNumberSumPartWithOperator; struct CalcNumberProduct; struct CalcNumberProductPartWithOperator; struct CalcNumberValue { Variant> value; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; }; struct CalcValue { Variant> value; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; bool contains_percentage() const; }; // This represents that: https://www.w3.org/TR/css-values-3/#calc-syntax struct CalcSum { CalcSum(NonnullOwnPtr first_calc_product, Vector> additional) : first_calc_product(move(first_calc_product)) , zero_or_more_additional_calc_products(move(additional)) {}; NonnullOwnPtr first_calc_product; Vector> zero_or_more_additional_calc_products; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; bool contains_percentage() const; }; struct CalcNumberSum { CalcNumberSum(NonnullOwnPtr first_calc_number_product, Vector> additional) : first_calc_number_product(move(first_calc_number_product)) , zero_or_more_additional_calc_number_products(move(additional)) {}; NonnullOwnPtr first_calc_number_product; Vector> zero_or_more_additional_calc_number_products; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; }; struct CalcProduct { CalcValue first_calc_value; Vector> zero_or_more_additional_calc_values; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; bool contains_percentage() const; }; struct CalcSumPartWithOperator { CalcSumPartWithOperator(SumOperation op, NonnullOwnPtr calc_product) : op(op) , value(move(calc_product)) {}; SumOperation op; NonnullOwnPtr value; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; bool contains_percentage() const; }; struct CalcProductPartWithOperator { ProductOperation op; Variant value; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; bool contains_percentage() const; }; struct CalcNumberProduct { CalcNumberValue first_calc_number_value; Vector> zero_or_more_additional_calc_number_values; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; }; struct CalcNumberProductPartWithOperator { ProductOperation op; CalcNumberValue value; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; }; struct CalcNumberSumPartWithOperator { CalcNumberSumPartWithOperator(SumOperation op, NonnullOwnPtr calc_number_product) : op(op) , value(move(calc_number_product)) {}; SumOperation op; NonnullOwnPtr value; ErrorOr to_string() const; Optional resolved_type() const; CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const; }; static ValueComparingNonnullRefPtr create(NonnullOwnPtr calc_sum, ResolvedType resolved_type) { return adopt_ref(*new CalculatedStyleValue(move(calc_sum), resolved_type)); } ErrorOr to_string() const override; virtual bool equals(StyleValue const& other) const override; ResolvedType resolved_type() const { return m_resolved_type; } NonnullOwnPtr const& expression() const { return m_expression; } bool resolves_to_angle() const { return m_resolved_type == ResolvedType::Angle; } Optional resolve_angle() const; Optional resolve_angle_percentage(Angle const& percentage_basis) const; bool resolves_to_frequency() const { return m_resolved_type == ResolvedType::Frequency; } Optional resolve_frequency() const; Optional resolve_frequency_percentage(Frequency const& percentage_basis) const; bool resolves_to_length() const { return m_resolved_type == ResolvedType::Length; } 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; } Optional resolve_percentage() const; bool resolves_to_time() const { return m_resolved_type == ResolvedType::Time; } Optional