summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderFlexibleBox.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-25 15:09:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-25 15:09:11 +0200
commita89b2ebb8e192c5e8cea21079bda2ee2c0c7dddd (patch)
treeb7abd9f49ae1d4d2e426a5883bfccd42b8e2ee12 /Source/WebCore/rendering/RenderFlexibleBox.cpp
parent8d473cf9743f1d30a16a27114e93bd5af5648d23 (diff)
downloadqtwebkit-a89b2ebb8e192c5e8cea21079bda2ee2c0c7dddd.tar.gz
Imported WebKit commit eb5c1b8fe4d4b1b90b5137433fc58a91da0e6878 (http://svn.webkit.org/repository/webkit/trunk@118516)
Diffstat (limited to 'Source/WebCore/rendering/RenderFlexibleBox.cpp')
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp103
1 files changed, 98 insertions, 5 deletions
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index efa2eb71d..2feab4f75 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -642,12 +642,99 @@ void RenderFlexibleBox::layoutFlexItems(FlexOrderIterator& iterator, WTF::Vector
}
}
+LayoutUnit RenderFlexibleBox::autoMarginOffsetInMainAxis(const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace)
+{
+ if (availableFreeSpace <= 0)
+ return 0;
+
+ int numberOfAutoMargins = 0;
+ bool isHorizontal = isHorizontalFlow();
+ for (size_t i = 0; i < children.size(); ++i) {
+ RenderBox* child = children[i];
+ if (child->isPositioned())
+ continue;
+ if (isHorizontal) {
+ if (child->style()->marginLeft().isAuto())
+ ++numberOfAutoMargins;
+ if (child->style()->marginRight().isAuto())
+ ++numberOfAutoMargins;
+ } else {
+ if (child->style()->marginTop().isAuto())
+ ++numberOfAutoMargins;
+ if (child->style()->marginBottom().isAuto())
+ ++numberOfAutoMargins;
+ }
+ }
+ if (!numberOfAutoMargins)
+ return 0;
+
+ LayoutUnit sizeOfAutoMargin = availableFreeSpace / numberOfAutoMargins;
+ availableFreeSpace = 0;
+ return sizeOfAutoMargin;
+}
+
+void RenderFlexibleBox::updateAutoMarginsInMainAxis(RenderBox* child, LayoutUnit autoMarginOffset)
+{
+ if (isHorizontalFlow()) {
+ if (child->style()->marginLeft().isAuto())
+ child->setMarginLeft(autoMarginOffset);
+ if (child->style()->marginRight().isAuto())
+ child->setMarginRight(autoMarginOffset);
+ } else {
+ if (child->style()->marginTop().isAuto())
+ child->setMarginTop(autoMarginOffset);
+ if (child->style()->marginBottom().isAuto())
+ child->setMarginBottom(autoMarginOffset);
+ }
+}
+
+bool RenderFlexibleBox::hasAutoMarginsInCrossAxis(RenderBox* child)
+{
+ if (isHorizontalFlow())
+ return child->style()->marginTop().isAuto() || child->style()->marginBottom().isAuto();
+ return child->style()->marginLeft().isAuto() || child->style()->marginRight().isAuto();
+}
+
LayoutUnit RenderFlexibleBox::availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox* child)
{
LayoutUnit childCrossExtent = crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child);
return lineCrossAxisExtent - childCrossExtent;
}
+bool RenderFlexibleBox::updateAutoMarginsInCrossAxis(RenderBox* child, LayoutUnit availableAlignmentSpace)
+{
+ bool isHorizontal = isHorizontalFlow();
+ Length start = isHorizontal ? child->style()->marginTop() : child->style()->marginLeft();
+ Length end = isHorizontal ? child->style()->marginBottom() : child->style()->marginRight();
+ if (start.isAuto() && end.isAuto()) {
+ adjustAlignmentForChild(child, availableAlignmentSpace / 2);
+ if (isHorizontal) {
+ child->setMarginTop(availableAlignmentSpace / 2);
+ child->setMarginBottom(availableAlignmentSpace / 2);
+ } else {
+ child->setMarginLeft(availableAlignmentSpace / 2);
+ child->setMarginRight(availableAlignmentSpace / 2);
+ }
+ return true;
+ }
+ if (start.isAuto()) {
+ adjustAlignmentForChild(child, availableAlignmentSpace);
+ if (isHorizontal)
+ child->setMarginTop(availableAlignmentSpace);
+ else
+ child->setMarginLeft(availableAlignmentSpace);
+ return true;
+ }
+ if (end.isAuto()) {
+ if (isHorizontal)
+ child->setMarginBottom(availableAlignmentSpace);
+ else
+ child->setMarginRight(availableAlignmentSpace);
+ return true;
+ }
+ return false;
+}
+
LayoutUnit RenderFlexibleBox::marginBoxAscentForChild(RenderBox* child)
{
LayoutUnit ascent = child->firstLineBoxBaseline();
@@ -673,9 +760,8 @@ void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, Fle
child->layoutIfNeeded();
}
- // We set the margins because we want to make sure 'auto' has a margin
- // of 0 and because if we're not auto sizing, we don't do a layout that
- // computes the start/end margins.
+ // Before running the flex algorithm, 'auto' has a margin of 0.
+ // Also, if we're not auto sizing, we don't do a layout that computes the start/end margins.
if (isHorizontalFlow()) {
child->setMarginLeft(minimumValueForLength(child->style()->marginLeft(), flexboxAvailableContentExtent, renderView));
child->setMarginRight(minimumValueForLength(child->style()->marginRight(), flexboxAvailableContentExtent, renderView));
@@ -881,6 +967,8 @@ static EFlexAlign flexAlignForChild(RenderBox* child)
void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, WTF::Vector<LineContext>& lineContexts)
{
ASSERT(childSizes.size() == children.size());
+
+ LayoutUnit autoMarginOffset = autoMarginOffsetInMainAxis(children, availableFreeSpace);
LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
mainAxisOffset += initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size());
if (style()->flexDirection() == FlowRowReverse)
@@ -902,8 +990,10 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons
child->setChildNeedsLayout(true);
child->layoutIfNeeded();
+ updateAutoMarginsInMainAxis(child, autoMarginOffset);
+
LayoutUnit childCrossAxisMarginBoxExtent;
- if (flexAlignForChild(child) == AlignBaseline) {
+ if (flexAlignForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child)) {
LayoutUnit ascent = marginBoxAscentForChild(child);
LayoutUnit descent = (crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child)) - ascent;
@@ -1047,6 +1137,9 @@ void RenderFlexibleBox::alignChildren(FlexOrderIterator& iterator, const WTF::Ve
for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
ASSERT(child);
+ if (updateAutoMarginsInCrossAxis(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child)))
+ continue;
+
switch (flexAlignForChild(child)) {
case AlignAuto:
ASSERT_NOT_REACHED();
@@ -1090,7 +1183,7 @@ void RenderFlexibleBox::alignChildren(FlexOrderIterator& iterator, const WTF::Ve
LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
ASSERT(child);
- if (flexAlignForChild(child) == AlignBaseline && minMarginAfterBaseline)
+ if (flexAlignForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child) && minMarginAfterBaseline)
adjustAlignmentForChild(child, minMarginAfterBaseline);
}
}