82b75b18c67d31c86ae76fbec1187d6d84856559
[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 "RuntimeEnabledFeatures.h"
38 #include <limits>
39 #include <wtf/MathExtras.h>
40
41 namespace WebCore {
42
43 static constexpr ItemPosition selfAlignmentNormalBehaviorFlexibleBox = ItemPositionStretch;
44
45 struct RenderFlexibleBox::LineContext {
46     LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t numberOfChildren, LayoutUnit maxAscent)
47         : crossAxisOffset(crossAxisOffset)
48         , crossAxisExtent(crossAxisExtent)
49         , numberOfChildren(numberOfChildren)
50         , maxAscent(maxAscent)
51     {
52     }
53
54     LayoutUnit crossAxisOffset;
55     LayoutUnit crossAxisExtent;
56     size_t numberOfChildren;
57     LayoutUnit maxAscent;
58 };
59
60 struct RenderFlexibleBox::Violation {
61     Violation(RenderBox& child, LayoutUnit childSize)
62         : child(child)
63         , childSize(childSize)
64     {
65     }
66
67     RenderBox& child;
68     LayoutUnit childSize;
69 };
70
71
72 RenderFlexibleBox::RenderFlexibleBox(Element& element, RenderStyle&& style)
73     : RenderBlock(element, WTFMove(style), 0)
74     , m_orderIterator(*this)
75     , m_numberOfInFlowChildrenOnFirstLine(-1)
76 {
77     setChildrenInline(false); // All of our children must be block-level.
78 }
79
80 RenderFlexibleBox::RenderFlexibleBox(Document& document, RenderStyle&& style)
81     : RenderBlock(document, WTFMove(style), 0)
82     , m_orderIterator(*this)
83     , m_numberOfInFlowChildrenOnFirstLine(-1)
84 {
85     setChildrenInline(false); // All of our children must be block-level.
86 }
87
88 RenderFlexibleBox::~RenderFlexibleBox()
89 {
90 }
91
92 const char* RenderFlexibleBox::renderName() const
93 {
94     return "RenderFlexibleBox";
95 }
96
97 void RenderFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
98 {
99     // FIXME: We're ignoring flex-basis here and we shouldn't. We can't start honoring it though until
100     // the flex shorthand stops setting it to 0.
101     // See https://bugs.webkit.org/show_bug.cgi?id=116117,
102     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
103         if (child->isOutOfFlowPositioned())
104             continue;
105
106         LayoutUnit margin = marginIntrinsicLogicalWidthForChild(*child);
107         bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
108         LayoutUnit minPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->minPreferredLogicalWidth();
109         LayoutUnit maxPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->maxPreferredLogicalWidth();
110         minPreferredLogicalWidth += margin;
111         maxPreferredLogicalWidth += margin;
112         if (!isColumnFlow()) {
113             maxLogicalWidth += maxPreferredLogicalWidth;
114             if (isMultiline()) {
115                 // For multiline, the min preferred width is if you put a break between each item.
116                 minLogicalWidth = std::max(minLogicalWidth, minPreferredLogicalWidth);
117             } else
118                 minLogicalWidth += minPreferredLogicalWidth;
119         } else {
120             minLogicalWidth = std::max(minPreferredLogicalWidth, minLogicalWidth);
121             if (isMultiline()) {
122                 // For multiline, the max preferred width is if you never break between items.
123                 maxLogicalWidth += maxPreferredLogicalWidth;
124             } else
125                 maxLogicalWidth = std::max(maxPreferredLogicalWidth, maxLogicalWidth);
126         }
127     }
128
129     // Due to negative margins, it is possible that we calculated a negative intrinsic width.
130     // Make sure that we never return a negative width.
131     minLogicalWidth = std::max(LayoutUnit(), minLogicalWidth);
132     maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
133
134     LayoutUnit scrollbarWidth = intrinsicScrollbarLogicalWidth();
135     maxLogicalWidth += scrollbarWidth;
136     minLogicalWidth += scrollbarWidth;
137 }
138
139 void RenderFlexibleBox::computePreferredLogicalWidths()
140 {
141     ASSERT(preferredLogicalWidthsDirty());
142
143     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
144
145     const RenderStyle& styleToUse = style();
146     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for width.
147     if (styleToUse.logicalWidth().isFixed() && styleToUse.logicalWidth().value() > 0)
148         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalWidth().value());
149     else
150         computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
151
152     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for min-width.
153     if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
154         m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
155         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
156     }
157
158     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for maxWidth.
159     if (styleToUse.logicalMaxWidth().isFixed()) {
160         m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
161         m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
162     }
163
164     LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
165     m_minPreferredLogicalWidth += borderAndPadding;
166     m_maxPreferredLogicalWidth += borderAndPadding;
167
168     setPreferredLogicalWidthsDirty(false);
169 }
170
171 static int synthesizedBaselineFromContentBox(const RenderBox& box, LineDirectionMode direction)
172 {
173     return direction == HorizontalLine ? box.borderTop() + box.paddingTop() + box.contentHeight() : box.borderRight() + box.paddingRight() + box.contentWidth();
174 }
175
176 int RenderFlexibleBox::baselinePosition(FontBaseline, bool, LineDirectionMode direction, LinePositionMode) const
177 {
178     int baseline = firstLineBaseline().value_or(synthesizedBaselineFromContentBox(*this, direction));
179
180     int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
181     return baseline + marginAscent;
182 }
183
184 std::optional<int> RenderFlexibleBox::firstLineBaseline() const
185 {
186     if (isWritingModeRoot() || m_numberOfInFlowChildrenOnFirstLine <= 0)
187         return std::optional<int>();
188     RenderBox* baselineChild = nullptr;
189     int childNumber = 0;
190     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
191         if (child->isOutOfFlowPositioned())
192             continue;
193         if (alignmentForChild(*child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(*child)) {
194             baselineChild = child;
195             break;
196         }
197         if (!baselineChild)
198             baselineChild = child;
199
200         ++childNumber;
201         if (childNumber == m_numberOfInFlowChildrenOnFirstLine)
202             break;
203     }
204
205     if (!baselineChild)
206         return std::optional<int>();
207
208     if (!isColumnFlow() && hasOrthogonalFlow(*baselineChild))
209         return std::optional<int>(crossAxisExtentForChild(*baselineChild) + baselineChild->logicalTop());
210     if (isColumnFlow() && !hasOrthogonalFlow(*baselineChild))
211         return std::optional<int>(mainAxisExtentForChild(*baselineChild) + baselineChild->logicalTop());
212
213     std::optional<int> baseline = baselineChild->firstLineBaseline();
214     if (!baseline) {
215         // FIXME: We should pass |direction| into firstLineBoxBaseline and stop bailing out if we're a writing mode root.
216         // This would also fix some cases where the flexbox is orthogonal to its container.
217         LineDirectionMode direction = isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
218         return std::optional<int>(synthesizedBaselineFromContentBox(*baselineChild, direction) + baselineChild->logicalTop());
219     }
220
221     return std::optional<int>(baseline.value() + baselineChild->logicalTop());
222 }
223
224 std::optional<int> RenderFlexibleBox::inlineBlockBaseline(LineDirectionMode direction) const
225 {
226     if (std::optional<int> baseline = firstLineBaseline())
227         return baseline;
228
229     int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
230     return synthesizedBaselineFromContentBox(*this, direction) + marginAscent;
231 }
232
233 void RenderFlexibleBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
234 {
235     RenderBlock::styleDidChange(diff, oldStyle);
236
237     if (oldStyle && oldStyle->resolvedAlignItems(selfAlignmentNormalBehaviorFlexibleBox).position() == ItemPositionStretch && diff == StyleDifferenceLayout) {
238         // Flex items that were previously stretching need to be relayed out so we can compute new available cross axis space.
239         // This is only necessary for stretching since other alignment values don't change the size of the box.
240         auto& newStyle = style();
241         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
242             auto& childStyle = child->style();
243             auto previousAlignment = childStyle.resolvedAlignSelf(*oldStyle, selfAlignmentNormalBehaviorFlexibleBox).position();
244             if (previousAlignment == ItemPositionStretch && previousAlignment != childStyle.resolvedAlignSelf(newStyle, selfAlignmentNormalBehaviorFlexibleBox).position())
245                 child->setChildNeedsLayout(MarkOnlyThis);
246         }
247     }
248 }
249
250 void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
251 {
252     ASSERT(needsLayout());
253
254     if (!relayoutChildren && simplifiedLayout())
255         return;
256
257     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
258
259     if (recomputeLogicalWidth())
260         relayoutChildren = true;
261
262     LayoutUnit previousHeight = logicalHeight();
263     setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight());
264
265     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
266
267     preparePaginationBeforeBlockLayout(relayoutChildren);
268
269     m_numberOfInFlowChildrenOnFirstLine = -1;
270
271     beginUpdateScrollInfoAfterLayoutTransaction();
272
273     dirtyForLayoutFromPercentageHeightDescendants();
274
275     prepareOrderIteratorAndMargins();
276
277     ChildFrameRects oldChildRects;
278     appendChildFrameRects(oldChildRects);
279     Vector<LineContext> lineContexts;
280     layoutFlexItems(relayoutChildren, lineContexts);
281
282     updateLogicalHeight();
283     repositionLogicalHeightDependentFlexItems(lineContexts);
284
285     endAndCommitUpdateScrollInfoAfterLayoutTransaction();
286
287     if (logicalHeight() != previousHeight)
288         relayoutChildren = true;
289
290     layoutPositionedObjects(relayoutChildren || isDocumentElementRenderer());
291
292     repaintChildrenDuringLayoutIfMoved(oldChildRects);
293     // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
294     computeOverflow(clientLogicalBottomAfterRepositioning());
295     statePusher.pop();
296
297     updateLayerTransform();
298
299     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
300     // we overflow or not.
301     updateScrollInfoAfterLayout();
302
303     repainter.repaintAfterLayout();
304
305     clearNeedsLayout();
306 }
307
308 void RenderFlexibleBox::appendChildFrameRects(ChildFrameRects& childFrameRects)
309 {
310     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
311         if (!child->isOutOfFlowPositioned())
312             childFrameRects.append(child->frameRect());
313     }
314 }
315
316 void RenderFlexibleBox::repaintChildrenDuringLayoutIfMoved(const ChildFrameRects& oldChildRects)
317 {
318     size_t childIndex = 0;
319     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
320         if (child->isOutOfFlowPositioned())
321             continue;
322
323         // If the child moved, we have to repaint it as well as any floating/positioned
324         // descendants. An exception is if we need a layout. In this case, we know we're going to
325         // repaint ourselves (and the child) anyway.
326         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
327             child->repaintDuringLayoutIfMoved(oldChildRects[childIndex]);
328         ++childIndex;
329     }
330     ASSERT(childIndex == oldChildRects.size());
331 }
332
333 void RenderFlexibleBox::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
334 {
335     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
336         if (!paintChild(*child, paintInfo, paintOffset, paintInfoForChild, usePrintRect, PaintAsInlineBlock))
337             return;
338     }
339 }
340
341 void RenderFlexibleBox::repositionLogicalHeightDependentFlexItems(Vector<LineContext>& lineContexts)
342 {
343     LayoutUnit crossAxisStartEdge = lineContexts.isEmpty() ? LayoutUnit() : lineContexts[0].crossAxisOffset;
344     alignFlexLines(lineContexts);
345
346     // If we have a single line flexbox, the line height is all the available space.
347     // For flex-direction: row, this means we need to use the height, so we do this after calling updateLogicalHeight.
348     if (!isMultiline() && lineContexts.size() == 1)
349         lineContexts[0].crossAxisExtent = crossAxisContentExtent();
350     alignChildren(lineContexts);
351
352     if (style().flexWrap() == FlexWrapReverse)
353         flipForWrapReverse(lineContexts, crossAxisStartEdge);
354
355     // direction:rtl + flex-direction:column means the cross-axis direction is flipped.
356     flipForRightToLeftColumn();
357 }
358
359 LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
360 {
361     LayoutUnit maxChildLogicalBottom = 0;
362     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
363         if (child->isOutOfFlowPositioned())
364             continue;
365         LayoutUnit childLogicalBottom = logicalTopForChild(*child) + logicalHeightForChild(*child) + marginAfterForChild(*child);
366         maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
367     }
368     return std::max(clientLogicalBottom(), maxChildLogicalBottom);
369 }
370
371 bool RenderFlexibleBox::hasOrthogonalFlow(const RenderBox& child) const
372 {
373     // FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
374     return isHorizontalFlow() != child.isHorizontalWritingMode();
375 }
376
377 bool RenderFlexibleBox::isColumnFlow() const
378 {
379     return style().isColumnFlexDirection();
380 }
381
382 bool RenderFlexibleBox::isHorizontalFlow() const
383 {
384     if (isHorizontalWritingMode())
385         return !isColumnFlow();
386     return isColumnFlow();
387 }
388
389 bool RenderFlexibleBox::isLeftToRightFlow() const
390 {
391     if (isColumnFlow())
392         return style().writingMode() == TopToBottomWritingMode || style().writingMode() == LeftToRightWritingMode;
393     return style().isLeftToRightDirection() ^ (style().flexDirection() == FlowRowReverse);
394 }
395
396 bool RenderFlexibleBox::isMultiline() const
397 {
398     return style().flexWrap() != FlexNoWrap;
399 }
400
401 Length RenderFlexibleBox::flexBasisForChild(RenderBox& child) const
402 {
403     Length flexLength = child.style().flexBasis();
404     if (flexLength.isAuto())
405         flexLength = isHorizontalFlow() ? child.style().width() : child.style().height();
406     return flexLength;
407 }
408
409 void RenderFlexibleBox::setCrossAxisExtent(LayoutUnit extent)
410 {
411     if (isHorizontalFlow())
412         setHeight(extent);
413     else
414         setWidth(extent);
415 }
416
417 LayoutUnit RenderFlexibleBox::crossAxisExtentForChild(RenderBox& child) const
418 {
419     return isHorizontalFlow() ? child.height() : child.width();
420 }
421
422 LayoutUnit RenderFlexibleBox::mainAxisExtentForChild(RenderBox& child) const
423 {
424     return isHorizontalFlow() ? child.width() : child.height();
425 }
426
427 LayoutUnit RenderFlexibleBox::crossAxisExtent() const
428 {
429     return isHorizontalFlow() ? height() : width();
430 }
431
432 LayoutUnit RenderFlexibleBox::mainAxisExtent() const
433 {
434     return isHorizontalFlow() ? width() : height();
435 }
436
437 LayoutUnit RenderFlexibleBox::crossAxisContentExtent() const
438 {
439     return isHorizontalFlow() ? contentHeight() : contentWidth();
440 }
441
442 LayoutUnit RenderFlexibleBox::mainAxisContentExtent(LayoutUnit contentLogicalHeight)
443 {
444     if (isColumnFlow()) {
445         LayoutUnit borderPaddingAndScrollbar = borderAndPaddingLogicalHeight() + scrollbarLogicalHeight();
446         if (contentLogicalHeight > LayoutUnit::max() - borderPaddingAndScrollbar)
447             contentLogicalHeight -= borderPaddingAndScrollbar;
448         LayoutUnit borderBoxLogicalHeight = contentLogicalHeight + borderPaddingAndScrollbar;
449         auto computedValues = computeLogicalHeight(borderBoxLogicalHeight, logicalTop());
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 std::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 std::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).value_or(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().value_or(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 std::optional<LayoutUnit> RenderFlexibleBox::computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const
872 {
873     ASSERT(child.hasAspectRatio());
874     ASSERT(child.intrinsicSize().height() > 0);
875     
876     std::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         std::optional<LayoutUnit> maxValue = computeMainSizeFromAspectRatioUsing(child, crossMax);
903         if (maxValue)
904             childSize = std::min(maxValue.value(), childSize);
905     }
906     
907     if (crossAxisLengthIsDefinite(child, crossMin)) {
908         std::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     std::optional<LayoutUnit> maxExtent = std::nullopt;
930     if (max.isSpecifiedOrIntrinsic()) {
931         maxExtent = computeMainAxisExtentForChild(child, MaxSize, max);
932         childSize = std::min(childSize, maxExtent.value_or(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).value_or(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.value_or(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.value_or(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             std::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     LayoutUnit preferredMainAxisExtentWithMinWidthConstraint;
986     for (RenderBox* child = m_orderIterator.currentChild(); child; child = m_orderIterator.next()) {
987         if (child->isOutOfFlowPositioned()) {
988             orderedChildren.append(child);
989             continue;
990         }
991
992         LayoutUnit childMainAxisExtent = preferredMainAxisContentExtentForChild(*child, hasInfiniteLineLength);
993         LayoutUnit borderMarginAndPaddingSpace = mainAxisBorderAndPaddingExtentForChild(*child) + (isHorizontalFlow() ? child->horizontalMarginExtent() : child->verticalMarginExtent());
994
995         LayoutUnit childMainAxisExtentWithMinWidthConstraint = childMainAxisExtent;
996         if (child->style().logicalMinWidth().isSpecifiedOrIntrinsic()) {
997             if (auto minWidthForChild = computeMainAxisExtentForChild(*child, MinSize, child->style().logicalMinWidth()))
998                 childMainAxisExtentWithMinWidthConstraint = std::max(childMainAxisExtent, minWidthForChild.value());
999         }
1000         preferredMainAxisExtentWithMinWidthConstraint += childMainAxisExtentWithMinWidthConstraint + borderMarginAndPaddingSpace;
1001
1002         if (isMultiline() && preferredMainAxisExtentWithMinWidthConstraint > lineBreakLength && lineHasInFlowItem)
1003             break;
1004         orderedChildren.append(child);
1005         lineHasInFlowItem  = true;
1006
1007         preferredMainAxisExtent += childMainAxisExtent + borderMarginAndPaddingSpace;
1008         totalFlexGrow += child->style().flexGrow();
1009         totalWeightedFlexShrink += child->style().flexShrink() * childMainAxisExtent;
1010
1011         LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(*child, childMainAxisExtent);
1012         minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent + borderMarginAndPaddingSpace;
1013     }
1014     return true;
1015 }
1016
1017 void RenderFlexibleBox::freezeViolations(const Vector<Violation>& violations, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, bool hasInfiniteLineLength)
1018 {
1019     for (size_t i = 0; i < violations.size(); ++i) {
1020         RenderBox& child = violations[i].child;
1021         LayoutUnit childSize = violations[i].childSize;
1022         LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child, hasInfiniteLineLength);
1023         availableFreeSpace -= childSize - preferredChildSize;
1024         totalFlexGrow -= child.style().flexGrow();
1025         totalWeightedFlexShrink -= child.style().flexShrink() * preferredChildSize;
1026         inflexibleItems.set(&child, childSize);
1027     }
1028 }
1029
1030 // Returns true if we successfully ran the algorithm and sized the flex items.
1031 bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit>& childSizes, bool hasInfiniteLineLength)
1032 {
1033     childSizes.clear();
1034     LayoutUnit totalViolation = 0;
1035     LayoutUnit usedFreeSpace = 0;
1036     Vector<Violation> minViolations;
1037     Vector<Violation> maxViolations;
1038     for (size_t i = 0; i < children.size(); ++i) {
1039         RenderBox& child = *children[i];
1040         if (child.isOutOfFlowPositioned()) {
1041             childSizes.append(0);
1042             continue;
1043         }
1044
1045         if (inflexibleItems.contains(&child))
1046             childSizes.append(inflexibleItems.get(&child));
1047         else {
1048             LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child, hasInfiniteLineLength);
1049             LayoutUnit childSize = preferredChildSize;
1050             double extraSpace = 0;
1051             if (availableFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow))
1052                 extraSpace = availableFreeSpace * child.style().flexGrow() / totalFlexGrow;
1053             else if (availableFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink))
1054                 extraSpace = availableFreeSpace * child.style().flexShrink() * preferredChildSize / totalWeightedFlexShrink;
1055             if (std::isfinite(extraSpace))
1056                 childSize += LayoutUnit::fromFloatRound(extraSpace);
1057
1058             LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize);
1059             childSizes.append(adjustedChildSize);
1060             usedFreeSpace += adjustedChildSize - preferredChildSize;
1061
1062             LayoutUnit violation = adjustedChildSize - childSize;
1063             if (violation > 0)
1064                 minViolations.append(Violation(child, adjustedChildSize));
1065             else if (violation < 0)
1066                 maxViolations.append(Violation(child, adjustedChildSize));
1067             totalViolation += violation;
1068         }
1069     }
1070
1071     if (totalViolation)
1072         freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, hasInfiniteLineLength);
1073     else
1074         availableFreeSpace -= usedFreeSpace;
1075
1076     return !totalViolation;
1077 }
1078
1079 static LayoutUnit initialJustifyContentOffset(LayoutUnit availableFreeSpace, ContentPosition justifyContent, ContentDistributionType justifyContentDistribution, unsigned numberOfChildren)
1080 {
1081     if (justifyContent == ContentPositionFlexEnd)
1082         return availableFreeSpace;
1083     if (justifyContent == ContentPositionCenter)
1084         return availableFreeSpace / 2;
1085     if (justifyContentDistribution == ContentDistributionSpaceAround) {
1086         if (availableFreeSpace > 0 && numberOfChildren)
1087             return availableFreeSpace / (2 * numberOfChildren);
1088         else
1089             return availableFreeSpace / 2;
1090     }
1091     return 0;
1092 }
1093
1094 static LayoutUnit justifyContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, ContentDistributionType justifyContentDistribution, unsigned numberOfChildren)
1095 {
1096     if (availableFreeSpace > 0 && numberOfChildren > 1) {
1097         if (justifyContentDistribution == ContentDistributionSpaceBetween)
1098             return availableFreeSpace / (numberOfChildren - 1);
1099         if (justifyContentDistribution == ContentDistributionSpaceAround)
1100             return availableFreeSpace / numberOfChildren;
1101     }
1102     return 0;
1103 }
1104
1105 void RenderFlexibleBox::setLogicalOverrideSize(RenderBox& child, LayoutUnit childPreferredSize)
1106 {
1107     if (hasOrthogonalFlow(child))
1108         child.setOverrideLogicalContentHeight(childPreferredSize - child.borderAndPaddingLogicalHeight());
1109     else
1110         child.setOverrideLogicalContentWidth(childPreferredSize - child.borderAndPaddingLogicalWidth());
1111 }
1112
1113 void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox& child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode layoutMode)
1114 {
1115     ASSERT(child.isOutOfFlowPositioned());
1116     child.containingBlock()->insertPositionedObject(child);
1117     RenderLayer* childLayer = child.layer();
1118     LayoutUnit inlinePosition = isColumnFlow() ? crossAxisOffset : mainAxisOffset;
1119     if (layoutMode == FlipForRowReverse && style().flexDirection() == FlowRowReverse)
1120         inlinePosition = mainAxisExtent() - mainAxisOffset;
1121     childLayer->setStaticInlinePosition(inlinePosition); // FIXME: Not right for regions.
1122
1123     LayoutUnit staticBlockPosition = isColumnFlow() ? mainAxisOffset : crossAxisOffset;
1124     if (childLayer->staticBlockPosition() != staticBlockPosition) {
1125         childLayer->setStaticBlockPosition(staticBlockPosition);
1126         if (child.style().hasStaticBlockPosition(style().isHorizontalWritingMode()))
1127             child.setChildNeedsLayout(MarkOnlyThis);
1128     }
1129 }
1130
1131 ItemPosition RenderFlexibleBox::alignmentForChild(RenderBox& child) const
1132 {
1133     ItemPosition align = child.style().resolvedAlignSelf(style(), selfAlignmentNormalBehaviorFlexibleBox).position();
1134
1135     if (align == ItemPositionBaseline && hasOrthogonalFlow(child))
1136         align = ItemPositionFlexStart;
1137
1138     if (style().flexWrap() == FlexWrapReverse) {
1139         if (align == ItemPositionFlexStart)
1140             align = ItemPositionFlexEnd;
1141         else if (align == ItemPositionFlexEnd)
1142             align = ItemPositionFlexStart;
1143     }
1144
1145     return align;
1146 }
1147
1148 size_t RenderFlexibleBox::numberOfInFlowPositionedChildren(const OrderedFlexItemList& children) const
1149 {
1150     size_t count = 0;
1151     for (size_t i = 0; i < children.size(); ++i) {
1152         RenderBox* child = children[i];
1153         if (!child->isOutOfFlowPositioned())
1154             ++count;
1155     }
1156     return count;
1157 }
1158
1159 bool RenderFlexibleBox::needToStretchChild(RenderBox& child)
1160 {
1161     if (alignmentForChild(child) != ItemPositionStretch)
1162         return false;
1163
1164     Length crossAxisLength = isHorizontalFlow() ? child.style().height() : child.style().width();
1165     return crossAxisLength.isAuto();
1166 }
1167
1168 void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox& child)
1169 {
1170     if (hasAutoMarginsInCrossAxis(child))
1171         child.updateLogicalHeight();
1172 }
1173
1174 EOverflow RenderFlexibleBox::mainAxisOverflowForChild(const RenderBox& child) const
1175 {
1176     if (isHorizontalFlow())
1177         return child.style().overflowX();
1178     return child.style().overflowY();
1179 }
1180
1181 static const StyleContentAlignmentData& contentAlignmentNormalBehaviorFlexibleBox()
1182 {
1183     // The justify-content property applies along the main axis, but since flexing
1184     // in the main axis is controlled by flex, stretch behaves as flex-start (ignoring
1185     // the specified fallback alignment, if any).
1186     // https://drafts.csswg.org/css-align/#distribution-flex
1187     static const StyleContentAlignmentData normalBehavior = {ContentPositionNormal, ContentDistributionStretch};
1188     return normalBehavior;
1189 }
1190
1191 void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>& lineContexts)
1192 {
1193     ASSERT(childSizes.size() == children.size());
1194
1195     auto position = style().resolvedJustifyContentPosition(contentAlignmentNormalBehaviorFlexibleBox());
1196     auto distribution = style().resolvedJustifyContentDistribution(contentAlignmentNormalBehaviorFlexibleBox());
1197
1198     size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren(children);
1199     LayoutUnit autoMarginOffset = autoMarginOffsetInMainAxis(children, availableFreeSpace);
1200     LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
1201     mainAxisOffset += initialJustifyContentOffset(availableFreeSpace, position, distribution, numberOfChildrenForJustifyContent);
1202     if (style().flexDirection() == FlowRowReverse)
1203         mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
1204
1205     LayoutUnit totalMainExtent = mainAxisExtent();
1206     LayoutUnit maxAscent = 0, maxDescent = 0; // Used when align-items: baseline.
1207     LayoutUnit maxChildCrossAxisExtent = 0;
1208     size_t seenInFlowPositionedChildren = 0;
1209     bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow();
1210     for (size_t i = 0; i < children.size(); ++i) {
1211         RenderBox& child = *children[i];
1212         if (child.isOutOfFlowPositioned()) {
1213             prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset, FlipForRowReverse);
1214             continue;
1215         }
1216
1217         LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child);
1218         setLogicalOverrideSize(child, childPreferredSize);
1219         // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
1220         if (needToStretchChild(child) || childPreferredSize != mainAxisExtentForChild(child))
1221             child.setChildNeedsLayout(MarkOnlyThis);
1222         else {
1223             // To avoid double applying margin changes in updateAutoMarginsInCrossAxis, we reset the margins here.
1224             resetAutoMarginsAndLogicalTopInCrossAxis(child);
1225         }
1226         updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
1227         child.layoutIfNeeded();
1228
1229         updateAutoMarginsInMainAxis(child, autoMarginOffset);
1230
1231         LayoutUnit childCrossAxisMarginBoxExtent;
1232         if (alignmentForChild(child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(child)) {
1233             LayoutUnit ascent = marginBoxAscentForChild(child);
1234             LayoutUnit descent = (crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child)) - ascent;
1235
1236             maxAscent = std::max(maxAscent, ascent);
1237             maxDescent = std::max(maxDescent, descent);
1238
1239             childCrossAxisMarginBoxExtent = maxAscent + maxDescent;
1240         } else
1241             childCrossAxisMarginBoxExtent = crossAxisExtentForChild(child) + crossAxisMarginExtentForChild(child);
1242         if (!isColumnFlow())
1243             setLogicalHeight(std::max(logicalHeight(), crossAxisOffset + flowAwareBorderAfter() + flowAwarePaddingAfter() + childCrossAxisMarginBoxExtent + crossAxisScrollbarExtent()));
1244         maxChildCrossAxisExtent = std::max(maxChildCrossAxisExtent, childCrossAxisMarginBoxExtent);
1245
1246         mainAxisOffset += flowAwareMarginStartForChild(child);
1247
1248         LayoutUnit childMainExtent = mainAxisExtentForChild(child);
1249         LayoutPoint childLocation(shouldFlipMainAxis ? totalMainExtent - mainAxisOffset - childMainExtent : mainAxisOffset,
1250             crossAxisOffset + flowAwareMarginBeforeForChild(child));
1251
1252         // FIXME: Supporting layout deltas.
1253         setFlowAwareLocationForChild(child, childLocation);
1254         mainAxisOffset += childMainExtent + flowAwareMarginEndForChild(child);
1255
1256         ++seenInFlowPositionedChildren;
1257         if (seenInFlowPositionedChildren < numberOfChildrenForJustifyContent)
1258             mainAxisOffset += justifyContentSpaceBetweenChildren(availableFreeSpace, distribution, numberOfChildrenForJustifyContent);
1259     }
1260
1261     if (isColumnFlow())
1262         setLogicalHeight(mainAxisOffset + flowAwareBorderEnd() + flowAwarePaddingEnd() + scrollbarLogicalHeight());
1263
1264     if (style().flexDirection() == FlowColumnReverse) {
1265         // We have to do an extra pass for column-reverse to reposition the flex items since the start depends
1266         // on the height of the flexbox, which we only know after we've positioned all the flex items.
1267         updateLogicalHeight();
1268         layoutColumnReverse(children, crossAxisOffset, availableFreeSpace);
1269     }
1270
1271     if (m_numberOfInFlowChildrenOnFirstLine == -1)
1272         m_numberOfInFlowChildrenOnFirstLine = seenInFlowPositionedChildren;
1273     lineContexts.append(LineContext(crossAxisOffset, maxChildCrossAxisExtent, children.size(), maxAscent));
1274     crossAxisOffset += maxChildCrossAxisExtent;
1275 }
1276
1277 void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace)
1278 {
1279     auto position = style().resolvedJustifyContentPosition(contentAlignmentNormalBehaviorFlexibleBox());
1280     auto distribution = style().resolvedJustifyContentDistribution(contentAlignmentNormalBehaviorFlexibleBox());
1281
1282     // This is similar to the logic in layoutAndPlaceChildren, except we place the children
1283     // starting from the end of the flexbox. We also don't need to layout anything since we're
1284     // just moving the children to a new position.
1285     size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren(children);
1286     LayoutUnit mainAxisOffset = logicalHeight() - flowAwareBorderEnd() - flowAwarePaddingEnd();
1287     mainAxisOffset -= initialJustifyContentOffset(availableFreeSpace, position, distribution, numberOfChildrenForJustifyContent);
1288     mainAxisOffset -= isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
1289
1290     size_t seenInFlowPositionedChildren = 0;
1291     for (size_t i = 0; i < children.size(); ++i) {
1292         RenderBox& child = *children[i];
1293         if (child.isOutOfFlowPositioned()) {
1294             child.layer()->setStaticBlockPosition(mainAxisOffset);
1295             continue;
1296         }
1297         mainAxisOffset -= mainAxisExtentForChild(child) + flowAwareMarginEndForChild(child);
1298
1299         setFlowAwareLocationForChild(child, LayoutPoint(mainAxisOffset, crossAxisOffset + flowAwareMarginBeforeForChild(child)));
1300
1301         mainAxisOffset -= flowAwareMarginStartForChild(child);
1302
1303         ++seenInFlowPositionedChildren;
1304         if (seenInFlowPositionedChildren < numberOfChildrenForJustifyContent)
1305             mainAxisOffset -= justifyContentSpaceBetweenChildren(availableFreeSpace, distribution, numberOfChildrenForJustifyContent);
1306     }
1307 }
1308
1309 static LayoutUnit initialAlignContentOffset(LayoutUnit availableFreeSpace, ContentPosition alignContent, ContentDistributionType alignContentDistribution, unsigned numberOfLines)
1310 {
1311     if (alignContent == ContentPositionFlexEnd)
1312         return availableFreeSpace;
1313     if (alignContent == ContentPositionCenter)
1314         return availableFreeSpace / 2;
1315     if (alignContentDistribution == ContentDistributionSpaceAround) {
1316         if (availableFreeSpace > 0 && numberOfLines)
1317             return availableFreeSpace / (2 * numberOfLines);
1318         if (availableFreeSpace < 0)
1319             return availableFreeSpace / 2;
1320     }
1321     return 0;
1322 }
1323
1324 static LayoutUnit alignContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, ContentDistributionType alignContentDistribution, unsigned numberOfLines)
1325 {
1326     if (availableFreeSpace > 0 && numberOfLines > 1) {
1327         if (alignContentDistribution == ContentDistributionSpaceBetween)
1328             return availableFreeSpace / (numberOfLines - 1);
1329         if (alignContentDistribution == ContentDistributionSpaceAround || alignContentDistribution == ContentDistributionStretch)
1330             return availableFreeSpace / numberOfLines;
1331     }
1332     return 0;
1333 }
1334
1335 void RenderFlexibleBox::alignFlexLines(Vector<LineContext>& lineContexts)
1336 {
1337     ContentPosition position = style().resolvedAlignContentPosition(contentAlignmentNormalBehaviorFlexibleBox());
1338     ContentDistributionType distribution = style().resolvedAlignContentDistribution(contentAlignmentNormalBehaviorFlexibleBox());
1339
1340     if (!isMultiline() || position == ContentPositionFlexStart)
1341         return;
1342
1343     LayoutUnit availableCrossAxisSpace = crossAxisContentExtent();
1344     for (size_t i = 0; i < lineContexts.size(); ++i)
1345         availableCrossAxisSpace -= lineContexts[i].crossAxisExtent;
1346
1347     RenderBox* child = m_orderIterator.first();
1348     LayoutUnit lineOffset = initialAlignContentOffset(availableCrossAxisSpace, position, distribution, lineContexts.size());
1349     for (unsigned lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1350         lineContexts[lineNumber].crossAxisOffset += lineOffset;
1351         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next())
1352             adjustAlignmentForChild(*child, lineOffset);
1353
1354         if (distribution == ContentDistributionStretch && availableCrossAxisSpace > 0)
1355             lineContexts[lineNumber].crossAxisExtent += availableCrossAxisSpace / static_cast<unsigned>(lineContexts.size());
1356
1357         lineOffset += alignContentSpaceBetweenChildren(availableCrossAxisSpace, distribution, lineContexts.size());
1358     }
1359 }
1360
1361 void RenderFlexibleBox::adjustAlignmentForChild(RenderBox& child, LayoutUnit delta)
1362 {
1363     if (child.isOutOfFlowPositioned()) {
1364         LayoutUnit staticInlinePosition = child.layer()->staticInlinePosition();
1365         LayoutUnit staticBlockPosition = child.layer()->staticBlockPosition();
1366         LayoutUnit mainAxis = isColumnFlow() ? staticBlockPosition : staticInlinePosition;
1367         LayoutUnit crossAxis = isColumnFlow() ? staticInlinePosition : staticBlockPosition;
1368         crossAxis += delta;
1369         prepareChildForPositionedLayout(child, mainAxis, crossAxis, NoFlipForRowReverse);
1370         return;
1371     }
1372
1373     setFlowAwareLocationForChild(child, flowAwareLocationForChild(child) + LayoutSize(0, delta));
1374 }
1375
1376 void RenderFlexibleBox::alignChildren(const Vector<LineContext>& lineContexts)
1377 {
1378     // Keep track of the space between the baseline edge and the after edge of the box for each line.
1379     Vector<LayoutUnit> minMarginAfterBaselines;
1380
1381     RenderBox* child = m_orderIterator.first();
1382     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1383         LayoutUnit minMarginAfterBaseline = LayoutUnit::max();
1384         LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
1385         LayoutUnit maxAscent = lineContexts[lineNumber].maxAscent;
1386
1387         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
1388             ASSERT(child);
1389             if (child->isOutOfFlowPositioned()) {
1390                 if (style().flexWrap() == FlexWrapReverse)
1391                     adjustAlignmentForChild(*child, lineCrossAxisExtent);
1392                 continue;
1393             }
1394
1395             if (updateAutoMarginsInCrossAxis(*child, std::max(LayoutUnit::fromPixel(0), availableAlignmentSpaceForChild(lineCrossAxisExtent, *child))))
1396                 continue;
1397
1398             switch (alignmentForChild(*child)) {
1399             case ItemPositionAuto:
1400             case ItemPositionNormal:
1401                 ASSERT_NOT_REACHED();
1402                 break;
1403             case ItemPositionStart:
1404                 // FIXME: https://webkit.org/b/135460 - The extended grammar is not supported
1405                 // yet for FlexibleBox.
1406                 // Defaulting to Stretch for now, as it what most of FlexBox based renders
1407                 // expect as default.
1408 #if ENABLE(CSS_GRID_LAYOUT)
1409                 ASSERT(RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled());
1410 #else
1411                 ASSERT_NOT_REACHED();
1412 #endif
1413                 FALLTHROUGH;
1414             case ItemPositionStretch: {
1415                 applyStretchAlignmentToChild(*child, lineCrossAxisExtent);
1416                 // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
1417                 if (style().flexWrap() == FlexWrapReverse)
1418                     adjustAlignmentForChild(*child, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child));
1419                 break;
1420             }
1421             case ItemPositionFlexStart:
1422                 break;
1423             case ItemPositionFlexEnd:
1424                 adjustAlignmentForChild(*child, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child));
1425                 break;
1426             case ItemPositionCenter:
1427                 adjustAlignmentForChild(*child, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child) / 2);
1428                 break;
1429             case ItemPositionBaseline: {
1430                 // 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.
1431                 // https://bugs.webkit.org/show_bug.cgi?id=98076
1432                 LayoutUnit ascent = marginBoxAscentForChild(*child);
1433                 LayoutUnit startOffset = maxAscent - ascent;
1434                 adjustAlignmentForChild(*child, startOffset);
1435
1436                 if (style().flexWrap() == FlexWrapReverse)
1437                     minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, *child) - startOffset);
1438                 break;
1439             }
1440             case ItemPositionLastBaseline:
1441             case ItemPositionSelfStart:
1442             case ItemPositionSelfEnd:
1443             case ItemPositionEnd:
1444             case ItemPositionLeft:
1445             case ItemPositionRight:
1446                 // FIXME: https://webkit.org/b/135460 - The extended grammar is not supported
1447                 // yet for FlexibleBox.
1448 #if ENABLE(CSS_GRID_LAYOUT)
1449                 ASSERT(RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled());
1450 #else
1451                 ASSERT_NOT_REACHED();
1452 #endif
1453                 break;
1454             default:
1455                 ASSERT_NOT_REACHED();
1456                 break;
1457             }
1458         }
1459         minMarginAfterBaselines.append(minMarginAfterBaseline);
1460     }
1461
1462     if (style().flexWrap() != FlexWrapReverse)
1463         return;
1464
1465     // wrap-reverse flips the cross axis start and end. For baseline alignment, this means we
1466     // need to align the after edge of baseline elements with the after edge of the flex line.
1467     child = m_orderIterator.first();
1468     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1469         LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
1470         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
1471             ASSERT(child);
1472             if (alignmentForChild(*child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(*child) && minMarginAfterBaseline)
1473                 adjustAlignmentForChild(*child, minMarginAfterBaseline);
1474         }
1475     }
1476 }
1477
1478 void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox& child, LayoutUnit lineCrossAxisExtent)
1479 {
1480     if (!isColumnFlow() && child.style().logicalHeight().isAuto()) {
1481         // FIXME: If the child has orthogonal flow, then it already has an override height set, so use it.
1482         if (!hasOrthogonalFlow(child)) {
1483             LayoutUnit stretchedLogicalHeight = child.logicalHeight() + availableAlignmentSpaceForChild(lineCrossAxisExtent, child);
1484             ASSERT(!child.needsLayout());
1485             LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(stretchedLogicalHeight, child.logicalHeight() - child.borderAndPaddingLogicalHeight());
1486
1487             // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
1488             if (desiredLogicalHeight != child.logicalHeight()) {
1489                 child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.borderAndPaddingLogicalHeight());
1490                 child.setLogicalHeight(0);
1491                 child.setChildNeedsLayout(MarkOnlyThis);
1492                 child.layout();
1493             }
1494         }
1495     } else if (isColumnFlow() && child.style().logicalWidth().isAuto()) {
1496         // FIXME: If the child doesn't have orthogonal flow, then it already has an override width set, so use it.
1497         if (hasOrthogonalFlow(child)) {
1498             LayoutUnit childWidth = std::max<LayoutUnit>(0, lineCrossAxisExtent - crossAxisMarginExtentForChild(child));
1499             childWidth = child.constrainLogicalWidthInRegionByMinMax(childWidth, childWidth, *this);
1500
1501             if (childWidth != child.logicalWidth()) {
1502                 child.setOverrideLogicalContentWidth(childWidth - child.borderAndPaddingLogicalWidth());
1503                 child.setChildNeedsLayout(MarkOnlyThis);
1504                 child.layout();
1505             }
1506         }
1507     }
1508 }
1509
1510 void RenderFlexibleBox::flipForRightToLeftColumn()
1511 {
1512     if (style().isLeftToRightDirection() || !isColumnFlow())
1513         return;
1514
1515     LayoutUnit crossExtent = crossAxisExtent();
1516     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
1517         if (child->isOutOfFlowPositioned())
1518             continue;
1519         LayoutPoint location = flowAwareLocationForChild(*child);
1520         location.setY(crossExtent - crossAxisExtentForChild(*child) - location.y());
1521         setFlowAwareLocationForChild(*child, location);
1522     }
1523 }
1524
1525 void RenderFlexibleBox::flipForWrapReverse(const Vector<LineContext>& lineContexts, LayoutUnit crossAxisStartEdge)
1526 {
1527     LayoutUnit contentExtent = crossAxisContentExtent();
1528     RenderBox* child = m_orderIterator.first();
1529     for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
1530         for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
1531             ASSERT(child);
1532             LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
1533             LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge;
1534             LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxisExtent;
1535             adjustAlignmentForChild(*child, newOffset - originalOffset);
1536         }
1537     }
1538 }
1539
1540 bool RenderFlexibleBox::isTopLayoutOverflowAllowed() const
1541 {
1542     bool hasTopOverflow = RenderBlock::isTopLayoutOverflowAllowed();
1543     if (hasTopOverflow || !style().isReverseFlexDirection())
1544         return hasTopOverflow;
1545     
1546     return !isHorizontalFlow();
1547 }
1548
1549 bool RenderFlexibleBox::isLeftLayoutOverflowAllowed() const
1550 {
1551     bool hasLeftOverflow = RenderBlock::isLeftLayoutOverflowAllowed();
1552     if (hasLeftOverflow || !style().isReverseFlexDirection())
1553         return hasLeftOverflow;
1554     
1555     return isHorizontalFlow();
1556 }
1557
1558 }