diff --git a/Tests/LibWeb/Text/expected/canvas/fillStyle-serialization.txt b/Tests/LibWeb/Text/expected/canvas/fillStyle-serialization.txt new file mode 100644 index 00000000000..4668e2a5939 --- /dev/null +++ b/Tests/LibWeb/Text/expected/canvas/fillStyle-serialization.txt @@ -0,0 +1,5 @@ +`green` -> `#008000` +`rgba(128, 128, 128, 0.4)` -> `rgba(128, 128, 128, 0.4)` +`rgba(128, 128, 128, 0)` -> `rgba(128, 128, 128, 0)` +`rgba(128, 128, 128, 1)` -> `#808080` +`rgb(128, 128, 128)` -> `#808080` diff --git a/Tests/LibWeb/Text/expected/canvas/fillstyle.txt b/Tests/LibWeb/Text/expected/canvas/fillstyle.txt index df993731f86..855bcb42cb8 100644 --- a/Tests/LibWeb/Text/expected/canvas/fillstyle.txt +++ b/Tests/LibWeb/Text/expected/canvas/fillstyle.txt @@ -1,5 +1,5 @@ -1. "#00ff00ff" -2. "#ff0000ff" -3. "#0000ffff" -4. "#00ff00ff" -5. "#ff0000ff" +1. "#00ff00" +2. "#ff0000" +3. "#0000ff" +4. "#00ff00" +5. "#ff0000" diff --git a/Tests/LibWeb/Text/input/canvas/fillStyle-serialization.html b/Tests/LibWeb/Text/input/canvas/fillStyle-serialization.html new file mode 100644 index 00000000000..c823232e387 --- /dev/null +++ b/Tests/LibWeb/Text/input/canvas/fillStyle-serialization.html @@ -0,0 +1,18 @@ + + + diff --git a/Userland/Libraries/LibGfx/Color.cpp b/Userland/Libraries/LibGfx/Color.cpp index 4071543e697..b63904c0d92 100644 --- a/Userland/Libraries/LibGfx/Color.cpp +++ b/Userland/Libraries/LibGfx/Color.cpp @@ -23,9 +23,29 @@ namespace Gfx { -String Color::to_string() const +String Color::to_string(HTMLCompatibleSerialization html_compatible_serialization) const { - return MUST(String::formatted("#{:02x}{:02x}{:02x}{:02x}", red(), green(), blue(), alpha())); + // If the following conditions are all true: + + // 1. The color space is sRGB + // NOTE: This is currently always true for Gfx::Color. + + // 2. The alpha is 1 + // NOTE: An alpha value of 1 will be stored as 255 currently. + + // 3. The RGB component values are internally represented as integers between 0 and 255 inclusive (i.e. 8-bit unsigned integer) + // NOTE: This is currently always true for Gfx::Color. + + // 4. HTML-compatible serialization is requested + if (alpha() == 255 + && html_compatible_serialization == HTMLCompatibleSerialization::Yes) { + return MUST(String::formatted("#{:02x}{:02x}{:02x}", red(), green(), blue())); + } + + // Otherwise, for sRGB the CSS serialization of sRGB values is used and for other color spaces, the relevant serialization of the value. + if (alpha() < 255) + return MUST(String::formatted("rgba({}, {}, {}, {})", red(), green(), blue(), alpha() / 255.0)); + return MUST(String::formatted("rgb({}, {}, {})", red(), green(), blue())); } String Color::to_string_without_alpha() const diff --git a/Userland/Libraries/LibGfx/Color.h b/Userland/Libraries/LibGfx/Color.h index 8d023081425..f00a48b71b9 100644 --- a/Userland/Libraries/LibGfx/Color.h +++ b/Userland/Libraries/LibGfx/Color.h @@ -446,7 +446,12 @@ public: return m_value == other.m_value; } - String to_string() const; + enum class HTMLCompatibleSerialization { + No, + Yes, + }; + + [[nodiscard]] String to_string(HTMLCompatibleSerialization = HTMLCompatibleSerialization::No) const; String to_string_without_alpha() const; ByteString to_byte_string() const; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 0c932e45b8b..bdfa04adaf9 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -2847,6 +2847,7 @@ RefPtr Parser::parse_rgb_color_value(TokenStream& inner_tokens.skip_whitespace(); alpha = parse_number_percentage_value(inner_tokens); + inner_tokens.skip_whitespace(); if (inner_tokens.has_next_token()) diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasState.h b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasState.h index 547ef519a82..1eb24a3b889 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasState.h +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasState.h @@ -63,7 +63,7 @@ public: { return m_fill_or_stroke_style.visit( [&](Gfx::Color color) -> JsFillOrStrokeStyle { - return color.to_string(); + return color.to_string(Gfx::Color::HTMLCompatibleSerialization::Yes); }, [&](auto handle) -> JsFillOrStrokeStyle { return handle;