summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2023-03-30 16:57:49 +0100
committerAndreas Kling <kling@serenityos.org>2023-03-30 21:29:50 +0200
commitfa90a3bb4fc3e4a8a0caa0b80a7ac87765ab67f9 (patch)
tree2d6acd146dcc1107c56d6a28d2da6d69ddde1f3b /Userland
parentb727f8113f9280e64e18dcbb0ed2921b19e51083 (diff)
downloadserenity-fa90a3bb4fc3e4a8a0caa0b80a7ac87765ab67f9.zip
LibWeb: Introduce CalculatedOr type
This is intended as a replacement for Length and friends each holding a `RefPtr<CalculatedStyleValue>`. Instead, let's make the types explicit about whether they are calculated or not. This then means a Length is always a Length, and won't require including `StyleValue.h`. As noted, it's probably nicer for LengthOrCalculated to live in `Length.h`, but we can't do that until Length stops including `StyleValue.h`.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibWeb/CSS/CalculatedOr.cpp36
-rw-r--r--Userland/Libraries/LibWeb/CSS/CalculatedOr.h155
-rw-r--r--Userland/Libraries/LibWeb/CSS/Percentage.h13
-rw-r--r--Userland/Libraries/LibWeb/Forward.h5
5 files changed, 206 insertions, 4 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt
index b4fb86ac21..2cd4effbcf 100644
--- a/Userland/Libraries/LibWeb/CMakeLists.txt
+++ b/Userland/Libraries/LibWeb/CMakeLists.txt
@@ -16,6 +16,7 @@ set(SOURCES
Crypto/Crypto.cpp
Crypto/SubtleCrypto.cpp
CSS/Angle.cpp
+ CSS/CalculatedOr.cpp
CSS/Clip.cpp
CSS/CSS.cpp
CSS/CSSConditionRule.cpp
diff --git a/Userland/Libraries/LibWeb/CSS/CalculatedOr.cpp b/Userland/Libraries/LibWeb/CSS/CalculatedOr.cpp
new file mode 100644
index 0000000000..ed01f47a68
--- /dev/null
+++ b/Userland/Libraries/LibWeb/CSS/CalculatedOr.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "CalculatedOr.h"
+
+namespace Web::CSS {
+
+Angle AngleOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
+{
+ return calculated->resolve_angle().value();
+}
+
+Frequency FrequencyOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
+{
+ return calculated->resolve_frequency().value();
+}
+
+Length LengthOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
+{
+ return calculated->resolve_length(layout_node).value();
+}
+
+Percentage PercentageOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
+{
+ return calculated->resolve_percentage().value();
+}
+
+Time TimeOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
+{
+ return calculated->resolve_time().value();
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/CSS/CalculatedOr.h b/Userland/Libraries/LibWeb/CSS/CalculatedOr.h
new file mode 100644
index 0000000000..f64e879476
--- /dev/null
+++ b/Userland/Libraries/LibWeb/CSS/CalculatedOr.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Variant.h>
+#include <LibWeb/CSS/Angle.h>
+#include <LibWeb/CSS/Frequency.h>
+#include <LibWeb/CSS/Length.h>
+#include <LibWeb/CSS/Percentage.h>
+#include <LibWeb/CSS/StyleValue.h>
+#include <LibWeb/CSS/Time.h>
+
+namespace Web::CSS {
+
+template<typename T>
+class CalculatedOr {
+public:
+ CalculatedOr(T t)
+ : m_value(move(t))
+ {
+ }
+
+ CalculatedOr(NonnullRefPtr<CalculatedStyleValue> calculated)
+ : m_value(move(calculated))
+ {
+ }
+
+ virtual ~CalculatedOr() = default;
+
+ bool is_calculated() const { return m_value.template has<NonnullRefPtr<CalculatedStyleValue>>(); }
+
+ T const& value() const
+ {
+ VERIFY(!is_calculated());
+ return m_value.template get<T>();
+ }
+
+ NonnullRefPtr<CalculatedStyleValue> const& calculated() const
+ {
+ VERIFY(is_calculated());
+ return m_value.template get<NonnullRefPtr<CalculatedStyleValue>>();
+ }
+
+ virtual T resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const = 0;
+
+ T resolved(Layout::Node const& layout_node) const
+ {
+ return m_value.visit(
+ [&](T const& t) {
+ return t;
+ },
+ [&](NonnullRefPtr<CalculatedStyleValue> const& calculated) {
+ return resolve_calculated(calculated, layout_node);
+ });
+ }
+
+ ErrorOr<String> to_string() const
+ {
+ if (is_calculated())
+ return m_value.template get<NonnullRefPtr<CalculatedStyleValue>>()->to_string();
+
+ return m_value.template get<T>().to_string();
+ }
+
+ bool operator==(CalculatedOr<T> const& other) const
+ {
+ if (is_calculated() || other.is_calculated())
+ return false;
+ return (m_value.template get<T>() == other.m_value.template get<T>());
+ }
+
+private:
+ Variant<T, NonnullRefPtr<CalculatedStyleValue>> m_value;
+};
+
+class AngleOrCalculated : public CalculatedOr<Angle> {
+public:
+ using CalculatedOr<Angle>::CalculatedOr;
+
+ Angle resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
+};
+
+class FrequencyOrCalculated : public CalculatedOr<Frequency> {
+public:
+ using CalculatedOr<Frequency>::CalculatedOr;
+
+ Frequency resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
+};
+
+class LengthOrCalculated : public CalculatedOr<Length> {
+public:
+ using CalculatedOr<Length>::CalculatedOr;
+
+ Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
+};
+
+class PercentageOrCalculated : public CalculatedOr<Percentage> {
+public:
+ using CalculatedOr<Percentage>::CalculatedOr;
+
+ Percentage resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
+};
+
+class TimeOrCalculated : public CalculatedOr<Time> {
+public:
+ using CalculatedOr<Time>::CalculatedOr;
+
+ Time resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
+};
+
+}
+
+template<>
+struct AK::Formatter<Web::CSS::AngleOrCalculated> : Formatter<StringView> {
+ ErrorOr<void> format(FormatBuilder& builder, Web::CSS::AngleOrCalculated const& calculated_or)
+ {
+ return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
+ }
+};
+
+template<>
+struct AK::Formatter<Web::CSS::FrequencyOrCalculated> : Formatter<StringView> {
+ ErrorOr<void> format(FormatBuilder& builder, Web::CSS::FrequencyOrCalculated const& calculated_or)
+ {
+ return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
+ }
+};
+
+template<>
+struct AK::Formatter<Web::CSS::LengthOrCalculated> : Formatter<StringView> {
+ ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthOrCalculated const& calculated_or)
+ {
+ return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
+ }
+};
+
+template<>
+struct AK::Formatter<Web::CSS::PercentageOrCalculated> : Formatter<StringView> {
+ ErrorOr<void> format(FormatBuilder& builder, Web::CSS::PercentageOrCalculated const& calculated_or)
+ {
+ return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
+ }
+};
+
+template<>
+struct AK::Formatter<Web::CSS::TimeOrCalculated> : Formatter<StringView> {
+ ErrorOr<void> format(FormatBuilder& builder, Web::CSS::TimeOrCalculated const& calculated_or)
+ {
+ return Formatter<StringView>::format(builder, TRY(calculated_or.to_string()));
+ }
+};
diff --git a/Userland/Libraries/LibWeb/CSS/Percentage.h b/Userland/Libraries/LibWeb/CSS/Percentage.h
index f49ec90777..48fbc067f9 100644
--- a/Userland/Libraries/LibWeb/CSS/Percentage.h
+++ b/Userland/Libraries/LibWeb/CSS/Percentage.h
@@ -83,8 +83,10 @@ public:
{
return m_value.visit(
[&](T const& t) {
- if (t.is_calculated())
- return calculated_style_value_contains_percentage(*t.calculated_style_value());
+ if constexpr (requires { t.is_calculated(); }) {
+ if (t.is_calculated())
+ return calculated_style_value_contains_percentage(*t.calculated_style_value());
+ }
return false;
},
[&](Percentage const&) {
@@ -116,8 +118,11 @@ public:
{
return m_value.visit(
[&](T const& t) {
- if (t.is_calculated())
- return resolve_calculated(t.calculated_style_value(), layout_node, reference_value);
+ if constexpr (requires { t.is_calculated(); }) {
+ if (t.is_calculated())
+ return resolve_calculated(t.calculated_style_value(), layout_node, reference_value);
+ }
+
return t;
},
[&](Percentage const& percentage) {
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index a5d52e689e..2d3f1a9ad7 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -28,6 +28,7 @@ namespace Web::CSS {
class AbstractImageStyleValue;
class Angle;
class AnglePercentage;
+class AngleOrCalculated;
class AngleStyleValue;
class BackgroundRepeatStyleValue;
class BackgroundSizeStyleValue;
@@ -61,6 +62,7 @@ class FontFace;
class FontStyleValue;
class Frequency;
class FrequencyPercentage;
+class FrequencyOrCalculated;
class FrequencyStyleValue;
class GridAreaShorthandStyleValue;
class GridMinMax;
@@ -79,6 +81,7 @@ class InitialStyleValue;
class Length;
class LengthBox;
class LengthPercentage;
+class LengthOrCalculated;
class LengthStyleValue;
class LinearGradientStyleValue;
class ListStyleStyleValue;
@@ -91,6 +94,7 @@ class Number;
class NumericStyleValue;
class OverflowStyleValue;
class Percentage;
+class PercentageOrCalculated;
class PercentageStyleValue;
class PositionStyleValue;
class PropertyOwningCSSStyleDeclaration;
@@ -113,6 +117,7 @@ class Supports;
class TextDecorationStyleValue;
class Time;
class TimePercentage;
+class TimeOrCalculated;
class TimeStyleValue;
class TransformationStyleValue;
class UnicodeRange;