Title: [264281] trunk
Revision
264281
Author
[email protected]
Date
2020-07-12 11:08:08 -0700 (Sun, 12 Jul 2020)

Log Message

[LFC][BFC][Min-Max width] Regular block level box resets the horizontal stacking
https://bugs.webkit.org/show_bug.cgi?id=214225

Reviewed by Antti Koivisto.

Source/WebCore:

Non-floating block level boxes reset the current horizontal float stacking.
e.g. with a shrink-to-fit width container:
<div style="float: left; width: 10px;"></div>
<div></div>
<div style="float: left; width: 40px;"></div>
will produce a max width of 40px which makes the floats vertically stacked.

Test: fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple.html

* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::computedIntrinsicWidthConstraints):
* layout/blockformatting/BlockFormattingContextGeometry.cpp:
(WebCore::Layout::BlockFormattingContext::Geometry::intrinsicWidthConstraints):

LayoutTests:

* fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple-expected.html: Added.
* fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (264280 => 264281)


--- trunk/LayoutTests/ChangeLog	2020-07-12 17:28:02 UTC (rev 264280)
+++ trunk/LayoutTests/ChangeLog	2020-07-12 18:08:08 UTC (rev 264281)
@@ -1,3 +1,13 @@
+2020-07-12  Zalan Bujtas  <[email protected]>
+
+        [LFC][BFC][Min-Max width] Regular block level box resets the horizontal stacking
+        https://bugs.webkit.org/show_bug.cgi?id=214225
+
+        Reviewed by Antti Koivisto.
+
+        * fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple-expected.html: Added.
+        * fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple.html: Added.
+
 2020-07-11  Fujii Hironori  <[email protected]>
 
         [WinCairo] Conic gradients support

Added: trunk/LayoutTests/fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple-expected.html (0 => 264281)


--- trunk/LayoutTests/fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple-expected.html	2020-07-12 18:08:08 UTC (rev 264281)
@@ -0,0 +1,13 @@
+<!DOCTYPE html><!-- webkit-test-runner [ internal:LayoutFormattingContextEnabled=true internal:LayoutFormattingContextIntegrationEnabled=false ] -->
+<style>
+div {
+    background-color: green;
+}
+</style>
+<div style="width: 100px; height: 20px;"></div>
+<div style="width: 200px; height: 20px;"></div>
+<div style="width: 100px; height: 80px;"></div>
+<div style="width: 200px; height: 60px;"></div>
+<div style="width: 100px; height: 20px;"></div>
+<div style="width: 100px; height: 20px; background-color: black; position: relative; top: -20px; left: 100px;"></div>
+<div style="width: 100px; height: 60px; position: relative; top: -20px;"></div>

Added: trunk/LayoutTests/fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple.html (0 => 264281)


--- trunk/LayoutTests/fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple.html	                        (rev 0)
+++ trunk/LayoutTests/fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple.html	2020-07-12 18:08:08 UTC (rev 264281)
@@ -0,0 +1,84 @@
+<!DOCTYPE html><!-- webkit-test-runner [ internal:LayoutFormattingContextEnabled=true internal:LayoutFormattingContextIntegrationEnabled=false ] -->
+<style>
+.container { 
+  float: left;
+  background-color: black;
+}
+
+.child_floating {
+  float: left;
+  width: 100px;
+  height: 20px;
+  background-color: green;
+}
+
+.divider {
+  clear: both;
+}
+</style>
+<div class=container>
+  <div class=child_floating></div>
+</div>
+
+<div class=divider></div>
+
+<div class=container>
+  <div class=child_floating></div>
+  <div class=child_floating></div>
+</div>
+
+<div class=divider></div>
+
+<div class=container>
+  <div class=child_floating></div>
+  <div></div>
+  <div class=child_floating></div>
+</div>
+
+<div class=divider></div>
+
+<div class=container>
+  <div class=child_floating></div>
+  <div>
+    <div class=child_floating></div>
+  </div>
+</div>
+
+<div class=divider></div>
+
+<div class=container>
+  <div>
+    <div class=child_floating></div>
+    <div class=child_floating></div>
+  </div>
+</div>
+
+<div class=divider></div>
+
+<div class=container>
+  <div></div>
+  <div class=child_floating></div>
+  <div class=child_floating></div>
+</div>
+
+<div class=divider></div>
+
+<div class=container>
+  <div class=child_floating></div>
+  <div>
+    <div class=child_floating></div>
+    <div class=child_floating></div>
+  </div>
+</div>
+
+<div class=divider></div>
+
+<div class=container>
+  <div class=child_floating></div>
+  <div>
+    <div>
+      <div class=child_floating></div>
+    <div>
+    <div class=child_floating></div>
+  </div>
+</div>

Modified: trunk/Source/WebCore/ChangeLog (264280 => 264281)


--- trunk/Source/WebCore/ChangeLog	2020-07-12 17:28:02 UTC (rev 264280)
+++ trunk/Source/WebCore/ChangeLog	2020-07-12 18:08:08 UTC (rev 264281)
@@ -1,3 +1,24 @@
+2020-07-12  Zalan Bujtas  <[email protected]>
+
+        [LFC][BFC][Min-Max width] Regular block level box resets the horizontal stacking
+        https://bugs.webkit.org/show_bug.cgi?id=214225
+
+        Reviewed by Antti Koivisto.
+
+        Non-floating block level boxes reset the current horizontal float stacking.
+        e.g. with a shrink-to-fit width container:
+        <div style="float: left; width: 10px;"></div>
+        <div></div>
+        <div style="float: left; width: 40px;"></div>
+        will produce a max width of 40px which makes the floats vertically stacked.
+
+        Test: fast/layoutformattingcontext/min-max-content-width-with-nested-floats-simple.html
+
+        * layout/blockformatting/BlockFormattingContext.cpp:
+        (WebCore::Layout::BlockFormattingContext::computedIntrinsicWidthConstraints):
+        * layout/blockformatting/BlockFormattingContextGeometry.cpp:
+        (WebCore::Layout::BlockFormattingContext::Geometry::intrinsicWidthConstraints):
+
 2020-07-12  Darin Adler  <[email protected]>
 
         Simplify and improve Gradient, some other small color-related removals

Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp (264280 => 264281)


--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp	2020-07-12 17:28:02 UTC (rev 264280)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp	2020-07-12 18:08:08 UTC (rev 264281)
@@ -408,11 +408,25 @@
         queue.append(root().firstInFlowOrFloatingChild());
 
     IntrinsicWidthConstraints constraints;
-    auto floatAvoidersMaximumIntrinsicWidth = LayoutUnit { };
+    auto maximumHorizontalStackingWidth = LayoutUnit { };
+    auto currentHorizontalStackingWidth = LayoutUnit { };
     while (!queue.isEmpty()) {
         while (true) {
             // Check if we have to deal with descendant content.
             auto& layoutBox = *queue.last();
+            // Float avoiders are all establish a new formatting context. No need to look inside them.
+            if (layoutBox.isFloatAvoider() && !layoutBox.hasFloatClear())
+                break;
+            // Non-floating block level boxes reset the current horizontal float stacking.
+            // SPEC: This is a bit odd as floating positioning is a formatting context level concept:
+            // e.g.
+            // <div style="float: left; width: 10px;"></div>
+            // <div></div>
+            // <div style="float: left; width: 40px;"></div>
+            // ...will produce a max width of 40px which makes the floats vertically stacked.
+            // Vertically stacked floats makes me think we haven't managed to provide the maximum preferred width for the content.
+            maximumHorizontalStackingWidth = std::max(currentHorizontalStackingWidth, maximumHorizontalStackingWidth);
+            currentHorizontalStackingWidth = { };
             // Already has computed intrinsic constraints.
             if (formattingState.intrinsicWidthConstraintsForBox(layoutBox))
                 break;
@@ -419,9 +433,6 @@
             // Box with fixed width defines their descendant content intrinsic width.
             if (layoutBox.style().width().isFixed())
                 break;
-            // Float avoiders are all establish a new formatting context. No need to look inside them.
-            if (layoutBox.isFloatAvoider())
-                break;
             // Non-float avoider formatting context roots are opaque to intrinsic width computation.
             if (layoutBox.establishesFormattingContext())
                 break;
@@ -439,13 +450,10 @@
                 formattingState.setIntrinsicWidthConstraintsForBox(layoutBox, *desdendantConstraints);
             }
             constraints.minimum = std::max(constraints.minimum, desdendantConstraints->minimum);
-            // FIXME: This works as long as the float avoider is a direct child of the root.
-            // When the containing block of the float avoider is not the root, the containing block itself sets the constraint.
-            if (layoutBox.isFloatAvoider()) {
-                // Floats and formatting context roots that avoid floats form a horizontal stack when the constraint is infinite.
-                // FIXME: Add support for clear property.
-                floatAvoidersMaximumIntrinsicWidth += desdendantConstraints->maximum;
-            } else
+            auto willStackHorizontally = layoutBox.isFloatAvoider() && !layoutBox.hasFloatClear();
+            if (willStackHorizontally)
+                currentHorizontalStackingWidth += desdendantConstraints->maximum;
+            else
                 constraints.maximum = std::max(constraints.maximum, desdendantConstraints->maximum);
             // Move over to the next sibling or take the next box in the queue.
             if (auto* nextSibling = layoutBox.nextInFlowOrFloatingSibling()) {
@@ -454,7 +462,8 @@
             }
         }
     }
-    constraints.maximum = std::max(constraints.maximum, floatAvoidersMaximumIntrinsicWidth);
+    maximumHorizontalStackingWidth = std::max(currentHorizontalStackingWidth, maximumHorizontalStackingWidth);
+    constraints.maximum = std::max(constraints.maximum, maximumHorizontalStackingWidth);
     formattingState.setIntrinsicWidthConstraints(constraints);
     return constraints;
 }

Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp (264280 => 264281)


--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp	2020-07-12 17:28:02 UTC (rev 264280)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp	2020-07-12 18:08:08 UTC (rev 264281)
@@ -372,7 +372,7 @@
         auto intrinsicWidthConstraints = IntrinsicWidthConstraints { };
         auto& formattingState = layoutState().formattingStateForBox(layoutBox);
         for (auto& child : childrenOfType<Box>(downcast<ContainerBox>(layoutBox))) {
-            if (child.isOutOfFlowPositioned() || child.isFloatAvoider())
+            if (child.isOutOfFlowPositioned() || (child.isFloatAvoider() && !child.hasFloatClear()))
                 continue;
             auto childIntrinsicWidthConstraints = formattingState.intrinsicWidthConstraintsForBox(child);
             ASSERT(childIntrinsicWidthConstraints);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to