Browse Source

LibWeb/CSS: Introduce OpenTypeTaggedStyleValue

Two font properties, font-feature-settings and font-variation-settings,
contain a list of values that are an `<opentype-tag>` followed by a
single value. This class is intended to fill both roles.
Sam Atkins 9 months ago
parent
commit
c22a2d8f2b

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -139,6 +139,7 @@ set(SOURCES
     CSS/StyleValues/LinearGradientStyleValue.cpp
     CSS/StyleValues/MathDepthStyleValue.cpp
     CSS/StyleValues/NumberStyleValue.cpp
+    CSS/StyleValues/OpenTypeTaggedStyleValue.cpp
     CSS/StyleValues/PositionStyleValue.cpp
     CSS/StyleValues/RadialGradientStyleValue.cpp
     CSS/StyleValues/RectStyleValue.cpp

+ 7 - 0
Userland/Libraries/LibWeb/CSS/CSSStyleValue.cpp

@@ -40,6 +40,7 @@
 #include <LibWeb/CSS/StyleValues/LinearGradientStyleValue.h>
 #include <LibWeb/CSS/StyleValues/MathDepthStyleValue.h>
 #include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
+#include <LibWeb/CSS/StyleValues/OpenTypeTaggedStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
 #include <LibWeb/CSS/StyleValues/RadialGradientStyleValue.h>
@@ -244,6 +245,12 @@ NumberStyleValue const& CSSStyleValue::as_number() const
     return static_cast<NumberStyleValue const&>(*this);
 }
 
+OpenTypeTaggedStyleValue const& CSSStyleValue::as_open_type_tagged() const
+{
+    VERIFY(is_open_type_tagged());
+    return static_cast<OpenTypeTaggedStyleValue const&>(*this);
+}
+
 PercentageStyleValue const& CSSStyleValue::as_percentage() const
 {
     VERIFY(is_percentage());

+ 5 - 0
Userland/Libraries/LibWeb/CSS/CSSStyleValue.h

@@ -117,6 +117,7 @@ public:
         Math,
         MathDepth,
         Number,
+        OpenTypeTagged,
         Percentage,
         Position,
         RadialGradient,
@@ -260,6 +261,10 @@ public:
     NumberStyleValue const& as_number() const;
     NumberStyleValue& as_number() { return const_cast<NumberStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_number()); }
 
+    bool is_open_type_tagged() const { return type() == Type::OpenTypeTagged; }
+    OpenTypeTaggedStyleValue const& as_open_type_tagged() const;
+    OpenTypeTaggedStyleValue& as_open_type_tagged() { return const_cast<OpenTypeTaggedStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_open_type_tagged()); }
+
     bool is_percentage() const { return type() == Type::Percentage; }
     PercentageStyleValue const& as_percentage() const;
     PercentageStyleValue& as_percentage() { return const_cast<PercentageStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_percentage()); }

+ 27 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/OpenTypeTaggedStyleValue.cpp

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "OpenTypeTaggedStyleValue.h"
+#include <LibWeb/CSS/Serialize.h>
+
+namespace Web::CSS {
+
+String OpenTypeTaggedStyleValue::to_string() const
+{
+    StringBuilder builder;
+    serialize_a_string(builder, m_tag);
+    // FIXME: For font-feature-settings, a 1 value is implicit, so we shouldn't output it.
+    builder.appendff(" {}", m_value->to_string());
+
+    return builder.to_string_without_validation();
+}
+
+bool OpenTypeTaggedStyleValue::properties_equal(OpenTypeTaggedStyleValue const& other) const
+{
+    return other.tag() == tag() && other.value() == value();
+}
+
+}

+ 44 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/OpenTypeTaggedStyleValue.h

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/FlyString.h>
+#include <LibWeb/CSS/CSSStyleValue.h>
+
+namespace Web::CSS {
+
+// An `<opentype-tag>` followed by an optional value.
+// For example, <feature-tag-value> ( https://drafts.csswg.org/css-fonts/#feature-tag-value )
+// and the `<opentype-tag> <number>` construct for `font-variation-settings`.
+class OpenTypeTaggedStyleValue : public StyleValueWithDefaultOperators<OpenTypeTaggedStyleValue> {
+public:
+    static ValueComparingNonnullRefPtr<OpenTypeTaggedStyleValue> create(FlyString tag, ValueComparingNonnullRefPtr<CSSStyleValue> value)
+    {
+        return adopt_ref(*new (nothrow) OpenTypeTaggedStyleValue(move(tag), move(value)));
+    }
+    virtual ~OpenTypeTaggedStyleValue() override = default;
+
+    FlyString const& tag() const { return m_tag; }
+    ValueComparingNonnullRefPtr<CSSStyleValue> const& value() const { return m_value; }
+
+    virtual String to_string() const override;
+
+    bool properties_equal(OpenTypeTaggedStyleValue const&) const;
+
+private:
+    explicit OpenTypeTaggedStyleValue(FlyString tag, ValueComparingNonnullRefPtr<CSSStyleValue> value)
+        : StyleValueWithDefaultOperators(Type::OpenTypeTagged)
+        , m_tag(move(tag))
+        , m_value(move(value))
+    {
+    }
+
+    FlyString m_tag;
+    ValueComparingNonnullRefPtr<CSSStyleValue> m_value;
+};
+
+}

+ 1 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -178,6 +178,7 @@ class MediaQueryListEvent;
 class Number;
 class NumberOrCalculated;
 class NumberStyleValue;
+class OpenTypeTaggedStyleValue;
 class ParsedFontFace;
 class Percentage;
 class PercentageOrCalculated;