From a61f09a0106ec3b62f6202b61473de188e77ac9c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 25 Feb 2024 12:56:01 +0100 Subject: [PATCH] LibWeb: Stretch-fit flex items with aspect ratio but no fixed sizes This solves a particular issue with SVG as flex items, where the SVG has an intrinsic aspect ratio via its viewBox, but no explicit natural width or height. Makes all corporate sponsor logos show up on https://ziglang.org/ :^) --- ...h-intrinsic-aspect-ratio-and-max-height.txt | 6 +++--- ...item-that-only-has-natural-aspect-ratio.txt | 18 +++++++++--------- ...item-that-only-has-natural-aspect-ratio.txt | 13 +++++++++++++ ...tem-that-only-has-natural-aspect-ratio.html | 6 ++++++ .../LibWeb/Layout/FlexFormattingContext.cpp | 15 ++++++++++++--- 5 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.txt create mode 100644 Tests/LibWeb/Layout/input/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.html diff --git a/Tests/LibWeb/Layout/expected/flex/flex-item-with-intrinsic-aspect-ratio-and-max-height.txt b/Tests/LibWeb/Layout/expected/flex/flex-item-with-intrinsic-aspect-ratio-and-max-height.txt index 2e9004c14d..b2e710b739 100644 --- a/Tests/LibWeb/Layout/expected/flex/flex-item-with-intrinsic-aspect-ratio-and-max-height.txt +++ b/Tests/LibWeb/Layout/expected/flex/flex-item-with-intrinsic-aspect-ratio-and-max-height.txt @@ -1,11 +1,11 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline BlockContainer at (1,1) content-size 798x69.984375 [BFC] children: not-inline Box at (10,10) content-size 780x51.984375 flex-container(row) [FFC] children: not-inline - ImageBox at (11,11) content-size 66.65625x49.984375 flex-item children: not-inline + ImageBox at (11,11) content-size 66.65625x50 flex-item children: not-inline BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x71.984375] - PaintableBox (Box) [9,9 782x53.984375] - ImagePaintable (ImageBox) [10,10 68.65625x51.984375] + PaintableBox (Box) [9,9 782x53.984375] overflow: [10,10 780x52] + ImagePaintable (ImageBox) [10,10 68.65625x52] diff --git a/Tests/LibWeb/Layout/expected/flex/intrinsic-height-of-flex-container-with-svg-item-that-only-has-natural-aspect-ratio.txt b/Tests/LibWeb/Layout/expected/flex/intrinsic-height-of-flex-container-with-svg-item-that-only-has-natural-aspect-ratio.txt index 53ec2567ba..33e74be3fb 100644 --- a/Tests/LibWeb/Layout/expected/flex/intrinsic-height-of-flex-container-with-svg-item-that-only-has-natural-aspect-ratio.txt +++ b/Tests/LibWeb/Layout/expected/flex/intrinsic-height-of-flex-container-with-svg-item-that-only-has-natural-aspect-ratio.txt @@ -1,11 +1,11 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline - BlockContainer at (0,0) content-size 800x16 [BFC] children: not-inline - Box at (8,8) content-size 784x0 flex-container(column) [FFC] children: not-inline - SVGSVGBox at (400,8) content-size 0x0 flex-item [SVG] children: not-inline - SVGGeometryBox at (400,8) content-size 0x0 children: not-inline + BlockContainer at (0,0) content-size 800x800 [BFC] children: not-inline + Box at (8,8) content-size 784x784 flex-container(column) [FFC] children: not-inline + SVGSVGBox at (8,8) content-size 784x784 flex-item [SVG] children: not-inline + SVGGeometryBox at (8,8) content-size 392x392 children: not-inline -ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x16] - PaintableBox (Box) [8,8 784x0] - SVGSVGPaintable (SVGSVGBox) [400,8 0x0] - SVGPathPaintable (SVGGeometryBox) [400,8 0x0] +ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x800] + PaintableWithLines (BlockContainer) [0,0 800x800] + PaintableBox (Box) [8,8 784x784] + SVGSVGPaintable (SVGSVGBox) [8,8 784x784] + SVGPathPaintable (SVGGeometryBox) [8,8 392x392] diff --git a/Tests/LibWeb/Layout/expected/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.txt b/Tests/LibWeb/Layout/expected/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.txt new file mode 100644 index 0000000000..ad06bef9cc --- /dev/null +++ b/Tests/LibWeb/Layout/expected/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.txt @@ -0,0 +1,13 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x800 [BFC] children: not-inline + Box at (8,8) content-size 784x784 flex-container(row) [FFC] children: not-inline + SVGSVGBox at (8,8) content-size 784x784 flex-item [SVG] children: not-inline + SVGGeometryBox at (8,8) content-size 392x392 children: not-inline + BlockContainer <(anonymous)> (not painted) [BFC] children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x800] + PaintableWithLines (BlockContainer) [0,0 800x800] + PaintableBox (Box) [8,8 784x784] + SVGSVGPaintable (SVGSVGBox) [8,8 784x784] + SVGPathPaintable (SVGGeometryBox) [8,8 392x392] diff --git a/Tests/LibWeb/Layout/input/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.html b/Tests/LibWeb/Layout/input/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.html new file mode 100644 index 0000000000..b969234cbc --- /dev/null +++ b/Tests/LibWeb/Layout/input/flex/stretch-fit-width-for-column-layout-svg-item-that-only-has-natural-aspect-ratio.html @@ -0,0 +1,6 @@ + diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index d4bf8ea4ae..782bb5ae25 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -628,8 +628,13 @@ void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size( }(); // AD-HOC: This is not mentioned in the spec, but if the item has an aspect ratio, - // we may need to adjust the main size in response to cross size min/max constraints. + // we may need to adjust the main size in these ways: + // - using stretch-fit main size if the flex basis is indefinite. + // - in response to cross size min/max constraints. if (item.box->has_preferred_aspect_ratio()) { + if (!item.used_flex_basis_is_definite) { + item.flex_base_size = inner_main_size(m_flex_container_state); + } item.flex_base_size = adjust_main_size_through_aspect_ratio_for_cross_size_min_max_constraints(child_box, item.flex_base_size, computed_cross_min_size(child_box), computed_cross_max_size(child_box)); } @@ -1038,8 +1043,12 @@ void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem& return; } - if (item.box->has_preferred_aspect_ratio() && item.main_size.has_value()) { - item.hypothetical_cross_size = calculate_cross_size_from_main_size_and_aspect_ratio(item.main_size.value(), item.box->preferred_aspect_ratio().value()); + if (item.box->has_preferred_aspect_ratio()) { + if (item.used_flex_basis_is_definite) { + item.hypothetical_cross_size = calculate_cross_size_from_main_size_and_aspect_ratio(item.main_size.value(), item.box->preferred_aspect_ratio().value()); + return; + } + item.hypothetical_cross_size = inner_cross_size(m_flex_container_state); return; }