summaryrefslogtreecommitdiff
path: root/layout/generic
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic')
-rw-r--r--layout/generic/nsContainerFrame.cpp25
-rw-r--r--layout/generic/nsFrame.cpp98
-rw-r--r--layout/generic/nsFrame.h13
3 files changed, 87 insertions, 49 deletions
diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
index 125d602635..dd20ccffee 100644
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -944,8 +944,29 @@ nsContainerFrame::ComputeAutoSize(nsRenderingContext* aRenderingContext,
aBorder.ISize(aWM) - aPadding.ISize(aWM);
// replaced elements always shrink-wrap
if ((aFlags & ComputeSizeFlags::eShrinkWrap) || IsFrameOfType(eReplaced)) {
- // don't bother setting it if the result won't be used
- if (StylePosition()->ISize(aWM).GetUnit() == eStyleUnit_Auto) {
+ const nsStylePosition* position = StylePosition();
+
+ bool isFlexBasisContent = false;
+ if (IsFlexItem()) {
+ uint32_t flexDirection =
+ GetParent()->StylePosition()->mFlexDirection;
+ bool isInlineFlexItem =
+ flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
+ flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
+ isFlexBasisContent =
+ position->mFlexBasis.GetUnit() == eStyleUnit_Enumerated &&
+ position->mFlexBasis.GetIntValue() == NS_STYLE_FLEX_BASIS_CONTENT &&
+ isInlineFlexItem;
+ }
+
+ // Only bother computing our 'auto' ISize if the result will be used.
+ // It'll be used under two scenarios:
+ // - If our ISize property is itself 'auto'.
+ // - If we're using flex-basis in place of our ISize property (i.e. we're a
+ // flex item with our inline axis being the main axis), AND we have
+ // flex-basis:content.
+ bool isAuto = position->ISize(aWM).GetUnit() == eStyleUnit_Auto;
+ if (isAuto || isFlexBasisContent) {
result.ISize(aWM) = ShrinkWidthToFit(aRenderingContext, availBased, aFlags);
}
} else {
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index 14d411e6ab..458b18abd9 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4635,6 +4635,54 @@ nsFrame::GetIntrinsicRatio()
return AspectRatio();
}
+void
+nsFrame::SetCoordToFlexBasis(bool aIsInlineFlexItem,
+ bool aIntrinsic,
+ const nsStyleCoord* aFlexBasis,
+ const nsStyleCoord** aInlineStyle,
+ const nsStyleCoord** aBlockStyle)
+{
+ auto mainAxisCoord = aIsInlineFlexItem ?
+ aInlineStyle :
+ aBlockStyle;
+ // We have a used flex-basis of 'content' if flex-basis explicitly has that
+ // value, OR if flex-basis is 'auto' (deferring to the main-size property)
+ // and the main-size property is also 'auto'.
+ // See https://drafts.csswg.org/css-flexbox-1/#valdef-flex-basis-auto
+ if ((aFlexBasis->GetUnit() == eStyleUnit_Enumerated &&
+ aFlexBasis->GetIntValue() == NS_STYLE_FLEX_BASIS_CONTENT) ||
+ (aFlexBasis->GetUnit() == eStyleUnit_Auto &&
+ (*mainAxisCoord)->GetUnit() == eStyleUnit_Auto)) {
+ // If we get here, we're resolving the flex base size for a flex item,
+ // and we fall into the flexbox spec section 9.2 step 3, substep C (if
+ // we have a definite cross size) or E (if not). And specifically:
+ //
+ // * If we have a definite cross size, we're supposed to resolve our
+ // main-size based on that and our intrinsic ratio.
+ // * Otherwise, we're supposed to produce our max-content size.
+ //
+ // Conveniently, we can handle both of those scenarios (regardless of
+ // which substep we fall into) by using the 'auto' keyword for our
+ // main-axis coordinate here. (This makes sense, because the spec is
+ // effectively trying to produce the 'auto' sizing behavior).
+ if (aIntrinsic) {
+ static const nsStyleCoord autoStyleCoord(eStyleUnit_Auto);
+ *mainAxisCoord = &autoStyleCoord;
+ } else {
+ // (Note: if our main axis is the block axis, then this 'max-content'
+ // value will be treated like 'auto', via the IsAutoBSize() call below.)
+ static const nsStyleCoord maxContStyleCoord(NS_STYLE_WIDTH_MAX_CONTENT,
+ eStyleUnit_Enumerated);
+ *mainAxisCoord = &maxContStyleCoord;
+ }
+ } else if (aFlexBasis->GetUnit() != eStyleUnit_Auto) {
+ // For all other non-'auto' flex-basis values, we just swap in the
+ // flex-basis itself for the main-size property.
+ *mainAxisCoord = aFlexBasis;
+ } // else: flex-basis is 'auto', which is deferring to some explicit
+ // value in mainAxisCoord. So we proceed w/o touching mainAxisCoord.
+}
+
/* virtual */
LogicalSize
nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
@@ -4689,35 +4737,14 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
!(GetStateBits() & NS_FRAME_OUT_OF_FLOW));
bool isInlineFlexItem = false;
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 =
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW ||
flexDirection == NS_STYLE_FLEX_DIRECTION_ROW_REVERSE;
- // 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;
- }
- }
- }
+ SetCoordToFlexBasis(isInlineFlexItem, false, flexBasis,
+ &inlineStyleCoord, &blockStyleCoord);
}
// Compute inline-axis size
@@ -4949,31 +4976,10 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
} 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;
- }
- }
- }
+ SetCoordToFlexBasis(isInlineFlexItem, true, flexBasis,
+ &inlineStyleCoord, &blockStyleCoord);
}
}
diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h
index d75555fec2..d703a62942 100644
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -266,6 +266,17 @@ public:
virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual mozilla::AspectRatio GetIntrinsicRatio() override;
+ /**
+ * Helper function for determining if flex items should use their
+ * 'flex-basis' property instead of their main-size property, such
+ * as 'width', for sizing purposes.
+ */
+ void SetCoordToFlexBasis(bool aIsInlineFlexItem,
+ bool aIntrinsic,
+ const nsStyleCoord* aFlexBasis,
+ const nsStyleCoord** aInlineStyle,
+ const nsStyleCoord** aBlockStyle);
+
virtual mozilla::LogicalSize
ComputeSize(nsRenderingContext* aRenderingContext,
mozilla::WritingMode aWM,
@@ -295,7 +306,7 @@ public:
// Compute tight bounds assuming this frame honours its border, background
// and outline, its children's tight bounds, and nothing else.
nsRect ComputeSimpleTightBounds(mozilla::gfx::DrawTarget* aDrawTarget) const;
-
+
/**
* A helper, used by |nsFrame::ComputeSize| (for frames that need to
* override only this part of ComputeSize), that computes the size