From 508927cae2edd890f3267da13a5d6e2642de80a9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 3 May 2023 17:14:15 +0200 Subject: [PATCH] LibWeb: Take floats into account when measuring automatic width of IFC When there are floats present inside an IFC, we must coordinate with the parent BFC to calculate the automatic width of the IFC's block box. This is because the IFC is not directly aware of floats. Only the BFC knows enough about them to account for them in automatic sizing. --- ...nline-children-and-nonempty-floating-child.txt | 6 ++++++ ...line-children-and-nonempty-floating-child.html | 15 +++++++++++++++ .../LibWeb/Layout/BlockFormattingContext.cpp | 6 ++++++ .../LibWeb/Layout/InlineFormattingContext.cpp | 6 +++--- 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.txt create mode 100644 Tests/LibWeb/Layout/input/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.html diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.txt b/Tests/LibWeb/Layout/expected/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.txt new file mode 100644 index 0000000000..0a4572b393 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.txt @@ -0,0 +1,6 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x0 [BFC] children: not-inline + BlockContainer at (8,8) content-size 140x100 positioned [BFC] children: not-inline + BlockContainer at (58,58) content-size 40x0 children: inline + BlockContainer at (78,78) content-size 0x0 floating [BFC] children: not-inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.html b/Tests/LibWeb/Layout/input/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.html new file mode 100644 index 0000000000..9d61d2c302 --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.html @@ -0,0 +1,15 @@ +
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index b4987315ed..d0f7fc58bf 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -985,6 +985,9 @@ CSSPixels BlockFormattingContext::greatest_child_width(Box const& box) const CSSPixels width_here = line_box.width(); CSSPixels extra_width_from_left_floats = 0; for (auto& left_float : m_left_floats.all_boxes) { + // NOTE: Floats directly affect the automatic size of their containing block, but only indirectly anything above in the tree. + if (left_float->box->containing_block() != &box) + continue; if (line_box.baseline() >= left_float->top_margin_edge.value() || line_box.baseline() <= left_float->bottom_margin_edge.value()) { auto const& left_float_state = m_state.get(left_float->box); extra_width_from_left_floats = max(extra_width_from_left_floats, left_float->offset_from_edge + left_float_state.content_width() + left_float_state.margin_box_right()); @@ -992,6 +995,9 @@ CSSPixels BlockFormattingContext::greatest_child_width(Box const& box) const } CSSPixels extra_width_from_right_floats = 0; for (auto& right_float : m_right_floats.all_boxes) { + // NOTE: Floats directly affect the automatic size of their containing block, but only indirectly anything above in the tree. + if (right_float->box->containing_block() != &box) + continue; if (line_box.baseline() >= right_float->top_margin_edge.value() || line_box.baseline() <= right_float->bottom_margin_edge.value()) { auto const& right_float_state = m_state.get(right_float->box); extra_width_from_right_floats = max(extra_width_from_right_floats, right_float->offset_from_edge + right_float_state.margin_box_left()); diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index 0490d4db8a..22730738fb 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -77,15 +77,15 @@ void InlineFormattingContext::run(Box const&, LayoutMode layout_mode, AvailableS m_available_space = available_space; generate_line_boxes(layout_mode); - CSSPixels max_line_width = 0; CSSPixels content_height = 0; for (auto& line_box : m_containing_block_state.line_boxes) { - max_line_width = max(max_line_width, line_box.width()); content_height += line_box.height(); } - m_automatic_content_width = max_line_width; + // NOTE: We ask the parent BFC to calculate the automatic content width of this IFC. + // This ensures that any floated boxes are taken into account. + m_automatic_content_width = parent().greatest_child_width(containing_block()); m_automatic_content_height = content_height; }