mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 09:17:36 +00:00
LibWeb: Make sure that SVG use and symbol elements get paintables
I'm about to make StackingContext traverse the paintable tree instead of actually traversing the layout tree, and it turns out we were not creating paintables for these SVG elements. Also switch them to Layout::Box instead of the default InlineNode to make the trees look a bit less weird. Ultimately, we should do something specialized for these subtrees, but for now this'll do.
This commit is contained in:
parent
3d7c880a42
commit
1e0ea45fe5
6 changed files with 45 additions and 13 deletions
|
@ -10,8 +10,8 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
SVGSVGBox <svg> at (8,8) content-size 300x150 [SVG] children: inline
|
SVGSVGBox <svg> at (8,8) content-size 300x150 [SVG] children: inline
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
InlineNode <use>
|
Box <use> at (8,8) content-size 0x0 children: inline
|
||||||
InlineNode <symbol#braces>
|
Box <symbol#braces> at (8,8) content-size 0x0 children: inline
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
SVGGeometryBox <path> at (92.375,26.75) content-size 131.25x112.15625 children: inline
|
SVGGeometryBox <path> at (92.375,26.75) content-size 131.25x112.15625 children: inline
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
|
@ -25,3 +25,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
||||||
PaintableWithLines (BlockContainer<DIV>) [8,8 784x150]
|
PaintableWithLines (BlockContainer<DIV>) [8,8 784x150]
|
||||||
SVGSVGPaintable (SVGSVGBox<svg>) [8,8 300x150]
|
SVGSVGPaintable (SVGSVGBox<svg>) [8,8 300x150]
|
||||||
|
PaintableBox (Box<use>) [8,8 0x0]
|
||||||
|
PaintableBox (Box<symbol>#braces) [8,8 0x0]
|
||||||
|
SVGGeometryPaintable (SVGGeometryBox<path>) [92.375,26.75 131.25x112.15625]
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include <LibWeb/Layout/SVGTextBox.h>
|
#include <LibWeb/Layout/SVGTextBox.h>
|
||||||
#include <LibWeb/SVG/SVGForeignObjectElement.h>
|
#include <LibWeb/SVG/SVGForeignObjectElement.h>
|
||||||
#include <LibWeb/SVG/SVGSVGElement.h>
|
#include <LibWeb/SVG/SVGSVGElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGSymbolElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGUseElement.h>
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
|
@ -131,6 +133,21 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio
|
||||||
return viewbox_transform;
|
return viewbox_transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool should_ensure_creation_of_paintable(Node const& node)
|
||||||
|
{
|
||||||
|
if (is<SVGTextBox>(node))
|
||||||
|
return true;
|
||||||
|
if (is<SVGGraphicsBox>(node))
|
||||||
|
return true;
|
||||||
|
if (node.dom_node()) {
|
||||||
|
if (is<SVG::SVGUseElement>(*node.dom_node()))
|
||||||
|
return true;
|
||||||
|
if (is<SVG::SVGSymbolElement>(*node.dom_node()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, AvailableSpace const& available_space)
|
void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, AvailableSpace const& available_space)
|
||||||
{
|
{
|
||||||
auto& svg_svg_element = verify_cast<SVG::SVGSVGElement>(*box.dom_node());
|
auto& svg_svg_element = verify_cast<SVG::SVGSVGElement>(*box.dom_node());
|
||||||
|
@ -149,7 +166,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
|
||||||
box.for_each_in_subtree_of_type<Box>([&](Box const& descendant) {
|
box.for_each_in_subtree([&](Node const& descendant) {
|
||||||
if (is<SVGGeometryBox>(descendant)) {
|
if (is<SVGGeometryBox>(descendant)) {
|
||||||
auto const& geometry_box = static_cast<SVGGeometryBox const&>(descendant);
|
auto const& geometry_box = static_cast<SVGGeometryBox const&>(descendant);
|
||||||
auto& geometry_box_state = m_state.get_mutable(geometry_box);
|
auto& geometry_box_state = m_state.get_mutable(geometry_box);
|
||||||
|
@ -186,16 +203,12 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
|
||||||
geometry_box_state.set_content_width(path_bounding_box.width());
|
geometry_box_state.set_content_width(path_bounding_box.width());
|
||||||
geometry_box_state.set_content_height(path_bounding_box.height());
|
geometry_box_state.set_content_height(path_bounding_box.height());
|
||||||
} else if (is<SVGSVGBox>(descendant)) {
|
} else if (is<SVGSVGBox>(descendant)) {
|
||||||
SVGFormattingContext nested_context(m_state, descendant, this);
|
SVGFormattingContext nested_context(m_state, static_cast<SVGSVGBox const&>(descendant), this);
|
||||||
nested_context.run(descendant, layout_mode, available_space);
|
nested_context.run(static_cast<SVGSVGBox const&>(descendant), layout_mode, available_space);
|
||||||
} else if (is<SVGTextBox>(descendant)) {
|
} else if (should_ensure_creation_of_paintable(descendant)) {
|
||||||
auto const& svg_text_box = static_cast<SVGTextBox const&>(descendant);
|
// NOTE: This hack creates a layout state to ensure the existence of
|
||||||
// NOTE: This hack creates a layout state to ensure the existence of a paintable box node in LayoutState::commit(), even when none of the values from UsedValues impact the SVG text.
|
// a paintable in LayoutState::commit().
|
||||||
m_state.get_mutable(svg_text_box);
|
m_state.get_mutable(static_cast<NodeWithStyleAndBoxModelMetrics const&>(descendant));
|
||||||
} else if (is<SVGGraphicsBox>(descendant)) {
|
|
||||||
// Same hack as above.
|
|
||||||
auto const& svg_graphics_box = static_cast<SVGGraphicsBox const&>(descendant);
|
|
||||||
m_state.get_mutable(svg_graphics_box);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/OverflowStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/OverflowStyleValue.h>
|
||||||
#include <LibWeb/DOM/ShadowRoot.h>
|
#include <LibWeb/DOM/ShadowRoot.h>
|
||||||
|
#include <LibWeb/Layout/Box.h>
|
||||||
#include <LibWeb/SVG/AttributeNames.h>
|
#include <LibWeb/SVG/AttributeNames.h>
|
||||||
#include <LibWeb/SVG/SVGSymbolElement.h>
|
#include <LibWeb/SVG/SVGSymbolElement.h>
|
||||||
#include <LibWeb/SVG/SVGUseElement.h>
|
#include <LibWeb/SVG/SVGUseElement.h>
|
||||||
|
@ -62,4 +63,9 @@ bool SVGSymbolElement::is_direct_child_of_use_shadow_tree() const
|
||||||
return is<SVGUseElement>(host);
|
return is<SVGUseElement>(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS::GCPtr<Layout::Node> SVGSymbolElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
|
||||||
|
{
|
||||||
|
return heap().allocate_without_realm<Layout::Box>(document(), this, move(style));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ private:
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
|
||||||
|
|
||||||
bool is_direct_child_of_use_shadow_tree() const;
|
bool is_direct_child_of_use_shadow_tree() const;
|
||||||
|
|
||||||
virtual void attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) override;
|
virtual void attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) override;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <LibWeb/DOM/ElementFactory.h>
|
#include <LibWeb/DOM/ElementFactory.h>
|
||||||
#include <LibWeb/DOM/Event.h>
|
#include <LibWeb/DOM/Event.h>
|
||||||
#include <LibWeb/DOM/ShadowRoot.h>
|
#include <LibWeb/DOM/ShadowRoot.h>
|
||||||
|
#include <LibWeb/Layout/Box.h>
|
||||||
#include <LibWeb/Namespace.h>
|
#include <LibWeb/Namespace.h>
|
||||||
#include <LibWeb/SVG/AttributeNames.h>
|
#include <LibWeb/SVG/AttributeNames.h>
|
||||||
#include <LibWeb/SVG/SVGSVGElement.h>
|
#include <LibWeb/SVG/SVGSVGElement.h>
|
||||||
|
@ -172,4 +173,9 @@ JS::GCPtr<SVGElement> SVGUseElement::animated_instance_root() const
|
||||||
return instance_root();
|
return instance_root();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS::GCPtr<Layout::Node> SVGUseElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
|
||||||
|
{
|
||||||
|
return heap().allocate_without_realm<Layout::Box>(document(), this, move(style));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ private:
|
||||||
|
|
||||||
virtual bool is_svg_use_element() const override { return true; }
|
virtual bool is_svg_use_element() const override { return true; }
|
||||||
|
|
||||||
|
virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
|
||||||
|
|
||||||
Optional<StringView> parse_id_from_href(DeprecatedString const& href);
|
Optional<StringView> parse_id_from_href(DeprecatedString const& href);
|
||||||
|
|
||||||
JS::GCPtr<DOM::Element> referenced_element();
|
JS::GCPtr<DOM::Element> referenced_element();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue