Vector<int>::const_iterator m_orderValuesIterator;
};
-struct RenderFlexibleBox::WrapReverseContext {
- explicit WrapReverseContext(EFlexWrap flexWrap)
- : isWrapReverse(flexWrap == FlexWrapReverse)
+struct RenderFlexibleBox::LineContext {
+ LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t numberOfChildren, LayoutUnit maxAscent)
+ : crossAxisOffset(crossAxisOffset)
+ , crossAxisExtent(crossAxisExtent)
+ , numberOfChildren(numberOfChildren)
+ , maxAscent(maxAscent)
{
}
- void addCrossAxisOffset(LayoutUnit offset)
- {
- if (!isWrapReverse)
- return;
- crossAxisOffsets.append(offset);
- }
-
- void addNumberOfChildrenOnLine(size_t numberOfChildren)
- {
- if (!isWrapReverse)
- return;
- childrenPerLine.append(numberOfChildren);
- }
-
- LayoutUnit lineCrossAxisDelta(size_t line, LayoutUnit crossAxisContentExtent) const
- {
- ASSERT(line + 1 < crossAxisOffsets.size());
- LayoutUnit lineHeight = crossAxisOffsets[line + 1] - crossAxisOffsets[line];
- LayoutUnit originalOffset = crossAxisOffsets[line] - crossAxisOffsets[0];
- LayoutUnit newOffset = crossAxisContentExtent - originalOffset - lineHeight;
- return newOffset - originalOffset;
- }
-
- WTF::Vector<LayoutUnit> crossAxisOffsets;
- WTF::Vector<size_t> childrenPerLine;
- bool isWrapReverse;
+ LayoutUnit crossAxisOffset;
+ LayoutUnit crossAxisExtent;
+ size_t numberOfChildren;
+ LayoutUnit maxAscent;
};
float totalPositiveFlexibility;
float totalNegativeFlexibility;
LayoutUnit minMaxAppliedMainAxisExtent;
+ WTF::Vector<LineContext> lineContexts;
FlexOrderIterator flexIterator(this, flexOrderValues);
- // For wrap-reverse, we need to layout as wrap, then reverse the lines. The next two arrays
- // are some extra information so it's possible to reverse the lines.
- WrapReverseContext wrapReverseContext(style()->flexWrap());
-
LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
while (computeNextFlexLine(flexIterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalNegativeFlexibility, minMaxAppliedMainAxisExtent)) {
LayoutUnit availableFreeSpace = computeAvailableFreeSpace(preferredMainAxisExtent);
ASSERT(inflexibleItems.size() > 0);
}
- wrapReverseContext.addNumberOfChildrenOnLine(orderedChildren.size());
- wrapReverseContext.addCrossAxisOffset(crossAxisOffset);
- layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace);
+ layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, lineContexts);
}
- if (wrapReverseContext.isWrapReverse) {
- wrapReverseContext.addCrossAxisOffset(crossAxisOffset);
- flipForWrapReverse(flexIterator, wrapReverseContext);
- }
+ alignChildren(flexIterator, lineContexts);
+
+ if (style()->flexWrap() == FlexWrapReverse)
+ flipForWrapReverse(flexIterator, lineContexts);
// direction:rtl + flex-direction:column means the cross-axis direction is flipped.
flipForRightToLeftColumn(flexIterator);
return align;
}
-void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace)
+void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, WTF::Vector<LineContext>& lineContexts)
{
LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
mainAxisOffset += initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size());
}
LayoutUnit lineCrossAxisExtent = isMultiline() ? maxChildCrossAxisExtent : crossAxisContentExtent();
- alignChildren(children, lineCrossAxisExtent, maxAscent);
-
+ lineContexts.append(LineContext(crossAxisOffset, lineCrossAxisExtent, children.size(), maxAscent));
crossAxisOffset += lineCrossAxisExtent;
}
child->repaintDuringLayoutIfMoved(oldRect);
}
-void RenderFlexibleBox::alignChildren(const OrderedFlexItemList& children, LayoutUnit lineCrossAxisExtent, LayoutUnit maxAscent)
+void RenderFlexibleBox::alignChildren(FlexOrderIterator& iterator, const WTF::Vector<LineContext>& lineContexts)
{
- LayoutUnit minMarginAfterBaseline = std::numeric_limits<LayoutUnit>::max();
-
- for (size_t i = 0; i < children.size(); ++i) {
- RenderBox* child = children[i];
- switch (flexAlignForChild(child)) {
- case AlignAuto:
- ASSERT_NOT_REACHED();
- break;
- case AlignStretch: {
- applyStretchAlignmentToChild(child, lineCrossAxisExtent);
- // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
- if (style()->flexWrap() == FlexWrapReverse)
+ // Keep track of the space between the baseline edge and the after edge of the box for each line.
+ WTF::Vector<LayoutUnit> minMarginAfterBaselines;
+
+ RenderBox* child = iterator.first();
+ for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+ LayoutUnit minMarginAfterBaseline = std::numeric_limits<LayoutUnit>::max();
+ LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
+ LayoutUnit maxAscent = lineContexts[lineNumber].maxAscent;
+
+ for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
+ ASSERT(child);
+ switch (flexAlignForChild(child)) {
+ case AlignAuto:
+ ASSERT_NOT_REACHED();
+ break;
+ case AlignStretch: {
+ applyStretchAlignmentToChild(child, lineCrossAxisExtent);
+ // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
+ if (style()->flexWrap() == FlexWrapReverse)
+ adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
+ break;
+ }
+ case AlignStart:
+ break;
+ case AlignEnd:
adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
- break;
- }
- case AlignStart:
- break;
- case AlignEnd:
- adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
- break;
- case AlignCenter:
- adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) / 2);
- break;
- case AlignBaseline: {
- LayoutUnit ascent = marginBoxAscentForChild(child);
- LayoutUnit startOffset = maxAscent - ascent;
- adjustAlignmentForChild(child, startOffset);
-
- if (style()->flexWrap() == FlexWrapReverse)
- minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) - startOffset);
- break;
- }
+ break;
+ case AlignCenter:
+ adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) / 2);
+ break;
+ case AlignBaseline: {
+ LayoutUnit ascent = marginBoxAscentForChild(child);
+ LayoutUnit startOffset = maxAscent - ascent;
+ adjustAlignmentForChild(child, startOffset);
+
+ if (style()->flexWrap() == FlexWrapReverse)
+ minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) - startOffset);
+ break;
+ }
+ }
}
+ minMarginAfterBaselines.append(minMarginAfterBaseline);
}
+ if (style()->flexWrap() != FlexWrapReverse)
+ return;
+
// wrap-reverse flips the cross axis start and end. For baseline alignment, this means we
// need to align the after edge of baseline elements with the after edge of the flex line.
- if (style()->flexWrap() == FlexWrapReverse && minMarginAfterBaseline) {
- for (size_t i = 0; i < children.size(); ++i) {
- RenderBox* child = children[i];
- if (flexAlignForChild(child) == AlignBaseline)
+ child = iterator.first();
+ for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+ LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
+ for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
+ ASSERT(child);
+ if (flexAlignForChild(child) == AlignBaseline && minMarginAfterBaseline)
adjustAlignmentForChild(child, minMarginAfterBaseline);
}
}
}
}
-void RenderFlexibleBox::flipForWrapReverse(FlexOrderIterator& iterator, const WrapReverseContext& wrapReverseContext)
+void RenderFlexibleBox::flipForWrapReverse(FlexOrderIterator& iterator, const WTF::Vector<LineContext>& lineContexts)
{
if (!isColumnFlow())
computeLogicalHeight();
- size_t currentChild = 0;
- size_t lineNumber = 0;
LayoutUnit contentExtent = crossAxisContentExtent();
- for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
- LayoutPoint location = flowAwareLocationForChild(child);
- location.setY(location.y() + wrapReverseContext.lineCrossAxisDelta(lineNumber, contentExtent));
-
- LayoutRect oldRect = child->frameRect();
- setFlowAwareLocationForChild(child, location);
- if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
- child->repaintDuringLayoutIfMoved(oldRect);
-
- if (++currentChild == wrapReverseContext.childrenPerLine[lineNumber]) {
- ++lineNumber;
- currentChild = 0;
+ RenderBox* child = iterator.first();
+ for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+ for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
+ ASSERT(child);
+ LayoutPoint location = flowAwareLocationForChild(child);
+ LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
+ LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - lineContexts[0].crossAxisOffset;
+ LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxisExtent;
+ location.setY(location.y() + newOffset - originalOffset);
+
+ LayoutRect oldRect = child->frameRect();
+ setFlowAwareLocationForChild(child, location);
+ if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
+ child->repaintDuringLayoutIfMoved(oldRect);
}
}
}