[CSS Grid Layout] Add support for max-content
authorjchaffraix@webkit.org <jchaffraix@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Jan 2013 21:36:53 +0000 (21:36 +0000)
committerjchaffraix@webkit.org <jchaffraix@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Jan 2013 21:36:53 +0000 (21:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=107604

Reviewed by Tony Chang.

Source/WebCore:

Tests: fast/css-grid-layout/minmax-max-content-resolution-columns.html
       fast/css-grid-layout/minmax-max-content-resolution-rows.html

This change implements max-content on top of the infrastructure introduced as part
of implementing min-content (bug 106474). No effort was made to share code, which
is what was done for min-content. The sharing will occur in follow-up refactoring(s)
to benefit from the extra testing but also the extra code to make the direction more
obvious.

* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::maxContentForChild):
Added this helper, similar to minContentForChild.

(WebCore::RenderGrid::resolveContentBasedTrackSizingFunctions):
Patched the function to handle max-content per the specification's algorithm.

* rendering/RenderGrid.h:
Added maxContentForChild.

LayoutTests:

* fast/css-grid-layout/minmax-max-content-resolution-columns-expected.txt: Added.
* fast/css-grid-layout/minmax-max-content-resolution-columns.html: Added.
* fast/css-grid-layout/minmax-max-content-resolution-rows-expected.txt: Added.
* fast/css-grid-layout/minmax-max-content-resolution-rows.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-columns-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-columns.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-rows-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-rows.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderGrid.h

index 4cffa8d..05dfd74 100644 (file)
@@ -1,3 +1,15 @@
+2013-01-23  Julien Chaffraix  <jchaffraix@webkit.org>
+
+        [CSS Grid Layout] Add support for max-content
+        https://bugs.webkit.org/show_bug.cgi?id=107604
+
+        Reviewed by Tony Chang.
+
+        * fast/css-grid-layout/minmax-max-content-resolution-columns-expected.txt: Added.
+        * fast/css-grid-layout/minmax-max-content-resolution-columns.html: Added.
+        * fast/css-grid-layout/minmax-max-content-resolution-rows-expected.txt: Added.
+        * fast/css-grid-layout/minmax-max-content-resolution-rows.html: Added.
+
 2013-01-23  Erik Arvidsson  <arv@chromium.org>
 
         [chromium] Layout test rebaselines
diff --git a/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-columns-expected.txt b/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-columns-expected.txt
new file mode 100644 (file)
index 0000000..48204d0
--- /dev/null
@@ -0,0 +1,22 @@
+Test that resolving minmax function with max-content on grid items works properly.
+
+XXX
+PASS
+XXXXX
+PASS
+XXXXXXXXXX
+PASS
+XXXXX
+PASS
+XXXXXXXXXX
+PASS
+XX
+PASS
+XXX
+PASS
+XXXXX
+PASS
+XXXXX
+PASS
+XX
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-columns.html b/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-columns.html
new file mode 100644 (file)
index 0000000..1281c48
--- /dev/null
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<script>
+if (window.testRunner)
+    testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1);
+</script>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.gridMinMaxContent {
+    -webkit-grid-columns: minmax(-webkit-max-content, 50px);
+    -webkit-grid-rows: 60px;
+}
+
+.gridMaxMaxContent {
+    -webkit-grid-columns: minmax(30px, -webkit-max-content);
+    -webkit-grid-rows: 20px;
+}
+
+/* This rule makes sure the container is smaller than any grid items to avoid distributing any extra logical space to them. */
+.constrainedContainer {
+    width: 10px;
+    height: 10px;
+}
+
+.firstRowFirstColumn {
+    font: 10px/1 Ahem;
+    /* Make us fit our grid area. */
+    width: 100%;
+    height: 100%;
+}
+
+.verticalRL {
+    -webkit-writing-mode: vertical-rl;
+}
+</style>
+<script src="../../resources/check-layout.js"></script>
+<body onload="checkLayout('.gridMinMaxContent'); checkLayout('.gridMaxMaxContent')">
+
+<p>Test that resolving minmax function with max-content on grid items works properly.</p>
+
+<div class="constrainedContainer">
+    <div class="grid gridMinMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="30" data-expected-height="60">XXX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMinMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="50" data-expected-height="60">XXXXX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMinMaxContent">
+        <!-- The 'max' logical width ends up being smaller than the 'min' so per the spec we ignore the 'max'. -->
+        <div class="firstRowFirstColumn" data-expected-width="100" data-expected-height="60">XXXXXXXXXX</div>
+    </div>
+</div>
+
+<!-- Allow the extra logical space distribution to occur. -->
+<div style="width: 100px; height: 10px;">
+    <div class="grid gridMinMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="50" data-expected-height="60">XXXXX</div>
+    </div>
+</div>
+
+<div style="width: 200px; height: 10px;">
+    <div class="grid gridMinMaxContent">
+        <!-- The 'max' logical width ends up being smaller than the 'min' so per the spec we ignore the 'max'. -->
+        <div class="firstRowFirstColumn" data-expected-width="100" data-expected-height="60">XXXXXXXXXX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="30" data-expected-height="20">XX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="30" data-expected-height="20">XXX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="30" data-expected-height="20">XXXXX</div>
+    </div>
+</div>
+
+<!-- Allow the extra logical space distribution to occur. -->
+
+<div style="width: 100px; height: 20px">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="50" data-expected-height="20">XXXXX</div>
+    </div>
+</div>
+
+<div style="width: 100px; height: 20px">
+    <div class="grid gridMaxMaxContent">
+        <!-- The 'max' logical width ends up being smaller than the 'min' so per the spec we ignore the 'max'. -->
+        <div class="firstRowFirstColumn" data-expected-width="30" data-expected-height="20">XX</div>
+    </div>
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-rows-expected.txt b/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-rows-expected.txt
new file mode 100644 (file)
index 0000000..6fb8f97
--- /dev/null
@@ -0,0 +1,22 @@
+Test that resolving minmax function with max-content on grid items works properly.
+
+XX XX XX
+PASS
+XX XX XX XX XX
+PASS
+XX XX XX XX XX XX XX XX
+PASS
+XX XX XX
+PASS
+XX XX XX XX XX XX XX XX
+PASS
+XX
+PASS
+XX XX XX
+PASS
+XX XX XX XX XX
+PASS
+XX XX XX
+PASS
+XX XX XX XX XX
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-rows.html b/LayoutTests/fast/css-grid-layout/minmax-max-content-resolution-rows.html
new file mode 100644 (file)
index 0000000..03f6e00
--- /dev/null
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<script>
+if (window.testRunner)
+    testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1);
+</script>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.gridMinMaxContent {
+    -webkit-grid-columns: 20px;
+    -webkit-grid-rows: minmax(-webkit-max-content, 50px);
+}
+
+.gridMaxMaxContent {
+    -webkit-grid-columns: 20px;
+    -webkit-grid-rows: minmax(30px, -webkit-max-content);
+}
+
+/* This rule makes sure the container is smaller than any grid items to avoid distributing any extra logical space to them. */
+.constrainedContainer {
+    width: 10px;
+    height: 10px;
+}
+
+.firstRowFirstColumn {
+    font: 10px/1 Ahem;
+    /* Make us fit our grid area. */
+    width: 100%;
+    height: 100%;
+}
+
+.verticalRL {
+    -webkit-writing-mode: vertical-rl;
+}
+</style>
+<script src="../../resources/check-layout.js"></script>
+<body onload="checkLayout('.gridMinMaxContent'); checkLayout('.gridMaxMaxContent')">
+
+<p>Test that resolving minmax function with max-content on grid items works properly.</p>
+
+<div class="constrainedContainer">
+    <div class="grid gridMinMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="30">XX XX XX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMinMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="50">XX XX XX XX XX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMinMaxContent">
+        <!-- The 'max' logical width ends up being smaller than the 'min' so per the spec we ignore the 'max'. -->
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="80">XX XX XX XX XX XX XX XX</div>
+    </div>
+</div>
+
+<!-- Allow the extra logical space distribution to occur. -->
+<div style="width: 10px; height: 100px;">
+    <div class="grid gridMinMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="50">XX XX XX</div>
+    </div>
+</div>
+
+<div style="width: 10px; height: 100px;">
+    <div class="grid gridMinMaxContent">
+        <!-- The 'max' logical width ends up being smaller than the 'min' so per the spec we ignore the 'max'. -->
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="80">XX XX XX XX XX XX XX XX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="30">XX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="30">XX XX XX</div>
+    </div>
+</div>
+
+<div class="constrainedContainer">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="30">XX XX XX XX XX</div>
+    </div>
+</div>
+
+<!-- Allow the extra logical space distribution to occur. -->
+
+<div style="width: 100px; height: 20px">
+    <div class="grid gridMaxMaxContent">
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="30">XX XX XX</div>
+    </div>
+</div>
+
+<div style="width: 100px; height: 20px">
+    <div class="grid gridMaxMaxContent">
+        <!-- The 'max' logical width ends up being smaller than the 'min' so per the spec we ignore the 'max'. -->
+        <div class="firstRowFirstColumn" data-expected-width="20" data-expected-height="30">XX XX XX XX XX</div>
+    </div>
+</div>
+
+</body>
+</html>
index de52df0..ab61e51 100644 (file)
@@ -1,3 +1,29 @@
+2013-01-23  Julien Chaffraix  <jchaffraix@webkit.org>
+
+        [CSS Grid Layout] Add support for max-content
+        https://bugs.webkit.org/show_bug.cgi?id=107604
+
+        Reviewed by Tony Chang.
+
+        Tests: fast/css-grid-layout/minmax-max-content-resolution-columns.html
+               fast/css-grid-layout/minmax-max-content-resolution-rows.html
+
+        This change implements max-content on top of the infrastructure introduced as part
+        of implementing min-content (bug 106474). No effort was made to share code, which
+        is what was done for min-content. The sharing will occur in follow-up refactoring(s)
+        to benefit from the extra testing but also the extra code to make the direction more
+        obvious.
+
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::maxContentForChild):
+        Added this helper, similar to minContentForChild.
+
+        (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctions):
+        Patched the function to handle max-content per the specification's algorithm.
+
+        * rendering/RenderGrid.h:
+        Added maxContentForChild.
+
 2013-01-23  Mark Lam  <mark.lam@apple.com>
 
         Assert that Supplementable objects is only used in their creator thread.
index 18629b8..ed7670e 100644 (file)
@@ -240,6 +240,27 @@ LayoutUnit RenderGrid::minContentForChild(RenderBox* child, TrackSizingDirection
     return child->logicalHeight();
 }
 
+LayoutUnit RenderGrid::maxContentForChild(RenderBox* child, TrackSizingDirection direction, Vector<GridTrack>& columnTracks)
+{
+    bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
+    // FIXME: Properly support orthogonal writing mode.
+    if (hasOrthogonalWritingMode)
+        return LayoutUnit();
+
+    if (direction == ForColumns) {
+        // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
+        // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
+        return child->maxPreferredLogicalWidth();
+    }
+
+    if (child->needsLayout()) {
+        size_t columnTrack = resolveGridPosition(ForColumns, child);
+        child->setOverrideContainingBlockContentLogicalWidth(columnTracks[columnTrack].m_usedBreadth);
+        child->layout();
+    }
+    return child->logicalHeight();
+}
+
 void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace)
 {
     // FIXME: Split the grid tracks once we support spanning or fractions (step 1 and 2 of the algorithm).
@@ -249,9 +270,8 @@ void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection di
 
     for (size_t i = 0; i < tracks.size(); ++i) {
         GridTrack& track = tracks[i];
-        // FIXME: Add support MaxContent.
         const Length& minTrackBreadth = trackStyles[i].minTrackBreadth();
-        if (minTrackBreadth.isMinContent()) {
+        if (minTrackBreadth.isMinContent() || minTrackBreadth.isMaxContent()) {
             // FIXME: The specification factors this logic into resolveContentBasedTrackSizingFunctionsForItems
             // to reuse code between the branches and also calls distributeSpaceToTracks.
             for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
@@ -265,9 +285,21 @@ void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection di
                 availableLogicalSpace -= additionalBreadthSpace;
             }
         }
+        if (minTrackBreadth.isMaxContent()) {
+            for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+                size_t cellIndex = resolveGridPosition((direction == ForColumns) ? child->style()->gridItemColumn() : child->style()->gridItemRow());
+                if (cellIndex != i)
+                    continue;
+
+                LayoutUnit additionalBreadthSpace = maxContentForChild(child, direction, columnTracks) - track.m_usedBreadth;
+                ASSERT(additionalBreadthSpace >= 0);
+                track.m_usedBreadth += additionalBreadthSpace;
+                availableLogicalSpace -= additionalBreadthSpace;
+            }
+        }
 
         const Length& maxTrackBreadth = trackStyles[i].maxTrackBreadth();
-        if (maxTrackBreadth.isMinContent()) {
+        if (maxTrackBreadth.isMinContent() || maxTrackBreadth.isMaxContent()) {
             for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
                 size_t cellIndex = resolveGridPosition(direction, child);
                 if (cellIndex != i)
@@ -281,6 +313,21 @@ void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection di
                     track.m_maxBreadth += share;
             }
         }
+
+        if (maxTrackBreadth.isMaxContent()) {
+            for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+                size_t cellIndex = resolveGridPosition((direction == ForColumns) ? child->style()->gridItemColumn() : child->style()->gridItemRow());
+                if (cellIndex != i)
+                    continue;
+
+                LayoutUnit additionalBreadthSpace = maxContentForChild(child, direction, columnTracks) - track.maxBreadthIfNotInfinite();
+                LayoutUnit share = std::min(additionalBreadthSpace, tracks[i].m_maxBreadth - track.maxBreadthIfNotInfinite());
+                if (track.m_maxBreadth == infinity)
+                    track.m_maxBreadth = track.m_usedBreadth + share;
+                else
+                    track.m_maxBreadth += share;
+            }
+        }
     }
 
     // FIXME: The spec says to update maxBreadth if it is Infinity.
index 5f0753c..d508ae0 100644 (file)
@@ -58,6 +58,7 @@ private:
     void layoutGridItems();
 
     LayoutUnit minContentForChild(RenderBox*, TrackSizingDirection, Vector<GridTrack>& columnTracks);
+    LayoutUnit maxContentForChild(RenderBox*, TrackSizingDirection, Vector<GridTrack>& columnTracks);
     LayoutPoint findChildLogicalPosition(RenderBox*, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks);
     size_t resolveGridPosition(TrackSizingDirection, const RenderObject*) const;
     size_t resolveGridPosition(const GridPosition&) const;