diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2022-02-11 16:45:59 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-11 21:38:27 +0100 |
commit | 3a1a35ef8f867ac16bfe10e2a687e5fdfa4aa4c4 (patch) | |
tree | bdc55bb94b57db9deb70a83f4844273ca55b1b2e /Userland/Libraries/LibWeb | |
parent | 21bdcee3c3ee604742ea6524a320e0cf5ad65abb (diff) | |
download | serenity-3a1a35ef8f867ac16bfe10e2a687e5fdfa4aa4c4.zip |
LibWeb: Add SVG `<ellipse>` element and test case :^)
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/ElementFactory.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp | 78 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h | 33 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/SVGEllipseElement.idl | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/TagNames.h | 1 |
9 files changed, 133 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp index 34262a384a..6e37cc5d37 100644 --- a/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp +++ b/Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp @@ -83,6 +83,7 @@ #include <LibWeb/Bindings/NodeWrapper.h> #include <LibWeb/Bindings/NodeWrapperFactory.h> #include <LibWeb/Bindings/SVGCircleElementWrapper.h> +#include <LibWeb/Bindings/SVGEllipseElementWrapper.h> #include <LibWeb/Bindings/SVGPathElementWrapper.h> #include <LibWeb/Bindings/SVGRectElementWrapper.h> #include <LibWeb/Bindings/SVGSVGElementWrapper.h> @@ -159,6 +160,7 @@ #include <LibWeb/HTML/HTMLUnknownElement.h> #include <LibWeb/HTML/HTMLVideoElement.h> #include <LibWeb/SVG/SVGCircleElement.h> +#include <LibWeb/SVG/SVGEllipseElement.h> #include <LibWeb/SVG/SVGPathElement.h> #include <LibWeb/SVG/SVGRectElement.h> #include <LibWeb/SVG/SVGSVGElement.h> @@ -315,6 +317,8 @@ NodeWrapper* wrap(JS::GlobalObject& global_object, DOM::Node& node) return static_cast<NodeWrapper*>(wrap_impl(global_object, verify_cast<SVG::SVGSVGElement>(node))); if (is<SVG::SVGCircleElement>(node)) return static_cast<NodeWrapper*>(wrap_impl(global_object, verify_cast<SVG::SVGCircleElement>(node))); + if (is<SVG::SVGEllipseElement>(node)) + return static_cast<NodeWrapper*>(wrap_impl(global_object, verify_cast<SVG::SVGEllipseElement>(node))); if (is<SVG::SVGPathElement>(node)) return static_cast<NodeWrapper*>(wrap_impl(global_object, verify_cast<SVG::SVGPathElement>(node))); if (is<SVG::SVGRectElement>(node)) diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h index 6ebd37f30c..88da06aea9 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h @@ -251,6 +251,8 @@ #include <LibWeb/Bindings/SVGCircleElementPrototype.h> #include <LibWeb/Bindings/SVGElementConstructor.h> #include <LibWeb/Bindings/SVGElementPrototype.h> +#include <LibWeb/Bindings/SVGEllipseElementConstructor.h> +#include <LibWeb/Bindings/SVGEllipseElementPrototype.h> #include <LibWeb/Bindings/SVGGeometryElementConstructor.h> #include <LibWeb/Bindings/SVGGeometryElementPrototype.h> #include <LibWeb/Bindings/SVGGraphicsElementConstructor.h> @@ -437,6 +439,7 @@ ADD_WINDOW_OBJECT_INTERFACE(SubtleCrypto) \ ADD_WINDOW_OBJECT_INTERFACE(SVGElement) \ ADD_WINDOW_OBJECT_INTERFACE(SVGCircleElement) \ + ADD_WINDOW_OBJECT_INTERFACE(SVGEllipseElement) \ ADD_WINDOW_OBJECT_INTERFACE(SVGGeometryElement) \ ADD_WINDOW_OBJECT_INTERFACE(SVGGraphicsElement) \ ADD_WINDOW_OBJECT_INTERFACE(SVGPathElement) \ diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 5447a8068d..36654b378f 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -272,6 +272,7 @@ set(SOURCES SVG/SVGGraphicsElement.cpp SVG/SVGPathElement.cpp SVG/SVGCircleElement.cpp + SVG/SVGEllipseElement.cpp SVG/SVGRectElement.cpp SVG/SVGSVGElement.cpp SVG/TagNames.cpp @@ -515,6 +516,7 @@ libweb_js_wrapper(SVG/SVGElement) libweb_js_wrapper(SVG/SVGGeometryElement) libweb_js_wrapper(SVG/SVGGraphicsElement) libweb_js_wrapper(SVG/SVGCircleElement) +libweb_js_wrapper(SVG/SVGEllipseElement) libweb_js_wrapper(SVG/SVGPathElement) libweb_js_wrapper(SVG/SVGRectElement) libweb_js_wrapper(SVG/SVGSVGElement) diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp index 02e587b4a1..54b562e54e 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp @@ -77,6 +77,7 @@ #include <LibWeb/HTML/HTMLUnknownElement.h> #include <LibWeb/HTML/HTMLVideoElement.h> #include <LibWeb/SVG/SVGCircleElement.h> +#include <LibWeb/SVG/SVGEllipseElement.h> #include <LibWeb/SVG/SVGGElement.h> #include <LibWeb/SVG/SVGPathElement.h> #include <LibWeb/SVG/SVGRectElement.h> @@ -238,6 +239,8 @@ NonnullRefPtr<Element> create_element(Document& document, const FlyString& tag_n return adopt_ref(*new SVG::SVGSVGElement(document, move(qualified_name))); if (lowercase_tag_name == SVG::TagNames::circle) return adopt_ref(*new SVG::SVGCircleElement(document, move(qualified_name))); + if (lowercase_tag_name == SVG::TagNames::ellipse) + return adopt_ref(*new SVG::SVGEllipseElement(document, move(qualified_name))); if (lowercase_tag_name == SVG::TagNames::path) return adopt_ref(*new SVG::SVGPathElement(document, move(qualified_name))); if (lowercase_tag_name == SVG::TagNames::rect) diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 4bc2bd98db..cee4b495e7 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -246,6 +246,7 @@ class ResizeObserver; namespace Web::SVG { class SVGCircleElement; class SVGElement; +class SVGEllipseElement; class SVGGeometryElement; class SVGGraphicsElement; class SVGPathElement; @@ -453,6 +454,7 @@ class SubmitEventWrapper; class SubtleCryptoWrapper; class SVGCircleElementWrapper; class SVGElementWrapper; +class SVGEllipseElementWrapper; class SVGGeometryElementWrapper; class SVGGraphicsElementWrapper; class SVGPathElementWrapper; diff --git a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp new file mode 100644 index 0000000000..4e2a43bbfd --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "SVGEllipseElement.h" +#include <LibWeb/SVG/AttributeNames.h> +#include <LibWeb/SVG/AttributeParser.h> + +namespace Web::SVG { + +SVGEllipseElement::SVGEllipseElement(DOM::Document& document, QualifiedName qualified_name) + : SVGGeometryElement(document, qualified_name) +{ +} + +void SVGEllipseElement::parse_attribute(FlyString const& name, String const& value) +{ + SVGGeometryElement::parse_attribute(name, value); + + if (name == SVG::AttributeNames::cx) { + m_center_x = AttributeParser::parse_coordinate(value); + m_path.clear(); + } else if (name == SVG::AttributeNames::cy) { + m_center_y = AttributeParser::parse_coordinate(value); + m_path.clear(); + } else if (name == SVG::AttributeNames::rx) { + m_radius_x = AttributeParser::parse_positive_length(value); + m_path.clear(); + } else if (name == SVG::AttributeNames::ry) { + m_radius_y = AttributeParser::parse_positive_length(value); + m_path.clear(); + } +} + +Gfx::Path& SVGEllipseElement::get_path() +{ + if (m_path.has_value()) + return m_path.value(); + + float rx = m_radius_x.value_or(0); + float ry = m_radius_y.value_or(0); + float cx = m_center_x.value_or(0); + float cy = m_center_y.value_or(0); + Gfx::Path path; + + // A computed value of zero for either dimension, or a computed value of auto for both dimensions, disables rendering of the element. + if (rx == 0 || ry == 0) { + m_path = move(path); + return m_path.value(); + } + + Gfx::FloatPoint radii = { rx, ry }; + double x_axis_rotation = 0; + bool large_arc = false; + bool sweep = true; // Note: Spec says it should be false, but it's wrong. https://github.com/w3c/svgwg/issues/765 + + // 1. A move-to command to the point cx+rx,cy; + path.move_to({ cx + rx, cy }); + + // 2. arc to cx,cy+ry; + path.elliptical_arc_to({ cx, cy + ry }, radii, x_axis_rotation, large_arc, sweep); + + // 3. arc to cx-rx,cy; + path.elliptical_arc_to({ cx - rx, cy }, radii, x_axis_rotation, large_arc, sweep); + + // 4. arc to cx,cy-ry; + path.elliptical_arc_to({ cx, cy - ry }, radii, x_axis_rotation, large_arc, sweep); + + // 5. arc with a segment-completing close path operation. + path.elliptical_arc_to({ cx + rx, cy }, radii, x_axis_rotation, large_arc, sweep); + + m_path = move(path); + return m_path.value(); +} + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h new file mode 100644 index 0000000000..4c262cb1e9 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/SVG/SVGGeometryElement.h> + +namespace Web::SVG { + +class SVGEllipseElement final : public SVGGeometryElement { +public: + using WrapperType = Bindings::SVGEllipseElementWrapper; + + SVGEllipseElement(DOM::Document&, QualifiedName); + virtual ~SVGEllipseElement() override = default; + + virtual void parse_attribute(FlyString const& name, String const& value) override; + + virtual Gfx::Path& get_path() override; + +private: + Optional<Gfx::Path> m_path; + + Optional<float> m_center_x; + Optional<float> m_center_y; + Optional<float> m_radius_x; + Optional<float> m_radius_y; +}; + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.idl b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.idl new file mode 100644 index 0000000000..876435ca05 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.idl @@ -0,0 +1,7 @@ +[Exposed=Window] +interface SVGEllipseElement : SVGGeometryElement { + // [SameObject] readonly attribute SVGAnimatedLength cx; + // [SameObject] readonly attribute SVGAnimatedLength cy; + // [SameObject] readonly attribute SVGAnimatedLength rx; + // [SameObject] readonly attribute SVGAnimatedLength ry; +}; diff --git a/Userland/Libraries/LibWeb/SVG/TagNames.h b/Userland/Libraries/LibWeb/SVG/TagNames.h index ef4065ae71..79ad440643 100644 --- a/Userland/Libraries/LibWeb/SVG/TagNames.h +++ b/Userland/Libraries/LibWeb/SVG/TagNames.h @@ -12,6 +12,7 @@ namespace Web::SVG::TagNames { #define ENUMERATE_SVG_GRAPHICS_TAGS \ __ENUMERATE_SVG_TAG(circle) \ + __ENUMERATE_SVG_TAG(ellipse) \ __ENUMERATE_SVG_TAG(g) \ __ENUMERATE_SVG_TAG(path) \ __ENUMERATE_SVG_TAG(rect) \ |