mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:27:45 +00:00
LibWeb: Ignore svg elements outside of <svg> when building layout tree
An svg layout element without a `SVGSVGElement` ancestor caused a failed assertion before, because the svg context does not exist when `paint()` is called
This commit is contained in:
parent
758d816b23
commit
e8d10fb429
5 changed files with 28 additions and 5 deletions
|
@ -69,6 +69,9 @@ public:
|
||||||
bool is_parent_node() const { return is_element() || is_document() || is_document_fragment(); }
|
bool is_parent_node() const { return is_element() || is_document() || is_document_fragment(); }
|
||||||
bool is_slottable() const { return is_element() || is_text(); }
|
bool is_slottable() const { return is_element() || is_text(); }
|
||||||
|
|
||||||
|
virtual bool requires_svg_container() const { return false; }
|
||||||
|
virtual bool is_svg_container() const { return false; }
|
||||||
|
|
||||||
// NOTE: This is intended for the JS bindings.
|
// NOTE: This is intended for the JS bindings.
|
||||||
u16 node_type() const { return (u16)m_type; }
|
u16 node_type() const { return (u16)m_type; }
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/Optional.h>
|
||||||
|
#include <AK/TemporaryChange.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOM/Element.h>
|
#include <LibWeb/DOM/Element.h>
|
||||||
#include <LibWeb/DOM/ParentNode.h>
|
#include <LibWeb/DOM/ParentNode.h>
|
||||||
|
@ -70,12 +72,20 @@ static Layout::Node& insertion_parent_for_block_node(Layout::Node& layout_parent
|
||||||
return layout_parent;
|
return layout_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeBuilder::create_layout_tree(DOM::Node& dom_node)
|
void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& context)
|
||||||
{
|
{
|
||||||
// If the parent doesn't have a layout node, we don't need one either.
|
// If the parent doesn't have a layout node, we don't need one either.
|
||||||
if (dom_node.parent_or_shadow_host() && !dom_node.parent_or_shadow_host()->layout_node())
|
if (dom_node.parent_or_shadow_host() && !dom_node.parent_or_shadow_host()->layout_node())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Optional<TemporaryChange<bool>> has_svg_root_change;
|
||||||
|
|
||||||
|
if (dom_node.is_svg_container()) {
|
||||||
|
has_svg_root_change.emplace(context.has_svg_root, true);
|
||||||
|
} else if (dom_node.requires_svg_container() && !context.has_svg_root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto layout_node = dom_node.create_layout_node();
|
auto layout_node = dom_node.create_layout_node();
|
||||||
if (!layout_node)
|
if (!layout_node)
|
||||||
return;
|
return;
|
||||||
|
@ -108,9 +118,9 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node)
|
||||||
if ((dom_node.has_children() || shadow_root) && layout_node->can_have_children()) {
|
if ((dom_node.has_children() || shadow_root) && layout_node->can_have_children()) {
|
||||||
push_parent(verify_cast<NodeWithStyle>(*layout_node));
|
push_parent(verify_cast<NodeWithStyle>(*layout_node));
|
||||||
if (shadow_root)
|
if (shadow_root)
|
||||||
create_layout_tree(*shadow_root);
|
create_layout_tree(*shadow_root, context);
|
||||||
verify_cast<DOM::ParentNode>(dom_node).for_each_child([&](auto& dom_child) {
|
verify_cast<DOM::ParentNode>(dom_node).for_each_child([&](auto& dom_child) {
|
||||||
create_layout_tree(dom_child);
|
create_layout_tree(dom_child, context);
|
||||||
});
|
});
|
||||||
pop_parent();
|
pop_parent();
|
||||||
}
|
}
|
||||||
|
@ -124,7 +134,8 @@ RefPtr<Node> TreeBuilder::build(DOM::Node& dom_node)
|
||||||
m_parent_stack.prepend(verify_cast<NodeWithStyle>(ancestor));
|
m_parent_stack.prepend(verify_cast<NodeWithStyle>(ancestor));
|
||||||
}
|
}
|
||||||
|
|
||||||
create_layout_tree(dom_node);
|
Context context;
|
||||||
|
create_layout_tree(dom_node, context);
|
||||||
|
|
||||||
if (auto* root = dom_node.document().layout_node())
|
if (auto* root = dom_node.document().layout_node())
|
||||||
fixup_tables(*root);
|
fixup_tables(*root);
|
||||||
|
|
|
@ -19,7 +19,11 @@ public:
|
||||||
RefPtr<Layout::Node> build(DOM::Node&);
|
RefPtr<Layout::Node> build(DOM::Node&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void create_layout_tree(DOM::Node&);
|
struct Context {
|
||||||
|
bool has_svg_root = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void create_layout_tree(DOM::Node&, Context&);
|
||||||
|
|
||||||
void push_parent(Layout::NodeWithStyle& node) { m_parent_stack.append(&node); }
|
void push_parent(Layout::NodeWithStyle& node) { m_parent_stack.append(&node); }
|
||||||
void pop_parent() { m_parent_stack.take_last(); }
|
void pop_parent() { m_parent_stack.take_last(); }
|
||||||
|
|
|
@ -14,6 +14,8 @@ class SVGElement : public DOM::Element {
|
||||||
public:
|
public:
|
||||||
using WrapperType = Bindings::SVGElementWrapper;
|
using WrapperType = Bindings::SVGElementWrapper;
|
||||||
|
|
||||||
|
virtual bool requires_svg_container() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SVGElement(DOM::Document&, QualifiedName);
|
SVGElement(DOM::Document&, QualifiedName);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,9 @@ public:
|
||||||
unsigned width() const;
|
unsigned width() const;
|
||||||
unsigned height() const;
|
unsigned height() const;
|
||||||
|
|
||||||
|
virtual bool requires_svg_container() const override { return false; }
|
||||||
|
virtual bool is_svg_container() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<Gfx::Bitmap> m_bitmap;
|
RefPtr<Gfx::Bitmap> m_bitmap;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue