mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
LibWeb/SVG: Support url() in the stroke attribute
This allows you to draw gradients in strokes, for example.
This commit is contained in:
parent
8993a710f8
commit
42a183720b
Notes:
sideshowbarker
2024-07-17 02:21:14 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/42a183720b Pull-request: https://github.com/SerenityOS/serenity/pull/19287 Reviewed-by: https://github.com/MacDue ✅
8 changed files with 51 additions and 12 deletions
|
@ -132,3 +132,14 @@
|
|||
</defs>
|
||||
<rect x="115" y="15" width="170" height="110" fill="url(#grad7)" transform="rotate(45 200 70)" />
|
||||
</svg>
|
||||
<br>
|
||||
<b>Stroke linear gradient + transform</b><br>
|
||||
<svg height="150" width="400">
|
||||
<defs>
|
||||
<linearGradient id="grad7" x1="0" y1="0" x2="70%" y2="0">
|
||||
<stop offset="0" stop-color="blue"/>
|
||||
<stop offset="1" stop-color="magenta"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="115" y="15" width="170" height="110" stroke="url(#grad7)" fill="none" transform="rotate(45 200 70)" />
|
||||
</svg>
|
||||
|
|
|
@ -7453,6 +7453,7 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> 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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -155,6 +155,7 @@ class StyleSheetList;
|
|||
class StyleValue;
|
||||
class StyleValueList;
|
||||
class Supports;
|
||||
class SVGPaint;
|
||||
class TextDecorationStyleValue;
|
||||
class Time;
|
||||
class TimeOrCalculated;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,15 +40,12 @@ void SVGGraphicsElement::parse_attribute(DeprecatedFlyString const& name, Deprec
|
|||
}
|
||||
}
|
||||
|
||||
Optional<Gfx::PaintStyle const&> SVGGraphicsElement::fill_paint_style(SVGPaintContext const& paint_context) const
|
||||
Optional<Gfx::PaintStyle const&> SVGGraphicsElement::svg_paint_computed_value_to_gfx_paint_style(SVGPaintContext const& paint_context, Optional<CSS::SVGPaint> 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<Gfx::PaintStyle const&> SVGGraphicsElement::fill_paint_style(SVGPaintCo
|
|||
return {};
|
||||
}
|
||||
|
||||
Optional<Gfx::PaintStyle const&> 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<Gfx::PaintStyle const&> 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> transform_list)
|
||||
{
|
||||
Gfx::AffineTransform affine_transform;
|
||||
|
|
|
@ -43,12 +43,15 @@ public:
|
|||
Gfx::AffineTransform get_transform() const;
|
||||
|
||||
Optional<Gfx::PaintStyle const&> fill_paint_style(SVGPaintContext const&) const;
|
||||
Optional<Gfx::PaintStyle const&> stroke_paint_style(SVGPaintContext const&) const;
|
||||
|
||||
protected:
|
||||
SVGGraphicsElement(DOM::Document&, DOM::QualifiedName);
|
||||
|
||||
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
|
||||
|
||||
Optional<Gfx::PaintStyle const&> svg_paint_computed_value_to_gfx_paint_style(SVGPaintContext const& paint_context, Optional<CSS::SVGPaint> const& paint_value) const;
|
||||
|
||||
Gfx::AffineTransform m_transform = {};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue