mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:47:34 +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
|
@ -55,12 +55,22 @@ protected:
|
|||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
JS::GCPtr<SVGGradientElement const> linked_gradient() const;
|
||||
JS::GCPtr<SVGGradientElement const> linked_gradient(HashTable<SVGGradientElement const*>& seen_gradients) const;
|
||||
|
||||
Gfx::AffineTransform gradient_paint_transform(SVGPaintContext const&) const;
|
||||
|
||||
template<VoidFunction<SVGStopElement> Callback>
|
||||
void for_each_color_stop(Callback const& callback) const
|
||||
{
|
||||
HashTable<SVGGradientElement const*> seen_gradients;
|
||||
return for_each_color_stop_impl(callback, seen_gradients);
|
||||
}
|
||||
|
||||
void add_color_stops(Gfx::SVGGradientPaintStyle&) const;
|
||||
|
||||
private:
|
||||
template<VoidFunction<SVGStopElement> Callback>
|
||||
void for_each_color_stop_impl(Callback const& callback, HashTable<SVGGradientElement const*>& seen_gradients) const
|
||||
{
|
||||
bool color_stops_found = false;
|
||||
for_each_child_of_type<SVG::SVGStopElement>([&](auto& stop) {
|
||||
|
@ -68,14 +78,15 @@ protected:
|
|||
callback(stop);
|
||||
});
|
||||
if (!color_stops_found) {
|
||||
if (auto gradient = linked_gradient())
|
||||
gradient->for_each_color_stop(callback);
|
||||
if (auto gradient = linked_gradient(seen_gradients))
|
||||
gradient->for_each_color_stop_impl(callback, seen_gradients);
|
||||
}
|
||||
}
|
||||
|
||||
void add_color_stops(Gfx::SVGGradientPaintStyle&) const;
|
||||
GradientUnits gradient_units_impl(HashTable<SVGGradientElement const*>& seen_gradients) const;
|
||||
SpreadMethod spread_method_impl(HashTable<SVGGradientElement const*>& seen_gradients) const;
|
||||
Optional<Gfx::AffineTransform> gradient_transform_impl(HashTable<SVGGradientElement const*>& seen_gradients) const;
|
||||
|
||||
private:
|
||||
Optional<GradientUnits> m_gradient_units = {};
|
||||
Optional<SpreadMethod> m_spread_method = {};
|
||||
Optional<Gfx::AffineTransform> m_gradient_transform = {};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue