summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrestonLTaylor <95388976+PrestonLTaylor@users.noreply.github.com>2023-05-31 00:50:12 +0100
committerAndreas Kling <kling@serenityos.org>2023-06-03 05:58:00 +0200
commitaa691c22d4c1169b99adba5046920e85bf0258f6 (patch)
tree4d28f87ca7b74c23e038ac4920c0d1c5e3c19906
parentc7c3043aa2bdf98b0e733286ef2d5547546ba87e (diff)
downloadserenity-aa691c22d4c1169b99adba5046920e85bf0258f6.zip
LibWeb: Implement the `<symbol>` SVG element
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibWeb/DOM/ElementFactory.cpp3
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGSymbolElement.cpp62
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGSymbolElement.h29
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGSymbolElement.idl9
-rw-r--r--Userland/Libraries/LibWeb/SVG/TagNames.h1
-rw-r--r--Userland/Libraries/LibWeb/idl_files.cmake1
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)