--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5630,51 +5630,66 @@ nsFrame::ComputeSize(gfxContext*
// When resolving justify/align-self below, we want to use the grid
// container's justify/align-items value and WritingMode.
alignCB = grandParent;
}
}
bool isFlexItem = parentFrame && parentFrame->IsFlexContainerFrame() &&
!parentFrame->HasAnyStateBits(NS_STATE_FLEX_IS_EMULATING_LEGACY_BOX) &&
!HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
- bool isInlineFlexItem = false;
+ // This bool only gets set (and used) if isFlexItem is true.
+ // It indicates (for flex items) whether we're using their flex-basis for the
+ // item's own ISize property vs. for its BSize property.
+ bool usingFlexBasisForISize;
if (isFlexItem) {
// Flex items use their "flex-basis" property in place of their main-size
// property (e.g. "width") for sizing purposes, *unless* they have
// "flex-basis:auto", in which case they use their main-size property after
// all.
uint32_t flexDirection = GetParent()->StylePosition()->mFlexDirection;
- isInlineFlexItem =
+ const bool flexContainerIsRowOriented =
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
+ const bool inlineAxisSameAsParent =
+ !aWM.IsOrthogonalTo(parentFrame->GetWritingMode());
+
+ // If parent is row-oriented, its main axis (i.e. the flex-basis axis) is
+ // its own inline axis. So if it's row oriented and our own inline axis
+ // is the same as our parent's, then we'll be using flex-basis in place
+ // of our _ISize_ sizing property.
+ // Otherwise, we'll be using flex-basis for our _BSize_ sizing property
+ // (unless both conditions are false, in which case we flip back around to
+ // using our ISize sizing property).
+ usingFlexBasisForISize =
+ (flexContainerIsRowOriented == inlineAxisSameAsParent);
// NOTE: The logic here should match the similar chunk for determining
// inlineStyleCoord and blockStyleCoord in
// nsFrame::ComputeSizeWithIntrinsicDimensions().
const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
if (flexBasis->GetUnit() != eStyleUnit_Auto) {
- if (isInlineFlexItem) {
- inlineStyleCoord = flexBasis;
- } else {
- // One caveat for vertical flex items: We don't support enumerated
- // values (e.g. "max-content") for height properties yet. So, if our
- // computed flex-basis is an enumerated value, we'll just behave as if
- // it were "auto", which means "use the main-size property after all"
- // (which is "height", in this case).
- // NOTE: Once we support intrinsic sizing keywords for "height",
- // we should remove this check.
- if (flexBasis->GetUnit() != eStyleUnit_Enumerated) {
- blockStyleCoord = flexBasis;
- }
+ // One caveat for when flex-basis is stomping on 'height': We don't
+ // support enumerated values (e.g. "max-content") for height yet (that's
+ // bug 567039). So, if our computed flex-basis is an enumerated value,
+ // we'll just behave as if it were "auto", which means "use the main-size
+ // property after all" (which is "height", in this case). NOTE: Once we
+ // support intrinsic sizing keywords for "height", we should remove this
+ // check.
+ bool usingFlexBasisForHeight =
+ (usingFlexBasisForISize != aWM.IsVertical());
+ if (!usingFlexBasisForHeight ||
+ flexBasis->GetUnit() != eStyleUnit_Enumerated) {
+ // Override whichever coord we're overriding:
+ (usingFlexBasisForISize ? inlineStyleCoord : blockStyleCoord) =
+ flexBasis;
}
}
}
// Compute inline-axis size
-
if (inlineStyleCoord->GetUnit() != eStyleUnit_Auto) {
result.ISize(aWM) =
ComputeISizeValue(aRenderingContext, aCBSize.ISize(aWM),
boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
*inlineStyleCoord, aFlags);
} else if (MOZ_UNLIKELY(isGridItem) &&
!IS_TRUE_OVERFLOW_CONTAINER(this)) {
// 'auto' inline-size for grid-level box - fill the CB for 'stretch' /
@@ -5701,28 +5716,28 @@ nsFrame::ComputeSize(gfxContext*
}
// Flex items ignore their min & max sizing properties in their
// flex container's main-axis. (Those properties get applied later in
// the flexbox algorithm.)
const nsStyleCoord& maxISizeCoord = stylePos->MaxISize(aWM);
nscoord maxISize = NS_UNCONSTRAINEDSIZE;
if (maxISizeCoord.GetUnit() != eStyleUnit_None &&
- !(isFlexItem && isInlineFlexItem)) {
+ !(isFlexItem && usingFlexBasisForISize)) {
maxISize =
ComputeISizeValue(aRenderingContext, aCBSize.ISize(aWM),
boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
maxISizeCoord, aFlags);
result.ISize(aWM) = std::min(maxISize, result.ISize(aWM));
}
const nsStyleCoord& minISizeCoord = stylePos->MinISize(aWM);
nscoord minISize;
if (minISizeCoord.GetUnit() != eStyleUnit_Auto &&
- !(isFlexItem && isInlineFlexItem)) {
+ !(isFlexItem && usingFlexBasisForISize)) {
minISize =
ComputeISizeValue(aRenderingContext, aCBSize.ISize(aWM),
boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
minISizeCoord, aFlags);
} else if (MOZ_UNLIKELY(aFlags & eIApplyAutoMinSize)) {
// This implements "Implied Minimum Size of Grid Items".
// https://drafts.csswg.org/css-grid/#min-size-auto
minISize = std::min(maxISize, GetMinISize(aRenderingContext));
@@ -5789,28 +5804,28 @@ nsFrame::ComputeSize(gfxContext*
}
}
}
const nsStyleCoord& maxBSizeCoord = stylePos->MaxBSize(aWM);
if (result.BSize(aWM) != NS_UNCONSTRAINEDSIZE) {
if (!nsLayoutUtils::IsAutoBSize(maxBSizeCoord, aCBSize.BSize(aWM)) &&
- !(isFlexItem && !isInlineFlexItem)) {
+ !(isFlexItem && !usingFlexBasisForISize)) {
nscoord maxBSize =
nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
maxBSizeCoord);
result.BSize(aWM) = std::min(maxBSize, result.BSize(aWM));
}
const nsStyleCoord& minBSizeCoord = stylePos->MinBSize(aWM);
if (!nsLayoutUtils::IsAutoBSize(minBSizeCoord, aCBSize.BSize(aWM)) &&
- !(isFlexItem && !isInlineFlexItem)) {
+ !(isFlexItem && !usingFlexBasisForISize)) {
nscoord minBSize =
nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM),
minBSizeCoord);
result.BSize(aWM) = std::max(minBSize, result.BSize(aWM));
}
}
@@ -5861,68 +5876,78 @@ nsFrame::ComputeSizeWithIntrinsicDimensi
const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM);
const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM);
auto* parentFrame = GetParent();
const bool isGridItem = parentFrame && parentFrame->IsGridContainerFrame() &&
!HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
const bool isFlexItem = parentFrame && parentFrame->IsFlexContainerFrame() &&
!parentFrame->HasAnyStateBits(NS_STATE_FLEX_IS_EMULATING_LEGACY_BOX) &&
!HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
- bool isInlineFlexItem = false;
+ // This bool only gets set (and used) if isFlexItem is true.
+ // It indicates (for flex items) whether we're using their flex-basis for the
+ // item's own ISize property vs. for its BSize property.
+ bool usingFlexBasisForISize;
Maybe<nsStyleCoord> imposedMainSizeStyleCoord;
// If this is a flex item, and we're measuring its cross size after flexing
// to resolve its main size, then we need to use the resolved main size
// that the container provides to us *instead of* the main-size coordinate
// from our style struct. (Otherwise, we'll be using an irrelevant value in
// the aspect-ratio calculations below.)
if (isFlexItem) {
uint32_t flexDirection =
GetParent()->StylePosition()->mFlexDirection;
- isInlineFlexItem =
+ const bool flexContainerIsRowOriented =
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
+ const bool inlineAxisSameAsParent =
+ !aWM.IsOrthogonalTo(parentFrame->GetWritingMode());
+
+ // (See explanatory comment in similar code within ComputeSize.)
+ usingFlexBasisForISize =
+ (flexContainerIsRowOriented == inlineAxisSameAsParent);
// If FlexItemMainSizeOverride frame-property is set, then that means the
// flex container is imposing a main-size on this flex item for it to use
// as its size in the container's main axis.
bool didImposeMainSize;
nscoord imposedMainSize =
GetProperty(nsIFrame::FlexItemMainSizeOverride(), &didImposeMainSize);
if (didImposeMainSize) {
imposedMainSizeStyleCoord.emplace(imposedMainSize,
nsStyleCoord::CoordConstructor);
- if (isInlineFlexItem) {
+ if (usingFlexBasisForISize) {
inlineStyleCoord = imposedMainSizeStyleCoord.ptr();
} else {
blockStyleCoord = imposedMainSizeStyleCoord.ptr();
}
} else {
// Flex items use their "flex-basis" property in place of their main-size
// property (e.g. "width") for sizing purposes, *unless* they have
// "flex-basis:auto", in which case they use their main-size property
// after all.
// NOTE: The logic here should match the similar chunk for determining
// inlineStyleCoord and blockStyleCoord in nsFrame::ComputeSize().
const nsStyleCoord* flexBasis = &(stylePos->mFlexBasis);
if (flexBasis->GetUnit() != eStyleUnit_Auto) {
- if (isInlineFlexItem) {
- inlineStyleCoord = flexBasis;
- } else {
- // One caveat for vertical flex items: We don't support enumerated
- // values (e.g. "max-content") for height properties yet. So, if our
- // computed flex-basis is an enumerated value, we'll just behave as if
- // it were "auto", which means "use the main-size property after all"
- // (which is "height", in this case).
- // NOTE: Once we support intrinsic sizing keywords for "height",
- // we should remove this check.
- if (flexBasis->GetUnit() != eStyleUnit_Enumerated) {
- blockStyleCoord = flexBasis;
- }
+ // One caveat for when flex-basis is stomping on 'height': We don't
+ // support enumerated values (e.g. "max-content") for height yet
+ // (that's bug 567039). So, if our computed flex-basis is an enumerated
+ // value, we'll just behave as if it were "auto", which means "use the
+ // main-size property after all" (which is "height", in this case).
+ // NOTE: Once we support intrinsic sizing keywords for "height", we
+ // should remove this check.
+ bool usingFlexBasisForHeight =
+ (usingFlexBasisForISize != aWM.IsVertical());
+ if (!usingFlexBasisForHeight ||
+ flexBasis->GetUnit() != eStyleUnit_Enumerated) {
+ // Override whichever coord we're overriding:
+ (usingFlexBasisForISize ? inlineStyleCoord : blockStyleCoord) =
+ flexBasis;
}
}
}
}
// Handle intrinsic sizes and their interaction with
// {min-,max-,}{width,height} according to the rules in
// http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
@@ -6025,32 +6050,32 @@ nsFrame::ComputeSizeWithIntrinsicDimensi
aFlags = ComputeSizeFlags(aFlags &
~ComputeSizeFlags::eIClampMarginBoxMinSize);
}
}
const nsStyleCoord& maxISizeCoord = stylePos->MaxISize(aWM);
if (maxISizeCoord.GetUnit() != eStyleUnit_None &&
- !(isFlexItem && isInlineFlexItem)) {
+ !(isFlexItem && usingFlexBasisForISize)) {
maxISize = ComputeISizeValue(aRenderingContext,
aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, maxISizeCoord, aFlags);
} else {
maxISize = nscoord_MAX;
}
// NOTE: Flex items ignore their min & max sizing properties in their
// flex container's main-axis. (Those properties get applied later in
// the flexbox algorithm.)
const nsStyleCoord& minISizeCoord = stylePos->MinISize(aWM);
if (minISizeCoord.GetUnit() != eStyleUnit_Auto &&
- !(isFlexItem && isInlineFlexItem)) {
+ !(isFlexItem && usingFlexBasisForISize)) {
minISize = ComputeISizeValue(aRenderingContext,
aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, minISizeCoord, aFlags);
} else {
// Treat "min-width: auto" as 0.
// NOTE: Technically, "auto" is supposed to behave like "min-content" on
// flex items. However, we don't need to worry about that here, because
// flex items' min-sizes are intentionally ignored until the flex
@@ -6094,27 +6119,27 @@ nsFrame::ComputeSizeWithIntrinsicDimensi
aFlags = ComputeSizeFlags(aFlags &
~ComputeSizeFlags::eBClampMarginBoxMinSize);
}
}
const nsStyleCoord& maxBSizeCoord = stylePos->MaxBSize(aWM);
if (!nsLayoutUtils::IsAutoBSize(maxBSizeCoord, aCBSize.BSize(aWM)) &&
- !(isFlexItem && !isInlineFlexItem)) {
+ !(isFlexItem && !usingFlexBasisForISize)) {
maxBSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM), maxBSizeCoord);
} else {
maxBSize = nscoord_MAX;
}
const nsStyleCoord& minBSizeCoord = stylePos->MinBSize(aWM);
if (!nsLayoutUtils::IsAutoBSize(minBSizeCoord, aCBSize.BSize(aWM)) &&
- !(isFlexItem && !isInlineFlexItem)) {
+ !(isFlexItem && !usingFlexBasisForISize)) {
minBSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
boxSizingAdjust.BSize(aWM), minBSizeCoord);
} else {
minBSize = 0;
}
NS_ASSERTION(aCBSize.ISize(aWM) != NS_UNCONSTRAINEDSIZE,
"Our containing block must not have unconstrained inline-size!");