From 41e8211405ae8187ccba1678b1d7d0e77d32fbcd Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 4 Aug 2025 15:55:19 +0200 Subject: [PATCH] LibWeb: Honor "should treat as auto" cases in aspect-ratio decisions --- .../LibWeb/Layout/BlockFormattingContext.cpp | 8 +++---- Libraries/LibWeb/Layout/FormattingContext.cpp | 10 ++++---- Libraries/LibWeb/Layout/FormattingContext.h | 4 ++-- .../LibWeb/Layout/InlineFormattingContext.cpp | 2 +- ...spect-ratio-and-cyclic-percentages-row.txt | 24 +++++++++++++++++++ ...pect-ratio-and-cyclic-percentages-row.html | 16 +++++++++++++ 6 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/flex/aspect-ratio-and-cyclic-percentages-row.txt create mode 100644 Tests/LibWeb/Layout/input/flex/aspect-ratio-and-cyclic-percentages-row.html diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index dad28349a81..f0c8dc1822f 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -187,7 +187,7 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const& remaining_available_space.width = AvailableSize::make_definite(remaining_width); } - if (box_is_sized_as_replaced_element(box)) { + if (box_is_sized_as_replaced_element(box, available_space)) { // FIXME: This should not be done *by* ReplacedBox if (is(box)) { auto& replaced = as(box); @@ -297,7 +297,7 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const& }; auto input_width = [&] { - if (box_is_sized_as_replaced_element(box)) { + if (box_is_sized_as_replaced_element(box, available_space)) { // NOTE: Replaced elements had their width calculated independently above. // We use that width as the input here to ensure that margins get resolved. return CSS::Length::make_px(box_state.content_width()); @@ -329,7 +329,7 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const& used_width = try_compute_width(CSS::Length::make_px(min_width)); } - if (!box_is_sized_as_replaced_element(box) && !used_width.is_auto()) + if (!box_is_sized_as_replaced_element(box, available_space) && !used_width.is_auto()) box_state.set_content_width(used_width.to_px(box)); box_state.margin_left = margin_left.to_px(box); @@ -522,7 +522,7 @@ void BlockFormattingContext::resolve_used_height_if_treated_as_auto(Box const& b auto& box_state = m_state.get_mutable(box); CSSPixels height = 0; - if (box_is_sized_as_replaced_element(box)) { + if (box_is_sized_as_replaced_element(box, available_space)) { height = compute_height_for_replaced_element(box, available_space); } else { if (box_formatting_context) { diff --git a/Libraries/LibWeb/Layout/FormattingContext.cpp b/Libraries/LibWeb/Layout/FormattingContext.cpp index e40cb6e2577..e880c8bdd92 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -551,7 +551,7 @@ CSSPixels FormattingContext::tentative_width_for_replaced_element(Box const& box void FormattingContext::compute_width_for_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space) { - if (box_is_sized_as_replaced_element(box)) + if (box_is_sized_as_replaced_element(box, available_space)) compute_width_for_absolutely_positioned_replaced_element(box, available_space); else compute_width_for_absolutely_positioned_non_replaced_element(box, available_space); @@ -559,7 +559,7 @@ void FormattingContext::compute_width_for_absolutely_positioned_element(Box cons void FormattingContext::compute_height_for_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space, BeforeOrAfterInsideLayout before_or_after_inside_layout) { - if (box_is_sized_as_replaced_element(box)) + if (box_is_sized_as_replaced_element(box, available_space)) compute_height_for_absolutely_positioned_replaced_element(box, available_space, before_or_after_inside_layout); else compute_height_for_absolutely_positioned_non_replaced_element(box, available_space, before_or_after_inside_layout); @@ -1888,7 +1888,7 @@ CSSPixelRect FormattingContext::margin_box_rect_in_ancestor_coordinate_space(Box return margin_box_rect_in_ancestor_coordinate_space(m_state.get(box), ancestor_box); } -bool box_is_sized_as_replaced_element(Box const& box) +bool FormattingContext::box_is_sized_as_replaced_element(Box const& box, AvailableSpace const& available_space) const { // When a box has a preferred aspect ratio, its automatic sizes are calculated the same as for a // replaced element with a natural aspect ratio and no natural size in that axis, see e.g. CSS2 ยง10 @@ -1906,8 +1906,8 @@ bool box_is_sized_as_replaced_element(Box const& box) // AD-HOC: If box has preferred aspect ratio but width and height are not specified, then we should // size it as a normal box to match other browsers. - if (box.computed_values().height().is_auto() - && box.computed_values().width().is_auto() + if (should_treat_width_as_auto(box, available_space) + && should_treat_height_as_auto(box, available_space) && !box.has_natural_width() && !box.has_natural_height()) { return false; diff --git a/Libraries/LibWeb/Layout/FormattingContext.h b/Libraries/LibWeb/Layout/FormattingContext.h index 2e10b64d66e..e7188b4f7dd 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Libraries/LibWeb/Layout/FormattingContext.h @@ -107,6 +107,8 @@ protected: [[nodiscard]] bool should_treat_max_width_as_none(Box const&, AvailableSize const&) const; [[nodiscard]] bool should_treat_max_height_as_none(Box const&, AvailableSize const&) const; + [[nodiscard]] bool box_is_sized_as_replaced_element(Box const&, AvailableSpace const&) const; + OwnPtr layout_inside(Box const&, LayoutMode, AvailableSpace const&); struct SpaceUsedByFloats { @@ -165,6 +167,4 @@ protected: LayoutState& m_state; }; -bool box_is_sized_as_replaced_element(Box const&); - } diff --git a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index 93f43feabbf..00eca44b53f 100644 --- a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -119,7 +119,7 @@ void InlineFormattingContext::dimension_box_on_line(Box const& box, LayoutMode l box_state.border_bottom = computed_values.border_bottom().width; box_state.margin_bottom = computed_values.margin().bottom().to_px(box, width_of_containing_block); - if (box_is_sized_as_replaced_element(box)) { + if (box_is_sized_as_replaced_element(box, *m_available_space)) { box_state.set_content_width(compute_width_for_replaced_element(box, *m_available_space)); box_state.set_content_height(compute_height_for_replaced_element(box, *m_available_space)); auto independent_formatting_context = layout_inside(box, layout_mode, box_state.available_inner_space_or_constraints_from(*m_available_space)); diff --git a/Tests/LibWeb/Layout/expected/flex/aspect-ratio-and-cyclic-percentages-row.txt b/Tests/LibWeb/Layout/expected/flex/aspect-ratio-and-cyclic-percentages-row.txt new file mode 100644 index 00000000000..bac9aa84856 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/flex/aspect-ratio-and-cyclic-percentages-row.txt @@ -0,0 +1,24 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x216 [BFC] children: not-inline + Box at (8,8) content-size 300x200 flex-container(row) [FFC] children: not-inline + BlockContainer
at (8,8) content-size 27.640625x200 flex-item [BFC] children: not-inline + BlockContainer
at (8,8) content-size 27.640625x27.640625 children: inline + frag 0 from TextNode start: 0, length: 3, rect: [8,8 27.15625x18] baseline: 13.796875 + "foo" + TextNode <#text> + BlockContainer
at (8,35.640625) content-size 27.640625x27.640625 children: inline + frag 0 from TextNode start: 0, length: 3, rect: [8,35.640625 27.640625x18] baseline: 13.796875 + "bar" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x216] + PaintableBox (Box) [8,8 300x200] + PaintableWithLines (BlockContainer
) [8,8 27.640625x200] + PaintableWithLines (BlockContainer
) [8,8 27.640625x27.640625] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
) [8,35.640625 27.640625x27.640625] + TextPaintable (TextNode<#text>) + +SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto) + SC for BlockContainer [0,0 800x216] [children: 0] (z-index: auto) diff --git a/Tests/LibWeb/Layout/input/flex/aspect-ratio-and-cyclic-percentages-row.html b/Tests/LibWeb/Layout/input/flex/aspect-ratio-and-cyclic-percentages-row.html new file mode 100644 index 00000000000..f4d4a9e9f5d --- /dev/null +++ b/Tests/LibWeb/Layout/input/flex/aspect-ratio-and-cyclic-percentages-row.html @@ -0,0 +1,16 @@ +
foo
bar