caabbaa6a7ec3b38eeeff0dcee6fd47ba5cac215
[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
39 namespace WebCore {
40
41 // Normally, -1 and 0 are not valid in a HashSet, but these are relatively likely flex-order values. Instead,
42 // we make the two smallest int values invalid flex-order values (in the css parser code we clamp them to
43 // int min + 2).
44 struct RenderFlexibleBox::FlexOrderHashTraits : WTF::GenericHashTraits<int> {
45     static const bool emptyValueIsZero = false;
46     static int emptyValue() { return std::numeric_limits<int>::min(); }
47     static void constructDeletedValue(int& slot) { slot = std::numeric_limits<int>::min() + 1; }
48     static bool isDeletedValue(int value) { return value == std::numeric_limits<int>::min() + 1; }
49 };
50
51 class RenderFlexibleBox::FlexOrderIterator {
52 public:
53     FlexOrderIterator(RenderFlexibleBox* flexibleBox, const FlexOrderHashSet& flexOrderValues)
54         : m_flexibleBox(flexibleBox)
55         , m_currentChild(0)
56         , m_orderValuesIterator(0)
57     {
58         copyToVector(flexOrderValues, m_orderValues);
59         std::sort(m_orderValues.begin(), m_orderValues.end());
60         first();
61     }
62
63     RenderBox* currentChild() { return m_currentChild; }
64
65     RenderBox* first()
66     {
67         reset();
68         return next();
69     }
70
71     RenderBox* next()
72     {
73         do {
74             if (!m_currentChild) {
75                 if (m_orderValuesIterator == m_orderValues.end())
76                     return 0;
77                 if (m_orderValuesIterator) {
78                     ++m_orderValuesIterator;
79                     if (m_orderValuesIterator == m_orderValues.end())
80                         return 0;
81                 } else
82                     m_orderValuesIterator = m_orderValues.begin();
83
84                 m_currentChild = m_flexibleBox->firstChildBox();
85             } else
86                 m_currentChild = m_currentChild->nextSiblingBox();
87         } while (!m_currentChild || m_currentChild->style()->flexOrder() != *m_orderValuesIterator);
88
89         return m_currentChild;
90     }
91
92     void reset()
93     {
94         m_currentChild = 0;
95         m_orderValuesIterator = 0;
96     }
97
98 private:
99     RenderFlexibleBox* m_flexibleBox;
100     RenderBox* m_currentChild;
101     Vector<int> m_orderValues;
102     Vector<int>::const_iterator m_orderValuesIterator;
103 };
104
105 struct RenderFlexibleBox::LineContext {
106     LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t numberOfChildren, LayoutUnit maxAscent)
107         : crossAxisOffset(crossAxisOffset)
108         , crossAxisExtent(crossAxisExtent)
109         , numberOfChildren(numberOfChildren)
110         , maxAscent(maxAscent)
111     {
112     }
113
114     LayoutUnit crossAxisOffset;
115     LayoutUnit crossAxisExtent;
116     size_t numberOfChildren;
117     LayoutUnit maxAscent;
118 };
119
120 struct RenderFlexibleBox::Violation {
121     Violation(RenderBox* child, LayoutUnit childSize)
122         : child(child)
123         , childSize(childSize)
124     {
125     }
126
127     RenderBox* child;
128     LayoutUnit childSize;
129 };
130
131
132 RenderFlexibleBox::RenderFlexibleBox(Node* node)
133     : RenderBlock(node)
134 {
135     setChildrenInline(false); // All of our children must be block-level.
136 }
137
138 RenderFlexibleBox::~RenderFlexibleBox()
139 {
140 }
141
142 const char* RenderFlexibleBox::renderName() const
143 {
144     return "RenderFlexibleBox";
145 }
146
147 static LayoutUnit marginLogicalWidthForChild(RenderBox* child, RenderStyle* parentStyle)
148 {
149     // A margin has three types: fixed, percentage, and auto (variable).
150     // Auto and percentage margins become 0 when computing min/max width.
151     // Fixed margins can be added in as is.
152     Length marginLeft = child->style()->marginStartUsing(parentStyle);
153     Length marginRight = child->style()->marginEndUsing(parentStyle);
154     LayoutUnit margin = 0;
155     if (marginLeft.isFixed())
156         margin += marginLeft.value();
157     if (marginRight.isFixed())
158         margin += marginRight.value();
159     return margin;
160 }
161
162 void RenderFlexibleBox::computePreferredLogicalWidths()
163 {
164     ASSERT(preferredLogicalWidthsDirty());
165
166     RenderStyle* styleToUse = style();
167     if (styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() > 0)
168         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(styleToUse->logicalWidth().value());
169     else {
170         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
171
172         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
173             if (child->isPositioned())
174                 continue;
175
176             LayoutUnit margin = marginLogicalWidthForChild(child, style());
177             bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
178             LayoutUnit minPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->minPreferredLogicalWidth();
179             LayoutUnit maxPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->maxPreferredLogicalWidth();
180             minPreferredLogicalWidth += margin;
181             maxPreferredLogicalWidth += margin;
182             if (!isColumnFlow()) {
183                 m_maxPreferredLogicalWidth += maxPreferredLogicalWidth;
184                 if (isMultiline()) {
185                     // For multiline, the min preferred width is if you put a break between each item.
186                     m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, minPreferredLogicalWidth);
187                 } else
188                     m_minPreferredLogicalWidth += minPreferredLogicalWidth;
189             } else {
190                 m_minPreferredLogicalWidth = std::max(minPreferredLogicalWidth, m_minPreferredLogicalWidth);
191                 if (isMultiline()) {
192                     // For multiline, the max preferred width is if you put a break between each item.
193                     m_maxPreferredLogicalWidth += maxPreferredLogicalWidth;
194                 } else
195                     m_maxPreferredLogicalWidth = std::max(maxPreferredLogicalWidth, m_maxPreferredLogicalWidth);
196             }
197         }
198
199         m_maxPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
200     }
201
202     LayoutUnit scrollbarWidth = 0;
203     if (hasOverflowClip()) {
204         if (isHorizontalWritingMode() && styleToUse->overflowY() == OSCROLL) {
205             layer()->setHasVerticalScrollbar(true);
206             scrollbarWidth = verticalScrollbarWidth();
207         } else if (!isHorizontalWritingMode() && styleToUse->overflowX() == OSCROLL) {
208             layer()->setHasHorizontalScrollbar(true);
209             scrollbarWidth = horizontalScrollbarHeight();
210         }
211     }
212
213     m_maxPreferredLogicalWidth += scrollbarWidth;
214     m_minPreferredLogicalWidth += scrollbarWidth;
215
216     if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
217         m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMinWidth().value()));
218         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMinWidth().value()));
219     }
220
221     if (styleToUse->logicalMaxWidth().isFixed()) {
222         m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMaxWidth().value()));
223         m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMaxWidth().value()));
224     }
225
226     LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
227     m_minPreferredLogicalWidth += borderAndPadding;
228     m_maxPreferredLogicalWidth += borderAndPadding;
229
230     setPreferredLogicalWidthsDirty(false);
231 }
232
233 void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
234 {
235     ASSERT(needsLayout());
236
237     if (!relayoutChildren && simplifiedLayout())
238         return;
239
240     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
241     LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
242
243     if (inRenderFlowThread()) {
244         // Regions changing widths can force us to relayout our children.
245         if (logicalWidthChangedInRegions())
246             relayoutChildren = true;
247     }
248     computeInitialRegionRangeForBlock();
249
250     IntSize previousSize = size();
251
252     setLogicalHeight(0);
253     // We need to call both of these because we grab both crossAxisExtent and mainAxisExtent in layoutFlexItems.
254     computeLogicalWidth();
255     computeLogicalHeight();
256
257     m_overflow.clear();
258
259     // For overflow:scroll blocks, ensure we have both scrollbars in place always.
260     if (scrollsOverflow()) {
261         if (style()->overflowX() == OSCROLL)
262             layer()->setHasHorizontalScrollbar(true);
263         if (style()->overflowY() == OSCROLL)
264             layer()->setHasVerticalScrollbar(true);
265     }
266
267     layoutFlexItems(relayoutChildren);
268
269     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
270     computeLogicalHeight();
271
272     if (size() != previousSize)
273         relayoutChildren = true;
274
275     layoutPositionedObjects(relayoutChildren || isRoot());
276
277     computeRegionRangeForBlock();
278
279     // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
280     computeOverflow(oldClientAfterEdge);
281     statePusher.pop();
282
283     updateLayerTransform();
284
285     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
286     // we overflow or not.
287     updateScrollInfoAfterLayout();
288
289     repainter.repaintAfterLayout();
290
291     setNeedsLayout(false);
292 }
293
294 bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox* child) const
295 {
296     // FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
297     return isHorizontalFlow() != child->isHorizontalWritingMode();
298 }
299
300 bool RenderFlexibleBox::isColumnFlow() const
301 {
302     return style()->isColumnFlexDirection();
303 }
304
305 bool RenderFlexibleBox::isHorizontalFlow() const
306 {
307     if (isHorizontalWritingMode())
308         return !isColumnFlow();
309     return isColumnFlow();
310 }
311
312 bool RenderFlexibleBox::isLeftToRightFlow() const
313 {
314     if (isColumnFlow())
315         return style()->writingMode() == TopToBottomWritingMode || style()->writingMode() == LeftToRightWritingMode;
316     return style()->isLeftToRightDirection() ^ (style()->flexDirection() == FlowRowReverse);
317 }
318
319 bool RenderFlexibleBox::isMultiline() const
320 {
321     return style()->flexWrap() != FlexWrapNone;
322 }
323
324 Length RenderFlexibleBox::mainAxisLengthForChild(RenderBox* child) const
325 {
326     return isHorizontalFlow() ? child->style()->width() : child->style()->height();
327 }
328
329 Length RenderFlexibleBox::crossAxisLength() const
330 {
331     return isHorizontalFlow() ? style()->height() : style()->width();
332 }
333
334 void RenderFlexibleBox::setCrossAxisExtent(LayoutUnit extent)
335 {
336     if (isHorizontalFlow())
337         setHeight(extent);
338     else
339         setWidth(extent);
340 }
341
342 LayoutUnit RenderFlexibleBox::crossAxisExtentForChild(RenderBox* child)
343 {
344     return isHorizontalFlow() ? child->height() : child->width();
345 }
346
347 LayoutUnit RenderFlexibleBox::mainAxisExtentForChild(RenderBox* child)
348 {
349     return isHorizontalFlow() ? child->width() : child->height();
350 }
351
352 LayoutUnit RenderFlexibleBox::crossAxisExtent() const
353 {
354     return isHorizontalFlow() ? height() : width();
355 }
356
357 LayoutUnit RenderFlexibleBox::mainAxisExtent() const
358 {
359     return isHorizontalFlow() ? width() : height();
360 }
361
362 LayoutUnit RenderFlexibleBox::crossAxisContentExtent() const
363 {
364     return isHorizontalFlow() ? contentHeight() : contentWidth();
365 }
366
367 LayoutUnit RenderFlexibleBox::mainAxisContentExtent() const
368 {
369     return isHorizontalFlow() ? contentWidth() : contentHeight();
370 }
371
372 WritingMode RenderFlexibleBox::transformedWritingMode() const
373 {
374     WritingMode mode = style()->writingMode();
375     if (!isColumnFlow())
376         return mode;
377
378     switch (mode) {
379     case TopToBottomWritingMode:
380     case BottomToTopWritingMode:
381         return style()->isLeftToRightDirection() ? LeftToRightWritingMode : RightToLeftWritingMode;
382     case LeftToRightWritingMode:
383     case RightToLeftWritingMode:
384         return style()->isLeftToRightDirection() ? TopToBottomWritingMode : BottomToTopWritingMode;
385     }
386     ASSERT_NOT_REACHED();
387     return TopToBottomWritingMode;
388 }
389
390 LayoutUnit RenderFlexibleBox::flowAwareBorderStart() const
391 {
392     if (isHorizontalFlow())
393         return isLeftToRightFlow() ? borderLeft() : borderRight();
394     return isLeftToRightFlow() ? borderTop() : borderBottom();
395 }
396
397 LayoutUnit RenderFlexibleBox::flowAwareBorderEnd() const
398 {
399     if (isHorizontalFlow())
400         return isLeftToRightFlow() ? borderRight() : borderLeft();
401     return isLeftToRightFlow() ? borderBottom() : borderTop();
402 }
403
404 LayoutUnit RenderFlexibleBox::flowAwareBorderBefore() const
405 {
406     switch (transformedWritingMode()) {
407     case TopToBottomWritingMode:
408         return borderTop();
409     case BottomToTopWritingMode:
410         return borderBottom();
411     case LeftToRightWritingMode:
412         return borderLeft();
413     case RightToLeftWritingMode:
414         return borderRight();
415     }
416     ASSERT_NOT_REACHED();
417     return borderTop();
418 }
419
420 LayoutUnit RenderFlexibleBox::flowAwareBorderAfter() const
421 {
422     switch (transformedWritingMode()) {
423     case TopToBottomWritingMode:
424         return borderBottom();
425     case BottomToTopWritingMode:
426         return borderTop();
427     case LeftToRightWritingMode:
428         return borderRight();
429     case RightToLeftWritingMode:
430         return borderLeft();
431     }
432     ASSERT_NOT_REACHED();
433     return borderTop();
434 }
435
436 LayoutUnit RenderFlexibleBox::flowAwarePaddingStart() const
437 {
438     if (isHorizontalFlow())
439         return isLeftToRightFlow() ? paddingLeft() : paddingRight();
440     return isLeftToRightFlow() ? paddingTop() : paddingBottom();
441 }
442
443 LayoutUnit RenderFlexibleBox::flowAwarePaddingEnd() const
444 {
445     if (isHorizontalFlow())
446         return isLeftToRightFlow() ? paddingRight() : paddingLeft();
447     return isLeftToRightFlow() ? paddingBottom() : paddingTop();
448 }
449
450 LayoutUnit RenderFlexibleBox::flowAwarePaddingBefore() const
451 {
452     switch (transformedWritingMode()) {
453     case TopToBottomWritingMode:
454         return paddingTop();
455     case BottomToTopWritingMode:
456         return paddingBottom();
457     case LeftToRightWritingMode:
458         return paddingLeft();
459     case RightToLeftWritingMode:
460         return paddingRight();
461     }
462     ASSERT_NOT_REACHED();
463     return paddingTop();
464 }
465
466 LayoutUnit RenderFlexibleBox::flowAwarePaddingAfter() const
467 {
468     switch (transformedWritingMode()) {
469     case TopToBottomWritingMode:
470         return paddingBottom();
471     case BottomToTopWritingMode:
472         return paddingTop();
473     case LeftToRightWritingMode:
474         return paddingRight();
475     case RightToLeftWritingMode:
476         return paddingLeft();
477     }
478     ASSERT_NOT_REACHED();
479     return paddingTop();
480 }
481
482 LayoutUnit RenderFlexibleBox::flowAwareMarginStartForChild(RenderBox* child) const
483 {
484     if (isHorizontalFlow())
485         return isLeftToRightFlow() ? child->marginLeft() : child->marginRight();
486     return isLeftToRightFlow() ? child->marginTop() : child->marginBottom();
487 }
488
489 LayoutUnit RenderFlexibleBox::flowAwareMarginEndForChild(RenderBox* child) const
490 {
491     if (isHorizontalFlow())
492         return isLeftToRightFlow() ? child->marginRight() : child->marginLeft();
493     return isLeftToRightFlow() ? child->marginBottom() : child->marginTop();
494 }
495
496 LayoutUnit RenderFlexibleBox::flowAwareMarginBeforeForChild(RenderBox* child) const
497 {
498     switch (transformedWritingMode()) {
499     case TopToBottomWritingMode:
500         return child->marginTop();
501     case BottomToTopWritingMode:
502         return child->marginBottom();
503     case LeftToRightWritingMode:
504         return child->marginLeft();
505     case RightToLeftWritingMode:
506         return child->marginRight();
507     }
508     ASSERT_NOT_REACHED();
509     return marginTop();
510 }
511
512 LayoutUnit RenderFlexibleBox::flowAwareMarginAfterForChild(RenderBox* child) const
513 {
514     switch (transformedWritingMode()) {
515     case TopToBottomWritingMode:
516         return child->marginBottom();
517     case BottomToTopWritingMode:
518         return child->marginTop();
519     case LeftToRightWritingMode:
520         return child->marginRight();
521     case RightToLeftWritingMode:
522         return child->marginLeft();
523     }
524     ASSERT_NOT_REACHED();
525     return marginBottom();
526 }
527
528 LayoutUnit RenderFlexibleBox::crossAxisMarginExtentForChild(RenderBox* child) const
529 {
530     return isHorizontalFlow() ? child->marginHeight() : child->marginWidth();
531 }
532
533 LayoutUnit RenderFlexibleBox::crossAxisScrollbarExtent() const
534 {
535     return isHorizontalFlow() ? horizontalScrollbarHeight() : verticalScrollbarWidth();
536 }
537
538 LayoutPoint RenderFlexibleBox::flowAwareLocationForChild(RenderBox* child) const
539 {
540     return isHorizontalFlow() ? child->location() : child->location().transposedPoint();
541 }
542
543 void RenderFlexibleBox::setFlowAwareLocationForChild(RenderBox* child, const LayoutPoint& location)
544 {
545     if (isHorizontalFlow())
546         child->setLocation(location);
547     else
548         child->setLocation(location.transposedPoint());
549 }
550
551 LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox* child) const
552 {
553     return isHorizontalFlow() ? child->borderAndPaddingWidth() : child->borderAndPaddingHeight();
554 }
555
556 LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox* child) const
557 {
558     return isHorizontalFlow() ? child->verticalScrollbarWidth() : child->horizontalScrollbarHeight();
559 }
560
561 LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* child) const
562 {
563     Length mainAxisLength = mainAxisLengthForChild(child);
564     if (mainAxisLength.isAuto()) {
565         LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth();
566         return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
567     }
568     return miminumValueForLength(mainAxisLength, mainAxisContentExtent());
569 }
570
571 LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent)
572 {
573     if (!isColumnFlow())
574         return mainAxisContentExtent() - preferredMainAxisExtent;
575
576     if (hasOverrideHeight())
577         return overrideHeight();
578
579     LayoutUnit heightResult = computeContentLogicalHeightUsing(style()->logicalHeight());
580     if (heightResult == -1)
581         heightResult = preferredMainAxisExtent;
582     LayoutUnit minHeight = computeContentLogicalHeightUsing(style()->logicalMinHeight()); // Leave as -1 if unset.
583     LayoutUnit maxHeight = style()->logicalMaxHeight().isUndefined() ? heightResult : computeContentLogicalHeightUsing(style()->logicalMaxHeight());
584     if (maxHeight == -1)
585         maxHeight = heightResult;
586     heightResult = std::min(maxHeight, heightResult);
587     heightResult = std::max(minHeight, heightResult);
588
589     return heightResult - preferredMainAxisExtent;
590 }
591
592 void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren)
593 {
594     FlexOrderHashSet flexOrderValues;
595     computeMainAxisPreferredSizes(relayoutChildren, flexOrderValues);
596
597     OrderedFlexItemList orderedChildren;
598     LayoutUnit preferredMainAxisExtent;
599     float totalPositiveFlexibility;
600     float totalNegativeFlexibility;
601     LayoutUnit minMaxAppliedMainAxisExtent;
602     WTF::Vector<LineContext> lineContexts;
603     FlexOrderIterator flexIterator(this, flexOrderValues);
604
605     LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
606     while (computeNextFlexLine(flexIterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalNegativeFlexibility, minMaxAppliedMainAxisExtent)) {
607         LayoutUnit availableFreeSpace = computeAvailableFreeSpace(preferredMainAxisExtent);
608         FlexSign flexSign = (minMaxAppliedMainAxisExtent < preferredMainAxisExtent + availableFreeSpace) ? PositiveFlexibility : NegativeFlexibility;
609         InflexibleFlexItemSize inflexibleItems;
610         WTF::Vector<LayoutUnit> childSizes;
611         while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems, childSizes)) {
612             ASSERT(totalPositiveFlexibility >= 0 && totalNegativeFlexibility >= 0);
613             ASSERT(inflexibleItems.size() > 0);
614         }
615
616         layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, lineContexts);
617     }
618 //
619     alignChildren(flexIterator, lineContexts);
620
621     if (style()->flexWrap() == FlexWrapReverse)
622         flipForWrapReverse(flexIterator, lineContexts);
623
624     // direction:rtl + flex-direction:column means the cross-axis direction is flipped.
625     flipForRightToLeftColumn(flexIterator);
626 }
627
628 float RenderFlexibleBox::positiveFlexForChild(RenderBox* child) const
629 {
630     return isHorizontalFlow() ? child->style()->flexboxWidthPositiveFlex() : child->style()->flexboxHeightPositiveFlex();
631 }
632
633 float RenderFlexibleBox::negativeFlexForChild(RenderBox* child) const
634 {
635     return isHorizontalFlow() ? child->style()->flexboxWidthNegativeFlex() : child->style()->flexboxHeightNegativeFlex();
636 }
637
638 LayoutUnit RenderFlexibleBox::availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox* child)
639 {
640     LayoutUnit childCrossExtent = crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child);
641     return lineCrossAxisExtent - childCrossExtent;
642 }
643
644 LayoutUnit RenderFlexibleBox::marginBoxAscentForChild(RenderBox* child)
645 {
646     LayoutUnit ascent = child->firstLineBoxBaseline();
647     if (ascent == -1)
648         ascent = crossAxisExtentForChild(child) + flowAwareMarginAfterForChild(child);
649     return ascent + flowAwareMarginBeforeForChild(child);
650 }
651
652 void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, FlexOrderHashSet& flexOrderValues)
653 {
654     LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
655     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
656         flexOrderValues.add(child->style()->flexOrder());
657
658         if (child->isPositioned())
659             continue;
660
661         child->clearOverrideSize();
662         if (mainAxisLengthForChild(child).isAuto()) {
663             if (!relayoutChildren)
664                 child->setChildNeedsLayout(true);
665             child->layoutIfNeeded();
666         }
667
668         // We set the margins because we want to make sure 'auto' has a margin
669         // of 0 and because if we're not auto sizing, we don't do a layout that
670         // computes the start/end margins.
671         if (isHorizontalFlow()) {
672             child->setMarginLeft(miminumValueForLength(child->style()->marginLeft(), flexboxAvailableContentExtent));
673             child->setMarginRight(miminumValueForLength(child->style()->marginRight(), flexboxAvailableContentExtent));
674         } else {
675             child->setMarginTop(miminumValueForLength(child->style()->marginTop(), flexboxAvailableContentExtent));
676             child->setMarginBottom(miminumValueForLength(child->style()->marginBottom(), flexboxAvailableContentExtent));
677         }
678     }
679 }
680
681 LayoutUnit RenderFlexibleBox::lineBreakLength()
682 {
683     if (!isColumnFlow())
684         return mainAxisContentExtent();
685
686     LayoutUnit height = computeContentLogicalHeightUsing(style()->logicalHeight());
687     if (height == -1)
688         height = std::numeric_limits<LayoutUnit>::max();
689     LayoutUnit maxHeight = computeContentLogicalHeightUsing(style()->logicalMaxHeight());
690     if (maxHeight != -1)
691         height = std::min(height, maxHeight);
692     return height;
693 }
694
695 LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent)
696 {
697     Length max = isHorizontalFlow() ? child->style()->maxWidth() : child->style()->maxHeight();
698     Length min = isHorizontalFlow() ? child->style()->minWidth() : child->style()->minHeight();
699     // FIXME: valueForLength isn't quite right in quirks mode: percentage heights should check parents until a value is found.
700     // https://bugs.webkit.org/show_bug.cgi?id=81809
701     if (max.isSpecified() && childSize > valueForLength(max, flexboxAvailableContentExtent))
702         childSize = valueForLength(max, flexboxAvailableContentExtent);
703     if (min.isSpecified() && childSize < valueForLength(min, flexboxAvailableContentExtent))
704         childSize = valueForLength(min, flexboxAvailableContentExtent);
705     return childSize;
706 }
707
708 bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent)
709 {
710     orderedChildren.clear();
711     preferredMainAxisExtent = 0;
712     totalPositiveFlexibility = totalNegativeFlexibility = 0;
713     minMaxAppliedMainAxisExtent = 0;
714
715     if (!iterator.currentChild())
716         return false;
717
718     LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
719     LayoutUnit lineBreak = lineBreakLength();
720
721     for (RenderBox* child = iterator.currentChild(); child; child = iterator.next()) {
722         if (child->isPositioned()) {
723             orderedChildren.append(child);
724             continue;
725         }
726
727         LayoutUnit childMainAxisExtent = preferredMainAxisContentExtentForChild(child);
728         LayoutUnit childMainAxisMarginBoxExtent = mainAxisBorderAndPaddingExtentForChild(child) + childMainAxisExtent;
729         childMainAxisMarginBoxExtent += isHorizontalFlow() ? child->marginWidth() : child->marginHeight();
730
731         if (isMultiline() && preferredMainAxisExtent + childMainAxisMarginBoxExtent > lineBreak && orderedChildren.size() > 0)
732             break;
733         orderedChildren.append(child);
734         preferredMainAxisExtent += childMainAxisMarginBoxExtent;
735         totalPositiveFlexibility += positiveFlexForChild(child);
736         totalNegativeFlexibility += negativeFlexForChild(child);
737
738         LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(child, childMainAxisExtent, flexboxAvailableContentExtent);
739         minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent - childMainAxisExtent + childMainAxisMarginBoxExtent;
740     }
741     return true;
742 }
743
744 void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
745 {
746     for (size_t i = 0; i < violations.size(); ++i) {
747         RenderBox* child = violations[i].child;
748         LayoutUnit childSize = violations[i].childSize;
749         availableFreeSpace -= childSize - preferredMainAxisContentExtentForChild(child);
750         totalPositiveFlexibility -= positiveFlexForChild(child);
751         totalNegativeFlexibility -= negativeFlexForChild(child);
752         inflexibleItems.set(child, childSize);
753     }
754 }
755
756 // Returns true if we successfully ran the algorithm and sized the flex items.
757 bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes)
758 {
759     childSizes.clear();
760
761     LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
762     LayoutUnit totalViolation = 0;
763     WTF::Vector<Violation> minViolations;
764     WTF::Vector<Violation> maxViolations;
765     for (size_t i = 0; i < children.size(); ++i) {
766         RenderBox* child = children[i];
767         if (child->isPositioned()) {
768             childSizes.append(0);
769             continue;
770         }
771
772         if (inflexibleItems.contains(child))
773             childSizes.append(inflexibleItems.get(child));
774         else {
775             LayoutUnit childSize = preferredMainAxisContentExtentForChild(child);
776             if (availableFreeSpace > 0 && totalPositiveFlexibility > 0 && flexSign == PositiveFlexibility)
777                 childSize += lroundf(availableFreeSpace * positiveFlexForChild(child) / totalPositiveFlexibility);
778             else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0  && flexSign == NegativeFlexibility)
779                 childSize += lroundf(availableFreeSpace * negativeFlexForChild(child) / totalNegativeFlexibility);
780
781             LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize, flexboxAvailableContentExtent);
782             childSizes.append(adjustedChildSize);
783
784             LayoutUnit violation = adjustedChildSize - childSize;
785             if (violation > 0)
786                 minViolations.append(Violation(child, adjustedChildSize));
787             else if (violation < 0)
788                 maxViolations.append(Violation(child, adjustedChildSize));
789             totalViolation += violation;
790         }
791     }
792
793     if (totalViolation)
794         freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems);
795     return !totalViolation;
796 }
797
798 static LayoutUnit initialPackingOffset(LayoutUnit availableFreeSpace, EFlexPack flexPack, size_t numberOfChildren)
799 {
800     if (availableFreeSpace > 0) {
801         if (flexPack == PackEnd)
802             return availableFreeSpace;
803         if (flexPack == PackCenter)
804             return availableFreeSpace / 2;
805         if (flexPack == PackDistribute && numberOfChildren)
806             return availableFreeSpace / (2 * numberOfChildren);
807     } else if (availableFreeSpace < 0) {
808         if (flexPack == PackCenter || flexPack == PackDistribute)
809             return availableFreeSpace / 2;
810     }
811     return 0;
812 }
813
814 static LayoutUnit packingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFlexPack flexPack, size_t numberOfChildren)
815 {
816     if (availableFreeSpace > 0 && numberOfChildren > 1) {
817         if (flexPack == PackJustify)
818             return availableFreeSpace / (numberOfChildren - 1);
819         if (flexPack == PackDistribute)
820             return availableFreeSpace / numberOfChildren;
821     }
822     return 0;
823 }
824
825 void RenderFlexibleBox::setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize)
826 {
827     // FIXME: Rename setOverrideWidth/setOverrideHeight to setOverrideLogicalWidth/setOverrideLogicalHeight.
828     if (hasOrthogonalFlow(child))
829         child->setOverrideHeight(childPreferredSize);
830     else
831         child->setOverrideWidth(childPreferredSize);
832 }
833
834 void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset)
835 {
836     ASSERT(child->isPositioned());
837     child->containingBlock()->insertPositionedObject(child);
838     RenderLayer* childLayer = child->layer();
839     LayoutUnit inlinePosition = isColumnFlow() ? crossAxisOffset : mainAxisOffset;
840     if (style()->flexDirection() == FlowRowReverse)
841         inlinePosition = mainAxisExtent() - mainAxisOffset;
842     childLayer->setStaticInlinePosition(inlinePosition); // FIXME: Not right for regions.
843
844     LayoutUnit staticBlockPosition = isColumnFlow() ? mainAxisOffset : crossAxisOffset;
845     if (childLayer->staticBlockPosition() != staticBlockPosition) {
846         childLayer->setStaticBlockPosition(staticBlockPosition);
847         if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
848             child->setChildNeedsLayout(true, false);
849     }
850 }
851
852 static EFlexAlign flexAlignForChild(RenderBox* child)
853 {
854     EFlexAlign align = child->style()->flexItemAlign();
855     if (align == AlignAuto)
856         align = child->parent()->style()->flexAlign();
857
858     if (child->parent()->style()->flexWrap() == FlexWrapReverse) {
859         if (align == AlignStart)
860             align = AlignEnd;
861         else if (align == AlignEnd)
862             align = AlignStart;
863     }
864
865     return align;
866 }
867
868 void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, WTF::Vector<LineContext>& lineContexts)
869 {
870     ASSERT(childSizes.size() == children.size());
871     LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
872     mainAxisOffset += initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size());
873     if (style()->flexDirection() == FlowRowReverse)
874         mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
875
876     LayoutUnit totalMainExtent = mainAxisExtent();
877     LayoutUnit maxAscent = 0, maxDescent = 0; // Used when flex-align: baseline.
878     LayoutUnit maxChildCrossAxisExtent = 0;
879     bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow();
880     for (size_t i = 0; i < children.size(); ++i) {
881         RenderBox* child = children[i];
882         if (child->isPositioned()) {
883             prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset);
884             mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size());
885             continue;
886         }
887         LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child);
888         setLogicalOverrideSize(child, childPreferredSize);
889         child->setChildNeedsLayout(true);
890         child->layoutIfNeeded();
891
892         LayoutUnit childCrossAxisMarginBoxExtent;
893         if (flexAlignForChild(child) == AlignBaseline) {
894             LayoutUnit ascent = marginBoxAscentForChild(child);
895             LayoutUnit descent = (crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child)) - ascent;
896
897             maxAscent = std::max(maxAscent, ascent);
898             maxDescent = std::max(maxDescent, descent);
899
900             childCrossAxisMarginBoxExtent = maxAscent + maxDescent;
901         } else
902             childCrossAxisMarginBoxExtent = crossAxisExtentForChild(child) + crossAxisMarginExtentForChild(child);
903         if (!isColumnFlow() && style()->logicalHeight().isAuto())
904             setLogicalHeight(std::max(logicalHeight(), crossAxisOffset + flowAwareBorderAfter() + flowAwarePaddingAfter() + childCrossAxisMarginBoxExtent + crossAxisScrollbarExtent()));
905         maxChildCrossAxisExtent = std::max(maxChildCrossAxisExtent, childCrossAxisMarginBoxExtent);
906
907         mainAxisOffset += flowAwareMarginStartForChild(child);
908
909         LayoutUnit childMainExtent = mainAxisExtentForChild(child);
910         IntPoint childLocation(shouldFlipMainAxis ? totalMainExtent - mainAxisOffset - childMainExtent : mainAxisOffset,
911             crossAxisOffset + flowAwareMarginBeforeForChild(child));
912
913         // FIXME: Supporting layout deltas.
914         setFlowAwareLocationForChild(child, childLocation);
915         mainAxisOffset += childMainExtent + flowAwareMarginEndForChild(child);
916
917         mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size());
918     }
919
920     if (isColumnFlow())
921         setLogicalHeight(mainAxisOffset + flowAwareBorderEnd() + flowAwarePaddingEnd() + scrollbarLogicalHeight());
922
923     if (style()->flexDirection() == FlowColumnReverse) {
924         // We have to do an extra pass for column-reverse to reposition the flex items since the start depends
925         // on the height of the flexbox, which we only know after we've positioned all the flex items.
926         computeLogicalHeight();
927         layoutColumnReverse(children, childSizes, crossAxisOffset, availableFreeSpace);
928     }
929
930     LayoutUnit lineCrossAxisExtent = isMultiline() ? maxChildCrossAxisExtent : crossAxisContentExtent();
931     lineContexts.append(LineContext(crossAxisOffset, lineCrossAxisExtent, children.size(), maxAscent));
932     crossAxisOffset += lineCrossAxisExtent;
933 }
934
935 void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace)
936 {
937     // This is similar to the logic in layoutAndPlaceChildren, except we place the children
938     // starting from the end of the flexbox. We also don't need to layout anything since we're
939     // just moving the children to a new position.
940     LayoutUnit mainAxisOffset = logicalHeight() - flowAwareBorderEnd() - flowAwarePaddingEnd();
941     mainAxisOffset -= initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size());
942     mainAxisOffset -= isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
943
944     for (size_t i = 0; i < children.size(); ++i) {
945         RenderBox* child = children[i];
946         if (child->isPositioned()) {
947             child->layer()->setStaticBlockPosition(mainAxisOffset);
948             mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size());
949             continue;
950         }
951         mainAxisOffset -= mainAxisExtentForChild(child) + flowAwareMarginEndForChild(child);
952
953         LayoutRect oldRect = child->frameRect();
954         setFlowAwareLocationForChild(child, IntPoint(mainAxisOffset, crossAxisOffset + flowAwareMarginBeforeForChild(child)));
955         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
956             child->repaintDuringLayoutIfMoved(oldRect);
957
958         mainAxisOffset -= flowAwareMarginStartForChild(child);
959         mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size());
960     }
961 }
962
963 void RenderFlexibleBox::adjustAlignmentForChild(RenderBox* child, LayoutUnit delta)
964 {
965     LayoutRect oldRect = child->frameRect();
966
967     setFlowAwareLocationForChild(child, flowAwareLocationForChild(child) + LayoutSize(0, delta));
968
969     // If the child moved, we have to repaint it as well as any floating/positioned
970     // descendants. An exception is if we need a layout. In this case, we know we're going to
971     // repaint ourselves (and the child) anyway.
972     if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
973         child->repaintDuringLayoutIfMoved(oldRect);
974 }
975
976 void RenderFlexibleBox::alignChildren(FlexOrderIterator& iterator, const WTF::Vector<LineContext>& lineContexts)
977 {
978     // Keep track of the space between the baseline edge and the after edge of the box for each line.
979     WTF::Vector<LayoutUnit> minMarginAfterBaselines;
980
981     RenderBox* child = iterator.first();
982     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
983         LayoutUnit minMarginAfterBaseline = std::numeric_limits<LayoutUnit>::max();
984         LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
985         LayoutUnit maxAscent = lineContexts[lineNumber].maxAscent;
986
987         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
988             ASSERT(child);
989             switch (flexAlignForChild(child)) {
990             case AlignAuto:
991                 ASSERT_NOT_REACHED();
992                 break;
993             case AlignStretch: {
994                 applyStretchAlignmentToChild(child, lineCrossAxisExtent);
995                 // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
996                 if (style()->flexWrap() == FlexWrapReverse)
997                     adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
998                 break;
999             }
1000             case AlignStart:
1001                 break;
1002             case AlignEnd:
1003                 adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
1004                 break;
1005             case AlignCenter:
1006                 adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) / 2);
1007                 break;
1008             case AlignBaseline: {
1009                 LayoutUnit ascent = marginBoxAscentForChild(child);
1010                 LayoutUnit startOffset = maxAscent - ascent;
1011                 adjustAlignmentForChild(child, startOffset);
1012
1013                 if (style()->flexWrap() == FlexWrapReverse)
1014                     minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) - startOffset);
1015                 break;
1016             }
1017             }
1018         }
1019         minMarginAfterBaselines.append(minMarginAfterBaseline);
1020     }
1021
1022     if (style()->flexWrap() != FlexWrapReverse)
1023         return;
1024
1025     // wrap-reverse flips the cross axis start and end. For baseline alignment, this means we
1026     // need to align the after edge of baseline elements with the after edge of the flex line.
1027     child = iterator.first();
1028     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1029         LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
1030         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
1031             ASSERT(child);
1032             if (flexAlignForChild(child) == AlignBaseline && minMarginAfterBaseline)
1033                 adjustAlignmentForChild(child, minMarginAfterBaseline);
1034         }
1035     }
1036 }
1037
1038 void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUnit lineCrossAxisExtent)
1039 {
1040     if (!isColumnFlow() && child->style()->logicalHeight().isAuto()) {
1041         LayoutUnit logicalHeightBefore = child->logicalHeight();
1042         LayoutUnit stretchedLogicalHeight = child->logicalHeight() + availableAlignmentSpaceForChild(lineCrossAxisExtent, child);
1043         if (stretchedLogicalHeight < logicalHeightBefore)
1044             return;
1045
1046         child->setLogicalHeight(stretchedLogicalHeight);
1047         child->computeLogicalHeight();
1048
1049         if (child->logicalHeight() != logicalHeightBefore) {
1050             child->setOverrideHeight(child->logicalHeight());
1051             child->setLogicalHeight(0);
1052             child->setChildNeedsLayout(true);
1053             child->layoutIfNeeded();
1054         }
1055     } else if (isColumnFlow() && child->style()->logicalWidth().isAuto() && isMultiline()) {
1056         // FIXME: Handle min-width and max-width.
1057         LayoutUnit childWidth = lineCrossAxisExtent - crossAxisMarginExtentForChild(child);
1058         child->setOverrideWidth(std::max(0, childWidth));
1059         child->setChildNeedsLayout(true);
1060         child->layoutIfNeeded();
1061     }
1062 }
1063
1064 void RenderFlexibleBox::flipForRightToLeftColumn(FlexOrderIterator& iterator)
1065 {
1066     if (style()->isLeftToRightDirection() || !isColumnFlow())
1067         return;
1068
1069     LayoutUnit crossExtent = crossAxisExtent();
1070     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
1071         LayoutPoint location = flowAwareLocationForChild(child);
1072         location.setY(crossExtent - crossAxisExtentForChild(child) - location.y());
1073         setFlowAwareLocationForChild(child, location);
1074     }
1075 }
1076
1077 void RenderFlexibleBox::flipForWrapReverse(FlexOrderIterator& iterator, const WTF::Vector<LineContext>& lineContexts)
1078 {
1079     if (!isColumnFlow())
1080         computeLogicalHeight();
1081
1082     LayoutUnit contentExtent = crossAxisContentExtent();
1083     RenderBox* child = iterator.first();
1084     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1085         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
1086             ASSERT(child);
1087             LayoutPoint location = flowAwareLocationForChild(child);
1088             LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
1089             LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - lineContexts[0].crossAxisOffset;
1090             LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxisExtent;
1091             location.setY(location.y() + newOffset - originalOffset);
1092
1093             LayoutRect oldRect = child->frameRect();
1094             setFlowAwareLocationForChild(child, location);
1095             if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
1096                 child->repaintDuringLayoutIfMoved(oldRect);
1097         }
1098     }
1099 }
1100
1101 }