From 7ae46bf8b7b5d0a1cf1d811fe9b8aecd3488d4eb Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 20 Jan 2025 21:45:46 +0100 Subject: [PATCH] LibWeb: Allow partial update of SVG subtrees in layout tree We were incorrectly always appending to the nearest ancestor in the partial update case, even when the node was eligible for replacement. --- Libraries/LibWeb/Layout/TreeBuilder.cpp | 13 ++++++++----- .../simple-update-inside-svg-subtree.txt | 17 +++++++++++++++++ .../simple-update-inside-svg-subtree.html | 6 ++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/layout-tree-update/simple-update-inside-svg-subtree.txt create mode 100644 Tests/LibWeb/Layout/input/layout-tree-update/simple-update-inside-svg-subtree.html diff --git a/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Libraries/LibWeb/Layout/TreeBuilder.cpp index e3901fa9451..b0f46cf8537 100644 --- a/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -402,17 +402,20 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& if (dom_node.is_document()) { m_layout_root = layout_node; - } else if (layout_node->is_svg_box()) { - m_ancestor_stack.last()->append_child(*layout_node); } else if (should_create_layout_node) { // Decide whether to replace an existing node (partial tree update) or insert a new one appropriately. - if (must_create_subtree == MustCreateSubtree::No + bool const may_replace_existing_layout_node = must_create_subtree == MustCreateSubtree::No && old_layout_node && old_layout_node->parent() - && old_layout_node != layout_node) { + && old_layout_node != layout_node; + if (may_replace_existing_layout_node) { old_layout_node->parent()->replace_child(*layout_node, *old_layout_node); } else { - insert_node_into_inline_or_block_ancestor(*layout_node, display, AppendOrPrepend::Append); + if (layout_node->is_svg_box()) { + m_ancestor_stack.last()->append_child(*layout_node); + } else { + insert_node_into_inline_or_block_ancestor(*layout_node, display, AppendOrPrepend::Append); + } } } diff --git a/Tests/LibWeb/Layout/expected/layout-tree-update/simple-update-inside-svg-subtree.txt b/Tests/LibWeb/Layout/expected/layout-tree-update/simple-update-inside-svg-subtree.txt new file mode 100644 index 00000000000..d828c00c1ed --- /dev/null +++ b/Tests/LibWeb/Layout/expected/layout-tree-update/simple-update-inside-svg-subtree.txt @@ -0,0 +1,17 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x150 children: inline + frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 300x150] baseline: 150 + SVGSVGBox at (8,8) content-size 300x150 [SVG] children: inline + SVGGraphicsBox at (8,8) content-size 300x150 [BFC] children: inline + InlineNode + TextNode <#text> + TextNode <#text> + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x600] + PaintableWithLines (BlockContainer) [8,8 784x150] + SVGSVGPaintable (SVGSVGBox) [8,8 300x150] + SVGGraphicsPaintable (SVGGraphicsBox) [8,8 300x150] + PaintableWithLines (InlineNode#set) diff --git a/Tests/LibWeb/Layout/input/layout-tree-update/simple-update-inside-svg-subtree.html b/Tests/LibWeb/Layout/input/layout-tree-update/simple-update-inside-svg-subtree.html new file mode 100644 index 00000000000..5dc5f5dba6d --- /dev/null +++ b/Tests/LibWeb/Layout/input/layout-tree-update/simple-update-inside-svg-subtree.html @@ -0,0 +1,6 @@ + +