LibWeb: Apply SVG viewbox transform to foreignObject elements

This commit is contained in:
Andreas Kling 2025-07-08 10:31:42 +02:00 committed by Andreas Kling
commit f5f3cd041a
Notes: github-actions[bot] 2025-07-09 12:37:35 +00:00
5 changed files with 100 additions and 3 deletions

View file

@ -281,9 +281,20 @@ void SVGFormattingContext::layout_svg_element(Box const& child)
Layout::BlockFormattingContext bfc(m_state, m_layout_mode, static_cast<BlockContainer const&>(child), this); Layout::BlockFormattingContext bfc(m_state, m_layout_mode, static_cast<BlockContainer const&>(child), this);
bfc.run(*m_available_space); bfc.run(*m_available_space);
auto& child_state = m_state.get_mutable(child); auto& child_state = m_state.get_mutable(child);
child_state.set_content_offset(child_state.offset.translated(m_svg_offset)); CSSPixelRect rect {
child_state.set_content_width(child.computed_values().width().to_px(child, m_available_space->width.to_px_or_zero())); {
child_state.set_content_height(child.computed_values().height().to_px(child, m_available_space->height.to_px_or_zero())); child.computed_values().x().to_px(child, m_available_space->width.to_px_or_zero()),
child.computed_values().y().to_px(child, m_available_space->height.to_px_or_zero()),
},
{
child.computed_values().width().to_px(child, m_available_space->width.to_px_or_zero()),
child.computed_values().height().to_px(child, m_available_space->height.to_px_or_zero()),
}
};
auto transformed_rect = m_current_viewbox_transform.map(rect.to_type<float>()).to_type<CSSPixels>();
child_state.set_content_offset(transformed_rect.location());
child_state.set_content_width(transformed_rect.width());
child_state.set_content_height(transformed_rect.height());
child.for_each_child_of_type<SVGMaskBox>([&](SVGMaskBox const& child) { child.for_each_child_of_type<SVGMaskBox>([&](SVGMaskBox const& child) {
layout_svg_element(child); layout_svg_element(child);
return IterationDecision::Continue; return IterationDecision::Continue;

View file

@ -0,0 +1,20 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x64 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x48 children: not-inline
SVGSVGBox <svg> at (8,8) content-size 48x48 [SVG] children: not-inline
SVGForeignObjectBox <foreignObject> at (8,8) content-size 30x30 [BFC] children: not-inline
BlockContainer <div> at (13,13) content-size 40x40 children: not-inline
BlockContainer <(anonymous)> at (8,56) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x64]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x48]
SVGSVGPaintable (SVGSVGBox<svg>) [8,8 48x48]
SVGForeignObjectPaintable (SVGForeignObjectBox<foreignObject>) [8,8 30x30] overflow: [8,8 50x50]
PaintableWithLines (BlockContainer<DIV>) [8,8 50x50]
PaintableWithLines (BlockContainer(anonymous)) [8,56 784x0]
SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto)
SC for BlockContainer<HTML> [0,0 800x64] [children: 1] (z-index: auto)
SC for SVGForeignObjectBox<foreignObject> [8,8 30x30] [children: 0] (z-index: auto)

View file

@ -0,0 +1,29 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x64 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x48 children: not-inline
SVGSVGBox <svg> at (8,8) content-size 48x48 [SVG] children: not-inline
BlockContainer <(anonymous)> (not painted) children: inline
TextNode <#text>
TextNode <#text>
TextNode <#text>
SVGForeignObjectBox <foreignObject> at (26,36) content-size 40x40 [BFC] children: not-inline
BlockContainer <div.lmao> at (31,41) content-size 40x40 children: not-inline
SVGMaskBox <mask#rektMask> at (16,16) content-size 48x48 children: inline
TextNode <#text>
SVGGraphicsBox <use> at (16,16) content-size 48x48 children: not-inline
SVGGeometryBox <rect#rekt> at (16,16) content-size 48x48 children: not-inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,56) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x64]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x48]
SVGSVGPaintable (SVGSVGBox<svg>) [8,8 48x48] overflow: [8,8 58x68]
SVGForeignObjectPaintable (SVGForeignObjectBox<foreignObject>) [26,36 40x40] overflow: [16,16 60x70]
PaintableWithLines (BlockContainer<DIV>.lmao) [26,36 50x50]
PaintableWithLines (BlockContainer(anonymous)) [8,56 784x0]
SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto)
SC for BlockContainer<HTML> [0,0 800x64] [children: 1] (z-index: auto)
SC for SVGForeignObjectBox<foreignObject> [26,36 40x40] [children: 0] (z-index: auto)

View file

@ -0,0 +1,13 @@
<!doctype html>
<style>
* { outline: 1px solid black; }
div {
width: 40px;
height: 40px;
background: orange;
border: 5px solid red;
}
svg {
display: block;
}
</style><svg width="48" height="48" viewBox="0 0 48 48"><foreignObject x="0" y="0" width="30" height="30"><div></div></foreignObject></svg>

View file

@ -0,0 +1,24 @@
<!doctype html>
<style>
* {
background: #888;
outline: 1px solid black;
}
.lmao {
width: 40px;
height: 40px;
background: orange;
border: 5px solid red;
}
svg {
display: block;
}
</style
><svg width="48" height="48" viewBox="-8 -8 48 48">
<defs><rect x="0" y="0" width="48" height="48" id="rekt" /></defs>
<mask id="rektMask" x="0" y="0" width="40" height="40">
<use href="#rekt" fill="white"></use>
</mask>
<foreignObject mask="url(#rektMask)" x="10" y="20" width="40" height="40"
><div class="lmao"></div
></foreignObject></svg>