diff options
author | PrestonLTaylor <95388976+PrestonLTaylor@users.noreply.github.com> | 2023-05-31 00:50:12 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-06-03 05:58:00 +0200 |
commit | aa691c22d4c1169b99adba5046920e85bf0258f6 (patch) | |
tree | 4d28f87ca7b74c23e038ac4920c0d1c5e3c19906 | |
parent | c7c3043aa2bdf98b0e733286ef2d5547546ba87e (diff) | |
download | serenity-aa691c22d4c1169b99adba5046920e85bf0258f6.zip |
LibWeb: Implement the `<symbol>` SVG element
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/ElementFactory.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp | 62 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h | 29 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/SVGSymbolElement.idl | 9 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/TagNames.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/idl_files.cmake | 1 |
7 files changed, 106 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 0e79a2caa9..395b5dd89b 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -522,6 +522,7 @@ set(SOURCES SVG/SVGRadialGradientElement.cpp SVG/SVGSVGElement.cpp SVG/SVGStopElement.cpp + SVG/SVGSymbolElement.cpp SVG/SVGTextContentElement.cpp SVG/SVGUseElement.cpp SVG/TagNames.cpp diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp index 00e2802f9c..c8bb809813 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp @@ -97,6 +97,7 @@ #include <LibWeb/SVG/SVGRectElement.h> #include <LibWeb/SVG/SVGSVGElement.h> #include <LibWeb/SVG/SVGStopElement.h> +#include <LibWeb/SVG/SVGSymbolElement.h> #include <LibWeb/SVG/SVGTextContentElement.h> #include <LibWeb/SVG/SVGUseElement.h> #include <LibWeb/SVG/TagNames.h> @@ -454,6 +455,8 @@ static WebIDL::ExceptionOr<JS::GCPtr<SVG::SVGElement>> create_svg_element(JS::Re return MUST_OR_THROW_OOM(realm.heap().allocate<SVG::SVGGElement>(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::stop) return MUST_OR_THROW_OOM(realm.heap().allocate<SVG::SVGStopElement>(realm, document, move(qualified_name))); + if (local_name == SVG::TagNames::symbol) + return MUST_OR_THROW_OOM(realm.heap().allocate<SVG::SVGSymbolElement>(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::text) return MUST_OR_THROW_OOM(realm.heap().allocate<SVG::SVGTextContentElement>(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::use) diff --git a/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp new file mode 100644 index 0000000000..5306a248c5 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023, Preston Taylor <95388976+PrestonLTaylor@users.noreply.github.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/Bindings/Intrinsics.h> +#include <LibWeb/CSS/StyleProperties.h> +#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h> +#include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h> +#include <LibWeb/CSS/StyleValues/OverflowStyleValue.h> +#include <LibWeb/DOM/ShadowRoot.h> +#include <LibWeb/SVG/SVGSymbolElement.h> +#include <LibWeb/SVG/SVGUseElement.h> + +namespace Web::SVG { + +SVGSymbolElement::SVGSymbolElement(DOM::Document& document, DOM::QualifiedName qualified_name) + : SVGGraphicsElement(document, qualified_name) +{ +} + +JS::ThrowCompletionOr<void> SVGSymbolElement::initialize(JS::Realm& realm) +{ + MUST_OR_THROW_OOM(Base::initialize(realm)); + set_prototype(&Bindings::ensure_web_prototype<Bindings::SVGSymbolElementPrototype>(realm, "SVGSymbolElement")); + + return {}; +} + +// https://svgwg.org/svg2-draft/struct.html#SymbolNotes +void SVGSymbolElement::apply_presentational_hints(CSS::StyleProperties& style) const +{ + // The user agent style sheet sets the overflow property for ‘symbol’ elements to hidden. + auto hidden = CSS::IdentifierStyleValue::create(CSS::ValueID::Hidden).release_value_but_fixme_should_propagate_errors(); + style.set_property(CSS::PropertyID::Overflow, CSS::OverflowStyleValue::create(hidden, hidden).release_value_but_fixme_should_propagate_errors()); + + if (is_direct_child_of_use_shadow_tree()) { + // The generated instance of a ‘symbol’ that is the direct referenced element of a ‘use’ element must always have a computed value of inline for the display property. + style.set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::Inline)).release_value_but_fixme_should_propagate_errors()); + } else { + // FIXME: When we have a DefaultSVG.css then use https://svgwg.org/svg2-draft/styling.html#UAStyleSheet instead. + // The user agent must set the display property on the ‘symbol’ element to none, as part of the user agent style sheet, + // and this declaration must have importance over any other CSS rule or presentation attribute. + style.set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::None)).release_value_but_fixme_should_propagate_errors()); + } + + // TODO: Parse viewBox and apply it in SVGGraphicsElement/SVGGraphicsPaintable +} + +bool SVGSymbolElement::is_direct_child_of_use_shadow_tree() const +{ + auto maybe_shadow_root = parent(); + if (!is<DOM::ShadowRoot>(maybe_shadow_root)) { + return false; + } + + auto host = static_cast<const DOM::ShadowRoot&>(*maybe_shadow_root).host(); + return is<SVGUseElement>(host); +} + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h new file mode 100644 index 0000000000..3b571d4397 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023, Preston Taylor <95388976+PrestonLTaylor@users.noreply.github.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/SVG/SVGGraphicsElement.h> + +namespace Web::SVG { + +class SVGSymbolElement final : public SVGGraphicsElement { + WEB_PLATFORM_OBJECT(SVGSymbolElement, SVGGraphicsElement); + +public: + virtual ~SVGSymbolElement() override = default; + + void apply_presentational_hints(CSS::StyleProperties& style) const override; + +private: + SVGSymbolElement(DOM::Document&, DOM::QualifiedName); + + virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override; + + bool is_direct_child_of_use_shadow_tree() const; +}; + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.idl b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.idl new file mode 100644 index 0000000000..52f33386a6 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGSymbolElement.idl @@ -0,0 +1,9 @@ +#import <SVG/SVGGraphicsElement.idl> + +// https://svgwg.org/svg2-draft/struct.html#InterfaceSVGSymbolElement +[Exposed=Window] +interface SVGSymbolElement : SVGGraphicsElement { + +}; + +// FIXME: SVGSymbolElement includes SVGFitToViewBox; diff --git a/Userland/Libraries/LibWeb/SVG/TagNames.h b/Userland/Libraries/LibWeb/SVG/TagNames.h index 9034987c81..36887a0d4b 100644 --- a/Userland/Libraries/LibWeb/SVG/TagNames.h +++ b/Userland/Libraries/LibWeb/SVG/TagNames.h @@ -33,6 +33,7 @@ namespace Web::SVG::TagNames { __ENUMERATE_SVG_TAG(radialGradient) \ __ENUMERATE_SVG_TAG(script) \ __ENUMERATE_SVG_TAG(stop) \ + __ENUMERATE_SVG_TAG(symbol) \ __ENUMERATE_SVG_TAG(title) \ __ENUMERATE_SVG_TAG(use) diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 53a5076bbb..ad69a5a78a 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -211,6 +211,7 @@ libweb_js_bindings(SVG/SVGRadialGradientElement) libweb_js_bindings(SVG/SVGRectElement) libweb_js_bindings(SVG/SVGSVGElement) libweb_js_bindings(SVG/SVGStopElement) +libweb_js_bindings(SVG/SVGSymbolElement) libweb_js_bindings(SVG/SVGTextContentElement) libweb_js_bindings(SVG/SVGUseElement) libweb_js_bindings(Selection/Selection) |