diff options
Diffstat (limited to 'layout/generic')
-rw-r--r-- | layout/generic/nsContainerFrame.cpp | 25 | ||||
-rw-r--r-- | layout/generic/nsFrame.cpp | 98 | ||||
-rw-r--r-- | layout/generic/nsFrame.h | 13 |
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 |