/* * 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; class CSSMathValue : public CSSStyleValue { public: enum class ResolvedType { Angle, Flex, Frequency, Integer, Length, Number, Percentage, Resolution, 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, 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(); Value const& value() const { return m_value; } ResolvedType resolved_type() const; [[nodiscard]] bool operator==(CalculationResult const&) const = default; private: void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Optional, PercentageBasis const& percentage_basis); Value m_value; }; static ValueComparingNonnullRefPtr create(NonnullOwnPtr calculation, CSSNumericType resolved_type) { return adopt_ref(*new (nothrow) CSSMathValue(move(calculation), resolved_type)); } String to_string() const override; virtual bool equals(CSSStyleValue const& other) const override; 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(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(); } Optional resolve_flex() const; 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.matches_length(); } bool resolves_to_length_percentage() const { return m_resolved_type.matches_length_percentage(); } 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(); } Optional resolve_resolution() const; 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