mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 09:28:11 +00:00
LibWeb: Handle reference cycles in SVG gradient linking
Since SVG gradients can reference each other, we have to keep track of visited gradients when traversing the link chain, or we will recurse infinitely when there's a reference cycle.
This commit is contained in:
parent
1b8d8c7bbc
commit
2e0297d703
8 changed files with 155 additions and 36 deletions
|
@ -52,13 +52,19 @@ void SVGRadialGradientElement::attribute_changed(FlyString const& name, Optional
|
|||
|
||||
// https://svgwg.org/svg2-draft/pservers.html#RadialGradientElementFXAttribute
|
||||
NumberPercentage SVGRadialGradientElement::start_circle_x() const
|
||||
{
|
||||
HashTable<SVGGradientElement const*> seen_gradients;
|
||||
return start_circle_x_impl(seen_gradients);
|
||||
}
|
||||
|
||||
NumberPercentage SVGRadialGradientElement::start_circle_x_impl(HashTable<SVGGradientElement const*>& seen_gradients) const
|
||||
{
|
||||
if (m_fx.has_value())
|
||||
return *m_fx;
|
||||
// If the element references an element that specifies a value for 'fx', then the value of 'fx' is
|
||||
// inherited from the referenced element.
|
||||
if (auto gradient = linked_radial_gradient())
|
||||
return gradient->start_circle_x();
|
||||
if (auto gradient = linked_radial_gradient(seen_gradients))
|
||||
return gradient->start_circle_x_impl(seen_gradients);
|
||||
// If attribute ‘fx’ is not specified, ‘fx’ will coincide with the presentational value of ‘cx’ for
|
||||
// the element whether the value for 'cx' was inherited or not.
|
||||
return end_circle_x();
|
||||
|
@ -66,13 +72,19 @@ NumberPercentage SVGRadialGradientElement::start_circle_x() const
|
|||
|
||||
// https://svgwg.org/svg2-draft/pservers.html#RadialGradientElementFYAttribute
|
||||
NumberPercentage SVGRadialGradientElement::start_circle_y() const
|
||||
{
|
||||
HashTable<SVGGradientElement const*> seen_gradients;
|
||||
return start_circle_y_impl(seen_gradients);
|
||||
}
|
||||
|
||||
NumberPercentage SVGRadialGradientElement::start_circle_y_impl(HashTable<SVGGradientElement const*>& seen_gradients) const
|
||||
{
|
||||
if (m_fy.has_value())
|
||||
return *m_fy;
|
||||
// If the element references an element that specifies a value for 'fy', then the value of 'fy' is
|
||||
// inherited from the referenced element.
|
||||
if (auto gradient = linked_radial_gradient())
|
||||
return gradient->start_circle_y();
|
||||
if (auto gradient = linked_radial_gradient(seen_gradients))
|
||||
return gradient->start_circle_y_impl(seen_gradients);
|
||||
// If attribute ‘fy’ is not specified, ‘fy’ will coincide with the presentational value of ‘cy’ for
|
||||
// the element whether the value for 'cy' was inherited or not.
|
||||
return end_circle_y();
|
||||
|
@ -80,46 +92,70 @@ NumberPercentage SVGRadialGradientElement::start_circle_y() const
|
|||
|
||||
// https://svgwg.org/svg2-draft/pservers.html#RadialGradientElementFRAttribute
|
||||
NumberPercentage SVGRadialGradientElement::start_circle_radius() const
|
||||
{
|
||||
HashTable<SVGGradientElement const*> seen_gradients;
|
||||
return start_circle_radius_impl(seen_gradients);
|
||||
}
|
||||
|
||||
NumberPercentage SVGRadialGradientElement::start_circle_radius_impl(HashTable<SVGGradientElement const*>& seen_gradients) const
|
||||
{
|
||||
// Note: A negative value is an error.
|
||||
if (m_fr.has_value() && m_fr->value() >= 0)
|
||||
return *m_fr;
|
||||
// if the element references an element that specifies a value for 'fr', then the value of
|
||||
// 'fr' is inherited from the referenced element.
|
||||
if (auto gradient = linked_radial_gradient())
|
||||
return gradient->start_circle_radius();
|
||||
if (auto gradient = linked_radial_gradient(seen_gradients))
|
||||
return gradient->start_circle_radius_impl(seen_gradients);
|
||||
// If the attribute is not specified, the effect is as if a value of '0%' were specified.
|
||||
return NumberPercentage::create_percentage(0);
|
||||
}
|
||||
|
||||
// https://svgwg.org/svg2-draft/pservers.html#RadialGradientElementCXAttribute
|
||||
NumberPercentage SVGRadialGradientElement::end_circle_x() const
|
||||
{
|
||||
HashTable<SVGGradientElement const*> seen_gradients;
|
||||
return end_circle_x_impl(seen_gradients);
|
||||
}
|
||||
|
||||
NumberPercentage SVGRadialGradientElement::end_circle_x_impl(HashTable<SVGGradientElement const*>& seen_gradients) const
|
||||
{
|
||||
if (m_cx.has_value())
|
||||
return *m_cx;
|
||||
if (auto gradient = linked_radial_gradient())
|
||||
return gradient->end_circle_x();
|
||||
if (auto gradient = linked_radial_gradient(seen_gradients))
|
||||
return gradient->end_circle_x_impl(seen_gradients);
|
||||
return NumberPercentage::create_percentage(50);
|
||||
}
|
||||
|
||||
// https://svgwg.org/svg2-draft/pservers.html#RadialGradientElementCYAttribute
|
||||
NumberPercentage SVGRadialGradientElement::end_circle_y() const
|
||||
{
|
||||
HashTable<SVGGradientElement const*> seen_gradients;
|
||||
return end_circle_y_impl(seen_gradients);
|
||||
}
|
||||
|
||||
NumberPercentage SVGRadialGradientElement::end_circle_y_impl(HashTable<SVGGradientElement const*>& seen_gradients) const
|
||||
{
|
||||
if (m_cy.has_value())
|
||||
return *m_cy;
|
||||
if (auto gradient = linked_radial_gradient())
|
||||
return gradient->end_circle_y();
|
||||
if (auto gradient = linked_radial_gradient(seen_gradients))
|
||||
return gradient->end_circle_y_impl(seen_gradients);
|
||||
return NumberPercentage::create_percentage(50);
|
||||
}
|
||||
|
||||
// https://svgwg.org/svg2-draft/pservers.html#RadialGradientElementRAttribute
|
||||
NumberPercentage SVGRadialGradientElement::end_circle_radius() const
|
||||
{
|
||||
HashTable<SVGGradientElement const*> seen_gradients;
|
||||
return end_circle_radius_impl(seen_gradients);
|
||||
}
|
||||
|
||||
NumberPercentage SVGRadialGradientElement::end_circle_radius_impl(HashTable<SVGGradientElement const*>& seen_gradients) const
|
||||
{
|
||||
// Note: A negative value is an error.
|
||||
if (m_r.has_value() && m_r->value() >= 0)
|
||||
return *m_r;
|
||||
if (auto gradient = linked_radial_gradient())
|
||||
return gradient->end_circle_radius();
|
||||
if (auto gradient = linked_radial_gradient(seen_gradients))
|
||||
return gradient->end_circle_radius_impl(seen_gradients);
|
||||
return NumberPercentage::create_percentage(50);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue