Explorar o código

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.
Andreas Kling %!s(int64=2) %!d(string=hai) anos
pai
achega
508927cae2

+ 6 - 0
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 <html> at (0,0) content-size 800x0 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 140x100 positioned [BFC] children: not-inline
+      BlockContainer <div.black> at (58,58) content-size 40x0 children: inline
+        BlockContainer <div.green> at (78,78) content-size 0x0 floating [BFC] children: not-inline
+        TextNode <#text>

+ 15 - 0
Tests/LibWeb/Layout/input/block-and-inline/automatic-size-of-block-container-with-inline-children-and-nonempty-floating-child.html

@@ -0,0 +1,15 @@
+<!doctype html><style>
+    * {
+    }
+    body {
+        position: absolute;
+    }
+    .black {
+        background: magenta;
+        border: 50px solid black;
+    }
+    .green {
+        float: left;
+        border: 20px solid lime;
+    }
+</style><body><div class="black"><div class="green"></div> 

+ 6 - 0
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());

+ 3 - 3
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;
 }