CalculatedOr.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Variant.h>
  8. #include <LibWeb/CSS/Angle.h>
  9. #include <LibWeb/CSS/Flex.h>
  10. #include <LibWeb/CSS/Frequency.h>
  11. #include <LibWeb/CSS/Length.h>
  12. #include <LibWeb/CSS/Percentage.h>
  13. #include <LibWeb/CSS/Resolution.h>
  14. #include <LibWeb/CSS/StyleValues/CSSMathValue.h>
  15. #include <LibWeb/CSS/Time.h>
  16. namespace Web::CSS {
  17. template<typename T>
  18. class CalculatedOr {
  19. public:
  20. CalculatedOr(T t)
  21. : m_value(move(t))
  22. {
  23. }
  24. CalculatedOr(NonnullRefPtr<CSSMathValue> calculated)
  25. : m_value(move(calculated))
  26. {
  27. }
  28. virtual ~CalculatedOr() = default;
  29. bool is_calculated() const { return m_value.template has<NonnullRefPtr<CSSMathValue>>(); }
  30. T const& value() const
  31. {
  32. VERIFY(!is_calculated());
  33. return m_value.template get<T>();
  34. }
  35. NonnullRefPtr<CSSStyleValue> as_style_value() const
  36. {
  37. if (is_calculated())
  38. return calculated();
  39. return create_style_value();
  40. }
  41. NonnullRefPtr<CSSMathValue> const& calculated() const
  42. {
  43. VERIFY(is_calculated());
  44. return m_value.template get<NonnullRefPtr<CSSMathValue>>();
  45. }
  46. T resolved(Layout::Node const& layout_node) const
  47. {
  48. return m_value.visit(
  49. [&](T const& t) {
  50. return t;
  51. },
  52. [&](NonnullRefPtr<CSSMathValue> const& calculated) {
  53. return resolve_calculated(calculated, layout_node);
  54. });
  55. }
  56. String to_string() const
  57. {
  58. if (is_calculated())
  59. return m_value.template get<NonnullRefPtr<CSSMathValue>>()->to_string(Web::CSS::CSSStyleValue::SerializationMode::Normal);
  60. return m_value.template get<T>().to_string();
  61. }
  62. bool operator==(CalculatedOr<T> const& other) const
  63. {
  64. if (is_calculated() || other.is_calculated())
  65. return false;
  66. return (m_value.template get<T>() == other.m_value.template get<T>());
  67. }
  68. protected:
  69. virtual T resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const = 0;
  70. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const = 0;
  71. private:
  72. Variant<T, NonnullRefPtr<CSSMathValue>> m_value;
  73. };
  74. class AngleOrCalculated : public CalculatedOr<Angle> {
  75. public:
  76. using CalculatedOr<Angle>::CalculatedOr;
  77. private:
  78. virtual Angle resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  79. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  80. };
  81. class FlexOrCalculated : public CalculatedOr<Flex> {
  82. public:
  83. using CalculatedOr<Flex>::CalculatedOr;
  84. private:
  85. virtual Flex resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  86. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  87. };
  88. class FrequencyOrCalculated : public CalculatedOr<Frequency> {
  89. public:
  90. using CalculatedOr<Frequency>::CalculatedOr;
  91. private:
  92. virtual Frequency resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  93. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  94. };
  95. class IntegerOrCalculated : public CalculatedOr<i64> {
  96. public:
  97. using CalculatedOr<i64>::CalculatedOr;
  98. [[nodiscard]] i64 resolved(Length::ResolutionContext const&) const;
  99. private:
  100. virtual i64 resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  101. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  102. };
  103. class LengthOrCalculated : public CalculatedOr<Length> {
  104. public:
  105. using CalculatedOr<Length>::CalculatedOr;
  106. [[nodiscard]] Length resolved(Length::ResolutionContext const&) const;
  107. private:
  108. virtual Length resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  109. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  110. };
  111. class NumberOrCalculated : public CalculatedOr<double> {
  112. public:
  113. using CalculatedOr<double>::CalculatedOr;
  114. private:
  115. virtual double resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  116. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  117. };
  118. class PercentageOrCalculated : public CalculatedOr<Percentage> {
  119. public:
  120. using CalculatedOr<Percentage>::CalculatedOr;
  121. private:
  122. virtual Percentage resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  123. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  124. };
  125. class ResolutionOrCalculated : public CalculatedOr<Resolution> {
  126. public:
  127. using CalculatedOr<Resolution>::CalculatedOr;
  128. [[nodiscard]] Resolution resolved() const;
  129. private:
  130. virtual Resolution resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  131. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  132. };
  133. class TimeOrCalculated : public CalculatedOr<Time> {
  134. public:
  135. using CalculatedOr<Time>::CalculatedOr;
  136. private:
  137. virtual Time resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
  138. virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
  139. };
  140. }
  141. template<>
  142. struct AK::Formatter<Web::CSS::AngleOrCalculated> : Formatter<StringView> {
  143. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::AngleOrCalculated const& calculated_or)
  144. {
  145. return Formatter<StringView>::format(builder, calculated_or.to_string());
  146. }
  147. };
  148. template<>
  149. struct AK::Formatter<Web::CSS::FrequencyOrCalculated> : Formatter<StringView> {
  150. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::FrequencyOrCalculated const& calculated_or)
  151. {
  152. return Formatter<StringView>::format(builder, calculated_or.to_string());
  153. }
  154. };
  155. template<>
  156. struct AK::Formatter<Web::CSS::LengthOrCalculated> : Formatter<StringView> {
  157. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthOrCalculated const& calculated_or)
  158. {
  159. return Formatter<StringView>::format(builder, calculated_or.to_string());
  160. }
  161. };
  162. template<>
  163. struct AK::Formatter<Web::CSS::PercentageOrCalculated> : Formatter<StringView> {
  164. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::PercentageOrCalculated const& calculated_or)
  165. {
  166. return Formatter<StringView>::format(builder, calculated_or.to_string());
  167. }
  168. };
  169. template<>
  170. struct AK::Formatter<Web::CSS::TimeOrCalculated> : Formatter<StringView> {
  171. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::TimeOrCalculated const& calculated_or)
  172. {
  173. return Formatter<StringView>::format(builder, calculated_or.to_string());
  174. }
  175. };