1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-10 18:10:56 +09:00

LibWeb: Ensure transform of SVG <use> updates with x and y attributes

Rather than modify the transform of the parent (which could change
independently), this adds a new override element_transform() where
element specific tranfroms can be applied. This will always stay in
sync with the attributes.

A ref test comparing a .svg and .html version of the same file is
added as due to differences in attribute parsing order, the .svg version
was previously drawn incorrectly.

Fixes #20859
This commit is contained in:
MacDue 2023-08-31 08:58:41 +01:00 committed by Andrew Kaster
parent 90af21aef4
commit 720c27efbd
Notes: sideshowbarker 2024-07-17 01:04:03 +09:00
7 changed files with 38 additions and 6 deletions

View file

@ -17,5 +17,6 @@
"svg-gradient-spreadMethod.html": "svg-gradient-spreadMethod-ref.html",
"svg-radialGradient.html": "svg-radialGradient-ref.html",
"svg-symbol.html": "svg-symbol-ref.html",
"border-radius-shrink-zero-sized-box.html": "border-radius-shrink-zero-sized-box-ref.html"
"border-radius-shrink-zero-sized-box.html": "border-radius-shrink-zero-sized-box-ref.html",
"svg-file-matches-html-file.svg": "svg-file-matches-html-file.html"
}

View file

@ -0,0 +1,13 @@
<style>
* {
margin: 0;
}
</style>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<g id="10">
<rect width="50" height="50" fill="#555555"></rect>
</g>
</defs>
<use href="#10" x="25" y="25"></use>
</svg>

View file

@ -0,0 +1,8 @@
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<defs>
<g id="10">
<rect width="50" height="50" fill="#555555"></rect>
</g>
</defs>
<use href="#10" x="25" y="25"></use>
</svg>

After

Width:  |  Height:  |  Size: 214 B

View file

@ -111,7 +111,7 @@ Gfx::AffineTransform SVGGraphicsElement::get_transform() const
{
Gfx::AffineTransform transform = m_transform;
for (auto* svg_ancestor = shadow_including_first_ancestor_of_type<SVGGraphicsElement>(); svg_ancestor; svg_ancestor = svg_ancestor->shadow_including_first_ancestor_of_type<SVGGraphicsElement>()) {
transform = Gfx::AffineTransform { svg_ancestor->m_transform }.multiply(transform);
transform = Gfx::AffineTransform { svg_ancestor->element_transform() }.multiply(transform);
}
return transform;
}

View file

@ -53,6 +53,11 @@ protected:
virtual void initialize(JS::Realm&) override;
virtual Gfx::AffineTransform element_transform() const
{
return m_transform;
}
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 = {};

View file

@ -72,13 +72,16 @@ Optional<StringView> SVGUseElement::parse_id_from_href(DeprecatedString const& h
return href.substring_view(id_seperator.value() + 1);
}
Gfx::AffineTransform SVGUseElement::element_transform() const
{
// The x and y properties define an additional transformation (translate(x,y), where x and y represent the computed value of the corresponding property)
// to be applied to the use element, after any transformations specified with other properties
return Base::element_transform().translate(m_x.value_or(0), m_y.value_or(0));
}
void SVGUseElement::inserted()
{
Base::inserted();
// The x and y properties define an additional transformation (translate(x,y), where x and y represent the computed value of the corresponding property)
// to be applied to the use element, after any transformations specified with other properties
m_transform.translate(m_x.value_or(0), m_y.value_or(0));
}
void SVGUseElement::svg_element_changed(SVGElement& svg_element)

View file

@ -34,6 +34,8 @@ public:
JS::GCPtr<SVGElement> instance_root() const;
JS::GCPtr<SVGElement> animated_instance_root() const;
virtual Gfx::AffineTransform element_transform() const override;
private:
SVGUseElement(DOM::Document&, DOM::QualifiedName);