Index: third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp |
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp |
index b9cf76806427f4aea07b6d3ca533ef3d4c64246f..35edf78c73e0a3c300e537013f25b3c0ddd68e70 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp |
@@ -62,20 +62,30 @@ struct LayoutFlexibleBox::LineContext { |
LayoutUnit maxAscent; |
}; |
-struct LayoutFlexibleBox::Violation { |
- Violation(LayoutBox* child, LayoutUnit childSize, LayoutUnit childInnerFlexBaseSize) |
- : child(child) |
- , childSize(childSize) |
- , childInnerFlexBaseSize(childInnerFlexBaseSize) |
+struct LayoutFlexibleBox::FlexItem { |
+ FlexItem(LayoutBox* box, LayoutUnit innerFlexBaseSize, LayoutUnit hypotheticalMainSize) |
+ : box(box) |
+ , innerFlexBaseSize(innerFlexBaseSize) |
+ , hypotheticalMainSize(hypotheticalMainSize) |
+ , frozen(false) |
{ |
} |
- LayoutBox* child; |
- LayoutUnit childSize; |
- LayoutUnit childInnerFlexBaseSize; |
+ // This constructor is used for out-of-flow children |
+ explicit FlexItem(LayoutBox* box) |
+ : box(box) |
+ , innerFlexBaseSize() |
+ , hypotheticalMainSize() |
+ , frozen(true) |
+ { |
+ } |
+ LayoutBox* box; |
+ const LayoutUnit innerFlexBaseSize; |
+ const LayoutUnit hypotheticalMainSize; |
+ LayoutUnit flexedContentSize; |
+ bool frozen; |
}; |
- |
LayoutFlexibleBox::LayoutFlexibleBox(Element* element) |
: LayoutBlock(element) |
, m_orderIterator(this) |
@@ -848,8 +858,6 @@ void LayoutFlexibleBox::layoutFlexItems(bool relayoutChildren, SubtreeLayoutScop |
double totalWeightedFlexShrink; |
LayoutUnit sumHypotheticalMainSize; |
- Vector<LayoutUnit, 16> childSizes; |
- |
PaintLayerScrollableArea::PreventRelayoutScope preventRelayoutScope(layoutScope); |
dirtyForLayoutFromPercentageHeightDescendants(layoutScope); |
@@ -864,24 +872,21 @@ void LayoutFlexibleBox::layoutFlexItems(bool relayoutChildren, SubtreeLayoutScop |
const LayoutUnit availableFreeSpace = containerMainInnerSize - sumFlexBaseSize; |
LayoutUnit remainingFreeSpace = availableFreeSpace; |
FlexSign flexSign = (sumHypotheticalMainSize < containerMainInnerSize) ? PositiveFlexibility : NegativeFlexibility; |
- InflexibleFlexItemSize inflexibleItems; |
- childSizes.reserveCapacity(orderedChildren.size()); |
- while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, remainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, inflexibleItems, childSizes)) { |
+ while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, remainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink)) { |
ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0); |
- ASSERT(inflexibleItems.size() > 0); |
} |
// Recalculate the remaining free space. The adjustment for flex factors between 0..1 means we can't just |
// use remainingFreeSpace here. |
remainingFreeSpace = containerMainInnerSize; |
for (size_t i = 0; i < orderedChildren.size(); ++i) { |
- LayoutBox* child = orderedChildren[i]; |
+ LayoutBox* child = orderedChildren[i].box; |
if (child->isOutOfFlowPositioned()) |
continue; |
- remainingFreeSpace -= (childSizes[i] + mainAxisBorderAndPaddingExtentForChild(*child) |
+ remainingFreeSpace -= (orderedChildren[i].flexedContentSize + mainAxisBorderAndPaddingExtentForChild(*child) |
+ (isHorizontalFlow() ? child->marginWidth() : child->marginHeight())); |
} |
- layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, remainingFreeSpace, relayoutChildren, layoutScope, lineContexts); |
+ layoutAndPlaceChildren(crossAxisOffset, orderedChildren, remainingFreeSpace, relayoutChildren, layoutScope, lineContexts); |
} |
if (hasLineIfEmpty()) { |
// Even if computeNextFlexLine returns true, the flexbox might not have |
@@ -905,7 +910,7 @@ LayoutUnit LayoutFlexibleBox::autoMarginOffsetInMainAxis(const OrderedFlexItemLi |
int numberOfAutoMargins = 0; |
bool isHorizontal = isHorizontalFlow(); |
for (size_t i = 0; i < children.size(); ++i) { |
- LayoutBox* child = children[i]; |
+ LayoutBox* child = children[i].box; |
if (child->isOutOfFlowPositioned()) |
continue; |
if (isHorizontal) { |
@@ -1191,7 +1196,7 @@ bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren |
for (LayoutBox* child = m_orderIterator.currentChild(); child; child = m_orderIterator.next()) { |
if (child->isOutOfFlowPositioned()) { |
- orderedChildren.append(child); |
+ orderedChildren.append(FlexItem(child)); |
continue; |
} |
@@ -1214,7 +1219,7 @@ bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren |
if (isMultiline() && sumHypotheticalMainSize + childHypotheticalMainSize > lineBreakLength && lineHasInFlowItem) |
break; |
- orderedChildren.append(child); |
+ orderedChildren.append(FlexItem(child, childInnerFlexBaseSize, childMinMaxAppliedMainAxisExtent)); |
lineHasInFlowItem = true; |
sumFlexBaseSize += childOuterFlexBaseSize; |
totalFlexGrow += child->style()->flexGrow(); |
@@ -1225,31 +1230,30 @@ bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren |
return true; |
} |
-void LayoutFlexibleBox::freezeViolations(const Vector<Violation>& violations, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems) |
+void LayoutFlexibleBox::freezeViolations(Vector<FlexItem*>& violations, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink) |
{ |
for (size_t i = 0; i < violations.size(); ++i) { |
- LayoutBox* child = violations[i].child; |
- LayoutUnit childSize = violations[i].childSize; |
- availableFreeSpace -= childSize - violations[i].childInnerFlexBaseSize; |
+ LayoutBox* child = violations[i]->box; |
+ LayoutUnit childSize = violations[i]->flexedContentSize; |
+ availableFreeSpace -= childSize - violations[i]->innerFlexBaseSize; |
totalFlexGrow -= child->style()->flexGrow(); |
totalFlexShrink -= child->style()->flexShrink(); |
- totalWeightedFlexShrink -= child->style()->flexShrink() * violations[i].childInnerFlexBaseSize; |
+ totalWeightedFlexShrink -= child->style()->flexShrink() * violations[i]->innerFlexBaseSize; |
// totalWeightedFlexShrink can be negative when we exceed the precision of a double when we initially |
// calcuate totalWeightedFlexShrink. We then subtract each child's weighted flex shrink with full precision, |
// now leading to a negative result. See css3/flexbox/large-flex-shrink-assert.html |
totalWeightedFlexShrink = std::max(totalWeightedFlexShrink, 0.0); |
- inflexibleItems.set(child, childSize); |
+ violations[i]->frozen = true; |
} |
} |
// Returns true if we successfully ran the algorithm and sized the flex items. |
-bool LayoutFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit availableFreeSpace, LayoutUnit& remainingFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit, 16>& childSizes) |
+bool LayoutFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, OrderedFlexItemList& children, LayoutUnit availableFreeSpace, LayoutUnit& remainingFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink) |
{ |
- childSizes.resize(0); |
LayoutUnit totalViolation; |
LayoutUnit usedFreeSpace; |
- Vector<Violation> minViolations; |
- Vector<Violation> maxViolations; |
+ Vector<FlexItem*> minViolations; |
+ Vector<FlexItem*> maxViolations; |
double sumFlexFactors = (flexSign == PositiveFlexibility) ? totalFlexGrow : totalFlexShrink; |
if (sumFlexFactors > 0 && sumFlexFactors < 1) { |
@@ -1259,42 +1263,39 @@ bool LayoutFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF |
} |
for (size_t i = 0; i < children.size(); ++i) { |
- LayoutBox* child = children[i]; |
+ FlexItem& flexItem = children[i]; |
+ LayoutBox* child = flexItem.box; |
if (child->isOutOfFlowPositioned()) { |
- childSizes.append(0); |
continue; |
} |
- if (inflexibleItems.contains(child)) { |
- childSizes.append(inflexibleItems.get(child)); |
- } else { |
- LayoutUnit childInnerFlexBaseSize = computeInnerFlexBaseSizeForChild(*child); |
- LayoutUnit childSize = childInnerFlexBaseSize; |
- double extraSpace = 0; |
- if (remainingFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow)) { |
- extraSpace = remainingFreeSpace * child->style()->flexGrow() / totalFlexGrow; |
- } else if (remainingFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink) && child->style()->flexShrink()) { |
- extraSpace = remainingFreeSpace * child->style()->flexShrink() * childInnerFlexBaseSize / totalWeightedFlexShrink; |
- } |
- if (std::isfinite(extraSpace)) |
- childSize += LayoutUnit::fromFloatRound(extraSpace); |
- |
- LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(*child, childSize); |
- ASSERT(adjustedChildSize >= 0); |
- childSizes.append(adjustedChildSize); |
- usedFreeSpace += adjustedChildSize - childInnerFlexBaseSize; |
- |
- LayoutUnit violation = adjustedChildSize - childSize; |
- if (violation > 0) |
- minViolations.append(Violation(child, adjustedChildSize, childInnerFlexBaseSize)); |
- else if (violation < 0) |
- maxViolations.append(Violation(child, adjustedChildSize, childInnerFlexBaseSize)); |
- totalViolation += violation; |
+ if (flexItem.frozen) |
+ continue; |
+ LayoutUnit childSize = flexItem.innerFlexBaseSize; |
+ double extraSpace = 0; |
+ if (remainingFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow)) { |
+ extraSpace = remainingFreeSpace * child->style()->flexGrow() / totalFlexGrow; |
+ } else if (remainingFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink) && child->style()->flexShrink()) { |
+ extraSpace = remainingFreeSpace * child->style()->flexShrink() * flexItem.innerFlexBaseSize / totalWeightedFlexShrink; |
} |
+ if (std::isfinite(extraSpace)) |
+ childSize += LayoutUnit::fromFloatRound(extraSpace); |
+ |
+ LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(*child, childSize); |
+ DCHECK_GE(adjustedChildSize, 0); |
+ flexItem.flexedContentSize = adjustedChildSize; |
+ usedFreeSpace += adjustedChildSize - flexItem.innerFlexBaseSize; |
+ |
+ LayoutUnit violation = adjustedChildSize - childSize; |
+ if (violation > 0) |
+ minViolations.append(&flexItem); |
+ else if (violation < 0) |
+ maxViolations.append(&flexItem); |
+ totalViolation += violation; |
} |
if (totalViolation) |
- freezeViolations(totalViolation < 0 ? maxViolations : minViolations, remainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, inflexibleItems); |
+ freezeViolations(totalViolation < 0 ? maxViolations : minViolations, remainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink); |
else |
remainingFreeSpace -= usedFreeSpace; |
@@ -1469,7 +1470,7 @@ size_t LayoutFlexibleBox::numberOfInFlowPositionedChildren(const OrderedFlexItem |
{ |
size_t count = 0; |
for (size_t i = 0; i < children.size(); ++i) { |
- LayoutBox* child = children[i]; |
+ LayoutBox* child = children[i].box; |
if (!child->isOutOfFlowPositioned()) |
++count; |
} |
@@ -1539,10 +1540,8 @@ EOverflow LayoutFlexibleBox::crossAxisOverflowForChild(const LayoutBox& child) c |
return child.styleRef().overflowX(); |
} |
-void LayoutFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const Vector<LayoutUnit, 16>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, SubtreeLayoutScope& layoutScope, Vector<LineContext>& lineContexts) |
+void LayoutFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, LayoutUnit availableFreeSpace, bool relayoutChildren, SubtreeLayoutScope& layoutScope, Vector<LineContext>& lineContexts) |
{ |
- ASSERT(childSizes.size() == children.size()); |
- |
ContentPosition position = styleRef().resolvedJustifyContentPosition(normalValueBehavior()); |
ContentDistributionType distribution = styleRef().resolvedJustifyContentDistribution(normalValueBehavior()); |
@@ -1561,7 +1560,8 @@ void LayoutFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons |
size_t seenInFlowPositionedChildren = 0; |
bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow(); |
for (size_t i = 0; i < children.size(); ++i) { |
- LayoutBox* child = children[i]; |
+ const FlexItem& flexItem = children[i]; |
+ LayoutBox* child = flexItem.box; |
if (child->isOutOfFlowPositioned()) { |
prepareChildForPositionedLayout(*child); |
@@ -1570,7 +1570,7 @@ void LayoutFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons |
child->setMayNeedPaintInvalidation(); |
- LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(*child); |
+ LayoutUnit childPreferredSize = flexItem.flexedContentSize + mainAxisBorderAndPaddingExtentForChild(*child); |
setOverrideMainAxisSizeForChild(*child, childPreferredSize); |
if (childPreferredSize != mainAxisExtentForChild(*child)) { |
child->setChildNeedsLayout(MarkOnlyThis); |
@@ -1658,7 +1658,7 @@ void LayoutFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, |
size_t seenInFlowPositionedChildren = 0; |
for (size_t i = 0; i < children.size(); ++i) { |
- LayoutBox* child = children[i]; |
+ LayoutBox* child = children[i].box; |
if (child->isOutOfFlowPositioned()) |
continue; |