зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1690422 - Resolve {min|max}-content contribution with the preferred aspect ratio and the definite block size. r=TYLin
This is simliar with the previous patch, but we use min-content/max-content for the inner div (i.e. child frame). Perhaps we could remove the simliar implementation from ComputeISizeValue(). However, I still keep it because it can avoid some extra work when resolving {min|max}-content with aspect-ratio when reflowing. Differential Revision: https://phabricator.services.mozilla.com/D104476
This commit is contained in:
Родитель
181e91cf22
Коммит
d9de5c2358
|
@ -4478,6 +4478,7 @@ static nscoord GetDefiniteSizeTakenByBoxSizing(
|
|||
enum eWidthProperty { PROP_WIDTH, PROP_MAX_WIDTH, PROP_MIN_WIDTH };
|
||||
static bool GetIntrinsicCoord(StyleExtremumLength aStyle,
|
||||
gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
Maybe<nscoord> aInlineSizeFromAspectRatio,
|
||||
eWidthProperty aProperty, nscoord& aResult) {
|
||||
MOZ_ASSERT(aProperty == PROP_WIDTH || aProperty == PROP_MAX_WIDTH ||
|
||||
aProperty == PROP_MIN_WIDTH,
|
||||
|
@ -4502,23 +4503,27 @@ static bool GetIntrinsicCoord(StyleExtremumLength aStyle,
|
|||
// wrapping inside of it should not apply font size inflation.
|
||||
AutoMaybeDisableFontInflation an(aFrame);
|
||||
|
||||
if (aStyle == StyleExtremumLength::MaxContent)
|
||||
if (aInlineSizeFromAspectRatio) {
|
||||
aResult = *aInlineSizeFromAspectRatio;
|
||||
} else if (aStyle == StyleExtremumLength::MaxContent) {
|
||||
aResult = aFrame->GetPrefISize(aRenderingContext);
|
||||
else
|
||||
} else {
|
||||
aResult = aFrame->GetMinISize(aRenderingContext);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename SizeOrMaxSize>
|
||||
static bool GetIntrinsicCoord(const SizeOrMaxSize& aStyle,
|
||||
gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
Maybe<nscoord> aInlineSizeFromAspectRatio,
|
||||
eWidthProperty aProperty, nscoord& aResult) {
|
||||
if (!aStyle.IsExtremumLength()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetIntrinsicCoord(aStyle.AsExtremumLength(), aRenderingContext, aFrame,
|
||||
aProperty, aResult);
|
||||
aInlineSizeFromAspectRatio, aProperty, aResult);
|
||||
}
|
||||
|
||||
#undef DEBUG_INTRINSIC_WIDTH
|
||||
|
@ -4545,6 +4550,10 @@ static int32_t gNoiseIndent = 0;
|
|||
* @param aFixedMaxSize if aStyleMaxSize is a definite size then this points to
|
||||
* the value, otherwise nullptr
|
||||
* @param aStyleMaxSize a 'max-width' or 'max-height' property value
|
||||
* @param aInlineSizeFromAspectRatio the content-box inline size computed from
|
||||
* aspect-ratio and the definite block size.
|
||||
* We use this value to resolve
|
||||
* {min|max}-content.
|
||||
* @param aFlags same as for IntrinsicForContainer
|
||||
* @param aContainerWM the container's WM
|
||||
*/
|
||||
|
@ -4554,7 +4563,9 @@ static nscoord AddIntrinsicSizeOffset(
|
|||
StyleBoxSizing aBoxSizing, nscoord aContentSize, nscoord aContentMinSize,
|
||||
const StyleSize& aStyleSize, const nscoord* aFixedMinSize,
|
||||
const StyleSize& aStyleMinSize, const nscoord* aFixedMaxSize,
|
||||
const StyleMaxSize& aStyleMaxSize, uint32_t aFlags, PhysicalAxis aAxis) {
|
||||
const StyleMaxSize& aStyleMaxSize,
|
||||
Maybe<nscoord> aInlineSizeFromAspectRatio, uint32_t aFlags,
|
||||
PhysicalAxis aAxis) {
|
||||
nscoord result = aContentSize;
|
||||
nscoord min = aContentMinSize;
|
||||
nscoord coordOutsideSize = 0;
|
||||
|
@ -4584,13 +4595,14 @@ static nscoord AddIntrinsicSizeOffset(
|
|||
result = 0; // let |min| handle padding/border/margin
|
||||
} else if (GetAbsoluteCoord(aStyleSize, size) ||
|
||||
GetIntrinsicCoord(aStyleSize, aRenderingContext, aFrame,
|
||||
PROP_WIDTH, size)) {
|
||||
aInlineSizeFromAspectRatio, PROP_WIDTH, size)) {
|
||||
result = size + coordOutsideSize;
|
||||
}
|
||||
|
||||
nscoord maxSize = aFixedMaxSize ? *aFixedMaxSize : 0;
|
||||
if (aFixedMaxSize || GetIntrinsicCoord(aStyleMaxSize, aRenderingContext,
|
||||
aFrame, PROP_MAX_WIDTH, maxSize)) {
|
||||
if (aFixedMaxSize ||
|
||||
GetIntrinsicCoord(aStyleMaxSize, aRenderingContext, aFrame,
|
||||
aInlineSizeFromAspectRatio, PROP_MAX_WIDTH, maxSize)) {
|
||||
maxSize += coordOutsideSize;
|
||||
if (result > maxSize) {
|
||||
result = maxSize;
|
||||
|
@ -4598,8 +4610,9 @@ static nscoord AddIntrinsicSizeOffset(
|
|||
}
|
||||
|
||||
nscoord minSize = aFixedMinSize ? *aFixedMinSize : 0;
|
||||
if (aFixedMinSize || GetIntrinsicCoord(aStyleMinSize, aRenderingContext,
|
||||
aFrame, PROP_MIN_WIDTH, minSize)) {
|
||||
if (aFixedMinSize ||
|
||||
GetIntrinsicCoord(aStyleMinSize, aRenderingContext, aFrame,
|
||||
aInlineSizeFromAspectRatio, PROP_MIN_WIDTH, minSize)) {
|
||||
minSize += coordOutsideSize;
|
||||
if (result < minSize) {
|
||||
result = minSize;
|
||||
|
@ -4749,6 +4762,28 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
|
|||
? aFrame->IntrinsicISizeOffsets(pmPercentageBasis)
|
||||
: aFrame->IntrinsicBSizeOffsets(pmPercentageBasis);
|
||||
|
||||
auto getContentBoxSizeToBoxSizingAdjust =
|
||||
[childWM, &offsets, &aFrame, isInlineAxis,
|
||||
pmPercentageBasis](const StyleBoxSizing aBoxSizing) {
|
||||
return aBoxSizing == StyleBoxSizing::Border
|
||||
? LogicalSize(childWM,
|
||||
(isInlineAxis ? offsets
|
||||
: aFrame->IntrinsicISizeOffsets(
|
||||
pmPercentageBasis))
|
||||
.BorderPadding(),
|
||||
(!isInlineAxis ? offsets
|
||||
: aFrame->IntrinsicBSizeOffsets(
|
||||
pmPercentageBasis))
|
||||
.BorderPadding())
|
||||
: LogicalSize(childWM);
|
||||
};
|
||||
|
||||
Maybe<nscoord> inlineSizeFromAspectRatio;
|
||||
Maybe<LogicalSize> contentBoxSizeToBoxSizingAdjust;
|
||||
|
||||
const bool ignorePadding =
|
||||
(aFlags & IGNORE_PADDING) || aFrame->IsAbsolutelyPositioned();
|
||||
|
||||
// If we have a specified width (or a specified 'min-width' greater
|
||||
// than the specified 'max-width', which works out to the same thing),
|
||||
// don't even bother getting the frame's intrinsic width, because in
|
||||
|
@ -4805,10 +4840,15 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
|
|||
|
||||
// Handle elements with an intrinsic ratio (or size) and a specified
|
||||
// height, min-height, or max-height.
|
||||
// NOTE: We treat "min-height:auto" as "0" for the purpose of this code,
|
||||
// NOTE:
|
||||
// 1. 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.
|
||||
// 2. The 'B' in |styleBSize|, |styleMinBSize|, and |styleMaxBSize|
|
||||
// represents the ratio-determining axis of |aFrame|. It could be the inline
|
||||
// axis or the block axis of |aFrame|. (So we are calculating the size
|
||||
// along the ratio-dependent axis in this if-branch.)
|
||||
StyleSize styleBSize =
|
||||
horizontalAxis ? stylePos->mHeight : stylePos->mWidth;
|
||||
StyleSize styleMinBSize =
|
||||
|
@ -4835,23 +4875,10 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
|
|||
AddStateBitToAncestors(
|
||||
aFrame, NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE);
|
||||
|
||||
const bool ignorePadding =
|
||||
(aFlags & IGNORE_PADDING) || aFrame->IsAbsolutelyPositioned();
|
||||
nscoord bSizeTakenByBoxSizing = GetDefiniteSizeTakenByBoxSizing(
|
||||
boxSizing, aFrame, !isInlineAxis, ignorePadding, aPercentageBasis);
|
||||
auto contentBoxSizeToBoxSizingAdjust =
|
||||
boxSizing == StyleBoxSizing::Border
|
||||
? LogicalSize(
|
||||
childWM,
|
||||
(isInlineAxis
|
||||
? offsets
|
||||
: aFrame->IntrinsicISizeOffsets(pmPercentageBasis))
|
||||
.BorderPadding(),
|
||||
(!isInlineAxis
|
||||
? offsets
|
||||
: aFrame->IntrinsicBSizeOffsets(pmPercentageBasis))
|
||||
.BorderPadding())
|
||||
: LogicalSize(childWM);
|
||||
contentBoxSizeToBoxSizingAdjust.emplace(
|
||||
getContentBoxSizeToBoxSizingAdjust(boxSizing));
|
||||
// NOTE: This is only the minContentSize if we've been passed
|
||||
// MIN_INTRINSIC_ISIZE (which is fine, because this should only be used
|
||||
// inside a check for that flag).
|
||||
|
@ -4866,7 +4893,10 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
|
|||
// dimensions of |aFrame|.
|
||||
result = ratio.ComputeRatioDependentSize(
|
||||
isInlineAxis ? eLogicalAxisInline : eLogicalAxisBlock, childWM, h,
|
||||
contentBoxSizeToBoxSizingAdjust);
|
||||
*contentBoxSizeToBoxSizingAdjust);
|
||||
// We have get the inlineSizeForAspectRatio value, so we don't have to
|
||||
// recompute this again below.
|
||||
inlineSizeFromAspectRatio.emplace(result);
|
||||
}
|
||||
|
||||
if (GetDefiniteSize(styleMaxBSize, aFrame, !isInlineAxis,
|
||||
|
@ -4876,7 +4906,7 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
|
|||
h = std::max(0, h - bSizeTakenByBoxSizing);
|
||||
nscoord maxISize = ratio.ComputeRatioDependentSize(
|
||||
isInlineAxis ? eLogicalAxisInline : eLogicalAxisBlock, childWM, h,
|
||||
contentBoxSizeToBoxSizingAdjust);
|
||||
*contentBoxSizeToBoxSizingAdjust);
|
||||
if (maxISize < result) {
|
||||
result = maxISize;
|
||||
}
|
||||
|
@ -4892,7 +4922,7 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
|
|||
h = std::max(0, h - bSizeTakenByBoxSizing);
|
||||
nscoord minISize = ratio.ComputeRatioDependentSize(
|
||||
isInlineAxis ? eLogicalAxisInline : eLogicalAxisBlock, childWM, h,
|
||||
contentBoxSizeToBoxSizingAdjust);
|
||||
*contentBoxSizeToBoxSizingAdjust);
|
||||
if (minISize > result) {
|
||||
result = minISize;
|
||||
}
|
||||
|
@ -4916,11 +4946,49 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
|
|||
min = aFrame->GetMinISize(aRenderingContext);
|
||||
}
|
||||
|
||||
// If we have an aspect-ratio and a definite block size of |aFrame|, we
|
||||
// resolve the {min|max}-content size by the aspect-ratio and the block size.
|
||||
// If |aAxis| is not the inline axis of |aFrame|, {min|max}-content should
|
||||
// behaves as auto, so we don't need this.
|
||||
// https://github.com/w3c/csswg-drafts/issues/5032
|
||||
// FIXME: Bug 1670151: Use GetAspectRatio() to cover replaced elements (and
|
||||
// then we can drop the check of eSupportsAspectRatio).
|
||||
const AspectRatio ar = stylePos->mAspectRatio.ToLayoutRatio();
|
||||
if (isInlineAxis && styleISize.IsExtremumLength() && ar &&
|
||||
aFrame->IsFrameOfType(nsIFrame::eSupportsAspectRatio) &&
|
||||
!inlineSizeFromAspectRatio) {
|
||||
// This 'B' in |styleBSize| means the block size of |aFrame|. We go into
|
||||
// this branch only if |aAxis| is the inline axis of |aFrame|.
|
||||
const StyleSize& styleBSize =
|
||||
horizontalAxis ? stylePos->mHeight : stylePos->mWidth;
|
||||
nscoord bSize;
|
||||
if (GetDefiniteSize(styleBSize, aFrame, !isInlineAxis, aPercentageBasis,
|
||||
&bSize) ||
|
||||
(aPercentageBasis.isNothing() &&
|
||||
GetPercentBSize(styleBSize, aFrame, horizontalAxis, bSize))) {
|
||||
// We cannot reuse |boxSizing| because it may be updated to content-box
|
||||
// in the above if-branch.
|
||||
const StyleBoxSizing boxSizingForAR = stylePos->mBoxSizing;
|
||||
if (!contentBoxSizeToBoxSizingAdjust) {
|
||||
contentBoxSizeToBoxSizingAdjust.emplace(
|
||||
getContentBoxSizeToBoxSizingAdjust(boxSizingForAR));
|
||||
}
|
||||
nscoord bSizeTakenByBoxSizing =
|
||||
GetDefiniteSizeTakenByBoxSizing(boxSizingForAR, aFrame, !isInlineAxis,
|
||||
ignorePadding, aPercentageBasis);
|
||||
bSize -= bSizeTakenByBoxSizing;
|
||||
inlineSizeFromAspectRatio.emplace(ar.ComputeRatioDependentSize(
|
||||
LogicalAxis::eLogicalAxisInline, childWM, bSize,
|
||||
*contentBoxSizeToBoxSizingAdjust));
|
||||
}
|
||||
}
|
||||
|
||||
nscoord contentBoxSize = result;
|
||||
result = AddIntrinsicSizeOffset(
|
||||
aRenderingContext, aFrame, offsets, aType, boxSizing, result, min,
|
||||
styleISize, haveFixedMinISize ? &minISize : nullptr, styleMinISize,
|
||||
haveFixedMaxISize ? &maxISize : nullptr, styleMaxISize, aFlags, aAxis);
|
||||
haveFixedMaxISize ? &maxISize : nullptr, styleMaxISize,
|
||||
inlineSizeFromAspectRatio, aFlags, aAxis);
|
||||
nscoord overflow = result - aMarginBoxMinSizeClamp;
|
||||
if (MOZ_UNLIKELY(overflow > 0)) {
|
||||
nscoord newContentBoxSize = std::max(nscoord(0), contentBoxSize - overflow);
|
||||
|
@ -5050,9 +5118,11 @@ nscoord nsLayoutUtils::MinSizeContributionForAxis(
|
|||
: aFrame->IntrinsicBSizeOffsets(pmPercentageBasis);
|
||||
nscoord result = 0;
|
||||
nscoord min = 0;
|
||||
// Note: aInlineSizeFromAspectRatio is Nothing() here because we don't handle
|
||||
// "content size" cases here (i.e. |fixedMinSize| is false here).
|
||||
result = AddIntrinsicSizeOffset(
|
||||
aRC, aFrame, offsets, aType, stylePos->mBoxSizing, result, min, size,
|
||||
fixedMinSize, size, nullptr, maxSize, aFlags, aAxis);
|
||||
fixedMinSize, size, nullptr, maxSize, Nothing(), aFlags, aAxis);
|
||||
|
||||
#ifdef DEBUG_INTRINSIC_WIDTH
|
||||
nsIFrame::IndentBy(stderr, gNoiseIndent);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS aspect-ratio: grid track size should respect aspect-ratio when using
|
||||
intrinsic size keywords in grid items</title>
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-grid/#algo-track-sizing">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
|
||||
<style>
|
||||
#reference-overlapped-red {
|
||||
position: absolute;
|
||||
background-color: red;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="reference-overlapped-red"></div>
|
||||
<div style="display: grid; grid-template-columns: auto; width: min-content; background: green;">
|
||||
<div style="height: 50px; width: min-content; aspect-ratio: 2/1;"></div>
|
||||
<div style="height: 50px; width: 1%; min-width: min-content; aspect-ratio: 2/1;"></div>
|
||||
</div>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS aspect-ratio: grid track size should respect aspect-ratio when using
|
||||
intrinsic size keywords in grid items with orthogonal writing mode</title>
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-grid/#algo-track-sizing">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
|
||||
<style>
|
||||
#reference-overlapped-red {
|
||||
position: absolute;
|
||||
background-color: red;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
z-index: -1;
|
||||
}
|
||||
.item {
|
||||
aspect-ratio: 2/1;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="reference-overlapped-red"></div>
|
||||
<div style="display: grid; grid-template-columns: auto; width: min-content; background: green;">
|
||||
<div class="item" style="width: 100px; height: min-content;"></div>
|
||||
<div class="item" style="width: 100px; height: 1%; min-height: min-content;"></div>
|
||||
</div>
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS aspect-ratio: min-content size keyword together with min-content size contribution</title>
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5032">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div style="width: min-content; background: green;">
|
||||
<div style="width: min-content; height: 100px; aspect-ratio: 1/1;"></div>
|
||||
</div>
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS aspect-ratio: max-content size keyword together with min-content size contribution</title>
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5032">
|
||||
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
|
||||
<div style="width: max-content; background: green;">
|
||||
<div style="width: min-content; height: 100px; aspect-ratio: 1/1;"></div>
|
||||
</div>
|
Загрузка…
Ссылка в новой задаче