Sfoglia il codice sorgente

LibWeb: Implement CSS Resolution class

This corresponds to `<resolution>` in the grammar.
Sam Atkins 3 anni fa
parent
commit
0465abcfec

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

@@ -42,6 +42,7 @@ set(SOURCES
     CSS/PropertyID.cpp
     CSS/PropertyID.h
     CSS/QuirksModeStyleSheetSource.cpp
+    CSS/Resolution.cpp
     CSS/ResolvedCSSStyleDeclaration.cpp
     CSS/Screen.cpp
     CSS/Selector.cpp

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

@@ -4306,6 +4306,10 @@ Optional<CalculatedStyleValue::CalcValue> Parser::parse_calc_value(TokenStream<S
             return CalculatedStyleValue::CalcValue { dimension.length() };
         if (dimension.is_percentage())
             return CalculatedStyleValue::CalcValue { dimension.percentage() };
+        if (dimension.is_resolution()) {
+            // Resolution is not allowed in calc()
+            return {};
+        }
         VERIFY_NOT_REACHED();
     }
 

+ 67 - 0
Userland/Libraries/LibWeb/CSS/Resolution.cpp

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "Resolution.h"
+#include <LibWeb/CSS/StyleValue.h>
+
+namespace Web::CSS {
+
+Resolution::Resolution(int value, Type type)
+    : m_type(type)
+    , m_value(value)
+{
+}
+
+Resolution::Resolution(float value, Type type)
+    : m_type(type)
+    , m_value(value)
+{
+}
+
+String Resolution::to_string() const
+{
+    return String::formatted("{}{}", m_value, unit_name());
+}
+
+float Resolution::to_dots_per_pixel() const
+{
+    switch (m_type) {
+    case Type::Dpi:
+        return m_value * 96; // 1in = 2.54cm = 96px
+    case Type::Dpcm:
+        return m_value * (96.0f / 2.54f); // 1cm = 96px/2.54
+    case Type::Dppx:
+        return m_value;
+    }
+    VERIFY_NOT_REACHED();
+}
+
+StringView Resolution::unit_name() const
+{
+    switch (m_type) {
+    case Type::Dpi:
+        return "dpi"sv;
+    case Type::Dpcm:
+        return "dpcm"sv;
+    case Type::Dppx:
+        return "dppx"sv;
+    }
+    VERIFY_NOT_REACHED();
+}
+
+Optional<Resolution::Type> Resolution::unit_from_name(StringView name)
+{
+    if (name.equals_ignoring_case("dpi"sv)) {
+        return Type::Dpi;
+    } else if (name.equals_ignoring_case("dpcm"sv)) {
+        return Type::Dpcm;
+    } else if (name.equals_ignoring_case("dppx"sv)) {
+        return Type::Dppx;
+    }
+    return {};
+}
+
+}

+ 46 - 0
Userland/Libraries/LibWeb/CSS/Resolution.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::CSS {
+
+class Resolution {
+public:
+    enum class Type {
+        Dpi,
+        Dpcm,
+        Dppx,
+    };
+
+    static Optional<Type> unit_from_name(StringView);
+
+    Resolution(int value, Type type);
+    Resolution(float value, Type type);
+
+    String to_string() const;
+    float to_dots_per_pixel() const;
+
+    bool operator==(Resolution const& other) const
+    {
+        return m_type == other.m_type && m_value == other.m_value;
+    }
+
+    bool operator!=(Resolution const& other) const
+    {
+        return !(*this == other);
+    }
+
+private:
+    StringView unit_name() const;
+
+    Type m_type;
+    float m_value { 0 };
+};
+}

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

@@ -165,6 +165,12 @@ PositionStyleValue const& StyleValue::as_position() const
     return static_cast<PositionStyleValue const&>(*this);
 }
 
+ResolutionStyleValue const& StyleValue::as_resolution() const
+{
+    VERIFY(is_resolution());
+    return static_cast<ResolutionStyleValue const&>(*this);
+}
+
 StringStyleValue const& StyleValue::as_string() const
 {
     VERIFY(is_string());

+ 34 - 0
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -29,6 +29,7 @@
 #include <LibWeb/CSS/Parser/StyleComponentValueRule.h>
 #include <LibWeb/CSS/Percentage.h>
 #include <LibWeb/CSS/PropertyID.h>
+#include <LibWeb/CSS/Resolution.h>
 #include <LibWeb/CSS/ValueID.h>
 #include <LibWeb/Forward.h>
 #include <LibWeb/Loader/ImageResource.h>
@@ -310,6 +311,7 @@ public:
         Overflow,
         Percentage,
         Position,
+        Resolution,
         String,
         TextDecoration,
         Transformation,
@@ -343,6 +345,7 @@ public:
     bool is_overflow() const { return type() == Type::Overflow; }
     bool is_percentage() const { return type() == Type::Percentage; }
     bool is_position() const { return type() == Type::Position; }
+    bool is_resolution() const { return type() == Type::Resolution; }
     bool is_string() const { return type() == Type::String; }
     bool is_text_decoration() const { return type() == Type::TextDecoration; }
     bool is_transformation() const { return type() == Type::Transformation; }
@@ -375,6 +378,7 @@ public:
     OverflowStyleValue const& as_overflow() const;
     PercentageStyleValue const& as_percentage() const;
     PositionStyleValue const& as_position() const;
+    ResolutionStyleValue const& as_resolution() const;
     StringStyleValue const& as_string() const;
     TextDecorationStyleValue const& as_text_decoration() const;
     TransformationStyleValue const& as_transformation() const;
@@ -405,6 +409,7 @@ public:
     OverflowStyleValue& as_overflow() { return const_cast<OverflowStyleValue&>(const_cast<StyleValue const&>(*this).as_overflow()); }
     PercentageStyleValue& as_percentage() { return const_cast<PercentageStyleValue&>(const_cast<StyleValue const&>(*this).as_percentage()); }
     PositionStyleValue& as_position() { return const_cast<PositionStyleValue&>(const_cast<StyleValue const&>(*this).as_position()); }
+    ResolutionStyleValue& as_resolution() { return const_cast<ResolutionStyleValue&>(const_cast<StyleValue const&>(*this).as_resolution()); }
     StringStyleValue& as_string() { return const_cast<StringStyleValue&>(const_cast<StyleValue const&>(*this).as_string()); }
     TextDecorationStyleValue& as_text_decoration() { return const_cast<TextDecorationStyleValue&>(const_cast<StyleValue const&>(*this).as_text_decoration()); }
     TransformationStyleValue& as_transformation() { return const_cast<TransformationStyleValue&>(const_cast<StyleValue const&>(*this).as_transformation()); }
@@ -1367,6 +1372,35 @@ private:
     LengthPercentage m_offset_y;
 };
 
+class ResolutionStyleValue : public StyleValue {
+public:
+    static NonnullRefPtr<ResolutionStyleValue> create(Resolution resolution)
+    {
+        return adopt_ref(*new ResolutionStyleValue(move(resolution)));
+    }
+    virtual ~ResolutionStyleValue() override { }
+
+    Resolution const& resolution() const { return m_resolution; }
+
+    virtual String to_string() const override { return m_resolution.to_string(); }
+
+    virtual bool equals(StyleValue const& other) const override
+    {
+        if (type() != other.type())
+            return false;
+        return m_resolution == static_cast<ResolutionStyleValue const&>(other).m_resolution;
+    }
+
+private:
+    explicit ResolutionStyleValue(Resolution resolution)
+        : StyleValue(Type::Resolution)
+        , m_resolution(move(resolution))
+    {
+    }
+
+    Resolution m_resolution;
+};
+
 class StringStyleValue : public StyleValue {
 public:
     static NonnullRefPtr<StringStyleValue> create(String const& string)

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

@@ -64,6 +64,8 @@ class Percentage;
 class PercentageStyleValue;
 class PositionStyleValue;
 class PropertyOwningCSSStyleDeclaration;
+class Resolution;
+class ResolutionStyleValue;
 class Screen;
 class Selector;
 class StringStyleValue;