From b4708510fb3515d4189a00799014ea5711b82668 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 7 Jul 2025 19:30:38 +0200 Subject: [PATCH] LibWeb: Layout foreignObject as block-level element with hidden overflow This is according to the default user-agent style from the SVG2 spec. In order for this to work correctly, we also have to assign width and height to foreignObject boxes during SVG layout, since they are handled manually by SVGFormattingContext. --- .../LibWeb/Layout/SVGFormattingContext.cpp | 2 + Libraries/LibWeb/SVG/Default.css | 5 +++ .../foreignObject-with-abspos-descendant.txt | 8 ++-- .../svg-foreign-object-with-block-element.txt | 37 ++++++++++++------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/Libraries/LibWeb/Layout/SVGFormattingContext.cpp b/Libraries/LibWeb/Layout/SVGFormattingContext.cpp index 2b6885f9c5a..cf666e61ffa 100644 --- a/Libraries/LibWeb/Layout/SVGFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/SVGFormattingContext.cpp @@ -282,6 +282,8 @@ void SVGFormattingContext::layout_svg_element(Box const& child) bfc.run(*m_available_space); auto& child_state = m_state.get_mutable(child); child_state.set_content_offset(child_state.offset.translated(m_svg_offset)); + 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.for_each_child_of_type([&](SVGMaskBox const& child) { layout_svg_element(child); return IterationDecision::Continue; diff --git a/Libraries/LibWeb/SVG/Default.css b/Libraries/LibWeb/SVG/Default.css index 5a5945d2a75..8bb556a1f0a 100644 --- a/Libraries/LibWeb/SVG/Default.css +++ b/Libraries/LibWeb/SVG/Default.css @@ -32,3 +32,8 @@ symbol { :link, :visited { cursor: pointer; } + +foreignObject { + display: block; + overflow: hidden; +} diff --git a/Tests/LibWeb/Layout/expected/svg/foreignObject-with-abspos-descendant.txt b/Tests/LibWeb/Layout/expected/svg/foreignObject-with-abspos-descendant.txt index f59e9297f6b..eb2612f3ff7 100644 --- a/Tests/LibWeb/Layout/expected/svg/foreignObject-with-abspos-descendant.txt +++ b/Tests/LibWeb/Layout/expected/svg/foreignObject-with-abspos-descendant.txt @@ -1,14 +1,16 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline BlockContainer at (0,0) content-size 800x166 [BFC] children: not-inline BlockContainer at (8,8) content-size 784x150 children: not-inline - SVGSVGBox at (8,8) content-size 300x150 [SVG] children: inline - TextNode <#text> + SVGSVGBox at (8,8) content-size 300x150 [SVG] children: not-inline + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> SVGForeignObjectBox at (8,8) content-size 100x200 [BFC] children: not-inline BlockContainer <(anonymous)> at (8,8) content-size 300x0 children: inline TextNode <#text> BlockContainer at (8,8) content-size 50x60 positioned [BFC] children: not-inline TextNode <#text> - TextNode <#text> + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> BlockContainer <(anonymous)> at (8,158) content-size 784x0 children: inline TextNode <#text> diff --git a/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt b/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt index 91e01e3ffb1..a399623e2a2 100644 --- a/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt +++ b/Tests/LibWeb/Layout/expected/svg/svg-foreign-object-with-block-element.txt @@ -1,22 +1,31 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline - BlockContainer at (0,0) content-size 800x116 [BFC] children: not-inline - BlockContainer at (8,8) content-size 784x100 children: inline - frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 100x100] baseline: 100 - SVGSVGBox at (8,8) content-size 100x100 [SVG] children: inline - SVGForeignObjectBox at (8,8) content-size 100x100 [BFC] children: not-inline - BlockContainer
at (8,8) content-size 100x18 children: inline - frag 0 from TextNode start: 0, length: 3, rect: [8,8 27.15625x18] baseline: 13.796875 + BlockContainer at (0,0) content-size 800x316 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x300 children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 784x100 children: inline + frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 100x100] baseline: 100 + SVGSVGBox at (8,8) content-size 100x100 [SVG] children: inline + BlockContainer <(anonymous)> at (8,108) content-size 784x100 children: not-inline continuation + SVGForeignObjectBox at (8,108) content-size 100x100 [BFC] children: not-inline + BlockContainer
at (8,108) content-size 100x18 children: inline + frag 0 from TextNode start: 0, length: 3, rect: [8,108 27.15625x18] baseline: 13.796875 "foo" TextNode <#text> + BlockContainer <(anonymous)> at (8,208) content-size 784x100 children: inline + frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,208 100x100] baseline: 100 + SVGSVGBox at (8,208) content-size 100x100 [SVG] children: not-inline continuation ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x116] - PaintableWithLines (BlockContainer) [8,8 784x100] - SVGSVGPaintable (SVGSVGBox) [8,8 100x100] - SVGForeignObjectPaintable (SVGForeignObjectBox) [8,8 100x100] - PaintableWithLines (BlockContainer
) [8,8 100x18] + PaintableWithLines (BlockContainer) [0,0 800x316] + PaintableWithLines (BlockContainer) [8,8 784x300] + PaintableWithLines (BlockContainer(anonymous)) [8,8 784x100] + SVGSVGPaintable (SVGSVGBox) [8,8 100x100] + PaintableWithLines (BlockContainer(anonymous)) [8,108 784x100] + SVGForeignObjectPaintable (SVGForeignObjectBox) [8,108 100x100] + PaintableWithLines (BlockContainer
) [8,108 100x18] TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [8,208 784x100] + SVGSVGPaintable (SVGSVGBox) [8,208 100x100] SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto) - SC for BlockContainer [0,0 800x116] [children: 1] (z-index: auto) - SC for SVGForeignObjectBox [8,8 100x100] [children: 0] (z-index: auto) + SC for BlockContainer [0,0 800x316] [children: 1] (z-index: auto) + SC for SVGForeignObjectBox [8,108 100x100] [children: 0] (z-index: auto)