REGRESSION (r189567): Elements with aspect ratios not handled correctly inside flexbox.
[WebKit-https.git] / Source / WebCore / rendering / RenderFlexibleBox.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "RenderFlexibleBox.h"
33
34 #include "LayoutRepainter.h"
35 #include "RenderLayer.h"
36 #include "RenderView.h"
37 #include <limits>
38 #include <wtf/MathExtras.h>
39
40 namespace WebCore {
41
42 static constexpr ItemPosition selfAlignmentNormalBehaviorFlexibleBox = ItemPositionStretch;
43
44 struct RenderFlexibleBox::LineContext {
45     LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t numberOfChildren, LayoutUnit maxAscent)
46         : crossAxisOffset(crossAxisOffset)
47         , crossAxisExtent(crossAxisExtent)
48         , numberOfChildren(numberOfChildren)
49         , maxAscent(maxAscent)
50     {
51     }
52
53     LayoutUnit crossAxisOffset;
54     LayoutUnit crossAxisExtent;
55     size_t numberOfChildren;
56     LayoutUnit maxAscent;
57 };
58
59 struct RenderFlexibleBox::Violation {
60     Violation(RenderBox& child, LayoutUnit childSize)
61         : child(child)
62         , childSize(childSize)
63     {
64     }
65
66     RenderBox& child;
67     LayoutUnit childSize;
68 };
69
70
71 RenderFlexibleBox::RenderFlexibleBox(Element& element, RenderStyle&& style)
72     : RenderBlock(element, WTFMove(style), 0)
73     , m_orderIterator(*this)
74     , m_numberOfInFlowChildrenOnFirstLine(-1)
75 {
76     setChildrenInline(false); // All of our children must be block-level.
77 }
78
79 RenderFlexibleBox::RenderFlexibleBox(Document& document, RenderStyle&& style)
80     : RenderBlock(document, WTFMove(style), 0)
81     , m_orderIterator(*this)
82     , m_numberOfInFlowChildrenOnFirstLine(-1)
83 {
84     setChildrenInline(false); // All of our children must be block-level.
85 }
86
87 RenderFlexibleBox::~RenderFlexibleBox()
88 {
89 }
90
91 const char* RenderFlexibleBox::renderName() const
92 {
93     return "RenderFlexibleBox";
94 }
95
96 void RenderFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
97 {
98     // FIXME: We're ignoring flex-basis here and we shouldn't. We can't start honoring it though until
99     // the flex shorthand stops setting it to 0.
100     // See https://bugs.webkit.org/show_bug.cgi?id=116117,
101     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
102         if (child->isOutOfFlowPositioned())
103             continue;
104
105         LayoutUnit margin = marginIntrinsicLogicalWidthForChild(*child);
106         bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
107         LayoutUnit minPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->minPreferredLogicalWidth();
108         LayoutUnit maxPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->maxPreferredLogicalWidth();
109         minPreferredLogicalWidth += margin;
110         maxPreferredLogicalWidth += margin;
111         if (!isColumnFlow()) {
112             maxLogicalWidth += maxPreferredLogicalWidth;
113             if (isMultiline()) {
114                 // For multiline, the min preferred width is if you put a break between each item.
115                 minLogicalWidth = std::max(minLogicalWidth, minPreferredLogicalWidth);
116             } else
117                 minLogicalWidth += minPreferredLogicalWidth;
118         } else {
119             minLogicalWidth = std::max(minPreferredLogicalWidth, minLogicalWidth);
120             if (isMultiline()) {
121                 // For multiline, the max preferred width is if you never break between items.
122                 maxLogicalWidth += maxPreferredLogicalWidth;
123             } else
124                 maxLogicalWidth = std::max(maxPreferredLogicalWidth, maxLogicalWidth);
125         }
126     }
127
128     // Due to negative margins, it is possible that we calculated a negative intrinsic width.
129     // Make sure that we never return a negative width.
130     minLogicalWidth = std::max(LayoutUnit(), minLogicalWidth);
131     maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
132
133     LayoutUnit scrollbarWidth = intrinsicScrollbarLogicalWidth();
134     maxLogicalWidth += scrollbarWidth;
135     minLogicalWidth += scrollbarWidth;
136 }
137
138 void RenderFlexibleBox::computePreferredLogicalWidths()
139 {
140     ASSERT(preferredLogicalWidthsDirty());
141
142     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
143
144     const RenderStyle& styleToUse = style();
145     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for width.
146     if (styleToUse.logicalWidth().isFixed() && styleToUse.logicalWidth().value() > 0)
147         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalWidth().value());
148     else
149         computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
150
151     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for min-width.
152     if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
153         m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
154         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
155     }
156
157     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for maxWidth.
158     if (styleToUse.logicalMaxWidth().isFixed()) {
159         m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
160         m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
161     }
162
163     LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
164     m_minPreferredLogicalWidth += borderAndPadding;
165     m_maxPreferredLogicalWidth += borderAndPadding;
166
167     setPreferredLogicalWidthsDirty(false);
168 }
169
170 static int synthesizedBaselineFromContentBox(const RenderBox& box, LineDirectionMode direction)
171 {
172     return direction == HorizontalLine ? box.borderTop() + box.paddingTop() + box.contentHeight() : box.borderRight() + box.paddingRight() + box.contentWidth();
173 }
174
175 int RenderFlexibleBox::baselinePosition(FontBaseline, bool, LineDirectionMode direction, LinePositionMode) const
176 {
177     int baseline = firstLineBaseline().valueOr(synthesizedBaselineFromContentBox(*this, direction));
178
179     int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
180     return baseline + marginAscent;
181 }
182
183 Optional<int> RenderFlexibleBox::firstLineBaseline() const
184 {
185     if (isWritingModeRoot() || m_numberOfInFlowChildrenOnFirstLine <= 0)
186         return Optional<int>();
187     RenderBox* baselineChild = nullptr;
188     int childNumber = 0;
189     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
190         if (child->isOutOfFlowPositioned())
191             continue;
192         if (alignmentForChild(*child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(*child)) {
193             baselineChild = child;
194             break;
195         }
196         if (!baselineChild)
197             baselineChild = child;
198
199         ++childNumber;
200         if (childNumber == m_numberOfInFlowChildrenOnFirstLine)
201             break;
202     }
203
204     if (!baselineChild)
205         return Optional<int>();
206
207     if (!isColumnFlow() && hasOrthogonalFlow(*baselineChild))
208         return Optional<int>(crossAxisExtentForChild(*baselineChild) + baselineChild->logicalTop());
209     if (isColumnFlow() && !hasOrthogonalFlow(*baselineChild))
210         return Optional<int>(mainAxisExtentForChild(*baselineChild) + baselineChild->logicalTop());
211
212     Optional<int> baseline = baselineChild->firstLineBaseline();
213     if (!baseline) {
214         // FIXME: We should pass |direction| into firstLineBoxBaseline and stop bailing out if we're a writing mode root.
215         // This would also fix some cases where the flexbox is orthogonal to its container.
216         LineDirectionMode direction = isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
217         return Optional<int>(synthesizedBaselineFromContentBox(*baselineChild, direction) + baselineChild->logicalTop());
218     }
219
220     return Optional<int>(baseline.value() + baselineChild->logicalTop());
221 }
222
223 Optional<int> RenderFlexibleBox::inlineBlockBaseline(LineDirectionMode direction) const
224 {
225     if (Optional<int> baseline = firstLineBaseline())
226         return baseline;
227
228     int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
229     return synthesizedBaselineFromContentBox(*this, direction) + marginAscent;
230 }
231
232 void RenderFlexibleBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
233 {
234     RenderBlock::styleDidChange(diff, oldStyle);
235
236     if (oldStyle && oldStyle->resolvedAlignItems(selfAlignmentNormalBehaviorFlexibleBox).position() == ItemPositionStretch && diff == StyleDifferenceLayout) {
237         // Flex items that were previously stretching need to be relayed out so we can compute new available cross axis space.
238         // This is only necessary for stretching since other alignment values don't change the size of the box.
239         auto& newStyle = style();
240         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
241             auto& childStyle = child->style();
242             auto previousAlignment = childStyle.resolvedAlignSelf(*oldStyle, selfAlignmentNormalBehaviorFlexibleBox).position();
243             if (previousAlignment == ItemPositionStretch && previousAlignment != childStyle.resolvedAlignSelf(newStyle, selfAlignmentNormalBehaviorFlexibleBox).position())
244                 child->setChildNeedsLayout(MarkOnlyThis);
245         }
246     }
247 }
248
249 void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
250 {
251     ASSERT(needsLayout());
252
253     if (!relayoutChildren && simplifiedLayout())
254         return;
255
256     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
257
258     if (recomputeLogicalWidth())
259         relayoutChildren = true;
260
261     LayoutUnit previousHeight = logicalHeight();
262     setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight());
263
264     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
265
266     preparePaginationBeforeBlockLayout(relayoutChildren);
267
268     m_numberOfInFlowChildrenOnFirstLine = -1;
269
270     beginUpdateScrollInfoAfterLayoutTransaction();
271
272     dirtyForLayoutFromPercentageHeightDescendants();
273
274     prepareOrderIteratorAndMargins();
275
276     ChildFrameRects oldChildRects;
277     appendChildFrameRects(oldChildRects);
278     Vector<LineContext> lineContexts;
279     layoutFlexItems(relayoutChildren, lineContexts);
280
281     updateLogicalHeight();
282     repositionLogicalHeightDependentFlexItems(lineContexts);
283
284     endAndCommitUpdateScrollInfoAfterLayoutTransaction();
285
286     if (logicalHeight() != previousHeight)
287         relayoutChildren = true;
288
289     layoutPositionedObjects(relayoutChildren || isDocumentElementRenderer());
290
291     repaintChildrenDuringLayoutIfMoved(oldChildRects);
292     // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
293     computeOverflow(clientLogicalBottomAfterRepositioning());
294     statePusher.pop();
295
296     updateLayerTransform();
297
298     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
299     // we overflow or not.
300     updateScrollInfoAfterLayout();
301
302     repainter.repaintAfterLayout();
303
304     clearNeedsLayout();
305 }
306
307 void RenderFlexibleBox::appendChildFrameRects(ChildFrameRects& childFrameRects)
308 {
309     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
310         if (!child->isOutOfFlowPositioned())
311             childFrameRects.append(child->frameRect());
312     }
313 }
314
315 void RenderFlexibleBox::repaintChildrenDuringLayoutIfMoved(const ChildFrameRects& oldChildRects)
316 {
317     size_t childIndex = 0;
318     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
319         if (child->isOutOfFlowPositioned())
320             continue;
321
322         // If the child moved, we have to repaint it as well as any floating/positioned
323         // descendants. An exception is if we need a layout. In this case, we know we're going to
324         // repaint ourselves (and the child) anyway.
325         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
326             child->repaintDuringLayoutIfMoved(oldChildRects[childIndex]);
327         ++childIndex;
328     }
329     ASSERT(childIndex == oldChildRects.size());
330 }
331
332 void RenderFlexibleBox::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
333 {
334     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
335         if (!paintChild(*child, paintInfo, paintOffset, paintInfoForChild, usePrintRect, PaintAsInlineBlock))
336             return;
337     }
338 }
339
340 void RenderFlexibleBox::repositionLogicalHeightDependentFlexItems(Vector<LineContext>& lineContexts)
341 {
342     LayoutUnit crossAxisStartEdge = lineContexts.isEmpty() ? LayoutUnit() : lineContexts[0].crossAxisOffset;
343     alignFlexLines(lineContexts);
344
345     // If we have a single line flexbox, the line height is all the available space.
346     // For flex-direction: row, this means we need to use the height, so we do this after calling updateLogicalHeight.
347     if (!isMultiline() && lineContexts.size() == 1)
348         lineContexts[0].crossAxisExtent = crossAxisContentExtent();
349     alignChildren(lineContexts);
350
351     if (style().flexWrap() == FlexWrapReverse)
352         flipForWrapReverse(lineContexts, crossAxisStartEdge);
353
354     // direction:rtl + flex-direction:column means the cross-axis direction is flipped.
355     flipForRightToLeftColumn();
356 }
357
358 LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
359 {
360     LayoutUnit maxChildLogicalBottom = 0;
361     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
362         if (child->isOutOfFlowPositioned())
363             continue;
364         LayoutUnit childLogicalBottom = logicalTopForChild(*child) + logicalHeightForChild(*child) + marginAfterForChild(*child);
365         maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
366     }
367     return std::max(clientLogicalBottom(), maxChildLogicalBottom);
368 }
369
370 bool RenderFlexibleBox::hasOrthogonalFlow(const RenderBox& child) const
371 {
372     // FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
373     return isHorizontalFlow() != child.isHorizontalWritingMode();
374 }
375
376 bool RenderFlexibleBox::isColumnFlow() const
377 {
378     return style().isColumnFlexDirection();
379 }
380
381 bool RenderFlexibleBox::isHorizontalFlow() const
382 {
383     if (isHorizontalWritingMode())
384         return !isColumnFlow();
385     return isColumnFlow();
386 }
387
388 bool RenderFlexibleBox::isLeftToRightFlow() const
389 {
390     if (isColumnFlow())
391         return style().writingMode() == TopToBottomWritingMode || style().writingMode() == LeftToRightWritingMode;
392     return style().isLeftToRightDirection() ^ (style().flexDirection() == FlowRowReverse);
393 }
394
395 bool RenderFlexibleBox::isMultiline() const
396 {
397     return style().flexWrap() != FlexNoWrap;
398 }
399
400 Length RenderFlexibleBox::flexBasisForChild(RenderBox& child) const
401 {
402     Length flexLength = child.style().flexBasis();
403     if (flexLength.isAuto())
404         flexLength = isHorizontalFlow() ? child.style().width() : child.style().height();
405     return flexLength;
406 }
407
408 void RenderFlexibleBox::setCrossAxisExtent(LayoutUnit extent)
409 {
410     if (isHorizontalFlow())
411         setHeight(extent);
412     else
413         setWidth(extent);
414 }
415
416 LayoutUnit RenderFlexibleBox::crossAxisExtentForChild(RenderBox& child) const
417 {
418     return isHorizontalFlow() ? child.height() : child.width();
419 }
420
421 LayoutUnit RenderFlexibleBox::mainAxisExtentForChild(RenderBox& child) const
422 {
423     return isHorizontalFlow() ? child.width() : child.height();
424 }
425
426 LayoutUnit RenderFlexibleBox::crossAxisExtent() const
427 {
428     return isHorizontalFlow() ? height() : width();
429 }
430
431 LayoutUnit RenderFlexibleBox::mainAxisExtent() const
432 {
433     return isHorizontalFlow() ? width() : height();
434 }
435
436 LayoutUnit RenderFlexibleBox::crossAxisContentExtent() const
437 {
438     return isHorizontalFlow() ? contentHeight() : contentWidth();
439 }
440
441 LayoutUnit RenderFlexibleBox::mainAxisContentExtent(LayoutUnit contentLogicalHeight)
442 {
443     if (isColumnFlow()) {
444         LogicalExtentComputedValues computedValues;
445         LayoutUnit borderPaddingAndScrollbar = borderAndPaddingLogicalHeight() + scrollbarLogicalHeight();
446         if (contentLogicalHeight > LayoutUnit::max() - borderPaddingAndScrollbar)
447             contentLogicalHeight -= borderPaddingAndScrollbar;
448         LayoutUnit borderBoxLogicalHeight = contentLogicalHeight + borderPaddingAndScrollbar;
449         computeLogicalHeight(borderBoxLogicalHeight, logicalTop(), computedValues);
450         if (computedValues.m_extent == LayoutUnit::max())
451             return computedValues.m_extent;
452         return std::max(LayoutUnit::fromPixel(0), computedValues.m_extent - borderPaddingAndScrollbar);
453     }
454     return contentLogicalWidth();
455 }
456
457 Optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(const RenderBox& child, SizeType sizeType, const Length& size)
458 {
459     // FIXME: This is wrong for orthogonal flows. It should use the flexbox's writing-mode, not the child's in order
460     // to figure out the logical height/width.
461     if (isColumnFlow()) {
462         // We don't have to check for "auto" here - computeContentLogicalHeight will just return Nullopt for that case anyway.
463         if (size.isIntrinsic())
464             const_cast<RenderBox&>(child).layoutIfNeeded(); // FIXME: Should not need to do a layout here.
465         return child.computeContentLogicalHeight(sizeType, size, child.logicalHeight() - child.borderAndPaddingLogicalHeight());
466     }
467     // FIXME: Figure out how this should work for regions and pass in the appropriate values.
468     RenderRegion* region = nullptr;
469     return child.computeLogicalWidthInRegionUsing(sizeType, size, contentLogicalWidth(), *this, region) - child.borderAndPaddingLogicalWidth();
470 }
471
472 WritingMode RenderFlexibleBox::transformedWritingMode() const
473 {
474     WritingMode mode = style().writingMode();
475     if (!isColumnFlow())
476         return mode;
477
478     switch (mode) {
479     case TopToBottomWritingMode:
480     case BottomToTopWritingMode:
481         return style().isLeftToRightDirection() ? LeftToRightWritingMode : RightToLeftWritingMode;
482     case LeftToRightWritingMode:
483     case RightToLeftWritingMode:
484         return style().isLeftToRightDirection() ? TopToBottomWritingMode : BottomToTopWritingMode;
485     }
486     ASSERT_NOT_REACHED();
487     return TopToBottomWritingMode;
488 }
489
490 LayoutUnit RenderFlexibleBox::flowAwareBorderStart() const
491 {
492     if (isHorizontalFlow())
493         return isLeftToRightFlow() ? borderLeft() : borderRight();
494     return isLeftToRightFlow() ? borderTop() : borderBottom();
495 }
496
497 LayoutUnit RenderFlexibleBox::flowAwareBorderEnd() const
498 {
499     if (isHorizontalFlow())
500         return isLeftToRightFlow() ? borderRight() : borderLeft();
501     return isLeftToRightFlow() ? borderBottom() : borderTop();
502 }
503
504 LayoutUnit RenderFlexibleBox::flowAwareBorderBefore() const
505 {
506     switch (transformedWritingMode()) {
507     case TopToBottomWritingMode:
508         return borderTop();
509     case BottomToTopWritingMode:
510         return borderBottom();
511     case LeftToRightWritingMode:
512         return borderLeft();
513     case RightToLeftWritingMode:
514         return borderRight();
515     }
516     ASSERT_NOT_REACHED();
517     return borderTop();
518 }
519
520 LayoutUnit RenderFlexibleBox::flowAwareBorderAfter() const
521 {
522     switch (transformedWritingMode()) {
523     case TopToBottomWritingMode:
524         return borderBottom();
525     case BottomToTopWritingMode:
526         return borderTop();
527     case LeftToRightWritingMode:
528         return borderRight();
529     case RightToLeftWritingMode:
530         return borderLeft();
531     }
532     ASSERT_NOT_REACHED();
533     return borderTop();
534 }
535
536 LayoutUnit RenderFlexibleBox::flowAwarePaddingStart() const
537 {
538     if (isHorizontalFlow())
539         return isLeftToRightFlow() ? paddingLeft() : paddingRight();
540     return isLeftToRightFlow() ? paddingTop() : paddingBottom();
541 }
542
543 LayoutUnit RenderFlexibleBox::flowAwarePaddingEnd() const
544 {
545     if (isHorizontalFlow())
546         return isLeftToRightFlow() ? paddingRight() : paddingLeft();
547     return isLeftToRightFlow() ? paddingBottom() : paddingTop();
548 }
549
550 LayoutUnit RenderFlexibleBox::flowAwarePaddingBefore() const
551 {
552     switch (transformedWritingMode()) {
553     case TopToBottomWritingMode:
554         return paddingTop();
555     case BottomToTopWritingMode:
556         return paddingBottom();
557     case LeftToRightWritingMode:
558         return paddingLeft();
559     case RightToLeftWritingMode:
560         return paddingRight();
561     }
562     ASSERT_NOT_REACHED();
563     return paddingTop();
564 }
565
566 LayoutUnit RenderFlexibleBox::flowAwarePaddingAfter() const
567 {
568     switch (transformedWritingMode()) {
569     case TopToBottomWritingMode:
570         return paddingBottom();
571     case BottomToTopWritingMode:
572         return paddingTop();
573     case LeftToRightWritingMode:
574         return paddingRight();
575     case RightToLeftWritingMode:
576         return paddingLeft();
577     }
578     ASSERT_NOT_REACHED();
579     return paddingTop();
580 }
581
582 LayoutUnit RenderFlexibleBox::flowAwareMarginStartForChild(RenderBox& child) const
583 {
584     if (isHorizontalFlow())
585         return isLeftToRightFlow() ? child.marginLeft() : child.marginRight();
586     return isLeftToRightFlow() ? child.marginTop() : child.marginBottom();
587 }
588
589 LayoutUnit RenderFlexibleBox::flowAwareMarginEndForChild(RenderBox& child) const
590 {
591     if (isHorizontalFlow())
592         return isLeftToRightFlow() ? child.marginRight() : child.marginLeft();
593     return isLeftToRightFlow() ? child.marginBottom() : child.marginTop();
594 }
595
596 LayoutUnit RenderFlexibleBox::flowAwareMarginBeforeForChild(RenderBox& child) const
597 {
598     switch (transformedWritingMode()) {
599     case TopToBottomWritingMode:
600         return child.marginTop();
601     case BottomToTopWritingMode:
602         return child.marginBottom();
603     case LeftToRightWritingMode:
604         return child.marginLeft();
605     case RightToLeftWritingMode:
606         return child.marginRight();
607     }
608     ASSERT_NOT_REACHED();
609     return marginTop();
610 }
611
612 LayoutUnit RenderFlexibleBox::flowAwareMarginAfterForChild(RenderBox& child) const
613 {
614     switch (transformedWritingMode()) {
615     case TopToBottomWritingMode:
616         return child.marginBottom();
617     case BottomToTopWritingMode:
618         return child.marginTop();
619     case LeftToRightWritingMode:
620         return child.marginRight();
621     case RightToLeftWritingMode:
622         return child.marginLeft();
623     }
624     ASSERT_NOT_REACHED();
625     return marginBottom();
626 }
627
628 LayoutUnit RenderFlexibleBox::crossAxisMarginExtentForChild(RenderBox& child) const
629 {
630     return isHorizontalFlow() ? child.verticalMarginExtent() : child.horizontalMarginExtent();
631 }
632
633 LayoutUnit RenderFlexibleBox::crossAxisScrollbarExtent() const
634 {
635     return isHorizontalFlow() ? horizontalScrollbarHeight() : verticalScrollbarWidth();
636 }
637
638 LayoutPoint RenderFlexibleBox::flowAwareLocationForChild(RenderBox& child) const
639 {
640     return isHorizontalFlow() ? child.location() : child.location().transposedPoint();
641 }
642
643 void RenderFlexibleBox::setFlowAwareLocationForChild(RenderBox& child, const LayoutPoint& location)
644 {
645     if (isHorizontalFlow())
646         child.setLocation(location);
647     else
648         child.setLocation(location.transposedPoint());
649 }
650
651 LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox& child) const
652 {
653     return isHorizontalFlow() ? child.horizontalBorderAndPaddingExtent() : child.verticalBorderAndPaddingExtent();
654 }
655     
656 bool RenderFlexibleBox::mainAxisLengthIsDefinite(const RenderBox& child, const Length& flexBasis) const
657 {
658     if (flexBasis.isAuto())
659         return false;
660     if (flexBasis.isPercentOrCalculated())
661         return isColumnFlow() ? bool(child.computePercentageLogicalHeight(flexBasis)) : hasDefiniteLogicalWidth();
662     return true;
663 }
664
665 LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox& child) const
666 {
667     return isHorizontalFlow() ? child.verticalScrollbarWidth() : child.horizontalScrollbarHeight();
668 }
669
670 LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox& child, bool hasInfiniteLineLength)
671 {
672     bool hasOverrideSize = child.hasOverrideLogicalContentWidth() || child.hasOverrideLogicalContentHeight();
673     if (hasOverrideSize)
674         child.clearOverrideSize();
675
676     Length flexBasis = flexBasisForChild(child);
677     if (flexBasis.isAuto() || (flexBasis.isFixed() && !flexBasis.value() && hasInfiniteLineLength)) {
678         if (hasOrthogonalFlow(child)) {
679             if (hasOverrideSize)
680                 child.setChildNeedsLayout(MarkOnlyThis);
681             child.layoutIfNeeded();
682         }
683         LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child.logicalHeight() : child.maxPreferredLogicalWidth();
684         ASSERT(mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child) >= 0);
685         return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
686     }
687     return computeMainAxisExtentForChild(child, MainOrPreferredSize, flexBasis).valueOr(0);
688 }
689
690 void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren, Vector<LineContext>& lineContexts)
691 {
692     OrderedFlexItemList orderedChildren;
693     LayoutUnit preferredMainAxisExtent;
694     double totalFlexGrow;
695     double totalWeightedFlexShrink;
696     LayoutUnit minMaxAppliedMainAxisExtent;
697
698     m_orderIterator.first();
699     LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
700     bool hasInfiniteLineLength = false;
701     while (computeNextFlexLine(orderedChildren, preferredMainAxisExtent, totalFlexGrow, totalWeightedFlexShrink, minMaxAppliedMainAxisExtent, hasInfiniteLineLength)) {
702         LayoutUnit availableFreeSpace = mainAxisContentExtent(preferredMainAxisExtent) - preferredMainAxisExtent;
703         FlexSign flexSign = (minMaxAppliedMainAxisExtent < preferredMainAxisExtent + availableFreeSpace) ? PositiveFlexibility : NegativeFlexibility;
704         InflexibleFlexItemSize inflexibleItems;
705         Vector<LayoutUnit> childSizes;
706         while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, childSizes, hasInfiniteLineLength)) {
707             ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0);
708             ASSERT(inflexibleItems.size() > 0);
709         }
710
711         layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, relayoutChildren, lineContexts);
712     }
713     if (hasLineIfEmpty()) {
714         // Even if computeNextFlexLine returns true, the flexbox might not have
715         // a line because all our children might be out of flow positioned.
716         // Instead of just checking if we have a line, make sure the flexbox
717         // has at least a line's worth of height to cover this case.
718         LayoutUnit minHeight = borderAndPaddingLogicalHeight()
719             + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)
720             + scrollbarLogicalHeight();
721         if (height() < minHeight)
722             setLogicalHeight(minHeight);
723     }
724 }
725
726 LayoutUnit RenderFlexibleBox::autoMarginOffsetInMainAxis(const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace)
727 {
728     if (availableFreeSpace <= 0)
729         return 0;
730
731     int numberOfAutoMargins = 0;
732     bool isHorizontal = isHorizontalFlow();
733     for (size_t i = 0; i < children.size(); ++i) {
734         RenderBox* child = children[i];
735         if (child->isOutOfFlowPositioned())
736             continue;
737         if (isHorizontal) {
738             if (child->style().marginLeft().isAuto())
739                 ++numberOfAutoMargins;
740             if (child->style().marginRight().isAuto())
741                 ++numberOfAutoMargins;
742         } else {
743             if (child->style().marginTop().isAuto())
744                 ++numberOfAutoMargins;
745             if (child->style().marginBottom().isAuto())
746                 ++numberOfAutoMargins;
747         }
748     }
749     if (!numberOfAutoMargins)
750         return 0;
751
752     LayoutUnit sizeOfAutoMargin = availableFreeSpace / numberOfAutoMargins;
753     availableFreeSpace = 0;
754     return sizeOfAutoMargin;
755 }
756
757 void RenderFlexibleBox::updateAutoMarginsInMainAxis(RenderBox& child, LayoutUnit autoMarginOffset)
758 {
759     ASSERT(autoMarginOffset >= 0);
760
761     if (isHorizontalFlow()) {
762         if (child.style().marginLeft().isAuto())
763             child.setMarginLeft(autoMarginOffset);
764         if (child.style().marginRight().isAuto())
765             child.setMarginRight(autoMarginOffset);
766     } else {
767         if (child.style().marginTop().isAuto())
768             child.setMarginTop(autoMarginOffset);
769         if (child.style().marginBottom().isAuto())
770             child.setMarginBottom(autoMarginOffset);
771     }
772 }
773
774 bool RenderFlexibleBox::hasAutoMarginsInCrossAxis(RenderBox& child) const
775 {
776     if (isHorizontalFlow())
777         return child.style().marginTop().isAuto() || child.style().marginBottom().isAuto();
778     return child.style().marginLeft().isAuto() || child.style().marginRight().isAuto();
779 }
780
781 LayoutUnit RenderFlexibleBox::availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox& child)
782 {
783     ASSERT(!child.isOutOfFlowPositioned());
784     LayoutUnit childCrossExtent = crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child);
785     return lineCrossAxisExtent - childCrossExtent;
786 }
787
788 bool RenderFlexibleBox::updateAutoMarginsInCrossAxis(RenderBox& child, LayoutUnit availableAlignmentSpace)
789 {
790     ASSERT(!child.isOutOfFlowPositioned());
791     ASSERT(availableAlignmentSpace >= 0);
792
793     bool isHorizontal = isHorizontalFlow();
794     Length start = isHorizontal ? child.style().marginTop() : child.style().marginLeft();
795     Length end = isHorizontal ? child.style().marginBottom() : child.style().marginRight();
796     if (start.isAuto() && end.isAuto()) {
797         adjustAlignmentForChild(child, availableAlignmentSpace / 2);
798         if (isHorizontal) {
799             child.setMarginTop(availableAlignmentSpace / 2);
800             child.setMarginBottom(availableAlignmentSpace / 2);
801         } else {
802             child.setMarginLeft(availableAlignmentSpace / 2);
803             child.setMarginRight(availableAlignmentSpace / 2);
804         }
805         return true;
806     }
807     if (start.isAuto()) {
808         adjustAlignmentForChild(child, availableAlignmentSpace);
809         if (isHorizontal)
810             child.setMarginTop(availableAlignmentSpace);
811         else
812             child.setMarginLeft(availableAlignmentSpace);
813         return true;
814     }
815     if (end.isAuto()) {
816         if (isHorizontal)
817             child.setMarginBottom(availableAlignmentSpace);
818         else
819             child.setMarginRight(availableAlignmentSpace);
820         return true;
821     }
822     return false;
823 }
824
825 LayoutUnit RenderFlexibleBox::marginBoxAscentForChild(RenderBox& child)
826 {
827     LayoutUnit ascent = child.firstLineBaseline().valueOr(crossAxisExtentForChild(child));
828     return ascent + flowAwareMarginBeforeForChild(child);
829 }
830
831 LayoutUnit RenderFlexibleBox::computeChildMarginValue(const Length& margin)
832 {
833     // When resolving the margins, we use the content size for resolving percent and calc (for percents in calc expressions) margins.
834     // Fortunately, percent margins are always computed with respect to the block's width, even for margin-top and margin-bottom.
835     LayoutUnit availableSize = contentLogicalWidth();
836     return minimumValueForLength(margin, availableSize);
837 }
838
839 void RenderFlexibleBox::prepareOrderIteratorAndMargins()
840 {
841     OrderIteratorPopulator populator(m_orderIterator);
842
843     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
844         populator.collectChild(*child);
845
846         if (child->isOutOfFlowPositioned())
847             continue;
848
849         // Before running the flex algorithm, 'auto' has a margin of 0.
850         // Also, if we're not auto sizing, we don't do a layout that computes the start/end margins.
851         if (isHorizontalFlow()) {
852             child->setMarginLeft(computeChildMarginValue(child->style().marginLeft()));
853             child->setMarginRight(computeChildMarginValue(child->style().marginRight()));
854         } else {
855             child->setMarginTop(computeChildMarginValue(child->style().marginTop()));
856             child->setMarginBottom(computeChildMarginValue(child->style().marginBottom()));
857         }
858     }
859 }
860
861 bool RenderFlexibleBox::crossAxisLengthIsDefinite(const RenderBox& child, const Length& length) const
862 {
863     if (length.isAuto())
864         return false;
865     if (length.isPercentOrCalculated())
866         return hasOrthogonalFlow(child) ? hasDefiniteLogicalWidth() : bool(child.computePercentageLogicalHeight(length));
867     return length.isFixed();
868 }
869
870     
871 Optional<LayoutUnit> RenderFlexibleBox::computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const
872 {
873     ASSERT(child.hasAspectRatio());
874     ASSERT(child.intrinsicSize().height() > 0);
875     
876     Optional<LayoutUnit> crossSize;
877     if (crossSizeLength.isFixed())
878         crossSize = LayoutUnit(crossSizeLength.value());
879     else {
880         ASSERT(crossSizeLength.isPercentOrCalculated());
881         crossSize = hasOrthogonalFlow(child) ?
882         adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(crossSizeLength, contentWidth())) :
883         child.computePercentageLogicalHeight(crossSizeLength);
884     }
885     
886     if (!crossSize)
887         return crossSize;
888
889     const LayoutSize& childIntrinsicSize = child.intrinsicSize();
890     double ratio = childIntrinsicSize.width().toFloat() / childIntrinsicSize.height().toFloat();
891     if (isHorizontalFlow())
892         return LayoutUnit(crossSize.value() * ratio);
893     return LayoutUnit(crossSize.value() / ratio);
894 }
895
896 LayoutUnit RenderFlexibleBox::adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox& child, LayoutUnit childSize)
897 {
898     Length crossMin = isHorizontalFlow() ? child.style().minHeight() : child.style().minWidth();
899     Length crossMax = isHorizontalFlow() ? child.style().maxHeight() : child.style().maxWidth();
900
901     if (crossAxisLengthIsDefinite(child, crossMax)) {
902         Optional<LayoutUnit> maxValue = computeMainSizeFromAspectRatioUsing(child, crossMax);
903         if (maxValue)
904             childSize = std::min(maxValue.value(), childSize);
905     }
906     
907     if (crossAxisLengthIsDefinite(child, crossMin)) {
908         Optional<LayoutUnit> minValue = computeMainSizeFromAspectRatioUsing(child, crossMin);
909         if (minValue)
910             childSize = std::max(minValue.value(), childSize);
911     }
912     
913     return childSize;
914 }
915
916 bool RenderFlexibleBox::useChildAspectRatio(const RenderBox& child) const
917 {
918     if (!child.hasAspectRatio())
919         return false;
920     if (!child.intrinsicSize().height())
921         return false;
922     Length crossSize = isHorizontalFlow() ? child.style().height() : child.style().width();
923     return crossAxisLengthIsDefinite(child, crossSize);
924 }
925
926 LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(const RenderBox& child, LayoutUnit childSize)
927 {
928     Length max = isHorizontalFlow() ? child.style().maxWidth() : child.style().maxHeight();
929     Optional<LayoutUnit> maxExtent = Nullopt;
930     if (max.isSpecifiedOrIntrinsic()) {
931         maxExtent = computeMainAxisExtentForChild(child, MaxSize, max);
932         childSize = std::min(childSize, maxExtent.valueOr(childSize));
933     }
934     
935     Length min = isHorizontalFlow() ? child.style().minWidth() : child.style().minHeight();
936     if (min.isSpecifiedOrIntrinsic())
937         return std::max(childSize, computeMainAxisExtentForChild(child, MinSize, min).valueOr(childSize));
938     
939     if (!isFlexibleBoxImpl() && min.isAuto() && mainAxisOverflowForChild(child) == OVISIBLE && !(isColumnFlow() && is<RenderFlexibleBox>(child))) {
940         // This is the implementation of CSS flexbox section 4.5 which defines the minimum size of "pure" flex
941         // items. For any other item the value should be 0, this also includes RenderFlexibleBox's derived clases
942         // (RenderButton, RenderFullScreen...) because that's just an implementation detail.
943         // FIXME: For now we don't handle nested column flexboxes. Need to implement better intrinsic
944         // size handling from the flex box spec first (4.5).
945         LayoutUnit contentSize = computeMainAxisExtentForChild(child, MinSize, Length(MinContent)).value();
946         ASSERT(contentSize >= 0);
947         if (child.hasAspectRatio() && child.intrinsicSize().height() > 0)
948             contentSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, contentSize);
949         contentSize = std::min(contentSize, maxExtent.valueOr(contentSize));
950         
951         Length mainSize = isHorizontalFlow() ? child.style().width() : child.style().height();
952         if (mainAxisLengthIsDefinite(child, mainSize)) {
953             LayoutUnit resolvedMainSize = computeMainAxisExtentForChild(child, MainOrPreferredSize, mainSize).value();
954             ASSERT(resolvedMainSize >= 0);
955             LayoutUnit specifiedSize = std::min(resolvedMainSize, maxExtent.valueOr(resolvedMainSize));
956             return std::max(childSize, std::min(specifiedSize, contentSize));
957         } else if (useChildAspectRatio(child)) {
958             Length crossSizeLength = isHorizontalFlow() ? child.style().height() : child.style().width();
959             Optional<LayoutUnit> transferredSize = computeMainSizeFromAspectRatioUsing(child, crossSizeLength);
960             if (transferredSize) {
961                 transferredSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, transferredSize.value());
962                 return std::max(childSize, std::min(transferredSize.value(), contentSize));
963             }
964         }
965         return std::max(childSize, contentSize);
966     }
967     return childSize;
968 }
969
970 bool RenderFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent, bool& hasInfiniteLineLength)
971 {
972     orderedChildren.clear();
973     preferredMainAxisExtent = 0;
974     totalFlexGrow = totalWeightedFlexShrink = 0;
975     minMaxAppliedMainAxisExtent = 0;
976
977     if (!m_orderIterator.currentChild())
978         return false;
979
980     LayoutUnit lineBreakLength = mainAxisContentExtent(LayoutUnit::max());
981     hasInfiniteLineLength = lineBreakLength == LayoutUnit::max();
982
983     bool lineHasInFlowItem = false;
984
985     for (RenderBox* child = m_orderIterator.currentChild(); child; child = m_orderIterator.next()) {
986         if (child->isOutOfFlowPositioned()) {
987             orderedChildren.append(child);
988             continue;
989         }
990
991         LayoutUnit childMainAxisExtent = preferredMainAxisContentExtentForChild(*child, hasInfiniteLineLength);
992         LayoutUnit childMainAxisMarginBoxExtent = mainAxisBorderAndPaddingExtentForChild(*child) + childMainAxisExtent;
993         childMainAxisMarginBoxExtent += isHorizontalFlow() ? child->horizontalMarginExtent() : child->verticalMarginExtent();
994
995         if (isMultiline() && preferredMainAxisExtent + childMainAxisMarginBoxExtent > lineBreakLength && lineHasInFlowItem)
996             break;
997         orderedChildren.append(child);
998         lineHasInFlowItem  = true;
999         preferredMainAxisExtent += childMainAxisMarginBoxExtent;
1000         totalFlexGrow += child->style().flexGrow();
1001         totalWeightedFlexShrink += child->style().flexShrink() * childMainAxisExtent;
1002
1003         LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(*child, childMainAxisExtent);
1004         minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent - childMainAxisExtent + childMainAxisMarginBoxExtent;
1005     }
1006     return true;
1007 }
1008
1009 void RenderFlexibleBox::freezeViolations(const Vector<Violation>& violations, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, bool hasInfiniteLineLength)
1010 {
1011     for (size_t i = 0; i < violations.size(); ++i) {
1012         RenderBox& child = violations[i].child;
1013         LayoutUnit childSize = violations[i].childSize;
1014         LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child, hasInfiniteLineLength);
1015         availableFreeSpace -= childSize - preferredChildSize;
1016         totalFlexGrow -= child.style().flexGrow();
1017         totalWeightedFlexShrink -= child.style().flexShrink() * preferredChildSize;
1018         inflexibleItems.set(&child, childSize);
1019     }
1020 }
1021
1022 // Returns true if we successfully ran the algorithm and sized the flex items.
1023 bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit>& childSizes, bool hasInfiniteLineLength)
1024 {
1025     childSizes.clear();
1026     LayoutUnit totalViolation = 0;
1027     LayoutUnit usedFreeSpace = 0;
1028     Vector<Violation> minViolations;
1029     Vector<Violation> maxViolations;
1030     for (size_t i = 0; i < children.size(); ++i) {
1031         RenderBox& child = *children[i];
1032         if (child.isOutOfFlowPositioned()) {
1033             childSizes.append(0);
1034             continue;
1035         }
1036
1037         if (inflexibleItems.contains(&child))
1038             childSizes.append(inflexibleItems.get(&child));
1039         else {
1040             LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child, hasInfiniteLineLength);
1041             LayoutUnit childSize = preferredChildSize;
1042             double extraSpace = 0;
1043             if (availableFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow))
1044                 extraSpace = availableFreeSpace * child.style().flexGrow() / totalFlexGrow;
1045             else if (availableFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink))
1046                 extraSpace = availableFreeSpace * child.style().flexShrink() * preferredChildSize / totalWeightedFlexShrink;
1047             if (std::isfinite(extraSpace))
1048                 childSize += LayoutUnit::fromFloatRound(extraSpace);
1049
1050             LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize);
1051             childSizes.append(adjustedChildSize);
1052             usedFreeSpace += adjustedChildSize - preferredChildSize;
1053
1054             LayoutUnit violation = adjustedChildSize - childSize;
1055             if (violation > 0)
1056                 minViolations.append(Violation(child, adjustedChildSize));
1057             else if (violation < 0)
1058                 maxViolations.append(Violation(child, adjustedChildSize));
1059             totalViolation += violation;
1060         }
1061     }
1062
1063     if (totalViolation)
1064         freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, hasInfiniteLineLength);
1065     else
1066         availableFreeSpace -= usedFreeSpace;
1067
1068     return !totalViolation;
1069 }
1070
1071 static LayoutUnit initialJustifyContentOffset(LayoutUnit availableFreeSpace, ContentPosition justifyContent, ContentDistributionType justifyContentDistribution, unsigned numberOfChildren)
1072 {
1073     if (justifyContent == ContentPositionFlexEnd)
1074         return availableFreeSpace;
1075     if (justifyContent == ContentPositionCenter)
1076         return availableFreeSpace / 2;
1077     if (justifyContentDistribution == ContentDistributionSpaceAround) {
1078         if (availableFreeSpace > 0 && numberOfChildren)
1079             return availableFreeSpace / (2 * numberOfChildren);
1080         else
1081             return availableFreeSpace / 2;
1082     }
1083     return 0;
1084 }
1085
1086 static LayoutUnit justifyContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, ContentDistributionType justifyContentDistribution, unsigned numberOfChildren)
1087 {
1088     if (availableFreeSpace > 0 && numberOfChildren > 1) {
1089         if (justifyContentDistribution == ContentDistributionSpaceBetween)
1090             return availableFreeSpace / (numberOfChildren - 1);
1091         if (justifyContentDistribution == ContentDistributionSpaceAround)
1092             return availableFreeSpace / numberOfChildren;
1093     }
1094     return 0;
1095 }
1096
1097 void RenderFlexibleBox::setLogicalOverrideSize(RenderBox& child, LayoutUnit childPreferredSize)
1098 {
1099     if (hasOrthogonalFlow(child))
1100         child.setOverrideLogicalContentHeight(childPreferredSize - child.borderAndPaddingLogicalHeight());
1101     else
1102         child.setOverrideLogicalContentWidth(childPreferredSize - child.borderAndPaddingLogicalWidth());
1103 }
1104
1105 void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox& child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode layoutMode)
1106 {
1107     ASSERT(child.isOutOfFlowPositioned());
1108     child.containingBlock()->insertPositionedObject(child);
1109     RenderLayer* childLayer = child.layer();
1110     LayoutUnit inlinePosition = isColumnFlow() ? crossAxisOffset : mainAxisOffset;
1111     if (layoutMode == FlipForRowReverse && style().flexDirection() == FlowRowReverse)
1112         inlinePosition = mainAxisExtent() - mainAxisOffset;
1113     childLayer->setStaticInlinePosition(inlinePosition); // FIXME: Not right for regions.
1114
1115     LayoutUnit staticBlockPosition = isColumnFlow() ? mainAxisOffset : crossAxisOffset;
1116     if (childLayer->staticBlockPosition() != staticBlockPosition) {
1117         childLayer->setStaticBlockPosition(staticBlockPosition);
1118         if (child.style().hasStaticBlockPosition(style().isHorizontalWritingMode()))
1119             child.setChildNeedsLayout(MarkOnlyThis);
1120     }
1121 }
1122
1123 ItemPosition RenderFlexibleBox::alignmentForChild(RenderBox& child) const
1124 {
1125     ItemPosition align = child.style().resolvedAlignSelf(style(), selfAlignmentNormalBehaviorFlexibleBox).position();
1126
1127     if (align == ItemPositionBaseline && hasOrthogonalFlow(child))
1128         align = ItemPositionFlexStart;
1129
1130     if (style().flexWrap() == FlexWrapReverse) {
1131         if (align == ItemPositionFlexStart)
1132             align = ItemPositionFlexEnd;
1133         else if (align == ItemPositionFlexEnd)
1134             align = ItemPositionFlexStart;
1135     }
1136
1137     return align;
1138 }
1139
1140 size_t RenderFlexibleBox::numberOfInFlowPositionedChildren(const OrderedFlexItemList& children) const
1141 {
1142     size_t count = 0;
1143     for (size_t i = 0; i < children.size(); ++i) {
1144         RenderBox* child = children[i];
1145         if (!child->isOutOfFlowPositioned())
1146             ++count;
1147     }
1148     return count;
1149 }
1150
1151 bool RenderFlexibleBox::needToStretchChild(RenderBox& child)
1152 {
1153     if (alignmentForChild(child) != ItemPositionStretch)
1154         return false;
1155
1156     Length crossAxisLength = isHorizontalFlow() ? child.style().height() : child.style().width();
1157     return crossAxisLength.isAuto();
1158 }
1159
1160 void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox& child)
1161 {
1162     if (hasAutoMarginsInCrossAxis(child))
1163         child.updateLogicalHeight();
1164 }
1165
1166 EOverflow RenderFlexibleBox::mainAxisOverflowForChild(const RenderBox& child) const
1167 {
1168     if (isHorizontalFlow())
1169         return child.style().overflowX();
1170     return child.style().overflowY();
1171 }
1172
1173 static const StyleContentAlignmentData& contentAlignmentNormalBehaviorFlexibleBox()
1174 {
1175     // The justify-content property applies along the main axis, but since flexing
1176     // in the main axis is controlled by flex, stretch behaves as flex-start (ignoring
1177     // the specified fallback alignment, if any).
1178     // https://drafts.csswg.org/css-align/#distribution-flex
1179     static const StyleContentAlignmentData normalBehavior = {ContentPositionNormal, ContentDistributionStretch};
1180     return normalBehavior;
1181 }
1182
1183 void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>& lineContexts)
1184 {
1185     ASSERT(childSizes.size() == children.size());
1186
1187     auto position = style().resolvedJustifyContentPosition(contentAlignmentNormalBehaviorFlexibleBox());
1188     auto distribution = style().resolvedJustifyContentDistribution(contentAlignmentNormalBehaviorFlexibleBox());
1189
1190     size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren(children);
1191     LayoutUnit autoMarginOffset = autoMarginOffsetInMainAxis(children, availableFreeSpace);
1192     LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
1193     mainAxisOffset += initialJustifyContentOffset(availableFreeSpace, position, distribution, numberOfChildrenForJustifyContent);
1194     if (style().flexDirection() == FlowRowReverse)
1195         mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
1196
1197     LayoutUnit totalMainExtent = mainAxisExtent();
1198     LayoutUnit maxAscent = 0, maxDescent = 0; // Used when align-items: baseline.
1199     LayoutUnit maxChildCrossAxisExtent = 0;
1200     size_t seenInFlowPositionedChildren = 0;
1201     bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow();
1202     for (size_t i = 0; i < children.size(); ++i) {
1203         RenderBox& child = *children[i];
1204         if (child.isOutOfFlowPositioned()) {
1205             prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset, FlipForRowReverse);
1206             continue;
1207         }
1208
1209         LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child);
1210         setLogicalOverrideSize(child, childPreferredSize);
1211         // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
1212         if (needToStretchChild(child) || childPreferredSize != mainAxisExtentForChild(child))
1213             child.setChildNeedsLayout(MarkOnlyThis);
1214         else {
1215             // To avoid double applying margin changes in updateAutoMarginsInCrossAxis, we reset the margins here.
1216             resetAutoMarginsAndLogicalTopInCrossAxis(child);
1217         }
1218         updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
1219         child.layoutIfNeeded();
1220
1221         updateAutoMarginsInMainAxis(child, autoMarginOffset);
1222
1223         LayoutUnit childCrossAxisMarginBoxExtent;
1224         if (alignmentForChild(child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(child)) {
1225             LayoutUnit ascent = marginBoxAscentForChild(child);
1226             LayoutUnit descent = (crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child)) - ascent;
1227
1228             maxAscent = std::max(maxAscent, ascent);
1229             maxDescent = std::max(maxDescent, descent);
1230
1231             childCrossAxisMarginBoxExtent = maxAscent + maxDescent;
1232         } else
1233             childCrossAxisMarginBoxExtent = crossAxisExtentForChild(child) + crossAxisMarginExtentForChild(child);
1234         if (!isColumnFlow())
1235             setLogicalHeight(std::max(logicalHeight(), crossAxisOffset + flowAwareBorderAfter() + flowAwarePaddingAfter() + childCrossAxisMarginBoxExtent + crossAxisScrollbarExtent()));
1236         maxChildCrossAxisExtent = std::max(maxChildCrossAxisExtent, childCrossAxisMarginBoxExtent);
1237
1238         mainAxisOffset += flowAwareMarginStartForChild(child);
1239
1240         LayoutUnit childMainExtent = mainAxisExtentForChild(child);
1241         LayoutPoint childLocation(shouldFlipMainAxis ? totalMainExtent - mainAxisOffset - childMainExtent : mainAxisOffset,
1242             crossAxisOffset + flowAwareMarginBeforeForChild(child));
1243
1244         // FIXME: Supporting layout deltas.
1245         setFlowAwareLocationForChild(child, childLocation);
1246         mainAxisOffset += childMainExtent + flowAwareMarginEndForChild(child);
1247
1248         ++seenInFlowPositionedChildren;
1249         if (seenInFlowPositionedChildren < numberOfChildrenForJustifyContent)
1250             mainAxisOffset += justifyContentSpaceBetweenChildren(availableFreeSpace, distribution, numberOfChildrenForJustifyContent);
1251     }
1252
1253     if (isColumnFlow())
1254         setLogicalHeight(mainAxisOffset + flowAwareBorderEnd() + flowAwarePaddingEnd() + scrollbarLogicalHeight());
1255
1256     if (style().flexDirection() == FlowColumnReverse) {
1257         // We have to do an extra pass for column-reverse to reposition the flex items since the start depends
1258         // on the height of the flexbox, which we only know after we've positioned all the flex items.
1259         updateLogicalHeight();
1260         layoutColumnReverse(children, crossAxisOffset, availableFreeSpace);
1261     }
1262
1263     if (m_numberOfInFlowChildrenOnFirstLine == -1)
1264         m_numberOfInFlowChildrenOnFirstLine = seenInFlowPositionedChildren;
1265     lineContexts.append(LineContext(crossAxisOffset, maxChildCrossAxisExtent, children.size(), maxAscent));
1266     crossAxisOffset += maxChildCrossAxisExtent;
1267 }
1268
1269 void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace)
1270 {
1271     auto position = style().resolvedJustifyContentPosition(contentAlignmentNormalBehaviorFlexibleBox());
1272     auto distribution = style().resolvedJustifyContentDistribution(contentAlignmentNormalBehaviorFlexibleBox());
1273
1274     // This is similar to the logic in layoutAndPlaceChildren, except we place the children
1275     // starting from the end of the flexbox. We also don't need to layout anything since we're
1276     // just moving the children to a new position.
1277     size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren(children);
1278     LayoutUnit mainAxisOffset = logicalHeight() - flowAwareBorderEnd() - flowAwarePaddingEnd();
1279     mainAxisOffset -= initialJustifyContentOffset(availableFreeSpace, position, distribution, numberOfChildrenForJustifyContent);
1280     mainAxisOffset -= isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
1281
1282     size_t seenInFlowPositionedChildren = 0;
1283     for (size_t i = 0; i < children.size(); ++i) {
1284         RenderBox& child = *children[i];
1285         if (child.isOutOfFlowPositioned()) {
1286             child.layer()->setStaticBlockPosition(mainAxisOffset);
1287             continue;
1288         }
1289         mainAxisOffset -= mainAxisExtentForChild(child) + flowAwareMarginEndForChild(child);
1290
1291         setFlowAwareLocationForChild(child, LayoutPoint(mainAxisOffset, crossAxisOffset + flowAwareMarginBeforeForChild(child)));
1292
1293         mainAxisOffset -= flowAwareMarginStartForChild(child);
1294
1295         ++seenInFlowPositionedChildren;
1296         if (seenInFlowPositionedChildren < numberOfChildrenForJustifyContent)
1297             mainAxisOffset -= justifyContentSpaceBetweenChildren(availableFreeSpace, distribution, numberOfChildrenForJustifyContent);
1298     }
1299 }
1300
1301 static LayoutUnit initialAlignContentOffset(LayoutUnit availableFreeSpace, ContentPosition alignContent, ContentDistributionType alignContentDistribution, unsigned numberOfLines)
1302 {
1303     if (alignContent == ContentPositionFlexEnd)
1304         return availableFreeSpace;
1305     if (alignContent == ContentPositionCenter)
1306         return availableFreeSpace / 2;
1307     if (alignContentDistribution == ContentDistributionSpaceAround) {
1308         if (availableFreeSpace > 0 && numberOfLines)
1309             return availableFreeSpace / (2 * numberOfLines);
1310         if (availableFreeSpace < 0)
1311             return availableFreeSpace / 2;
1312     }
1313     return 0;
1314 }
1315
1316 static LayoutUnit alignContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, ContentDistributionType alignContentDistribution, unsigned numberOfLines)
1317 {
1318     if (availableFreeSpace > 0 && numberOfLines > 1) {
1319         if (alignContentDistribution == ContentDistributionSpaceBetween)
1320             return availableFreeSpace / (numberOfLines - 1);
1321         if (alignContentDistribution == ContentDistributionSpaceAround || alignContentDistribution == ContentDistributionStretch)
1322             return availableFreeSpace / numberOfLines;
1323     }
1324     return 0;
1325 }
1326
1327 void RenderFlexibleBox::alignFlexLines(Vector<LineContext>& lineContexts)
1328 {
1329     ContentPosition position = style().resolvedAlignContentPosition(contentAlignmentNormalBehaviorFlexibleBox());
1330     ContentDistributionType distribution = style().resolvedAlignContentDistribution(contentAlignmentNormalBehaviorFlexibleBox());
1331
1332     if (!isMultiline() || position == ContentPositionFlexStart)
1333         return;
1334
1335     LayoutUnit availableCrossAxisSpace = crossAxisContentExtent();
1336     for (size_t i = 0; i < lineContexts.size(); ++i)
1337         availableCrossAxisSpace -= lineContexts[i].crossAxisExtent;
1338
1339     RenderBox* child = m_orderIterator.first();
1340     LayoutUnit lineOffset = initialAlignContentOffset(availableCrossAxisSpace, position, distribution, lineContexts.size());
1341     for (unsigned lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1342         lineContexts[lineNumber].crossAxisOffset += lineOffset;
1343         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next())
1344             adjustAlignmentForChild(*child, lineOffset);
1345
1346         if (distribution == ContentDistributionStretch && availableCrossAxisSpace > 0)
1347             lineContexts[lineNumber].crossAxisExtent += availableCrossAxisSpace / static_cast<unsigned>(lineContexts.size());
1348
1349         lineOffset += alignContentSpaceBetweenChildren(availableCrossAxisSpace, distribution, lineContexts.size());
1350     }
1351 }
1352
1353 void RenderFlexibleBox::adjustAlignmentForChild(RenderBox& child, LayoutUnit delta)
1354 {
1355     if (child.isOutOfFlowPositioned()) {
1356         LayoutUnit staticInlinePosition = child.layer()->staticInlinePosition();
1357         LayoutUnit staticBlockPosition = child.layer()->staticBlockPosition();
1358         LayoutUnit mainAxis = isColumnFlow() ? staticBlockPosition : staticInlinePosition;
1359         LayoutUnit crossAxis = isColumnFlow() ? staticInlinePosition : staticBlockPosition;
1360         crossAxis += delta;
1361         prepareChildForPositionedLayout(child, mainAxis, crossAxis, NoFlipForRowReverse);
1362         return;
1363     }
1364
1365     setFlowAwareLocationForChild(child, flowAwareLocationForChild(child) + LayoutSize(0, delta));
1366 }
1367
1368 void RenderFlexibleBox::alignChildren(const Vector<LineContext>& lineContexts)
1369 {
1370     // Keep track of the space between the baseline edge and the after edge of the box for each line.
1371     Vector<LayoutUnit> minMarginAfterBaselines;
1372
1373     RenderBox* child = m_orderIterator.first();
1374     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1375         LayoutUnit minMarginAfterBaseline = LayoutUnit::max();
1376         LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
1377         LayoutUnit maxAscent = lineContexts[lineNumber].maxAscent;
1378
1379         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
1380             ASSERT(child);
1381             if (child->isOutOfFlowPositioned()) {
1382                 if (style().flexWrap() == FlexWrapReverse)
1383                     adjustAlignmentForChild(*child, lineCrossAxisExtent);
1384                 continue;
1385             }
1386
1387             if (updateAutoMarginsInCrossAxis(*child, std::max(LayoutUnit::fromPixel(0), availableAlignmentSpaceForChild(lineCrossAxisExtent, *child))))
1388                 continue;
1389
1390             switch (alignmentForChild(*child)) {
1391             case ItemPositionAuto:
1392             case ItemPositionNormal:
1393                 ASSERT_NOT_REACHED();
1394                 break;
1395             case ItemPositionStart:
1396                 // FIXME: https://webkit.org/b/135460 - The extended grammar is not supported
1397                 // yet for FlexibleBox.
1398                 // Defaulting to Stretch for now, as it what most of FlexBox based renders
1399                 // expect as default.
1400             case ItemPositionStretch: {
1401                 applyStretchAlignmentToChild(*child, lineCrossAxisExtent);
1402                 // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
1403                 if (style().flexWrap() == FlexWrapReverse)
1404                     adjustAlignmentForChild(*child, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child));
1405                 break;
1406             }
1407             case ItemPositionFlexStart:
1408                 break;
1409             case ItemPositionFlexEnd:
1410                 adjustAlignmentForChild(*child, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child));
1411                 break;
1412             case ItemPositionCenter:
1413                 adjustAlignmentForChild(*child, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child) / 2);
1414                 break;
1415             case ItemPositionBaseline: {
1416                 // FIXME: If we get here in columns, we want the use the descent, except we currently can't get the ascent/descent of orthogonal children.
1417                 // https://bugs.webkit.org/show_bug.cgi?id=98076
1418                 LayoutUnit ascent = marginBoxAscentForChild(*child);
1419                 LayoutUnit startOffset = maxAscent - ascent;
1420                 adjustAlignmentForChild(*child, startOffset);
1421
1422                 if (style().flexWrap() == FlexWrapReverse)
1423                     minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child) - startOffset);
1424                 break;
1425             }
1426             case ItemPositionLastBaseline:
1427             case ItemPositionSelfStart:
1428             case ItemPositionSelfEnd:
1429             case ItemPositionEnd:
1430             case ItemPositionLeft:
1431             case ItemPositionRight:
1432                 // FIXME: https://webkit.org/b/135460 - The extended grammar is not supported
1433                 // yet for FlexibleBox.
1434             default:
1435                 ASSERT_NOT_REACHED();
1436                 break;
1437             }
1438         }
1439         minMarginAfterBaselines.append(minMarginAfterBaseline);
1440     }
1441
1442     if (style().flexWrap() != FlexWrapReverse)
1443         return;
1444
1445     // wrap-reverse flips the cross axis start and end. For baseline alignment, this means we
1446     // need to align the after edge of baseline elements with the after edge of the flex line.
1447     child = m_orderIterator.first();
1448     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1449         LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
1450         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
1451             ASSERT(child);
1452             if (alignmentForChild(*child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(*child) && minMarginAfterBaseline)
1453                 adjustAlignmentForChild(*child, minMarginAfterBaseline);
1454         }
1455     }
1456 }
1457
1458 void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox& child, LayoutUnit lineCrossAxisExtent)
1459 {
1460     if (!isColumnFlow() && child.style().logicalHeight().isAuto()) {
1461         // FIXME: If the child has orthogonal flow, then it already has an override height set, so use it.
1462         if (!hasOrthogonalFlow(child)) {
1463             LayoutUnit stretchedLogicalHeight = child.logicalHeight() + availableAlignmentSpaceForChild(lineCrossAxisExtent, child);
1464             ASSERT(!child.needsLayout());
1465             LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(stretchedLogicalHeight, child.logicalHeight() - child.borderAndPaddingLogicalHeight());
1466
1467             // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
1468             if (desiredLogicalHeight != child.logicalHeight()) {
1469                 child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.borderAndPaddingLogicalHeight());
1470                 child.setLogicalHeight(0);
1471                 child.setChildNeedsLayout(MarkOnlyThis);
1472                 child.layout();
1473             }
1474         }
1475     } else if (isColumnFlow() && child.style().logicalWidth().isAuto()) {
1476         // FIXME: If the child doesn't have orthogonal flow, then it already has an override width set, so use it.
1477         if (hasOrthogonalFlow(child)) {
1478             LayoutUnit childWidth = std::max<LayoutUnit>(0, lineCrossAxisExtent - crossAxisMarginExtentForChild(child));
1479             childWidth = child.constrainLogicalWidthInRegionByMinMax(childWidth, childWidth, *this);
1480
1481             if (childWidth != child.logicalWidth()) {
1482                 child.setOverrideLogicalContentWidth(childWidth - child.borderAndPaddingLogicalWidth());
1483                 child.setChildNeedsLayout(MarkOnlyThis);
1484                 child.layout();
1485             }
1486         }
1487     }
1488 }
1489
1490 void RenderFlexibleBox::flipForRightToLeftColumn()
1491 {
1492     if (style().isLeftToRightDirection() || !isColumnFlow())
1493         return;
1494
1495     LayoutUnit crossExtent = crossAxisExtent();
1496     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
1497         if (child->isOutOfFlowPositioned())
1498             continue;
1499         LayoutPoint location = flowAwareLocationForChild(*child);
1500         location.setY(crossExtent - crossAxisExtentForChild(*child) - location.y());
1501         setFlowAwareLocationForChild(*child, location);
1502     }
1503 }
1504
1505 void RenderFlexibleBox::flipForWrapReverse(const Vector<LineContext>& lineContexts, LayoutUnit crossAxisStartEdge)
1506 {
1507     LayoutUnit contentExtent = crossAxisContentExtent();
1508     RenderBox* child = m_orderIterator.first();
1509     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1510         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
1511             ASSERT(child);
1512             LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
1513             LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge;
1514             LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxisExtent;
1515             adjustAlignmentForChild(*child, newOffset - originalOffset);
1516         }
1517     }
1518 }
1519
1520 bool RenderFlexibleBox::isTopLayoutOverflowAllowed() const
1521 {
1522     bool hasTopOverflow = RenderBlock::isTopLayoutOverflowAllowed();
1523     if (hasTopOverflow || !style().isReverseFlexDirection())
1524         return hasTopOverflow;
1525     
1526     return !isHorizontalFlow();
1527 }
1528
1529 bool RenderFlexibleBox::isLeftLayoutOverflowAllowed() const
1530 {
1531     bool hasLeftOverflow = RenderBlock::isLeftLayoutOverflowAllowed();
1532     if (hasLeftOverflow || !style().isReverseFlexDirection())
1533         return hasLeftOverflow;
1534     
1535     return isHorizontalFlow();
1536 }
1537
1538 }