/* * Copyright (c) 2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include namespace Web::SVG { struct SVGPaintContext { Gfx::FloatRect viewport; Gfx::FloatRect path_bounding_box; Gfx::AffineTransform paint_transform; }; inline Painting::SVGGradientPaintStyle::SpreadMethod to_painting_spread_method(SpreadMethod spread_method) { switch (spread_method) { case SpreadMethod::Pad: return Painting::SVGGradientPaintStyle::SpreadMethod::Pad; case SpreadMethod::Reflect: return Painting::SVGGradientPaintStyle::SpreadMethod::Reflect; case SpreadMethod::Repeat: return Painting::SVGGradientPaintStyle::SpreadMethod::Repeat; default: VERIFY_NOT_REACHED(); } } class SVGGradientElement : public SVGElement , public SVGURIReferenceMixin { WEB_PLATFORM_OBJECT(SVGGradientElement, SVGElement); public: virtual ~SVGGradientElement() override = default; virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) override; virtual Optional to_gfx_paint_style(SVGPaintContext const&) const = 0; GradientUnits gradient_units() const; SpreadMethod spread_method() const; Optional gradient_transform() const; protected: SVGGradientElement(DOM::Document&, DOM::QualifiedName); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; GC::Ptr linked_gradient(HashTable& seen_gradients) const; Gfx::AffineTransform gradient_paint_transform(SVGPaintContext const&) const; template Callback> void for_each_color_stop(Callback const& callback) const { HashTable seen_gradients; return for_each_color_stop_impl(callback, seen_gradients); } void add_color_stops(Painting::SVGGradientPaintStyle&) const; private: template Callback> void for_each_color_stop_impl(Callback const& callback, HashTable& seen_gradients) const { bool color_stops_found = false; for_each_child_of_type([&](auto& stop) { color_stops_found = true; callback(stop); return IterationDecision::Continue; }); if (!color_stops_found) { if (auto gradient = linked_gradient(seen_gradients)) gradient->for_each_color_stop_impl(callback, seen_gradients); } } GradientUnits gradient_units_impl(HashTable& seen_gradients) const; SpreadMethod spread_method_impl(HashTable& seen_gradients) const; Optional gradient_transform_impl(HashTable& seen_gradients) const; // https://svgwg.org/svg2-draft/pservers.html#LinearGradientAttributes Optional m_gradient_units = {}; Optional m_spread_method = {}; Optional m_gradient_transform = {}; }; }