diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 107dccccfe..49713280c6 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -550,6 +550,8 @@ set(SOURCES SVG/SVGStyleElement.cpp SVG/SVGSymbolElement.cpp SVG/SVGTextContentElement.cpp + SVG/SVGTextElement.cpp + SVG/SVGTextPositioningElement.cpp SVG/SVGTitleElement.cpp SVG/SVGUseElement.cpp SVG/TagNames.cpp diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp index 5c11be7abc..468b724cb9 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp @@ -99,7 +99,7 @@ #include #include #include -#include +#include #include #include #include @@ -462,7 +462,7 @@ static WebIDL::ExceptionOr> create_svg_element(JS::Re if (local_name == SVG::TagNames::symbol) return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::text) - return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); + return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::title) return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::use) diff --git a/Userland/Libraries/LibWeb/Layout/SVGTextBox.cpp b/Userland/Libraries/LibWeb/Layout/SVGTextBox.cpp index 19553de948..55a5d4d4a6 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGTextBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGTextBox.cpp @@ -10,7 +10,7 @@ namespace Web::Layout { -SVGTextBox::SVGTextBox(DOM::Document& document, SVG::SVGTextContentElement& element, NonnullRefPtr properties) +SVGTextBox::SVGTextBox(DOM::Document& document, SVG::SVGTextPositioningElement& element, NonnullRefPtr properties) : SVGGraphicsBox(document, element, properties) { } diff --git a/Userland/Libraries/LibWeb/Layout/SVGTextBox.h b/Userland/Libraries/LibWeb/Layout/SVGTextBox.h index f47c5cc917..dc9b58e0b8 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGTextBox.h +++ b/Userland/Libraries/LibWeb/Layout/SVGTextBox.h @@ -8,7 +8,7 @@ #include #include -#include +#include namespace Web::Layout { @@ -16,11 +16,11 @@ class SVGTextBox final : public SVGGraphicsBox { JS_CELL(SVGTextBox, SVGGraphicsBox); public: - SVGTextBox(DOM::Document&, SVG::SVGTextContentElement&, NonnullRefPtr); + SVGTextBox(DOM::Document&, SVG::SVGTextPositioningElement&, NonnullRefPtr); virtual ~SVGTextBox() override = default; - SVG::SVGTextContentElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } - SVG::SVGTextContentElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } + SVG::SVGTextPositioningElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } + SVG::SVGTextPositioningElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } Optional layout_transform() const; diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp index 9adb0c6596..55dc87b4f5 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.cpp @@ -47,26 +47,6 @@ Optional SVGTextContentElement::text_anchor() const } } -void SVGTextContentElement::attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) -{ - SVGGraphicsElement::attribute_changed(name, value); - - if (name == SVG::AttributeNames::x) { - m_x = AttributeParser::parse_coordinate(value).value_or(m_x); - } else if (name == SVG::AttributeNames::y) { - m_y = AttributeParser::parse_coordinate(value).value_or(m_y); - } else if (name == SVG::AttributeNames::dx) { - m_dx = AttributeParser::parse_coordinate(value).value_or(m_dx); - } else if (name == SVG::AttributeNames::dy) { - m_dy = AttributeParser::parse_coordinate(value).value_or(m_dy); - } -} - -JS::GCPtr SVGTextContentElement::create_layout_node(NonnullRefPtr style) -{ - return heap().allocate_without_realm(document(), *this, move(style)); -} - // https://svgwg.org/svg2-draft/text.html#__svg__SVGTextContentElement__getNumberOfChars WebIDL::ExceptionOr SVGTextContentElement::get_number_of_chars() const { @@ -74,9 +54,4 @@ WebIDL::ExceptionOr SVGTextContentElement::get_number_of_chars() const return static_cast(chars.size()); } -Gfx::FloatPoint SVGTextContentElement::get_offset() const -{ - return { m_x + m_dx, m_y + m_dy }; -} - } diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h index 5f2cfdc94b..63d71c3b2f 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.h @@ -17,26 +17,14 @@ class SVGTextContentElement : public SVGGraphicsElement { WEB_PLATFORM_OBJECT(SVGTextContentElement, SVGGraphicsElement); public: - virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; - - virtual void attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) override; - WebIDL::ExceptionOr get_number_of_chars() const; - Gfx::FloatPoint get_offset() const; - Optional text_anchor() const; protected: SVGTextContentElement(DOM::Document&, DOM::QualifiedName); virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; - -private: - float m_x { 0 }; - float m_y { 0 }; - float m_dx { 0 }; - float m_dy { 0 }; }; } diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.idl b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.idl index a063b628c7..186dccd1c6 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.idl +++ b/Userland/Libraries/LibWeb/SVG/SVGTextContentElement.idl @@ -1,8 +1,24 @@ #import +// https://svgwg.org/svg2-draft/text.html#InterfaceSVGTextContentElement [Exposed=Window] interface SVGTextContentElement : SVGGraphicsElement { - long getNumberOfChars(); + // lengthAdjust Types + const unsigned short LENGTHADJUST_UNKNOWN = 0; + const unsigned short LENGTHADJUST_SPACING = 1; + const unsigned short LENGTHADJUST_SPACINGANDGLYPHS = 2; + // FIXME: [SameObject] readonly attribute SVGAnimatedLength textLength; + // FIXME:[SameObject] readonly attribute SVGAnimatedEnumeration lengthAdjust; + + long getNumberOfChars(); + // FIXME: float getComputedTextLength(); + // FIXME: float getSubStringLength(unsigned long charnum, unsigned long nchars); + // FIXME: DOMPoint getStartPositionOfChar(unsigned long charnum); + // FIXME: DOMPoint getEndPositionOfChar(unsigned long charnum); + // FIXME: DOMRect getExtentOfChar(unsigned long charnum); + // FIXME: float getRotationOfChar(unsigned long charnum); + // FIXME: long getCharNumAtPosition(optional DOMPointInit point = {}); + // FIXME: undefined selectSubString(unsigned long charnum, unsigned long nchars); }; diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGTextElement.cpp new file mode 100644 index 0000000000..ee6abe5f73 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGTextElement.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace Web::SVG { + +SVGTextElement::SVGTextElement(DOM::Document& document, DOM::QualifiedName qualified_name) + : SVGTextPositioningElement(document, move(qualified_name)) +{ +} + +JS::ThrowCompletionOr SVGTextElement::initialize(JS::Realm& realm) +{ + MUST_OR_THROW_OOM(Base::initialize(realm)); + set_prototype(&Bindings::ensure_web_prototype(realm, "SVGTextElement")); + + return {}; +} + +JS::GCPtr SVGTextElement::create_layout_node(NonnullRefPtr style) +{ + return heap().allocate_without_realm(document(), *this, move(style)); +} + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextElement.h b/Userland/Libraries/LibWeb/SVG/SVGTextElement.h new file mode 100644 index 0000000000..4910c9d26d --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGTextElement.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::SVG { + +// https://svgwg.org/svg2-draft/text.html#InterfaceSVGTextElement +class SVGTextElement : public SVGTextPositioningElement { + WEB_PLATFORM_OBJECT(SVGTextElement, SVGTextPositioningElement); + +public: + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; + +protected: + SVGTextElement(DOM::Document&, DOM::QualifiedName); + + virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; +}; + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextElement.idl b/Userland/Libraries/LibWeb/SVG/SVGTextElement.idl new file mode 100644 index 0000000000..1c74a7f9e4 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGTextElement.idl @@ -0,0 +1,6 @@ +#import + +// https://svgwg.org/svg2-draft/text.html#InterfaceSVGTextElement +[Exposed=Window] +interface SVGTextElement : SVGTextPositioningElement { +}; diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.cpp new file mode 100644 index 0000000000..b4cff1cd0a --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Andreas Kling + * Copyright (c) 2023, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Web::SVG { + +SVGTextPositioningElement::SVGTextPositioningElement(DOM::Document& document, DOM::QualifiedName qualified_name) + : SVGTextContentElement(document, move(qualified_name)) +{ +} + +JS::ThrowCompletionOr SVGTextPositioningElement::initialize(JS::Realm& realm) +{ + MUST_OR_THROW_OOM(Base::initialize(realm)); + set_prototype(&Bindings::ensure_web_prototype(realm, "SVGTextPositioningElement")); + + return {}; +} + +void SVGTextPositioningElement::attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) +{ + SVGGraphicsElement::attribute_changed(name, value); + + if (name == SVG::AttributeNames::x) { + m_x = AttributeParser::parse_coordinate(value).value_or(m_x); + } else if (name == SVG::AttributeNames::y) { + m_y = AttributeParser::parse_coordinate(value).value_or(m_y); + } else if (name == SVG::AttributeNames::dx) { + m_dx = AttributeParser::parse_coordinate(value).value_or(m_dx); + } else if (name == SVG::AttributeNames::dy) { + m_dy = AttributeParser::parse_coordinate(value).value_or(m_dy); + } +} + +Gfx::FloatPoint SVGTextPositioningElement::get_offset() const +{ + return { m_x + m_dx, m_y + m_dy }; +} + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.h b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.h new file mode 100644 index 0000000000..7308c753c8 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::SVG { + +// https://svgwg.org/svg2-draft/text.html#InterfaceSVGTextPositioningElement +class SVGTextPositioningElement : public SVGTextContentElement { + WEB_PLATFORM_OBJECT(SVGTextPositioningElement, SVGTextContentElement); + +public: + virtual void attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) override; + + Gfx::FloatPoint get_offset() const; + + JS::NonnullGCPtr x() const; + JS::NonnullGCPtr y() const; + JS::NonnullGCPtr dx() const; + JS::NonnullGCPtr dy() const; + +protected: + SVGTextPositioningElement(DOM::Document&, DOM::QualifiedName); + + virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; + +private: + float m_x { 0 }; + float m_y { 0 }; + float m_dx { 0 }; + float m_dy { 0 }; +}; + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.idl b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.idl new file mode 100644 index 0000000000..f9ca5153a0 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.idl @@ -0,0 +1,11 @@ +#import + +// https://svgwg.org/svg2-draft/text.html#InterfaceSVGTextPositioningElement +[Exposed=Window] +interface SVGTextPositioningElement : SVGTextContentElement { + // FIXME: [SameObject] readonly attribute SVGAnimatedLengthList x; + // FIXME: [SameObject] readonly attribute SVGAnimatedLengthList y; + // FIXME: [SameObject] readonly attribute SVGAnimatedLengthList dx; + // FIXME: [SameObject] readonly attribute SVGAnimatedLengthList dy; + // FIXME: [SameObject] readonly attribute SVGAnimatedNumberList rotate; +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 512e30e7c3..79373af21f 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -225,6 +225,8 @@ libweb_js_bindings(SVG/SVGStopElement) libweb_js_bindings(SVG/SVGStyleElement) libweb_js_bindings(SVG/SVGSymbolElement) libweb_js_bindings(SVG/SVGTextContentElement) +libweb_js_bindings(SVG/SVGTextElement) +libweb_js_bindings(SVG/SVGTextPositioningElement) libweb_js_bindings(SVG/SVGTitleElement) libweb_js_bindings(SVG/SVGUseElement) libweb_js_bindings(Selection/Selection)