LibWeb: Parse the shape-rendering property

This commit is contained in:
Tim Ledbetter 2025-08-16 17:48:30 +01:00 committed by Sam Atkins
commit 1d745884be
Notes: github-actions[bot] 2025-08-19 08:48:57 +00:00
20 changed files with 110 additions and 13 deletions

View file

@ -1911,6 +1911,12 @@ ScrollbarWidth ComputedProperties::scrollbar_width() const
return keyword_to_scrollbar_width(value.to_keyword()).release_value();
}
ShapeRendering ComputedProperties::shape_rendering() const
{
auto const& value = property(PropertyID::ShapeRendering);
return keyword_to_shape_rendering(value.to_keyword()).release_value();
}
WillChange ComputedProperties::will_change() const
{
auto const& value = property(PropertyID::WillChange);

View file

@ -195,6 +195,7 @@ public:
FillRule fill_rule() const;
ClipRule clip_rule() const;
float flood_opacity() const;
CSS::ShapeRendering shape_rendering() const;
WillChange will_change() const;

View file

@ -258,6 +258,7 @@ public:
};
}
static CSS::ScrollbarWidth scrollbar_width() { return CSS::ScrollbarWidth::Auto; }
static CSS::ShapeRendering shape_rendering() { return CSS::ShapeRendering::Auto; }
static WillChange will_change() { return WillChange::make_auto(); }
};
@ -539,6 +540,7 @@ public:
CSS::MixBlendMode mix_blend_mode() const { return m_noninherited.mix_blend_mode; }
Optional<FlyString> view_transition_name() const { return m_noninherited.view_transition_name; }
TouchActionData touch_action() const { return m_noninherited.touch_action; }
CSS::ShapeRendering shape_rendering() const { return m_noninherited.shape_rendering; }
CSS::LengthBox const& inset() const { return m_noninherited.inset; }
const CSS::LengthBox& margin() const { return m_noninherited.margin; }
@ -838,6 +840,8 @@ protected:
Color flood_color { InitialValues::flood_color() };
float flood_opacity { InitialValues::flood_opacity() };
CSS::ShapeRendering shape_rendering { InitialValues::shape_rendering() };
} m_noninherited;
};
@ -1027,6 +1031,7 @@ public:
void set_clip_rule(CSS::ClipRule value) { m_inherited.clip_rule = value; }
void set_flood_color(Color value) { m_noninherited.flood_color = value; }
void set_flood_opacity(float value) { m_noninherited.flood_opacity = value; }
void set_shape_rendering(CSS::ShapeRendering value) { m_noninherited.shape_rendering = value; }
void set_cx(LengthPercentage cx) { m_noninherited.cx = move(cx); }
void set_cy(LengthPercentage cy) { m_noninherited.cy = move(cy); }

View file

@ -632,6 +632,12 @@
"thin",
"none"
],
"shape-rendering": [
"auto",
"optimizespeed",
"crispedges",
"geometricprecision"
],
"stroke-linecap": [
"butt",
"square",

View file

@ -151,6 +151,7 @@
"copy",
"cover",
"crisp-edges",
"crispedges",
"crop",
"cross",
"crosshair",

View file

@ -3060,6 +3060,15 @@
"none"
]
},
"shape-rendering": {
"affects-layout": true,
"animation-type": "discrete",
"inherited": true,
"initial": "auto",
"valid-types": [
"shape-rendering"
]
},
"stop-color": {
"affects-layout": false,
"animation-type": "by-computed-value",

View file

@ -913,6 +913,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
computed_values.set_stroke_width(stroke_width.as_length().length());
else if (stroke_width.is_percentage())
computed_values.set_stroke_width(CSS::LengthPercentage { stroke_width.as_percentage().percentage() });
computed_values.set_shape_rendering(computed_style.shape_rendering());
auto const& mask_image = computed_style.property(CSS::PropertyID::MaskImage);
if (mask_image.is_url()) {
@ -1035,6 +1036,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
computed_values.set_mix_blend_mode(computed_style.mix_blend_mode());
computed_values.set_view_transition_name(computed_style.view_transition_name());
computed_values.set_contain(computed_style.contain());
computed_values.set_shape_rendering(computed_values.shape_rendering());
computed_values.set_will_change(computed_style.will_change());
computed_values.set_caret_color(computed_style.caret_color(*this));

View file

@ -80,6 +80,7 @@ static ReadonlySpan<NamedPropertyID> attribute_style_properties()
NamedPropertyID(CSS::PropertyID::R, { SVG::TagNames::circle }),
NamedPropertyID(CSS::PropertyID::Rx, { SVG::TagNames::ellipse, SVG::TagNames::rect }),
NamedPropertyID(CSS::PropertyID::Ry, { SVG::TagNames::ellipse, SVG::TagNames::rect }),
NamedPropertyID(CSS::PropertyID::ShapeRendering),
NamedPropertyID(CSS::PropertyID::StopColor),
NamedPropertyID(CSS::PropertyID::StopOpacity),
NamedPropertyID(CSS::PropertyID::Stroke),

View file

@ -43,6 +43,7 @@ All properties associated with getComputedStyle(document.body):
"math-style",
"pointer-events",
"quotes",
"shape-rendering",
"stroke",
"stroke-dasharray",
"stroke-dashoffset",

View file

@ -634,6 +634,8 @@ All supported properties and their default values exposed from CSSStylePropertie
'scrollbar-gutter': 'auto'
'scrollbarWidth': 'auto'
'scrollbar-width': 'auto'
'shapeRendering': 'auto'
'shape-rendering': 'auto'
'stopColor': 'rgb(0, 0, 0)'
'stop-color': 'rgb(0, 0, 0)'
'stopOpacity': '1'

View file

@ -41,6 +41,7 @@ math-shift: normal
math-style: normal
pointer-events: auto
quotes: auto
shape-rendering: auto
stroke: none
stroke-dasharray: none
stroke-dashoffset: 0
@ -90,7 +91,7 @@ background-position-x: 0%
background-position-y: 0%
background-repeat: repeat
background-size: auto
block-size: 1380px
block-size: 1395px
border-block-end-color: rgb(0, 0, 0)
border-block-end-style: none
border-block-end-width: 0px
@ -166,7 +167,7 @@ grid-row-start: auto
grid-template-areas: none
grid-template-columns: none
grid-template-rows: none
height: 2520px
height: 2535px
inline-size: 784px
inset-block-end: auto
inset-block-start: auto

View file

@ -1,8 +1,8 @@
Harness status: OK
Found 256 tests
Found 257 tests
249 Pass
250 Pass
7 Fail
Pass accent-color
Pass border-collapse
@ -45,6 +45,7 @@ Pass math-shift
Pass math-style
Pass pointer-events
Pass quotes
Pass shape-rendering
Pass stroke
Pass stroke-dasharray
Pass stroke-dashoffset

View file

@ -2,15 +2,15 @@ Harness status: OK
Found 20 tests
14 Pass
6 Fail
15 Pass
5 Fail
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 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; should be canonical.
Fail The serialization of border-top: 1px; border-right: 2px; border-bottom: 3px; border-left: 4px; 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: 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-color: red; should be canonical.

View file

@ -0,0 +1,7 @@
Harness status: OK
Found 2 tests
2 Pass
Pass e.style['shape-rendering'] = "optimizelegibility" should not set the property value
Pass e.style['shape-rendering'] = "auto optimizespeed" should not set the property value

View file

@ -0,0 +1,9 @@
Harness status: OK
Found 4 tests
4 Pass
Pass e.style['shape-rendering'] = "auto" should set the property value
Pass e.style['shape-rendering'] = "optimizespeed" should set the property value
Pass e.style['shape-rendering'] = "crispedges" should set the property value
Pass e.style['shape-rendering'] = "geometricprecision" should set the property value

View file

@ -1,8 +1,8 @@
Harness status: OK
Found 46 tests
Found 47 tests
43 Pass
44 Pass
3 Fail
Pass clip-path presentation attribute supported on an irrelevant element
Pass clip-rule presentation attribute supported on an irrelevant element
@ -30,6 +30,7 @@ Pass mask presentation attribute supported on an irrelevant element
Pass opacity presentation attribute supported on an irrelevant element
Pass overflow presentation attribute supported on an irrelevant element
Pass pointer-events presentation attribute supported on an irrelevant element
Pass shape-rendering presentation attribute supported on an irrelevant element
Pass stop-color presentation attribute supported on an irrelevant element
Pass stop-opacity presentation attribute supported on an irrelevant element
Pass stroke presentation attribute supported on an irrelevant element

View file

@ -1,8 +1,8 @@
Harness status: OK
Found 56 tests
Found 57 tests
52 Pass
53 Pass
4 Fail
Pass clip-path presentation attribute supported on a relevant element
Pass clip-rule presentation attribute supported on a relevant element
@ -36,6 +36,7 @@ Pass pointer-events presentation attribute supported on a relevant element
Pass r presentation attribute supported on a relevant element
Pass rx presentation attribute supported on a relevant element
Pass ry presentation attribute supported on a relevant element
Pass shape-rendering presentation attribute supported on a relevant element
Pass stop-color presentation attribute supported on a relevant element
Pass stop-opacity presentation attribute supported on a relevant element
Pass stroke presentation attribute supported on a relevant element

View file

@ -1,8 +1,8 @@
Harness status: OK
Found 46 tests
Found 47 tests
43 Pass
44 Pass
3 Fail
Pass clip-path presentation attribute supported on an unknown SVG element
Pass clip-rule presentation attribute supported on an unknown SVG element
@ -30,6 +30,7 @@ Pass mask presentation attribute supported on an unknown SVG element
Pass opacity presentation attribute supported on an unknown SVG element
Pass overflow presentation attribute supported on an unknown SVG element
Pass pointer-events presentation attribute supported on an unknown SVG element
Pass shape-rendering presentation attribute supported on an unknown SVG element
Pass stop-color presentation attribute supported on an unknown SVG element
Pass stop-opacity presentation attribute supported on an unknown SVG element
Pass stroke 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 shape-rendering with invalid values</title>
<metadata>
<h:link rel="help" href="https://svgwg.org/svg2-draft/painting.html#ShapeRenderingProperty"/>
<h:meta name="assert" content="shape-rendering supports only the grammar 'auto | optimizeSpeed | crispEdges | geometricPrecision'."/>
</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("shape-rendering", "optimizelegibility");
test_invalid_value("shape-rendering", "auto optimizespeed");
]]></script>
</svg>

After

Width:  |  Height:  |  Size: 861 B

View file

@ -0,0 +1,22 @@
<?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 shape-rendering with valid values</title>
<metadata>
<h:link rel="help" href="https://svgwg.org/svg2-draft/painting.html#ShapeRenderingProperty"/>
<h:meta name="assert" content="shape-rendering supports the full grammar 'auto | optimizeSpeed | crispEdges | geometricPrecision'."/>
</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("shape-rendering", "auto");
test_valid_value("shape-rendering", "optimizespeed");
test_valid_value("shape-rendering", "crispedges");
test_valid_value("shape-rendering", "geometricprecision");
]]></script>
</svg>

After

Width:  |  Height:  |  Size: 946 B