[css-grid] Add support for percentage gaps
authorrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Apr 2017 16:27:53 +0000 (16:27 +0000)
committerrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Apr 2017 16:27:53 +0000 (16:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170764

Reviewed by Sergio Villar Senin.

Source/WebCore:

Part of the code to support percentage gaps was already imported
from Blink in r213149 (bug #168657). However parsing was not enabled yet,
so some pieces were missing.

This patch accepts percentages in the parsing of grid-column-gap and
grid-row-gap properties, and the grid-gap shorthand.
On top of that it gets rid of GridTrackSizingAlgorithm::sizingOperation()
method as it's not needed. And instead it passes the specific operation
to each call to RenderGrid::guttersSize(), otherwise we would be getting
wrong results.

Test: fast/css-grid-layout/grid-gutters-as-percentage.html

* css/parser/CSSPropertyParser.cpp:
(WebCore::CSSPropertyParser::parseSingleValue): Add support for
percentage values.
(WebCore::CSSPropertyParser::parseShorthand): Ditto.
* rendering/GridTrackSizingAlgorithm.cpp:
(WebCore::IndefiniteSizeStrategy::recomputeUsedFlexFractionIfNeeded):
Pass the specific sizing operation.
* rendering/GridTrackSizingAlgorithm.h: Remove sizingOperation().
* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::computeTrackBasedLogicalHeight): Pass the specific
sizing operation.
(WebCore::RenderGrid::computeTrackSizesForDefiniteSize): Ditto.
(WebCore::RenderGrid::computeTrackSizesForIndefiniteSize): Ditto.
(WebCore::RenderGrid::populateGridPositionsForDirection): Ditto.

LayoutTests:

Import tests from Blink.

* fast/css-grid-layout/grid-gutters-as-percentage-expected.txt: Added.
* fast/css-grid-layout/grid-gutters-as-percentage.html: Added.
* fast/css-grid-layout/grid-gutters-get-set-expected.txt:
* fast/css-grid-layout/grid-gutters-get-set.html:

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

LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/grid-gutters-as-percentage-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-gutters-as-percentage.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-gutters-get-set-expected.txt
LayoutTests/fast/css-grid-layout/grid-gutters-get-set.html
Source/WebCore/ChangeLog
Source/WebCore/css/parser/CSSPropertyParser.cpp
Source/WebCore/rendering/GridTrackSizingAlgorithm.cpp
Source/WebCore/rendering/GridTrackSizingAlgorithm.h
Source/WebCore/rendering/RenderGrid.cpp

index 01a894a..654a0ba 100644 (file)
@@ -1,3 +1,17 @@
+2017-04-18  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [css-grid] Add support for percentage gaps
+        https://bugs.webkit.org/show_bug.cgi?id=170764
+
+        Reviewed by Sergio Villar Senin.
+
+        Import tests from Blink.
+
+        * fast/css-grid-layout/grid-gutters-as-percentage-expected.txt: Added.
+        * fast/css-grid-layout/grid-gutters-as-percentage.html: Added.
+        * fast/css-grid-layout/grid-gutters-get-set-expected.txt:
+        * fast/css-grid-layout/grid-gutters-get-set.html:
+
 2017-04-18  Miguel Gomez  <magomez@igalia.com>
 
         [GTK+] Crash in WebCore::ImageFrame::ImageFrame()
diff --git a/LayoutTests/fast/css-grid-layout/grid-gutters-as-percentage-expected.txt b/LayoutTests/fast/css-grid-layout/grid-gutters-as-percentage-expected.txt
new file mode 100644 (file)
index 0000000..d8a7b5e
--- /dev/null
@@ -0,0 +1,109 @@
+
+PASS .grid 1 
+PASS .grid 2 
+PASS .grid 3 
+PASS .grid 4 
+PASS .grid 5 
+PASS .grid 6 
+PASS .grid 7 
+PASS .grid 8 
+PASS .grid 9 
+PASS .grid 10 
+PASS .grid 11 
+PASS .grid 12 
+PASS .grid 13 
+PASS .grid 14 
+PASS .grid 15 
+PASS .grid 16 
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which will reduce the available space for tracks; however, they can grow exceeding their content's max-width.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'instrinsic' width, which reduce the available space for tracks; however, since we use 'fit-content' intrinsic size, first column's width is reduced and height increased to let its content to fit.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which will reduce the available space for tracks; however, they can grow exceeding their content's max-width.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'instrinsic' width, which reduce the available space for tracks; however, since we use 'fit-content' intrinsic size, first column's width is reduced and height increased to let its content to fit.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which reduce the available space for tracks; however, they are fixed sized and fit.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'intrinsic' width, which reduce the available space for tracks; however, they are fixed sized and don't fit so they overflow the grid container.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which reduce the available space for tracks; however, they are fixed sized and fit.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Both row and column gaps are based on definite sizes, but they will reduce the available space for tracks; however, since the container's specified inline size is not enough, first column's width is reduced and height increased to let its content to fit.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Both row and column gaps are based on definite sizes, but they will reduce the available space for tracks; however, they can grow exceeding their content's max-width.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, they are fixed sized and don't fit so they overflow the grid container.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, they are fixed sized and fit.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'instrinsic' width, which reduce the available space for tracks; however, since we use 'fit-content' intrinsic size, only 1 repeteation is allowed, so tracks are adjusted to fit in the intrinsic size reduced by the gaps.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, repeat auto-fill allows all of them to fit.
+
+XXX X XX X
+XX XXX X X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+XXXXX X XX
+Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, repeat auto-fill allows only 1 repetition.
+
+XXX X XX X
+XX XXX X X
+X XX XXX X
+XXXXX X XX
+Grid with positioned items. Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which reduce the available space for tracks; however, they are fixed sized and fit.
+
+XXX X XX XXX XXX X XX XX XXX XXXXXX X XX
+Grid with positioned items. Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, they are fixed sized and don't fit so they overflow the grid container.
+
+XXX X XX XXX XXX X XX XX XXX XXXXXX X XX
diff --git a/LayoutTests/fast/css-grid-layout/grid-gutters-as-percentage.html b/LayoutTests/fast/css-grid-layout/grid-gutters-as-percentage.html
new file mode 100644 (file)
index 0000000..4b4f4f2
--- /dev/null
@@ -0,0 +1,191 @@
+<!DOCTYPE html>
+<link href="resources/grid.css" rel="stylesheet">
+<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
+<link href="../css-intrinsic-dimensions/resources/height-keyword-classes.css" rel="stylesheet">
+<style>
+body { margin: 0; }
+.grid { font: 10px/1 Ahem; position: relative; }
+.widthAuto { width: auto; }
+.heightAuto { height: auto; }
+.width400 { width: 400px; }
+.width200 { width: 200px; }
+.height200 { height: 200px; }
+.height100 { height: 100px; }
+.two100pxColumns { grid-template-columns: 100px 100px; }
+.two50pxRows { grid-template-rows: 50px 50px; }
+.autoRepeat { grid-template: repeat(auto-fill, 50px) / repeat(auto-fill, 100px); }
+.columnGap10Percent { grid-column-gap: 10% }
+.rowGap20Percent { grid-row-gap: 20% }
+.positioned { position: absolute; width: 100%; height: 100%; }
+</style>
+
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../../resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which will reduce the available space for tracks; however, they can grow exceeding their content's max-width.</p>
+<div class="width400">
+    <div class="grid columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="20">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="180" data-expected-height="10">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="220" data-offset-y="0"  data-expected-width="180" data-expected-height="10">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="10" data-expected-width="180" data-expected-height="10">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="220" data-offset-y="10" data-expected-width="180" data-expected-height="10">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'instrinsic' width, which reduce the available space for tracks; however, since we use 'fit-content' intrinsic size, first column's width is reduced and height increased to let its content to fit.</p>
+<div class="width400">
+    <div class="grid fit-content heightAuto columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="40">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="80"  data-expected-height="20">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="100" data-offset-y="0"  data-expected-width="100" data-expected-height="20">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="20" data-expected-width="80"  data-expected-height="20">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="100" data-offset-y="20" data-expected-width="100" data-expected-height="20">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which will reduce the available space for tracks; however, they can grow exceeding their content's max-width.</p>
+<div class="width400">
+    <div class="grid fit-content widthAuto columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="20">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="180" data-expected-height="10">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="220" data-offset-y="0"  data-expected-width="180" data-expected-height="10">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="10" data-expected-width="180" data-expected-height="10">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="220" data-offset-y="10" data-expected-width="180" data-expected-height="10">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'instrinsic' width, which reduce the available space for tracks; however, since we use 'fit-content' intrinsic size, first column's width is reduced and height increased to let its content to fit.</p>
+<div class="width400">
+    <div class="grid fit-content columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="40">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="80"  data-expected-height="20">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="100" data-offset-y="0"  data-expected-width="100" data-expected-height="20">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="20" data-expected-width="80"  data-expected-height="20">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="100" data-offset-y="20" data-expected-width="100" data-expected-height="20">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which reduce the available space for tracks; however, they are fixed sized and fit.</p>
+<div class="width400">
+     <div class="grid two100pxColumns two50pxRows columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="100">
+         <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+         <div class="firstRowSecondColumn"  data-offset-x="140" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+         <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="50" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+         <div class="secondRowSecondColumn" data-offset-x="140" data-offset-y="50" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+     </div>
+</div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'intrinsic' width, which reduce the available space for tracks; however, they are fixed sized and don't fit so they overflow the grid container.</p>
+<div class="width400">
+     <div class="grid fit-content heightAuto two100pxColumns two50pxRows columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="100">
+         <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+         <div class="firstRowSecondColumn"  data-offset-x="120" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+         <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="50" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+         <div class="secondRowSecondColumn" data-offset-x="120" data-offset-y="50" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+     </div>
+</div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which reduce the available space for tracks; however, they are fixed sized and fit.</p>
+<div class="width400">
+     <div class="grid fit-content widthAuto two100pxColumns two50pxRows columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="100">
+         <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+         <div class="firstRowSecondColumn"  data-offset-x="140" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+         <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="50" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+         <div class="secondRowSecondColumn" data-offset-x="140" data-offset-y="50" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+     </div>
+</div>
+
+<p>Both row and column gaps are based on definite sizes, but they will reduce the available space for tracks; however, since the container's specified inline size is not enough, first column's width is reduced and height increased to let its content to fit.</p>
+<div class="width400">
+    <div class="grid width200 height100 columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="100">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="80"  data-expected-height="40">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="100" data-offset-y="0"  data-expected-width="100" data-expected-height="40">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="60" data-expected-width="80"  data-expected-height="40">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="100" data-offset-y="60" data-expected-width="100" data-expected-height="40">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Both row and column gaps are based on definite sizes, but they will reduce the available space for tracks; however, they can grow exceeding their content's max-width.</p>
+<div class="width400">
+    <div class="grid width400 height200 columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="200">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"   data-expected-width="180" data-expected-height="80">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="220" data-offset-y="0"   data-expected-width="180" data-expected-height="80">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="120" data-expected-width="180" data-expected-height="80">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="220" data-offset-y="120" data-expected-width="180" data-expected-height="80">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, they are fixed sized and don't fit so they overflow the grid container.</p>
+<div class="width400">
+    <div class="grid width200 height100 two100pxColumns two50pxRows columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="100">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="120" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="70" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="120" data-offset-y="70" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, they are fixed sized and fit.</p>
+<div class="width400">
+    <div class="grid width400 height200 two100pxColumns two50pxRows columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="200">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="140" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="90" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="140" data-offset-y="90" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'instrinsic' width, which reduce the available space for tracks; however, since we use 'fit-content' intrinsic size, only 1 repeteation is allowed, so tracks are adjusted to fit in the intrinsic size reduced by the gaps.</p>
+<div class="width400">
+    <div class="grid fit-content autoRepeat columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="70">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="120" data-offset-y="0"  data-expected-width="80" data-expected-height="50">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="50" data-expected-width="100" data-expected-height="20">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="120" data-offset-y="50" data-expected-width="80" data-expected-height="20">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, repeat auto-fill allows all of them to fit.</p>
+<div class="">
+    <div class="grid width400 height200 autoRepeat columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="200">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="140" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+        <div class="firstRowThirdColumn"  data-offset-x="280" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="90" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="140" data-offset-y="90" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+        <div class="secondRowThirdColumn" data-offset-x="280" data-offset-y="90" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, repeat auto-fill allows only 1 repetition.</p>
+<div class="">
+    <div class="grid width200 height100 autoRepeat columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="100">
+        <div class="firstRowFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+        <div class="firstRowSecondColumn"  data-offset-x="120" data-offset-y="0"  data-expected-width="80" data-expected-height="50">XX XXX X X</div>
+        <div class="secondRowFirstColumn"  data-offset-x="0"   data-offset-y="70" data-expected-width="100" data-expected-height="30">X XX XXX X</div>
+        <div class="secondRowSecondColumn" data-offset-x="120" data-offset-y="70" data-expected-width="80" data-expected-height="30">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Grid with positioned items. Height is indefinite, so row gaps should be 0. Column gaps based on a grid's 'auto' width, which reduce the available space for tracks; however, they are fixed sized and fit.</p>
+<div class="width400">
+    <div class="grid two100pxColumns two50pxRows columnGap10Percent rowGap20Percent" data-expected-width="400" data-expected-height="100">
+        <div class="positioned onlyFirstRowOnlyFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+        <div class="positioned onlyFirstRowOnlySecondColumn"  data-offset-x="140" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+        <div class="positioned onlySecondRowOnlyFirstColumn"  data-offset-x="0"   data-offset-y="50" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+        <div class="positioned onlySecondRowOnlySecondColumn" data-offset-x="140" data-offset-y="50" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+    </div>
+</div>
+
+<p>Grid with positioned items. Both row and column gaps are based on definite sizes, they will reduce the available space for tracks; however, they are fixed sized and don't fit so they overflow the grid container.</p>
+<div class="">
+    <div class="grid width200 height100 two100pxColumns two50pxRows columnGap10Percent rowGap20Percent" data-expected-width="200" data-expected-height="100">
+        <div class="positioned onlyFirstRowOnlyFirstColumn"   data-offset-x="0"   data-offset-y="0"  data-expected-width="100" data-expected-height="50">XXX X XX X</div>
+        <div class="positioned onlyFirstRowOnlySecondColumn"  data-offset-x="120" data-offset-y="0"  data-expected-width="100" data-expected-height="50">XX XXX X X</div>
+        <div class="positioned onlySecondRowOnlyFirstColumn"  data-offset-x="0"   data-offset-y="70" data-expected-width="100" data-expected-height="50">X XX XXX X</div>
+        <div class="positioned onlySecondRowOnlySecondColumn" data-offset-x="120" data-offset-y="70" data-expected-width="100" data-expected-height="50">XXXXX X XX</div>
+    </div>
+</div>
+
+</body>
index 473ba8f..ebe9ffc 100644 (file)
@@ -8,8 +8,12 @@ PASS window.getComputedStyle(defaultGrid, '').getPropertyValue('grid-row-gap') i
 PASS window.getComputedStyle(defaultGrid, '').getPropertyValue('grid-column-gap') is "0px"
 PASS window.getComputedStyle(gridGap, '').getPropertyValue('grid-row-gap') is "20px"
 PASS window.getComputedStyle(gridGap, '').getPropertyValue('grid-column-gap') is "15px"
+PASS window.getComputedStyle(gridPercentGap, '').getPropertyValue('grid-row-gap') is "10%"
+PASS window.getComputedStyle(gridPercentGap, '').getPropertyValue('grid-column-gap') is "15%"
 PASS window.getComputedStyle(gridSimpleGap, '').getPropertyValue('grid-row-gap') is "25px"
 PASS window.getComputedStyle(gridSimpleGap, '').getPropertyValue('grid-column-gap') is "25px"
+PASS window.getComputedStyle(gridSimplePercentGap, '').getPropertyValue('grid-row-gap') is "10%"
+PASS window.getComputedStyle(gridSimplePercentGap, '').getPropertyValue('grid-column-gap') is "10%"
 PASS window.getComputedStyle(gridColumnGap, '').getPropertyValue('grid-row-gap') is "0px"
 PASS window.getComputedStyle(gridColumnGap, '').getPropertyValue('grid-column-gap') is "16px"
 PASS window.getComputedStyle(gridRowGap, '').getPropertyValue('grid-row-gap') is "32px"
@@ -20,6 +24,8 @@ PASS window.getComputedStyle(gridRowColumnGaps, '').getPropertyValue('grid-row-g
 PASS window.getComputedStyle(gridRowColumnGaps, '').getPropertyValue('grid-column-gap') is "16px"
 PASS window.getComputedStyle(gridRowColumnGaps, '').getPropertyValue('grid-row-gap') is "12px"
 PASS window.getComputedStyle(gridRowColumnGaps, '').getPropertyValue('grid-column-gap') is "16px"
+PASS window.getComputedStyle(gridRowColumnPercentGaps, '').getPropertyValue('grid-row-gap') is "10%"
+PASS window.getComputedStyle(gridRowColumnPercentGaps, '').getPropertyValue('grid-column-gap') is "15%"
 PASS window.getComputedStyle(gridRowColumnInheritGaps, '').getPropertyValue('grid-row-gap') is "25px"
 PASS window.getComputedStyle(gridRowColumnInheritGaps, '').getPropertyValue('grid-column-gap') is "25px"
 PASS window.getComputedStyle(gridRowColumnInitialGaps, '').getPropertyValue('grid-row-gap') is "0px"
index 58c4cfe..0479042 100644 (file)
@@ -4,13 +4,19 @@
 <link href="resources/grid.css" rel="stylesheet">
 <style>
 .gridGap { grid-gap: 20px 15px; }
+.gridPercentGap { grid-gap: 10% 15%; }
 .gridSimpleGap { grid-gap: 25px; }
+.gridSimplePercentGap { grid-gap: 10%; }
 .gridColumnGap { grid-column-gap: 2vw; }
 .gridRowGap { grid-row-gap: 2em; }
 .gridRowColumnGaps {
     grid-row-gap: 12px;
     grid-column-gap: 1rem;
 }
+.gridRowColumnPercentGaps {
+    grid-row-gap: 10%;
+    grid-column-gap: 15%;
+}
 .gridRowColumnInheritGaps {
     grid-row-gap: inherit;
     grid-column-gap: inherit;
@@ -23,7 +29,7 @@
     grid-row-gap: calc(10px + 3px);
     grid-column-gap: calc(2px + 1vw);
 }
-.gridInvalidRowGap { grid-row-gap: 10%; }
+.gridInvalidRowGap { grid-row-gap: -10px; }
 .gridInvalidColumnGap { grid-column-gap: max-content; }
 .gridInvalidMultipleRowColumnGaps {
     grid-row-gap: 10px 1px;
 
 <div class="grid" id="defaultGrid"></div>
 <div class="grid gridGap" id="gridGap"></div>
+<div class="grid gridPercentGap" id="gridPercentGap"></div>
 <div class="grid gridSimpleGap" id="gridSimpleGap"></div>
+<div class="grid gridSimplePercentGap" id="gridSimplePercentGap"></div>
 <div class="grid gridColumnGap" id="gridColumnGap"></div>
 <div class="grid gridRowGap" id="gridRowGap"></div>
 <div class="grid gridCalcGaps" id="gridCalcGaps"></div>
 <div class="grid gridRowColumnGaps" id="gridRowColumnGaps"></div>
+<div class="grid gridRowColumnPercentGaps" id="gridRowColumnPercentGaps"></div>
 <div class="grid gridSimpleGap">
     <div class="grid gridRowColumnInheritGaps" id="gridRowColumnInheritGaps"></div>
 </div>
@@ -72,12 +81,15 @@ debug("Test getting grid-column-gap and grid-row-gap set through CSS");
 
 testGridGapDefinitionsValues("defaultGrid", "0px", "0px");
 testGridGapDefinitionsValues("gridGap", "20px", "15px");
+testGridGapDefinitionsValues("gridPercentGap", "10%", "15%");
 testGridGapDefinitionsValues("gridSimpleGap", "25px", "25px");
+testGridGapDefinitionsValues("gridSimplePercentGap", "10%", "10%");
 testGridGapDefinitionsValues("gridColumnGap", "0px", "16px");
 testGridGapDefinitionsValues("gridRowGap", "32px", "0px");
 testGridGapDefinitionsValues("gridCalcGaps", "13px", "10px");
 testGridGapDefinitionsValues("gridRowColumnGaps", "12px", "16px");
 testGridGapDefinitionsValues("gridRowColumnGaps", "12px", "16px");
+testGridGapDefinitionsValues("gridRowColumnPercentGaps", "10%", "15%");
 testGridGapDefinitionsValues("gridRowColumnInheritGaps", "25px", "25px");
 testGridGapDefinitionsValues("gridRowColumnInitialGaps", "0px", "0px");
 
index 3f26f45..c8526ce 100644 (file)
@@ -1,3 +1,38 @@
+2017-04-18  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [css-grid] Add support for percentage gaps
+        https://bugs.webkit.org/show_bug.cgi?id=170764
+
+        Reviewed by Sergio Villar Senin.
+
+        Part of the code to support percentage gaps was already imported
+        from Blink in r213149 (bug #168657). However parsing was not enabled yet,
+        so some pieces were missing.
+
+        This patch accepts percentages in the parsing of grid-column-gap and
+        grid-row-gap properties, and the grid-gap shorthand.
+        On top of that it gets rid of GridTrackSizingAlgorithm::sizingOperation()
+        method as it's not needed. And instead it passes the specific operation
+        to each call to RenderGrid::guttersSize(), otherwise we would be getting
+        wrong results.
+
+        Test: fast/css-grid-layout/grid-gutters-as-percentage.html
+
+        * css/parser/CSSPropertyParser.cpp:
+        (WebCore::CSSPropertyParser::parseSingleValue): Add support for
+        percentage values.
+        (WebCore::CSSPropertyParser::parseShorthand): Ditto.
+        * rendering/GridTrackSizingAlgorithm.cpp:
+        (WebCore::IndefiniteSizeStrategy::recomputeUsedFlexFractionIfNeeded):
+        Pass the specific sizing operation.
+        * rendering/GridTrackSizingAlgorithm.h: Remove sizingOperation().
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::computeTrackBasedLogicalHeight): Pass the specific
+        sizing operation.
+        (WebCore::RenderGrid::computeTrackSizesForDefiniteSize): Ditto.
+        (WebCore::RenderGrid::computeTrackSizesForIndefiniteSize): Ditto.
+        (WebCore::RenderGrid::populateGridPositionsForDirection): Ditto.
+
 2017-04-18  Per Arne Vollan  <pvollan@apple.com>
 
         Add fallback fonts to video captions stylesheet.
index 949f4d4..9fadb80 100644 (file)
@@ -3989,7 +3989,7 @@ RefPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID property, CSS
         return consumeAnimationPropertyList(property, m_range, m_context);
     case CSSPropertyGridColumnGap:
     case CSSPropertyGridRowGap:
-        return consumeLength(m_range, m_context.mode, ValueRangeNonNegative);
+        return consumeLengthOrPercent(m_range, m_context.mode, ValueRangeNonNegative);
     case CSSPropertyShapeMargin:
         return consumeLengthOrPercent(m_range, m_context.mode, ValueRangeNonNegative);
     case CSSPropertyShapeImageThreshold:
@@ -5707,8 +5707,8 @@ bool CSSPropertyParser::parseShorthand(CSSPropertyID property, bool important)
     case CSSPropertyPerspectiveOrigin:
         return consumePerspectiveOrigin(important);
     case CSSPropertyGridGap: {
-        RefPtr<CSSValue> rowGap = consumeLength(m_range, m_context.mode, ValueRangeNonNegative);
-        RefPtr<CSSValue> columnGap = consumeLength(m_range, m_context.mode, ValueRangeNonNegative);
+        RefPtr<CSSValue> rowGap = consumeLengthOrPercent(m_range, m_context.mode, ValueRangeNonNegative);
+        RefPtr<CSSValue> columnGap = consumeLengthOrPercent(m_range, m_context.mode, ValueRangeNonNegative);
         if (!rowGap || !m_range.atEnd())
             return false;
         if (!columnGap)
index fa7e71d..15efb7e 100644 (file)
@@ -915,7 +915,7 @@ bool IndefiniteSizeStrategy::recomputeUsedFlexFractionIfNeeded(double& flexFract
 
     LayoutUnit freeSpace = checkMaxSize ? maxSize.value() : LayoutUnit(-1);
     const Grid& grid = m_algorithm.grid();
-    freeSpace = std::max(freeSpace, minSize.value()) - renderGrid->guttersSize(grid, ForRows, 0, grid.numTracks(ForRows), m_algorithm.sizingOperation());
+    freeSpace = std::max(freeSpace, minSize.value()) - renderGrid->guttersSize(grid, ForRows, 0, grid.numTracks(ForRows), IntrinsicSizeComputation);
 
     size_t numberOfTracks = m_algorithm.tracks(ForRows).size();
     flexFraction = findFrUnitSize(GridSpan::translatedDefiniteGridSpan(0, numberOfTracks), freeSpace);
index 2ce2d27..da66e1f 100644 (file)
@@ -117,8 +117,6 @@ public:
     bool tracksAreWiderThanMinTrackBreadth() const;
 #endif
 
-    SizingOperation sizingOperation() const { return m_sizingOperation; }
-
 private:
     GridTrackSize gridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex) const { return gridTrackSize(direction, translatedIndex, m_sizingOperation); }
     const GridTrackSize& rawGridTrackSize(GridTrackSizingDirection, unsigned translatedIndex) const;
index 9656071..d888b6d 100644 (file)
@@ -128,14 +128,14 @@ LayoutUnit RenderGrid::computeTrackBasedLogicalHeight() const
     for (const auto& row : allRows)
         logicalHeight += row.baseSize();
 
-    logicalHeight += guttersSize(m_grid, ForRows, 0, allRows.size(), m_trackSizingAlgorithm.sizingOperation());
+    logicalHeight += guttersSize(m_grid, ForRows, 0, allRows.size(), TrackSizing);
 
     return logicalHeight;
 }
 
 void RenderGrid::computeTrackSizesForDefiniteSize(GridTrackSizingDirection direction, LayoutUnit availableSpace)
 {
-    LayoutUnit totalGuttersSize = guttersSize(m_grid, direction, 0, m_grid.numTracks(direction), m_trackSizingAlgorithm.sizingOperation());
+    LayoutUnit totalGuttersSize = guttersSize(m_grid, direction, 0, m_grid.numTracks(direction), TrackSizing);
     LayoutUnit freeSpace = availableSpace - totalGuttersSize;
 
     m_trackSizingAlgorithm.setup(direction, numTracks(direction, m_grid), TrackSizing, availableSpace, freeSpace);
@@ -383,7 +383,7 @@ void RenderGrid::computeTrackSizesForIndefiniteSize(GridTrackSizingAlgorithm& al
     algorithm.run();
 
     size_t numberOfTracks = algorithm.tracks(direction).size();
-    LayoutUnit totalGuttersSize = guttersSize(grid, direction, 0, numberOfTracks, algorithm.sizingOperation());
+    LayoutUnit totalGuttersSize = guttersSize(grid, direction, 0, numberOfTracks, IntrinsicSizeComputation);
 
     minIntrinsicSize = algorithm.minContentSize() + totalGuttersSize;
     maxIntrinsicSize = algorithm.maxContentSize() + totalGuttersSize;
@@ -1077,7 +1077,7 @@ void RenderGrid::populateGridPositionsForDirection(GridTrackSizingDirection dire
         // If we have collapsed tracks we just ignore gaps here and add them later as we might not
         // compute the gap between two consecutive tracks without examining the surrounding ones.
         bool hasCollapsedTracks = m_grid.hasAutoRepeatEmptyTracks(direction);
-        LayoutUnit gap = !hasCollapsedTracks ? gridGapForDirection(direction, m_trackSizingAlgorithm.sizingOperation()) : LayoutUnit();
+        LayoutUnit gap = !hasCollapsedTracks ? gridGapForDirection(direction, TrackSizing) : LayoutUnit();
         unsigned nextToLastLine = numberOfLines - 2;
         for (unsigned i = 0; i < nextToLastLine; ++i)
             positions[i + 1] = positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap;
@@ -1086,7 +1086,7 @@ void RenderGrid::populateGridPositionsForDirection(GridTrackSizingDirection dire
         // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to collapse (they
         // coincide exactly) except on the edges of the grid where they become 0.
         if (hasCollapsedTracks) {
-            gap = gridGapForDirection(direction, m_trackSizingAlgorithm.sizingOperation());
+            gap = gridGapForDirection(direction, TrackSizing);
             unsigned remainingEmptyTracks = m_grid.autoRepeatEmptyTracks(direction)->size();
             LayoutUnit gapAccumulator;
             for (unsigned i = 1; i < lastLine; ++i) {