Explorar o código

LibWeb: Implement CSS Frequency class

This corresponds to `<frequency>` in the grammar.
Sam Atkins %!s(int64=3) %!d(string=hai) anos
pai
achega
bd79c303f6

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

@@ -28,6 +28,7 @@ set(SOURCES
     CSS/CSSSupportsRule.cpp
     CSS/CSSSupportsRule.cpp
     CSS/DefaultStyleSheetSource.cpp
     CSS/DefaultStyleSheetSource.cpp
     CSS/Display.cpp
     CSS/Display.cpp
+    CSS/Frequency.cpp
     CSS/Length.cpp
     CSS/Length.cpp
     CSS/MediaList.cpp
     CSS/MediaList.cpp
     CSS/MediaQuery.cpp
     CSS/MediaQuery.cpp

+ 86 - 0
Userland/Libraries/LibWeb/CSS/Frequency.cpp

@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "Frequency.h"
+#include <LibWeb/CSS/StyleValue.h>
+
+namespace Web::CSS {
+
+Frequency::Frequency(int value, Type type)
+    : m_type(type)
+    , m_value(value)
+{
+}
+
+Frequency::Frequency(float value, Type type)
+    : m_type(type)
+    , m_value(value)
+{
+}
+
+Frequency Frequency::make_calculated(NonnullRefPtr<CalculatedStyleValue> calculated_style_value)
+{
+    Frequency frequency { 0, Type::Calculated };
+    frequency.m_calculated_style = move(calculated_style_value);
+    return frequency;
+}
+
+Frequency Frequency::make_hertz(float value)
+{
+    return { value, Type::Hz };
+}
+
+Frequency Frequency::percentage_of(Percentage const& percentage) const
+{
+    VERIFY(!is_calculated());
+
+    return Frequency { percentage.as_fraction() * m_value, m_type };
+}
+
+String Frequency::to_string() const
+{
+    if (is_calculated())
+        return m_calculated_style->to_string();
+    return String::formatted("{}{}", m_value, unit_name());
+}
+
+float Frequency::to_hertz() const
+{
+    switch (m_type) {
+    case Type::Calculated:
+        return m_calculated_style->resolve_frequency()->to_hertz();
+    case Type::Hz:
+        return m_value;
+    case Type::kHz:
+        return m_value * 1000;
+    }
+    VERIFY_NOT_REACHED();
+}
+
+StringView Frequency::unit_name() const
+{
+    switch (m_type) {
+    case Type::Calculated:
+        return "calculated"sv;
+    case Type::Hz:
+        return "hz"sv;
+    case Type::kHz:
+        return "khz"sv;
+    }
+    VERIFY_NOT_REACHED();
+}
+
+Optional<Frequency::Type> Frequency::unit_from_name(StringView name)
+{
+    if (name.equals_ignoring_case("hz"sv)) {
+        return Type::Hz;
+    } else if (name.equals_ignoring_case("khz"sv)) {
+        return Type::kHz;
+    }
+    return {};
+}
+
+}

+ 53 - 0
Userland/Libraries/LibWeb/CSS/Frequency.h

@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/RefPtr.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::CSS {
+class Frequency {
+public:
+    enum class Type {
+        Calculated,
+        Hz,
+        kHz
+    };
+
+    static Optional<Type> unit_from_name(StringView);
+
+    Frequency(int value, Type type);
+    Frequency(float value, Type type);
+    static Frequency make_calculated(NonnullRefPtr<CalculatedStyleValue>);
+    static Frequency make_hertz(float);
+    Frequency percentage_of(Percentage const&) const;
+
+    bool is_calculated() const { return m_type == Type::Calculated; }
+
+    String to_string() const;
+    float to_hertz() const;
+
+    bool operator==(Frequency const& other) const
+    {
+        if (is_calculated())
+            return m_calculated_style == other.m_calculated_style;
+        return m_type == other.m_type && m_value == other.m_value;
+    }
+
+    bool operator!=(Frequency const& other) const
+    {
+        return !(*this == other);
+    }
+
+private:
+    StringView unit_name() const;
+
+    Type m_type;
+    float m_value { 0 };
+    RefPtr<CalculatedStyleValue> m_calculated_style;
+};
+}

+ 2 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -4300,6 +4300,8 @@ Optional<CalculatedStyleValue::CalcValue> Parser::parse_calc_value(TokenStream<S
 
 
         if (dimension.is_angle())
         if (dimension.is_angle())
             return CalculatedStyleValue::CalcValue { dimension.angle() };
             return CalculatedStyleValue::CalcValue { dimension.angle() };
+        if (dimension.is_frequency())
+            return CalculatedStyleValue::CalcValue { dimension.frequency() };
         if (dimension.is_length())
         if (dimension.is_length())
             return CalculatedStyleValue::CalcValue { dimension.length() };
             return CalculatedStyleValue::CalcValue { dimension.length() };
         if (dimension.is_percentage())
         if (dimension.is_percentage())

+ 5 - 0
Userland/Libraries/LibWeb/CSS/Percentage.cpp

@@ -14,6 +14,11 @@ Angle AnglePercentage::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> co
     return calculated->resolve_angle_percentage(reference_value)->resolved(layout_node, reference_value);
     return calculated->resolve_angle_percentage(reference_value)->resolved(layout_node, reference_value);
 }
 }
 
 
+Frequency FrequencyPercentage::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, Frequency const& reference_value) const
+{
+    return calculated->resolve_frequency_percentage(reference_value)->resolved(layout_node, reference_value);
+}
+
 Length LengthPercentage::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, Length const& reference_value) const
 Length LengthPercentage::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, Length const& reference_value) const
 {
 {
     return calculated->resolve_length_percentage(layout_node, reference_value)->resolved(layout_node, reference_value);
     return calculated->resolve_length_percentage(layout_node, reference_value)->resolved(layout_node, reference_value);

+ 20 - 0
Userland/Libraries/LibWeb/CSS/Percentage.h

@@ -9,6 +9,7 @@
 #include <AK/String.h>
 #include <AK/String.h>
 #include <AK/Variant.h>
 #include <AK/Variant.h>
 #include <LibWeb/CSS/Angle.h>
 #include <LibWeb/CSS/Angle.h>
+#include <LibWeb/CSS/Frequency.h>
 #include <LibWeb/CSS/Length.h>
 #include <LibWeb/CSS/Length.h>
 
 
 namespace Web::CSS {
 namespace Web::CSS {
@@ -160,6 +161,16 @@ public:
     Angle const& angle() const { return get_t(); }
     Angle const& angle() const { return get_t(); }
     virtual Angle resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&, Angle const& reference_value) const override;
     virtual Angle resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&, Angle const& reference_value) const override;
 };
 };
+
+class FrequencyPercentage : public PercentageOr<Frequency> {
+public:
+    using PercentageOr<Frequency>::PercentageOr;
+
+    bool is_frequency() const { return is_t(); }
+    Frequency const& frequency() const { return get_t(); }
+    virtual Frequency resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&, Frequency const& reference_value) const override;
+};
+
 class LengthPercentage : public PercentageOr<Length> {
 class LengthPercentage : public PercentageOr<Length> {
 public:
 public:
     using PercentageOr<Length>::PercentageOr;
     using PercentageOr<Length>::PercentageOr;
@@ -187,6 +198,15 @@ struct AK::Formatter<Web::CSS::AnglePercentage> : Formatter<StringView> {
     }
     }
 };
 };
 
 
+template<>
+struct AK::Formatter<Web::CSS::FrequencyPercentage> : Formatter<StringView> {
+    ErrorOr<void> format(FormatBuilder& builder, Web::CSS::FrequencyPercentage const& frequency_percentage)
+    {
+        return Formatter<StringView>::format(builder, frequency_percentage.to_string());
+    }
+};
+
+template<>
 struct AK::Formatter<Web::CSS::LengthPercentage> : Formatter<StringView> {
 struct AK::Formatter<Web::CSS::LengthPercentage> : Formatter<StringView> {
     ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthPercentage const& length_percentage)
     ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthPercentage const& length_percentage)
     {
     {

+ 56 - 0
Userland/Libraries/LibWeb/CSS/StyleValue.cpp

@@ -99,6 +99,12 @@ FontStyleValue const& StyleValue::as_font() const
     return static_cast<FontStyleValue const&>(*this);
     return static_cast<FontStyleValue const&>(*this);
 }
 }
 
 
+FrequencyStyleValue const& StyleValue::as_frequency() const
+{
+    VERIFY(is_frequency());
+    return static_cast<FrequencyStyleValue const&>(*this);
+}
+
 IdentifierStyleValue const& StyleValue::as_identifier() const
 IdentifierStyleValue const& StyleValue::as_identifier() const
 {
 {
     VERIFY(is_identifier());
     VERIFY(is_identifier());
@@ -333,6 +339,24 @@ void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperat
                     m_value = Angle::make_degrees(this_degrees - other_degrees);
                     m_value = Angle::make_degrees(this_degrees - other_degrees);
             }
             }
         },
         },
+        [&](Frequency const& frequency) {
+            auto this_hertz = frequency.to_hertz();
+            if (other.m_value.has<Frequency>()) {
+                auto other_hertz = other.m_value.get<Frequency>().to_hertz();
+                if (op == SumOperation::Add)
+                    m_value = Frequency::make_hertz(this_hertz + other_hertz);
+                else
+                    m_value = Frequency::make_hertz(this_hertz - other_hertz);
+            } else {
+                VERIFY(percentage_basis.has<Frequency>());
+
+                auto other_hertz = percentage_basis.get<Frequency>().percentage_of(other.m_value.get<Percentage>()).to_hertz();
+                if (op == SumOperation::Add)
+                    m_value = Frequency::make_hertz(this_hertz + other_hertz);
+                else
+                    m_value = Frequency::make_hertz(this_hertz - other_hertz);
+            }
+        },
         [&](Length const& length) {
         [&](Length const& length) {
             auto this_px = length.to_px(*layout_node);
             auto this_px = length.to_px(*layout_node);
             if (other.m_value.has<Length>()) {
             if (other.m_value.has<Length>()) {
@@ -396,6 +420,9 @@ void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult cons
         [&](Angle const& angle) {
         [&](Angle const& angle) {
             m_value = Angle::make_degrees(angle.to_degrees() * other.m_value.get<Number>().value);
             m_value = Angle::make_degrees(angle.to_degrees() * other.m_value.get<Number>().value);
         },
         },
+        [&](Frequency const& frequency) {
+            m_value = Frequency::make_hertz(frequency.to_hertz() * other.m_value.get<Number>().value);
+        },
         [&](Length const& length) {
         [&](Length const& length) {
             VERIFY(layout_node);
             VERIFY(layout_node);
             m_value = Length::make_px(length.to_px(*layout_node) * other.m_value.get<Number>().value);
             m_value = Length::make_px(length.to_px(*layout_node) * other.m_value.get<Number>().value);
@@ -423,6 +450,9 @@ void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const&
         [&](Angle const& angle) {
         [&](Angle const& angle) {
             m_value = Angle::make_degrees(angle.to_degrees() / denominator);
             m_value = Angle::make_degrees(angle.to_degrees() / denominator);
         },
         },
+        [&](Frequency const& frequency) {
+            m_value = Frequency::make_hertz(frequency.to_hertz() / denominator);
+        },
         [&](Length const& length) {
         [&](Length const& length) {
             VERIFY(layout_node);
             VERIFY(layout_node);
             m_value = Length::make_px(length.to_px(*layout_node) / denominator);
             m_value = Length::make_px(length.to_px(*layout_node) / denominator);
@@ -536,6 +566,31 @@ Optional<AnglePercentage> CalculatedStyleValue::resolve_angle_percentage(Angle c
         });
         });
 }
 }
 
 
+Optional<Frequency> CalculatedStyleValue::resolve_frequency() const
+{
+    auto result = m_expression->resolve(nullptr, {});
+
+    if (result.value().has<Frequency>())
+        return result.value().get<Frequency>();
+    return {};
+}
+
+Optional<FrequencyPercentage> CalculatedStyleValue::resolve_frequency_percentage(Frequency const& percentage_basis) const
+{
+    auto result = m_expression->resolve(nullptr, percentage_basis);
+
+    return result.value().visit(
+        [&](Frequency const& frequency) -> Optional<FrequencyPercentage> {
+            return frequency;
+        },
+        [&](Percentage const& percentage) -> Optional<FrequencyPercentage> {
+            return percentage;
+        },
+        [&](auto const&) -> Optional<FrequencyPercentage> {
+            return {};
+        });
+}
+
 Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout_node) const
 Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout_node) const
 {
 {
     auto result = m_expression->resolve(&layout_node, {});
     auto result = m_expression->resolve(&layout_node, {});
@@ -745,6 +800,7 @@ Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcValue::re
             return { number.is_integer ? ResolvedType::Integer : ResolvedType::Number };
             return { number.is_integer ? ResolvedType::Integer : ResolvedType::Number };
         },
         },
         [](Angle const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Angle }; },
         [](Angle const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Angle }; },
+        [](Frequency const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Frequency }; },
         [](Length const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Length }; },
         [](Length const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Length }; },
         [](Percentage const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Percentage }; },
         [](Percentage const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Percentage }; },
         [](NonnullOwnPtr<CalcSum> const& sum) { return sum->resolved_type(); });
         [](NonnullOwnPtr<CalcSum> const& sum) { return sum->resolved_type(); });

+ 41 - 5
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -24,6 +24,7 @@
 #include <LibGfx/Color.h>
 #include <LibGfx/Color.h>
 #include <LibWeb/CSS/Angle.h>
 #include <LibWeb/CSS/Angle.h>
 #include <LibWeb/CSS/Display.h>
 #include <LibWeb/CSS/Display.h>
+#include <LibWeb/CSS/Frequency.h>
 #include <LibWeb/CSS/Length.h>
 #include <LibWeb/CSS/Length.h>
 #include <LibWeb/CSS/Parser/StyleComponentValueRule.h>
 #include <LibWeb/CSS/Parser/StyleComponentValueRule.h>
 #include <LibWeb/CSS/Percentage.h>
 #include <LibWeb/CSS/Percentage.h>
@@ -297,6 +298,7 @@ public:
         Flex,
         Flex,
         FlexFlow,
         FlexFlow,
         Font,
         Font,
+        Frequency,
         Identifier,
         Identifier,
         Image,
         Image,
         Inherit,
         Inherit,
@@ -330,6 +332,7 @@ public:
     bool is_flex() const { return type() == Type::Flex; }
     bool is_flex() const { return type() == Type::Flex; }
     bool is_flex_flow() const { return type() == Type::FlexFlow; }
     bool is_flex_flow() const { return type() == Type::FlexFlow; }
     bool is_font() const { return type() == Type::Font; }
     bool is_font() const { return type() == Type::Font; }
+    bool is_frequency() const { return type() == Type::Frequency; }
     bool is_identifier() const { return type() == Type::Identifier; }
     bool is_identifier() const { return type() == Type::Identifier; }
     bool is_image() const { return type() == Type::Image; }
     bool is_image() const { return type() == Type::Image; }
     bool is_inherit() const { return type() == Type::Inherit; }
     bool is_inherit() const { return type() == Type::Inherit; }
@@ -361,6 +364,7 @@ public:
     FlexFlowStyleValue const& as_flex_flow() const;
     FlexFlowStyleValue const& as_flex_flow() const;
     FlexStyleValue const& as_flex() const;
     FlexStyleValue const& as_flex() const;
     FontStyleValue const& as_font() const;
     FontStyleValue const& as_font() const;
+    FrequencyStyleValue const& as_frequency() const;
     IdentifierStyleValue const& as_identifier() const;
     IdentifierStyleValue const& as_identifier() const;
     ImageStyleValue const& as_image() const;
     ImageStyleValue const& as_image() const;
     InheritStyleValue const& as_inherit() const;
     InheritStyleValue const& as_inherit() const;
@@ -390,6 +394,7 @@ public:
     FlexFlowStyleValue& as_flex_flow() { return const_cast<FlexFlowStyleValue&>(const_cast<StyleValue const&>(*this).as_flex_flow()); }
     FlexFlowStyleValue& as_flex_flow() { return const_cast<FlexFlowStyleValue&>(const_cast<StyleValue const&>(*this).as_flex_flow()); }
     FlexStyleValue& as_flex() { return const_cast<FlexStyleValue&>(const_cast<StyleValue const&>(*this).as_flex()); }
     FlexStyleValue& as_flex() { return const_cast<FlexStyleValue&>(const_cast<StyleValue const&>(*this).as_flex()); }
     FontStyleValue& as_font() { return const_cast<FontStyleValue&>(const_cast<StyleValue const&>(*this).as_font()); }
     FontStyleValue& as_font() { return const_cast<FontStyleValue&>(const_cast<StyleValue const&>(*this).as_font()); }
+    FrequencyStyleValue& as_frequency() { return const_cast<FrequencyStyleValue&>(const_cast<StyleValue const&>(*this).as_frequency()); }
     IdentifierStyleValue& as_identifier() { return const_cast<IdentifierStyleValue&>(const_cast<StyleValue const&>(*this).as_identifier()); }
     IdentifierStyleValue& as_identifier() { return const_cast<IdentifierStyleValue&>(const_cast<StyleValue const&>(*this).as_identifier()); }
     ImageStyleValue& as_image() { return const_cast<ImageStyleValue&>(const_cast<StyleValue const&>(*this).as_image()); }
     ImageStyleValue& as_image() { return const_cast<ImageStyleValue&>(const_cast<StyleValue const&>(*this).as_image()); }
     InheritStyleValue& as_inherit() { return const_cast<InheritStyleValue&>(const_cast<StyleValue const&>(*this).as_inherit()); }
     InheritStyleValue& as_inherit() { return const_cast<InheritStyleValue&>(const_cast<StyleValue const&>(*this).as_inherit()); }
@@ -730,11 +735,11 @@ public:
         float value;
         float value;
     };
     };
 
 
-    using PercentageBasis = Variant<Empty, Angle, Length>;
+    using PercentageBasis = Variant<Empty, Angle, Frequency, Length>;
 
 
     class CalculationResult {
     class CalculationResult {
     public:
     public:
-        CalculationResult(Variant<Number, Angle, Length, Percentage> value)
+        CalculationResult(Variant<Number, Angle, Frequency, Length, Percentage> value)
             : m_value(move(value))
             : m_value(move(value))
         {
         {
         }
         }
@@ -743,11 +748,11 @@ public:
         void multiply_by(CalculationResult const& other, Layout::Node const*);
         void multiply_by(CalculationResult const& other, Layout::Node const*);
         void divide_by(CalculationResult const& other, Layout::Node const*);
         void divide_by(CalculationResult const& other, Layout::Node const*);
 
 
-        Variant<Number, Angle, Length, Percentage> const& value() const { return m_value; }
+        Variant<Number, Angle, Frequency, Length, Percentage> const& value() const { return m_value; }
 
 
     private:
     private:
         void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis);
         void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis);
-        Variant<Number, Angle, Length, Percentage> m_value;
+        Variant<Number, Angle, Frequency, Length, Percentage> m_value;
     };
     };
 
 
     struct CalcSum;
     struct CalcSum;
@@ -767,7 +772,7 @@ public:
     };
     };
 
 
     struct CalcValue {
     struct CalcValue {
-        Variant<Number, Angle, Length, Percentage, NonnullOwnPtr<CalcSum>> value;
+        Variant<Number, Angle, Frequency, Length, Percentage, NonnullOwnPtr<CalcSum>> value;
         String to_string() const;
         String to_string() const;
         Optional<ResolvedType> resolved_type() const;
         Optional<ResolvedType> resolved_type() const;
         CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
         CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
@@ -873,6 +878,8 @@ public:
 
 
     Optional<Angle> resolve_angle() const;
     Optional<Angle> resolve_angle() const;
     Optional<AnglePercentage> resolve_angle_percentage(Angle const& percentage_basis) const;
     Optional<AnglePercentage> resolve_angle_percentage(Angle const& percentage_basis) const;
+    Optional<Frequency> resolve_frequency() const;
+    Optional<FrequencyPercentage> resolve_frequency_percentage(Frequency const& percentage_basis) const;
     Optional<Length> resolve_length(Layout::Node const& layout_node) const;
     Optional<Length> resolve_length(Layout::Node const& layout_node) const;
     Optional<LengthPercentage> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
     Optional<LengthPercentage> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
     Optional<Percentage> resolve_percentage() const;
     Optional<Percentage> resolve_percentage() const;
@@ -1040,6 +1047,35 @@ private:
     // FIXME: Implement font-stretch and font-variant.
     // FIXME: Implement font-stretch and font-variant.
 };
 };
 
 
+class FrequencyStyleValue : public StyleValue {
+public:
+    static NonnullRefPtr<FrequencyStyleValue> create(Frequency frequency)
+    {
+        return adopt_ref(*new FrequencyStyleValue(move(frequency)));
+    }
+    virtual ~FrequencyStyleValue() override { }
+
+    Frequency const& frequency() const { return m_frequency; }
+
+    virtual String to_string() const override { return m_frequency.to_string(); }
+
+    virtual bool equals(StyleValue const& other) const override
+    {
+        if (type() != other.type())
+            return false;
+        return m_frequency == static_cast<FrequencyStyleValue const&>(other).m_frequency;
+    }
+
+private:
+    explicit FrequencyStyleValue(Frequency frequency)
+        : StyleValue(Type::Frequency)
+        , m_frequency(move(frequency))
+    {
+    }
+
+    Frequency m_frequency;
+};
+
 class IdentifierStyleValue final : public StyleValue {
 class IdentifierStyleValue final : public StyleValue {
 public:
 public:
     static NonnullRefPtr<IdentifierStyleValue> create(CSS::ValueID id)
     static NonnullRefPtr<IdentifierStyleValue> create(CSS::ValueID id)

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

@@ -43,6 +43,9 @@ class ElementInlineCSSStyleDeclaration;
 class FlexFlowStyleValue;
 class FlexFlowStyleValue;
 class FlexStyleValue;
 class FlexStyleValue;
 class FontStyleValue;
 class FontStyleValue;
+class Frequency;
+class FrequencyPercentage;
+class FrequencyStyleValue;
 class IdentifierStyleValue;
 class IdentifierStyleValue;
 class ImageStyleValue;
 class ImageStyleValue;
 class InheritStyleValue;
 class InheritStyleValue;