Bug 1593796 - Apply the correct specified implicit size. r=mats

Per the spec, if multiple track sizes are given, the pattern is repeated as
necessary to find the size of the implicit tracks:
1. The first implicit grid track after the explicit grid receives the first
   specified size, and so on forwards.
2. The last implicit grid track before the explicit grid receives the last
   specified size, and so on backwards.

We use a positive index of the auto track sizes for (1) and a negative index
for (2), so we can apply the correct specified implicit size.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Chiou 2019-11-12 22:28:09 +00:00
parent 3e1c2db5be
commit 41488d1a22
3 changed files with 603 additions and 6 deletions

View File

@ -1149,20 +1149,34 @@ struct nsGridContainerFrame::TrackSizingFunctions {
const StyleTrackSize& SizingFor(uint32_t aTrackIndex) const {
static const StyleTrackSize kAutoTrackSize =
StyleTrackSize::Breadth(StyleTrackBreadth::Auto());
auto getImplicitSize = [this](size_t aIndex) -> const StyleTrackSize& {
// |aIndex| is the relative index to mAutoSizing. A negative value means it
// is the last Nth element.
auto getImplicitSize = [this](int32_t aIndex) -> const StyleTrackSize& {
MOZ_ASSERT(!(mAutoSizing.Length() == 1 &&
mAutoSizing.AsSpan()[0] == kAutoTrackSize),
"It's impossible to have one track with auto value because we "
"filter out this case during parsing");
if (mAutoSizing.IsEmpty()) {
return kAutoTrackSize;
}
// If multiple track sizes are given, the pattern is repeated as necessary
// to find the size of the implicit tracks.
return mAutoSizing.IsEmpty()
? kAutoTrackSize
: mAutoSizing.AsSpan()[aIndex % mAutoSizing.Length()];
int32_t i = aIndex % int32_t(mAutoSizing.Length());
if (i < 0) {
i += mAutoSizing.Length();
}
return mAutoSizing.AsSpan()[i];
};
if (MOZ_UNLIKELY(aTrackIndex < mExplicitGridOffset)) {
return getImplicitSize(aTrackIndex);
// The last implicit grid track before the explicit grid receives the
// last specified size, and so on backwards. Therefore we pass the
// negative relative index to imply that we should get the implicit size
// from the last Nth specified grid auto size.
return getImplicitSize(int32_t(aTrackIndex) -
int32_t(mExplicitGridOffset));
}
uint32_t index = aTrackIndex - mExplicitGridOffset;
if (index >= mRepeatAutoStart) {
@ -1173,7 +1187,7 @@ struct nsGridContainerFrame::TrackSizingFunctions {
}
}
if (index >= mExpandedTracks.Length()) {
return getImplicitSize(index);
return getImplicitSize(index - mExpandedTracks.Length());
}
auto& indices = mExpandedTracks[index];
const TrackListValue& value = mTrackListValues[indices.first()];

View File

@ -0,0 +1,130 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<meta charset="utf-8">
<title>CSS Grid Layout Test: Support for 'grid-auto-columns' and
'grid-auto-rows' properties with implicit tracks after and before the
explicit grid</title>
<link rel="help" href="https://drafts.csswg.org/css-grid/#auto-tracks">
<link rel="match" href="../reference/grid-support-grid-auto-columns-rows-003-ref.html">
<style>
#wrapper {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
}
/* Implicit and explicit grid track sizes */
.grid {
display: grid;
grid-auto-rows: 2px 3px;
grid-auto-columns: 2px 3px;
}
#one .grid { grid-template: 5px / 5px; }
#two .grid { grid-template: 5px 5px / 5px 5px; }
#three .grid { grid-template: 5px 5px 5px / 5px 5px 5px; }
/* Grid item positions. */
.item-left1 { grid-area: auto / auto / 1 / 1; }
.item-explicit { grid-area: 1 / 1 / -1 / -1; }
.item-right1 { grid-area: -1 / -1; }
#zero .item-left3 { grid-area: auto / auto / -3 / -3; }
#zero .item-left2 { grid-area: auto / auto / -2 / -2; }
#zero .item-right2 { grid-area: 2 / 2; }
#zero .item-right3 { grid-area: 3 / 3; }
#one .item-left3 { grid-area: auto / auto / -4 / -4; }
#one .item-left2 { grid-area: auto / auto / -3 / -3; }
#one .item-right2 { grid-area: 3 / 3; }
#one .item-right3 { grid-area: 4 / 4; }
#two .item-left3 { grid-area: auto / auto / -5 / -5; }
#two .item-left2 { grid-area: auto / auto / -4 / -4; }
#two .item-right2 { grid-area: 4 / 4; }
#two .item-right3 { grid-area: 5 / 5; }
#three .item-left3 { grid-area: auto / auto / -6 / -6; }
#three .item-left2 { grid-area: auto / auto / -5 / -5; }
#three .item-right2 { grid-area: 5 / 5; }
#three .item-right3 { grid-area: 6 / 6; }
/* Colors */
.item-left3 { background: #ff0; }
.item-left2 { background: #ff0; }
.item-left1 { background: #ff0; }
.item-explicit { background: #f0f; }
.item-right1 { background: #0ff; }
.item-right2 { background: #0ff; }
.item-right3 { background: #0ff; }
</style>
<script>
function createDivWithClass(className, parent) {
let element = document.createElement('div');
element.className = className || '';
if (!parent) {
parent = document.body;
}
parent.appendChild(element);
return element;
}
function generate(parentId) {
let parent = document.getElementById(parentId);
for (let leftNum = 0; leftNum <= 3; ++leftNum) {
for (let rightNum = 0; rightNum <= 3; ++rightNum) {
let grid = leftNum + rightNum > 0
? createDivWithClass("grid", parent)
: null;
for (let i = 1; i <= leftNum; ++i) {
createDivWithClass("item-left" + i, grid);
}
if (leftNum + rightNum > 0) {
createDivWithClass("item-explicit", grid);
}
for (let i = 1; i <= rightNum; ++i) {
createDivWithClass("item-right" + i, grid);
}
}
}
}
function run() {
// This is equal to something like this:
// <div class="grid">
// <div class="item-left3"></div>
// <div class="item-left2"></div>
// <div class="item-left1"></div>
// <div class="item-explicit"></div>
// <div class="item-right1"></div>
// <div class="item-right2"></div>
// <div class="item-right3"></div>
// </div>
// Generate the grid examples with 0~3 left items and 0~3 right items.
// The item-explicit is placed inside the 0x0 ~ 3x3 explicit tracks.
generate("zero");
generate("one");
generate("two");
generate("three");
document.documentElement.offsetHeight;
document.documentElement.classList.remove('reftest-wait');
}
</script>
</head>
<body onload="run()">
<div id="wrapper">
<!-- Zero explicit track -->
<div id="zero"></div>
<!-- One explicit track -->
<div id="one"></div>
<!-- Two explicit tracks -->
<div id="two"></div>
<!-- Three explicit tracks -->
<div id="three"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,453 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Grid Layout Test Reference: Support for 'grid-auto-columns' and
'grid-auto-rows' properties with implicit tracks after and before the
explicit grid</title>
<style>
#wrapper {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
}
div { position: relative; }
.item-left3 {
width: 3px;
height: 3px;
background: #ff0;
}
.item-left2 {
width: 2px;
height: 2px;
background: #ff0;
}
.item-left1 {
width: 3px;
height: 3px;
background: #ff0;
}
.item-explicit {
width: 5px;
height: 5px;
background: #f0f;
}
.item-right1 {
width: 2px;
height: 2px;
background: #0ff;
}
.item-right2 {
width: 3px;
height: 3px;
background: #0ff;
}
.item-right3 {
width: 2px;
height: 2px;
background: #0ff;
}
#zero .item-explicit {
width: 2px;
height: 2px;
}
#two .item-explicit {
width: 10px;
height: 10px;
}
#three .item-explicit {
width: 15px;
height: 15px;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="zero">
<div>
<div class="item-right1"></div>
</div>
<div>
<div class="item-right1"></div>
<div class="item-right2" style="left:2px;"></div>
</div>
<div>
<div class="item-right1"></div>
<div class="item-right2" style="left:2px;"></div>
<div class="item-right3" style="left:5px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-right1" style="left:3px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-right1" style="left:3px;"></div>
<div class="item-right2" style="left:5px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-right1" style="left:3px;"></div>
<div class="item-right2" style="left:5px;"></div>
<div class="item-right3" style="left:8px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-right1" style="left:5px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-right1" style="left:5px;"></div>
<div class="item-right2" style="left:7px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-right1" style="left:5px;"></div>
<div class="item-right2" style="left:7px;"></div>
<div class="item-right3" style="left:10px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-right1" style="left:8px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-right1" style="left:8px;"></div>
<div class="item-right2" style="left:10px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-right1" style="left:8px;"></div>
<div class="item-right2" style="left:10px;"></div>
<div class="item-right3" style="left:13px;"></div>
</div>
</div>
<div id="one">
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:5px;"></div>
</div>
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:5px;"></div>
<div class="item-right2" style="left:7px;"></div>
</div>
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:5px;"></div>
<div class="item-right2" style="left:7px;"></div>
<div class="item-right3" style="left:10px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:8px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:8px;"></div>
<div class="item-right2" style="left:10px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:8px;"></div>
<div class="item-right2" style="left:10px;"></div>
<div class="item-right3" style="left:13px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:10px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:10px;"></div>
<div class="item-right2" style="left:12px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:10px;"></div>
<div class="item-right2" style="left:12px;"></div>
<div class="item-right3" style="left:15px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:13px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:13px;"></div>
<div class="item-right2" style="left:15px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:13px;"></div>
<div class="item-right2" style="left:15px;"></div>
<div class="item-right3" style="left:18px;"></div>
</div>
</div>
<div id="two">
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:10px;"></div>
</div>
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:10px;"></div>
<div class="item-right2" style="left:12px;"></div>
</div>
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:10px;"></div>
<div class="item-right2" style="left:12px;"></div>
<div class="item-right3" style="left:15px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:13px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:13px;"></div>
<div class="item-right2" style="left:15px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:13px;"></div>
<div class="item-right2" style="left:15px;"></div>
<div class="item-right3" style="left:18px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:15px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:15px;"></div>
<div class="item-right2" style="left:17px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:15px;"></div>
<div class="item-right2" style="left:17px;"></div>
<div class="item-right3" style="left:20px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:18px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:18px;"></div>
<div class="item-right2" style="left:20px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:18px;"></div>
<div class="item-right2" style="left:20px;"></div>
<div class="item-right3" style="left:23px;"></div>
</div>
</div>
<div id="three">
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:15px;"></div>
</div>
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:15px;"></div>
<div class="item-right2" style="left:17px;"></div>
</div>
<div>
<div class="item-explicit"></div>
<div class="item-right1" style="left:15px;"></div>
<div class="item-right2" style="left:17px;"></div>
<div class="item-right3" style="left:20px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:18px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:18px;"></div>
<div class="item-right2" style="left:20px;"></div>
</div>
<div>
<div class="item-left1"></div>
<div class="item-explicit" style="left:3px;"></div>
<div class="item-right1" style="left:18px;"></div>
<div class="item-right2" style="left:20px;"></div>
<div class="item-right3" style="left:23px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:20px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:20px;"></div>
<div class="item-right2" style="left:22px;"></div>
</div>
<div>
<div class="item-left2"></div>
<div class="item-left1" style="left:2px;"></div>
<div class="item-explicit" style="left:5px;"></div>
<div class="item-right1" style="left:20px;"></div>
<div class="item-right2" style="left:22px;"></div>
<div class="item-right3" style="left:25px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:23px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:23px;"></div>
<div class="item-right2" style="left:25px;"></div>
</div>
<div>
<div class="item-left3"></div>
<div class="item-left2" style="left:3px;"></div>
<div class="item-left1" style="left:5px;"></div>
<div class="item-explicit" style="left:8px;"></div>
<div class="item-right1" style="left:23px;"></div>
<div class="item-right2" style="left:25px;"></div>
<div class="item-right3" style="left:28px;"></div>
</div>
</div>
</div>
</body>
</html>