[CSS Grid Layout] Add support for order inside grid items
authorsvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Oct 2013 17:35:52 +0000 (17:35 +0000)
committersvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Oct 2013 17:35:52 +0000 (17:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=123208

Reviewed by Antti Koivisto.

Source/WebCore:

Based on Blink r153457 and r153536 by <jchaffraix@chromium.org>

Added support for sorting grid items by using -webkit-order
property. Used OrderIterator to implement it so it had to be moved
out of RenderFlexibleBox to be shared with RenderGrid.

Tests: fast/css-grid-layout/grid-item-order-auto-flow-resolution.html
       fast/css-grid-layout/grid-item-order-paint-order.html

* CMakeLists.txt: Added new file.
* GNUmakefile.list.am: Ditto.
* WebCore.vcxproj/WebCore.vcxproj: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* rendering/OrderIterator.cpp: Added. Ripped out of RenderFlexibleBox.
(WebCore::OrderIterator::OrderIterator):
(WebCore::OrderIterator::setOrderValues): Use std::move semantics.
(WebCore::OrderIterator::first): Use an integer as iterator.
(WebCore::OrderIterator::next): Ditto.
(WebCore::OrderIterator::reset): Ditto.
* rendering/OrderIterator.h: Added.
(WebCore::OrderIterator::currentChild):
* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::RenderFlexibleBox):
(WebCore::RenderFlexibleBox::layoutBlock):
* rendering/RenderFlexibleBox.h:
* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::RenderGrid):
(WebCore::RenderGrid::placeItemsOnGrid):
(WebCore::RenderGrid::populateExplicitGridAndOrderIterator):
(WebCore::RenderGrid::paintChildren):
* rendering/RenderGrid.h:

LayoutTests:

From Blink r153536 by <jchaffraix@chromium.org>

Added a couple of tests to verify that we respect the specified
order of grid items both in the auto-placement algorithm and in
the final painting.

* fast/css-grid-layout/grid-item-order-auto-flow-resolution-expected.txt: Added.
* fast/css-grid-layout/grid-item-order-auto-flow-resolution.html: Added.
* fast/css-grid-layout/grid-item-order-paint-order-expected.html: Added.
* fast/css-grid-layout/grid-item-order-paint-order.html: Added.

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

16 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-order-paint-order-expected.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-order-paint-order.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/rendering/OrderIterator.cpp [new file with mode: 0644]
Source/WebCore/rendering/OrderIterator.h [new file with mode: 0644]
Source/WebCore/rendering/RenderFlexibleBox.cpp
Source/WebCore/rendering/RenderFlexibleBox.h
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderGrid.h

index ad2358c..ed30779 100644 (file)
@@ -1,3 +1,21 @@
+2013-10-28  Sergio Villar Senin  <svillar@igalia.com>
+
+        [CSS Grid Layout] Add support for order inside grid items
+        https://bugs.webkit.org/show_bug.cgi?id=123208
+
+        Reviewed by Antti Koivisto.
+
+        From Blink r153536 by <jchaffraix@chromium.org>
+
+        Added a couple of tests to verify that we respect the specified
+        order of grid items both in the auto-placement algorithm and in
+        the final painting.
+
+        * fast/css-grid-layout/grid-item-order-auto-flow-resolution-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-order-auto-flow-resolution.html: Added.
+        * fast/css-grid-layout/grid-item-order-paint-order-expected.html: Added.
+        * fast/css-grid-layout/grid-item-order-paint-order.html: Added.
+
 2013-10-28  Afonso R. Costa Jr.  <afonso.costa@samsung.com>
 
         Methods on window.internals shouldn't pass a document.
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution-expected.txt b/LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution-expected.txt
new file mode 100644 (file)
index 0000000..c2f8689
--- /dev/null
@@ -0,0 +1,8 @@
+This test checks that the auto-placement algorithm takes 'order' into account when placing grid items.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution.html b/LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution.html
new file mode 100644 (file)
index 0000000..1d321c1
--- /dev/null
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<script>
+if (window.testRunner)
+    testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1);
+</script>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    display: -webkit-grid;
+    -webkit-grid-definition-columns: 50px 100px;
+    -webkit-grid-definition-rows: 50px 100px;
+}
+
+.negativeOrder {
+    -webkit-order: -1;
+}
+
+.positiveOrder {
+    -webkit-order: 10;
+}
+</style>
+</head>
+<script src="../../resources/check-layout.js"></script>
+<body onload="checkLayout('.grid')">
+    <p>This test checks that the auto-placement algorithm takes 'order' into account when placing grid items.</p>
+
+    <!-- Step 1, grid item with a major-axis position that is not 'auto'. -->
+    <div style="position: relative">
+        <div class="grid gridAutoFlowRow">
+            <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="50" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+            <div class="sizedToGridArea firstRowAutoColumn negativeOrder" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50"></div>
+        </div>
+    </div>
+
+    <div style="position: relative">
+        <div class="grid gridAutoFlowRow">
+            <div class="sizedToGridArea firstRowAutoColumn positiveOrder" data-offset-x="50" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+            <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50"></div>
+        </div>
+    </div>
+
+    <!-- Step 4.1, grid items with a minor-axis position that is not 'auto'. -->
+    <div style="position: relative">
+        <div class="grid gridAutoFlowColumn">
+            <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="50" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+            <div class="sizedToGridArea secondRowAutoColumn negativeOrder" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
+        </div>
+    </div>
+
+    <div style="position: relative">
+        <div class="grid gridAutoFlowColumn">
+            <div class="sizedToGridArea secondRowAutoColumn positiveOrder" data-offset-x="50" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+            <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
+        </div>
+    </div>
+
+    <!-- Step 4.2, both minor and major-axis position are 'auto'. -->
+    <div style="position: relative">
+        <div class="grid gridAutoFlowColumn">
+            <div class="sizedToGridArea" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
+            <div class="sizedToGridArea negativeOrder" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50"></div>
+        </div>
+    </div>
+
+    <div style="position: relative">
+        <div class="grid gridAutoFlowColumn">
+            <div class="sizedToGridArea positiveOrder" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
+            <div class="sizedToGridArea" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50"></div>
+        </div>
+    </div>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-order-paint-order-expected.html b/LayoutTests/fast/css-grid-layout/grid-item-order-paint-order-expected.html
new file mode 100644 (file)
index 0000000..761af60
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.grid {
+    width: 100px;
+    height: 100px;
+    background-color: green;
+}
+</style>
+</head>
+<body>
+    <p>This test checks that 'order' changes the paint ordering.</p>
+    <p>There should be 2 green squares below.</p>
+    <div class="grid"></div>
+
+    <div class="grid"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-order-paint-order.html b/LayoutTests/fast/css-grid-layout/grid-item-order-paint-order.html
new file mode 100644 (file)
index 0000000..592752d
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.testRunner)
+    testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1);
+</script>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    display: -webkit-grid;
+    -webkit-grid-definition-rows: 100px;
+    -webkit-grid-definition-columns: 100px;
+    width: -webkit-fit-content;
+}
+.sizedToGridArea {
+    background-color: green;
+}
+
+.red {
+    background-color: red;
+}
+
+.negativeOrder {
+    -webkit-order: -1;
+}
+
+.positiveOrder {
+    -webkit-order: 10;
+}
+</style>
+</head>
+<body>
+    <p>This test checks that 'order' changes the paint ordering.</p>
+    <p>There should be 2 green squares below.</p>
+    <div class="grid">
+        <div class="sizedToGridArea firstRowFirstColumn"></div>
+        <div class="sizedToGridArea firstRowFirstColumn negativeOrder red"></div>
+    </div>
+
+    <div class="grid">
+        <div class="sizedToGridArea firstRowFirstColumn positiveOrder"></div>
+        <div class="sizedToGridArea firstRowFirstColumn red"></div>
+    </div>
+</body>
+</html>
index 220f481..07627ef 100644 (file)
@@ -2087,6 +2087,7 @@ set(WebCore_SOURCES
     rendering/LayoutRepainter.cpp
     rendering/LayoutState.cpp
     rendering/LineWidth.cpp
+    rendering/OrderIterator.cpp
     rendering/PointerEventsHitRules.cpp
     rendering/RenderArena.cpp
     rendering/RenderBlock.cpp
index 7bb0f93..b486d6f 100644 (file)
@@ -1,3 +1,42 @@
+2013-10-28  Sergio Villar Senin  <svillar@igalia.com>
+
+        [CSS Grid Layout] Add support for order inside grid items
+        https://bugs.webkit.org/show_bug.cgi?id=123208
+
+        Reviewed by Antti Koivisto.
+
+        Based on Blink r153457 and r153536 by <jchaffraix@chromium.org>
+
+        Added support for sorting grid items by using -webkit-order
+        property. Used OrderIterator to implement it so it had to be moved
+        out of RenderFlexibleBox to be shared with RenderGrid.
+
+        Tests: fast/css-grid-layout/grid-item-order-auto-flow-resolution.html
+               fast/css-grid-layout/grid-item-order-paint-order.html
+
+        * CMakeLists.txt: Added new file.
+        * GNUmakefile.list.am: Ditto.
+        * WebCore.vcxproj/WebCore.vcxproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * rendering/OrderIterator.cpp: Added. Ripped out of RenderFlexibleBox.
+        (WebCore::OrderIterator::OrderIterator):
+        (WebCore::OrderIterator::setOrderValues): Use std::move semantics.
+        (WebCore::OrderIterator::first): Use an integer as iterator.
+        (WebCore::OrderIterator::next): Ditto.
+        (WebCore::OrderIterator::reset): Ditto.
+        * rendering/OrderIterator.h: Added.
+        (WebCore::OrderIterator::currentChild):
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::RenderFlexibleBox):
+        (WebCore::RenderFlexibleBox::layoutBlock):
+        * rendering/RenderFlexibleBox.h:
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::RenderGrid):
+        (WebCore::RenderGrid::placeItemsOnGrid):
+        (WebCore::RenderGrid::populateExplicitGridAndOrderIterator):
+        (WebCore::RenderGrid::paintChildren):
+        * rendering/RenderGrid.h:
+
 2013-10-28  Afonso R. Costa Jr.  <afonso.costa@samsung.com>
 
         Methods on window.internals shouldn't pass a document.
index 37e42ff..4fb4121 100644 (file)
@@ -4298,6 +4298,8 @@ webcore_sources += \
        Source/WebCore/rendering/LineWidth.h \
        Source/WebCore/rendering/LineWidth.cpp \
        Source/WebCore/rendering/OverlapTestRequestClient.h \
+       Source/WebCore/rendering/OrderIterator.cpp \
+       Source/WebCore/rendering/OrderIterator.h \
        Source/WebCore/rendering/Pagination.h \
        Source/WebCore/rendering/PaintInfo.h \
        Source/WebCore/rendering/PaintPhase.h \
index e8a76e8..bd21beb 100644 (file)
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
     </ClCompile>
     <ClCompile Include="..\rendering\LineWidth.cpp" />
+    <ClCompile Include="..\rendering\OrderIterator.cpp" />
     <ClCompile Include="..\rendering\PointerEventsHitRules.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
     <ClInclude Include="..\rendering\LineInfo.h" />
     <ClInclude Include="..\rendering\LineLayoutState.h" />
     <ClInclude Include="..\rendering\LineWidth.h" />
+    <ClInclude Include="..\rendering\OrderIterator.h" />
     <ClInclude Include="..\rendering\PaintInfo.h" />
     <ClInclude Include="..\rendering\PaintPhase.h" />
     <ClInclude Include="..\rendering\PointerEventsHitRules.h" />
   <ImportGroup Label="ExtensionTargets">
     <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
index 634cce6..912f0ed 100644 (file)
                CDE3A85417F5FCE600C5BE20 /* AudioTrackPrivateAVF.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85217F5FCE600C5BE20 /* AudioTrackPrivateAVF.h */; };
                CDE3A85717F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */; };
                CDE3A85817F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */; };
+               CDE7FC44181904B1002BBB77 /* OrderIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */; };
+               CDE7FC45181904B1002BBB77 /* OrderIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE7FC43181904B1002BBB77 /* OrderIterator.h */; };
                CDEA763014608A53008B31F1 /* PlatformClockCA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDEA762E146084DE008B31F1 /* PlatformClockCA.cpp */; };
                CDEA76341460B56F008B31F1 /* ClockGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDEA76321460AE29008B31F1 /* ClockGeneric.cpp */; };
                CDEA76351460B71A008B31F1 /* Clock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDEA76331460B462008B31F1 /* Clock.cpp */; };
                CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AudioTrackPrivateAVFObjC.mm; path = objc/AudioTrackPrivateAVFObjC.mm; sourceTree = "<group>"; };
                CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioTrackPrivateAVFObjC.h; path = objc/AudioTrackPrivateAVFObjC.h; sourceTree = "<group>"; };
                CDE6560E17CA6E7600526BA7 /* mediaControlsApple.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = mediaControlsApple.js; sourceTree = "<group>"; };
+               CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OrderIterator.cpp; sourceTree = "<group>"; };
+               CDE7FC43181904B1002BBB77 /* OrderIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OrderIterator.h; sourceTree = "<group>"; };
                CDEA762C14608224008B31F1 /* Clock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clock.h; sourceTree = "<group>"; };
                CDEA762E146084DE008B31F1 /* PlatformClockCA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformClockCA.cpp; sourceTree = "<group>"; };
                CDEA762F146084EE008B31F1 /* PlatformClockCA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformClockCA.h; sourceTree = "<group>"; };
                F523D2F302DE443B018635CA /* rendering */ = {
                        isa = PBXGroup;
                        children = (
+                               CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */,
+                               CDE7FC43181904B1002BBB77 /* OrderIterator.h */,
                                439046C212DA25CE00AF80A2 /* mathml */,
                                FD08A879175D3926002CD360 /* shapes */,
                                BC8C8FAA0DDCD2F200B592F4 /* style */,
                                CD3E251C18046B0600E27F56 /* GridCoordinate.h in Headers */,
                                CD3E252418046BCD00E27F56 /* CSSGridTemplateValue.h in Headers */,
                                CDEF4FD717E85C8F00AEE24B /* GridLength.h in Headers */,
+                               CDE7FC45181904B1002BBB77 /* OrderIterator.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                BC10D76717D8EE6E005E2626 /* RenderBlockFlow.cpp in Sources */,
                                A0CB002417DF82660017896B /* LineWidth.cpp in Sources */,
                                CD3E252318046BCD00E27F56 /* CSSGridTemplateValue.cpp in Sources */,
+                               CDE7FC44181904B1002BBB77 /* OrderIterator.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/Source/WebCore/rendering/OrderIterator.cpp b/Source/WebCore/rendering/OrderIterator.cpp
new file mode 100644 (file)
index 0000000..bfbcc97
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Igalia S.L. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "OrderIterator.h"
+
+#include "RenderFlexibleBox.h"
+#include "RenderGrid.h"
+
+namespace WebCore {
+
+static const int cInvalidIndex = -1;
+
+OrderIterator::OrderIterator(RenderBox& containerBox)
+    : m_containerBox(containerBox)
+{
+    reset();
+}
+
+void OrderIterator::setOrderValues(OrderValues&& orderValues)
+{
+    reset();
+    m_orderValues = std::move(orderValues);
+    if (m_orderValues.size() < 2)
+        return;
+
+    std::sort(m_orderValues.begin(), m_orderValues.end());
+    auto nextElement = std::unique(m_orderValues.begin(), m_orderValues.end());
+    m_orderValues.shrinkCapacity(nextElement - m_orderValues.begin());
+}
+
+RenderBox* OrderIterator::first()
+{
+    reset();
+    return next();
+}
+
+RenderBox* OrderIterator::next()
+{
+    int endIndex = m_orderValues.size();
+    do {
+        if (m_currentChild) {
+            m_currentChild = m_currentChild->nextSiblingBox();
+            continue;
+        }
+
+        if (m_orderIndex == endIndex)
+            return nullptr;
+
+        if (m_orderIndex != cInvalidIndex) {
+            ++m_orderIndex;
+            if (m_orderIndex == endIndex)
+                return nullptr;
+        } else
+            m_orderIndex = 0;
+
+        m_currentChild = m_containerBox.firstChildBox();
+    } while (!m_currentChild || m_currentChild->style()->order() != m_orderValues[m_orderIndex]);
+
+    return m_currentChild;
+}
+
+void OrderIterator::reset()
+{
+    m_currentChild = nullptr;
+    m_orderIndex = cInvalidIndex;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/OrderIterator.h b/Source/WebCore/rendering/OrderIterator.h
new file mode 100644 (file)
index 0000000..e47c850
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Igalia S.L. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OrderIterator_h
+#define OrderIterator_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderBox;
+
+class OrderIterator {
+public:
+    OrderIterator(RenderBox&);
+
+    typedef Vector<int, 1> OrderValues;
+    void setOrderValues(OrderValues&&);
+
+    RenderBox* currentChild() const { return m_currentChild; }
+    RenderBox* first();
+    RenderBox* next();
+
+private:
+    void reset();
+
+    RenderBox& m_containerBox;
+    RenderBox* m_currentChild;
+    OrderValues m_orderValues;
+    int m_orderIndex;
+};
+
+} // namespace WebCore
+
+#endif //  OrderIterator_h
index dc7d6fd..f111795 100644 (file)
 
 namespace WebCore {
 
-RenderFlexibleBox::OrderIterator::OrderIterator(const RenderFlexibleBox* flexibleBox)
-    : m_flexibleBox(flexibleBox)
-    , m_currentChild(0)
-    , m_orderValuesIterator(0)
-{
-}
-
-void RenderFlexibleBox::OrderIterator::setOrderValues(const OrderValues& orderValues)
-{
-    reset();
-    m_orderValues = orderValues;
-    if (m_orderValues.size() < 2)
-        return;
-
-    std::sort(m_orderValues.begin(), m_orderValues.end());
-    auto nextElement = std::unique(m_orderValues.begin(), m_orderValues.end());
-    m_orderValues.shrinkCapacity(nextElement - m_orderValues.begin());
-}
-
-RenderBox* RenderFlexibleBox::OrderIterator::first()
-{
-    reset();
-    return next();
-}
-
-RenderBox* RenderFlexibleBox::OrderIterator::next()
-{
-    do {
-        if (!m_currentChild) {
-            if (m_orderValuesIterator == m_orderValues.end())
-                return 0;
-            if (m_orderValuesIterator) {
-                ++m_orderValuesIterator;
-                if (m_orderValuesIterator == m_orderValues.end())
-                    return 0;
-            } else
-                m_orderValuesIterator = m_orderValues.begin();
-
-            m_currentChild = m_flexibleBox->firstChildBox();
-        } else
-            m_currentChild = m_currentChild->nextSiblingBox();
-    } while (!m_currentChild || m_currentChild->style()->order() != *m_orderValuesIterator);
-
-    return m_currentChild;
-}
-
-void RenderFlexibleBox::OrderIterator::reset()
-{
-    m_currentChild = 0;
-    m_orderValuesIterator = 0;
-}
-
 struct RenderFlexibleBox::LineContext {
     LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t numberOfChildren, LayoutUnit maxAscent)
         : crossAxisOffset(crossAxisOffset)
@@ -120,7 +68,7 @@ struct RenderFlexibleBox::Violation {
 
 RenderFlexibleBox::RenderFlexibleBox(Element& element, PassRef<RenderStyle> style)
     : RenderBlock(element, std::move(style), 0)
-    , m_orderIterator(this)
+    , m_orderIterator(*this)
     , m_numberOfInFlowChildrenOnFirstLine(-1)
 {
     setChildrenInline(false); // All of our children must be block-level.
@@ -128,7 +76,7 @@ RenderFlexibleBox::RenderFlexibleBox(Element& element, PassRef<RenderStyle> styl
 
 RenderFlexibleBox::RenderFlexibleBox(Document& document, PassRef<RenderStyle> style)
     : RenderBlock(document, std::move(style), 0)
-    , m_orderIterator(this)
+    , m_orderIterator(*this)
     , m_numberOfInFlowChildrenOnFirstLine(-1)
 {
     setChildrenInline(false); // All of our children must be block-level.
@@ -345,7 +293,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
     Vector<LineContext> lineContexts;
     OrderIterator::OrderValues orderValues;
     computeMainAxisPreferredSizes(orderValues);
-    m_orderIterator.setOrderValues(orderValues);
+    m_orderIterator.setOrderValues(std::move(orderValues));
 
     ChildFrameRects oldChildRects;
     appendChildFrameRects(oldChildRects);
index a385216..77d4bfa 100644 (file)
@@ -31,6 +31,7 @@
 #ifndef RenderFlexibleBox_h
 #define RenderFlexibleBox_h
 
+#include "OrderIterator.h"
 #include "RenderBlock.h"
 
 namespace WebCore {
@@ -73,25 +74,6 @@ private:
         NoFlipForRowReverse,
     };
 
-    class OrderIterator {
-        WTF_MAKE_NONCOPYABLE(OrderIterator);
-    public:
-        typedef Vector<int, 1> OrderValues;
-
-        OrderIterator(const RenderFlexibleBox*);
-        void setOrderValues(const OrderValues&);
-        RenderBox* currentChild() const { return m_currentChild; }
-        RenderBox* first();
-        RenderBox* next();
-        void reset();
-
-    private:
-        const RenderFlexibleBox* m_flexibleBox;
-        RenderBox* m_currentChild;
-        OrderValues m_orderValues;
-        Vector<int>::const_iterator m_orderValuesIterator;
-    };
-
     typedef HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize;
     typedef Vector<RenderBox*> OrderedFlexItemList;
 
index 754a7af..fb90e0d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Apple Inc. All rights reserved.
- * Copyright (C) 2013 Igalia S.L.
+ * Copyright (C) 2013 Igalia S.L. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -143,6 +143,7 @@ private:
 
 RenderGrid::RenderGrid(Element& element, PassRef<RenderStyle> style)
     : RenderBlock(element, std::move(style), 0)
+    , m_orderIterator(*this)
 {
     // All of our children must be block level.
     setChildrenInline(false);
@@ -427,24 +428,6 @@ size_t RenderGrid::explicitGridSizeForSide(GridPositionSide side) const
     return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColumnCount() : explicitGridRowCount();
 }
 
-size_t RenderGrid::maximumIndexInDirection(TrackSizingDirection direction) const
-{
-    size_t maximumIndex = std::max<size_t>(1, (direction == ForColumns) ? explicitGridColumnCount() : explicitGridRowCount());
-
-    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        OwnPtr<GridSpan> positions = resolveGridPositionsFromStyle(child, direction);
-
-        // |positions| is null if we need to run the auto-placement algorithm. Our estimation ignores
-        // this case as the auto-placement algorithm will grow the grid as needed.
-        if (!positions)
-            continue;
-
-        maximumIndex = std::max(maximumIndex, positions->finalPositionIndex + 1);
-    }
-
-    return maximumIndex;
-}
-
 LayoutUnit RenderGrid::logicalContentHeightForChild(RenderBox* child, Vector<GridTrack>& columnTracks)
 {
     // FIXME: We shouldn't force a layout every time this function is called but
@@ -625,15 +608,12 @@ void RenderGrid::placeItemsOnGrid()
     ASSERT(!gridWasPopulated());
     ASSERT(m_gridItemCoordinate.isEmpty());
 
-    m_grid.grow(maximumIndexInDirection(ForRows));
-    size_t maximumColumnIndex = maximumIndexInDirection(ForColumns);
-    for (size_t i = 0; i < m_grid.size(); ++i)
-        m_grid[i].grow(maximumColumnIndex);
+    populateExplicitGridAndOrderIterator();
 
     Vector<RenderBox*> autoMajorAxisAutoGridItems;
     Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
     GridAutoFlow autoFlow = style()->gridAutoFlow();
-    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+    for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
         // FIXME: We never re-resolve positions if the grid is grown during auto-placement which may lead auto / <integer>
         // positions to not match the author's intent. The specification is unclear on what should be done in this case.
         OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
@@ -663,6 +643,39 @@ void RenderGrid::placeItemsOnGrid()
     placeAutoMajorAxisItemsOnGrid(autoMajorAxisAutoGridItems);
 }
 
+void RenderGrid::populateExplicitGridAndOrderIterator()
+{
+    // FIXME: We should find a way to share OrderValues's initialization code with RenderFlexibleBox.
+    OrderIterator::OrderValues orderValues;
+    size_t maximumRowIndex = std::max<size_t>(1, explicitGridRowCount());
+    size_t maximumColumnIndex = std::max<size_t>(1, explicitGridColumnCount());
+
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        // Avoid growing the vector for the common-case default value of 0. This optimizes the most common case which is
+        // one or a few values with the default order 0
+        int order = child->style()->order();
+        if (orderValues.isEmpty() || orderValues.last() != order)
+            orderValues.append(order);
+
+        // This function bypasses the cache (cachedGridCoordinate()) as it is used to build it.
+        OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
+        OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
+
+        // |positions| is 0 if we need to run the auto-placement algorithm. Our estimation ignores
+        // this case as the auto-placement algorithm will grow the grid as needed.
+        if (rowPositions)
+            maximumRowIndex = std::max(maximumRowIndex, rowPositions->finalPositionIndex + 1);
+        if (columnPositions)
+            maximumColumnIndex = std::max(maximumColumnIndex, columnPositions->finalPositionIndex + 1);
+    }
+
+    m_grid.grow(maximumRowIndex);
+    for (size_t i = 0; i < m_grid.size(); ++i)
+        m_grid[i].grow(maximumColumnIndex);
+
+    m_orderIterator.setOrderValues(std::move(orderValues));
+}
+
 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(Vector<RenderBox*> autoGridItems)
 {
     for (size_t i = 0; i < autoGridItems.size(); ++i) {
@@ -1014,6 +1027,12 @@ LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<
     return offset;
 }
 
+void RenderGrid::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& forChild, bool usePrintRect)
+{
+    for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next())
+        paintChild(*child, paintInfo, paintOffset, forChild, usePrintRect);
+}
+
 const char* RenderGrid::renderName() const
 {
     if (isFloating())
index 456812d..c3afa33 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Igalia S.L. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +27,7 @@
 #ifndef RenderGrid_h
 #define RenderGrid_h
 
+#include "OrderIterator.h"
 #include "RenderBlock.h"
 
 namespace WebCore {
@@ -73,6 +75,7 @@ private:
     void insertItemIntoGrid(RenderBox*, size_t rowTrack, size_t columnTrack);
     void insertItemIntoGrid(RenderBox*, const GridCoordinate&);
     void placeItemsOnGrid();
+    void populateExplicitGridAndOrderIterator();
     void placeSpecifiedMajorAxisItemsOnGrid(Vector<RenderBox*>);
     void placeAutoMajorAxisItemsOnGrid(Vector<RenderBox*>);
     void placeAutoMajorAxisItemOnGrid(RenderBox*);
@@ -95,7 +98,6 @@ private:
     size_t explicitGridColumnCount() const;
     size_t explicitGridRowCount() const;
     size_t explicitGridSizeForSide(GridPositionSide) const;
-    size_t maximumIndexInDirection(TrackSizingDirection) const;
 
     LayoutUnit logicalContentHeightForChild(RenderBox*, Vector<GridTrack>&);
     LayoutUnit minContentForChild(RenderBox*, TrackSizingDirection, Vector<GridTrack>& columnTracks);
@@ -114,6 +116,8 @@ private:
 
     LayoutUnit gridAreaBreadthForChild(const RenderBox* child, TrackSizingDirection, const Vector<GridTrack>&) const;
 
+    virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint& paintOffset, PaintInfo& forChild, bool usePrintRect) OVERRIDE FINAL;
+
 #ifndef NDEBUG
     bool tracksAreWiderThanMinTrackBreadth(TrackSizingDirection, const Vector<GridTrack>&);
     bool gridWasPopulated() const { return !m_grid.isEmpty() && !m_grid[0].isEmpty(); }
@@ -132,6 +136,7 @@ private:
 
     Vector<Vector<Vector<RenderBox*, 1>>> m_grid;
     HashMap<const RenderBox*, GridCoordinate> m_gridItemCoordinate;
+    OrderIterator m_orderIterator;
 };
 
 } // namespace WebCore