From d89a67ffee2a6dd8b11a1b178b9bc678a2da9e9a Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Sat, 14 Jun 2025 04:06:01 +0100 Subject: [PATCH] LibWeb: Don't serialize omitted `box-shadow` and `text-shadow` values --- .../LibWeb/CSS/Parser/PropertyParsing.cpp | 12 +--- .../CSS/StyleValues/ShadowStyleValue.cpp | 51 ++++++++++++-- .../LibWeb/CSS/StyleValues/ShadowStyleValue.h | 28 ++++---- .../parsing/box-shadow-valid.txt | 43 ++++++++++++ .../text-shadow/parsing/text-shadow-valid.txt | 15 +++++ .../parsing/box-shadow-valid.html | 67 +++++++++++++++++++ .../parsing/text-shadow-valid.html | 22 ++++++ 7 files changed, 207 insertions(+), 31 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.html diff --git a/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp b/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp index 19a0708a30e..fab5dc2b520 100644 --- a/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp @@ -1921,26 +1921,16 @@ RefPtr Parser::parse_single_shadow_value(TokenStream Parser::parse_rotate_value(TokenStream& tokens) diff --git a/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.cpp index f6554624c4f..dbe7ab58c58 100644 --- a/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.cpp @@ -8,6 +8,8 @@ */ #include +#include +#include #include namespace Web::CSS { @@ -15,19 +17,56 @@ namespace Web::CSS { String ShadowStyleValue::to_string(SerializationMode mode) const { StringBuilder builder; - builder.appendff("{} {} {} {} {}", m_properties.color->to_string(mode), m_properties.offset_x->to_string(mode), m_properties.offset_y->to_string(mode), m_properties.blur_radius->to_string(mode), m_properties.spread_distance->to_string(mode)); + if (m_properties.color) + builder.append(m_properties.color->to_string(mode)); + + if (!builder.is_empty()) + builder.append(' '); + builder.appendff("{} {}", m_properties.offset_x->to_string(mode), m_properties.offset_y->to_string(mode)); + + auto append_value = [&](ValueComparingRefPtr const& value) { + if (!value) + return; + if (!builder.is_empty()) + builder.append(' '); + builder.append(value->to_string(mode)); + }; + append_value(m_properties.blur_radius); + append_value(m_properties.spread_distance); + if (m_properties.placement == ShadowPlacement::Inner) builder.append(" inset"sv); return MUST(builder.to_string()); } +ValueComparingNonnullRefPtr ShadowStyleValue::color() const +{ + if (!m_properties.color) + return CSSKeywordValue::create(Keyword::Currentcolor); + return *m_properties.color; +} + +ValueComparingNonnullRefPtr ShadowStyleValue::blur_radius() const +{ + if (!m_properties.blur_radius) + return LengthStyleValue::create(Length::make_px(0)); + return *m_properties.blur_radius; +} + +ValueComparingNonnullRefPtr ShadowStyleValue::spread_distance() const +{ + if (!m_properties.spread_distance) + return LengthStyleValue::create(Length::make_px(0)); + return *m_properties.spread_distance; +} + ValueComparingNonnullRefPtr ShadowStyleValue::absolutized(CSSPixelRect const& viewport_rect, Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const { - auto absolutized_offset_x = m_properties.offset_x->absolutized(viewport_rect, font_metrics, root_font_metrics); - auto absolutized_offset_y = m_properties.offset_y->absolutized(viewport_rect, font_metrics, root_font_metrics); - auto absolutized_blur_radius = m_properties.blur_radius->absolutized(viewport_rect, font_metrics, root_font_metrics); - auto absolutized_spread_distance = m_properties.spread_distance->absolutized(viewport_rect, font_metrics, root_font_metrics); - return ShadowStyleValue::create(m_properties.color, absolutized_offset_x, absolutized_offset_y, absolutized_blur_radius, absolutized_spread_distance, m_properties.placement); + auto absolutized_offset_x = offset_x()->absolutized(viewport_rect, font_metrics, root_font_metrics); + auto absolutized_offset_y = offset_y()->absolutized(viewport_rect, font_metrics, root_font_metrics); + auto absolutized_blur_radius = blur_radius()->absolutized(viewport_rect, font_metrics, root_font_metrics); + auto absolutized_spread_distance = spread_distance()->absolutized(viewport_rect, font_metrics, root_font_metrics); + return create(color(), absolutized_offset_x, absolutized_offset_y, absolutized_blur_radius, absolutized_spread_distance, placement()); } } diff --git a/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.h index d057c520d90..9446e2c7e1a 100644 --- a/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/ShadowStyleValue.h @@ -23,22 +23,22 @@ enum class ShadowPlacement { class ShadowStyleValue final : public StyleValueWithDefaultOperators { public: static ValueComparingNonnullRefPtr create( - ValueComparingNonnullRefPtr color, + ValueComparingRefPtr color, ValueComparingNonnullRefPtr offset_x, ValueComparingNonnullRefPtr offset_y, - ValueComparingNonnullRefPtr blur_radius, - ValueComparingNonnullRefPtr spread_distance, + ValueComparingRefPtr blur_radius, + ValueComparingRefPtr spread_distance, ShadowPlacement placement) { return adopt_ref(*new (nothrow) ShadowStyleValue(move(color), move(offset_x), move(offset_y), move(blur_radius), move(spread_distance), placement)); } virtual ~ShadowStyleValue() override = default; - ValueComparingNonnullRefPtr const& color() const { return m_properties.color; } - ValueComparingNonnullRefPtr const& offset_x() const { return m_properties.offset_x; } - ValueComparingNonnullRefPtr const& offset_y() const { return m_properties.offset_y; } - ValueComparingNonnullRefPtr const& blur_radius() const { return m_properties.blur_radius; } - ValueComparingNonnullRefPtr const& spread_distance() const { return m_properties.spread_distance; } + ValueComparingNonnullRefPtr color() const; + ValueComparingNonnullRefPtr offset_x() const { return m_properties.offset_x; } + ValueComparingNonnullRefPtr offset_y() const { return m_properties.offset_y; } + ValueComparingNonnullRefPtr blur_radius() const; + ValueComparingNonnullRefPtr spread_distance() const; ShadowPlacement placement() const { return m_properties.placement; } virtual String to_string(SerializationMode) const override; @@ -47,11 +47,11 @@ public: private: ShadowStyleValue( - ValueComparingNonnullRefPtr color, + ValueComparingRefPtr color, ValueComparingNonnullRefPtr offset_x, ValueComparingNonnullRefPtr offset_y, - ValueComparingNonnullRefPtr blur_radius, - ValueComparingNonnullRefPtr spread_distance, + ValueComparingRefPtr blur_radius, + ValueComparingRefPtr spread_distance, ShadowPlacement placement) : StyleValueWithDefaultOperators(Type::Shadow) , m_properties { @@ -68,11 +68,11 @@ private: virtual ValueComparingNonnullRefPtr absolutized(CSSPixelRect const& viewport_rect, Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const override; struct Properties { - ValueComparingNonnullRefPtr color; + ValueComparingRefPtr color; ValueComparingNonnullRefPtr offset_x; ValueComparingNonnullRefPtr offset_y; - ValueComparingNonnullRefPtr blur_radius; - ValueComparingNonnullRefPtr spread_distance; + ValueComparingRefPtr blur_radius; + ValueComparingRefPtr spread_distance; ShadowPlacement placement; bool operator==(Properties const&) const = default; } m_properties; diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.txt new file mode 100644 index 00000000000..eb644450058 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.txt @@ -0,0 +1,43 @@ +Harness status: OK + +Found 38 tests + +38 Pass +Pass e.style['box-shadow'] = "none" should set the property value +Pass e.style['box-shadow'] = "1px 2px" should set the property value +Pass e.style['box-shadow'] = "red 1px 2px 3px -4px inset" should set the property value +Pass e.style['box-shadow'] = "inset 1px 2px red" should set the property value +Pass e.style['box-shadow'] = "1px -2px inset, red -3px 4px" should set the property value +Pass e.style['box-shadow'] = "inset 1px -2px, -3px 4px red" should set the property value +Pass e.style['box-shadow'] = "4px 4px green" should set the property value +Pass e.style['box-shadow'] = "green -4px 4px" should set the property value +Pass e.style['box-shadow'] = "-4px 4px 0 green" should set the property value +Pass e.style['box-shadow'] = "green -4px 4px 0" should set the property value +Pass e.style['box-shadow'] = "-4px 4px 0 0 green" should set the property value +Pass e.style['box-shadow'] = "green -4px 4px 0 0" should set the property value +Pass e.style['box-shadow'] = "4px -4px inset" should set the property value +Pass e.style['box-shadow'] = "inset 4px -4px" should set the property value +Pass e.style['box-shadow'] = "4px -4px 0 inset" should set the property value +Pass e.style['box-shadow'] = "inset 4px -4px 0" should set the property value +Pass e.style['box-shadow'] = "4px -4px 0 0 inset" should set the property value +Pass e.style['box-shadow'] = "inset 4px -4px 0 0" should set the property value +Pass e.style['box-shadow'] = "4px -4px green inset" should set the property value +Pass e.style['box-shadow'] = "4px -4px inset green" should set the property value +Pass e.style['box-shadow'] = "inset green 4px -4px" should set the property value +Pass e.style['box-shadow'] = "green inset 4px -4px" should set the property value +Pass e.style['box-shadow'] = "green 4px -4px inset" should set the property value +Pass e.style['box-shadow'] = "inset 4px -4px green" should set the property value +Pass e.style['box-shadow'] = "inset green 4px -4px 0" should set the property value +Pass e.style['box-shadow'] = "green inset 4px -4px 0" should set the property value +Pass e.style['box-shadow'] = "4px -4px 0 green inset" should set the property value +Pass e.style['box-shadow'] = "4px -4px 0 inset green" should set the property value +Pass e.style['box-shadow'] = "green 4px -4px 0 inset" should set the property value +Pass e.style['box-shadow'] = "inset 4px -4px 0 green" should set the property value +Pass e.style['box-shadow'] = "inset green 4px -4px 0 0" should set the property value +Pass e.style['box-shadow'] = "green inset 4px -4px 0 0" should set the property value +Pass e.style['box-shadow'] = "4px -4px 0 0 green inset" should set the property value +Pass e.style['box-shadow'] = "4px -4px 0 0 inset green" should set the property value +Pass e.style['box-shadow'] = "green 4px -4px 0 0 inset" should set the property value +Pass e.style['box-shadow'] = "inset 4px -4px 0 0 green" should set the property value +Pass e.style['box-shadow'] = "1px 1px calc(-1px)" should set the property value +Pass e.style['box-shadow'] = "1px 1px calc(1em - 2px)" should set the property value \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.txt new file mode 100644 index 00000000000..49de50a987c --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.txt @@ -0,0 +1,15 @@ +Harness status: OK + +Found 10 tests + +10 Pass +Pass e.style['text-shadow'] = "none" should set the property value +Pass e.style['text-shadow'] = "10px 20px" should set the property value +Pass e.style['text-shadow'] = "10px 20px 30px" should set the property value +Pass e.style['text-shadow'] = "calc(1em + 2px) calc(3em + 4px) calc(5em + 6px)" should set the property value +Pass e.style['text-shadow'] = "-10px 20px 30px" should set the property value +Pass e.style['text-shadow'] = "10px -20px 30px" should set the property value +Pass e.style['text-shadow'] = "rgb(255, 0, 0) 10px 20px" should set the property value +Pass e.style['text-shadow'] = "10px 20px 30px lime" should set the property value +Pass e.style['text-shadow'] = "10px 20px, 30px 40px" should set the property value +Pass e.style['text-shadow'] = "lime 10px 20px 30px, blue 40px 50px" should set the property value \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.html b/Tests/LibWeb/Text/input/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.html new file mode 100644 index 00000000000..a1c08c6bb8e --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-backgrounds/parsing/box-shadow-valid.html @@ -0,0 +1,67 @@ + + + + +CSS Backgrounds and Borders Module Level 3: parsing box-shadow with valid values + + + + + + + + + + + + + diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.html b/Tests/LibWeb/Text/input/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.html new file mode 100644 index 00000000000..930338b6fb3 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-text-decor/text-shadow/parsing/text-shadow-valid.html @@ -0,0 +1,22 @@ + + +CSS Text Decoration Test: Parsing text-shadow with valid values + + + + + +