Modified: trunk/LayoutTests/ChangeLog (93650 => 93651)
--- trunk/LayoutTests/ChangeLog 2011-08-23 23:08:31 UTC (rev 93650)
+++ trunk/LayoutTests/ChangeLog 2011-08-23 23:10:45 UTC (rev 93651)
@@ -1,3 +1,13 @@
+2011-08-23 Tony Chang <[email protected]>
+
+ Add handling of mix-width and max-width for flexitems
+ https://bugs.webkit.org/show_bug.cgi?id=66723
+
+ Reviewed by David Hyatt.
+
+ * css3/flexbox/003-expected.txt: Added.
+ * css3/flexbox/003.html: Added.
+
2011-08-23 Adam Barth <[email protected]>
Update expectations for pkasting. The rebaseline script is having
Added: trunk/LayoutTests/css3/flexbox/003-expected.txt (0 => 93651)
--- trunk/LayoutTests/css3/flexbox/003-expected.txt (rev 0)
+++ trunk/LayoutTests/css3/flexbox/003-expected.txt 2011-08-23 23:10:45 UTC (rev 93651)
@@ -0,0 +1,8 @@
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
Added: trunk/LayoutTests/css3/flexbox/003.html (0 => 93651)
--- trunk/LayoutTests/css3/flexbox/003.html (rev 0)
+++ trunk/LayoutTests/css3/flexbox/003.html 2011-08-23 23:10:45 UTC (rev 93651)
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+ margin: 0;
+}
+.horizontal-box {
+ width: 600px;
+ display: -webkit-flexbox;
+ background-color: #aaa;
+ position: relative;
+}
+.horizontal-box div {
+ height: 20px;
+ border: 0;
+}
+
+.horizontal-box :nth-child(1) {
+ background-color: blue;
+}
+.horizontal-box :nth-child(2) {
+ background-color: green;
+}
+.horizontal-box :nth-child(3) {
+ background-color: red;
+}
+</style>
+<script>
+if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+</script>
+<script src=""
+<body _onload_="checkHorizontalBoxen()">
+<div class="horizontal-box">
+ <div data-expected-width="100" style="width: -webkit-flex(1 0 0); max-width: 100px;"></div>
+ <div data-expected-width="250" style="width: -webkit-flex(1 0 0);"></div>
+ <div data-expected-width="250" style="width: -webkit-flex(1 0 0);"></div>
+</div>
+
+<!-- The first two flexitems should hit their max width and the third item fills the remaining space. -->
+<div class="horizontal-box">
+ <div data-expected-width="50" style="width: -webkit-flex(1 0 0); max-width: 50px;"></div>
+ <div data-expected-width="300" style="width: -webkit-flex(4 0 0); max-width: 300px;"></div>
+ <div data-expected-width="250" style="width: -webkit-flex(1 0 0);"></div>
+</div>
+
+<div class="horizontal-box">
+ <div data-expected-width="100" style="width: -webkit-flex(1 0 0); max-width: 100px;"></div>
+ <div data-expected-width="300" style="width: -webkit-flex(1 0 200px); max-width: 300px;"></div>
+ <div data-expected-width="200" style="width: -webkit-flex(1 0 0);"></div>
+</div>
+
+<!-- Test min-width. -->
+<div class="horizontal-box">
+ <div data-expected-width="350" style="width: -webkit-flex(1 1 400px); min-width: 350px;"></div>
+ <div data-expected-width="250" style="width: -webkit-flex(1 1 400px);"></div>
+</div>
+
+<!-- The flex items can overflow the flexbox. -->
+<div class="horizontal-box">
+ <div data-expected-width="350" style="width: -webkit-flex(1 1 400px); min-width: 350px;"></div>
+ <div data-expected-width="300" style="width: -webkit-flex(2 0 300px); max-width: 300px;"></div>
+ <div data-expected-width="0" style="width: -webkit-flex(1 0 0);"></div>
+</div>
+
+<div class="horizontal-box">
+ <div data-expected-width="100" data-offset-x="100" style="width: -webkit-flex(1 0 0); margin: 0 auto; max-width: 100px;"></div>
+ <div data-expected-width="200" data-offset-x="300" style="width: -webkit-flex(2 0 0);"></div>
+ <div data-expected-width="100" data-offset-x="500" style="width: -webkit-flex(1 0 0);"></div>
+</div>
+
+<!-- min-width and max-width take priority over the preferred size. -->
+<div class="horizontal-box">
+ <div data-expected-width="500" style="width: -webkit-flex(1 0 0); min-width: 300px"></div>
+ <div data-expected-width="100" style="width: -webkit-flex(1 0 50%); max-width: 100px"></div>
+</div>
+
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (93650 => 93651)
--- trunk/Source/WebCore/ChangeLog 2011-08-23 23:08:31 UTC (rev 93650)
+++ trunk/Source/WebCore/ChangeLog 2011-08-23 23:10:45 UTC (rev 93651)
@@ -1,3 +1,24 @@
+2011-08-23 Tony Chang <[email protected]>
+
+ Add handling of mix-width and max-width for flexitems
+ https://bugs.webkit.org/show_bug.cgi?id=66723
+
+ Reviewed by David Hyatt.
+
+ If we flex past a min/max width value, we need to mark the flexitem as
+ a fixed width and re-start the flexing algorithm. We use a HashMap to
+ keep track of fixed width items.
+
+ This patch also split out the size computation from the actual layout
+ to avoid unnecessary layouts caused by restarting the flexing algorithm.
+
+ Test: css3/flexbox/003.html
+
+ * rendering/RenderFlexibleBox.cpp:
+ (WebCore::RenderFlexibleBox::layoutHorizontalBlock):
+ (WebCore::RenderFlexibleBox::runFreeSpaceAllocationAlgorithm):
+ * rendering/RenderFlexibleBox.h:
+
2011-08-23 Pratik Solanki <[email protected]>
ResourceRequest::setStorageSession should update NSURLRequest as well
Modified: trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp (93650 => 93651)
--- trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp 2011-08-23 23:08:31 UTC (rev 93650)
+++ trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp 2011-08-23 23:10:45 UTC (rev 93651)
@@ -99,7 +99,7 @@
m_overflow.clear();
- // FIXME: Assume horizontal layout until flex-direction is added.
+ // FIXME: Assume horizontal layout until flex-flow is added.
layoutHorizontalBlock(relayoutChildren);
computeLogicalHeight();
@@ -116,6 +116,7 @@
static LayoutUnit preferredFlexItemContentWidth(RenderBox* child)
{
+ // FIXME: Handle vertical writing modes with horizontal flexing.
if (child->style()->width().isAuto())
return child->maxPreferredLogicalWidth() - child->borderLeft() - child->borderRight() - child->verticalScrollbarWidth() - child->paddingLeft() - child->paddingRight();
return child->contentWidth();
@@ -128,34 +129,13 @@
float totalNegativeFlexibility;
FlexibleBoxIterator iterator(this);
- computePreferredSize(relayoutChildren, iterator, preferredSize, totalPositiveFlexibility, totalNegativeFlexibility);
+ computePreferredSizeHorizontal(relayoutChildren, iterator, preferredSize, totalPositiveFlexibility, totalNegativeFlexibility);
LayoutUnit availableFreeSpace = contentWidth() - preferredSize;
- LayoutUnit xOffset = borderLeft() + paddingLeft();
- LayoutUnit yOffset = borderTop() + paddingTop();
- for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
- LayoutUnit childPreferredSize = preferredFlexItemContentWidth(child);
- // FIXME: Handle max-width and min-width (we should clamp to the max/min value and restart the algorithm).
- if (availableFreeSpace > 0 && totalPositiveFlexibility > 0)
- childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthPositiveFlex() / totalPositiveFlexibility);
- else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0)
- childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthNegativeFlex() / totalNegativeFlexibility);
-
- childPreferredSize += child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight();
- child->setOverrideSize(LayoutSize(childPreferredSize, 0));
- child->setChildNeedsLayout(true);
- child->layoutIfNeeded();
-
- setHeight(std::max(height(), borderTop() + paddingTop() + child->marginTop() + child->height() + child->marginBottom() + paddingBottom() + borderBottom() + horizontalScrollbarHeight()));
-
- if (child->style()->marginLeft().isAuto())
- child->setMarginLeft(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
- if (child->style()->marginRight().isAuto())
- child->setMarginRight(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
-
- xOffset += child->marginLeft();
- child->setLocation(IntPoint(xOffset, yOffset));
- xOffset += child->width() + child->marginRight();
+ InflexibleFlexItemSize inflexibleItems;
+ while (!runFreeSpaceAllocationAlgorithmHorizontal(availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems)) {
+ ASSERT(totalPositiveFlexibility >= 0 && totalNegativeFlexibility >= 0);
+ ASSERT(inflexibleItems.size() > 0);
}
// FIXME: Distribute leftover space to the packing space (second distribution round).
@@ -167,11 +147,12 @@
return length.calcMinValue(containerLength);
}
-void RenderFlexibleBox::computePreferredSize(bool relayoutChildren, FlexibleBoxIterator& iterator, LayoutUnit& preferredSize, float& totalPositiveFlexibility, float& totalNegativeFlexibility)
+void RenderFlexibleBox::computePreferredSizeHorizontal(bool relayoutChildren, FlexibleBoxIterator& iterator, LayoutUnit& preferredSize, float& totalPositiveFlexibility, float& totalNegativeFlexibility)
{
preferredSize = 0;
totalPositiveFlexibility = totalNegativeFlexibility = 0;
+ // FIXME: Handle vertical writing modes with horizontal flexing.
LayoutUnit flexboxAvailableLogicalWidth = availableLogicalWidth();
for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
// We always have to lay out flexible objects again, since the flex distribution
@@ -200,6 +181,76 @@
}
}
+// Returns true if we successfully ran the algorithm and sized the flex items.
+bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithmHorizontal(LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
+{
+ FlexibleBoxIterator iterator(this);
+
+ // FIXME: Handle vertical writing modes with horizontal flexing.
+ LayoutUnit flexboxAvailableLogicalWidth = availableLogicalWidth();
+ WTF::Vector<LayoutUnit> childSizes;
+ for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+ LayoutUnit childPreferredSize;
+ if (inflexibleItems.contains(child))
+ childPreferredSize = inflexibleItems.get(child);
+ else {
+ childPreferredSize = preferredFlexItemContentWidth(child);
+ if (availableFreeSpace > 0 && totalPositiveFlexibility > 0) {
+ childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthPositiveFlex() / totalPositiveFlexibility);
+
+ Length childMaxWidth = child->style()->maxWidth();
+ if (!childMaxWidth.isUndefined() && childMaxWidth.isSpecified() && childPreferredSize > childMaxWidth.calcValue(flexboxAvailableLogicalWidth)) {
+ childPreferredSize = childMaxWidth.calcValue(flexboxAvailableLogicalWidth);
+ availableFreeSpace -= childPreferredSize - preferredFlexItemContentWidth(child);
+ totalPositiveFlexibility -= child->style()->flexboxWidthPositiveFlex();
+
+ inflexibleItems.set(child, childPreferredSize);
+ return false;
+ }
+ } else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0) {
+ childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthNegativeFlex() / totalNegativeFlexibility);
+
+ Length childMinWidth = child->style()->minWidth();
+ if (!childMinWidth.isUndefined() && childMinWidth.isSpecified() && childPreferredSize < childMinWidth.calcValue(flexboxAvailableLogicalWidth)) {
+ childPreferredSize = childMinWidth.calcValue(flexboxAvailableLogicalWidth);
+ availableFreeSpace += preferredFlexItemContentWidth(child) - childPreferredSize;
+ totalNegativeFlexibility -= child->style()->flexboxWidthNegativeFlex();
+
+ inflexibleItems.set(child, childPreferredSize);
+ return false;
+ }
+ }
+ }
+ childSizes.append(childPreferredSize);
+ }
+
+ // Now that we know the sizes, layout and position the flex items.
+ LayoutUnit xOffset = borderLeft() + paddingLeft();
+ LayoutUnit yOffset = borderTop() + paddingTop();
+ setHeight(0);
+ size_t i = 0;
+ for (RenderBox* child = iterator.first(); child; child = iterator.next(), ++i) {
+ LayoutUnit childPreferredSize = childSizes[i];
+ childPreferredSize += child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight();
+ // FIXME: Handle vertical writing modes with horizontal flexing.
+ child->setOverrideSize(LayoutSize(childPreferredSize, 0));
+ child->setChildNeedsLayout(true);
+ child->layoutIfNeeded();
+
+ setHeight(std::max(height(), borderTop() + paddingTop() + child->marginTop() + child->height() + child->marginBottom() + paddingBottom() + borderBottom() + horizontalScrollbarHeight()));
+
+ if (child->style()->marginLeft().isAuto())
+ child->setMarginLeft(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
+ if (child->style()->marginRight().isAuto())
+ child->setMarginRight(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
+
+ xOffset += child->marginLeft();
+ child->setLocation(IntPoint(xOffset, yOffset));
+ xOffset += child->width() + child->marginRight();
+ }
+ return true;
}
+}
+
#endif // ENABLE(CSS3_FLEXBOX)
Modified: trunk/Source/WebCore/rendering/RenderFlexibleBox.h (93650 => 93651)
--- trunk/Source/WebCore/rendering/RenderFlexibleBox.h 2011-08-23 23:08:31 UTC (rev 93650)
+++ trunk/Source/WebCore/rendering/RenderFlexibleBox.h 2011-08-23 23:10:45 UTC (rev 93651)
@@ -50,10 +50,12 @@
private:
class FlexibleBoxIterator;
+ typedef WTF::HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize;
void layoutHorizontalBlock(bool relayoutChildren);
- void computePreferredSize(bool relayoutChildren, FlexibleBoxIterator&, LayoutUnit&, float& totalPositiveFlexibility, float& totalNegativeFlexibility);
+ void computePreferredSizeHorizontal(bool relayoutChildren, FlexibleBoxIterator&, LayoutUnit&, float& totalPositiveFlexibility, float& totalNegativeFlexibility);
+ bool runFreeSpaceAllocationAlgorithmHorizontal(LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&);
};
} // namespace WebCore