Bug 1909761 Part 4 - Construct a percentage basis when computing children's intrinsic inline size contributions. r=dholbert

A percentage basis is needed to resolve percentage block size when computing
children's intrinsic inline size contributions. This is necessary for a child or
descendants with a preferred aspect-ratio so that the block size can transfer
through the aspect-ratio to become an intrinsic inline size.

The change in `nsFlexContainerFrame::ComputeIntrinsicISize()` is necessary to
keep us passing
`testing/web-platform/tests/css/css-flexbox/image-nested-within-definite-column-flexbox.html`.

The change in `nsPlaceholderFrame::AddFloatToIntrinsicISizeData()` is necessary
to keep us passing
`testing/web-platform/tests/css/css-sizing/intrinsic-percent-replaced-dynamic-010.html`.

`GetISizeInfo()` in BasicTableLayoutStrategy.cpp is modified to pass table cell
frame's bsize as percentage basis. Otherwise,
`layout/reftests/bugs/522632-1.html` fails. This is our current behavior, but it
is bug 1461852.

Differential Revision: https://phabricator.services.mozilla.com/D219523
This commit is contained in:
Ting-Yu Lin 2024-08-28 06:18:45 +00:00
parent 520580e888
commit 55248224df
20 changed files with 246 additions and 74 deletions

View File

@ -2622,7 +2622,7 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP nsDocumentViewer::GetContentSize(
const nscoord minISize = wm.IsVertical() ? constraints.mMinSize.height
: constraints.mMinSize.width;
const nscoord maxISize = wm.IsVertical() ? aMaxHeight : aMaxWidth;
const IntrinsicSizeInput input(rcx.get());
const IntrinsicSizeInput input(rcx.get(), Nothing());
if (aPrefWidth) {
prefISize = std::max(root->GetMinISize(input), aPrefWidth);
} else {

View File

@ -4041,6 +4041,9 @@ static Maybe<nscoord> GetPercentBSize(const LengthPercentage& aSize,
nsIFrame* aFrame, bool aHorizontalAxis);
// Only call on aSize for which GetAbsoluteSize returned Nothing().
//
// Bug 1363918: We can remove GetPercentBSize() after we've updated all of
// IntrinsicForAxis()'s callsites to pass it a percentage basis.
template <typename SizeOrMaxSize>
static Maybe<nscoord> GetPercentBSize(const SizeOrMaxSize& aSize,
nsIFrame* aFrame, bool aHorizontalAxis) {
@ -4309,7 +4312,9 @@ static Maybe<nscoord> GetIntrinsicSize(nsIFrame::ExtremumLength aLength,
if (aISizeFromAspectRatio) {
result = *aISizeFromAspectRatio;
} else {
const IntrinsicSizeInput input(aRenderingContext);
// Bug 1363918: We need to refactor this function to compute a percentage
// basis when computing intrinsic sizes.
const IntrinsicSizeInput input(aRenderingContext, Nothing());
auto type = aLength == nsIFrame::ExtremumLength::MaxContent
? IntrinsicISizeType::PrefISize
: IntrinsicISizeType::MinISize;
@ -4439,7 +4444,9 @@ static nscoord AddIntrinsicSizeOffset(
if (aISizeFromAspectRatio) {
minContent = maxContent = *aISizeFromAspectRatio;
} else {
const IntrinsicSizeInput input(aRenderingContext);
// Bug 1363918: We need to refactor this function to compute a percentage
// basis when computing intrinsic sizes.
const IntrinsicSizeInput input(aRenderingContext, Nothing());
minContent = aFrame->GetMinISize(input);
maxContent = aFrame->GetPrefISize(input);
}
@ -4643,6 +4650,32 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
fixedMinISize = GetAbsoluteSize(styleMinISize);
}
// Handle elements with an intrinsic ratio (or size) and a specified
// height, min-height, or max-height.
// 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 =
horizontalAxis ? stylePos->mMinHeight : stylePos->mMinWidth;
StyleMaxSize styleMaxBSize =
horizontalAxis ? stylePos->mMaxHeight : stylePos->mMaxWidth;
// According to the spec, max-content and min-content should behave as the
// property's initial values in block axis.
// It also make senses to use the initial values for -moz-fit-content and
// -moz-available for intrinsic size in block axis. Therefore, we reset them
// if needed.
if (isInlineAxis) {
ResetIfKeywords(styleBSize, styleMinBSize, styleMaxBSize);
}
auto childWM = aFrame->GetWritingMode();
nscoord pmPercentageBasis = NS_UNCONSTRAINEDSIZE;
if (aPercentageBasis.isSome()) {
@ -4734,7 +4767,37 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
result = aFrame->BSize();
}
} else {
const IntrinsicSizeInput input(aRenderingContext);
// To resolve aFrame's intrinsic inline size, we first check if we can
// resolve a block-axis percentage basis for aFrame's children. This can
// influence their inline size contributions, e.g. if they have an
// aspect-ratio and a percentage-based block size.
const nscoord percentageBasisBSizeForFrame =
aPercentageBasis ? aPercentageBasis->BSize(childWM)
: NS_UNCONSTRAINEDSIZE;
nscoord percentageBasisBSizeForChildren;
if (aFrame->IsBlockContainer()) {
// Compute and cache the box-sizing adjustment in contentEdgeToBoxSizing
// for later use within this function.
contentEdgeToBoxSizing.emplace(GetContentEdgeToBoxSizing(boxSizing));
// aFrame is a containing block, so its block size (with min and max
// block size constraints applied) serves as the percentage basis for
// its children.
percentageBasisBSizeForChildren =
nsIFrame::ComputeBSizeValueAsPercentageBasis(
styleBSize, styleMinBSize, styleMaxBSize,
percentageBasisBSizeForFrame,
contentEdgeToBoxSizing->BSize(childWM));
} else {
// aFrame is not a containing block, so its children share the same
// containing block as aFrame. Therefore, the percentage basis for
// aFrame's children is the same as that for aFrame.
percentageBasisBSizeForChildren = percentageBasisBSizeForFrame;
}
const IntrinsicSizeInput input(
aRenderingContext,
Some(LogicalSize(childWM, NS_UNCONSTRAINEDSIZE,
percentageBasisBSizeForChildren)));
result = aFrame->IntrinsicISize(input, aType);
}
#ifdef DEBUG_INTRINSIC_WIDTH
@ -4746,33 +4809,6 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
horizontalAxis ? "horizontal" : "vertical", result);
#endif
// Handle elements with an intrinsic ratio (or size) and a specified
// height, min-height, or max-height.
// 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 =
horizontalAxis ? stylePos->mMinHeight : stylePos->mMinWidth;
StyleMaxSize styleMaxBSize =
horizontalAxis ? stylePos->mMaxHeight : stylePos->mMaxWidth;
// According to the spec, max-content and min-content should behave as the
// property's initial values in block axis.
// It also make senses to use the initial values for -moz-fit-content and
// -moz-available for intrinsic size in block axis. Therefore, we reset them
// if needed.
if (isInlineAxis) {
ResetIfKeywords(styleBSize, styleMinBSize, styleMaxBSize);
}
// If our BSize or min/max-BSize properties are set to values that we can
// resolve and that will impose a constraint when transferred through our
// aspect ratio (if we have one), then compute and apply that constraint.
@ -4808,7 +4844,10 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
nscoord bSizeTakenByBoxSizing = GetDefiniteSizeTakenByBoxSizing(
boxSizing, aFrame, !isInlineAxis, ignorePadding, aPercentageBasis);
contentEdgeToBoxSizing.emplace(GetContentEdgeToBoxSizing(boxSizing));
if (!contentEdgeToBoxSizing) {
contentEdgeToBoxSizing.emplace(GetContentEdgeToBoxSizing(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).
@ -4869,7 +4908,7 @@ nscoord nsLayoutUtils::IntrinsicForAxis(
if (aFrame->IsTableFrame()) {
// Tables can't shrink smaller than their intrinsic minimum inline size,
// no matter what.
const IntrinsicSizeInput input(aRenderingContext);
const IntrinsicSizeInput input(aRenderingContext, Nothing());
min = aFrame->GetMinISize(input);
}

View File

@ -249,7 +249,7 @@ LogicalSize nsTextControlFrame::CalcIntrinsicSize(gfxContext* aRenderingContext,
// Add the inline size of the button if our char size is explicit, so as to
// make sure to make enough space for it.
if (maybeCols.isSome() && mButton && mButton->GetPrimaryFrame()) {
const IntrinsicSizeInput input(aRenderingContext);
const IntrinsicSizeInput input(aRenderingContext, Nothing());
intrinsicSize.ISize(aWM) += mButton->GetPrimaryFrame()->GetMinISize(input);
}

View File

@ -199,8 +199,9 @@ nscoord ColumnSetWrapperFrame::MinISize(const IntrinsicSizeInput& aInput) {
}
} else {
for (nsIFrame* f : PrincipalChildList()) {
const IntrinsicSizeInput input(aInput.mContext);
iSize = std::max(iSize, f->GetMinISize(input));
const IntrinsicSizeInput childInput(aInput, f->GetWritingMode(),
GetWritingMode());
iSize = std::max(iSize, f->GetMinISize(childInput));
}
}
@ -236,8 +237,9 @@ nscoord ColumnSetWrapperFrame::PrefISize(const IntrinsicSizeInput& aInput) {
iSize = ColumnUtils::IntrinsicISize(numColumns, colGap, colISize);
} else {
for (nsIFrame* f : PrincipalChildList()) {
const IntrinsicSizeInput input(aInput.mContext);
iSize = std::max(iSize, f->GetPrefISize(input));
const IntrinsicSizeInput childInput(aInput, f->GetWritingMode(),
GetWritingMode());
iSize = std::max(iSize, f->GetPrefISize(childInput));
}
}

View File

@ -871,8 +871,12 @@ nscoord nsBlockFrame::MinISize(const IntrinsicSizeInput& aInput) {
#endif
if (line->IsBlock()) {
data.ForceBreak();
nsIFrame* kid = line->mFirstChild;
const IntrinsicSizeInput kidInput(aInput, kid->GetWritingMode(),
GetWritingMode());
data.mCurrentLine = nsLayoutUtils::IntrinsicForContainer(
aInput.mContext, line->mFirstChild, IntrinsicISizeType::MinISize);
kidInput.mContext, kid, IntrinsicISizeType::MinISize,
kidInput.mPercentageBasis);
data.ForceBreak();
} else {
if (!curFrame->GetPrevContinuation() && TextIndentAppliesTo(line)) {
@ -883,7 +887,8 @@ nscoord nsBlockFrame::MinISize(const IntrinsicSizeInput& aInput) {
nsIFrame* kid = line->mFirstChild;
for (int32_t i = 0, i_end = line->GetChildCount(); i != i_end;
++i, kid = kid->GetNextSibling()) {
const IntrinsicSizeInput kidInput(aInput.mContext);
const IntrinsicSizeInput kidInput(aInput, kid->GetWritingMode(),
GetWritingMode());
kid->AddInlineMinISize(kidInput, &data);
if (whiteSpaceCanWrap && data.mTrailingWhitespace) {
data.OptionallyBreak();
@ -942,15 +947,19 @@ nscoord nsBlockFrame::PrefISize(const IntrinsicSizeInput& aInput) {
AutoNoisyIndenter lineindent(gNoisyIntrinsic);
#endif
if (line->IsBlock()) {
nsIFrame* kid = line->mFirstChild;
StyleClear clearType;
if (!data.mLineIsEmpty || BlockCanIntersectFloats(line->mFirstChild)) {
if (!data.mLineIsEmpty || BlockCanIntersectFloats(kid)) {
clearType = StyleClear::Both;
} else {
clearType = line->mFirstChild->StyleDisplay()->mClear;
clearType = kid->StyleDisplay()->mClear;
}
data.ForceBreak(clearType);
const IntrinsicSizeInput kidInput(aInput, kid->GetWritingMode(),
GetWritingMode());
data.mCurrentLine = nsLayoutUtils::IntrinsicForContainer(
aInput.mContext, line->mFirstChild, IntrinsicISizeType::PrefISize);
kidInput.mContext, kid, IntrinsicISizeType::PrefISize,
kidInput.mPercentageBasis);
data.ForceBreak();
} else {
if (!curFrame->GetPrevContinuation() && TextIndentAppliesTo(line)) {
@ -966,7 +975,8 @@ nscoord nsBlockFrame::PrefISize(const IntrinsicSizeInput& aInput) {
nsIFrame* kid = line->mFirstChild;
for (int32_t i = 0, i_end = line->GetChildCount(); i != i_end;
++i, kid = kid->GetNextSibling()) {
const IntrinsicSizeInput kidInput(aInput.mContext);
const IntrinsicSizeInput kidInput(aInput, kid->GetWritingMode(),
GetWritingMode());
kid->AddInlinePrefISize(kidInput, &data);
}
}
@ -1024,7 +1034,12 @@ nsresult nsBlockFrame::GetPrefWidthTightBounds(gfxContext* aRenderingContext,
data.mLine = &line;
data.SetLineContainer(curFrame);
nsIFrame* kid = line->mFirstChild;
const IntrinsicSizeInput kidInput(aRenderingContext);
// Per comment in nsIFrame::GetPrefWidthTightBounds(), the function is
// only implemented for nsBlockFrame and nsTextFrame and is used to
// determine the intrinsic inline sizes of MathML token elements. These
// elements shouldn't have percentage block sizes that require a
// percentage basis for resolution.
const IntrinsicSizeInput kidInput(aRenderingContext, Nothing());
for (int32_t i = 0, i_end = line->GetChildCount(); i != i_end;
++i, kid = kid->GetNextSibling()) {
rv = kid->GetPrefWidthTightBounds(aRenderingContext, &childX,

View File

@ -792,7 +792,8 @@ void nsContainerFrame::DoInlineMinISize(const IntrinsicSizeInput& aInput,
InlineMinISizeData* aData) {
auto handleChildren = [&](auto frame, auto data) {
for (nsIFrame* kid : frame->mFrames) {
const IntrinsicSizeInput kidInput(aInput.mContext);
const IntrinsicSizeInput kidInput(aInput, kid->GetWritingMode(),
GetWritingMode());
kid->AddInlineMinISize(kidInput, data);
}
};
@ -803,7 +804,8 @@ void nsContainerFrame::DoInlinePrefISize(const IntrinsicSizeInput& aInput,
InlinePrefISizeData* aData) {
auto handleChildren = [&](auto frame, auto data) {
for (nsIFrame* kid : frame->mFrames) {
const IntrinsicSizeInput kidInput(aInput.mContext);
const IntrinsicSizeInput kidInput(aInput, kid->GetWritingMode(),
GetWritingMode());
kid->AddInlinePrefISize(kidInput, data);
}
};
@ -835,7 +837,7 @@ LogicalSize nsContainerFrame::ComputeAutoSize(
AutoMaybeDisableFontInflation an(this);
WritingMode tableWM = GetParent()->GetWritingMode();
const IntrinsicSizeInput input(aRenderingContext);
const IntrinsicSizeInput input(aRenderingContext, Nothing());
if (aWM.IsOrthogonalTo(tableWM)) {
// For an orthogonal caption on a block-dir side of the table, shrink-wrap
// to min-isize.

View File

@ -6454,8 +6454,10 @@ nscoord nsFlexContainerFrame::ComputeIntrinsicISize(
continue;
}
const IntrinsicSizeInput childInput(aInput, childFrame->GetWritingMode(),
GetWritingMode());
nscoord childISize = nsLayoutUtils::IntrinsicForContainer(
aInput.mContext, childFrame, aType);
childInput.mContext, childFrame, aType, childInput.mPercentageBasis);
// * For a row-oriented single-line flex container, the intrinsic
// {min/pref}-isize is the sum of its items' {min/pref}-isizes and

View File

@ -6016,7 +6016,8 @@ void nsIFrame::MarkSubtreeDirty() {
void nsIFrame::AddInlineMinISize(const IntrinsicSizeInput& aInput,
InlineMinISizeData* aData) {
nscoord isize = nsLayoutUtils::IntrinsicForContainer(
aInput.mContext, this, IntrinsicISizeType::MinISize);
aInput.mContext, this, IntrinsicISizeType::MinISize,
aInput.mPercentageBasis);
aData->DefaultAddInlineMinISize(this, isize);
}
@ -6024,7 +6025,8 @@ void nsIFrame::AddInlineMinISize(const IntrinsicSizeInput& aInput,
void nsIFrame::AddInlinePrefISize(const IntrinsicSizeInput& aInput,
nsIFrame::InlinePrefISizeData* aData) {
nscoord isize = nsLayoutUtils::IntrinsicForContainer(
aInput.mContext, this, IntrinsicISizeType::PrefISize);
aInput.mContext, this, IntrinsicISizeType::PrefISize,
aInput.mPercentageBasis);
aData->DefaultAddInlinePrefISize(isize);
}
@ -6515,7 +6517,7 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize(
result.ISize(aWM) = std::min(maxISize, result.ISize(aWM));
}
const IntrinsicSizeInput input(aRenderingContext);
const IntrinsicSizeInput input(aRenderingContext, Nothing());
const auto& minISizeCoord = stylePos->MinISize(aWM);
nscoord minISize;
if (!minISizeCoord.IsAuto() && !shouldIgnoreMinMaxISize) {
@ -6684,6 +6686,31 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize(
return {result, aspectRatioUsage};
}
nscoord nsIFrame::ComputeBSizeValueAsPercentageBasis(
const StyleSize& aStyleBSize, const StyleSize& aStyleMinBSize,
const StyleMaxSize& aStyleMaxBSize, nscoord aCBBSize,
nscoord aContentEdgeToBoxSizingBSize) {
const nscoord bSize = nsLayoutUtils::IsAutoBSize(aStyleBSize, aCBBSize)
? NS_UNCONSTRAINEDSIZE
: nsLayoutUtils::ComputeBSizeValue(
aCBBSize, aContentEdgeToBoxSizingBSize,
aStyleBSize.AsLengthPercentage());
const nscoord minBSize = nsLayoutUtils::IsAutoBSize(aStyleMinBSize, aCBBSize)
? 0
: nsLayoutUtils::ComputeBSizeValue(
aCBBSize, aContentEdgeToBoxSizingBSize,
aStyleMinBSize.AsLengthPercentage());
const nscoord maxBSize = nsLayoutUtils::IsAutoBSize(aStyleMaxBSize, aCBBSize)
? NS_UNCONSTRAINEDSIZE
: nsLayoutUtils::ComputeBSizeValue(
aCBBSize, aContentEdgeToBoxSizingBSize,
aStyleMaxBSize.AsLengthPercentage());
return CSSMinMax(bSize, minBSize, maxBSize);
}
nsRect nsIFrame::ComputeTightBounds(DrawTarget* aDrawTarget) const {
return InkOverflowRect();
}
@ -6711,7 +6738,19 @@ LogicalSize nsIFrame::ComputeAutoSize(
if (styleISize.IsAuto()) {
nscoord availBased =
aAvailableISize - aMargin.ISize(aWM) - aBorderPadding.ISize(aWM);
const IntrinsicSizeInput input(aRenderingContext);
const auto* stylePos = StylePosition();
const auto& styleBSize = aSizeOverrides.mStyleBSize
? *aSizeOverrides.mStyleBSize
: stylePos->BSize(aWM);
const LogicalSize contentEdgeToBoxSizing =
stylePos->mBoxSizing == StyleBoxSizing::Border ? aBorderPadding
: LogicalSize(aWM);
const nscoord bSize = ComputeBSizeValueAsPercentageBasis(
styleBSize, stylePos->MinBSize(aWM), stylePos->MaxBSize(aWM),
aCBSize.BSize(aWM), contentEdgeToBoxSizing.BSize(aWM));
const IntrinsicSizeInput input(
aRenderingContext, Some(LogicalSize(aWM, NS_UNCONSTRAINEDSIZE, bSize)
.ConvertTo(GetWritingMode(), aWM)));
result.ISize(aWM) = ShrinkISizeToFit(input, availBased, aFlags);
}
return result;
@ -6802,7 +6841,12 @@ nsIFrame::ISizeComputationResult nsIFrame::ComputeISizeValue(
aAspectRatio));
}();
const IntrinsicSizeInput input(aRenderingContext);
const auto* stylePos = StylePosition();
const nscoord bSize = ComputeBSizeValueAsPercentageBasis(
aStyleBSize, stylePos->MinBSize(aWM), stylePos->MaxBSize(aWM),
aCBSize.BSize(aWM), aContentEdgeToBoxSizing.BSize(aWM));
const IntrinsicSizeInput input(
aRenderingContext, Some(LogicalSize(aWM, NS_UNCONSTRAINEDSIZE, bSize)));
nscoord result;
switch (aSize) {
case ExtremumLength::MaxContent:

View File

@ -422,9 +422,32 @@ struct FrameBidiData {
struct MOZ_STACK_CLASS IntrinsicSizeInput final {
gfxContext* const mContext;
explicit IntrinsicSizeInput(gfxContext* aContext) : mContext(aContext) {
// The content-box size of a frame, served as a percentage basis when
// computing the children's intrinsic contributions. If the basis is
// indefinite in a given axis, use NS_UNCONSTRAINEDSIZE for that component.
//
// In most scenarios, this struct is used when computing the inline size
// contribution, so the inline component of the percentage basis should be set
// to NS_UNCONSTRAINEDSIZE.
Maybe<LogicalSize> mPercentageBasis;
IntrinsicSizeInput(gfxContext* aContext,
const Maybe<LogicalSize>& aPercentageBasis)
: mContext(aContext), mPercentageBasis(aPercentageBasis) {
MOZ_ASSERT(mContext);
}
// Construct a new IntrinsicSizeInput by copying from aSource.
//
// This constructor converts mPercentageBasis' writing mode, if it exists. The
// original mPercentageBasis in aSource is expected to be in the writing mode
// aFromWM, and it will be converted to the writing mode aToWM.
IntrinsicSizeInput(const IntrinsicSizeInput& aSource,
mozilla::WritingMode aToWM, mozilla::WritingMode aFromWM)
: IntrinsicSizeInput(aSource.mContext,
aSource.mPercentageBasis.map([&](const auto& aPB) {
return aPB.ConvertTo(aToWM, aFromWM);
})) {}
};
} // namespace mozilla
@ -2872,6 +2895,12 @@ class nsIFrame : public nsQueryFrame {
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags);
static nscoord ComputeBSizeValueAsPercentageBasis(
const mozilla::StyleSize& aStyleBSize,
const mozilla::StyleSize& aStyleMinBSize,
const mozilla::StyleMaxSize& aStyleMaxBSize, nscoord aCBBSize,
nscoord aContentEdgeToBoxSizingBSize);
protected:
/**
* A helper, used by |nsIFrame::ComputeSize| (for frames that need to

View File

@ -2850,7 +2850,8 @@ static bool IsInAutoWidthTableCellForQuirk(nsIFrame* aFrame) {
void nsImageFrame::AddInlineMinISize(const IntrinsicSizeInput& aInput,
InlineMinISizeData* aData) {
nscoord isize = nsLayoutUtils::IntrinsicForContainer(
aInput.mContext, this, IntrinsicISizeType::MinISize);
aInput.mContext, this, IntrinsicISizeType::MinISize,
aInput.mPercentageBasis);
bool canBreak = !IsInAutoWidthTableCellForQuirk(this);
aData->DefaultAddInlineMinISize(this, isize, canBreak);
}

View File

@ -75,8 +75,11 @@ void nsPlaceholderFrame::AddFloatToIntrinsicISizeData(
const IntrinsicSizeInput& aInput, IntrinsicISizeType aType,
InlineIntrinsicISizeData* aData) const {
if (mOutOfFlowFrame->IsFloating()) {
const IntrinsicSizeInput floatInput(
aInput, mOutOfFlowFrame->GetWritingMode(), GetWritingMode());
const nscoord floatISize = nsLayoutUtils::IntrinsicForContainer(
aInput.mContext, mOutOfFlowFrame, aType);
floatInput.mContext, mOutOfFlowFrame, aType,
floatInput.mPercentageBasis);
aData->mFloats.EmplaceBack(mOutOfFlowFrame, floatISize);
}
}

View File

@ -214,7 +214,7 @@ void nsRubyBaseContainerFrame::AddInlineMinISize(
void nsRubyBaseContainerFrame::AddInlinePrefISize(
const IntrinsicSizeInput& aInput, InlinePrefISizeData* aData) {
AutoRubyTextContainerArray textContainers(this);
const IntrinsicSizeInput input(aInput.mContext);
const IntrinsicSizeInput input(aInput.mContext, Nothing());
nscoord sum = 0;
for (nsIFrame* frame = this; frame; frame = frame->GetNextInFlow()) {

View File

@ -54,7 +54,9 @@ nsresult nsRubyFrame::GetFrameName(nsAString& aResult) const {
void nsRubyFrame::AddInlineMinISize(const IntrinsicSizeInput& aInput,
InlineMinISizeData* aData) {
auto handleChildren = [&](auto frame, auto data) {
const IntrinsicSizeInput input(aInput.mContext);
// Ruby frames shouldn't have percentage block sizes that require a
// percentage basis for resolution.
const IntrinsicSizeInput input(aInput.mContext, Nothing());
for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame)); !e.AtEnd();
e.Next()) {
e.GetBaseContainer()->AddInlineMinISize(input, data);
@ -67,7 +69,9 @@ void nsRubyFrame::AddInlineMinISize(const IntrinsicSizeInput& aInput,
void nsRubyFrame::AddInlinePrefISize(const IntrinsicSizeInput& aInput,
InlinePrefISizeData* aData) {
auto handleChildren = [&](auto frame, auto data) {
const IntrinsicSizeInput input(aInput.mContext);
// Ruby frames shouldn't have percentage block sizes that require a
// percentage basis for resolution.
const IntrinsicSizeInput input(aInput.mContext, Nothing());
for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame)); !e.AtEnd();
e.Next()) {
e.GetBaseContainer()->AddInlinePrefISize(input, data);

View File

@ -5105,7 +5105,7 @@ void SVGTextFrame::DoReflow() {
kid->MarkIntrinsicISizesDirty();
}
const IntrinsicSizeInput input(renderingContext.get());
const IntrinsicSizeInput input(renderingContext.get(), Nothing());
nscoord inlineSize = kid->GetPrefISize(input);
WritingMode wm = kid->GetWritingMode();
ReflowInput reflowInput(presContext, kid, renderingContext.get(),

View File

@ -69,11 +69,14 @@ struct CellISizeInfo {
float prefPercent;
};
// Used for both column and cell calculations. The parts needed only
// for cells are skipped when aIsCell is false.
// A helper for ComputeColumnIntrinsicISizes(), used for both column and cell
// intrinsic inline size calculations. The parts needed only for cells are
// skipped when aIsCell is false.
static CellISizeInfo GetISizeInfo(gfxContext* aRenderingContext,
nsIFrame* aFrame, WritingMode aWM,
bool aIsCell) {
MOZ_ASSERT(aFrame->GetWritingMode() == aWM,
"The caller is expected to pass aFrame's writing mode!");
nscoord minCoord, prefCoord;
const nsStylePosition* stylePos = aFrame->StylePosition();
bool isQuirks =
@ -84,7 +87,28 @@ static CellISizeInfo GetISizeInfo(gfxContext* aRenderingContext,
// wrapping inside of it should not apply font size inflation.
AutoMaybeDisableFontInflation an(aFrame);
const IntrinsicSizeInput input(aRenderingContext);
// Resolve the cell's block size 'cellBSize' as a percentage basis, in case
// it impacts its children's inline-size contributions (e.g. via percentage
// block size + aspect-ratio). However, this behavior might not be
// web-compatible (Bug 1461852).
//
// Note that if the cell *itself* has a percentage-based block size, we
// treat it as unresolvable here by using an unconstrained cbBSize. It will
// be resolved during the "special bsize reflow" pass if the table has a
// specified block size. See nsTableFrame::Reflow() and
// ReflowInput::Flags::mSpecialBSizeReflow.
const nscoord cbBSize = NS_UNCONSTRAINEDSIZE;
const nscoord contentEdgeToBoxSizingBSize =
stylePos->mBoxSizing == StyleBoxSizing::Border
? aFrame->IntrinsicBSizeOffsets().BorderPadding()
: 0;
const nscoord cellBSize = nsIFrame::ComputeBSizeValueAsPercentageBasis(
stylePos->BSize(aWM), stylePos->MinBSize(aWM), stylePos->MaxBSize(aWM),
cbBSize, contentEdgeToBoxSizingBSize);
const IntrinsicSizeInput input(
aRenderingContext,
Some(LogicalSize(aWM, NS_UNCONSTRAINEDSIZE, cellBSize)));
minCoord = aFrame->GetMinISize(input);
prefCoord = aFrame->GetPrefISize(input);
// Until almost the end of this function, minCoord and prefCoord

View File

@ -598,9 +598,14 @@ ScrollContainerFrame* nsTableCellFrame::GetScrollTargetFrame() const {
nscoord nsTableCellFrame::IntrinsicISize(const IntrinsicSizeInput& aInput,
IntrinsicISizeType aType) {
return nsLayoutUtils::IntrinsicForContainer(aInput.mContext, Inner(), aType,
Nothing(),
nsLayoutUtils::IGNORE_PADDING);
// Note: a table cell has the same writing mode as its table ancestor, which
// may differ from its inner frame that derives its writing mode from the
// style of the <td> element. See nsTableCellFrame::Init().
const IntrinsicSizeInput innerInput(aInput, Inner()->GetWritingMode(),
GetWritingMode());
return nsLayoutUtils::IntrinsicForContainer(
innerInput.mContext, Inner(), aType, innerInput.mPercentageBasis,
nsLayoutUtils::IGNORE_PADDING);
}
/* virtual */ nsIFrame::IntrinsicSizeOffsetData

View File

@ -1403,7 +1403,7 @@ nsIFrame::SizeComputationResult nsTableFrame::ComputeSize(
AutoMaybeDisableFontInflation an(this);
// Tables never shrink below their min inline-size.
const IntrinsicSizeInput input(aRenderingContext);
const IntrinsicSizeInput input(aRenderingContext, Nothing());
nscoord minISize = GetMinISize(input);
if (minISize > result.mLogicalSize.ISize(aWM)) {
result.mLogicalSize.ISize(aWM) = minISize;
@ -1419,7 +1419,7 @@ nscoord nsTableFrame::TableShrinkISizeToFit(gfxContext* aRenderingContext,
AutoMaybeDisableFontInflation an(this);
nscoord result;
const IntrinsicSizeInput input(aRenderingContext);
const IntrinsicSizeInput input(aRenderingContext, Nothing());
nscoord minISize = GetMinISize(input);
if (minISize > aISizeInCB) {
result = minISize;

View File

@ -3,6 +3,3 @@
if (os == "android") and fission: [OK, TIMEOUT]
[#target height matches containing block height, and target parent width matches #target width after resize]
expected: FAIL
[#target height matches containing block height, and target parent width matches #target width]
expected: FAIL

View File

@ -0,0 +1,7 @@
[grid-aspect-ratio-041.html]
# Before bug 1909761, we pass this test by accident. To pass this test, we
# need to resolve row size based on the grid container's definite height, and
# use that row size to resolve "height: 100%" when computing the intrinsic
# size of the middle div. Bug 1300366 might fix this.
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1300366

View File

@ -1,2 +0,0 @@
[abs-pos-with-replaced-child.html]
expected: FAIL