/* * Copyright (c) 2023, MacDue * Copyright (c) 2025, Jelle Raaijmakers * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include namespace Web::SVG { // https://svgwg.org/svg2-draft/text.html#TSpanNotes // https://svgwg.org/svg2-draft/text.html#TSpanAttributes struct TextPositioning { using Position = Variant; Vector x; Vector y; Vector dx; Vector dy; Vector rotate; void apply_to_text_position(Layout::Node const& node, CSSPixelSize viewport, Gfx::FloatPoint& current_text_position, size_t character_index) const { auto value_for_character = [&](Vector const& values) -> float { if (values.is_empty()) return 0.f; auto position = character_index < values.size() ? values[character_index] : values.last(); return position.visit( [](CSS::Number const& number) { return static_cast(number.value()); }, [&](CSS::LengthPercentage const& length_percentage) { auto reference = &values == &x || &values == &dx ? viewport.width() : viewport.height(); return length_percentage.to_px(node, reference).to_float(); }); }; if (!x.is_empty()) current_text_position.set_x(value_for_character(x)); if (!y.is_empty()) current_text_position.set_y(value_for_character(y)); current_text_position.translate_by(value_for_character(dx), value_for_character(dy)); } }; // https://svgwg.org/svg2-draft/text.html#InterfaceSVGTextPositioningElement class SVGTextPositioningElement : public SVGTextContentElement { WEB_PLATFORM_OBJECT(SVGTextPositioningElement, SVGTextContentElement); public: virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) override; TextPositioning text_positioning() const; GC::Ref x(); GC::Ref y(); GC::Ref dx(); GC::Ref dy(); GC::Ref rotate(); protected: SVGTextPositioningElement(DOM::Document&, DOM::QualifiedName); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Visitor&) override; private: GC::Ref ensure_length_list(GC::Ptr&, FlyString const& attribute_name) const; GC::Ptr m_x; GC::Ptr m_y; GC::Ptr m_dx; GC::Ptr m_dy; GC::Ptr m_rotate; }; }