implement new negative flexing algorithm
authortony@chromium.org <tony@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 May 2012 02:07:18 +0000 (02:07 +0000)
committertony@chromium.org <tony@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 May 2012 02:07:18 +0000 (02:07 +0000)
https://bugs.webkit.org/show_bug.cgi?id=86528

Reviewed by Ojan Vafai.

Source/WebCore:

Rather than just scale by the negative flexibility, we also take the
flex-basis (preferred size) into consideration.  That means items with
a larger preferred size will shrink faster.

Test: css3/flexbox/flex-algorithm.html (new test cases added)

* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::preferredMainAxisContentExtentForChild): Handle overflow.
(WebCore::RenderFlexibleBox::layoutFlexItems):
(WebCore::RenderFlexibleBox::computeNextFlexLine): Sum weighted negative flex.
(WebCore::RenderFlexibleBox::freezeViolations):
(WebCore::RenderFlexibleBox::resolveFlexibleLengths): Shrink by weighted amount.
Also handle large values by making sure the flex values are finite.
* rendering/RenderFlexibleBox.h:

LayoutTests:

* css3/flexbox/flex-algorithm-expected.txt:
* css3/flexbox/flex-algorithm.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@118600 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/css3/flexbox/flex-algorithm-expected.txt
LayoutTests/css3/flexbox/flex-algorithm.html
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderFlexibleBox.cpp
Source/WebCore/rendering/RenderFlexibleBox.h

index f61dd5f..759aa5a 100644 (file)
@@ -1,3 +1,13 @@
+2012-05-25  Tony Chang  <tony@chromium.org>
+
+        implement new negative flexing algorithm
+        https://bugs.webkit.org/show_bug.cgi?id=86528
+
+        Reviewed by Ojan Vafai.
+
+        * css3/flexbox/flex-algorithm-expected.txt:
+        * css3/flexbox/flex-algorithm.html:
+
 2012-05-25  Mihai Parparita  <mihaip@chromium.org>
 
         Allow synchronous XHRs to be disabled in documents
index 6fffcd7..f99a414 100644 (file)
@@ -86,6 +86,39 @@ if (window.layoutTestController)
   <div data-expected-width="200" style="width: 200px"></div>
 </div>
 
+<div style="display: -webkit-flex" class="flexbox">
+  <div data-expected-width="50" style="-webkit-flex: 1 1 100px"></div>
+  <div data-expected-width="250" style="-webkit-flex: 1 1 500px"></div>
+  <div data-expected-width="300" style="width: 300px"></div>
+</div>
+
+<div style="display: -webkit-flex" class="flexbox">
+  <div data-expected-width="50" style="-webkit-flex: 1 1 100px"></div>
+  <div data-expected-width="250" style="-webkit-flex: 1 1 500px; margin-right: 300px;"></div>
+</div>
+
+<div style="display: -webkit-flex" class="flexbox">
+  <div data-expected-width="50" style="-webkit-flex: 1 1 100px"></div>
+  <div data-expected-width="550" style="-webkit-flex: 1 1 500px; padding-left: 300px;"></div>
+</div>
+
+<div style="display: -webkit-flex" class="flexbox">
+  <div data-expected-width="50" style="-webkit-flex: 1 1 100px"></div>
+  <div data-expected-width="550" style="-webkit-flex: 1 1 500px; border-left: 200px dashed orange; border-right: 100px dashed orange;"></div>
+</div>
+
+<!-- Test some overflow cases. -->
+<div style="display: -webkit-flex" class="flexbox">
+  <div data-expected-width="600" style="-webkit-flex: 0 100000000000000000000000000000000000000 600px"></div>
+  <div data-expected-width="600" style="-webkit-flex: 0 100000000000000000000000000000000000000 600px"></div>
+</div>
+
+<div style="display: -webkit-flex" class="flexbox">
+  <div data-expected-width="600" style="-webkit-flex: 100000000000000000000000000000000000000 0 600px"></div>
+  <div data-expected-width="600" style="-webkit-flex: 0 100000000000000000000000000000000000000 600px"></div>
+  <div data-expected-width="0" style="-webkit-flex: 1 1 100000000000000000000000000000000000000px"></div>
+</div>
+
 <!-- Test flexitem borders. -->
 <div style="display: -webkit-flex" class="flexbox">
   <div data-expected-width="250" style="-webkit-flex: 1; border-left: 150px solid black"></div>
index 61871f4..6a4eff5 100644 (file)
@@ -1,3 +1,25 @@
+2012-05-25  Tony Chang  <tony@chromium.org>
+
+        implement new negative flexing algorithm
+        https://bugs.webkit.org/show_bug.cgi?id=86528
+
+        Reviewed by Ojan Vafai.
+
+        Rather than just scale by the negative flexibility, we also take the
+        flex-basis (preferred size) into consideration.  That means items with
+        a larger preferred size will shrink faster.
+
+        Test: css3/flexbox/flex-algorithm.html (new test cases added)
+
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::preferredMainAxisContentExtentForChild): Handle overflow.
+        (WebCore::RenderFlexibleBox::layoutFlexItems):
+        (WebCore::RenderFlexibleBox::computeNextFlexLine): Sum weighted negative flex.
+        (WebCore::RenderFlexibleBox::freezeViolations):
+        (WebCore::RenderFlexibleBox::resolveFlexibleLengths): Shrink by weighted amount.
+        Also handle large values by making sure the flex values are finite.
+        * rendering/RenderFlexibleBox.h:
+
 2012-05-25  Mihai Parparita  <mihaip@chromium.org>
 
         Allow synchronous XHRs to be disabled in documents
index 2feab4f..8f0997b 100644 (file)
@@ -35,6 +35,7 @@
 #include "RenderLayer.h"
 #include "RenderView.h"
 #include <limits>
+#include <wtf/MathExtras.h>
 
 namespace WebCore {
 
@@ -593,7 +594,7 @@ LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox*
         LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth();
         return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
     }
-    return minimumValueForLength(mainAxisLength, mainAxisContentExtent(), view());
+    return std::max(LayoutUnit(0), minimumValueForLength(mainAxisLength, mainAxisContentExtent(), view()));
 }
 
 LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent)
@@ -624,17 +625,17 @@ void RenderFlexibleBox::layoutFlexItems(FlexOrderIterator& iterator, WTF::Vector
     OrderedFlexItemList orderedChildren;
     LayoutUnit preferredMainAxisExtent;
     float totalPositiveFlexibility;
-    float totalNegativeFlexibility;
+    float totalWeightedNegativeFlexibility;
     LayoutUnit minMaxAppliedMainAxisExtent;
 
     LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
-    while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalNegativeFlexibility, minMaxAppliedMainAxisExtent)) {
+    while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalWeightedNegativeFlexibility, minMaxAppliedMainAxisExtent)) {
         LayoutUnit availableFreeSpace = computeAvailableFreeSpace(preferredMainAxisExtent);
         FlexSign flexSign = (minMaxAppliedMainAxisExtent < preferredMainAxisExtent + availableFreeSpace) ? PositiveFlexibility : NegativeFlexibility;
         InflexibleFlexItemSize inflexibleItems;
         WTF::Vector<LayoutUnit> childSizes;
-        while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems, childSizes)) {
-            ASSERT(totalPositiveFlexibility >= 0 && totalNegativeFlexibility >= 0);
+        while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalWeightedNegativeFlexibility, inflexibleItems, childSizes)) {
+            ASSERT(totalPositiveFlexibility >= 0 && totalWeightedNegativeFlexibility >= 0);
             ASSERT(inflexibleItems.size() > 0);
         }
 
@@ -800,11 +801,11 @@ LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, Layo
     return childSize;
 }
 
-bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent)
+bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent)
 {
     orderedChildren.clear();
     preferredMainAxisExtent = 0;
-    totalPositiveFlexibility = totalNegativeFlexibility = 0;
+    totalPositiveFlexibility = totalWeightedNegativeFlexibility = 0;
     minMaxAppliedMainAxisExtent = 0;
 
     if (!iterator.currentChild())
@@ -828,7 +829,7 @@ bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, Ordered
         orderedChildren.append(child);
         preferredMainAxisExtent += childMainAxisMarginBoxExtent;
         totalPositiveFlexibility += child->style()->positiveFlex();
-        totalNegativeFlexibility += child->style()->negativeFlex();
+        totalWeightedNegativeFlexibility += child->style()->negativeFlex() * childMainAxisExtent;
 
         LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(child, childMainAxisExtent, flexboxAvailableContentExtent);
         minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent - childMainAxisExtent + childMainAxisMarginBoxExtent;
@@ -836,20 +837,21 @@ bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, Ordered
     return true;
 }
 
-void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
+void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
 {
     for (size_t i = 0; i < violations.size(); ++i) {
         RenderBox* child = violations[i].child;
         LayoutUnit childSize = violations[i].childSize;
-        availableFreeSpace -= childSize - preferredMainAxisContentExtentForChild(child);
+        LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child);
+        availableFreeSpace -= childSize - preferredChildSize;
         totalPositiveFlexibility -= child->style()->positiveFlex();
-        totalNegativeFlexibility -= child->style()->negativeFlex();
+        totalWeightedNegativeFlexibility -= child->style()->negativeFlex() * preferredChildSize;
         inflexibleItems.set(child, childSize);
     }
 }
 
 // Returns true if we successfully ran the algorithm and sized the flex items.
-bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes)
+bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes)
 {
     childSizes.clear();
     LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
@@ -869,10 +871,10 @@ bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF
         else {
             LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child);
             LayoutUnit childSize = preferredChildSize;
-            if (availableFreeSpace > 0 && totalPositiveFlexibility > 0 && flexSign == PositiveFlexibility)
+            if (availableFreeSpace > 0 && totalPositiveFlexibility > 0 && flexSign == PositiveFlexibility && isfinite(totalPositiveFlexibility))
                 childSize += lroundf(availableFreeSpace * child->style()->positiveFlex() / totalPositiveFlexibility);
-            else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0  && flexSign == NegativeFlexibility)
-                childSize += lroundf(availableFreeSpace * child->style()->negativeFlex() / totalNegativeFlexibility);
+            else if (availableFreeSpace < 0 && totalWeightedNegativeFlexibility > 0 && flexSign == NegativeFlexibility && isfinite(totalWeightedNegativeFlexibility))
+                childSize += lroundf(availableFreeSpace * child->style()->negativeFlex() * preferredChildSize / totalWeightedNegativeFlexibility);
 
             LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize, flexboxAvailableContentExtent);
             childSizes.append(adjustedChildSize);
@@ -888,7 +890,7 @@ bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF
     }
 
     if (totalViolation)
-        freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems);
+        freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalPositiveFlexibility, totalWeightedNegativeFlexibility, inflexibleItems);
     else
         availableFreeSpace -= usedFreeSpace;
 
index 8383a46..ae61d63 100644 (file)
@@ -113,11 +113,11 @@ private:
     void computeMainAxisPreferredSizes(bool relayoutChildren, FlexOrderHashSet&);
     LayoutUnit lineBreakLength();
     LayoutUnit adjustChildSizeForMinAndMax(RenderBox*, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent);
-    bool computeNextFlexLine(FlexOrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent);
+    bool computeNextFlexLine(FlexOrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent);
     LayoutUnit computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent);
 
-    bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
-    void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&);
+    bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
+    void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize&);
 
     void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize);
     void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset);