CalculatedOr.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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/CalculatedStyleValue.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<CalculatedStyleValue> calculated)
  25. : m_value(move(calculated))
  26. {
  27. }
  28. virtual ~CalculatedOr() = default;
  29. bool is_calculated() const { return m_value.template has<NonnullRefPtr<CalculatedStyleValue>>(); }
  30. T const& value() const
  31. {
  32. VERIFY(!is_calculated());
  33. return m_value.template get<T>();
  34. }
  35. NonnullRefPtr<StyleValue> as_style_value() const
  36. {
  37. if (is_calculated())
  38. return calculated();
  39. return create_style_value();
  40. }
  41. NonnullRefPtr<CalculatedStyleValue> const& calculated() const
  42. {
  43. VERIFY(is_calculated());
  44. return m_value.template get<NonnullRefPtr<CalculatedStyleValue>>();
  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<CalculatedStyleValue> 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<CalculatedStyleValue>>()->to_string();
  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<CalculatedStyleValue> const&, Layout::Node const&) const = 0;
  70. virtual NonnullRefPtr<StyleValue> create_style_value() const = 0;
  71. private:
  72. Variant<T, NonnullRefPtr<CalculatedStyleValue>> m_value;
  73. };
  74. class AngleOrCalculated : public CalculatedOr<Angle> {
  75. public:
  76. using CalculatedOr<Angle>::CalculatedOr;
  77. private:
  78. virtual Angle resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
  79. virtual NonnullRefPtr<StyleValue> 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<CalculatedStyleValue> const&, Layout::Node const&) const override;
  86. virtual NonnullRefPtr<StyleValue> 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<CalculatedStyleValue> const&, Layout::Node const&) const override;
  93. virtual NonnullRefPtr<StyleValue> create_style_value() const override;
  94. };
  95. class IntegerOrCalculated : public CalculatedOr<i64> {
  96. public:
  97. using CalculatedOr<i64>::CalculatedOr;
  98. private:
  99. virtual i64 resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
  100. virtual NonnullRefPtr<StyleValue> create_style_value() const override;
  101. };
  102. class LengthOrCalculated : public CalculatedOr<Length> {
  103. public:
  104. using CalculatedOr<Length>::CalculatedOr;
  105. [[nodiscard]] Length resolved(Length::ResolutionContext const&) const;
  106. private:
  107. virtual Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
  108. virtual NonnullRefPtr<StyleValue> create_style_value() const override;
  109. };
  110. class NumberOrCalculated : public CalculatedOr<double> {
  111. public:
  112. using CalculatedOr<double>::CalculatedOr;
  113. private:
  114. virtual double resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
  115. virtual NonnullRefPtr<StyleValue> create_style_value() const override;
  116. };
  117. class PercentageOrCalculated : public CalculatedOr<Percentage> {
  118. public:
  119. using CalculatedOr<Percentage>::CalculatedOr;
  120. private:
  121. virtual Percentage resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
  122. virtual NonnullRefPtr<StyleValue> create_style_value() const override;
  123. };
  124. class ResolutionOrCalculated : public CalculatedOr<Resolution> {
  125. public:
  126. using CalculatedOr<Resolution>::CalculatedOr;
  127. private:
  128. virtual Resolution resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
  129. virtual NonnullRefPtr<StyleValue> create_style_value() const override;
  130. };
  131. class TimeOrCalculated : public CalculatedOr<Time> {
  132. public:
  133. using CalculatedOr<Time>::CalculatedOr;
  134. private:
  135. virtual Time resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
  136. virtual NonnullRefPtr<StyleValue> create_style_value() const override;
  137. };
  138. }
  139. template<>
  140. struct AK::Formatter<Web::CSS::AngleOrCalculated> : Formatter<StringView> {
  141. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::AngleOrCalculated const& calculated_or)
  142. {
  143. return Formatter<StringView>::format(builder, calculated_or.to_string());
  144. }
  145. };
  146. template<>
  147. struct AK::Formatter<Web::CSS::FrequencyOrCalculated> : Formatter<StringView> {
  148. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::FrequencyOrCalculated const& calculated_or)
  149. {
  150. return Formatter<StringView>::format(builder, calculated_or.to_string());
  151. }
  152. };
  153. template<>
  154. struct AK::Formatter<Web::CSS::LengthOrCalculated> : Formatter<StringView> {
  155. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthOrCalculated const& calculated_or)
  156. {
  157. return Formatter<StringView>::format(builder, calculated_or.to_string());
  158. }
  159. };
  160. template<>
  161. struct AK::Formatter<Web::CSS::PercentageOrCalculated> : Formatter<StringView> {
  162. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::PercentageOrCalculated const& calculated_or)
  163. {
  164. return Formatter<StringView>::format(builder, calculated_or.to_string());
  165. }
  166. };
  167. template<>
  168. struct AK::Formatter<Web::CSS::TimeOrCalculated> : Formatter<StringView> {
  169. ErrorOr<void> format(FormatBuilder& builder, Web::CSS::TimeOrCalculated const& calculated_or)
  170. {
  171. return Formatter<StringView>::format(builder, calculated_or.to_string());
  172. }
  173. };