| 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;
|
|
|