From 2f8e9dec2abdff190ec339adf069a481b197c5d4 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 22 Jul 2014 08:24:37 -0700 Subject: [PATCH] Bug 1015474 part 1: Update behavior of "min-width:auto"/"min-height:auto" to match current spec text. r=mats This updates min-width:auto / min-height:auto to now take several more things into account, beyond just a flex item's min-content size. Now we'll also consider its used 'flex-basis', its main max-size property ('max-width' or 'max-height'), and its intrinsic ratio & any constraints in the other dimension. --- layout/generic/nsFlexContainerFrame.cpp | 416 ++++++++++++++++++++---- layout/generic/nsFlexContainerFrame.h | 2 +- layout/generic/nsHTMLReflowState.cpp | 22 +- 3 files changed, 362 insertions(+), 78 deletions(-) diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 699e2de03e3..dc23d19f4c9 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -15,6 +15,7 @@ #include "nsLayoutUtils.h" #include "nsPlaceholderFrame.h" #include "nsPresContext.h" +#include "nsRenderingContext.h" #include "nsStyleContext.h" #include "prlog.h" #include @@ -271,7 +272,11 @@ public: nsIFrame* Frame() const { return mFrame; } nscoord GetFlexBaseSize() const { return mFlexBaseSize; } - nscoord GetMainMinSize() const { return mMainMinSize; } + nscoord GetMainMinSize() const { + MOZ_ASSERT(!mNeedsMinSizeAutoResolution, + "Someone's using an unresolved 'auto' main min-size"); + return mMainMinSize; + } nscoord GetMainMaxSize() const { return mMainMaxSize; } // Note: These return the main-axis position and size of our *content box*. @@ -322,6 +327,11 @@ public: // cross axis). bool IsStretched() const { return mIsStretched; } + // Indicates whether we need to resolve an 'auto' value for the main-axis + // min-[width|height] property. + bool NeedsMinSizeAutoResolution() const + { return mNeedsMinSizeAutoResolution; } + // Indicates whether this item is a "strut" left behind by an element with // visibility:collapse. bool IsStrut() const { return mIsStrut; } @@ -417,21 +427,27 @@ public: // Setters // ======= - + // Helper to set the resolved value of min-[width|height]:auto for the main + // axis. (Should only be used if NeedsMinSizeAutoResolution() returns true.) void UpdateMainMinSize(nscoord aNewMinSize) { - MOZ_ASSERT(mMainMinSize == 0 || - mFrame->IsThemed(mFrame->StyleDisplay()), - "Should only update main min-size for min-height:auto, " - "which would initially be resolved as 0 (unless we have an " - "additional themed-widget-imposed minimum size)"); + NS_ASSERTION(aNewMinSize >= 0, + "How did we end up with a negative min-size?"); + MOZ_ASSERT(mMainMaxSize >= aNewMinSize, + "Should only use this function for resolving min-size:auto, " + "and main max-size should be an upper-bound for resolved val"); + MOZ_ASSERT(mNeedsMinSizeAutoResolution && + (mMainMinSize == 0 || mFrame->IsThemed(mFrame->StyleDisplay())), + "Should only use this function for resolving min-size:auto, " + "so we shouldn't already have a nonzero min-size established " + "(unless it's a themed-widget-imposed minimum size)"); if (aNewMinSize > mMainMinSize) { mMainMinSize = aNewMinSize; - // Clamp main-max-size & main-size to be >= new min-size: - mMainMaxSize = std::max(mMainMaxSize, aNewMinSize); + // Also clamp main-size to be >= new min-size: mMainSize = std::max(mMainSize, aNewMinSize); } + mNeedsMinSizeAutoResolution = false; } // This sets our flex base size, and then sets our main size to the @@ -539,6 +555,10 @@ public: uint32_t GetNumAutoMarginsInAxis(AxisOrientationType aAxis) const; protected: + // Helper called by the constructor, to set mNeedsMinSizeAutoResolution: + void CheckForMinSizeAuto(const nsHTMLReflowState& aFlexItemReflowState, + const FlexboxAxisTracker& aAxisTracker); + // Our frame: nsIFrame* const mFrame; @@ -582,6 +602,10 @@ protected: bool mIsStretched; // See IsStretched() documentation bool mIsStrut; // Is this item a "strut" left behind by an element // with visibility:collapse? + + // Does this item need to resolve a min-[width|height]:auto (in main-axis). + bool mNeedsMinSizeAutoResolution; + uint8_t mAlignSelf; // My "align-self" computed value (with "auto" // swapped out for parent"s "align-items" value, // in our constructor). @@ -1030,80 +1054,321 @@ nsFlexContainerFrame::GenerateFlexItemForChild( item->Freeze(); } - // Resolve "flex-basis:auto" and/or "min-height:auto" (which might + // Resolve "flex-basis:auto" and/or "min-[width|height]:auto" (which might // require us to reflow the item to measure content height) ResolveAutoFlexBasisAndMinSize(aPresContext, *item, - aParentReflowState, aAxisTracker); - + childRS, aAxisTracker); return item; } +// Static helper-functions for ResolveAutoFlexBasisAndMinSize(): +// ------------------------------------------------------------- +// Indicates whether the cross-size property is set to something definite. +// The logic here should be similar to the logic for isAutoWidth/isAutoHeight +// in nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(). +static bool +IsCrossSizeDefinite(const nsHTMLReflowState& aItemReflowState, + const FlexboxAxisTracker& aAxisTracker) +{ + const nsStylePosition* pos = aItemReflowState.mStylePosition; + if (IsAxisHorizontal(aAxisTracker.GetCrossAxis())) { + return pos->mWidth.GetUnit() != eStyleUnit_Auto; + } + // else, vertical. (We need to use IsAutoHeight() to catch e.g. %-height + // applied to indefinite-height containing block, which counts as auto.) + nscoord cbHeight = aItemReflowState.mCBReflowState->ComputedHeight(); + return !nsLayoutUtils::IsAutoHeight(pos->mHeight, cbHeight); +} + +// If aFlexItem has a definite cross size, this function returns it, for usage +// (in combination with an intrinsic ratio) for resolving the item's main size +// or main min-size. +// +// The parameter "aMinSizeFallback" indicates whether we should fall back to +// returning the cross min-size, when the cross size is indefinite. (This param +// should be set IFF the caller intends to resolve the main min-size.) If this +// param is true, then this function is guaranteed to return a definite value +// (i.e. not NS_AUTOHEIGHT, excluding cases where huge sizes are involved). +// +// XXXdholbert the min-size behavior here is based on my understanding in +// http://lists.w3.org/Archives/Public/www-style/2014Jul/0053.html +// If my understanding there ends up being wrong, we'll need to update this. +static nscoord +CrossSizeToUseWithRatio(const FlexItem& aFlexItem, + const nsHTMLReflowState& aItemReflowState, + bool aMinSizeFallback, + const FlexboxAxisTracker& aAxisTracker) +{ + if (aFlexItem.IsStretched()) { + // Definite cross-size, imposed via 'align-self:stretch' & flex container. + return aFlexItem.GetCrossSize(); + } + + if (IsCrossSizeDefinite(aItemReflowState, aAxisTracker)) { + // Definite cross size. + return GET_CROSS_COMPONENT(aAxisTracker, + aItemReflowState.ComputedWidth(), + aItemReflowState.ComputedHeight()); + } + + if (aMinSizeFallback) { + // Indefinite cross-size, and we're resolving main min-size, so we'll fall + // back to ussing the cross min-size (which should be definite). + return GET_CROSS_COMPONENT(aAxisTracker, + aItemReflowState.ComputedMinWidth(), + aItemReflowState.ComputedMinHeight()); + } + + // Indefinite cross-size. + return NS_AUTOHEIGHT; +} + +// XXX This macro shamelessly stolen from nsLayoutUtils.cpp. +// (Maybe it should be exposed via a nsLayoutUtils method?) +#define MULDIV(a,b,c) (nscoord(int64_t(a) * int64_t(b) / int64_t(c))) + +// Convenience function; returns a main-size, given a cross-size and an +// intrinsic ratio. The intrinsic ratio must not have 0 in its cross-axis +// component (or else we'll divide by 0). +static nscoord +MainSizeFromAspectRatio(nscoord aCrossSize, + const nsSize& aIntrinsicRatio, + const FlexboxAxisTracker& aAxisTracker) +{ + MOZ_ASSERT(aAxisTracker.GetCrossComponent(aIntrinsicRatio) != 0, + "Invalid ratio; will divide by 0! Caller should've checked..."); + + if (IsAxisHorizontal(aAxisTracker.GetCrossAxis())) { + // cross axis horiz --> aCrossSize is a width. Converting to height. + return MULDIV(aCrossSize, aIntrinsicRatio.height, aIntrinsicRatio.width); + } + // cross axis vert --> aCrossSize is a height. Converting to width. + return MULDIV(aCrossSize, aIntrinsicRatio.width, aIntrinsicRatio.height); +} + +// Partially resolves "min-[width|height]:auto" and returns the resulting value. +// By "partially", I mean we don't consider the min-content size (but we do +// consider flex-basis, main max-size, and the intrinsic aspect ratio). +// The caller is responsible for computing & considering the min-content size +// in combination with the partially-resolved value that this function returns. +// +// Spec reference: http://dev.w3.org/csswg/css-flexbox/#min-size-auto +static nscoord +PartiallyResolveAutoMinSize(const FlexItem& aFlexItem, + const nsHTMLReflowState& aItemReflowState, + const nsSize& aIntrinsicRatio, + const FlexboxAxisTracker& aAxisTracker) +{ + MOZ_ASSERT(aFlexItem.NeedsMinSizeAutoResolution(), + "only call for FlexItems that need min-size auto resolution"); + + nscoord minMainSize = nscoord_MAX; // Intentionally huge; we'll shrink it + // from here, w/ std::min(). + + // We need the smallest of: + // * the used flex-basis, if the computed flex-basis was 'auto': + // XXXdholbert ('auto' might be renamed to 'main-size'; see bug 1032922) + if (eStyleUnit_Auto == + aItemReflowState.mStylePosition->mFlexBasis.GetUnit() && + aFlexItem.GetFlexBaseSize() != NS_AUTOHEIGHT) { + // NOTE: We skip this if the flex base size depends on content & isn't yet + // resolved. This is OK, because the caller is responsible for computing + // the min-content height and min()'ing it with the value we return, which + // is equivalent to what would happen if we min()'d that at this point. + minMainSize = std::min(minMainSize, aFlexItem.GetFlexBaseSize()); + } + + // * the computed max-width (max-height), if that value is definite: + nscoord maxSize = + GET_MAIN_COMPONENT(aAxisTracker, + aItemReflowState.ComputedMaxWidth(), + aItemReflowState.ComputedMaxHeight()); + if (maxSize != NS_UNCONSTRAINEDSIZE) { + minMainSize = std::min(minMainSize, maxSize); + } + + // * if the item has no intrinsic aspect ratio, its min-content size: + // --- SKIPPING THIS IN THIS FUNCTION --- caller's responsibility. + + // * if the item has an intrinsic aspect ratio, the width (height) calculated + // from the aspect ratio and any definite size constraints in the opposite + // dimension. + if (aAxisTracker.GetCrossComponent(aIntrinsicRatio) != 0) { + // We have a usable aspect ratio. (not going to divide by 0) + const bool useMinSizeIfCrossSizeIsIndefinite = true; + nscoord crossSizeToUseWithRatio = + CrossSizeToUseWithRatio(aFlexItem, aItemReflowState, + useMinSizeIfCrossSizeIsIndefinite, + aAxisTracker); + nscoord minMainSizeFromRatio = + MainSizeFromAspectRatio(crossSizeToUseWithRatio, + aIntrinsicRatio, aAxisTracker); + minMainSize = std::min(minMainSize, minMainSizeFromRatio); + } + + return minMainSize; +} + +// Resolves flex-basis:auto, using the given intrinsic ratio and the flex +// item's cross size. On success, updates the flex item with its resolved +// flex-basis and returns true. On failure (e.g. if the ratio is invalid or +// the cross-size is indefinite), returns false. +static bool +ResolveAutoFlexBasisFromRatio(FlexItem& aFlexItem, + const nsHTMLReflowState& aItemReflowState, + const nsSize& aIntrinsicRatio, + const FlexboxAxisTracker& aAxisTracker) +{ + MOZ_ASSERT(NS_AUTOHEIGHT == aFlexItem.GetFlexBaseSize(), + "Should only be called to resolve an 'auto' flex-basis"); + // If the flex item has ... + // - an intrinsic aspect ratio, + // - a [used] flex-basis of 'main-size' [auto?] [We have this, if we're here.] + // - a definite cross size + // then the flex base size is calculated from its inner cross size and the + // flex item’s intrinsic aspect ratio. + if (aAxisTracker.GetCrossComponent(aIntrinsicRatio) != 0) { + // We have a usable aspect ratio. (not going to divide by 0) + const bool useMinSizeIfCrossSizeIsIndefinite = false; + nscoord crossSizeToUseWithRatio = + CrossSizeToUseWithRatio(aFlexItem, aItemReflowState, + useMinSizeIfCrossSizeIsIndefinite, + aAxisTracker); + if (crossSizeToUseWithRatio != NS_AUTOHEIGHT) { + // We have a definite cross-size + nscoord mainSizeFromRatio = + MainSizeFromAspectRatio(crossSizeToUseWithRatio, + aIntrinsicRatio, aAxisTracker); + aFlexItem.SetFlexBaseSizeAndMainSize(mainSizeFromRatio); + return true; + } + } + return false; +} + +// Note: If & when we handle "min-height: min-content" for flex items, +// we may want to resolve that in this function, too. void nsFlexContainerFrame:: ResolveAutoFlexBasisAndMinSize(nsPresContext* aPresContext, FlexItem& aFlexItem, - const nsHTMLReflowState& aParentReflowState, + const nsHTMLReflowState& aItemReflowState, const FlexboxAxisTracker& aAxisTracker) { - if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) { - // Nothing to do -- this function is only for measuring flex items - // in a vertical flex container. - return; - } + // (Note: We should never have a used flex-basis of "auto" if our main axis + // is horizontal; width values should always be resolvable without reflow.) + const bool isMainSizeAuto = (!IsAxisHorizontal(aAxisTracker.GetMainAxis()) && + NS_AUTOHEIGHT == aFlexItem.GetFlexBaseSize()); - // Both "flex-basis:auto;height:auto" & "min-height:auto" require that we - // resolve our max-content height. - bool isMainSizeAuto = (NS_AUTOHEIGHT == aFlexItem.GetFlexBaseSize()); - - // 'min-height:auto' is treated as 0 in most code (e.g. in the reflow state), - // so we have to actually go the source & check the style struct: - bool isMainMinSizeAuto = - (eStyleUnit_Auto == - aFlexItem.Frame()->StylePosition()->mMinHeight.GetUnit()); + const bool isMainMinSizeAuto = aFlexItem.NeedsMinSizeAutoResolution(); if (!isMainSizeAuto && !isMainMinSizeAuto) { - // Nothing to do; this function's only relevant for flex items - // with a base size of "auto" (or equivalent). - // XXXdholbert If & when we handle "min-height: min-content" for flex items, - // we'll want to resolve that in this function, too. + // Nothing to do; this function is only needed for flex items + // with a used flex-basis of "auto" or a min-main-size of "auto". return; } - // For single-line vertical flexbox, we need to give our flex items an early - // opportunity to stretch, since any stretching of their cross-size (width) - // will likely impact the max-content main-size (height) that we're about to - // measure for them. (We can't do this for multi-line, since we don't know - // yet how many lines there will be & how much each line will stretch.) - if (NS_STYLE_FLEX_WRAP_NOWRAP == - aParentReflowState.mStylePosition->mFlexWrap) { - aFlexItem.ResolveStretchedCrossSize(aParentReflowState.ComputedWidth(), - aAxisTracker); + // We may be about to do computations based on our item's cross-size + // (e.g. using it as a contstraint when measuring our content in the + // main axis, or using it with the intrinsic ratio to obtain a main size). + // BEFORE WE DO THAT, we need let the item "pre-stretch" its cross size (if + // it's got 'align-self:stretch'), for a certain case where the spec says + // the stretched cross size is considered "definite". That case is if we + // have a single-line (nowrap) flex container which itself has a definite + // cross-size. Otherwise, we'll wait to do stretching, since (in other + // cases) we don't know how much the item should stretch yet. + const nsHTMLReflowState* flexContainerRS = aItemReflowState.parentReflowState; + MOZ_ASSERT(flexContainerRS, + "flex item's reflow state should have ptr to container's state"); + if (NS_STYLE_FLEX_WRAP_NOWRAP == flexContainerRS->mStylePosition->mFlexWrap) { + // XXXdholbert Maybe this should share logic with ComputeCrossSize()... + // Alternately, maybe tentative container cross size should be passed down. + nscoord containerCrossSize = + GET_CROSS_COMPONENT(aAxisTracker, + flexContainerRS->ComputedWidth(), + flexContainerRS->ComputedHeight()); + // Is container's cross size "definite"? + // (Container's cross size is definite if cross-axis is horizontal, or if + // cross-axis is vertical and the cross-size is not NS_AUTOHEIGHT.) + if (IsAxisHorizontal(aAxisTracker.GetCrossAxis()) || + containerCrossSize != NS_AUTOHEIGHT) { + aFlexItem.ResolveStretchedCrossSize(containerCrossSize, aAxisTracker); + } } - // If this item is flexible (vertically), or if we're measuring the - // 'auto' min-height and our main-size is something else, then we assume - // that the computed-height we're reflowing with now could be different - // from the one we'll use for this flex item's "actual" reflow later on. - // In that case, we need to be sure the flex item treats this as a - // vertical resize, even though none of its ancestors are necessarily - // being vertically resized. - // (Note: We don't have to do this for width, because InitResizeFlags - // will always turn on mHResize on when it sees that the computed width - // is different from current width, and that's all we need.) - bool forceVerticalResizeForMeasuringReflow = - !aFlexItem.IsFrozen() || // Is the item flexible? - !isMainSizeAuto; // Are we *only* measuring it for 'min-height:auto'? + // We'll need the intrinsic ratio (if there is one), regardless of whether + // we're resolving min-[width|height]:auto or flex-basis:auto. + const nsSize ratio = aFlexItem.Frame()->GetIntrinsicRatio(); - nscoord contentHeight = - MeasureFlexItemContentHeight(aPresContext, aFlexItem, - forceVerticalResizeForMeasuringReflow, - aParentReflowState); - - if (isMainSizeAuto) { - aFlexItem.SetFlexBaseSizeAndMainSize(contentHeight); - } + nscoord resolvedMinSize; // (only set/used if isMainMinSizeAuto==true) + bool minSizeNeedsToMeasureContent = false; // assume the best if (isMainMinSizeAuto) { - aFlexItem.UpdateMainMinSize(contentHeight); + // Resolve the min-size, except for considering the min-content size. + // (We'll consider that later, if we need to.) + resolvedMinSize = PartiallyResolveAutoMinSize(aFlexItem, aItemReflowState, + ratio, aAxisTracker); + if (resolvedMinSize > 0 && + aAxisTracker.GetCrossComponent(ratio) == 0) { + // We don't have a usable aspect ratio, so we need to consider our + // min-content size as another candidate min-size, which we'll have to + // min() with the current resolvedMinSize. + // (If resolvedMinSize were already at 0, we could skip this measurement + // because it can't go any lower. But it's not 0, so we need it.) + minSizeNeedsToMeasureContent = true; + } + } + + bool flexBasisNeedsToMeasureContent = false; // assume the best + if (isMainSizeAuto) { + if (!ResolveAutoFlexBasisFromRatio(aFlexItem, aItemReflowState, + ratio, aAxisTracker)) { + flexBasisNeedsToMeasureContent = true; + } + } + + // Measure content, if needed (w/ intrinsic-width method or a reflow) + if (minSizeNeedsToMeasureContent || flexBasisNeedsToMeasureContent) { + if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) { + nsRefPtr rctx = + aPresContext->PresShell()->CreateReferenceRenderingContext(); + if (minSizeNeedsToMeasureContent) { + resolvedMinSize = std::min(resolvedMinSize, aFlexItem.Frame()->GetMinWidth(rctx)); + } + NS_ASSERTION(!flexBasisNeedsToMeasureContent, + "flex-basis:auto should have been resolved in the " + "reflow state, for horizontal flexbox. It shouldn't need " + "special handling here"); + } else { + // If this item is flexible (vertically), or if we're measuring the + // 'auto' min-height and our main-size is something else, then we assume + // that the computed-height we're reflowing with now could be different + // from the one we'll use for this flex item's "actual" reflow later on. + // In that case, we need to be sure the flex item treats this as a + // vertical resize, even though none of its ancestors are necessarily + // being vertically resized. + // (Note: We don't have to do this for width, because InitResizeFlags + // will always turn on mHResize on when it sees that the computed width + // is different from current width, and that's all we need.) + bool forceVerticalResizeForMeasuringReflow = + !aFlexItem.IsFrozen() || // Is the item flexible? + !flexBasisNeedsToMeasureContent; // Are we *only* measuring it for + // 'min-height:auto'? + + nscoord contentHeight = + MeasureFlexItemContentHeight(aPresContext, aFlexItem, + forceVerticalResizeForMeasuringReflow, + *flexContainerRS); + if (minSizeNeedsToMeasureContent) { + resolvedMinSize = std::min(resolvedMinSize, contentHeight); + } + if (flexBasisNeedsToMeasureContent) { + aFlexItem.SetFlexBaseSizeAndMainSize(contentHeight); + } + } + } + + if (isMainMinSizeAuto) { + aFlexItem.UpdateMainMinSize(resolvedMinSize); } } @@ -1183,6 +1448,7 @@ FlexItem::FlexItem(nsHTMLReflowState& aFlexItemReflowState, mHadMeasuringReflow(false), mIsStretched(false), mIsStrut(false), + // mNeedsMinSizeAutoResolution is initialized in CheckForMinSizeAuto() mAlignSelf(aFlexItemReflowState.mStylePosition->mAlignSelf) { MOZ_ASSERT(mFrame, "expecting a non-null child frame"); @@ -1192,6 +1458,7 @@ FlexItem::FlexItem(nsHTMLReflowState& aFlexItemReflowState, "out-of-flow frames should not be treated as flex items"); SetFlexBaseSizeAndMainSize(aFlexBaseSize); + CheckForMinSizeAuto(aFlexItemReflowState, aAxisTracker); // Assert that any "auto" margin components are set to 0. // (We'll resolve them later; until then, we want to treat them as 0-sized.) @@ -1256,6 +1523,7 @@ FlexItem::FlexItem(nsIFrame* aChildFrame, nscoord aCrossSize) mHadMeasuringReflow(false), mIsStretched(false), mIsStrut(true), // (this is the constructor for making struts, after all) + mNeedsMinSizeAutoResolution(false), mAlignSelf(NS_STYLE_ALIGN_ITEMS_FLEX_START) { MOZ_ASSERT(mFrame, "expecting a non-null child frame"); @@ -1268,6 +1536,30 @@ FlexItem::FlexItem(nsIFrame* aChildFrame, nscoord aCrossSize) "out-of-flow frames should not be treated as flex items"); } +void +FlexItem::CheckForMinSizeAuto(const nsHTMLReflowState& aFlexItemReflowState, + const FlexboxAxisTracker& aAxisTracker) +{ + const nsStylePosition* pos = aFlexItemReflowState.mStylePosition; + const nsStyleDisplay* disp = aFlexItemReflowState.mStyleDisplay; + + // We'll need special behavior for "min-[width|height]:auto" (whichever is in + // the main axis) iff: + // (a) its computed value is "auto" + // (b) the "overflow" sub-property in the same axis (the main axis) has a + // computed value of "visible" + const nsStyleCoord& minSize = GET_MAIN_COMPONENT(aAxisTracker, + pos->mMinWidth, + pos->mMinHeight); + + const uint8_t overflowVal = GET_MAIN_COMPONENT(aAxisTracker, + disp->mOverflowX, + disp->mOverflowY); + + mNeedsMinSizeAutoResolution = (minSize.GetUnit() == eStyleUnit_Auto && + overflowVal == NS_STYLE_OVERFLOW_VISIBLE); +} + nscoord FlexItem::GetBaselineOffsetFromOuterCrossEdge(AxisOrientationType aCrossAxis, AxisEdgeType aEdge) const diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h index 73a490704b6..6c417bb06e3 100644 --- a/layout/generic/nsFlexContainerFrame.h +++ b/layout/generic/nsFlexContainerFrame.h @@ -140,7 +140,7 @@ protected: */ void ResolveAutoFlexBasisAndMinSize(nsPresContext* aPresContext, FlexItem& aFlexItem, - const nsHTMLReflowState& aParentReflowState, + const nsHTMLReflowState& aItemReflowState, const FlexboxAxisTracker& aAxisTracker); // Creates FlexItems for all of our child frames, arranged in a list of diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index d22d63beff6..5306b414e5c 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -2595,18 +2595,11 @@ nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, const nsHTMLReflowState* aContainingBlockRS) { - // Handle "min-width: auto" + // NOTE: min-width:auto resolves to 0, except on a flex item. (But + // even there, it's supposed to be ignored (i.e. treated as 0) until + // the flex container explicitly resolves & considers it.) if (eStyleUnit_Auto == mStylePosition->mMinWidth.GetUnit()) { - nsFlexContainerFrame* flexContainerFrame = GetFlexContainer(frame); - if (flexContainerFrame && flexContainerFrame->IsHorizontal()) { - ComputedMinWidth() = - ComputeWidthValue(aContainingBlockWidth, - mStylePosition->mBoxSizing, - nsStyleCoord(NS_STYLE_WIDTH_MIN_CONTENT, - eStyleUnit_Enumerated)); - } else { - ComputedMinWidth() = 0; - } + ComputedMinWidth() = 0; } else { ComputedMinWidth() = ComputeWidthValue(aContainingBlockWidth, mStylePosition->mBoxSizing, @@ -2635,10 +2628,9 @@ nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth, // Likewise, if we're a child of a flex container who's measuring our // intrinsic height, then we want to disregard our min-height. - // NOTE: We treat "min-height:auto" as "0" for the purpose of this code, - // since that's what it means in all cases except for on flex items -- and - // even there, we're supposed to ignore it (i.e. treat it as 0) until the - // flex container explicitly considers it. + // NOTE: min-height:auto resolves to 0, except on a flex item. (But + // even there, it's supposed to be ignored (i.e. treated as 0) until + // the flex container explicitly resolves & considers it.) const nsStyleCoord &minHeight = mStylePosition->mMinHeight; if (eStyleUnit_Auto == minHeight.GetUnit() || (NS_AUTOHEIGHT == aContainingBlockHeight &&