From 778759517e8bd8520bce936d62dd3a7319ca0b16 Mon Sep 17 00:00:00 2001 From: Callum Law Date: Thu, 3 Jul 2025 23:20:10 +1200 Subject: [PATCH] LibWeb: Support `calc`s which resolve to numbers as hue values in colors Gains us 5 new WPT tests. --- .../LibWeb/CSS/StyleValues/CSSColorValue.cpp | 17 +++++++++++++++-- .../css-color/parsing/color-computed-hsl.txt | 12 ++++++------ .../css-color/parsing/color-computed-hwb.txt | 6 +++--- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Libraries/LibWeb/CSS/StyleValues/CSSColorValue.cpp b/Libraries/LibWeb/CSS/StyleValues/CSSColorValue.cpp index c0ebb698bc7..2279c828d64 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CSSColorValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/CSSColorValue.cpp @@ -34,6 +34,14 @@ Optional CSSColorValue::resolve_hue(CSSStyleValue const& style_value, Ca { // | | none auto normalized = [](double number) { + // +inf should be clamped to 360 + if (!isfinite(number) && number > 0) + number = 360.0; + + // -inf and NaN should be clamped to 0 + if (!isfinite(number) || isnan(number)) + number = 0.0; + return JS::modulo(number, 360.0); }; @@ -43,8 +51,13 @@ Optional CSSColorValue::resolve_hue(CSSStyleValue const& style_value, Ca if (style_value.is_angle()) return normalized(style_value.as_angle().angle().to_degrees()); - if (style_value.is_calculated() && style_value.as_calculated().resolves_to_angle()) - return normalized(style_value.as_calculated().resolve_angle(resolution_context).value().to_degrees()); + if (style_value.is_calculated()) { + if (style_value.as_calculated().resolves_to_number()) + return normalized(style_value.as_calculated().resolve_number(resolution_context).value()); + + if (style_value.as_calculated().resolves_to_angle()) + return normalized(style_value.as_calculated().resolve_angle(resolution_context).value().to_degrees()); + } if (style_value.is_keyword() && style_value.to_keyword() == Keyword::None) return 0; diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt index eb707359aba..690d9234c4d 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt @@ -2,8 +2,8 @@ Harness status: OK Found 3753 tests -3747 Pass -6 Fail +3751 Pass +2 Fail Pass Property color value 'hsl(120 30% 50%)' Pass Property color value 'hsl(120 30% 50% / 0.5)' Pass Property color value 'hsl(120 30% 50% / 50%)' @@ -3741,16 +3741,16 @@ Pass Property color value 'hsl(360, 37.5%, 75%)' [HSL/HSLA value should parse an Pass Property color value 'hsla(360, 37.5%, 75%, 0)' [HSL/HSLA value should parse and round correctly] Pass Property color value 'hsl(calc(50deg + (sign(1em - 10px) * 10deg)), 100%, 37.5%, 50%)' Pass Property color value 'hsla(calc(50deg + (sign(1em - 10px) * 10deg)), 100%, 37.5%, 50%)' -Fail Property color value 'hsl(calc(50 + (sign(1em - 10px) * 10)), 100%, 37.5%, 50%)' -Fail Property color value 'hsla(calc(50 + (sign(1em - 10px) * 10)), 100%, 37.5%, 50%)' +Pass Property color value 'hsl(calc(50 + (sign(1em - 10px) * 10)), 100%, 37.5%, 50%)' +Pass Property color value 'hsla(calc(50 + (sign(1em - 10px) * 10)), 100%, 37.5%, 50%)' Pass Property color value 'hsl(60deg, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' Pass Property color value 'hsla(60deg, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' Pass Property color value 'hsl(60, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' Pass Property color value 'hsla(60, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' Pass Property color value 'hsl(calc(50deg + (sign(1em - 10px) * 10deg)) 100% 37.5% / 50%)' Pass Property color value 'hsla(calc(50deg + (sign(1em - 10px) * 10deg)) 100% 37.5% / 50%)' -Fail Property color value 'hsl(calc(50 + (sign(1em - 10px) * 10)) 100 37.5 / 0.5)' -Fail Property color value 'hsla(calc(50 + (sign(1em - 10px) * 10)) 100 37.5 / 0.5)' +Pass Property color value 'hsl(calc(50 + (sign(1em - 10px) * 10)) 100 37.5 / 0.5)' +Pass Property color value 'hsla(calc(50 + (sign(1em - 10px) * 10)) 100 37.5 / 0.5)' Pass Property color value 'hsl(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) * 10%)))' Pass Property color value 'hsla(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) * 10%)))' Pass Property color value 'hsl(60 100 37.5 / calc(0.75 + (sign(1em - 10px) * 0.1)))' diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt index 9902c65b690..6663fb08c5a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt @@ -2,8 +2,8 @@ Harness status: OK Found 56 tests -53 Pass -3 Fail +54 Pass +2 Fail Pass Property color value 'hwb(120 30% 50%)' Pass Property color value 'hwb(120 30% 50% / 0.5)' Pass Property color value 'hwb(120 30% 50% / 50%)' @@ -55,7 +55,7 @@ Pass Property color value 'hwb(90 50% 50% / 0)' [HWB value should parse and roun Pass Property color value 'hwb(90 50% 50% / 0.2)' [HWB value should parse and round correctly] Pass Property color value 'hwb(90 50% 50% / 1)' [HWB value should parse and round correctly] Pass Property color value 'hwb(calc(110deg + (sign(1em - 10px) * 10deg)) 30% 50% / 50%)' -Fail Property color value 'hwb(calc(110 + (sign(1em - 10px) * 10)) 30 50 / 0.5)' +Pass Property color value 'hwb(calc(110 + (sign(1em - 10px) * 10)) 30 50 / 0.5)' Pass Property color value 'hwb(120deg 30% 50% / calc(50% + (sign(1em - 10px) * 10%)))' Pass Property color value 'hwb(120 30 50 / calc(0.75 + (sign(1em - 10px) * 0.1)))' Fail Property color value 'hwb(calc(110deg + (sign(2cqw - 10px) * 10deg)) 30 50 / 51%)'