diff --git a/Base/res/html/misc/svg-gradients.html b/Base/res/html/misc/svg-gradients.html
index b01e7b6644..23a4eaa826 100644
--- a/Base/res/html/misc/svg-gradients.html
+++ b/Base/res/html/misc/svg-gradients.html
@@ -132,3 +132,14 @@
+
+Stroke linear gradient + transform
+
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
index 03bdde4a1d..e365d7eef9 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
@@ -7453,6 +7453,7 @@ Parser::ParseErrorOr> Parser::parse_css_value(Property
return parsed_value.release_nonnull();
return ParseError ::SyntaxError;
case PropertyID::Fill:
+ case PropertyID::Stroke:
if (component_values.size() == 1) {
if (auto parsed_url = FIXME_TRY(parse_url_value(component_values.first())))
return parsed_url.release_nonnull();
diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json
index 016d76245c..42a12bd1ab 100644
--- a/Userland/Libraries/LibWeb/CSS/Properties.json
+++ b/Userland/Libraries/LibWeb/CSS/Properties.json
@@ -1663,8 +1663,10 @@
"affects-layout": false,
"inherited": true,
"initial": "none",
+ "__comment": "FIXME: Use `paint` as the type, once we have a PaintStyleValue and generic parsing for it.",
"valid-types": [
- "color"
+ "color",
+ "url"
],
"valid-identifiers": [
"none"
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index e262e3cff1..6167d011f8 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -155,6 +155,7 @@ class StyleSheetList;
class StyleValue;
class StyleValueList;
class Supports;
+class SVGPaint;
class TextDecorationStyleValue;
class Time;
class TimeOrCalculated;
diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp
index 57b63f0d08..ccc74bb40a 100644
--- a/Userland/Libraries/LibWeb/Layout/Node.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Node.cpp
@@ -681,9 +681,11 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
computed_values.set_fill(fill->to_color(*this));
else if (fill->is_url())
computed_values.set_fill(fill->as_url().url());
- // TODO: Allow url()s for strokes
- if (auto stroke = computed_style.property(CSS::PropertyID::Stroke); stroke->has_color())
+ auto stroke = computed_style.property(CSS::PropertyID::Stroke);
+ if (stroke->has_color())
computed_values.set_stroke(stroke->to_color(*this));
+ else if (stroke->is_url())
+ computed_values.set_stroke(stroke->as_url().url());
if (auto stop_color = computed_style.property(CSS::PropertyID::StopColor); stop_color->has_color())
computed_values.set_stop_color(stop_color->to_color(*this));
auto stroke_width = computed_style.property(CSS::PropertyID::StrokeWidth);
diff --git a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp
index 931b8f6211..3cd9071f1f 100644
--- a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp
+++ b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp
@@ -114,12 +114,20 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const
}
auto stroke_opacity = geometry_element.stroke_opacity().value_or(svg_context.stroke_opacity());
- if (auto stroke_color = geometry_element.stroke_color().value_or(svg_context.stroke_color()).with_opacity(stroke_opacity); stroke_color.alpha() > 0) {
+
+ // Note: This is assuming .x_scale() == .y_scale() (which it does currently).
+ float stroke_thickness = geometry_element.stroke_width().value_or(svg_context.stroke_width()) * viewbox_scale;
+
+ if (auto paint_style = geometry_element.stroke_paint_style(paint_context); paint_style.has_value()) {
+ painter.stroke_path(
+ path,
+ *paint_style,
+ stroke_thickness);
+ } else if (auto stroke_color = geometry_element.stroke_color().value_or(svg_context.stroke_color()).with_opacity(stroke_opacity); stroke_color.alpha() > 0) {
painter.stroke_path(
path,
stroke_color,
- // Note: This is assuming .x_scale() == .y_scale() (which it does currently).
- geometry_element.stroke_width().value_or(svg_context.stroke_width()) * viewbox_scale);
+ stroke_thickness);
}
}
diff --git a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp
index 54e1528b6e..50195e1d3f 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp
+++ b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp
@@ -40,15 +40,12 @@ void SVGGraphicsElement::parse_attribute(DeprecatedFlyString const& name, Deprec
}
}
-Optional SVGGraphicsElement::fill_paint_style(SVGPaintContext const& paint_context) const
+Optional SVGGraphicsElement::svg_paint_computed_value_to_gfx_paint_style(SVGPaintContext const& paint_context, Optional const& paint_value) const
{
// FIXME: This entire function is an ad-hoc hack:
- if (!layout_node())
+ if (!paint_value.has_value() || !paint_value->is_url())
return {};
- auto& fill = layout_node()->computed_values().fill();
- if (!fill.has_value() || !fill->is_url())
- return {};
- auto& url = fill->as_url();
+ auto& url = paint_value->as_url();
auto gradient = document().get_element_by_id(url.fragment());
if (!gradient)
return {};
@@ -57,6 +54,20 @@ Optional SVGGraphicsElement::fill_paint_style(SVGPaintCo
return {};
}
+Optional SVGGraphicsElement::fill_paint_style(SVGPaintContext const& paint_context) const
+{
+ if (!layout_node())
+ return {};
+ return svg_paint_computed_value_to_gfx_paint_style(paint_context, layout_node()->computed_values().fill());
+}
+
+Optional SVGGraphicsElement::stroke_paint_style(SVGPaintContext const& paint_context) const
+{
+ if (!layout_node())
+ return {};
+ return svg_paint_computed_value_to_gfx_paint_style(paint_context, layout_node()->computed_values().stroke());
+}
+
Gfx::AffineTransform transform_from_transform_list(ReadonlySpan transform_list)
{
Gfx::AffineTransform affine_transform;
diff --git a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h
index e3192e5eda..c0d1fd9b62 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h
+++ b/Userland/Libraries/LibWeb/SVG/SVGGraphicsElement.h
@@ -43,12 +43,15 @@ public:
Gfx::AffineTransform get_transform() const;
Optional fill_paint_style(SVGPaintContext const&) const;
+ Optional stroke_paint_style(SVGPaintContext const&) const;
protected:
SVGGraphicsElement(DOM::Document&, DOM::QualifiedName);
virtual JS::ThrowCompletionOr initialize(JS::Realm&) override;
+ Optional svg_paint_computed_value_to_gfx_paint_style(SVGPaintContext const& paint_context, Optional const& paint_value) const;
+
Gfx::AffineTransform m_transform = {};
};