Bug 1546739 - Fix detection of intrinsic size dependence of images. r=dholbert

Fixed width and height is not a strong enough condition.

min/max-width with intrinsic size keywords makes the final size of the image
also depend on the intrinsic size. Don't optimize away reflows when the
intrinsic size changes if they're used.

Differential Revision: https://phabricator.services.mozilla.com/D28720

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-04-24 20:05:34 +00:00
Родитель 08992fb8e8
Коммит 761f6c8751
13 изменённых файлов: 266 добавлений и 6 удалений

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

@ -121,16 +121,40 @@ static bool HaveSpecifiedSize(const nsStylePosition* aStylePosition) {
aStylePosition->mHeight.IsLengthPercentage();
}
template<typename SizeOrMaxSize>
static bool DependsOnIntrinsicSize(const SizeOrMaxSize& aMinOrMaxSize) {
if (!aMinOrMaxSize.IsExtremumLength()) {
return false;
}
auto keyword = aMinOrMaxSize.AsExtremumLength();
switch (keyword) {
case StyleExtremumLength::MinContent:
case StyleExtremumLength::MaxContent:
case StyleExtremumLength::MozFitContent:
return true;
case StyleExtremumLength::MozAvailable:
return false;
}
MOZ_ASSERT_UNREACHABLE("Unknown sizing keyword?");
return false;
}
// Decide whether we can optimize away reflows that result from the
// image's intrinsic size changing.
static bool HaveFixedSize(const ReflowInput& aReflowInput) {
NS_ASSERTION(aReflowInput.mStylePosition,
"crappy reflowInput - null stylePosition");
static bool SizeDependsOnIntrinsicSize(const ReflowInput& aReflowInput) {
const auto& position = *aReflowInput.mStylePosition;
WritingMode wm = aReflowInput.GetWritingMode();
// Don't try to make this optimization when an image has percentages
// in its 'width' or 'height'. The percentages might be treated like
// auto (especially for intrinsic width calculations and for heights).
return aReflowInput.mStylePosition->mHeight.ConvertsToLength() &&
aReflowInput.mStylePosition->mWidth.ConvertsToLength();
//
// min-width: min-content and such can also affect our intrinsic size.
// but note that those keywords on the block axis behave like auto, so we
// don't need to check them.
return !position.mHeight.ConvertsToLength() ||
!position.mWidth.ConvertsToLength() ||
DependsOnIntrinsicSize(position.MinISize(wm)) ||
DependsOnIntrinsicSize(position.MaxISize(wm));
}
nsIFrame* NS_NewImageFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
@ -987,7 +1011,7 @@ void nsImageFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
MOZ_ASSERT(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
// see if we have a frozen size (i.e. a fixed width and height)
if (HaveFixedSize(aReflowInput)) {
if (!SizeDependsOnIntrinsicSize(aReflowInput)) {
AddStateBits(IMAGE_SIZECONSTRAINED);
} else {
RemoveStateBits(IMAGE_SIZECONSTRAINED);

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

@ -0,0 +1,12 @@
<!doctype html>
<title>CSS Test Reference</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
img {
border: 1px solid black;
height: 30px;
width: 60px;
}
</style>
<img src="/css/support/60x60-green.png">

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

@ -0,0 +1,23 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their min-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-001-ref.html">
<style>
img {
border: 1px solid black;
height: 30px;
width: 30px;
min-width: min-content;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>

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

@ -0,0 +1,23 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their min-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-001-ref.html">
<style>
img {
border: 1px solid black;
height: 30px;
width: 30px;
min-width: max-content;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>

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

@ -0,0 +1,12 @@
<!doctype html>
<title>CSS Test Reference</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
img {
border: 1px solid black;
height: 80px;
width: 60px;
}
</style>
<img src="/css/support/60x60-green.png">

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

@ -0,0 +1,23 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their max-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-003-ref.html">
<style>
img {
border: 1px solid black;
height: 80px;
width: 80px;
max-width: min-content;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>

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

@ -0,0 +1,23 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their max-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-003-ref.html">
<style>
img {
border: 1px solid black;
height: 80px;
width: 80px;
max-width: max-content;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>

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

@ -0,0 +1,12 @@
<!doctype html>
<title>CSS Test Reference</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
img {
border: 1px solid black;
height: 60px;
width: 30px;
}
</style>
<img src="/css/support/60x60-green.png">

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

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their min-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-005-ref.html">
<style>
img {
border: 1px solid black;
height: 30px;
width: 30px;
min-height: min-content;
writing-mode: vertical-lr;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>

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

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their min-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-005-ref.html">
<style>
img {
border: 1px solid black;
height: 30px;
width: 30px;
min-height: max-content;
writing-mode: vertical-lr;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>

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

@ -0,0 +1,12 @@
<!doctype html>
<title>CSS Test Reference</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
img {
border: 1px solid black;
width: 80px;
height: 60px;
}
</style>
<img src="/css/support/60x60-green.png">

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

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their max-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-007-ref.html">
<style>
img {
border: 1px solid black;
height: 80px;
width: 80px;
max-height: min-content;
writing-mode: vertical-lr;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>

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

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Image size is updated properly when intrinsic size changes, even with a fixed width and height, if their max-size depends on their intrinsic size</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-sizing/#sizing-values">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1546739">
<link rel="match" href="image-min-max-content-intrinsic-size-change-007-ref.html">
<style>
img {
border: 1px solid black;
height: 80px;
width: 80px;
max-height: max-content;
writing-mode: vertical-lr;
}
</style>
<img>
<script>
let img = document.querySelector("img");
img.offsetWidth; // Ensure the image is laid out.
img.onload = () => document.documentElement.className = "";
img.src = "/css/support/60x60-green.png";
</script>