[css-grid] Implement fit-content track size
authorsvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Sep 2016 09:45:36 +0000 (09:45 +0000)
committersvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Sep 2016 09:45:36 +0000 (09:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161379

Reviewed by Manuel Rego Casasnovas.

Source/WebCore:

This implements the new <fit-content> track size which is defined as follows: "Represents
the formula min(max-content, max(auto, argument)), which is calculated similar to auto
(i.e. minmax(auto, max-content)), except that the track size is clamped at argument if it is
greater than the auto minimum."

From the parsing POV fit-content was implemented as a new type of function which only takes
one argument. That forced us to refactor some code because minmax() was the only allowed
function for <track-size>s so far.

The implementation key is a new attribute in GridTrack called growthLimitCap which is
precisely the single attribute of fit-content(). Some parts of the track sizing algorithm
were adapted to this change like for example the sorting of tracks by growth potential (we
need to consider the caps).

Tests: fast/css-grid-layout/fit-content-columns.html
fast/css-grid-layout/fit-content-rows.html

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::specifiedValueForGridTrackSize): Added support for fit-content sizes.
* css/StyleBuilderConverter.h:
(WebCore::StyleBuilderConverter::createGridTrackSize): Added support for fit-content sizes.
* css/parser/CSSParser.cpp:
(WebCore::isGridTrackFixedSized): Added support for fit-content sizes.
(WebCore::CSSParser::parseGridTrackSize): Added support for parsing fit-content() functions.
* css/parser/CSSPropertyParser.cpp: Added support for parsing fit-content() functions so
it'll be available once we switch to the new parser.
* rendering/RenderGrid.cpp:
(WebCore::GridTrack::baseSize): Just return a LayoutUnit, the return value optimization will
keep it fast in any case.
(WebCore::GridTrack::growthLimit): Ditto.
(WebCore::GridTrack::setGrowthLimit): Added an ASSERT to check that the growth limit is
never higher than the cap.
(WebCore::GridTrack::infiniteGrowthPotential):
(WebCore::GridTrack::plannedSize): Just return a LayoutUnit, the return value optimization will
keep it fast in any case.
(WebCore::GridTrack::tempSize): Just return a LayoutUnit, the return value optimization will
keep it fast in any case.
(WebCore::GridTrack::setTempSize): Added as we no longer return a reference in tempSize().
(WebCore::GridTrack::growTempSize): New utility function which increases the tempSize.
(WebCore::GridTrack::setInfinitelyGrowable):
(WebCore::GridTrack::setGrowthLimitCap): Added.
(WebCore::GridTrack::growthLimitCap): Ditto.
(WebCore::GridTrack::growthLimitIsInfinite): Made private.
(WebCore::RenderGrid::GridSizingData::freeSpace): Renamed from freeSpaceForDirection.
(WebCore::RenderGrid::GridSizingData::availableSpace): We now cache the available space as
it is used to compute relative (percentage) sizes.
(WebCore::RenderGrid::GridSizingData::setAvailableSpace): Ditto.
(WebCore::RenderGrid::GridSizingData::setFreeSpace): Renamed from setFreeSpaceForDirection.
(WebCore::RenderGrid::computeTrackSizesForDirection): Receives the available space instead
of the free space.
(WebCore::RenderGrid::computeIntrinsicLogicalWidths): Properly initialize free and available
spaces.
(WebCore::RenderGrid::computeIntrinsicLogicalHeight): Ditto.
(WebCore::RenderGrid::computeUsedBreadthOfGridTracks): Use available space to initialize the
track sizes. Also use sizingOperation to decide whether or not sizes are indefinite. Last
but not least, added support for fit-content tracks.
(WebCore::RenderGrid::computeUsedBreadthOfMinLength): Pass a GridTrackSize instead of a GridLength.
(WebCore::RenderGrid::computeUsedBreadthOfMaxLength): Ditto.
(WebCore::RenderGrid::gridTrackSize): Added support for fit-content.
(WebCore::RenderGrid::resolveContentBasedTrackSizingFunctions): Ditto.
(WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems): Ditto.
(WebCore::trackSizeForTrackSizeComputationPhase):
(WebCore::sortByGridTrackGrowthPotential): Reworked the function so it properly sorts tracks
with growth limit caps to support fit-content().
(WebCore::clampGrowthShareIfNeeded): Clamps the given growthShare passed as argument to the
track growth limit cap.
(WebCore::RenderGrid::distributeSpaceToTracks): Use the new setTempSize() method. Also sort
the selected tracks to grow over growth limits in order to respect the track caps eventually
set by fit-content (otherwise those tracks could indefinitely grow over the specified value).
(WebCore::RenderGrid::tracksAreWiderThanMinTrackBreadth): Use the new defined functions.
(WebCore::RenderGrid::applyStretchAlignmentToTracksIfNeeded): Use freeSpace().
(WebCore::RenderGrid::populateGridPositionsForDirection): Ditto.
(WebCore::GridTrack::infinitelyGrowable): Deleted.
(WebCore::RenderGrid::GridSizingData::freeSpaceForDirection): Deleted.
(WebCore::RenderGrid::GridSizingData::setFreeSpaceForDirection): Deleted.
(WebCore::RenderGrid::trackSizeForTrackSizeComputationPhase): Deleted.
* rendering/RenderGrid.h: Changed the signature of some methods. Moved
TrackSizeComputationPhase out of the RenderGrid class.
* rendering/style/GridTrackSize.h:
(WebCore::GridTrackSize::GridTrackSize): Added some extra documentation. Added a new
attribute to the constructor to support fit-content GridTrackSizes.
(WebCore::GridTrackSize::fitContentTrackBreadth): New method which returns the growth limit
cap set by fit-content().
(WebCore::GridTrackSize::minTrackBreadth):
(WebCore::GridTrackSize::isFitContent): Added.
(WebCore::GridTrackSize::length): Deleted.
(WebCore::GridTrackSize::isPercentage): Deleted.

LayoutTests:

New tests to verify that fit-content track sizes work as expected for columns and for
rows. Also added some more test cases to verify that we properly parse fit-content().

* fast/css-grid-layout/fit-content-columns-expected.html: Added.
* fast/css-grid-layout/fit-content-columns.html: Added.
* fast/css-grid-layout/fit-content-rows-expected.html: Added.
* fast/css-grid-layout/fit-content-rows.html: Added.
* fast/css-grid-layout/grid-auto-columns-rows-get-set-expected.txt:
* fast/css-grid-layout/grid-auto-columns-rows-get-set.html:
* fast/css-grid-layout/grid-columns-rows-get-set-expected.txt:
* fast/css-grid-layout/grid-columns-rows-get-set.html:
* fast/css-grid-layout/resources/grid-columns-rows-get-set.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@205966 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/fit-content-columns-expected.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/fit-content-columns.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/fit-content-rows-expected.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/fit-content-rows.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set-expected.txt
LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set.html
LayoutTests/fast/css-grid-layout/grid-columns-rows-get-set-expected.txt
LayoutTests/fast/css-grid-layout/grid-columns-rows-get-set.html
LayoutTests/fast/css-grid-layout/resources/grid-columns-rows-get-set.js
Source/WebCore/ChangeLog
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/StyleBuilderConverter.h
Source/WebCore/css/parser/CSSParser.cpp
Source/WebCore/css/parser/CSSPropertyParser.cpp
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderGrid.h
Source/WebCore/rendering/style/GridTrackSize.h

index 11f27cb..f4ac64f 100644 (file)
@@ -1,3 +1,23 @@
+2016-09-07  Sergio Villar Senin  <svillar@igalia.com>
+
+        [css-grid] Implement fit-content track size
+        https://bugs.webkit.org/show_bug.cgi?id=161379
+
+        Reviewed by Manuel Rego Casasnovas.
+
+        New tests to verify that fit-content track sizes work as expected for columns and for
+        rows. Also added some more test cases to verify that we properly parse fit-content().
+
+        * fast/css-grid-layout/fit-content-columns-expected.html: Added.
+        * fast/css-grid-layout/fit-content-columns.html: Added.
+        * fast/css-grid-layout/fit-content-rows-expected.html: Added.
+        * fast/css-grid-layout/fit-content-rows.html: Added.
+        * fast/css-grid-layout/grid-auto-columns-rows-get-set-expected.txt:
+        * fast/css-grid-layout/grid-auto-columns-rows-get-set.html:
+        * fast/css-grid-layout/grid-columns-rows-get-set-expected.txt:
+        * fast/css-grid-layout/grid-columns-rows-get-set.html:
+        * fast/css-grid-layout/resources/grid-columns-rows-get-set.js:
+
 2016-09-15  Alejandro G. Castro  <alex@igalia.com>
 
         [WebRTC][OpenWebRTC] crash in maybeHandleChangeMutedState
diff --git a/LayoutTests/fast/css-grid-layout/fit-content-columns-expected.html b/LayoutTests/fast/css-grid-layout/fit-content-columns-expected.html
new file mode 100644 (file)
index 0000000..5d5f24a
--- /dev/null
@@ -0,0 +1,346 @@
+<!DOCTYPE html>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    justify-content: start;
+    width: 100px;
+    position: relative;
+    padding-top: 10px;
+    margin-bottom: 5px;
+    grid-column-gap: 5px;
+}
+
+.fc0 { grid-template-columns: minmax(auto, 0px);}
+.fc40 { grid-template-columns: minmax(auto, 40px); }
+.fc80 { grid-template-columns: minmax(auto, 80px); }
+.fc110 { grid-template-columns: auto; }
+
+.fc0x2 { grid-template-columns: repeat(2, minmax(auto, 0px));}
+.fc40x2 { grid-template-columns: repeat(2, minmax(auto, 40px)); }
+.fc80x2 { grid-template-columns: repeat(2, minmax(auto, 80px)); }
+.fc110x2 { grid-template-columns: auto auto; }
+
+.fc0p { grid-template-columns: minmax(auto, 0%); }
+.fc30p { grid-template-columns: minmax(auto, 30%); }
+.fc90p { grid-template-columns: minmax(auto, 90%); }
+.fc110p { grid-template-columns: auto; }
+
+.fc0px2 { grid-template-columns: repeat(2, minmax(auto, 0%)); }
+.fc30px2 { grid-template-columns: repeat(2, minmax(auto, 30%)); }
+.fc90px2 { grid-template-columns: repeat(2, minmax(auto, 90%)); }
+.fc110px2 { grid-template-columns: auto auto; }
+
+.item {
+    font: 10px/1 Ahem;
+    background: cyan;
+}
+
+.spanningItem {
+    font: 10px/1 Ahem;
+    grid-column: 1 / -1;
+    grid-row: 2;
+    background: salmon;
+}
+
+.test {
+    position: absolute;
+    left: 0; right: 0; top: 0;
+    height: 5px;
+    background: purple;
+}
+.test:nth-child(2n) { background: orange; }
+
+.floatLeft {
+    float: left;
+    width: 190px;
+}
+
+h3 { font-size: 1em; }
+</style>
+
+<p>This test checks that 'fit-content()' works as expected, i.e., it's similar to 'auto' ('minmax(auto, -webkit-max-content)') except that the growth limit is clamped at the argument of 'fit-content' (if greater that the 'auto' minimum).</p>
+
+<div class="floatLeft">
+    <h3>Only fit-content() and with fixed size tracks.</h3>
+    <div class="grid fc0">
+        <div class="item">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc0x2">
+        <div class="item">XXX</div>
+        <div class="spanningItem">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc40">
+        <div class="item">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto auto;">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(auto, 40px) auto;">
+        <div class="item">XXX XXX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc80">
+        <div class="item">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc80x2">
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto minmax(auto, 80px)">
+        <div class="item autoRowSecondColumn">XXX XXX XXX</div>
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(auto, 20px) 50%;">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(10px, 40px) minmax(auto, 40px);">
+        <div class="item">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto minmax(10%, 200px);">
+        <div class="item autoRowSecondColumn">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+</div>
+
+<div class="floatLeft">
+    <h3>fit-content() with other content-sized tracks.</h3>
+    <div class="grid" style="grid-template-columns: minmax(auto, 40px) -webkit-max-content;">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(auto, 40px) -webkit-max-content;">
+        <div class="item">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(auto, 40px) -webkit-max-content;">
+        <div class="item autoRowSecondColumn">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content minmax(auto, 40px);">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content minmax(auto, 40px);">
+        <div class="item">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content minmax(auto, 40px);">
+        <div class="item autoRowSecondColumn">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(auto, 30px) -webkit-min-content -webkit-max-content">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content minmax(auto, 30px) -webkit-max-content">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content -webkit-max-content minmax(auto, 30px)">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(auto, 30px) -webkit-min-content -webkit-max-content">
+        <div class="item" style="grid-column: 1">XXX XX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content minmax(auto, 30px) -webkit-max-content">
+        <div class="item" style="grid-column: 1">XXX XX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content -webkit-max-content minmax(auto, 30px)">
+        <div class="item" style="grid-column: 2">XXX XX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+</div>
+
+<div class="floatLeft">
+    <h3>fit-content() with percentage arguments.</h3>
+    <div class="grid fc0p">
+        <div class="item">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc0px2">
+        <div class="item">XXX</div>
+        <div class="spanningItem">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc30p">
+        <div class="item">XX XX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc30px2">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc30px2">
+        <div class="item autoRowSecondColumn">X X X</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc90p">
+        <div class="item">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc90px2">
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto minmax(auto, 90%)">
+        <div class="item autoRowSecondColumn">XXX XXX XXX</div>
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+</div>
+
+<div class="floatLeft">
+    <h3>-webkit-max-content < fit-content() argument.</h3>
+
+    <div class="grid fc110">
+        <div class="item">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc110x2">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc110x2">
+        <div class="item">XXX XXX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto auto;">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto auto;">
+        <div class="item autoRowSecondColumn">XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-max-content auto;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto -webkit-min-content;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-max-content auto -webkit-max-content;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content auto -webkit-min-content;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto auto auto;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+</div>
diff --git a/LayoutTests/fast/css-grid-layout/fit-content-columns.html b/LayoutTests/fast/css-grid-layout/fit-content-columns.html
new file mode 100644 (file)
index 0000000..770dc2f
--- /dev/null
@@ -0,0 +1,347 @@
+<!DOCTYPE html>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    justify-content: start;
+    width: 100px;
+    position: relative;
+    padding-top: 10px;
+    margin-bottom: 5px;
+    grid-column-gap: 5px;
+}
+
+.fc0 { grid-template-columns: fit-content(0px);}
+.fc40 { grid-template-columns: fit-content(40px); }
+.fc80 { grid-template-columns: fit-content(80px); }
+.fc110 { grid-template-columns: fit-content(110px); }
+
+.fc0x2 { grid-template-columns: repeat(2, fit-content(0px));}
+.fc40x2 { grid-template-columns: repeat(2, fit-content(40px)); }
+.fc80x2 { grid-template-columns: repeat(2, fit-content(80px)); }
+.fc110x2 { grid-template-columns: repeat(2, fit-content(110px)); }
+
+.fc0p { grid-template-columns: fit-content(0%); }
+.fc30p { grid-template-columns: fit-content(30%); }
+.fc90p { grid-template-columns: fit-content(90%); }
+.fc110p { grid-template-columns: fit-content(110%); }
+
+.fc0px2 { grid-template-columns: repeat(2, fit-content(0%)); }
+.fc30px2 { grid-template-columns: repeat(2, fit-content(30%)); }
+.fc90px2 { grid-template-columns: repeat(2, fit-content(90%)); }
+.fc110px2 { grid-template-columns: repeat(2, fit-content(110%)); }
+
+.item {
+    font: 10px/1 Ahem;
+    background: cyan;
+}
+
+.spanningItem {
+    font: 10px/1 Ahem;
+    grid-column: 1 / -1;
+    grid-row: 2;
+    background: salmon;
+}
+
+.test {
+    position: absolute;
+    left: 0; right: 0; top: 0;
+    height: 5px;
+    background: purple;
+}
+.test:nth-child(2n) { background: orange; }
+
+.floatLeft {
+    float: left;
+    width: 190px;
+}
+
+h3 { font-size: 1em; }
+
+</style>
+
+<p>This test checks that 'fit-content()' works as expected, i.e., it's similar to 'auto' ('minmax(auto, -webkit-max-content)') except that the growth limit is clamped at the argument of 'fit-content' (if greater that the 'auto' minimum).</p>
+
+<div class="floatLeft">
+    <h3>Only fit-content() and with fixed size tracks.</h3>
+    <div class="grid fc0">
+        <div class="item">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc0x2">
+        <div class="item">XXX</div>
+        <div class="spanningItem">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc40">
+        <div class="item">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc40x2">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc40x2">
+        <div class="item">XXX XXX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc80">
+        <div class="item">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc80x2">
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc80x2">
+        <div class="item autoRowSecondColumn">XXX XXX XXX</div>
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(20px) 50%;">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: minmax(10px, 40px) fit-content(40px);">
+        <div class="item">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(40px) minmax(10%, 200px);">
+        <div class="item autoRowSecondColumn">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+</div>
+
+<div class="floatLeft">
+    <h3>fit-content() with other content-sized tracks.</h3>
+    <div class="grid" style="grid-template-columns: fit-content(40px) -webkit-max-content;">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(40px) -webkit-max-content;">
+        <div class="item">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(40px) -webkit-max-content;">
+        <div class="item autoRowSecondColumn">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content fit-content(40px);">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content fit-content(40px);">
+        <div class="item">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content fit-content(40px);">
+        <div class="item autoRowSecondColumn">XXXXX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(30px) -webkit-min-content -webkit-max-content">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content fit-content(30px) -webkit-max-content">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content -webkit-max-content fit-content(30px)">
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(30px) -webkit-min-content -webkit-max-content">
+        <div class="item" style="grid-column: 1">XXX XX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content fit-content(30px) -webkit-max-content">
+        <div class="item" style="grid-column: 1">XXX XX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content -webkit-max-content fit-content(30px)">
+        <div class="item" style="grid-column: 2">XXX XX</div>
+        <div class="spanningItem">XXX XX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+</div>
+
+<div class="floatLeft">
+    <h3>fit-content() with percentage arguments.</h3>
+    <div class="grid fc0p">
+        <div class="item">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc0px2">
+        <div class="item">XXX</div>
+        <div class="spanningItem">XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc30p">
+        <div class="item">XX XX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc30px2">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc30px2">
+        <div class="item autoRowSecondColumn">X X X</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc90p">
+        <div class="item">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc90px2">
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc90px2">
+        <div class="item autoRowSecondColumn">XXX XXX XXX</div>
+        <div class="spanningItem">XXX XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+</div>
+
+<div class="floatLeft">
+    <h3>-webkit-max-content < fit-content() argument.</h3>
+
+    <div class="grid fc110">
+        <div class="item">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+    </div>
+
+    <div class="grid fc110x2">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid fc110x2">
+        <div class="item">XXX XXX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(110px) fit-content(40px);">
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(110px) fit-content(40px);">
+        <div class="item autoRowSecondColumn">XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-max-content fit-content(110px);">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: fit-content(110px) -webkit-min-content;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-max-content fit-content(110px) -webkit-max-content;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: -webkit-min-content fit-content(110px) -webkit-min-content;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+    <div class="grid" style="grid-template-columns: auto fit-content(110px) auto;">
+        <div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
+        <div class="spanningItem">XXX XXX</div>
+        <div class="test autoRowFirstColumn"></div>
+        <div class="test autoRowSecondColumn"></div>
+        <div class="test autoRowThirdColumn"></div>
+    </div>
+
+</div>
diff --git a/LayoutTests/fast/css-grid-layout/fit-content-rows-expected.html b/LayoutTests/fast/css-grid-layout/fit-content-rows-expected.html
new file mode 100644 (file)
index 0000000..60b6640
--- /dev/null
@@ -0,0 +1,343 @@
+<!DOCTYPE html>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    justify-content: start;
+    align-content: start;
+    height: 100px;
+    width: 40px;
+    position: relative;
+    padding-left: 10px;
+    margin-right: 5px;
+    grid-row-gap: 5px;
+    float: left;
+}
+
+.fc0 { grid-template-rows: minmax(auto, 0px);}
+.fc40 { grid-template-rows: minmax(auto, 40px); }
+.fc80 { grid-template-rows: minmax(auto, 80px); }
+.fc110 { grid-template-rows: auto; }
+
+.fc0x2 { grid-template-rows: repeat(2, minmax(auto, 0px));}
+.fc40x2 { grid-template-rows: repeat(2, minmax(auto, 40px)); }
+.fc80x2 { grid-template-rows: repeat(2, minmax(auto, 80px)); }
+.fc110x2 { grid-template-rows: auto auto; }
+
+.fc0p { grid-template-rows: minmax(auto, 0%); }
+.fc30p { grid-template-rows: minmax(auto, 30px); }
+.fc90p { grid-template-rows: minmax(auto, 90px); }
+.fc110p { grid-template-rows: auto; }
+
+.fc0px2 { grid-template-rows: repeat(2, minmax(auto, 0%)); }
+.fc30px2 { grid-template-rows: repeat(2, minmax(auto, 30px)); }
+.fc90px2 { grid-template-rows: repeat(2, minmax(auto, 90px)); }
+.fc110px2 { grid-template-rows: auto auto; }
+
+.item {
+    font: 10px/1 Ahem;
+    background: cyan;
+}
+
+.spanningItem {
+    font: 10px/1 Ahem;
+    grid-row: 1 / -1;
+    grid-column: 2;
+    background: salmon;
+}
+
+.test {
+    position: absolute;
+    left: 0; top: 0; bottom: 0;
+    width: 5px;
+    background: purple;
+}
+.test:nth-child(2n) { background: orange; }
+
+.firstRow { grid-row: 1 / 2; }
+.secondRow { grid-row: 2 / 3; }
+.thirdRow { grid-row: 3 / 4; }
+
+div.grid > div { -webkit-writing-mode: vertical-lr; }
+
+</style>
+
+<p>This test checks that 'fit-content()' works as expected, i.e., it's similar to 'auto' ('minmax(auto, -webkit-max-content)') except that the growth limit is clamped at the argument of 'fit-content' (if greater that the 'auto' minimum).</p>
+
+<div class="grid fc0">
+    <div class="item">XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc0x2">
+    <div class="item">XXX</div>
+    <div class="spanningItem">XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc40">
+    <div class="item">XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto auto;">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 40px) auto;">
+    <div class="item">XXX XXX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc80">
+    <div class="item">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc80x2">
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto minmax(auto, 80px)">
+    <div class="item secondRow">XXX XXX XXX</div>
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 20px) 50%;">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(10px, 40px) minmax(auto, 40px);">
+    <div class="item">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto minmax(10%, 200px);">
+    <div class="item secondRow">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<br clear="all">
+<br clear="all">
+
+<div class="grid" style="grid-template-rows: minmax(auto, 40px) -webkit-max-content;">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 40px) -webkit-max-content;">
+    <div class="item">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 40px) -webkit-max-content;">
+    <div class="item secondRow">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content minmax(auto, 40px);">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content minmax(auto, 40px);">
+    <div class="item">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content minmax(auto, 40px);">
+    <div class="item secondRow">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 30px) -webkit-min-content -webkit-max-content">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content minmax(auto, 30px) -webkit-max-content">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content -webkit-max-content minmax(auto, 30px)">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 30px) -webkit-min-content -webkit-max-content">
+    <div class="item" style="grid-row: 1">XXX XX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content minmax(auto, 30px) -webkit-max-content">
+    <div class="item" style="grid-row: 1">XXX XX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content -webkit-max-content minmax(auto, 30px)">
+    <div class="item" style="grid-row: 2">XXX XX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<br clear="all">
+<br clear="all">
+
+<div class="grid fc0p">
+    <div class="item">XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc0px2">
+    <div class="item">XXX</div>
+    <div class="spanningItem">XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc30p">
+    <div class="item">XX XX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc30px2">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc30px2">
+    <div class="item secondRow">X X X</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc90p">
+    <div class="item">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc90px2">
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto minmax(auto, 90px)">
+    <div class="item secondRow">XXX XXX XXX</div>
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<br clear="all">
+<br clear="all">
+
+<div class="grid fc110">
+    <div class="item">XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc110x2">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc110x2">
+    <div class="item">XXX XXX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto auto;">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto auto;">
+    <div class="item secondRow">XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-max-content auto;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto -webkit-min-content;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-max-content auto -webkit-max-content;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content auto -webkit-min-content;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto auto auto;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
diff --git a/LayoutTests/fast/css-grid-layout/fit-content-rows.html b/LayoutTests/fast/css-grid-layout/fit-content-rows.html
new file mode 100644 (file)
index 0000000..327e4be
--- /dev/null
@@ -0,0 +1,347 @@
+<!DOCTYPE html>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    justify-content: start;
+    align-content: start;
+    height: 100px;
+    width: 40px;
+    position: relative;
+    padding-left: 10px;
+    margin-right: 5px;
+    grid-row-gap: 5px;
+    float: left;
+}
+
+.fc0 { grid-template-rows: fit-content(0px);}
+.fc40 { grid-template-rows: fit-content(40px); }
+.fc80 { grid-template-rows: fit-content(80px); }
+.fc110 { grid-template-rows: fit-content(110px); }
+
+.fc0x2 { grid-template-rows: repeat(2, fit-content(0px));}
+.fc40x2 { grid-template-rows: repeat(2, fit-content(40px)); }
+.fc80x2 { grid-template-rows: repeat(2, fit-content(80px)); }
+.fc110x2 { grid-template-rows: repeat(2, fit-content(110px)); }
+
+.fc0p { grid-template-rows: fit-content(0%); }
+.fc30p { grid-template-rows: fit-content(30%); }
+.fc90p { grid-template-rows: fit-content(90%); }
+.fc110p { grid-template-rows: fit-content(110%); }
+
+.fc0px2 { grid-template-rows: repeat(2, fit-content(0%)); }
+.fc30px2 { grid-template-rows: repeat(2, fit-content(30%)); }
+.fc90px2 { grid-template-rows: repeat(2, fit-content(90%)); }
+.fc110px2 { grid-template-rows: repeat(2, fit-content(110%)); }
+
+div.grid > div { -webkit-writing-mode: vertical-lr; }
+
+.item {
+    font: 10px/1 Ahem;
+    background: cyan;
+}
+
+.spanningItem {
+    font: 10px/1 Ahem;
+    grid-row: 1 / -1;
+    grid-column: 2;
+    background: salmon;
+}
+
+.test {
+    position: absolute;
+    left: 0; bottom: 0; top: 0;
+    width: 5px;
+    background: purple;
+}
+.test:nth-child(2n) { background: orange; }
+
+.firstRow { grid-row: 1 / 2; }
+.secondRow { grid-row: 2 / 3; }
+.thirdRow { grid-row: 3 / 4; }
+
+h3 { font-size: 1em; }
+.container { float: left; height: 110px;}
+
+</style>
+
+<p>This test checks that 'fit-content()' works as expected, i.e., it's similar to 'auto' ('minmax(auto, -webkit-max-content)') except that the growth limit is clamped at the argument of 'fit-content' (if greater that the 'auto' minimum).</p>
+
+<div class="grid fc0">
+    <div class="item">XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc0x2">
+    <div class="item">XXX</div>
+    <div class="spanningItem">XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc40">
+    <div class="item">XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc40x2">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc40x2">
+    <div class="item">XXX XXX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc80">
+    <div class="item">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc80x2">
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc80x2">
+    <div class="item secondRow">XXX XXX XXX</div>
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(20px) 50%;">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: minmax(10px, 40px) fit-content(40px);">
+    <div class="item">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(40px) minmax(10%, 200px);">
+    <div class="item secondRow">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+</div>
+
+<br clear ="all">
+<br clear ="all">
+
+<div class="grid" style="grid-template-rows: fit-content(40px) -webkit-max-content;">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(40px) -webkit-max-content;">
+    <div class="item">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(40px) -webkit-max-content;">
+    <div class="item secondRow">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content fit-content(40px);">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content fit-content(40px);">
+    <div class="item">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content fit-content(40px);">
+    <div class="item secondRow">XXXXX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(30px) -webkit-min-content -webkit-max-content">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content fit-content(30px) -webkit-max-content">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content -webkit-max-content fit-content(30px)">
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(30px) -webkit-min-content -webkit-max-content">
+    <div class="item" style="grid-row: 1">XXX XX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content fit-content(30px) -webkit-max-content">
+    <div class="item" style="grid-row: 1">XXX XX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content -webkit-max-content fit-content(30px)">
+    <div class="item" style="grid-row: 2">XXX XX</div>
+    <div class="spanningItem">XXX XX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<br clear="all">
+<br clear="all">
+
+<div class="grid fc0p">
+    <div class="item">XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc0px2">
+    <div class="item">XXX</div>
+    <div class="spanningItem">XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc30p">
+    <div class="item">XX XX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc30px2">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc30px2">
+    <div class="item secondRow">X X X</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc90p">
+    <div class="item">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc90px2">
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc90px2">
+    <div class="item secondRow">XXX XXX XXX</div>
+    <div class="spanningItem">XXX XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<br clear="all">
+<br clear="all">
+
+<div class="grid fc110">
+    <div class="item">XXX XXX</div>
+    <div class="test firstRow"></div>
+</div>
+
+<div class="grid fc110x2">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid fc110x2">
+    <div class="item">XXX XXX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(110px) fit-content(40px);">
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(110px) fit-content(40px);">
+    <div class="item secondRow">XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-max-content fit-content(110px);">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: fit-content(110px) -webkit-min-content;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-max-content fit-content(110px) -webkit-max-content;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: -webkit-min-content fit-content(110px) -webkit-min-content;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
+
+<div class="grid" style="grid-template-rows: auto fit-content(110px) auto;">
+    <div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
+    <div class="spanningItem">XXX XXX</div>
+    <div class="test firstRow"></div>
+    <div class="test secondRow"></div>
+    <div class="test thirdRow"></div>
+</div>
index 12532a8..77fb300 100644 (file)
@@ -12,6 +12,8 @@ PASS window.getComputedStyle(gridAutoMinMaxContent, '').getPropertyValue('grid-a
 PASS window.getComputedStyle(gridAutoMinMaxContent, '').getPropertyValue('grid-auto-columns') is "-webkit-max-content"
 PASS window.getComputedStyle(gridAutoAutoInMinMax, '').getPropertyValue('grid-auto-rows') is "minmax(auto, 48px)"
 PASS window.getComputedStyle(gridAutoAutoInMinMax, '').getPropertyValue('grid-auto-columns') is "minmax(80px, auto)"
+PASS window.getComputedStyle(gridAutoFitContent, '').getPropertyValue('grid-auto-rows') is "fit-content(50%)"
+PASS window.getComputedStyle(gridAutoFitContent, '').getPropertyValue('grid-auto-columns') is "fit-content(30px)"
 
 Test that getting grid-template-columns and grid-template-rows set through CSS lists every track listed whether implicitly or explicitly created
 PASS window.getComputedStyle(gridAutoFixedFixedWithChildren, '').getPropertyValue('grid-auto-rows') is "30px"
@@ -48,6 +50,8 @@ PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "min
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "minmax(-webkit-max-content, -webkit-min-content)"
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "minmax(-webkit-min-content, 10px) 48px 5%"
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto 30px minmax(10%, 60%)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "fit-content(10px) fit-content(30%)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "fit-content(5%) fit-content(40px)"
 
 Test setting grid-auto-columns and grid-auto-rows to bad minmax value through JS
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
@@ -62,6 +66,8 @@ PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "aut
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
 
 Test setting grid-auto-columns and grid-auto-rows to 'inherit' through JS
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is '50px'
index eaa62c4..f369ac9 100644 (file)
     grid-auto-columns: 25px 50px 100px;
 }
 
+.gridAutoFitContent {
+    height: 50px;
+    grid-auto-columns: fit-content(30px);
+    grid-auto-rows: fit-content(50%);
+}
+
 </style>
 <script src="../../resources/js-test-pre.js"></script>
 <script src="resources/grid-definitions-parsing-utils.js"></script>
@@ -66,6 +72,7 @@
     <div style="grid-column: -4; grid-row: -4"></div>
     <div style="grid-column: -5; grid-row: -5"></div>
 </div>
+<div class="grid gridAutoFitContent" id="gridAutoFitContent"></div>
 
 <script>
 description('Test that setting and getting grid-auto-columns and grid-auto-rows works as expected');
@@ -75,6 +82,7 @@ testGridAutoDefinitionsValues(document.getElementById("gridAutoFixedFixed"), "30
 testGridAutoDefinitionsValues(document.getElementById("gridAutoMinMax"), "minmax(10%, 15px)", "minmax(30%, 100px)");
 testGridAutoDefinitionsValues(document.getElementById("gridAutoMinMaxContent"), "-webkit-min-content", "-webkit-max-content");
 testGridAutoDefinitionsValues(document.getElementById("gridAutoAutoInMinMax"), "minmax(auto, 48px)", "minmax(80px, auto)");
+testGridAutoDefinitionsValues(document.getElementById("gridAutoFitContent"), "fit-content(50%)", "fit-content(30px)");
 
 debug("");
 debug("Test that getting grid-template-columns and grid-template-rows set through CSS lists every track listed whether implicitly or explicitly created");
@@ -114,6 +122,7 @@ testAutoValues("18em", "66em", "180px", "660px");
 testAutoValues("minmax(-webkit-min-content, 8vh)", "minmax(10vw, -webkit-min-content)", "minmax(-webkit-min-content, 48px)", "minmax(80px, -webkit-min-content)");
 testAutoValues("minmax(-webkit-min-content, -webkit-max-content)", "minmax(-webkit-max-content, -webkit-min-content)");
 testAutoValues("minmax(-webkit-min-content, 10px) 48px 5%", "auto 30px minmax(10%, 60%)");
+testAutoValues("fit-content(10px) fit-content(30%)", "fit-content(5%) fit-content(calc(20px + 2em))", "fit-content(10px) fit-content(30%)", "fit-content(5%) fit-content(40px)");
 
 debug("");
 debug("Test setting grid-auto-columns and grid-auto-rows to bad minmax value through JS");
@@ -123,6 +132,7 @@ testAutoValues("minmax()", "minmax(30px 30% 30em)", "auto", "auto");
 testAutoValues("none", "none", "auto", "auto");
 testAutoValues("10px [a] 20px", "[z] auto [y] -webkit-min-content", "auto", "auto");
 testAutoValues("repeat(2, 10px [a] 20px)", "[z] repeat(auto-fit, 100px)", "auto", "auto");
+testAutoValues("fit-content(min-content) fit-content(auto)", "fit-content(fit-content(3%)) fit-content(minmax(2px, 30px))", "auto", "auto");
 
 function testInherit()
 {
index 1358a4c..58cb387 100644 (file)
@@ -44,6 +44,8 @@ PASS window.getComputedStyle(gridWithCalcComplexInsideMinMaxElement, '').getProp
 PASS window.getComputedStyle(gridWithCalcComplexInsideMinMaxElement, '').getPropertyValue('grid-template-rows') is "300px"
 PASS window.getComputedStyle(gridWithAutoInsideMinMaxElement, '').getPropertyValue('grid-template-columns') is "20px"
 PASS window.getComputedStyle(gridWithAutoInsideMinMaxElement, '').getPropertyValue('grid-template-rows') is "11px"
+PASS window.getComputedStyle(gridWithFitContentFunctionElement, '').getPropertyValue('grid-template-columns') is "7px"
+PASS window.getComputedStyle(gridWithFitContentFunctionElement, '').getPropertyValue('grid-template-rows') is "11px"
 
 Test getting wrong values for grid-template-columns and grid-template-rows through CSS (they should resolve to the default: 'none')
 PASS window.getComputedStyle(gridWithFitContentElement, '').getPropertyValue('grid-template-columns') is "none"
@@ -80,6 +82,10 @@ PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is
 PASS element.style.gridTemplateColumns is "-webkit-max-content"
 PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "0px"
 PASS element.style.gridTemplateRows is "-webkit-max-content"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "0px"
+PASS element.style.gridTemplateColumns is "fit-content(100px)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "0px"
+PASS element.style.gridTemplateRows is "fit-content(25%)"
 
 Test getting and setting grid-template-columns and grid-template-rows to minmax() values through JS
 PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "440px"
@@ -166,6 +172,22 @@ PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-column
 PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
 PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
 PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none"
 
 Test setting grid-template-columns and grid-template-rows back to 'none' through JS
 PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "18px"
index 0dfed24..4dff1af 100644 (file)
     grid-template-columns: minmax(auto, 20px);
     grid-template-rows: minmax(max-content, auto);
 }
+.gridWithFitContentFunction {
+    grid-template-columns: fit-content(30%);
+    grid-template-rows: fit-content(20px):
+}
 </style>
 <script src="../../resources/js-test-pre.js"></script>
 </head>
 <div class="grid definite gridWithAutoInsideMinMax contentStart" id="gridWithAutoInsideMinMaxElement">
     <div class="gridItem"></div>
 </div>
+<div class="grid definite gridWithFitContentFunction contentStart" id="gridWithFitContentFunctionElement">
+    <div class="gridItem"></div>
+</div>
 <script src="resources/grid-definitions-parsing-utils.js"></script>
 <script src="resources/grid-columns-rows-get-set.js"></script>
 <script src="../../resources/js-test-post.js"></script>
index 9dc291e..9518737 100644 (file)
@@ -21,6 +21,7 @@ testGridTemplatesValues(document.getElementById("gridWithCalcComplexElement"), "
 testGridTemplatesValues(document.getElementById("gridWithCalcInsideMinMaxElement"), "minmax(10%, 15px)", "minmax(20px, 50%)", "80px", "300px");
 testGridTemplatesValues(document.getElementById("gridWithCalcComplexInsideMinMaxElement"), "minmax(10%, 415px)", "minmax(80px, 50%)", "415px", "300px");
 testGridTemplatesValues(document.getElementById("gridWithAutoInsideMinMaxElement"), "20px", "11px");
+testGridTemplatesValues(document.getElementById("gridWithFitContentFunctionElement"), "7px", "11px");
 
 debug("");
 debug("Test getting wrong values for grid-template-columns and grid-template-rows through CSS (they should resolve to the default: 'none')");
@@ -44,6 +45,7 @@ testGridTemplatesSetJSValues("auto", "auto", "0px", "0px");
 testGridTemplatesSetJSValues("10vw", "25vh", "80px", "150px");
 testGridTemplatesSetJSValues("-webkit-min-content", "-webkit-min-content", "0px", "0px");
 testGridTemplatesSetJSValues("-webkit-max-content", "-webkit-max-content", "0px", "0px");
+testGridTemplatesSetJSValues("fit-content(100px)", "fit-content(25%)", "0px", "0px");
 
 debug("");
 debug("Test getting and setting grid-template-columns and grid-template-rows to minmax() values through JS");
@@ -80,6 +82,14 @@ testGridTemplatesSetBadJSValues("minmax()", "minmax(30px 30% 30em)");
 // Flexible lengths are invalid on the min slot of minmax().
 testGridTemplatesSetBadJSValues("minmax(0fr, 100px)", "minmax(.0fr, 200px)");
 testGridTemplatesSetBadJSValues("minmax(1fr, 100px)", "minmax(2.5fr, 200px)");
+testGridTemplatesSetBadJSValues("fit-content()", "fit-content( )");
+testGridTemplatesSetBadJSValues("fit-content(-10em)", "fit-content(-2px)");
+testGridTemplatesSetBadJSValues("fit-content(10px 2%)", "fit-content(5% 10em)");
+testGridTemplatesSetBadJSValues("fit-content(-webkit-max-content)", "fit-content(-webkit-min-content)");
+testGridTemplatesSetBadJSValues("fit-content(auto)", "fit-content(3fr)");
+testGridTemplatesSetBadJSValues("fit-content(repeat(2, 100px))", "fit-content(repeat(auto-fit), 1%)");
+testGridTemplatesSetBadJSValues("fit-content(fit-content(10px))", "fit-content(fit-content(30%))");
+testGridTemplatesSetBadJSValues("fit-content([a] 100px)", "fit-content(30px [b c])");
 
 testGridTemplatesSetBadJSValues("-2fr", "3ffr");
 testGridTemplatesSetBadJSValues("-2.05fr", "+-3fr");
index 3bbab61..cf7f052 100644 (file)
@@ -1,3 +1,98 @@
+2016-09-07  Sergio Villar Senin  <svillar@igalia.com>
+
+        [css-grid] Implement fit-content track size
+        https://bugs.webkit.org/show_bug.cgi?id=161379
+
+        Reviewed by Manuel Rego Casasnovas.
+
+        This implements the new <fit-content> track size which is defined as follows: "Represents
+        the formula min(max-content, max(auto, argument)), which is calculated similar to auto
+        (i.e. minmax(auto, max-content)), except that the track size is clamped at argument if it is
+        greater than the auto minimum."
+
+        From the parsing POV fit-content was implemented as a new type of function which only takes
+        one argument. That forced us to refactor some code because minmax() was the only allowed
+        function for <track-size>s so far.
+
+        The implementation key is a new attribute in GridTrack called growthLimitCap which is
+        precisely the single attribute of fit-content(). Some parts of the track sizing algorithm
+        were adapted to this change like for example the sorting of tracks by growth potential (we
+        need to consider the caps).
+
+        Tests: fast/css-grid-layout/fit-content-columns.html
+        fast/css-grid-layout/fit-content-rows.html
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::specifiedValueForGridTrackSize): Added support for fit-content sizes.
+        * css/StyleBuilderConverter.h:
+        (WebCore::StyleBuilderConverter::createGridTrackSize): Added support for fit-content sizes.
+        * css/parser/CSSParser.cpp:
+        (WebCore::isGridTrackFixedSized): Added support for fit-content sizes.
+        (WebCore::CSSParser::parseGridTrackSize): Added support for parsing fit-content() functions.
+        * css/parser/CSSPropertyParser.cpp: Added support for parsing fit-content() functions so
+        it'll be available once we switch to the new parser.
+        * rendering/RenderGrid.cpp:
+        (WebCore::GridTrack::baseSize): Just return a LayoutUnit, the return value optimization will
+        keep it fast in any case.
+        (WebCore::GridTrack::growthLimit): Ditto.
+        (WebCore::GridTrack::setGrowthLimit): Added an ASSERT to check that the growth limit is
+        never higher than the cap.
+        (WebCore::GridTrack::infiniteGrowthPotential):
+        (WebCore::GridTrack::plannedSize): Just return a LayoutUnit, the return value optimization will
+        keep it fast in any case.
+        (WebCore::GridTrack::tempSize): Just return a LayoutUnit, the return value optimization will
+        keep it fast in any case.
+        (WebCore::GridTrack::setTempSize): Added as we no longer return a reference in tempSize().
+        (WebCore::GridTrack::growTempSize): New utility function which increases the tempSize.
+        (WebCore::GridTrack::setInfinitelyGrowable):
+        (WebCore::GridTrack::setGrowthLimitCap): Added.
+        (WebCore::GridTrack::growthLimitCap): Ditto.
+        (WebCore::GridTrack::growthLimitIsInfinite): Made private.
+        (WebCore::RenderGrid::GridSizingData::freeSpace): Renamed from freeSpaceForDirection.
+        (WebCore::RenderGrid::GridSizingData::availableSpace): We now cache the available space as
+        it is used to compute relative (percentage) sizes.
+        (WebCore::RenderGrid::GridSizingData::setAvailableSpace): Ditto.
+        (WebCore::RenderGrid::GridSizingData::setFreeSpace): Renamed from setFreeSpaceForDirection.
+        (WebCore::RenderGrid::computeTrackSizesForDirection): Receives the available space instead
+        of the free space.
+        (WebCore::RenderGrid::computeIntrinsicLogicalWidths): Properly initialize free and available
+        spaces.
+        (WebCore::RenderGrid::computeIntrinsicLogicalHeight): Ditto.
+        (WebCore::RenderGrid::computeUsedBreadthOfGridTracks): Use available space to initialize the
+        track sizes. Also use sizingOperation to decide whether or not sizes are indefinite. Last
+        but not least, added support for fit-content tracks.
+        (WebCore::RenderGrid::computeUsedBreadthOfMinLength): Pass a GridTrackSize instead of a GridLength.
+        (WebCore::RenderGrid::computeUsedBreadthOfMaxLength): Ditto.
+        (WebCore::RenderGrid::gridTrackSize): Added support for fit-content.
+        (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctions): Ditto.
+        (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems): Ditto.
+        (WebCore::trackSizeForTrackSizeComputationPhase):
+        (WebCore::sortByGridTrackGrowthPotential): Reworked the function so it properly sorts tracks
+        with growth limit caps to support fit-content().
+        (WebCore::clampGrowthShareIfNeeded): Clamps the given growthShare passed as argument to the
+        track growth limit cap.
+        (WebCore::RenderGrid::distributeSpaceToTracks): Use the new setTempSize() method. Also sort
+        the selected tracks to grow over growth limits in order to respect the track caps eventually
+        set by fit-content (otherwise those tracks could indefinitely grow over the specified value).
+        (WebCore::RenderGrid::tracksAreWiderThanMinTrackBreadth): Use the new defined functions.
+        (WebCore::RenderGrid::applyStretchAlignmentToTracksIfNeeded): Use freeSpace().
+        (WebCore::RenderGrid::populateGridPositionsForDirection): Ditto.
+        (WebCore::GridTrack::infinitelyGrowable): Deleted.
+        (WebCore::RenderGrid::GridSizingData::freeSpaceForDirection): Deleted.
+        (WebCore::RenderGrid::GridSizingData::setFreeSpaceForDirection): Deleted.
+        (WebCore::RenderGrid::trackSizeForTrackSizeComputationPhase): Deleted.
+        * rendering/RenderGrid.h: Changed the signature of some methods. Moved
+        TrackSizeComputationPhase out of the RenderGrid class.
+        * rendering/style/GridTrackSize.h:
+        (WebCore::GridTrackSize::GridTrackSize): Added some extra documentation. Added a new
+        attribute to the constructor to support fit-content GridTrackSizes.
+        (WebCore::GridTrackSize::fitContentTrackBreadth): New method which returns the growth limit
+        cap set by fit-content().
+        (WebCore::GridTrackSize::minTrackBreadth):
+        (WebCore::GridTrackSize::isFitContent): Added.
+        (WebCore::GridTrackSize::length): Deleted.
+        (WebCore::GridTrackSize::isPercentage): Deleted.
+
 2016-09-15  Alejandro G. Castro  <alex@igalia.com>
 
         Fix build warnings in the mediastream code
index ba08186..c7c8725 100644 (file)
@@ -1013,7 +1013,12 @@ static Ref<CSSValue> specifiedValueForGridTrackSize(const GridTrackSize& trackSi
 {
     switch (trackSize.type()) {
     case LengthTrackSizing:
-        return specifiedValueForGridTrackBreadth(trackSize.length(), style);
+        return specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style);
+    case FitContentTrackSizing: {
+        auto fitContentTrackSize = CSSValueList::createCommaSeparated();
+        fitContentTrackSize->append(zoomAdjustedPixelValueForLength(trackSize.fitContentTrackBreadth().length(), style));
+        return CSSFunctionValue::create("fit-content(", WTFMove(fitContentTrackSize));
+    }
     default:
         ASSERT(trackSize.type() == MinMaxTrackSizing);
         auto minMaxTrackBreadths = CSSValueList::createCommaSeparated();
index a5a6096..163a297 100644 (file)
@@ -843,9 +843,13 @@ inline GridTrackSize StyleBuilderConverter::createGridTrackSize(CSSValue& value,
     if (is<CSSPrimitiveValue>(value))
         return GridTrackSize(createGridTrackBreadth(downcast<CSSPrimitiveValue>(value), styleResolver));
 
+    ASSERT(is<CSSFunctionValue>(value));
     CSSValueList& arguments = *downcast<CSSFunctionValue>(value).arguments();
-    ASSERT_WITH_SECURITY_IMPLICATION(arguments.length() == 2);
 
+    if (arguments.length() == 1)
+        return GridTrackSize(createGridTrackBreadth(downcast<CSSPrimitiveValue>(*arguments.itemWithoutBoundsCheck(0)), styleResolver), FitContentTrackSizing);
+
+    ASSERT_WITH_SECURITY_IMPLICATION(arguments.length() == 2);
     GridLength minTrackBreadth(createGridTrackBreadth(downcast<CSSPrimitiveValue>(*arguments.itemWithoutBoundsCheck(0)), styleResolver));
     GridLength maxTrackBreadth(createGridTrackBreadth(downcast<CSSPrimitiveValue>(*arguments.itemWithoutBoundsCheck(1)), styleResolver));
     return GridTrackSize(minTrackBreadth, maxTrackBreadth);
index 6f91576..0611c03 100644 (file)
@@ -5645,11 +5645,14 @@ static bool isGridTrackFixedSized(const CSSValue& value)
         return isGridTrackFixedSized(downcast<CSSPrimitiveValue>(value));
 
     ASSERT(value.isFunctionValue());
-    ASSERT(downcast<CSSFunctionValue>(value).arguments());
-    ASSERT(downcast<CSSFunctionValue>(value).arguments()->length() == 2);
+    auto& arguments = *downcast<CSSFunctionValue>(value).arguments();
+    // fit-content
+    if (arguments.length() == 1)
+        return false;
 
-    auto& min = downcast<CSSPrimitiveValue>(*downcast<CSSFunctionValue>(value).arguments()->item(0));
-    auto& max = downcast<CSSPrimitiveValue>(*downcast<CSSFunctionValue>(value).arguments()->item(1));
+    ASSERT(arguments.length() == 2);
+    auto& min = downcast<CSSPrimitiveValue>(*arguments.itemWithoutBoundsCheck(0));
+    auto& max = downcast<CSSPrimitiveValue>(*arguments.itemWithoutBoundsCheck(1));
     return isGridTrackFixedSized(min) || isGridTrackFixedSized(max);
 }
 
@@ -5795,6 +5798,21 @@ RefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList)
     if (currentValue.id == CSSValueAuto)
         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
 
+    if (currentValue.unit == CSSParserValue::Function && equalLettersIgnoringASCIICase(currentValue.function->name, "fit-content(")) {
+        CSSParserValueList* arguments = currentValue.function->args.get();
+        if (!arguments || arguments->size() != 1)
+            return nullptr;
+        ValueWithCalculation valueWithCalculation(*arguments->valueAt(0));
+        if (!validateUnit(valueWithCalculation, FNonNeg | FLength | FPercent))
+            return nullptr;
+        RefPtr<CSSPrimitiveValue> trackBreadth = createPrimitiveNumericValue(valueWithCalculation);
+        if (!trackBreadth)
+            return nullptr;
+        auto parsedArguments = CSSValueList::createCommaSeparated();
+        parsedArguments->append(trackBreadth.releaseNonNull());
+        return CSSFunctionValue::create("fit-content(", WTFMove(parsedArguments));
+    }
+
     if (currentValue.unit == CSSParserValue::Function && equalLettersIgnoringASCIICase(currentValue.function->name, "minmax(")) {
         // The spec defines the following grammar: minmax( <track-breadth> , <track-breadth> )
         CSSParserValueList* arguments = currentValue.function->args.get();
index e60f964..206b869 100644 (file)
@@ -2794,6 +2794,19 @@ static CSSValue* consumeJustifyItems(CSSParserTokenRange& range)
     return consumeSelfPositionOverflowPosition(range);
 }
 
+static CSSValue* consumeFitContent(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+    CSSParserTokenRange rangeCopy = range;
+    CSSParserTokenRange args = consumeFunction(rangeCopy);
+    CSSPrimitiveValue* length = consumeLengthOrPercent(args, cssParserMode, ValueRangeNonNegative, UnitlessQuirk::Allow);
+    if (!length || !args.atEnd())
+        return nullptr;
+    range = rangeCopy;
+    CSSFunctionValue* result = CSSFunctionValue::create(CSSValueFitContent);
+    result->append(*length);
+    return result;
+}
+
 static CSSCustomIdentValue* consumeCustomIdentForGridLine(CSSParserTokenRange& range)
 {
     if (range.peek().id() == CSSValueAuto || range.peek().id() == CSSValueSpan)
@@ -2864,8 +2877,13 @@ static bool isGridTrackFixedSized(const CSSValue& value)
     if (value.isPrimitiveValue())
         return isGridTrackFixedSized(toCSSPrimitiveValue(value));
 
-    const CSSPrimitiveValue& minPrimitiveValue = toCSSPrimitiveValue(toCSSFunctionValue(value).item(0));
-    const CSSPrimitiveValue& maxPrimitiveValue = toCSSPrimitiveValue(toCSSFunctionValue(value).item(1));
+    ASSERT(value.isFunctionValue());
+    auto& function = toCSSFunctionValue(value);
+    if (function.functionType() == CSSValueFitContent)
+        return false;
+
+    const CSSPrimitiveValue& minPrimitiveValue = toCSSPrimitiveValue(function.item(0));
+    const CSSPrimitiveValue& maxPrimitiveValue = toCSSPrimitiveValue(function.item(1));
     return isGridTrackFixedSized(minPrimitiveValue) || isGridTrackFixedSized(maxPrimitiveValue);
 }
 
@@ -2997,6 +3015,10 @@ static CSSValue* consumeGridTrackSize(CSSParserTokenRange& range, CSSParserMode
         result->append(*maxTrackBreadth);
         return result;
     }
+
+    if (token.functionId() == CSSValueFitContent)
+        return consumeFitContent(range, cssParserMode);
+
     return consumeGridBreadth(range, cssParserMode);
 }
 
index 2a0da43..75ae70f 100644 (file)
@@ -41,6 +41,11 @@ namespace WebCore {
 static const int infinity = -1;
 static constexpr ItemPosition selfAlignmentNormalBehavior = ItemPositionStretch;
 
+enum TrackSizeRestriction {
+    AllowInfinity,
+    ForbidInfinity,
+};
+
 class GridTrack {
 public:
     GridTrack() {}
@@ -54,6 +59,7 @@ public:
     const LayoutUnit& growthLimit() const
     {
         ASSERT(isGrowthLimitBiggerThanBaseSize());
+        ASSERT(!m_growthLimitCap || m_growthLimitCap.value() >= m_growthLimit || m_baseSize >= m_growthLimitCap.value());
         return m_growthLimit;
     }
 
@@ -65,19 +71,11 @@ public:
 
     void setGrowthLimit(LayoutUnit growthLimit)
     {
-        m_growthLimit = growthLimit;
+        m_growthLimit = growthLimit == infinity ? growthLimit : std::min(growthLimit, m_growthLimitCap.valueOr(growthLimit));
         ensureGrowthLimitIsBiggerThanBaseSize();
     }
 
-    bool growthLimitIsInfinite() const
-    {
-        return m_growthLimit == infinity;
-    }
-
-    bool infiniteGrowthPotential() const
-    {
-        return growthLimitIsInfinite() || m_infinitelyGrowable;
-    }
+    bool infiniteGrowthPotential() const { return growthLimitIsInfinite() || m_infinitelyGrowable; }
 
     const LayoutUnit& growthLimitIfNotInfinite() const
     {
@@ -92,16 +90,35 @@ public:
         m_plannedSize = plannedSize;
     }
 
-    LayoutUnit& tempSize() { return m_tempSize; }
+    const LayoutUnit& tempSize() const { return m_tempSize; }
+
+    void setTempSize(const LayoutUnit& tempSize)
+    {
+        ASSERT(tempSize >= 0);
+        ASSERT(growthLimitIsInfinite() || growthLimit() >= tempSize);
+        m_tempSize = tempSize;
+    }
+
+    void growTempSize(const LayoutUnit& tempSize)
+    {
+        ASSERT(tempSize >= 0);
+        m_tempSize += tempSize;
+        ASSERT(growthLimitIsInfinite() || growthLimit() >= m_tempSize);
+    }
 
     bool infinitelyGrowable() const { return m_infinitelyGrowable; }
+    void setInfinitelyGrowable(bool infinitelyGrowable) { m_infinitelyGrowable = infinitelyGrowable; }
 
-    void setInfinitelyGrowable(bool infinitelyGrowable)
+    void setGrowthLimitCap(Optional<LayoutUnit> growthLimitCap)
     {
-        m_infinitelyGrowable = infinitelyGrowable;
+        ASSERT(!growthLimitCap || growthLimitCap.value() >= 0);
+        m_growthLimitCap = growthLimitCap;
     }
 
+    Optional<LayoutUnit> growthLimitCap() const { return m_growthLimitCap; }
+
 private:
+    bool growthLimitIsInfinite() const { return m_growthLimit == infinity; }
     bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite() || m_growthLimit >= m_baseSize; }
 
     void ensureGrowthLimitIsBiggerThanBaseSize()
@@ -114,6 +131,7 @@ private:
     LayoutUnit m_growthLimit { 0 };
     LayoutUnit m_plannedSize { 0 };
     LayoutUnit m_tempSize { 0 };
+    Optional<LayoutUnit> m_growthLimitCap;
     bool m_infinitelyGrowable { false };
 };
 
@@ -235,8 +253,11 @@ public:
     Vector<GridTrack*> growBeyondGrowthLimitsTracks;
     Vector<GridItemWithSpan> itemsSortedByIncreasingSpan;
 
-    Optional<LayoutUnit> freeSpaceForDirection(GridTrackSizingDirection direction) { return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; }
-    void setFreeSpaceForDirection(GridTrackSizingDirection, Optional<LayoutUnit> freeSpace);
+    Optional<LayoutUnit> freeSpace(GridTrackSizingDirection direction) { return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; }
+    void setFreeSpace(GridTrackSizingDirection, Optional<LayoutUnit> freeSpace);
+
+    Optional<LayoutUnit> availableSpace() const { return m_availableSpace; }
+    void setAvailableSpace(Optional<LayoutUnit> availableSpace) { m_availableSpace = availableSpace; }
 
     SizingOperation sizingOperation { TrackSizing };
 
@@ -278,9 +299,12 @@ public:
 private:
     Optional<LayoutUnit> freeSpaceForColumns;
     Optional<LayoutUnit> freeSpaceForRows;
+    // No need to store one per direction as it will be only used for computations during each axis
+    // track sizing. It's cached here because we need it to compute relative sizes.
+    Optional<LayoutUnit> m_availableSpace;
 };
 
-void RenderGrid::GridSizingData::setFreeSpaceForDirection(GridTrackSizingDirection direction, Optional<LayoutUnit> freeSpace)
+void RenderGrid::GridSizingData::setFreeSpace(GridTrackSizingDirection direction, Optional<LayoutUnit> freeSpace)
 {
     if (direction == ForColumns)
         freeSpaceForColumns = freeSpace;
@@ -390,11 +414,12 @@ LayoutUnit RenderGrid::computeTrackBasedLogicalHeight(const GridSizingData& sizi
     return logicalHeight;
 }
 
-void RenderGrid::computeTrackSizesForDirection(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit freeSpace)
+void RenderGrid::computeTrackSizesForDirection(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit availableSpace)
 {
     ASSERT(sizingData.isValidTransition(direction));
     LayoutUnit totalGuttersSize = guttersSize(direction, 0, direction == ForRows ? gridRowCount() : gridColumnCount());
-    sizingData.setFreeSpaceForDirection(direction, freeSpace - totalGuttersSize);
+    sizingData.setAvailableSpace(availableSpace);
+    sizingData.setFreeSpace(direction, availableSpace - totalGuttersSize);
     sizingData.sizingOperation = TrackSizing;
 
     LayoutUnit baseSizes, growthLimits;
@@ -590,7 +615,8 @@ void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Layo
         const_cast<RenderGrid*>(this)->placeItemsOnGrid(IntrinsicSizeComputation);
 
     GridSizingData sizingData(gridColumnCount(), gridRowCount());
-    sizingData.setFreeSpaceForDirection(ForColumns, Nullopt);
+    sizingData.setAvailableSpace(Nullopt);
+    sizingData.setFreeSpace(ForColumns, Nullopt);
     sizingData.sizingOperation = IntrinsicSizeComputation;
     computeUsedBreadthOfGridTracks(ForColumns, sizingData, minLogicalWidth, maxLogicalWidth);
 
@@ -609,7 +635,8 @@ void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Layo
 void RenderGrid::computeIntrinsicLogicalHeight(GridSizingData& sizingData)
 {
     ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, sizingData));
-    sizingData.setFreeSpaceForDirection(ForRows, Nullopt);
+    sizingData.setAvailableSpace(Nullopt);
+    sizingData.setFreeSpace(ForRows, Nullopt);
     sizingData.sizingOperation = IntrinsicSizeComputation;
     LayoutUnit minHeight, maxHeight;
     computeUsedBreadthOfGridTracks(ForRows, sizingData, minHeight, maxHeight);
@@ -659,28 +686,30 @@ static inline double normalizedFlexFraction(const GridTrack& track, double flexF
 
 void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& baseSizesWithoutMaximization, LayoutUnit& growthLimitsWithoutMaximization) const
 {
-    const Optional<LayoutUnit> initialFreeSpace = sizingData.freeSpaceForDirection(direction);
+    const Optional<LayoutUnit> initialFreeSpace = sizingData.freeSpace(direction);
     Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
     Vector<unsigned> flexibleSizedTracksIndex;
     sizingData.contentSizedTracksIndex.shrink(0);
 
-    LayoutUnit maxSize = initialFreeSpace.valueOr(0);
     // Grid gutters were removed from freeSpace by the caller (if freeSpace is definite),
     // but we must use them to compute relative (i.e. percentages) sizes.
-    if (initialFreeSpace)
-        maxSize += guttersSize(direction, 0, direction == ForColumns ? gridColumnCount() : gridRowCount());
+    LayoutUnit maxSize = std::max(LayoutUnit(), sizingData.availableSpace().valueOr(LayoutUnit()));
+    const bool hasDefiniteFreeSpace = sizingData.sizingOperation == TrackSizing;
 
     // 1. Initialize per Grid track variables.
     for (unsigned i = 0; i < tracks.size(); ++i) {
         GridTrack& track = tracks[i];
         const GridTrackSize& trackSize = gridTrackSize(direction, i, sizingData.sizingOperation);
-        const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
-        const GridLength& maxTrackBreadth = trackSize.maxTrackBreadth();
 
-        track.setBaseSize(computeUsedBreadthOfMinLength(minTrackBreadth, maxSize));
-        track.setGrowthLimit(computeUsedBreadthOfMaxLength(maxTrackBreadth, track.baseSize(), maxSize));
+        track.setBaseSize(computeUsedBreadthOfMinLength(trackSize, maxSize));
+        track.setGrowthLimit(computeUsedBreadthOfMaxLength(trackSize, track.baseSize(), maxSize));
         track.setInfinitelyGrowable(false);
 
+        if (trackSize.isFitContent()) {
+            GridLength gridLength = trackSize.fitContentTrackBreadth();
+            if (!gridLength.isPercentage() || hasDefiniteFreeSpace)
+                track.setGrowthLimitCap(valueForLength(gridLength.length(), maxSize));
+        }
         if (trackSize.isContentSized())
             sizingData.contentSizedTracksIndex.append(i);
         if (trackSize.maxTrackBreadth().isFlex())
@@ -694,16 +723,17 @@ void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi
     baseSizesWithoutMaximization = growthLimitsWithoutMaximization = 0;
 
     for (auto& track : tracks) {
-        ASSERT(!track.growthLimitIsInfinite());
+        ASSERT(!track.infiniteGrowthPotential());
         baseSizesWithoutMaximization += track.baseSize();
         growthLimitsWithoutMaximization += track.growthLimit();
+        // The growth limit caps must be cleared now in order to properly sort tracks by growth
+        // potential on an eventual "Maximize Tracks".
+        track.setGrowthLimitCap(Nullopt);
     }
     LayoutUnit freeSpace = initialFreeSpace ? initialFreeSpace.value() - baseSizesWithoutMaximization : LayoutUnit(0);
 
-    const bool hasDefiniteFreeSpace = !!initialFreeSpace;
-
     if (hasDefiniteFreeSpace && freeSpace <= 0) {
-        sizingData.setFreeSpaceForDirection(direction, freeSpace);
+        sizingData.setFreeSpace(direction, freeSpace);
         return;
     }
 
@@ -726,7 +756,7 @@ void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi
     }
 
     if (flexibleSizedTracksIndex.isEmpty()) {
-        sizingData.setFreeSpaceForDirection(direction, freeSpace);
+        sizingData.setFreeSpace(direction, freeSpace);
         return;
     }
 
@@ -765,11 +795,12 @@ void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi
             growthLimitsWithoutMaximization += increment;
         }
     }
-    sizingData.setFreeSpaceForDirection(direction, freeSpace);
+    sizingData.setFreeSpace(direction, freeSpace);
 }
 
-LayoutUnit RenderGrid::computeUsedBreadthOfMinLength(const GridLength& gridLength, LayoutUnit maxSize) const
+LayoutUnit RenderGrid::computeUsedBreadthOfMinLength(const GridTrackSize& trackSize, LayoutUnit maxSize) const
 {
+    const GridLength& gridLength = trackSize.minTrackBreadth();
     if (gridLength.isFlex())
         return 0;
 
@@ -781,8 +812,9 @@ LayoutUnit RenderGrid::computeUsedBreadthOfMinLength(const GridLength& gridLengt
     return 0;
 }
 
-LayoutUnit RenderGrid::computeUsedBreadthOfMaxLength(const GridLength& gridLength, LayoutUnit usedBreadth, LayoutUnit maxSize) const
+LayoutUnit RenderGrid::computeUsedBreadthOfMaxLength(const GridTrackSize& trackSize, LayoutUnit usedBreadth, LayoutUnit maxSize) const
 {
+    const GridLength& gridLength = trackSize.maxTrackBreadth();
     if (gridLength.isFlex())
         return usedBreadth;
 
@@ -912,9 +944,11 @@ GridTrackSize RenderGrid::gridTrackSize(GridTrackSizingDirection direction, unsi
 {
     // Collapse empty auto repeat tracks if auto-fit.
     if (hasAutoRepeatEmptyTracks(direction) && isEmptyAutoRepeatTrack(direction, translatedIndex))
-        return { Length(Fixed), Length(Fixed) };
+        return { Length(Fixed), LengthTrackSizing };
 
     auto& trackSize = rawGridTrackSize(direction, translatedIndex);
+    if (trackSize.isFitContent())
+        return trackSize;
 
     GridLength minTrackBreadth = trackSize.minTrackBreadth();
     GridLength maxTrackBreadth = trackSize.maxTrackBreadth();
@@ -1127,7 +1161,7 @@ void RenderGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirectio
 
     for (auto trackIndex : sizingData.contentSizedTracksIndex) {
         GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex] : sizingData.rowTracks[trackIndex];
-        if (track.growthLimitIsInfinite())
+        if (track.growthLimit() == infinity)
             track.setGrowthLimit(track.baseSize());
     }
 }
@@ -1144,13 +1178,17 @@ void RenderGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems(Grid
     else if (trackSize.hasAutoMinTrackBreadth())
         track.setBaseSize(std::max(track.baseSize(), minSizeForChild(gridItem, direction, sizingData)));
 
-    if (trackSize.hasMinContentMaxTrackBreadth())
+    if (trackSize.hasMinContentMaxTrackBreadth()) {
         track.setGrowthLimit(std::max(track.growthLimit(), minContentForChild(gridItem, direction, sizingData)));
-    else if (trackSize.hasMaxContentOrAutoMaxTrackBreadth())
-        track.setGrowthLimit(std::max(track.growthLimit(), maxContentForChild(gridItem, direction, sizingData)));
+    } else if (trackSize.hasMaxContentOrAutoMaxTrackBreadth()) {
+        LayoutUnit growthLimit = maxContentForChild(gridItem, direction, sizingData);
+        if (trackSize.isFitContent())
+            growthLimit = std::min(growthLimit, valueForLength(trackSize.fitContentTrackBreadth().length(), sizingData.availableSpace().valueOr(0)));
+        track.setGrowthLimit(std::max(track.growthLimit(), growthLimit));
+    }
 }
 
-const LayoutUnit& RenderGrid::trackSizeForTrackSizeComputationPhase(TrackSizeComputationPhase phase, GridTrack& track, TrackSizeRestriction restriction)
+static LayoutUnit trackSizeForTrackSizeComputationPhase(TrackSizeComputationPhase phase, GridTrack& track, TrackSizeRestriction restriction)
 {
     switch (phase) {
     case ResolveIntrinsicMinimums:
@@ -1272,7 +1310,7 @@ LayoutUnit RenderGrid::currentItemSizeForTrackSizeComputationPhase(TrackSizeComp
     return 0;
 }
 
-template <RenderGrid::TrackSizeComputationPhase phase>
+template <TrackSizeComputationPhase phase>
 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, const GridItemsSpanGroupRange& gridItemsWithSpan) const
 {
     Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
@@ -1324,22 +1362,39 @@ static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTr
 {
     // This check ensures that we respect the irreflexivity property of the strict weak ordering required by std::sort
     // (forall x: NOT x < x).
-    if (track1->infiniteGrowthPotential() && track2->infiniteGrowthPotential())
+    bool track1HasInfiniteGrowthPotentialWithoutCap = track1->infiniteGrowthPotential() && !track1->growthLimitCap();
+    bool track2HasInfiniteGrowthPotentialWithoutCap = track2->infiniteGrowthPotential() && !track2->growthLimitCap();
+
+    if (track1HasInfiniteGrowthPotentialWithoutCap && track2HasInfiniteGrowthPotentialWithoutCap)
         return false;
 
-    if (track1->infiniteGrowthPotential() || track2->infiniteGrowthPotential())
-        return track2->infiniteGrowthPotential();
+    if (track1HasInfiniteGrowthPotentialWithoutCap || track2HasInfiniteGrowthPotentialWithoutCap)
+        return track2HasInfiniteGrowthPotentialWithoutCap;
 
-    return (track1->growthLimit() - track1->baseSize()) < (track2->growthLimit() - track2->baseSize());
+    LayoutUnit track1Limit = track1->growthLimitCap().valueOr(track1->growthLimit());
+    LayoutUnit track2Limit = track2->growthLimitCap().valueOr(track2->growthLimit());
+    return (track1Limit - track1->baseSize()) < (track2Limit - track2->baseSize());
 }
 
-template <RenderGrid::TrackSizeComputationPhase phase>
-void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& freeSpace) const
+static void clampGrowthShareIfNeeded(TrackSizeComputationPhase phase, const GridTrack& track, LayoutUnit& growthShare)
+{
+    if (phase != ResolveMaxContentMaximums || !track.growthLimitCap())
+        return;
+
+    LayoutUnit distanceToCap = track.growthLimitCap().value() - track.tempSize();
+    if (distanceToCap <= 0)
+        return;
+
+    growthShare = std::min(growthShare, distanceToCap);
+}
+
+template <TrackSizeComputationPhase phase>
+void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& freeSpace) const
 {
     ASSERT(freeSpace >= 0);
 
     for (auto* track : tracks)
-        track->tempSize() = trackSizeForTrackSizeComputationPhase(phase, *track, ForbidInfinity);
+        track->setTempSize(trackSizeForTrackSizeComputationPhase(phase, *track, ForbidInfinity));
 
     if (freeSpace > 0) {
         std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
@@ -1354,19 +1409,26 @@ void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vecto
             if (trackGrowthPotential > 0 || infiniteGrowthPotential) {
                 LayoutUnit availableLogicalSpaceShare = freeSpace / (tracksSize - i);
                 LayoutUnit growthShare = infiniteGrowthPotential ? availableLogicalSpaceShare : std::min(availableLogicalSpaceShare, trackGrowthPotential);
+                clampGrowthShareIfNeeded(phase, track, growthShare);
                 ASSERT_WITH_MESSAGE(growthShare >= 0, "We should never shrink any grid track or else we can't guarantee we abide by our min-sizing function. We can still have 0 as growthShare if the amount of tracks greatly exceeds the freeSpace.");
-                track.tempSize() += growthShare;
+                track.growTempSize(growthShare);
                 freeSpace -= growthShare;
             }
         }
     }
 
     if (freeSpace > 0 && growBeyondGrowthLimitsTracks) {
+        // We need to sort them because there might be tracks with growth limit caps (like the ones
+        // with fit-content()) which cannot indefinitely grow over the limits.
+        if (phase == ResolveMaxContentMaximums)
+            std::sort(growBeyondGrowthLimitsTracks->begin(), growBeyondGrowthLimitsTracks->end(), sortByGridTrackGrowthPotential);
+
         unsigned tracksGrowingBeyondGrowthLimitsSize = growBeyondGrowthLimitsTracks->size();
         for (unsigned i = 0; i < tracksGrowingBeyondGrowthLimitsSize; ++i) {
             GridTrack* track = growBeyondGrowthLimitsTracks->at(i);
             LayoutUnit growthShare = freeSpace / (tracksGrowingBeyondGrowthLimitsSize - i);
-            track->tempSize() += growthShare;
+            clampGrowthShareIfNeeded(phase, *track, growthShare);
+            track->growTempSize(growthShare);
             freeSpace -= growthShare;
         }
     }
@@ -1379,11 +1441,10 @@ void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vecto
 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection direction, GridSizingData& sizingData)
 {
     const Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
-    const LayoutUnit maxSize = sizingData.freeSpaceForDirection(direction).valueOr(0);
+    const LayoutUnit maxSize = sizingData.freeSpace(direction).valueOr(0);
     for (unsigned i = 0; i < tracks.size(); ++i) {
         const GridTrackSize& trackSize = gridTrackSize(direction, i, sizingData.sizingOperation);
-        const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
-        if (computeUsedBreadthOfMinLength(minTrackBreadth, maxSize) > tracks[i].baseSize())
+        if (computeUsedBreadthOfMinLength(trackSize, maxSize) > tracks[i].baseSize())
             return false;
     }
     return true;
@@ -1798,7 +1859,7 @@ static const StyleContentAlignmentData& contentAlignmentNormalBehaviorGrid()
 
 void RenderGrid::applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection direction, GridSizingData& sizingData)
 {
-    Optional<LayoutUnit> freeSpace = sizingData.freeSpaceForDirection(direction);
+    Optional<LayoutUnit> freeSpace = sizingData.freeSpace(direction);
     if (!freeSpace
         || freeSpace.value() <= 0
         || (direction == ForColumns && style().resolvedJustifyContentDistribution(contentAlignmentNormalBehaviorGrid()) != ContentDistributionStretch)
@@ -1823,7 +1884,7 @@ void RenderGrid::applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection
         auto& track = tracks[trackIndex];
         track.setBaseSize(track.baseSize() + sizeToIncrease);
     }
-    sizingData.setFreeSpaceForDirection(direction, Optional<LayoutUnit>(0));
+    sizingData.setFreeSpace(direction, Optional<LayoutUnit>(0));
 }
 
 void RenderGrid::layoutGridItems(GridSizingData& sizingData)
@@ -2071,7 +2132,7 @@ void RenderGrid::populateGridPositionsForDirection(GridSizingData& sizingData, G
     unsigned numberOfLines = numberOfTracks + 1;
     unsigned lastLine = numberOfLines - 1;
 
-    ContentAlignmentData offset = computeContentPositionAndDistributionOffset(direction, sizingData.freeSpaceForDirection(direction).value(), numberOfTracks);
+    ContentAlignmentData offset = computeContentPositionAndDistributionOffset(direction, sizingData.freeSpace(direction).value(), numberOfTracks);
     auto& positions = isRowAxis ? m_columnPositions : m_rowPositions;
     positions.resize(numberOfLines);
     auto borderAndPadding = isRowAxis ? borderAndPaddingLogicalLeft() : borderAndPaddingBefore();
index 3fc3642..3807160 100644 (file)
@@ -44,6 +44,15 @@ struct ContentAlignmentData;
 
 enum GridAxisPosition {GridAxisStart, GridAxisEnd, GridAxisCenter};
 
+enum TrackSizeComputationPhase {
+    ResolveIntrinsicMinimums,
+    ResolveContentBasedMinimums,
+    ResolveMaxContentMinimums,
+    ResolveIntrinsicMaximums,
+    ResolveMaxContentMaximums,
+    MaximizeTracks,
+};
+
 class RenderGrid final : public RenderBlock {
 public:
     RenderGrid(Element&, RenderStyle&&);
@@ -75,8 +84,8 @@ private:
     class GridSizingData;
     enum SizingOperation { TrackSizing, IntrinsicSizeComputation };
     void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&, LayoutUnit& baseSizesWithoutMaximization, LayoutUnit& growthLimitsWithoutMaximization) const;
-    LayoutUnit computeUsedBreadthOfMinLength(const GridLength&, LayoutUnit maxSize) const;
-    LayoutUnit computeUsedBreadthOfMaxLength(const GridLength&, LayoutUnit usedBreadth, LayoutUnit maxSize) const;
+    LayoutUnit computeUsedBreadthOfMinLength(const GridTrackSize&, LayoutUnit maxSize) const;
+    LayoutUnit computeUsedBreadthOfMaxLength(const GridTrackSize&, LayoutUnit usedBreadth, LayoutUnit maxSize) const;
     void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&) const;
 
     void ensureGridSize(unsigned maximumRowSize, unsigned maximumColumnSize);
@@ -114,19 +123,6 @@ private:
     void populateGridPositionsForDirection(GridSizingData&, GridTrackSizingDirection);
     void clearGrid();
 
-    enum TrackSizeRestriction {
-        AllowInfinity,
-        ForbidInfinity,
-    };
-    enum TrackSizeComputationPhase {
-        ResolveIntrinsicMinimums,
-        ResolveContentBasedMinimums,
-        ResolveMaxContentMinimums,
-        ResolveIntrinsicMaximums,
-        ResolveMaxContentMaximums,
-        MaximizeTracks,
-    };
-    static const LayoutUnit& trackSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, GridTrack&, TrackSizeRestriction);
     static bool shouldProcessTrackForTrackSizeComputationPhase(TrackSizeComputationPhase, const GridTrackSize&);
     static bool trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(TrackSizeComputationPhase, const GridTrackSize&);
     static void markAsInfinitelyGrowableForTrackSizeComputationPhase(TrackSizeComputationPhase, GridTrack&);
@@ -136,7 +132,7 @@ private:
     typedef struct GridItemsSpanGroupRange GridItemsSpanGroupRange;
     void resolveContentBasedTrackSizingFunctionsForNonSpanningItems(GridTrackSizingDirection, const GridSpan&, RenderBox& gridItem, GridTrack&, GridSizingData&) const;
     template <TrackSizeComputationPhase> void resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection, GridSizingData&, const GridItemsSpanGroupRange&) const;
-    template <TrackSizeComputationPhase> void distributeSpaceToTracks(Vector<GridTrack*>&, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& availableLogicalSpace) const;
+    template <TrackSizeComputationPhase> void distributeSpaceToTracks(Vector<GridTrack*>&, Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& availableLogicalSpace) const;
 
     typedef HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> TrackIndexSet;
     double computeFlexFactorUnitSize(const Vector<GridTrack>&, GridTrackSizingDirection, SizingOperation, double flexFactorSum, LayoutUnit leftOverSpace, const Vector<unsigned, 8>& flexibleTracksIndexes, std::unique_ptr<TrackIndexSet> tracksToTreatAsInflexible = nullptr) const;
index 9134737..898633a 100644 (file)
@@ -40,16 +40,31 @@ namespace WebCore {
 
 enum GridTrackSizeType {
     LengthTrackSizing,
-    MinMaxTrackSizing
+    MinMaxTrackSizing,
+    FitContentTrackSizing
 };
 
+// This class represents a <track-size> from the spec. Althought there are 3 different types of
+// <track-size> there is always an equivalent minmax() representation that could represent any of
+// them. The only special case is fit-content(argument) which is similar to minmax(auto,
+// max-content) except that the track size is clamped at argument if it is greater than the auto
+// minimum. At the GridTrackSize level we don't need to worry about clamping so we treat that case
+// exactly as auto.
+//
+// We're using a separate attribute to store fit-content argument even though we could directly use
+// m_maxTrackBreadth. The reason why we don't do it is because the maxTrackBreadh() call is a hot
+// spot, so adding a conditional statement there (to distinguish between fit-content and any other
+// case) was causing a severe performance drop.
 class GridTrackSize {
 public:
-    GridTrackSize(const GridLength& length)
-        : m_type(LengthTrackSizing)
-        , m_minTrackBreadth(length)
-        , m_maxTrackBreadth(length)
+    GridTrackSize(const GridLength& length, GridTrackSizeType trackSizeType = LengthTrackSizing)
+        : m_type(trackSizeType)
+        , m_minTrackBreadth(trackSizeType == FitContentTrackSizing ? Length(Auto) : length)
+        , m_maxTrackBreadth(trackSizeType == FitContentTrackSizing ? Length(Auto) : length)
+        , m_fitContentTrackBreadth(trackSizeType == FitContentTrackSizing ? length : GridLength(Length(Fixed)))
     {
+        ASSERT(trackSizeType == LengthTrackSizing || trackSizeType == FitContentTrackSizing);
+        ASSERT(trackSizeType != FitContentTrackSizing || length.isLength());
         cacheMinMaxTrackBreadthTypes();
     }
 
@@ -57,27 +72,24 @@ public:
         : m_type(MinMaxTrackSizing)
         , m_minTrackBreadth(minTrackBreadth)
         , m_maxTrackBreadth(maxTrackBreadth)
+        , m_fitContentTrackBreadth(GridLength(Length(Fixed)))
     {
         cacheMinMaxTrackBreadthTypes();
     }
 
-    const GridLength& length() const
+    const GridLength& fitContentTrackBreadth() const
     {
-        ASSERT(m_type == LengthTrackSizing);
-        ASSERT(m_minTrackBreadth == m_maxTrackBreadth);
-        const GridLength& minTrackBreadth = m_minTrackBreadth;
-        return minTrackBreadth;
+        ASSERT(m_type == FitContentTrackSizing);
+        return m_fitContentTrackBreadth;
     }
 
     const GridLength& minTrackBreadth() const { return m_minTrackBreadth; }
-
     const GridLength& maxTrackBreadth() const { return m_maxTrackBreadth; }
 
     GridTrackSizeType type() const { return m_type; }
 
     bool isContentSized() const { return m_minTrackBreadth.isContentSized() || m_maxTrackBreadth.isContentSized(); }
-
-    bool isPercentage() const { return m_type == LengthTrackSizing && length().isLength() && length().length().isPercentOrCalculated(); }
+    bool isFitContent() const { return m_type == FitContentTrackSizing; }
 
     bool operator==(const GridTrackSize& other) const
     {
@@ -111,12 +123,14 @@ private:
     GridTrackSizeType m_type;
     GridLength m_minTrackBreadth;
     GridLength m_maxTrackBreadth;
-    bool m_minTrackBreadthIsAuto;
-    bool m_minTrackBreadthIsMaxContent;
-    bool m_minTrackBreadthIsMinContent;
-    bool m_maxTrackBreadthIsAuto;
-    bool m_maxTrackBreadthIsMaxContent;
-    bool m_maxTrackBreadthIsMinContent;
+    GridLength m_fitContentTrackBreadth;
+
+    bool m_minTrackBreadthIsAuto : 1;
+    bool m_maxTrackBreadthIsAuto : 1;
+    bool m_minTrackBreadthIsMaxContent : 1;
+    bool m_minTrackBreadthIsMinContent : 1;
+    bool m_maxTrackBreadthIsMaxContent : 1;
+    bool m_maxTrackBreadthIsMinContent : 1;
 };
 
 } // namespace WebCore