LibWeb: Implement the color-interpolation property for SVG gradients

This changes the operating color space for gradient `<linearGradient>`
and `<radialGradient>` elements.
This commit is contained in:
Tim Ledbetter 2025-08-15 23:53:15 +01:00 committed by Jelle Raaijmakers
commit ad06ac0d58
Notes: github-actions[bot] 2025-08-17 08:52:13 +00:00
29 changed files with 192 additions and 13 deletions

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
namespace Gfx {
enum class InterpolationColorSpace {
LinearRGB,
SRGB,
};
}

View file

@ -232,6 +232,12 @@ Color ComputedProperties::color_or_fallback(PropertyID id, ColorResolutionContex
return value.to_color(color_resolution_context).value(); return value.to_color(color_resolution_context).value();
} }
ColorInterpolation ComputedProperties::color_interpolation() const
{
auto const& value = property(PropertyID::ColorInterpolation);
return keyword_to_color_interpolation(value.to_keyword()).value_or(CSS::ColorInterpolation::Auto);
}
// https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme // https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme
PreferredColorScheme ComputedProperties::color_scheme(PreferredColorScheme preferred_scheme, Optional<Vector<String> const&> document_supported_schemes) const PreferredColorScheme ComputedProperties::color_scheme(PreferredColorScheme preferred_scheme, Optional<Vector<String> const&> document_supported_schemes) const
{ {

View file

@ -78,6 +78,7 @@ public:
Optional<LengthPercentage> length_percentage(PropertyID) const; Optional<LengthPercentage> length_percentage(PropertyID) const;
LengthBox length_box(PropertyID left_id, PropertyID top_id, PropertyID right_id, PropertyID bottom_id, Length const& default_value) const; LengthBox length_box(PropertyID left_id, PropertyID top_id, PropertyID right_id, PropertyID bottom_id, Length const& default_value) const;
Color color_or_fallback(PropertyID, ColorResolutionContext, Color fallback) const; Color color_or_fallback(PropertyID, ColorResolutionContext, Color fallback) const;
ColorInterpolation color_interpolation() const;
PreferredColorScheme color_scheme(PreferredColorScheme, Optional<Vector<String> const&> document_supported_schemes) const; PreferredColorScheme color_scheme(PreferredColorScheme, Optional<Vector<String> const&> document_supported_schemes) const;
TextAnchor text_anchor() const; TextAnchor text_anchor() const;
TextAlign text_align() const; TextAlign text_align() const;

View file

@ -104,6 +104,7 @@ public:
static Color caret_color() { return Color::Black; } static Color caret_color() { return Color::Black; }
static CSS::Clear clear() { return CSS::Clear::None; } static CSS::Clear clear() { return CSS::Clear::None; }
static CSS::Clip clip() { return CSS::Clip::make_auto(); } static CSS::Clip clip() { return CSS::Clip::make_auto(); }
static CSS::ColorInterpolation color_interpolation() { return CSS::ColorInterpolation::Auto; }
static CSS::PreferredColorScheme color_scheme() { return CSS::PreferredColorScheme::Auto; } static CSS::PreferredColorScheme color_scheme() { return CSS::PreferredColorScheme::Auto; }
static CSS::ContentVisibility content_visibility() { return CSS::ContentVisibility::Visible; } static CSS::ContentVisibility content_visibility() { return CSS::ContentVisibility::Visible; }
static CursorData cursor() { return { CSS::CursorPredefined::Auto }; } static CursorData cursor() { return { CSS::CursorPredefined::Auto }; }
@ -428,6 +429,7 @@ public:
Color caret_color() const { return m_inherited.caret_color; } Color caret_color() const { return m_inherited.caret_color; }
CSS::Clear clear() const { return m_noninherited.clear; } CSS::Clear clear() const { return m_noninherited.clear; }
CSS::Clip clip() const { return m_noninherited.clip; } CSS::Clip clip() const { return m_noninherited.clip; }
CSS::ColorInterpolation color_interpolation() const { return m_inherited.color_interpolation; }
CSS::PreferredColorScheme color_scheme() const { return m_inherited.color_scheme; } CSS::PreferredColorScheme color_scheme() const { return m_inherited.color_scheme; }
CSS::ContentVisibility content_visibility() const { return m_inherited.content_visibility; } CSS::ContentVisibility content_visibility() const { return m_inherited.content_visibility; }
Vector<CursorData> const& cursor() const { return m_inherited.cursor; } Vector<CursorData> const& cursor() const { return m_inherited.cursor; }
@ -638,6 +640,7 @@ protected:
CSS::Length border_spacing_vertical { InitialValues::border_spacing() }; CSS::Length border_spacing_vertical { InitialValues::border_spacing() };
CSS::CaptionSide caption_side { InitialValues::caption_side() }; CSS::CaptionSide caption_side { InitialValues::caption_side() };
Color color { InitialValues::color() }; Color color { InitialValues::color() };
CSS::ColorInterpolation color_interpolation { InitialValues::color_interpolation() };
CSS::PreferredColorScheme color_scheme { InitialValues::color_scheme() }; CSS::PreferredColorScheme color_scheme { InitialValues::color_scheme() };
Optional<Color> accent_color {}; Optional<Color> accent_color {};
Color webkit_text_fill_color { InitialValues::color() }; Color webkit_text_fill_color { InitialValues::color() };
@ -837,6 +840,7 @@ public:
void set_border_spacing_vertical(CSS::Length border_spacing_vertical) { m_inherited.border_spacing_vertical = border_spacing_vertical; } void set_border_spacing_vertical(CSS::Length border_spacing_vertical) { m_inherited.border_spacing_vertical = border_spacing_vertical; }
void set_caption_side(CSS::CaptionSide caption_side) { m_inherited.caption_side = caption_side; } void set_caption_side(CSS::CaptionSide caption_side) { m_inherited.caption_side = caption_side; }
void set_color(Color color) { m_inherited.color = color; } void set_color(Color color) { m_inherited.color = color; }
void set_color_interpolation(CSS::ColorInterpolation color_interpolation) { m_inherited.color_interpolation = color_interpolation; }
void set_color_scheme(CSS::PreferredColorScheme color_scheme) { m_inherited.color_scheme = color_scheme; } void set_color_scheme(CSS::PreferredColorScheme color_scheme) { m_inherited.color_scheme = color_scheme; }
void set_clip(CSS::Clip const& clip) { m_noninherited.clip = clip; } void set_clip(CSS::Clip const& clip) { m_noninherited.clip = clip; }
void set_content(ContentData const& content) { m_noninherited.content = content; } void set_content(ContentData const& content) { m_noninherited.content = content; }

View file

@ -132,6 +132,11 @@
"inline-start", "inline-start",
"inline-end" "inline-end"
], ],
"color-interpolation": [
"auto",
"linearrgb",
"srgb"
],
"column-span": [ "column-span": [
"none", "none",
"all" "all"

View file

@ -301,6 +301,7 @@
"lighter", "lighter",
"line-through", "line-through",
"linear", "linear",
"linearrgb",
"lining-nums", "lining-nums",
"linktext", "linktext",
"list-item", "list-item",

View file

@ -1229,6 +1229,15 @@
"hashless-hex-color" "hashless-hex-color"
] ]
}, },
"color-interpolation": {
"affects-layout": false,
"animation-type": "discrete",
"inherited": true,
"initial": "srgb",
"valid-types": [
"color-interpolation"
]
},
"color-scheme": { "color-scheme": {
"affects-layout": false, "affects-layout": false,
"animation-type": "discrete", "animation-type": "discrete",

View file

@ -1017,6 +1017,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
computed_values.set_contain(computed_style.contain()); computed_values.set_contain(computed_style.contain());
computed_values.set_caret_color(computed_style.caret_color(*this)); computed_values.set_caret_color(computed_style.caret_color(*this));
computed_values.set_color_interpolation(computed_style.color_interpolation());
propagate_style_to_anonymous_wrappers(); propagate_style_to_anonymous_wrappers();

View file

@ -633,6 +633,9 @@ static SkPaint paint_style_to_skia_paint(Painting::SVGGradientPaintStyle const&
shader = SkGradientShader::MakeTwoPointConical(start_center, start_radius, end_center, end_radius, colors.data(), positions.data(), color_stops.size(), tile_mode, 0, &matrix); shader = SkGradientShader::MakeTwoPointConical(start_center, start_radius, end_center, end_radius, colors.data(), positions.data(), color_stops.size(), tile_mode, 0, &matrix);
} }
paint.setShader(shader); paint.setShader(shader);
if (auto* gradient_paint_style = as_if<SVGGradientPaintStyle>(paint_style); gradient_paint_style->color_space() == Gfx::InterpolationColorSpace::LinearRGB) {
paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
}
return paint; return paint;
} }

View file

@ -7,6 +7,7 @@
#pragma once #pragma once
#include <AK/AtomicRefCounted.h> #include <AK/AtomicRefCounted.h>
#include <LibGfx/InterpolationColorSpace.h>
#include <LibGfx/PaintStyle.h> #include <LibGfx/PaintStyle.h>
namespace Web::Painting { namespace Web::Painting {
@ -46,6 +47,9 @@ public:
ReadonlySpan<ColorStop> color_stops() const { return m_color_stops; } ReadonlySpan<ColorStop> color_stops() const { return m_color_stops; }
Optional<float> repeat_length() const { return m_repeat_length; } Optional<float> repeat_length() const { return m_repeat_length; }
Gfx::InterpolationColorSpace color_space() const { return m_color_space; }
void set_color_space(Gfx::InterpolationColorSpace color_space) { m_color_space = color_space; }
virtual ~SVGGradientPaintStyle() { } virtual ~SVGGradientPaintStyle() { }
protected: protected:
@ -54,6 +58,7 @@ protected:
Optional<Gfx::AffineTransform> m_gradient_transform {}; Optional<Gfx::AffineTransform> m_gradient_transform {};
SpreadMethod m_spread_method { SpreadMethod::Pad }; SpreadMethod m_spread_method { SpreadMethod::Pad };
Gfx::InterpolationColorSpace m_color_space { Gfx::InterpolationColorSpace::SRGB };
}; };
class SVGLinearGradientPaintStyle final : public SVGGradientPaintStyle { class SVGLinearGradientPaintStyle final : public SVGGradientPaintStyle {

View file

@ -54,6 +54,7 @@ static ReadonlySpan<NamedPropertyID> attribute_style_properties()
NamedPropertyID(CSS::PropertyID::ClipPath), NamedPropertyID(CSS::PropertyID::ClipPath),
NamedPropertyID(CSS::PropertyID::ClipRule), NamedPropertyID(CSS::PropertyID::ClipRule),
NamedPropertyID(CSS::PropertyID::Color), NamedPropertyID(CSS::PropertyID::Color),
NamedPropertyID(CSS::PropertyID::ColorInterpolation),
NamedPropertyID(CSS::PropertyID::Cursor), NamedPropertyID(CSS::PropertyID::Cursor),
NamedPropertyID(CSS::PropertyID::Cx, { SVG::TagNames::circle, SVG::TagNames::ellipse }), NamedPropertyID(CSS::PropertyID::Cx, { SVG::TagNames::circle, SVG::TagNames::ellipse }),
NamedPropertyID(CSS::PropertyID::Cy, { SVG::TagNames::circle, SVG::TagNames::ellipse }), NamedPropertyID(CSS::PropertyID::Cy, { SVG::TagNames::circle, SVG::TagNames::ellipse }),

View file

@ -66,6 +66,19 @@ SpreadMethod SVGGradientElement::spread_method_impl(HashTable<SVGGradientElement
return SpreadMethod::Pad; return SpreadMethod::Pad;
} }
Gfx::InterpolationColorSpace SVGGradientElement::color_space() const
{
switch (computed_properties()->color_interpolation()) {
case CSS::ColorInterpolation::Linearrgb:
return Gfx::InterpolationColorSpace::LinearRGB;
case CSS::ColorInterpolation::Auto:
case CSS::ColorInterpolation::Srgb:
return Gfx::InterpolationColorSpace::SRGB;
}
VERIFY_NOT_REACHED();
}
Optional<Gfx::AffineTransform> SVGGradientElement::gradient_transform() const Optional<Gfx::AffineTransform> SVGGradientElement::gradient_transform() const
{ {
HashTable<SVGGradientElement const*> seen_gradients; HashTable<SVGGradientElement const*> seen_gradients;

View file

@ -52,6 +52,8 @@ public:
SpreadMethod spread_method() const; SpreadMethod spread_method() const;
Gfx::InterpolationColorSpace color_space() const;
Optional<Gfx::AffineTransform> gradient_transform() const; Optional<Gfx::AffineTransform> gradient_transform() const;
protected: protected:

View file

@ -156,6 +156,7 @@ Optional<Painting::PaintStyle> SVGLinearGradientElement::to_gfx_paint_style(SVGP
m_paint_style->set_gradient_transform(gradient_paint_transform(paint_context)); m_paint_style->set_gradient_transform(gradient_paint_transform(paint_context));
m_paint_style->set_spread_method(to_painting_spread_method(spread_method())); m_paint_style->set_spread_method(to_painting_spread_method(spread_method()));
m_paint_style->set_color_space(color_space());
return *m_paint_style; return *m_paint_style;
} }

View file

@ -212,6 +212,7 @@ Optional<Painting::PaintStyle> SVGRadialGradientElement::to_gfx_paint_style(SVGP
} }
m_paint_style->set_gradient_transform(gradient_paint_transform(paint_context)); m_paint_style->set_gradient_transform(gradient_paint_transform(paint_context));
m_paint_style->set_spread_method(to_painting_spread_method(spread_method())); m_paint_style->set_spread_method(to_painting_spread_method(spread_method()));
m_paint_style->set_color_space(color_space());
return *m_paint_style; return *m_paint_style;
} }

View file

@ -0,0 +1,24 @@
<svg width="100%" height="100%"
xmlns="http://www.w3.org/2000/svg"
xmlns:html="http://www.w3.org/1999/xhtml">
<style>
div {
border: none;
margin: 0;
padding: 0;
};
</style>
<defs>
<linearGradient id="gradientLinearRGB" gradientUnits="objectBoundingBox" color-interpolation="linearRGB">
<stop offset="0" stop-color="white"/>
<stop offset=".33" stop-color="blue"/>
<stop offset=".66" stop-color="red"/>
<stop offset="1" stop-color="yellow"/>
</linearGradient>
</defs>
<foreignObject x="20" y="20" width="200" height="200">
<html:div style="height:100%;width:100%;background: linear-gradient(90deg in srgb-linear, white 0%, blue 33%, red 66%, yellow 100%);"/>
</foreignObject>
</svg>

After

Width:  |  Height:  |  Size: 761 B

View file

@ -0,0 +1,22 @@
<svg width="100%" height="100%"
xmlns="http://www.w3.org/2000/svg"
xmlns:html="http://www.w3.org/1999/xhtml">
<g id="testmeta">
<title>Gradient with color-interpolation: linearRGB</title>
<html:link rel="help"
href="https://www.w3.org/TR/SVG2/pservers.html#LinearGradients"/>
<html:link rel="match" href="../../../../../expected/wpt-import/svg/pservers/reftests/reference/gradient-color-interpolation-ref.svg" />
<html:meta name="fuzzy" content="maxDifference=0-20;totalPixels=0-29400" />
</g>
<defs>
<linearGradient id="gradientLinearRGB" gradientUnits="objectBoundingBox" color-interpolation="linearRGB">
<stop offset="0" stop-color="white"/>
<stop offset=".33" stop-color="blue"/>
<stop offset=".66" stop-color="red"/>
<stop offset="1" stop-color="yellow"/>
</linearGradient>
</defs>
<rect x="20" y="20" width="200" height="200" style="fill:url(#gradientLinearRGB)" />
</svg>

After

Width:  |  Height:  |  Size: 953 B

View file

@ -8,6 +8,7 @@ All properties associated with getComputedStyle(document.body):
"caret-color", "caret-color",
"clip-rule", "clip-rule",
"color", "color",
"color-interpolation",
"color-scheme", "color-scheme",
"cursor", "cursor",
"direction", "direction",

View file

@ -340,6 +340,8 @@ All supported properties and their default values exposed from CSSStylePropertie
'clipRule': 'nonzero' 'clipRule': 'nonzero'
'clip-rule': 'nonzero' 'clip-rule': 'nonzero'
'color': 'rgb(0, 0, 0)' 'color': 'rgb(0, 0, 0)'
'colorInterpolation': 'srgb'
'color-interpolation': 'srgb'
'colorScheme': 'normal' 'colorScheme': 'normal'
'color-scheme': 'normal' 'color-scheme': 'normal'
'columnCount': 'auto' 'columnCount': 'auto'

View file

@ -6,6 +6,7 @@ caption-side: top
caret-color: rgb(0, 0, 0) caret-color: rgb(0, 0, 0)
clip-rule: nonzero clip-rule: nonzero
color: rgb(0, 0, 0) color: rgb(0, 0, 0)
color-interpolation: srgb
color-scheme: normal color-scheme: normal
cursor: auto cursor: auto
direction: ltr direction: ltr
@ -89,7 +90,7 @@ background-position-x: 0%
background-position-y: 0% background-position-y: 0%
background-repeat: repeat background-repeat: repeat
background-size: auto background-size: auto
block-size: 1365px block-size: 1380px
border-block-end-color: rgb(0, 0, 0) border-block-end-color: rgb(0, 0, 0)
border-block-end-style: none border-block-end-style: none
border-block-end-width: 0px border-block-end-width: 0px
@ -165,7 +166,7 @@ grid-row-start: auto
grid-template-areas: none grid-template-areas: none
grid-template-columns: none grid-template-columns: none
grid-template-rows: none grid-template-rows: none
height: 2505px height: 2520px
inline-size: 784px inline-size: 784px
inset-block-end: auto inset-block-end: auto
inset-block-start: auto inset-block-start: auto

View file

@ -1,8 +1,8 @@
Harness status: OK Harness status: OK
Found 254 tests Found 255 tests
247 Pass 248 Pass
7 Fail 7 Fail
Pass accent-color Pass accent-color
Pass border-collapse Pass border-collapse
@ -11,6 +11,7 @@ Pass caption-side
Pass caret-color Pass caret-color
Pass clip-rule Pass clip-rule
Pass color Pass color
Pass color-interpolation
Pass color-scheme Pass color-scheme
Pass cursor Pass cursor
Pass direction Pass direction

View file

@ -2,15 +2,15 @@ Harness status: OK
Found 20 tests Found 20 tests
15 Pass 14 Pass
5 Fail 6 Fail
Pass The serialization of border: 1px; border-top: 1px; should be canonical. Pass The serialization of border: 1px; border-top: 1px; should be canonical.
Pass The serialization of border: 1px solid red; should be canonical. Pass The serialization of border: 1px solid red; should be canonical.
Pass The serialization of border: 1px red; should be canonical. Pass The serialization of border: 1px red; should be canonical.
Pass The serialization of border: red; should be canonical. Pass The serialization of border: red; should be canonical.
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical. Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; should be canonical. Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; should be canonical.
Pass The serialization of border-top: 1px; border-right: 2px; border-bottom: 3px; border-left: 4px; should be canonical. Fail The serialization of border-top: 1px; border-right: 2px; border-bottom: 3px; border-left: 4px; should be canonical.
Fail The serialization of border: 1px; border-top: 2px; should be canonical. Fail The serialization of border: 1px; border-top: 2px; should be canonical.
Fail The serialization of border: 1px; border-top: 1px !important; should be canonical. Fail The serialization of border: 1px; border-top: 1px !important; should be canonical.
Fail The serialization of border: 1px; border-top-color: red; should be canonical. Fail The serialization of border: 1px; border-top-color: red; should be canonical.

View file

@ -0,0 +1,7 @@
Harness status: OK
Found 2 tests
2 Pass
Pass e.style['color-interpolation'] = "none" should not set the property value
Pass e.style['color-interpolation'] = "auto srgb" should not set the property value

View file

@ -0,0 +1,8 @@
Harness status: OK
Found 3 tests
3 Pass
Pass e.style['color-interpolation'] = "auto" should set the property value
Pass e.style['color-interpolation'] = "srgb" should set the property value
Pass e.style['color-interpolation'] = "linearrgb" should set the property value

View file

@ -1,12 +1,13 @@
Harness status: OK Harness status: OK
Found 45 tests Found 46 tests
42 Pass 43 Pass
3 Fail 3 Fail
Pass clip-path presentation attribute supported on an irrelevant element Pass clip-path presentation attribute supported on an irrelevant element
Pass clip-rule presentation attribute supported on an irrelevant element Pass clip-rule presentation attribute supported on an irrelevant element
Pass color presentation attribute supported on an irrelevant element Pass color presentation attribute supported on an irrelevant element
Pass color-interpolation presentation attribute supported on an irrelevant element
Pass cursor presentation attribute supported on an irrelevant element Pass cursor presentation attribute supported on an irrelevant element
Pass direction presentation attribute supported on an irrelevant element Pass direction presentation attribute supported on an irrelevant element
Pass display presentation attribute supported on an irrelevant element Pass display presentation attribute supported on an irrelevant element

View file

@ -1,12 +1,13 @@
Harness status: OK Harness status: OK
Found 55 tests Found 56 tests
51 Pass 52 Pass
4 Fail 4 Fail
Pass clip-path presentation attribute supported on a relevant element Pass clip-path presentation attribute supported on a relevant element
Pass clip-rule presentation attribute supported on a relevant element Pass clip-rule presentation attribute supported on a relevant element
Pass color presentation attribute supported on a relevant element Pass color presentation attribute supported on a relevant element
Pass color-interpolation presentation attribute supported on a relevant element
Pass cursor presentation attribute supported on a relevant element Pass cursor presentation attribute supported on a relevant element
Pass cx presentation attribute supported on a relevant element Pass cx presentation attribute supported on a relevant element
Pass cy presentation attribute supported on a relevant element Pass cy presentation attribute supported on a relevant element

View file

@ -1,12 +1,13 @@
Harness status: OK Harness status: OK
Found 45 tests Found 46 tests
42 Pass 43 Pass
3 Fail 3 Fail
Pass clip-path presentation attribute supported on an unknown SVG element Pass clip-path presentation attribute supported on an unknown SVG element
Pass clip-rule presentation attribute supported on an unknown SVG element Pass clip-rule presentation attribute supported on an unknown SVG element
Pass color presentation attribute supported on an unknown SVG element Pass color presentation attribute supported on an unknown SVG element
Pass color-interpolation presentation attribute supported on an unknown SVG element
Pass cursor presentation attribute supported on an unknown SVG element Pass cursor presentation attribute supported on an unknown SVG element
Pass direction presentation attribute supported on an unknown SVG element Pass direction presentation attribute supported on an unknown SVG element
Pass display presentation attribute supported on an unknown SVG element Pass display presentation attribute supported on an unknown SVG element

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:h="http://www.w3.org/1999/xhtml"
width="800px" height="800px">
<title>SVG Painting: parsing color-interpolation with invalid values</title>
<metadata>
<h:link rel="help" href="https://svgwg.org/svg2-draft/painting.html#ColorInterpolationProperty"/>
<h:meta name="assert" content="color-interpolation supports only the grammar 'auto | sRGB | linearRGB'."/>
</metadata>
<g id="target"></g>
<h:script src="../../../resources/testharness.js"/>
<h:script src="../../../resources/testharnessreport.js"/>
<h:script src="../../../css/support/parsing-testcommon.js"/>
<script><![CDATA[
test_invalid_value("color-interpolation", "none");
test_invalid_value("color-interpolation", "auto srgb");
]]></script>
</svg>

After

Width:  |  Height:  |  Size: 827 B

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:h="http://www.w3.org/1999/xhtml"
width="800px" height="800px">
<title>SVG Painting: parsing color-interpolation with valid values</title>
<metadata>
<h:link rel="help" href="https://svgwg.org/svg2-draft/painting.html#ColorInterpolationProperty"/>
<h:meta name="assert" content="color-interpolation supports the full grammar 'auto | sRGB | linearRGB'."/>
</metadata>
<g id="target"></g>
<h:script src="../../../resources/testharness.js"/>
<h:script src="../../../resources/testharnessreport.js"/>
<h:script src="../../../css/support/parsing-testcommon.js"/>
<script><![CDATA[
test_valid_value("color-interpolation", "auto");
test_valid_value("color-interpolation", "srgb");
test_valid_value("color-interpolation", "linearrgb");
]]></script>
</svg>

After

Width:  |  Height:  |  Size: 870 B