فهرست منبع

LibWeb/CSS: Add support for the `lch` color function

This makes us pass all `css/css-color/lch-00*.html` tests.
Lucas CHOLLET 8 ماه پیش
والد
کامیت
f253246a6c

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

@@ -3385,6 +3385,26 @@ Optional<Array<RefPtr<CSSStyleValue>, 4>> Parser::parse_lch_like_color_value(Tok
     return Array { move(l), move(c), move(h), move(alpha) };
 }
 
+// https://www.w3.org/TR/css-color-4/#funcdef-lch
+RefPtr<CSSStyleValue> Parser::parse_lch_color_value(TokenStream<ComponentValue>& outer_tokens)
+{
+    // lch() = lch( [<percentage> | <number> | none]
+    //      [ <percentage> | <number> | none]
+    //      [ <hue> | none]
+    //      [ / [<alpha-value> | none] ]? )
+
+    auto maybe_color_values = parse_lch_like_color_value(outer_tokens, "lch"sv);
+    if (!maybe_color_values.has_value())
+        return {};
+
+    auto& color_values = *maybe_color_values;
+
+    return CSSLCHLike::create<CSSLCH>(color_values[0].release_nonnull(),
+        color_values[1].release_nonnull(),
+        color_values[2].release_nonnull(),
+        color_values[3].release_nonnull());
+}
+
 // https://www.w3.org/TR/css-color-4/#funcdef-oklch
 RefPtr<CSSStyleValue> Parser::parse_oklch_color_value(TokenStream<ComponentValue>& outer_tokens)
 {
@@ -3490,6 +3510,8 @@ RefPtr<CSSStyleValue> Parser::parse_color_value(TokenStream<ComponentValue>& tok
         return hwb;
     if (auto lab = parse_lab_color_value(tokens))
         return lab;
+    if (auto lch = parse_lch_color_value(tokens))
+        return lch;
     if (auto oklab = parse_oklab_color_value(tokens))
         return oklab;
     if (auto oklch = parse_oklch_color_value(tokens))

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

@@ -254,6 +254,7 @@ private:
     RefPtr<CSSStyleValue> parse_lab_color_value(TokenStream<ComponentValue>&);
     RefPtr<CSSStyleValue> parse_oklab_color_value(TokenStream<ComponentValue>&);
     Optional<Array<RefPtr<CSSStyleValue>, 4>> parse_lch_like_color_value(TokenStream<ComponentValue>&, StringView);
+    RefPtr<CSSStyleValue> parse_lch_color_value(TokenStream<ComponentValue>&);
     RefPtr<CSSStyleValue> parse_oklch_color_value(TokenStream<ComponentValue>&);
     RefPtr<CSSStyleValue> parse_color_function(TokenStream<ComponentValue>&);
     RefPtr<CSSStyleValue> parse_color_value(TokenStream<ComponentValue>&);

+ 1 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/CSSColorValue.h

@@ -27,6 +27,7 @@ public:
         HSL,
         HWB,
         Lab,
+        LCH,
         OKLab,
         OKLCH,
         XYZD50,

+ 17 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/CSSLCHLike.cpp

@@ -25,6 +25,23 @@ bool CSSLCHLike::equals(CSSStyleValue const& other) const
     return m_properties == other_oklch_like.m_properties;
 }
 
+Color CSSLCH::to_color(Optional<Layout::NodeWithStyle const&>) const
+{
+    auto const l_val = clamp(resolve_with_reference_value(m_properties.l, 100).value_or(0), 0, 100);
+    auto const c_val = resolve_with_reference_value(m_properties.c, 150).value_or(0);
+    auto const h_val = AK::to_radians(resolve_hue(m_properties.h).value_or(0));
+    auto const alpha_val = resolve_alpha(m_properties.alpha).value_or(1);
+
+    return Color::from_lab(l_val, c_val * cos(h_val), c_val * sin(h_val), alpha_val);
+}
+
+// https://www.w3.org/TR/css-color-4/#serializing-lab-lch
+String CSSLCH::to_string() const
+{
+    // FIXME: Do this properly, taking unresolved calculated values into account.
+    return serialize_a_srgb_value(to_color({}));
+}
+
 Color CSSOKLCH::to_color(Optional<Layout::NodeWithStyle const&>) const
 {
     auto const l_val = clamp(resolve_with_reference_value(m_properties.l, 1.0).value_or(0), 0, 1);

+ 15 - 1
Userland/Libraries/LibWeb/CSS/StyleValues/CSSLCHLike.h

@@ -14,7 +14,7 @@ namespace Web::CSS {
 class CSSLCHLike : public CSSColorValue {
 public:
     template<DerivedFrom<CSSLCHLike> T>
-    static ValueComparingNonnullRefPtr<CSSOKLCH> create(ValueComparingNonnullRefPtr<CSSStyleValue> l, ValueComparingNonnullRefPtr<CSSStyleValue> c, ValueComparingNonnullRefPtr<CSSStyleValue> h, ValueComparingRefPtr<CSSStyleValue> alpha = {})
+    static ValueComparingNonnullRefPtr<T> create(ValueComparingNonnullRefPtr<CSSStyleValue> l, ValueComparingNonnullRefPtr<CSSStyleValue> c, ValueComparingNonnullRefPtr<CSSStyleValue> h, ValueComparingRefPtr<CSSStyleValue> alpha = {})
     {
         // alpha defaults to 1
         if (!alpha)
@@ -47,6 +47,20 @@ protected:
     } m_properties;
 };
 
+// https://drafts.css-houdini.org/css-typed-om-1/#csslch
+class CSSLCH final : public CSSLCHLike {
+public:
+    CSSLCH(Badge<CSSLCHLike>, ValueComparingNonnullRefPtr<CSSStyleValue> l, ValueComparingNonnullRefPtr<CSSStyleValue> c, ValueComparingNonnullRefPtr<CSSStyleValue> h, ValueComparingNonnullRefPtr<CSSStyleValue> alpha)
+        : CSSLCHLike(ColorType::LCH, move(l), move(c), move(h), move(alpha))
+    {
+    }
+    virtual ~CSSLCH() override = default;
+
+    virtual Color to_color(Optional<Layout::NodeWithStyle const&>) const override;
+
+    virtual String to_string() const override;
+};
+
 // https://drafts.css-houdini.org/css-typed-om-1/#cssoklch
 class CSSOKLCH final : public CSSLCHLike {
 public: