Bug 1780475 - Obey contain-intrinsic-size in ContainSizeAxes. r=emilio

ContainSizeAxes::ContainSize and ContainSizeAxes::ContainIntrinsicSize
were just using 0 for the axes with size containment, now they will take
contain-intrinsic-width and contain-intrinsic-height into account.

The WritingMode parameter is replaced with a nsIFrame from which the
properties are retrieved.

There are various places that aren't currently using these functions, so
the effect of this patch is rather minimal, but some cases of the new
test are now passing.

Differential Revision: https://phabricator.services.mozilla.com/D152355
This commit is contained in:
Oriol Brufau 2022-07-22 14:35:10 +00:00
Родитель 5706a29a88
Коммит 6ae79ec065
10 изменённых файлов: 182 добавлений и 32 удалений

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

@ -586,7 +586,7 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
// XXXldb Can we depend more on ComputeSize here?
nsSize kidSize =
aState.mReflowInput.mStyleDisplay->GetContainSizeAxes().ContainSize(
aKidMetrics->PhysicalSize(), wm);
aKidMetrics->PhysicalSize(), *aState.mReflowInput.mFrame);
const nsSize desiredInsideBorderSize = kidSize + scrollbarGutterSize;
aState.mInsideBorderSize =
ComputeInsideBorderSize(aState, desiredInsideBorderSize);
@ -999,7 +999,7 @@ void nsHTMLScrollFrame::ReflowContents(ScrollReflowInput& aState,
aState.mHScrollbar != ShowScrollbar::Always) {
nsSize kidSize =
aState.mReflowInput.mStyleDisplay->GetContainSizeAxes().ContainSize(
kidDesiredSize.PhysicalSize(), desiredWm);
kidDesiredSize.PhysicalSize(), *aState.mReflowInput.mFrame);
nsSize insideBorderSize = ComputeInsideBorderSize(aState, kidSize);
nsRect scrolledRect = mHelper.GetUnsnappedScrolledRectInternal(
kidDesiredSize.ScrollableOverflow(), insideBorderSize);

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

@ -442,7 +442,7 @@ IntrinsicSize nsHTMLCanvasFrame::GetIntrinsicSize() {
return IntrinsicSize(0, 0);
}
return containAxes.ContainIntrinsicSize(
IntrinsicSizeFromCanvasSize(GetCanvasSize()), GetWritingMode());
IntrinsicSizeFromCanvasSize(GetCanvasSize()), *this);
}
/* virtual */

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

@ -640,23 +640,21 @@ static IntrinsicSize ComputeIntrinsicSize(imgIContainer* aImage,
ScaleIntrinsicSizeForDensity(intrinsicSize,
aFrame.GetImageFromStyle()->GetResolution());
}
return containAxes.ContainIntrinsicSize(intrinsicSize,
aFrame.GetWritingMode());
return containAxes.ContainIntrinsicSize(intrinsicSize, aFrame);
}
if (aKind == nsImageFrame::Kind::ListStyleImage) {
// Note: images are handled above, this handles gradients etc.
nscoord defaultLength = ListImageDefaultLength(aFrame);
return containAxes.ContainIntrinsicSize(
IntrinsicSize(defaultLength, defaultLength), aFrame.GetWritingMode());
IntrinsicSize(defaultLength, defaultLength), aFrame);
}
if (aFrame.ShouldShowBrokenImageIcon()) {
nscoord edgeLengthToUse = nsPresContext::CSSPixelsToAppUnits(
ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
return containAxes.ContainIntrinsicSize(
IntrinsicSize(edgeLengthToUse, edgeLengthToUse),
aFrame.GetWritingMode());
IntrinsicSize(edgeLengthToUse, edgeLengthToUse), aFrame);
}
if (aUseMappedRatio && style.StylePosition()->mAspectRatio.HasRatio()) {

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

@ -626,7 +626,7 @@ IntrinsicSize nsSubDocumentFrame::GetIntrinsicSize() {
if (auto size = olc->GetSubdocumentIntrinsicSize()) {
// Use the intrinsic size from the child SVG document, if available.
return containAxes.ContainIntrinsicSize(*size, GetWritingMode());
return containAxes.ContainIntrinsicSize(*size, *this);
}
}
@ -640,7 +640,7 @@ IntrinsicSize nsSubDocumentFrame::GetIntrinsicSize() {
// We must be an HTML <iframe>. Return fallback size.
return containAxes.ContainIntrinsicSize(IntrinsicSize(kFallbackIntrinsicSize),
GetWritingMode());
*this);
}
/* virtual */

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

@ -473,22 +473,21 @@ nsSize nsVideoFrame::GetVideoIntrinsicSize() const {
return {};
}
auto wm = GetWritingMode();
if (!isVideo) {
return containAxes.ContainSize(kFallbackIntrinsicSize, wm);
return containAxes.ContainSize(kFallbackIntrinsicSize, *this);
}
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
if (Maybe<CSSIntSize> size = element->GetVideoSize()) {
return containAxes.ContainSize(CSSPixel::ToAppUnits(*size), wm);
return containAxes.ContainSize(CSSPixel::ToAppUnits(*size), *this);
}
if (ShouldDisplayPoster()) {
if (Maybe<nsSize> imgSize = PosterImageSize()) {
return containAxes.ContainSize(*imgSize, wm);
return containAxes.ContainSize(*imgSize, *this);
}
}
return containAxes.ContainSize(kFallbackIntrinsicSize, wm);
return containAxes.ContainSize(kFallbackIntrinsicSize, *this);
}
IntrinsicSize nsVideoFrame::GetIntrinsicSize() {

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

@ -3565,39 +3565,57 @@ nscoord StyleCalcNode::Resolve(nscoord aBasis,
return ResolveInternal(aBasis, aRounder);
}
static nscoord Resolve(const StyleContainIntrinsicSize& aSize) {
if (aSize.IsNone()) {
return 0;
}
if (aSize.IsLength()) {
return aSize.AsLength().ToAppUnits();
}
MOZ_ASSERT(aSize.IsAutoLength());
// TODO: use last remembered size if possible.
return aSize.AsAutoLength().ToAppUnits();
}
nsSize ContainSizeAxes::ContainSize(const nsSize& aUncontainedSize,
const WritingMode& aWM) const {
const nsIFrame& aFrame) const {
if (!IsAny()) {
return aUncontainedSize;
}
const nsStylePosition* stylePos = aFrame.StylePosition();
if (IsBoth()) {
return nsSize();
return nsSize(Resolve(stylePos->mContainIntrinsicWidth),
Resolve(stylePos->mContainIntrinsicHeight));
}
// At this point, we know that precisely one of our dimensions is contained.
const bool zeroWidth =
(!aWM.IsVertical() && mIContained) || (aWM.IsVertical() && mBContained);
if (zeroWidth) {
return nsSize(0, aUncontainedSize.Height());
const bool containsWidth =
aFrame.GetWritingMode().IsVertical() ? mBContained : mIContained;
if (containsWidth) {
return nsSize(Resolve(stylePos->mContainIntrinsicWidth),
aUncontainedSize.Height());
}
return nsSize(aUncontainedSize.Width(), 0);
return nsSize(aUncontainedSize.Width(),
Resolve(stylePos->mContainIntrinsicHeight));
}
IntrinsicSize ContainSizeAxes::ContainIntrinsicSize(
const IntrinsicSize& aUncontainedSize, const WritingMode& aWM) const {
const IntrinsicSize& aUncontainedSize, const nsIFrame& aFrame) const {
if (!IsAny()) {
return aUncontainedSize;
}
const nsStylePosition* stylePos = aFrame.StylePosition();
if (IsBoth()) {
return IntrinsicSize(0, 0);
return IntrinsicSize(Resolve(stylePos->mContainIntrinsicWidth),
Resolve(stylePos->mContainIntrinsicHeight));
}
// At this point, we know that precisely one of our dimensions is contained.
const bool zeroWidth =
(!aWM.IsVertical() && mIContained) || (aWM.IsVertical() && mBContained);
const bool containsWidth =
aFrame.GetWritingMode().IsVertical() ? mBContained : mIContained;
IntrinsicSize result(aUncontainedSize);
if (zeroWidth) {
result.width = Some(0);
if (containsWidth) {
result.width = Some(Resolve(stylePos->mContainIntrinsicWidth));
} else {
result.height = Some(0);
result.height = Some(Resolve(stylePos->mContainIntrinsicHeight));
}
return result;
}

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

@ -87,9 +87,9 @@ struct ContainSizeAxes {
* Return a contained size from an uncontained size.
*/
nsSize ContainSize(const nsSize& aUncontainedSize,
const WritingMode& aWM) const;
const nsIFrame& aFrame) const;
IntrinsicSize ContainIntrinsicSize(const IntrinsicSize& aUncontainedSize,
const WritingMode& aWM) const;
const nsIFrame& aFrame) const;
const bool mIContained;
const bool mBContained;

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

@ -237,7 +237,7 @@ IntrinsicSize SVGOuterSVGFrame::GetIntrinsicSize() {
intrinsicSize.height.emplace(std::max(val, 0));
}
return containAxes.ContainIntrinsicSize(intrinsicSize, GetWritingMode());
return containAxes.ContainIntrinsicSize(intrinsicSize, *this);
}
/* virtual */

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

@ -0,0 +1,36 @@
[contain-intrinsic-size-028.html]
[.test 3]
expected: FAIL
[.test 4]
expected: FAIL
[.test 6]
expected: FAIL
[.test 8]
expected: FAIL
[.test 9]
expected: FAIL
[.test 10]
expected: FAIL
[.test 13]
expected: FAIL
[.test 15]
expected: FAIL
[.test 17]
expected: FAIL
[.test 18]
expected: FAIL
[.test 21]
expected: FAIL
[.test 23]
expected: FAIL

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

@ -0,0 +1,99 @@
<!DOCTYPE html>
<meta charset="utf8">
<title>CSS contain-intrinsic-size: single axis size containment</title>
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#intrinsic-size-override">
<link rel="help" href="https://drafts.csswg.org/css-contain-3/#containment-inline-size">
<style>
.test {
contain: inline-size;
display: inline-block;
background: green;
}
.test::before {
content: '';
display: block;
width: 40px;
height: 20px;
}
.cis-none {
contain-intrinsic-size: none none;
}
.cis-height {
contain-intrinsic-size: none 50px;
}
.cis-width {
contain-intrinsic-size: 100px none;
}
.cis-both {
contain-intrinsic-size: 100px 50px;
}
.vertical {
writing-mode: vertical-lr;
}
</style>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/check-layout-th.js"></script>
<body onload="checkLayout('.test')">
<div id="log"></div>
<div class="test cis-none"
data-expected-client-width="0" data-expected-client-height="20"></div>
<div class="test cis-height"
data-expected-client-width="0" data-expected-client-height="20"></div>
<div class="test cis-width"
data-expected-client-width="100" data-expected-client-height="20"></div>
<div class="test cis-both"
data-expected-client-width="100" data-expected-client-height="20"></div>
<div class="test cis-none vertical"
data-expected-client-width="40" data-expected-client-height="0"></div>
<div class="test cis-height vertical"
data-expected-client-width="40" data-expected-client-height="50"></div>
<div class="test cis-width vertical"
data-expected-client-width="40" data-expected-client-height="0"></div>
<div class="test cis-both vertical"
data-expected-client-width="40" data-expected-client-height="50"></div>
<hr>
<img class="test cis-none" src="/css/support/60x60-green.png"
data-expected-client-width="60" data-expected-client-height="60">
<img class="test cis-height" src="/css/support/60x60-green.png"
data-expected-client-width="60" data-expected-client-height="60">
<img class="test cis-width" src="/css/support/60x60-green.png"
data-expected-client-width="100" data-expected-client-height="60">
<img class="test cis-both" src="/css/support/60x60-green.png"
data-expected-client-width="100" data-expected-client-height="60">
<img class="test cis-none vertical" src="/css/support/60x60-green.png"
data-expected-client-width="60" data-expected-client-height="60">
<img class="test cis-height vertical" src="/css/support/60x60-green.png"
data-expected-client-width="60" data-expected-client-height="50">
<img class="test cis-width vertical" src="/css/support/60x60-green.png"
data-expected-client-width="60" data-expected-client-height="60">
<img class="test cis-both vertical" src="/css/support/60x60-green.png"
data-expected-client-width="60" data-expected-client-height="50">
<hr>
<svg class="test cis-none"
data-expected-client-width="300" data-expected-client-height="150"></svg>
<svg class="test cis-height"
data-expected-client-width="300" data-expected-client-height="150"></svg>
<svg class="test cis-width"
data-expected-client-width="100" data-expected-client-height="150"></svg>
<svg class="test cis-both"
data-expected-client-width="100" data-expected-client-height="150"></svg>
<svg class="test cis-none vertical"
data-expected-client-width="300" data-expected-client-height="150"></svg>
<svg class="test cis-height vertical"
data-expected-client-width="300" data-expected-client-height="50"></svg>
<svg class="test cis-width vertical"
data-expected-client-width="300" data-expected-client-height="150"></svg>
<svg class="test cis-both vertical"
data-expected-client-width="300" data-expected-client-height="50"></svg>
</body>