summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/rendering/RenderFlexibleBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderFlexibleBox.cpp')
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp112
1 files changed, 93 insertions, 19 deletions
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index 98e9f2d06..5b0a83de7 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -363,7 +363,7 @@ LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
return std::max(clientLogicalBottom(), maxChildLogicalBottom);
}
-bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox& child) const
+bool RenderFlexibleBox::hasOrthogonalFlow(const RenderBox& child) const
{
// FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
return isHorizontalFlow() != child.isHorizontalWritingMode();
@@ -450,14 +450,14 @@ LayoutUnit RenderFlexibleBox::mainAxisContentExtent(LayoutUnit contentLogicalHei
return contentLogicalWidth();
}
-Optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(RenderBox& child, SizeType sizeType, const Length& size)
+Optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(const RenderBox& child, SizeType sizeType, const Length& size)
{
// FIXME: This is wrong for orthogonal flows. It should use the flexbox's writing-mode, not the child's in order
// to figure out the logical height/width.
if (isColumnFlow()) {
// We don't have to check for "auto" here - computeContentLogicalHeight will just return Nullopt for that case anyway.
if (size.isIntrinsic())
- child.layoutIfNeeded();
+ const_cast<RenderBox&>(child).layoutIfNeeded(); // FIXME: Should not need to do a layout here.
return child.computeContentLogicalHeight(sizeType, size, child.logicalHeight() - child.borderAndPaddingLogicalHeight());
}
// FIXME: Figure out how this should work for regions and pass in the appropriate values.
@@ -648,15 +648,14 @@ LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox&
{
return isHorizontalFlow() ? child.horizontalBorderAndPaddingExtent() : child.verticalBorderAndPaddingExtent();
}
-
-bool RenderFlexibleBox::mainAxisExtentIsDefinite() const
-{
- return isColumnFlow() ? hasDefiniteLogicalHeight() : hasDefiniteLogicalWidth();
-}
-
-bool RenderFlexibleBox::mainAxisLengthIsIndefinite(const Length& flexBasis) const
+
+bool RenderFlexibleBox::mainAxisLengthIsDefinite(const RenderBox& child, const Length& flexBasis) const
{
- return flexBasis.isAuto() || (flexBasis.isPercentOrCalculated() && !mainAxisExtentIsDefinite());
+ if (flexBasis.isAuto())
+ return false;
+ if (flexBasis.isPercentOrCalculated())
+ return isColumnFlow() ? bool(child.computePercentageLogicalHeight(flexBasis)) : hasDefiniteLogicalWidth();
+ return true;
}
LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox& child) const
@@ -855,7 +854,72 @@ void RenderFlexibleBox::prepareOrderIteratorAndMargins()
}
}
-LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox& child, LayoutUnit childSize)
+bool RenderFlexibleBox::crossAxisLengthIsDefinite(const RenderBox& child, const Length& length) const
+{
+ if (length.isAuto())
+ return false;
+ if (length.isPercentOrCalculated())
+ return hasOrthogonalFlow(child) ? hasDefiniteLogicalWidth() : bool(child.computePercentageLogicalHeight(length));
+ return length.isFixed();
+}
+
+
+Optional<LayoutUnit> RenderFlexibleBox::computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const
+{
+ ASSERT(child.hasAspectRatio());
+ ASSERT(child.intrinsicSize().height() > 0);
+
+ Optional<LayoutUnit> crossSize;
+ if (crossSizeLength.isFixed())
+ crossSize = LayoutUnit(crossSizeLength.value());
+ else {
+ ASSERT(crossSizeLength.isPercentOrCalculated());
+ crossSize = hasOrthogonalFlow(child) ?
+ adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(crossSizeLength, contentWidth())) :
+ child.computePercentageLogicalHeight(crossSizeLength);
+ }
+
+ if (!crossSize)
+ return crossSize;
+
+ const LayoutSize& childIntrinsicSize = child.intrinsicSize();
+ double ratio = childIntrinsicSize.width().toFloat() / childIntrinsicSize.height().toFloat();
+ if (isHorizontalFlow())
+ return LayoutUnit(crossSize.value() * ratio);
+ return LayoutUnit(crossSize.value() / ratio);
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox& child, LayoutUnit childSize)
+{
+ Length crossMin = isHorizontalFlow() ? child.style().minHeight() : child.style().minWidth();
+ Length crossMax = isHorizontalFlow() ? child.style().maxHeight() : child.style().maxWidth();
+
+ if (crossAxisLengthIsDefinite(child, crossMax)) {
+ Optional<LayoutUnit> maxValue = computeMainSizeFromAspectRatioUsing(child, crossMax);
+ if (maxValue)
+ childSize = std::min(maxValue.value(), childSize);
+ }
+
+ if (crossAxisLengthIsDefinite(child, crossMin)) {
+ Optional<LayoutUnit> minValue = computeMainSizeFromAspectRatioUsing(child, crossMin);
+ if (minValue)
+ childSize = std::max(minValue.value(), childSize);
+ }
+
+ return childSize;
+}
+
+bool RenderFlexibleBox::useChildAspectRatio(const RenderBox& child) const
+{
+ if (!child.hasAspectRatio())
+ return false;
+ if (!child.intrinsicSize().height())
+ return false;
+ Length crossSize = isHorizontalFlow() ? child.style().height() : child.style().width();
+ return crossAxisLengthIsDefinite(child, crossSize);
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(const RenderBox& child, LayoutUnit childSize)
{
Length max = isHorizontalFlow() ? child.style().maxWidth() : child.style().maxHeight();
Optional<LayoutUnit> maxExtent = Nullopt;
@@ -863,26 +927,36 @@ LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox& child, Layo
maxExtent = computeMainAxisExtentForChild(child, MaxSize, max);
childSize = std::min(childSize, maxExtent.valueOr(childSize));
}
-
+
Length min = isHorizontalFlow() ? child.style().minWidth() : child.style().minHeight();
if (min.isSpecifiedOrIntrinsic())
return std::max(childSize, computeMainAxisExtentForChild(child, MinSize, min).valueOr(childSize));
-
- if (!isFlexibleBoxImpl() && min.isAuto() && mainAxisOverflowForChild(child) == OVISIBLE) {
+
+ if (!isFlexibleBoxImpl() && min.isAuto() && mainAxisOverflowForChild(child) == OVISIBLE && !(isColumnFlow() && is<RenderFlexibleBox>(child))) {
// This is the implementation of CSS flexbox section 4.5 which defines the minimum size of "pure" flex
// items. For any other item the value should be 0, this also includes RenderFlexibleBox's derived clases
// (RenderButton, RenderFullScreen...) because that's just an implementation detail.
+ // FIXME: For now we don't handle nested column flexboxes. Need to implement better intrinsic
+ // size handling from the flex box spec first (4.5).
LayoutUnit contentSize = computeMainAxisExtentForChild(child, MinSize, Length(MinContent)).value();
ASSERT(contentSize >= 0);
+ if (child.hasAspectRatio() && child.intrinsicSize().height() > 0)
+ contentSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, contentSize);
contentSize = std::min(contentSize, maxExtent.valueOr(contentSize));
-
+
Length mainSize = isHorizontalFlow() ? child.style().width() : child.style().height();
- if (!mainAxisLengthIsIndefinite(mainSize)) {
+ if (mainAxisLengthIsDefinite(child, mainSize)) {
LayoutUnit resolvedMainSize = computeMainAxisExtentForChild(child, MainOrPreferredSize, mainSize).value();
ASSERT(resolvedMainSize >= 0);
LayoutUnit specifiedSize = std::min(resolvedMainSize, maxExtent.valueOr(resolvedMainSize));
-
return std::max(childSize, std::min(specifiedSize, contentSize));
+ } else if (useChildAspectRatio(child)) {
+ Length crossSizeLength = isHorizontalFlow() ? child.style().height() : child.style().width();
+ Optional<LayoutUnit> transferredSize = computeMainSizeFromAspectRatioUsing(child, crossSizeLength);
+ if (transferredSize) {
+ transferredSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, transferredSize.value());
+ return std::max(childSize, std::min(transferredSize.value(), contentSize));
+ }
}
return std::max(childSize, contentSize);
}
@@ -1085,7 +1159,7 @@ void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox& chil
child.updateLogicalHeight();
}
-EOverflow RenderFlexibleBox::mainAxisOverflowForChild(RenderBox& child) const
+EOverflow RenderFlexibleBox::mainAxisOverflowForChild(const RenderBox& child) const
{
if (isHorizontalFlow())
return child.style().overflowX();