mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 14:27:35 +00: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:
parent
90af21aef4
commit
720c27efbd
7 changed files with 38 additions and 6 deletions
|
@ -17,5 +17,6 @@
|
||||||
"svg-gradient-spreadMethod.html": "svg-gradient-spreadMethod-ref.html",
|
"svg-gradient-spreadMethod.html": "svg-gradient-spreadMethod-ref.html",
|
||||||
"svg-radialGradient.html": "svg-radialGradient-ref.html",
|
"svg-radialGradient.html": "svg-radialGradient-ref.html",
|
||||||
"svg-symbol.html": "svg-symbol-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"
|
||||||
}
|
}
|
||||||
|
|
13
Tests/LibWeb/Ref/svg-file-matches-html-file.html
Normal file
13
Tests/LibWeb/Ref/svg-file-matches-html-file.html
Normal 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>
|
8
Tests/LibWeb/Ref/svg-file-matches-html-file.svg
Normal file
8
Tests/LibWeb/Ref/svg-file-matches-html-file.svg
Normal 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 |
|
@ -111,7 +111,7 @@ Gfx::AffineTransform SVGGraphicsElement::get_transform() const
|
||||||
{
|
{
|
||||||
Gfx::AffineTransform transform = m_transform;
|
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>()) {
|
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;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,11 @@ protected:
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
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;
|
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 = {};
|
Gfx::AffineTransform m_transform = {};
|
||||||
|
|
|
@ -72,13 +72,16 @@ Optional<StringView> SVGUseElement::parse_id_from_href(DeprecatedString const& h
|
||||||
return href.substring_view(id_seperator.value() + 1);
|
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()
|
void SVGUseElement::inserted()
|
||||||
{
|
{
|
||||||
Base::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)
|
void SVGUseElement::svg_element_changed(SVGElement& svg_element)
|
||||||
|
|
|
@ -34,6 +34,8 @@ public:
|
||||||
JS::GCPtr<SVGElement> instance_root() const;
|
JS::GCPtr<SVGElement> instance_root() const;
|
||||||
JS::GCPtr<SVGElement> animated_instance_root() const;
|
JS::GCPtr<SVGElement> animated_instance_root() const;
|
||||||
|
|
||||||
|
virtual Gfx::AffineTransform element_transform() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SVGUseElement(DOM::Document&, DOM::QualifiedName);
|
SVGUseElement(DOM::Document&, DOM::QualifiedName);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue