Skip to content

Commit

Permalink
Bug 1646100 - Compute {min|max|fit}-content from the definite block-s…
Browse files Browse the repository at this point in the history
…ize and aspect-ratio. r=TYLin,emilio

ComputeISizeValue() takes aspect-ratio into account. Also, add a
ComputeSizeFlag which skips aspect-ratio in ComputeISizeValue(), so
internal table boxes can use this flag to skip aspect-ratio.

Differential Revision: https://phabricator.services.mozilla.com/D99290
  • Loading branch information
BorisChiou committed Jan 19, 2021
1 parent 8d1403f commit eff538f
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 24 deletions.
8 changes: 8 additions & 0 deletions layout/base/LayoutConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ enum class ComputeSizeFlag : uint8_t {
* https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch
*/
IApplyAutoMinSize, // only has an effect when eShrinkWrap is false

/**
* Indicates that we shouldn't take aspect ratio into account.
* This flag is only used to ignore aspect-ratio when computing intrinsic
* sizes in ComputeISizeValue(). (For now, only internal table boxes use this
* flag.)
*/
SkipAspectRatio,
};
using ComputeSizeFlags = mozilla::EnumSet<ComputeSizeFlag>;

Expand Down
63 changes: 51 additions & 12 deletions layout/generic/nsIFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6313,10 +6313,9 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize(
// https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
MOZ_ASSERT(!IsFrameOfType(eReplaced),
"aspect-ratio minimums should not apply to replaced elements");
// We use min-content on the inline-axis as the minimum size.
minISize = ComputeISizeValue(aRenderingContext, aWM, aCBSize,
boxSizingAdjust, boxSizingToMarginEdgeISize,
StyleExtremumLength::MinContent, aFlags);
// The inline size computed by aspect-ratio shouldn't less than the content
// size.
minISize = GetMinISize(aRenderingContext);
} else {
// Treat "min-width: auto" as 0.
// NOTE: Technically, "auto" is supposed to behave like "min-content" on
Expand Down Expand Up @@ -6474,6 +6473,29 @@ nscoord nsIFrame::ShrinkWidthToFit(gfxContext* aRenderingContext,
return result;
}

Maybe<nscoord> nsIFrame::ComputeInlineSizeFromAspectRatio(
WritingMode aWM, const LogicalSize& aCBSize,
const LogicalSize& aContentEdgeToBoxSizing, ComputeSizeFlags aFlags) const {
// FIXME: Bug 1670151: Use GetAspectRatio() to cover replaced elements.
const AspectRatio aspectRatio = StylePosition()->mAspectRatio.ToLayoutRatio();
if (aFlags.contains(ComputeSizeFlag::SkipAspectRatio) || !aspectRatio) {
return Nothing();
}

const StyleSize& styleBSize = StylePosition()->BSize(aWM);
if (aFlags.contains(ComputeSizeFlag::UseAutoBSize) ||
nsLayoutUtils::IsAutoBSize(styleBSize, aCBSize.BSize(aWM))) {
return Nothing();
}

MOZ_ASSERT(styleBSize.IsLengthPercentage());
nscoord bSize = nsLayoutUtils::ComputeBSizeValue(
aCBSize.BSize(aWM), aContentEdgeToBoxSizing.BSize(aWM),
styleBSize.AsLengthPercentage());
return Some(aspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisInline, aWM, bSize, aContentEdgeToBoxSizing));
}

nscoord nsIFrame::ComputeISizeValue(gfxContext* aRenderingContext,
const WritingMode aWM,
const LogicalSize& aContainingBlockSize,
Expand All @@ -6484,15 +6506,24 @@ nscoord nsIFrame::ComputeISizeValue(gfxContext* aRenderingContext,
// If 'this' is a container for font size inflation, then shrink
// wrapping inside of it should not apply font size inflation.
AutoMaybeDisableFontInflation an(this);
// TODO: Calculate aspect-ratio
// If we have an aspect-ratio and a definite block size, we resolve the
// min-content and max-content size by the aspect-ratio and the block size.
// https://github.com/w3c/csswg-drafts/issues/5032
Maybe<nscoord> intrinsicSizeFromAspectRatio =
aSize == StyleExtremumLength::MozAvailable
? Nothing()
: ComputeInlineSizeFromAspectRatio(aWM, aContainingBlockSize,
aContentEdgeToBoxSizing, aFlags);
nscoord result;
switch (aSize) {
case StyleExtremumLength::MaxContent:
result = GetPrefISize(aRenderingContext);
result = intrinsicSizeFromAspectRatio ? *intrinsicSizeFromAspectRatio
: GetPrefISize(aRenderingContext);
NS_ASSERTION(result >= 0, "inline-size less than zero");
return result;
case StyleExtremumLength::MinContent:
result = GetMinISize(aRenderingContext);
result = intrinsicSizeFromAspectRatio ? *intrinsicSizeFromAspectRatio
: GetMinISize(aRenderingContext);
NS_ASSERTION(result >= 0, "inline-size less than zero");
if (MOZ_UNLIKELY(
aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize))) {
Expand All @@ -6503,11 +6534,19 @@ nscoord nsIFrame::ComputeISizeValue(gfxContext* aRenderingContext,
}
return result;
case StyleExtremumLength::MozFitContent: {
nscoord pref = GetPrefISize(aRenderingContext),
min = GetMinISize(aRenderingContext),
fill =
aContainingBlockSize.ISize(aWM) -
(aBoxSizingToMarginEdge + aContentEdgeToBoxSizing.ISize(aWM));
nscoord pref = NS_UNCONSTRAINEDSIZE;
nscoord min = 0;
if (intrinsicSizeFromAspectRatio) {
// The min-content and max-content size are identical and equal to the
// size computed from the block size and the aspect ratio.
pref = min = *intrinsicSizeFromAspectRatio;
} else {
pref = GetPrefISize(aRenderingContext);
min = GetMinISize(aRenderingContext);
}
nscoord fill =
aContainingBlockSize.ISize(aWM) -
(aBoxSizingToMarginEdge + aContentEdgeToBoxSizing.ISize(aWM));
if (MOZ_UNLIKELY(
aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize))) {
min = std::min(min, fill);
Expand Down
5 changes: 5 additions & 0 deletions layout/generic/nsIFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -4389,6 +4389,11 @@ class nsIFrame : public nsQueryFrame {

NS_IMETHODIMP RefreshSizeCache(nsBoxLayoutState& aState);

Maybe<nscoord> ComputeInlineSizeFromAspectRatio(
mozilla::WritingMode aWM, const mozilla::LogicalSize& aCBSize,
const mozilla::LogicalSize& aContentEdgeToBoxSizing,
mozilla::ComputeSizeFlags aFlags) const;

public:
/**
* @return true if this text frame ends with a newline character. It
Expand Down
10 changes: 6 additions & 4 deletions layout/tables/BasicTableLayoutStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ static CellISizeInfo GetISizeInfo(gfxContext* aRenderingContext,
// it separately on the columns.
const LogicalSize zeroSize(aWM);
if (maxISize.ConvertsToLength() || maxISize.IsExtremumLength()) {
nscoord c = aFrame->ComputeISizeValue(aRenderingContext, aWM, zeroSize,
zeroSize, 0, maxISize);
nscoord c =
aFrame->ComputeISizeValue(aRenderingContext, aWM, zeroSize, zeroSize, 0,
maxISize, {ComputeSizeFlag::SkipAspectRatio});
minCoord = std::min(c, minCoord);
prefCoord = std::min(c, prefCoord);
} else if (maxISize.ConvertsToPercentage()) {
Expand All @@ -195,8 +196,9 @@ static CellISizeInfo GetISizeInfo(gfxContext* aRenderingContext,
}
}
if (minISize.ConvertsToLength() || minISize.IsExtremumLength()) {
nscoord c = aFrame->ComputeISizeValue(aRenderingContext, aWM, zeroSize,
zeroSize, 0, minISize);
nscoord c =
aFrame->ComputeISizeValue(aRenderingContext, aWM, zeroSize, zeroSize, 0,
minISize, {ComputeSizeFlag::SkipAspectRatio});
minCoord = std::max(c, minCoord);
prefCoord = std::max(c, prefCoord);
} else if (minISize.ConvertsToPercentage()) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
<title>CSS aspect-ratio: min-content size keyword</title>
<link rel="author" title="Google LLC" href="https://www.google.com/">
<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>

<!-- This is still under discussion in https://github.com/w3c/csswg-drafts/issues/5032
but this testcase tests the likely outcome. -->

<div style="height: 100px; width: min-content; aspect-ratio: 1/1; background: green;"></div>


<div style="height: 50px; width: min-content; aspect-ratio: 2/1; background: green;"></div>
<!-- min-content in the block axis is treated as auto -->
<div style="height: min-content; width: 100px; aspect-ratio: 2/1; background: green;"></div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<title>CSS aspect-ratio: fit-content size keyword</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-sizing-4/#valdef-width-fit-content">
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5032">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
<style>
div {
background: green;
aspect-ratio: 2/1;
}
</style>

<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>

<div style="height: 50px; width: -moz-fit-content; width: fit-content;"></div>
<!-- fit-content in the block axis is treated as auto -->
<div style="height: -moz-fit-content; height: fit-content; width: 100px;"></div>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<tr>
<th style='background: green; width: 100px; aspect-ratio: 1/1;'></th>
<td style='background: red; height: 50px; aspect-ratio: 4/1;'></td>
<td style='background: red; height: 50px; min-width: min-content; aspect-ratio: 4/1;'></td>
</tr>
</table>
<!-- aspect-ratio should apply to the table element -->
Expand Down

0 comments on commit eff538f

Please sign in to comment.