瀏覽代碼

LibWeb: Add `BasicShapeStyleValue` to represent CSS basic shapes

See: https://www.w3.org/TR/css-shapes-1/#basic-shape-functions

This patch only implements the `polygon()` basic shape (with the rest
left as FIXMEs).
MacDue 1 年之前
父節點
當前提交
5f17d9b34a

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

@@ -102,6 +102,7 @@ set(SOURCES
     CSS/StyleValues/AngleStyleValue.cpp
     CSS/StyleValues/BackgroundRepeatStyleValue.cpp
     CSS/StyleValues/BackgroundSizeStyleValue.cpp
+    CSS/StyleValues/BasicShapeStyleValue.cpp
     CSS/StyleValues/BorderRadiusStyleValue.cpp
     CSS/StyleValues/CalculatedStyleValue.cpp
     CSS/StyleValues/ColorStyleValue.cpp

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

@@ -14,6 +14,7 @@
 #include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
 #include <LibWeb/CSS/StyleValues/BackgroundRepeatStyleValue.h>
 #include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
+#include <LibWeb/CSS/StyleValues/BasicShapeStyleValue.h>
 #include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
 #include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
 #include <LibWeb/CSS/StyleValues/ColorStyleValue.h>

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

@@ -86,6 +86,7 @@ using StyleValueVector = Vector<ValueComparingNonnullRefPtr<StyleValue const>>;
     __ENUMERATE_STYLE_VALUE_TYPE(Angle, angle)                             \
     __ENUMERATE_STYLE_VALUE_TYPE(BackgroundRepeat, background_repeat)      \
     __ENUMERATE_STYLE_VALUE_TYPE(BackgroundSize, background_size)          \
+    __ENUMERATE_STYLE_VALUE_TYPE(BasicShape, basic_shape)                  \
     __ENUMERATE_STYLE_VALUE_TYPE(BorderRadius, border_radius)              \
     __ENUMERATE_STYLE_VALUE_TYPE(Calculated, calculated)                   \
     __ENUMERATE_STYLE_VALUE_TYPE(Color, color)                             \

+ 61 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/BasicShapeStyleValue.cpp

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024, MacDue <macdue@dueutil.tech>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "BasicShapeStyleValue.h"
+
+namespace Web::CSS {
+
+Gfx::Path Polygon::to_path(CSSPixelRect reference_box, Layout::Node const& node) const
+{
+    Gfx::Path path;
+    bool first = true;
+    for (auto const& point : points) {
+        Gfx::FloatPoint resolved_point {
+            static_cast<float>(point.x.to_px(node, reference_box.width())),
+            static_cast<float>(point.y.to_px(node, reference_box.height()))
+        };
+        if (first)
+            path.move_to(resolved_point);
+        else
+            path.line_to(resolved_point);
+        first = false;
+    }
+    path.close();
+    return path;
+}
+
+String Polygon::to_string() const
+{
+    StringBuilder builder;
+    builder.append("polygon("sv);
+    bool first = true;
+    for (auto const& point : points) {
+        if (!first)
+            builder.append(',');
+        builder.appendff("{} {}", point.x, point.y);
+        first = false;
+    }
+    builder.append(')');
+    return MUST(builder.to_string());
+}
+
+BasicShapeStyleValue::~BasicShapeStyleValue() = default;
+
+Gfx::Path BasicShapeStyleValue::to_path(CSSPixelRect reference_box, Layout::Node const& node) const
+{
+    return m_basic_shape.visit([&](auto const& shape) {
+        return shape.to_path(reference_box, node);
+    });
+}
+
+String BasicShapeStyleValue::to_string() const
+{
+    return m_basic_shape.visit([](auto const& shape) {
+        return shape.to_string();
+    });
+}
+
+}

+ 61 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/BasicShapeStyleValue.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024, MacDue <macdue@dueutil.tech>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Variant.h>
+#include <LibGfx/Path.h>
+#include <LibWeb/CSS/PercentageOr.h>
+#include <LibWeb/CSS/StyleValue.h>
+
+namespace Web::CSS {
+
+struct Polygon {
+    struct Point {
+        bool operator==(Point const&) const = default;
+        LengthPercentage x;
+        LengthPercentage y;
+    };
+
+    Gfx::Path to_path(CSSPixelRect reference_box, Layout::Node const&) const;
+    String to_string() const;
+
+    bool operator==(Polygon const&) const = default;
+
+    FillRule fill_rule;
+    Vector<Point> points;
+};
+
+// FIXME: Implement other basic shapes. See: https://www.w3.org/TR/css-shapes-1/#basic-shape-functions
+using BasicShape = Variant<Polygon>;
+
+class BasicShapeStyleValue : public StyleValueWithDefaultOperators<BasicShapeStyleValue> {
+public:
+    static ValueComparingNonnullRefPtr<BasicShapeStyleValue> create(BasicShape basic_shape)
+    {
+        return adopt_ref(*new (nothrow) BasicShapeStyleValue(move(basic_shape)));
+    }
+    virtual ~BasicShapeStyleValue() override;
+
+    BasicShape const& basic_shape() const { return m_basic_shape; }
+
+    virtual String to_string() const override;
+
+    bool properties_equal(BasicShapeStyleValue const& other) const { return m_basic_shape == other.m_basic_shape; }
+
+    Gfx::Path to_path(CSSPixelRect reference_box, Layout::Node const&) const;
+
+private:
+    BasicShapeStyleValue(BasicShape basic_shape)
+        : StyleValueWithDefaultOperators(Type::BasicShape)
+        , m_basic_shape(move(basic_shape))
+    {
+    }
+
+    BasicShape m_basic_shape;
+};
+
+}

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

@@ -92,6 +92,7 @@ class AnglePercentage;
 class AngleStyleValue;
 class BackgroundRepeatStyleValue;
 class BackgroundSizeStyleValue;
+class BasicShapeStyleValue;
 class BorderRadiusStyleValue;
 class CSSAnimation;
 class CSSConditionRule;