Bug 1683424 - Take box sizing into account for replaced elements with aspect-ratio. r=TYLin

If aspect-ratio is '<ratio>', now the aspect-ratio works with box sizing
dimensions for replaced elements.

Also, ComputeRatioDependentSize() already considers writing-mode so we don't
need the conversion like logicalRatio in the old code.

For those calculations for intrinsic size contribution, we will fix them
in a separate patch.

Differential Revision: https://phabricator.services.mozilla.com/D100175
This commit is contained in:
Boris Chiou 2020-12-23 22:58:35 +00:00
Родитель 361f923f82
Коммит 11ab842010
4 изменённых файлов: 103 добавлений и 25 удалений

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

@ -2387,11 +2387,9 @@ bool nsContainerFrame::ResolvedOrientationIsVertical() {
LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
gfxContext* aRenderingContext, WritingMode aWM,
const IntrinsicSize& aIntrinsicSize, const AspectRatio& aIntrinsicRatio,
const IntrinsicSize& aIntrinsicSize, const AspectRatio& aAspectRatio,
const LogicalSize& aCBSize, const LogicalSize& aMargin,
const LogicalSize& aBorderPadding, ComputeSizeFlags aFlags) {
auto logicalRatio =
aWM.IsVertical() ? aIntrinsicRatio.Inverted() : aIntrinsicRatio;
const nsStylePosition* stylePos = StylePosition();
const auto* inlineStyleCoord = &stylePos->ISize(aWM);
const auto* blockStyleCoord = &stylePos->BSize(aWM);
@ -2641,7 +2639,6 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
"Our containing block must not have unconstrained inline-size!");
// Now calculate the used values for iSize and bSize:
if (isAutoISize) {
if (isAutoBSize) {
// 'auto' iSize, 'auto' bSize
@ -2652,9 +2649,11 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
if (hasIntrinsicISize) {
tentISize = intrinsicISize;
} else if (hasIntrinsicBSize && logicalRatio) {
tentISize = logicalRatio.ApplyTo(intrinsicBSize);
} else if (logicalRatio) {
} else if (hasIntrinsicBSize && aAspectRatio) {
tentISize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisInline, aWM, intrinsicBSize,
boxSizingAdjust);
} else if (aAspectRatio) {
tentISize =
aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar?
if (tentISize < 0) {
@ -2674,8 +2673,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
if (hasIntrinsicBSize) {
tentBSize = intrinsicBSize;
} else if (logicalRatio) {
tentBSize = logicalRatio.Inverted().ApplyTo(tentISize);
} else if (aAspectRatio) {
tentBSize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisBlock, aWM, tentISize, boxSizingAdjust);
} else {
tentBSize = fallbackIntrinsicSize.BSize(aWM);
}
@ -2690,34 +2690,39 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
tentISize = iSize; // * / 'stretch'
if (stretchB == eStretch) {
tentBSize = bSize; // 'stretch' / 'stretch'
} else if (stretchB == eStretchPreservingRatio && logicalRatio) {
} else if (stretchB == eStretchPreservingRatio && aAspectRatio) {
// 'normal' / 'stretch'
tentBSize = logicalRatio.Inverted().ApplyTo(iSize);
tentBSize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisBlock, aWM, iSize, boxSizingAdjust);
}
} else if (stretchB == eStretch) {
tentBSize = bSize; // 'stretch' / * (except 'stretch')
if (stretchI == eStretchPreservingRatio && logicalRatio) {
if (stretchI == eStretchPreservingRatio && aAspectRatio) {
// 'stretch' / 'normal'
tentISize = logicalRatio.ApplyTo(bSize);
tentISize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust);
}
} else if (stretchI == eStretchPreservingRatio && logicalRatio) {
} else if (stretchI == eStretchPreservingRatio && aAspectRatio) {
tentISize = iSize; // * (except 'stretch') / 'normal'
tentBSize = logicalRatio.Inverted().ApplyTo(iSize);
tentBSize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisBlock, aWM, iSize, boxSizingAdjust);
if (stretchB == eStretchPreservingRatio && tentBSize > bSize) {
// Stretch within the CB size with preserved intrinsic ratio.
tentBSize = bSize; // 'normal' / 'normal'
tentISize = logicalRatio.ApplyTo(bSize);
tentISize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust);
}
} else if (stretchB == eStretchPreservingRatio && logicalRatio) {
} else if (stretchB == eStretchPreservingRatio && aAspectRatio) {
tentBSize = bSize; // 'normal' / * (except 'normal' and 'stretch')
tentISize = logicalRatio.ApplyTo(bSize);
tentISize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust);
}
// ComputeAutoSizeWithIntrinsicDimensions preserves the ratio when
// applying the min/max-size. We don't want that when we have 'stretch'
// in either axis because tentISize/tentBSize is likely not according to
// ratio now.
if (logicalRatio && stretchI != eStretch && stretchB != eStretch) {
if (aAspectRatio && stretchI != eStretch && stretchB != eStretch) {
nsSize autoSize = nsLayoutUtils::ComputeAutoSizeWithIntrinsicDimensions(
minISize, minBSize, maxISize, maxBSize, tentISize, tentBSize);
// The nsSize that ComputeAutoSizeWithIntrinsicDimensions returns will
@ -2735,8 +2740,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
// 'auto' iSize, non-'auto' bSize
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
if (stretchI != eStretch) {
if (logicalRatio) {
iSize = logicalRatio.ApplyTo(bSize);
if (aAspectRatio) {
iSize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust);
} else if (hasIntrinsicISize) {
if (!(aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize) &&
intrinsicISize > iSize)) {
@ -2753,8 +2759,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
// non-'auto' iSize, 'auto' bSize
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
if (stretchB != eStretch) {
if (logicalRatio) {
bSize = logicalRatio.Inverted().ApplyTo(iSize);
if (aAspectRatio) {
bSize = aAspectRatio.ComputeRatioDependentSize(
LogicalAxis::eLogicalAxisBlock, aWM, iSize, boxSizingAdjust);
} else if (hasIntrinsicBSize) {
if (!(aFlags.contains(ComputeSizeFlag::BClampMarginBoxMinSize) &&
intrinsicBSize > bSize)) {

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

@ -864,12 +864,12 @@ class nsContainerFrame : public nsSplittableFrame {
* Calculate the used values for 'width' and 'height' for a replaced element.
* http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
*
* @param aIntrinsicRatio the aspect ratio calculated by GetAspectRatio().
* @param aAspectRatio the aspect ratio calculated by GetAspectRatio().
*/
mozilla::LogicalSize ComputeSizeWithIntrinsicDimensions(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::IntrinsicSize& aIntrinsicSize,
const mozilla::AspectRatio& aIntrinsicRatio,
const mozilla::AspectRatio& aAspectRatio,
const mozilla::LogicalSize& aCBSize, const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
mozilla::ComputeSizeFlags aFlags);

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

@ -0,0 +1,37 @@
<!DOCTYPE html>
<title>CSS aspect-ratio: img block size with box-sizing</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="match" href="../../reference/ref-filled-green-100px-square.xht" />
<style>
.border1 {
border-left: 10px solid green;
}
.border2 {
border-left: 15px solid green;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<!--
1st: A green rect 50x100.
border-left is 10x100 and the content box is 40x100.
We use 'aspect-ratio: auto && <ratio>', so the aspect-ratio works with
content-box dimensions always. The inline size of the content box is
(50px - 10px) = 40px, so the block size is 40px * 5/2 = 100px.
(note: width here is the inline size of border-box.)
2st: A green rect 25x100.
border-left is 15x100 and the content box is 10x100.
(note: width here is the inline size of content-box.)
3nd: A green rect 25x100.
border-left is 15x100 and the content box is 10x100 because we compute
the block size by aspect-ratio which works with border-box and so the
block size is 25px * 4 = 100.
(note: width here is the inline size of border-box.)
-->
<img class="border1" src="support/20x50-green.png" style="width: 50px; aspect-ratio: auto 1/1; box-sizing: border-box;"
><img class="border2" src="support/20x50-green.png" style="width: 10px; aspect-ratio: 1/10; box-sizing: content-box;"
><img class="border2" src="support/20x50-green.png" style="width: 25px; aspect-ratio: 1/4; box-sizing: border-box;">

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

@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>CSS aspect-ratio: img inline size with box-sizing</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="match" href="../../reference/ref-filled-green-100px-square.xht" />
<style>
img {
border-top: 40px solid green;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<!--
1st: A green rect 60x100.
border-top is 60x40 and the content box is 60x60.
We use 'aspect-ratio: auto && <ratio>', so the aspect-ratio works with
content-box dimensions always. The block size of the content box is
(100px - 40px) = 60px, so the inline size is 60px * 1/1 = 60px.
(note: height here is the block size of border-box.)
2nd: A green rect 20x100.
border-top is 20x40 and the content box is 20x60.
(note: height here is the block size of content-box.)
3rd: A green rect 20x100.
border-top is 20x40 and the content box is 20x60 because we compute
the inline size by aspect-ratio which works with border-box and so the
inline size is 100px / 5 = 20px.
(note: height here is the block size of border-box.)
-->
<img src="support/1x1-green.png" style="height: 100px; aspect-ratio: auto 1/10; box-sizing: border-box;"
><img src="support/1x1-green.png" style="height: 60px; aspect-ratio: 1/3; box-sizing: content-box;"
><img src="support/1x1-green.png" style="height: 100px; aspect-ratio: 1/5; box-sizing: border-box;">