From 7a783d3a89aec0caaa63a483c855fe921b6d0984 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Thu, 8 Aug 2024 17:04:59 +0200 Subject: [PATCH] LibWeb: Account for intrinsic width or height in flex base size In calculating the base size of a flex item, we have a piece of ad-hoc code that deals with an item that does have an instrinsic aspect ratio, but not a cross size to resolve that ratio against. In determining the actual flex item size however, we also take into account the minimum content width and height, which assumes the box' intrinsic width or height when available. This would break having an image as a flex item, which gets stretched to its maximum size within the flex container instead of the flex item being shrunk to the instrinsic size of the image. Fix this by only stretching flex items that do not have an instrinsic width nor height set. --- .../flex/flex-item-on-row-with-intrinsic-size.txt | 15 +++++++++++++++ .../flex-item-on-row-with-intrinsic-size.html | 2 ++ .../LibWeb/Layout/FlexFormattingContext.cpp | 12 ++++++------ 3 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/flex/flex-item-on-row-with-intrinsic-size.txt create mode 100644 Tests/LibWeb/Layout/input/flex/flex-item-on-row-with-intrinsic-size.html diff --git a/Tests/LibWeb/Layout/expected/flex/flex-item-on-row-with-intrinsic-size.txt b/Tests/LibWeb/Layout/expected/flex/flex-item-on-row-with-intrinsic-size.txt new file mode 100644 index 00000000000..0a1fe5fc243 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/flex/flex-item-on-row-with-intrinsic-size.txt @@ -0,0 +1,15 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x8 children: not-inline + Box
at (8,8) content-size 784x8 flex-container(row) [FFC] children: not-inline + BlockContainer <(anonymous)> (not painted) [BFC] children: inline + TextNode <#text> + ImageBox at (8,8) content-size 8x8 flex-item children: not-inline + BlockContainer <(anonymous)> (not painted) [BFC] children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x600] + PaintableWithLines (BlockContainer) [8,8 784x8] + PaintableBox (Box
) [8,8 784x8] + ImagePaintable (ImageBox) [8,8 8x8] diff --git a/Tests/LibWeb/Layout/input/flex/flex-item-on-row-with-intrinsic-size.html b/Tests/LibWeb/Layout/input/flex/flex-item-on-row-with-intrinsic-size.html new file mode 100644 index 00000000000..d9631cea095 --- /dev/null +++ b/Tests/LibWeb/Layout/input/flex/flex-item-on-row-with-intrinsic-size.html @@ -0,0 +1,2 @@ +
+ diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index 637c3235beb..9c0978e5d0f 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -621,19 +621,19 @@ void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size( // in the various helpers that calculate the intrinsic sizes of a flex item, // e.g. calculate_min_content_main_size(). - if (item.used_flex_basis->has()) { + if (item.used_flex_basis->has()) return calculate_max_content_main_size(item); - } return calculate_fit_content_main_size(item); }(); - // 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 these ways: - // - using stretch-fit main size if the flex basis is indefinite and there is no cross size to resolve the ratio against. + // 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 these ways: + // - using stretch-fit main size if the flex basis is indefinite, there is no + // intrinsic size and no cross size to resolve the ratio against. // - in response to cross size min/max constraints. if (item.box->has_natural_aspect_ratio()) { - if (!item.used_flex_basis_is_definite && !has_definite_cross_size(item)) { + if (!item.used_flex_basis_is_definite && !item.box->has_natural_width() && !item.box->has_natural_height() && !has_definite_cross_size(item)) { 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));