diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp index 9610730da9fd..4f6fa974cf8e 100644 --- a/layout/generic/ReflowInput.cpp +++ b/layout/generic/ReflowInput.cpp @@ -760,6 +760,13 @@ void ReflowInput::InitDynamicReflowRoot() { } } +bool ReflowInput::ShouldApplyAutomaticMinimumOnBlockAxis() const { + MOZ_ASSERT(!mFrame->IsFrameOfType(nsIFrame::eReplacedSizing)); + return mFlags.mIsBSizeSetByAspectRatio && + !mStyleDisplay->IsScrollableOverflow() && + mStylePosition->MinBSize(GetWritingMode()).IsAuto(); +} + /* static */ LogicalMargin ReflowInput::ComputeRelativeOffsets(WritingMode aWM, nsIFrame* aFrame, diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h index 2f3ccca4e732..f7294ec404ff 100644 --- a/layout/generic/ReflowInput.h +++ b/layout/generic/ReflowInput.h @@ -842,6 +842,15 @@ struct ReflowInput : public SizeComputationInput { return mDiscoveredClearance && *mDiscoveredClearance; } + // Returns true if we should apply automatic minimum on the block axis. + // + // The automatic minimum size in the ratio-dependent axis of a box with a + // preferred aspect ratio that is neither a replaced element nor a scroll + // container is its min-content size clamped from above by its maximum size. + // + // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum + bool ShouldApplyAutomaticMinimumOnBlockAxis() const; + // Compute the offsets for a relative position element // // @param aWM the writing mode of aCBSize and the returned offsets. diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index fbbc90ab532a..00b60db5979f 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1836,19 +1836,6 @@ static nscoord ApplyLineClamp(const ReflowInput& aReflowInput, return edge; } -static bool ShouldApplyAutomaticMinimumOnBlockAxis( - WritingMode aWM, const nsStyleDisplay* aDisplay, - const nsStylePosition* aPosition) { - // The automatic minimum size in the ratio-dependent axis of a box with a - // preferred aspect ratio that is neither a replaced element nor a scroll - // container is its min-content size clamped from above by its maximum size. - // - // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum - // Note: we only need to check scroll container because replaced element - // doesn't go into nsBlockFrame::Reflow(). - return !aDisplay->IsScrollableOverflow() && aPosition->MinBSize(aWM).IsAuto(); -} - void nsBlockFrame::ComputeFinalSize(const ReflowInput& aReflowInput, BlockReflowState& aState, ReflowOutput& aMetrics, @@ -1930,9 +1917,7 @@ void nsBlockFrame::ComputeFinalSize(const ReflowInput& aReflowInput, // If the content block-size is larger than the effective computed // block-size, we extend the block-size to contain all the content. // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum - if (aReflowInput.mFlags.mIsBSizeSetByAspectRatio && - ShouldApplyAutomaticMinimumOnBlockAxis(wm, aReflowInput.mStyleDisplay, - aReflowInput.mStylePosition)) { + if (aReflowInput.ShouldApplyAutomaticMinimumOnBlockAxis()) { // Note: finalSize.BSize(wm) is the border-box size, so we compare it with // the content's block-size plus our border and padding.. finalSize.BSize(wm) = diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 4aa405f75f98..90da61059ba5 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -4305,7 +4305,10 @@ nscoord nsFlexContainerFrame::ComputeMainSize( return aTentativeContentBoxMainSize; } - if (aTentativeContentBoxMainSize != NS_UNCONSTRAINEDSIZE) { + const bool shouldApplyAutomaticMinimumOnBlockAxis = + aReflowInput.ShouldApplyAutomaticMinimumOnBlockAxis(); + if (aTentativeContentBoxMainSize != NS_UNCONSTRAINEDSIZE && + !shouldApplyAutomaticMinimumOnBlockAxis) { // Column-oriented case, with fixed BSize: // Just use our fixed block-size because we always assume the available // block-size is unconstrained, and the reflow input has already done the @@ -4319,13 +4322,24 @@ nscoord nsFlexContainerFrame::ComputeMainSize( return aReflowInput.ComputedMinBSize(); } + const AuCoord64 largestLineMainSize = GetLargestLineMainSize(aLines); + const nscoord contentBSize = NS_CSS_MINMAX( + nscoord(largestLineMainSize.ToMinMaxClamped()), + aReflowInput.ComputedMinBSize(), aReflowInput.ComputedMaxBSize()); + // If the clamped largest FlexLine length is larger than the tentative main + // size (which is resolved by aspect-ratio), we extend it to contain the + // entire FlexLine. + // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum + if (shouldApplyAutomaticMinimumOnBlockAxis) { + // Column-oriented case, with auto BSize which is resolved by + // aspect-ratio. + return std::max(contentBSize, aTentativeContentBoxMainSize); + } + // Column-oriented case, with auto BSize: // Resolve auto BSize to the largest FlexLine length, clamped to our // computed min/max main-size properties. - const AuCoord64 largestLineMainSize = GetLargestLineMainSize(aLines); - return NS_CSS_MINMAX(nscoord(largestLineMainSize.ToMinMaxClamped()), - aReflowInput.ComputedMinBSize(), - aReflowInput.ComputedMaxBSize()); + return contentBSize; } nscoord nsFlexContainerFrame::ComputeCrossSize( @@ -4349,8 +4363,11 @@ nscoord nsFlexContainerFrame::ComputeCrossSize( return aTentativeContentBoxCrossSize; } + const bool shouldApplyAutomaticMinimumOnBlockAxis = + aReflowInput.ShouldApplyAutomaticMinimumOnBlockAxis(); const nscoord computedBSize = aReflowInput.ComputedBSize(); - if (computedBSize != NS_UNCONSTRAINEDSIZE) { + if (computedBSize != NS_UNCONSTRAINEDSIZE && + !shouldApplyAutomaticMinimumOnBlockAxis) { // Row-oriented case (cross axis is block-axis), with fixed BSize: *aIsDefinite = true; @@ -4367,12 +4384,25 @@ nscoord nsFlexContainerFrame::ComputeCrossSize( return aReflowInput.ComputedMinBSize(); } + // The cross size must not be definite in the following cases. + *aIsDefinite = false; + + const nscoord contentBSize = + NS_CSS_MINMAX(aSumLineCrossSizes, aReflowInput.ComputedMinBSize(), + aReflowInput.ComputedMaxBSize()); + // If the content block-size is larger than the effective computed + // block-size, we extend the block-size to contain all the content. + // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum + if (shouldApplyAutomaticMinimumOnBlockAxis) { + // Row-oriented case (cross axis is block-axis), with auto BSize which is + // resolved by aspect-ratio or content size. + return std::max(contentBSize, computedBSize); + } + // Row-oriented case (cross axis is block axis), with auto BSize: // Shrink-wrap our line(s), subject to our min-size / max-size // constraints in that (block) axis. - *aIsDefinite = false; - return NS_CSS_MINMAX(aSumLineCrossSizes, aReflowInput.ComputedMinBSize(), - aReflowInput.ComputedMaxBSize()); + return contentBSize; } LogicalSize nsFlexContainerFrame::ComputeAvailableSizeForItems( diff --git a/testing/web-platform/tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-040.html b/testing/web-platform/tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-040.html new file mode 100644 index 000000000000..dc5c74a3d4f2 --- /dev/null +++ b/testing/web-platform/tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-040.html @@ -0,0 +1,24 @@ + +
Test passes if there is a filled green square and no red.
+Test passes if there is a filled green square and no red.
+