Bug 1760658 - Part 1: Apply automatic content-based minimum on flex container. r=emilio

Basides, factor out the utility function to AspectRatio so everyone can
use it.

Differential Revision: https://phabricator.services.mozilla.com/D144891
This commit is contained in:
Boris Chiou 2022-05-02 20:06:32 +00:00
Родитель c5077a5261
Коммит 035220bf4c
6 изменённых файлов: 106 добавлений и 25 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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.

Просмотреть файл

@ -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) =

Просмотреть файл

@ -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(

Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE html>
<title>CSS aspect-ratio: Test flex container's cross size (block axis) honoring automatic content-based minimum</title>
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
<style>
#container {
display: flex;
width: 100px;
aspect-ratio: 2 / 1;
background: green;
}
#item {
width: 100%;
height: 100px;
}
</style>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="container">
<div id="item"></div>
</div>
</body>

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE html>
<title>CSS aspect-ratio: Test flex container's main size (block axis) honoring automatic content-based minimum</title>
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
<style>
#container {
display: flex;
flex-direction: column;
background: green;
width: 100px;
aspect-ratio: 2 / 1;
}
#item {
width: 100%;
height: 100px;
flex: none
}
</style>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="container">
<div id="item"></div>
</div>
</body>