From 0af8d81f484517d87c87dec7b02dd52a3d944779 Mon Sep 17 00:00:00 2001 From: MacDue Date: Sun, 17 Sep 2023 15:32:24 +0100 Subject: [PATCH] LibWeb: Layout SVG elements (but don't paint them) This allows SVG mask elements to have layout computed, but not connected to the main paint tree. They should only be reachable if (and painted) if referenced by the "mask" attribute of another element. This is controlled by the forms_unconnected_subtree() function on the paintable, which (if it returns true) prevents the paintable from being added as a child to what would be its parent. --- ...element-should-not-participate-in-layout.txt | 17 ----------------- ...lement-should-not-participate-in-layout.html | 7 ------- .../Libraries/LibWeb/Layout/LayoutState.cpp | 2 +- Userland/Libraries/LibWeb/Painting/Paintable.h | 2 ++ .../LibWeb/Painting/SVGGraphicsPaintable.cpp | 7 +++++++ .../LibWeb/Painting/SVGGraphicsPaintable.h | 2 ++ .../Libraries/LibWeb/SVG/SVGDefsElement.cpp | 6 ++++-- .../Libraries/LibWeb/SVG/SVGMaskElement.cpp | 5 +++-- 8 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 Tests/LibWeb/Layout/expected/svg/mask-element-should-not-participate-in-layout.txt delete mode 100644 Tests/LibWeb/Layout/input/svg/mask-element-should-not-participate-in-layout.html diff --git a/Tests/LibWeb/Layout/expected/svg/mask-element-should-not-participate-in-layout.txt b/Tests/LibWeb/Layout/expected/svg/mask-element-should-not-participate-in-layout.txt deleted file mode 100644 index 66e291a5a7..0000000000 --- a/Tests/LibWeb/Layout/expected/svg/mask-element-should-not-participate-in-layout.txt +++ /dev/null @@ -1,17 +0,0 @@ -Viewport <#document> at (0,0) content-size 800x600 children: not-inline - BlockContainer at (0,0) content-size 800x116 [BFC] children: not-inline - BlockContainer at (8,8) content-size 784x100 children: inline - line 0 width: 100, height: 100, bottom: 100, baseline: 100 - frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 100x100] - SVGSVGBox at (8,8) content-size 100x100 [SVG] children: inline - TextNode <#text> - SVGGeometryBox at (8,8) content-size 100x100 children: not-inline - TextNode <#text> - TextNode <#text> - TextNode <#text> - -ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x116] - PaintableWithLines (BlockContainer) [8,8 784x100] - SVGSVGPaintable (SVGSVGBox) [8,8 100x100] - SVGGeometryPaintable (SVGGeometryBox) [8,8 100x100] diff --git a/Tests/LibWeb/Layout/input/svg/mask-element-should-not-participate-in-layout.html b/Tests/LibWeb/Layout/input/svg/mask-element-should-not-participate-in-layout.html deleted file mode 100644 index e9096ac122..0000000000 --- a/Tests/LibWeb/Layout/input/svg/mask-element-should-not-participate-in-layout.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index 4db316074a..be4d456714 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -201,7 +201,7 @@ static void build_paint_tree(Node& node, Painting::Paintable* parent_paintable = Painting::Paintable* paintable = nullptr; if (node.paintable()) { paintable = const_cast(node.paintable()); - if (parent_paintable) { + if (parent_paintable && !paintable->forms_unconnected_subtree()) { VERIFY(!paintable->parent()); parent_paintable->append_child(*paintable); } diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.h b/Userland/Libraries/LibWeb/Painting/Paintable.h index 49e97f5316..fb10819514 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.h +++ b/Userland/Libraries/LibWeb/Painting/Paintable.h @@ -124,6 +124,8 @@ public: virtual bool wants_mouse_events() const { return false; } + virtual bool forms_unconnected_subtree() const { return false; } + enum class DispatchEventOfSameName { Yes, No, diff --git a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp index 0e30c14ad1..22f6c0ef1a 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace Web::Painting { @@ -19,6 +20,12 @@ SVGGraphicsPaintable::SVGGraphicsPaintable(Layout::SVGGraphicsBox const& layout_ { } +bool SVGGraphicsPaintable::forms_unconnected_subtree() const +{ + // Masks should not be painted (i.e. reachable) unless referenced by another element. + return is(dom_node()); +} + Layout::SVGGraphicsBox const& SVGGraphicsPaintable::layout_box() const { return static_cast(layout_node()); diff --git a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h b/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h index 5366a90265..e1d8c16d06 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h +++ b/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h @@ -19,6 +19,8 @@ public: Layout::SVGGraphicsBox const& layout_box() const; + virtual bool forms_unconnected_subtree() const override; + protected: SVGGraphicsPaintable(Layout::SVGGraphicsBox const&); }; diff --git a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp index 1403ed8380..119830da61 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp @@ -5,6 +5,7 @@ */ #include +#include #include namespace Web::SVG { @@ -24,9 +25,10 @@ void SVGDefsElement::initialize(JS::Realm& realm) set_prototype(&Bindings::ensure_web_prototype(realm, "SVGDefsElement")); } -JS::GCPtr SVGDefsElement::create_layout_node(NonnullRefPtr) +JS::GCPtr SVGDefsElement::create_layout_node(NonnullRefPtr style) { - return nullptr; + // FIXME: We need this layout node so any s inside this element get layout computed. + return heap().allocate_without_realm(document(), *this, move(style)); } } diff --git a/Userland/Libraries/LibWeb/SVG/SVGMaskElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGMaskElement.cpp index d7fcab4e1f..5fdefd6967 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGMaskElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGMaskElement.cpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace Web::SVG { @@ -23,9 +24,9 @@ void SVGMaskElement::initialize(JS::Realm& realm) set_prototype(&Bindings::ensure_web_prototype(realm, "SVGMaskElement")); } -JS::GCPtr SVGMaskElement::create_layout_node(NonnullRefPtr) +JS::GCPtr SVGMaskElement::create_layout_node(NonnullRefPtr style) { - return nullptr; + return heap().allocate_without_realm(document(), *this, move(style)); } }