mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:07:34 +00:00
LibWeb: Allow SVG painting to escape out of a shadow tree
The spec for the `<use>` element requires a shadow tree for the rendered content, so we need to be able to escape shadow trees when rendering svg content.
This commit is contained in:
parent
fd360ba171
commit
31d536912c
5 changed files with 24 additions and 5 deletions
|
@ -636,6 +636,15 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
U const* shadow_including_first_ancestor_of_type() const
|
||||||
|
{
|
||||||
|
return const_cast<Node*>(this)->template shadow_including_first_ancestor_of_type<U>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
U* shadow_including_first_ancestor_of_type();
|
||||||
|
|
||||||
bool is_parent_of(Node const& other) const
|
bool is_parent_of(Node const& other) const
|
||||||
{
|
{
|
||||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||||
|
|
|
@ -55,6 +55,16 @@ private:
|
||||||
template<>
|
template<>
|
||||||
inline bool Node::fast_is<ParentNode>() const { return is_parent_node(); }
|
inline bool Node::fast_is<ParentNode>() const { return is_parent_node(); }
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
inline U* Node::shadow_including_first_ancestor_of_type()
|
||||||
|
{
|
||||||
|
for (auto* ancestor = parent_or_shadow_host(); ancestor; ancestor = ancestor->parent_or_shadow_host()) {
|
||||||
|
if (is<U>(*ancestor))
|
||||||
|
return &verify_cast<U>(*ancestor);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
inline void ParentNode::for_each_child(Callback callback) const
|
inline void ParentNode::for_each_child(Callback callback) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ SVGGeometryBox::SVGGeometryBox(DOM::Document& document, SVG::SVGGeometryElement&
|
||||||
|
|
||||||
CSSPixelPoint SVGGeometryBox::viewbox_origin() const
|
CSSPixelPoint SVGGeometryBox::viewbox_origin() const
|
||||||
{
|
{
|
||||||
auto* svg_box = dom_node().first_ancestor_of_type<SVG::SVGSVGElement>();
|
auto* svg_box = dom_node().shadow_including_first_ancestor_of_type<SVG::SVGSVGElement>();
|
||||||
if (!svg_box || !svg_box->view_box().has_value())
|
if (!svg_box || !svg_box->view_box().has_value())
|
||||||
return { 0, 0 };
|
return { 0, 0 };
|
||||||
return { svg_box->view_box().value().min_x, svg_box->view_box().value().min_y };
|
return { svg_box->view_box().value().min_x, svg_box->view_box().value().min_y };
|
||||||
|
@ -29,7 +29,7 @@ Optional<Gfx::AffineTransform> SVGGeometryBox::layout_transform() const
|
||||||
{
|
{
|
||||||
auto& geometry_element = dom_node();
|
auto& geometry_element = dom_node();
|
||||||
auto transform = geometry_element.get_transform();
|
auto transform = geometry_element.get_transform();
|
||||||
auto* svg_box = geometry_element.first_ancestor_of_type<SVG::SVGSVGElement>();
|
auto* svg_box = geometry_element.shadow_including_first_ancestor_of_type<SVG::SVGSVGElement>();
|
||||||
double scaling = 1;
|
double scaling = 1;
|
||||||
auto origin = viewbox_origin().to_type<double>().to_type<float>();
|
auto origin = viewbox_origin().to_type<double>().to_type<float>();
|
||||||
Gfx::FloatPoint paint_offset = {};
|
Gfx::FloatPoint paint_offset = {};
|
||||||
|
|
|
@ -62,7 +62,7 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||||
auto offset = context.floored_device_point(svg_context.svg_element_position()).to_type<int>().to_type<float>();
|
auto offset = context.floored_device_point(svg_context.svg_element_position()).to_type<int>().to_type<float>();
|
||||||
painter.translate(offset);
|
painter.translate(offset);
|
||||||
|
|
||||||
auto const* svg_element = geometry_element.first_ancestor_of_type<SVG::SVGSVGElement>();
|
auto const* svg_element = geometry_element.shadow_including_first_ancestor_of_type<SVG::SVGSVGElement>();
|
||||||
auto maybe_view_box = svg_element->view_box();
|
auto maybe_view_box = svg_element->view_box();
|
||||||
|
|
||||||
auto transform = layout_box().layout_transform();
|
auto transform = layout_box().layout_transform();
|
||||||
|
|
|
@ -97,7 +97,7 @@ Gfx::AffineTransform SVGGraphicsElement::get_transform() const
|
||||||
{
|
{
|
||||||
// FIXME: It would be nice to do this using the SVGContext, however, then layout/hit testing knows nothing about the transform.
|
// FIXME: It would be nice to do this using the SVGContext, however, then layout/hit testing knows nothing about the transform.
|
||||||
Gfx::AffineTransform transform = m_transform;
|
Gfx::AffineTransform transform = m_transform;
|
||||||
for (auto* svg_ancestor = first_ancestor_of_type<SVGGraphicsElement>(); svg_ancestor; svg_ancestor = svg_ancestor->first_ancestor_of_type<SVGGraphicsElement>()) {
|
for (auto* svg_ancestor = shadow_including_first_ancestor_of_type<SVGGraphicsElement>(); svg_ancestor; svg_ancestor = svg_ancestor->shadow_including_first_ancestor_of_type<SVGGraphicsElement>()) {
|
||||||
transform = Gfx::AffineTransform { svg_ancestor->m_transform }.multiply(transform);
|
transform = Gfx::AffineTransform { svg_ancestor->m_transform }.multiply(transform);
|
||||||
}
|
}
|
||||||
return transform;
|
return transform;
|
||||||
|
@ -179,7 +179,7 @@ Optional<float> SVGGraphicsElement::stroke_width() const
|
||||||
// FIXME: This isn't right, but it's something.
|
// FIXME: This isn't right, but it's something.
|
||||||
CSSPixels viewport_width = 0;
|
CSSPixels viewport_width = 0;
|
||||||
CSSPixels viewport_height = 0;
|
CSSPixels viewport_height = 0;
|
||||||
if (auto* svg_svg_element = first_ancestor_of_type<SVGSVGElement>()) {
|
if (auto* svg_svg_element = shadow_including_first_ancestor_of_type<SVGSVGElement>()) {
|
||||||
if (auto* svg_svg_layout_node = svg_svg_element->layout_node()) {
|
if (auto* svg_svg_layout_node = svg_svg_element->layout_node()) {
|
||||||
viewport_width = svg_svg_layout_node->computed_values().width().to_px(*svg_svg_layout_node, 0);
|
viewport_width = svg_svg_layout_node->computed_values().width().to_px(*svg_svg_layout_node, 0);
|
||||||
viewport_height = svg_svg_layout_node->computed_values().height().to_px(*svg_svg_layout_node, 0);
|
viewport_height = svg_svg_layout_node->computed_values().height().to_px(*svg_svg_layout_node, 0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue