[CSSRegions]Implement NamedFlow::getRegionsByContentNode
authormihnea@adobe.com <mihnea@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Feb 2012 09:21:51 +0000 (09:21 +0000)
committermihnea@adobe.com <mihnea@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Feb 2012 09:21:51 +0000 (09:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=77746

Reviewed by David Hyatt.

Source/WebCore:

Tests: fast/regions/get-regions-by-content-node-horiz-bt.html
       fast/regions/get-regions-by-content-node-horiz-tb.html
       fast/regions/get-regions-by-content-node-vert-lr.html
       fast/regions/get-regions-by-content-node-vert-rl.html
       fast/regions/get-regions-by-content-node.html
       fast/regions/get-regions-by-content-node2.html

* CMakeLists.txt:
* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* dom/Node.cpp:
(WebCore::Node::removeCachedRegionNodeList):
(WebCore):
(WebCore::Node::getRegionsByContentNode):
(WebCore::NodeListsNodeData::invalidateCaches):
(WebCore::NodeListsNodeData::isEmpty):
* dom/Node.h:
(WebCore):
(Node):
* dom/NodeRareData.h:
(NodeListsNodeData):
* dom/RegionNodeList.cpp:
(WebCore):
(WebCore::RegionNodeList::RegionNodeList):
(WebCore::RegionNodeList::~RegionNodeList):
(WebCore::RegionNodeList::nodeMatches):
* dom/RegionNodeList.h:
(WebCore):
(RegionNodeList):
(WebCore::RegionNodeList::create):
* dom/WebKitNamedFlow.cpp:
(WebCore::WebKitNamedFlow::getRegionsByContentNode):
(WebCore):
* dom/WebKitNamedFlow.h:
(WebCore):
(WebKitNamedFlow):
* dom/WebKitNamedFlow.idl:
* rendering/RenderFlowThread.cpp:
(WebCore::RenderFlowThread::regionInRange):
(WebCore):
(WebCore::RenderFlowThread::objectInFlowRegion):
* rendering/RenderFlowThread.h:
* rendering/RenderRegion.h:
(WebCore::RenderRegion::flowThread):

LayoutTests:

* fast/regions/get-regions-by-content-node-expected.txt: Added.
* fast/regions/get-regions-by-content-node-horiz-bt-expected.txt: Added.
* fast/regions/get-regions-by-content-node-horiz-bt.html: Added.
* fast/regions/get-regions-by-content-node-horiz-tb-expected.txt: Added.
* fast/regions/get-regions-by-content-node-horiz-tb.html: Added.
* fast/regions/get-regions-by-content-node-vert-lr-expected.txt: Added.
* fast/regions/get-regions-by-content-node-vert-lr.html: Added.
* fast/regions/get-regions-by-content-node-vert-rl-expected.txt: Added.
* fast/regions/get-regions-by-content-node-vert-rl.html: Added.
* fast/regions/get-regions-by-content-node.html: Added.
* fast/regions/get-regions-by-content-node2-expected.txt: Added.
* fast/regions/get-regions-by-content-node2.html: Added.

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

31 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/regions/get-regions-by-content-node-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-horiz-bt-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-horiz-bt.html [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-horiz-tb-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-horiz-tb.html [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-vert-lr-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-vert-lr.html [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-vert-rl-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node-vert-rl.html [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node.html [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node2-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/get-regions-by-content-node2.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/NodeRareData.h
Source/WebCore/dom/RegionNodeList.cpp [new file with mode: 0644]
Source/WebCore/dom/RegionNodeList.h [new file with mode: 0644]
Source/WebCore/dom/WebKitNamedFlow.cpp
Source/WebCore/dom/WebKitNamedFlow.h
Source/WebCore/dom/WebKitNamedFlow.idl
Source/WebCore/rendering/RenderFlowThread.cpp
Source/WebCore/rendering/RenderFlowThread.h
Source/WebCore/rendering/RenderRegion.h

index 590b9c8..6c1e2ca 100644 (file)
@@ -1,3 +1,23 @@
+2012-02-27  Mihnea Ovidenie  <mihnea@adobe.com>
+
+        [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+        https://bugs.webkit.org/show_bug.cgi?id=77746
+
+        Reviewed by David Hyatt.
+
+        * fast/regions/get-regions-by-content-node-expected.txt: Added.
+        * fast/regions/get-regions-by-content-node-horiz-bt-expected.txt: Added.
+        * fast/regions/get-regions-by-content-node-horiz-bt.html: Added.
+        * fast/regions/get-regions-by-content-node-horiz-tb-expected.txt: Added.
+        * fast/regions/get-regions-by-content-node-horiz-tb.html: Added.
+        * fast/regions/get-regions-by-content-node-vert-lr-expected.txt: Added.
+        * fast/regions/get-regions-by-content-node-vert-lr.html: Added.
+        * fast/regions/get-regions-by-content-node-vert-rl-expected.txt: Added.
+        * fast/regions/get-regions-by-content-node-vert-rl.html: Added.
+        * fast/regions/get-regions-by-content-node.html: Added.
+        * fast/regions/get-regions-by-content-node2-expected.txt: Added.
+        * fast/regions/get-regions-by-content-node2.html: Added.
+
 2012-02-27  Kenichi Ishibashi  <bashi@chromium.org>
 
         [Chromium] Unreviewed test expectaion update.
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-expected.txt b/LayoutTests/fast/regions/get-regions-by-content-node-expected.txt
new file mode 100644 (file)
index 0000000..3696b13
--- /dev/null
@@ -0,0 +1,15 @@
+Test for 77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+
+On success, you should see a series of PASS below.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
+
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-horiz-bt-expected.txt b/LayoutTests/fast/regions/get-regions-by-content-node-horiz-bt-expected.txt
new file mode 100644 (file)
index 0000000..5ddc201
--- /dev/null
@@ -0,0 +1,48 @@
+Test for 77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+
+On success, you should see a series of PASS below.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
+
+
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-horiz-bt.html b/LayoutTests/fast/regions/get-regions-by-content-node-horiz-bt.html
new file mode 100644 (file)
index 0000000..3c13b35
--- /dev/null
@@ -0,0 +1,171 @@
+<!doctype html>
+<html>
+    <head>
+        <link rel="stylesheet" href="resources/region-style.css">
+        <script src="resources/helper.js"></script>
+        <style>
+            html { -webkit-writing-mode: horizontal-bt; }
+            body { font-family: monospace; }
+            .regionBox { width: 250px; height: 50px; }
+            #article { -webkit-flow-into: flow; }
+            #region, #region2, #region3 { -webkit-flow-from: flow; }
+
+            #article2 { -webkit-flow-into: flow2; }
+            #region4, #region5 { -webkit-flow-from: flow2; }
+        </style>
+    </head>
+    <body>
+        <div id="containerMessage">
+            <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=77746">
+            77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode</a></p>
+            <p>On success, you should see a series of PASS below.</p>
+        </div>
+        <div id="console"></div>
+        <!-- some tests with inline elements -->
+        <div id="article">
+            <span id="spanNode">Text inside span.</span>
+            Text outside span. Text outside span. Text outside span.
+            <span id="spanNode2">Text inside span2.</span>
+            <span id="spanNode3">Text inside span3</span>
+        </div>
+        <div id="region" class="regionBox"></div>
+        <div id="region2" class="regionBox"></div>
+
+        <!-- some tests with block elements -->
+        <div id="article2">
+            <p id="p1">Text inside paragraph p1.</p>
+        </div>
+        <div id="region4" class="regionBox"></region>
+        <script>
+            if (window.layoutTestController)
+                window.layoutTestController.dumpAsText();
+            var namedFlow = document.webkitGetFlowByName("flow");
+
+            function hideRegions()
+            {
+                document.getElementById("article").style.visibility = "hidden";
+                document.getElementById("article2").style.visibility = "hidden";
+                document.getElementById("region").style.visibility = "hidden";
+                document.getElementById("region2").style.visibility = "hidden";
+                document.getElementById("region3").style.visibility = "hidden";
+                document.getElementById("region4").style.visibility = "hidden";
+                document.getElementById("region5").style.visibility = "hidden";
+            }
+
+            var regionListArticle = namedFlow.getRegionsByContentNode(document.getElementById("article"));
+            assert(regionListArticle != null, "Region list for article should not be null");
+            assert(regionListArticle.length == 2, "Region list for article should have 2 elements, has " + regionListArticle.length);
+            if (regionListArticle.length > 0)
+                assert(regionListArticle.item(0) == document.getElementById("region"), "First element in region list for article should be region, it is " + regionListArticle.item(0).id);
+            if (regionListArticle.length > 1)
+                assert(regionListArticle.item(1) == document.getElementById("region2"), "Second element in region list for article should be region2, it is " + regionListArticle.item(1).id);
+
+            var spanNode = document.getElementById("spanNode");
+            var regionListSpan = namedFlow.getRegionsByContentNode(spanNode);
+            assert(regionListSpan != null, "Region list for span should not be null");
+            assert(regionListSpan.length == 1, "Region list for span should have 1 element, has " + regionListSpan.length);
+            if (regionListSpan.length > 0)
+                assert(regionListSpan.item(0) == document.getElementById("region"), "First region for span should be region, it is " + regionListSpan.item(0).id);
+
+            var spanNode2 = document.getElementById("spanNode2");
+            var regionListSpan2 = namedFlow.getRegionsByContentNode(spanNode2);
+            assert(regionListSpan2 != null, "Region list for span2 should not be null");
+            assert(regionListSpan2.length == 2, "Region list for span2 should have 2 elements, has " + regionListSpan2.length);
+
+            var spanNode3 = document.getElementById("spanNode3");
+            var regionListSpan3 = namedFlow.getRegionsByContentNode(spanNode3);
+            assert(regionListSpan3 != null, "Region list for span3 should not be null");
+            assert(regionListSpan3.length == 1, "Region list for span3 should have 1 element, has " + regionListSpan3.length);
+            if (regionListSpan3.length > 0)
+                assert(regionListSpan3.item(0) == document.getElementById("region2"), "First region for span node 3 should be the second region, it is " + regionListSpan3.item(0).id);
+
+            var textNode = document.createTextNode("Text node. Text node. Text node. Text node. Text node. Text node. Text node. ");
+            document.getElementById("article").appendChild(textNode);
+            var regionListTextNode = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode != null, "Region list for text node should not be null");
+            assert(regionListTextNode.length == 1, "Region list for text node should have 1 element, has " + regionListTextNode.length);
+            if (regionListTextNode.length > 0)
+                assert(regionListTextNode.item(0) == document.getElementById("region2"), "First region for text node should be second region, it is " + regionListTextNode.item(0).id);
+
+            // Add another text node that will overflow the region2.
+            var textNode2 = document.createTextNode("Text node2.");
+            document.getElementById("article").appendChild(textNode2);
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode2);
+            assert(regionListTextNode2 != null, "Region list for text node 2 should not be null");
+            assert(regionListTextNode2.length == 1, "Region list for text node 2 should have 1 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node 2 should be second region, it is " + regionListTextNode2.item(0).id);
+
+            // Add another text node that is in the overflow of the last region.
+            var textNode3 = document.createTextNode("Text node3.");
+            document.getElementById("article").appendChild(textNode3);
+            var regionListTextNode3 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 != null, "Region list for text node 3 should not be null");
+            assert(regionListTextNode3.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode3.length > 0)
+                assert(regionListTextNode3.item(0) == document.getElementById("region2"), "First region for text node 3 should be second region, it is " + regionListTextNode3.item(0).id);
+
+            // Add another region to take the overflowing elements from second region.
+            var region3 = document.createElement("div");
+            region3.id = "region3";
+            region3.className = "regionBox";
+            document.body.appendChild(region3);
+
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode == regionListTextNode2, "Region lists for text node should reference the same object");
+            assert(regionListTextNode2.length == 2, "Region list for text node should have 2 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node should be the second region from flow, it is " + regionListTextNode2.item(0).id);
+            if (regionListTextNode2.length > 1)
+                assert(regionListTextNode2.item(1) == document.getElementById("region3"), "Second region for text node should be the third region from flow, it is " + regionListTextNode2.item(1).id);
+
+            var regionListTextNode32 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 == regionListTextNode32, "Region lists for text node 3 should reference the same object");
+            assert(regionListTextNode32.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode32.length > 0)
+                assert(regionListTextNode32.item(0) == document.getElementById("region3"), "First region for text node 3 should be the third region from flow, it is " + regionListTextNode32.item(0).id);
+
+            var namedFlow2 = document.webkitGetFlowByName("flow2");
+            var regionListP1 = namedFlow2.getRegionsByContentNode(document.getElementById("p1"));
+            assert(regionListP1 != null, "Region list for p1 node should not be null");
+            assert(regionListP1.length == 1, "Region list for p1 node should have 1 element, has " + regionListP1.length);
+            if (regionListP1.length > 0)
+                assert(regionListP1.item(0) == document.getElementById("region4"), "First region for p1 node should be region4, it is " + regionListP1.item(0).id);
+
+            var p2 = document.createElement("p");
+            p2.id = "p2";
+            p2.appendChild(document.createTextNode("Text inside paragraph p2."));
+            document.getElementById("article2").appendChild(p2);
+            var regionListP2 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 != null, "Region list for p2 node should not be null");
+            assert(regionListP2.length == 1, "Region list for p2 node should have 1 element, has " + regionListP2.length);
+            if (regionListP2.length > 0)
+                assert(regionListP2.item(0) == document.getElementById("region4"), "First region for p2 should be region4, it is " + regionListP2.item(0).id);
+            // add another element p, in the overflow part of the region4
+            var p3 = document.createElement("p");
+            p3.id = "p3";
+            p3.appendChild(document.createTextNode("Text inside paragraph p3."));
+            document.getElementById("article2").appendChild(p3);
+            var regionListP3 = namedFlow2.getRegionsByContentNode(p3);
+            assert(regionListP3 != null, "Region list for p3 node should not be null");
+            assert(regionListP3.length == 1, "Region list for p3 should have 1 element, has " + regionListP3.length);
+            if (regionListP3.length > 0)
+                assert(regionListP3.item(0) == document.getElementById("region4"), "First region for p3 should be region4, it is " + regionListP3.item(0).id);
+
+            // add another region to flow2, p2 and p3 go to region5
+            var region5 = document.createElement("div");
+            region5.id = "region5";
+            region5.className = "regionBox";
+            document.body.appendChild(region5);
+
+            var regionListP22 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 == regionListP22, "Region lists for p2 should refer the same region list");
+            assert(regionListP22.length == 1, "Region list for p2 should have 1 element, has " + regionListP2.length);
+            if (regionListP22.length > 0)
+                assert(regionListP22.item(0) == region5, "First region for p2 should be region5, it is " + regionListP2.item(0).id);
+
+            hideRegions();
+        </script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-horiz-tb-expected.txt b/LayoutTests/fast/regions/get-regions-by-content-node-horiz-tb-expected.txt
new file mode 100644 (file)
index 0000000..5ddc201
--- /dev/null
@@ -0,0 +1,48 @@
+Test for 77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+
+On success, you should see a series of PASS below.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
+
+
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-horiz-tb.html b/LayoutTests/fast/regions/get-regions-by-content-node-horiz-tb.html
new file mode 100644 (file)
index 0000000..030aa5e
--- /dev/null
@@ -0,0 +1,171 @@
+<!doctype html>
+<html>
+    <head>
+        <link rel="stylesheet" href="resources/region-style.css">
+        <script src="resources/helper.js"></script>
+        <style>
+            body { font-family: monospace; }
+            .regionBox { width: 250px; height: 50px; } 
+            #article { -webkit-flow-into: flow; }
+            #region, #region2, #region3 { -webkit-flow-from: flow; }
+
+            #article2 { -webkit-flow-into: flow2; }
+            #region4, #region5 { -webkit-flow-from: flow2; }
+        </style>
+    </head>
+    <body>
+        <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=77746">
+        77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode</a></p>
+        <p>On success, you should see a series of PASS below.</p>
+        <div id="console"></div>
+        <!-- some tests with inline elements -->
+        <div id="article">
+            <span id="spanNode">Text inside span.</span>
+            Text outside span. Text outside span. Text outside span.
+            <span id="spanNode2">Text inside span2.</span>
+            <span id="spanNode3">Text inside span3</span>
+        </div>
+        <div id="region" class="regionBox"></div>
+        <div id="region2" class="regionBox"></div>
+
+        <!-- some tests with block elements -->
+        <div id="article2">
+            <p id="p1">Text inside paragraph p1.</p>
+        </div>
+        <div id="region4" class="regionBox"></region>
+
+        <script>
+            if (window.layoutTestController)
+                window.layoutTestController.dumpAsText();
+
+            function hideRegions()
+            {
+                document.getElementById("article").style.visibility = "hidden";
+                document.getElementById("article2").style.visibility = "hidden";
+                document.getElementById("region").style.visibility = "hidden";
+                document.getElementById("region2").style.visibility = "hidden";
+                document.getElementById("region3").style.visibility = "hidden";
+                document.getElementById("region4").style.visibility = "hidden";
+                document.getElementById("region5").style.visibility = "hidden";
+            }
+
+            var namedFlow = document.webkitGetFlowByName("flow");
+
+            var regionListArticle = namedFlow.getRegionsByContentNode(document.getElementById("article"));
+            assert(regionListArticle != null, "Region list for article should not be null");
+            assert(regionListArticle.length == 2, "Region list for article should have 2 elements, has " + regionListArticle.length);
+            if (regionListArticle.length > 0)
+                assert(regionListArticle.item(0) == document.getElementById("region"), "First element in region list for article should be region, it is " + regionListArticle.item(0).id);
+            if (regionListArticle.length > 1)
+                assert(regionListArticle.item(1) == document.getElementById("region2"), "Second element in region list for article should be region2, it is " + regionListArticle.item(1).id);
+
+            var spanNode = document.getElementById("spanNode");
+            var regionListSpan = namedFlow.getRegionsByContentNode(spanNode);
+            assert(regionListSpan != null, "Region list for span should not be null");
+            assert(regionListSpan.length == 1, "Region list for span should have 1 element, has " + regionListSpan.length);
+            if (regionListSpan.length > 0)
+                assert(regionListSpan.item(0) == document.getElementById("region"), "First region for span should be region, it is " + regionListSpan.item(0).id);
+
+            var spanNode2 = document.getElementById("spanNode2");
+            var regionListSpan2 = namedFlow.getRegionsByContentNode(spanNode2);
+            assert(regionListSpan2 != null, "Region list for span2 should not be null");
+            assert(regionListSpan2.length == 2, "Region list for span2 should have 2 elements, has " + regionListSpan2.length);
+
+            var spanNode3 = document.getElementById("spanNode3");
+            var regionListSpan3 = namedFlow.getRegionsByContentNode(spanNode3);
+            assert(regionListSpan3 != null, "Region list for span3 should not be null");
+            assert(regionListSpan3.length == 1, "Region list for span3 should have 1 element, has " + regionListSpan3.length);
+            if (regionListSpan3.length > 0)
+                assert(regionListSpan3.item(0) == document.getElementById("region2"), "First region for span node 3 should be the second region, it is " + regionListSpan3.item(0).id);
+
+            var textNode = document.createTextNode("Text node. Text node. Text node. Text node. Text node. Text node. Text node. ");
+            document.getElementById("article").appendChild(textNode);
+            var regionListTextNode = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode != null, "Region list for text node should not be null");
+            assert(regionListTextNode.length == 1, "Region list for text node should have 1 element, has " + regionListTextNode.length);
+            if (regionListTextNode.length > 0)
+                assert(regionListTextNode.item(0) == document.getElementById("region2"), "First region for text node should be second region, it is " + regionListTextNode.item(0).id);
+
+            // Add another text node that will overflow the region2.
+            var textNode2 = document.createTextNode("Text node2.");
+            document.getElementById("article").appendChild(textNode2);
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode2);
+            assert(regionListTextNode2 != null, "Region list for text node 2 should not be null");
+            assert(regionListTextNode2.length == 1, "Region list for text node 2 should have 1 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node 2 should be second region, it is " + regionListTextNode2.item(0).id);
+
+            // Add another text node that is in the overflow of the last region.
+            var textNode3 = document.createTextNode("Text node3.");
+            document.getElementById("article").appendChild(textNode3);
+            var regionListTextNode3 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 != null, "Region list for text node 3 should not be null");
+            assert(regionListTextNode3.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode3.length > 0)
+                assert(regionListTextNode3.item(0) == document.getElementById("region2"), "First region for text node 3 should be second region, it is " + regionListTextNode3.item(0).id);
+
+            // Add another region to take the overflowing elements from second region.
+            var region3 = document.createElement("div");
+            region3.id = "region3";
+            region3.className = "regionBox";
+            document.body.appendChild(region3);
+
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode == regionListTextNode2, "Region lists for text node should reference the same object");
+            assert(regionListTextNode2.length == 2, "Region list for text node should have 2 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node should be the second region from flow, it is " + regionListTextNode2.item(0).id);
+            if (regionListTextNode2.length > 1)
+                assert(regionListTextNode2.item(1) == document.getElementById("region3"), "Second region for text node should be the third region from flow, it is " + regionListTextNode2.item(1).id);
+
+            var regionListTextNode32 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 == regionListTextNode32, "Region lists for text node 3 should reference the same object");
+            assert(regionListTextNode32.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode32.length > 0)
+                assert(regionListTextNode32.item(0) == document.getElementById("region3"), "First region for text node 3 should be the third region from flow, it is " + regionListTextNode32.item(0).id);
+
+            var namedFlow2 = document.webkitGetFlowByName("flow2");
+            var regionListP1 = namedFlow2.getRegionsByContentNode(document.getElementById("p1"));
+            assert(regionListP1 != null, "Region list for p1 node should not be null");
+            assert(regionListP1.length == 1, "Region list for p1 node should have 1 element, has " + regionListP1.length);
+            if (regionListP1.length > 0)
+                assert(regionListP1.item(0) == document.getElementById("region4"), "First region for p1 node should be region4, it is " + regionListP1.item(0).id);
+
+            var p2 = document.createElement("p");
+            p2.id = "p2";
+            p2.appendChild(document.createTextNode("Text inside paragraph p2."));
+            document.getElementById("article2").appendChild(p2);
+            var regionListP2 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 != null, "Region list for p2 node should not be null");
+            assert(regionListP2.length == 1, "Region list for p2 node should have 1 element, has " + regionListP2.length);
+            if (regionListP2.length > 0)
+                assert(regionListP2.item(0) == document.getElementById("region4"), "First region for p2 should be region4, it is " + regionListP2.item(0).id);
+            // add another element p, in the overflow part of the region4
+            var p3 = document.createElement("p");
+            p3.id = "p3";
+            p3.appendChild(document.createTextNode("Text inside paragraph p3."));
+            document.getElementById("article2").appendChild(p3);
+            var regionListP3 = namedFlow2.getRegionsByContentNode(p3);
+            assert(regionListP3 != null, "Region list for p3 node should not be null");
+            assert(regionListP3.length == 1, "Region list for p3 should have 1 element, has " + regionListP3.length);
+            if (regionListP3.length > 0)
+                assert(regionListP3.item(0) == document.getElementById("region4"), "First region for p3 should be region4, it is " + regionListP3.item(0).id);
+
+            // add another region to flow2, p2 and p3 go to region5
+            var region5 = document.createElement("div");
+            region5.id = "region5";
+            region5.className = "regionBox";
+            document.body.appendChild(region5);
+
+            var regionListP22 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 == regionListP22, "Region lists for p2 should refer the same region list");
+            assert(regionListP22.length == 1, "Region list for p2 should have 1 element, has " + regionListP2.length);
+            if (regionListP22.length > 0)
+                assert(regionListP22.item(0) == region5, "First region for p2 should be region5, it is " + regionListP2.item(0).id);
+
+            hideRegions();
+        </script>
+    </body>
+</html>
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-vert-lr-expected.txt b/LayoutTests/fast/regions/get-regions-by-content-node-vert-lr-expected.txt
new file mode 100644 (file)
index 0000000..5ddc201
--- /dev/null
@@ -0,0 +1,48 @@
+Test for 77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+
+On success, you should see a series of PASS below.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
+
+
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-vert-lr.html b/LayoutTests/fast/regions/get-regions-by-content-node-vert-lr.html
new file mode 100644 (file)
index 0000000..e43944d
--- /dev/null
@@ -0,0 +1,172 @@
+<!doctype html>
+<html>
+    <head>
+        <link rel="stylesheet" href="resources/region-style.css">
+        <script src="resources/helper.js"></script>
+        <style>
+            html { -webkit-writing-mode: vertical-lr; }
+            body { font-family: monospace; }
+            .regionBox {  height: 250px; width: 50px; }
+
+            #article { -webkit-flow-into: flow; }
+            #region, #region2, #region3 { -webkit-flow-from: flow; }
+
+            #article2 { -webkit-flow-into: flow2; }
+            #region4, #region5 { -webkit-flow-from: flow2; }
+        </style>
+    </head>
+    <body>
+        <div id="containerMessage">
+            <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=77746">
+            77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode</a></p>
+            <p>On success, you should see a series of PASS below.</p>
+        </div>
+        <div id="console"></div>
+        <!-- some tests with inline elements -->
+        <div id="article">
+            <span id="spanNode">Text inside span.</span>
+            Text outside span. Text outside span. Text outside span.
+            <span id="spanNode2">Text inside span2. Text.</span>
+            <span id="spanNode3">Text inside span3</span>
+        </div>
+        <div id="region" class="regionBox"></div>
+        <div id="region2" class="regionBox"></div>
+
+        <!-- some tests with block elements -->
+        <div id="article2">
+            <p id="p1">Text inside paragraph p1.</p>
+        </div>
+        <div id="region4" class="regionBox"></region>
+        <script>
+            if (window.layoutTestController)
+                window.layoutTestController.dumpAsText();
+            var namedFlow = document.webkitGetFlowByName("flow");
+
+            function hideRegions()
+            {
+                document.getElementById("article").style.visibility = "hidden";
+                document.getElementById("article2").style.visibility = "hidden";
+                document.getElementById("region").style.visibility = "hidden";
+                document.getElementById("region2").style.visibility = "hidden";
+                document.getElementById("region3").style.visibility = "hidden";
+                document.getElementById("region4").style.visibility = "hidden";
+                document.getElementById("region5").style.visibility = "hidden";
+            }
+
+            var regionListArticle = namedFlow.getRegionsByContentNode(document.getElementById("article"));
+            assert(regionListArticle != null, "Region list for article should not be null");
+            assert(regionListArticle.length == 2, "Region list for article should have 2 elements, has " + regionListArticle.length);
+            if (regionListArticle.length > 0)
+                assert(regionListArticle.item(0) == document.getElementById("region"), "First element in region list for article should be region, it is " + regionListArticle.item(0).id);
+            if (regionListArticle.length > 1)
+                assert(regionListArticle.item(1) == document.getElementById("region2"), "Second element in region list for article should be region2, it is " + regionListArticle.item(1).id);
+
+            var spanNode = document.getElementById("spanNode");
+            var regionListSpan = namedFlow.getRegionsByContentNode(spanNode);
+            assert(regionListSpan != null, "Region list for span should not be null");
+            assert(regionListSpan.length == 1, "Region list for span should have 1 element, has " + regionListSpan.length);
+            if (regionListSpan.length > 0)
+                assert(regionListSpan.item(0) == document.getElementById("region"), "First region for span should be region, it is " + regionListSpan.item(0).id);
+
+            var spanNode2 = document.getElementById("spanNode2");
+            var regionListSpan2 = namedFlow.getRegionsByContentNode(spanNode2);
+            assert(regionListSpan2 != null, "Region list for span2 should not be null");
+            assert(regionListSpan2.length == 2, "Region list for span2 should have 2 elements, has " + regionListSpan2.length);
+
+            var spanNode3 = document.getElementById("spanNode3");
+            var regionListSpan3 = namedFlow.getRegionsByContentNode(spanNode3);
+            assert(regionListSpan3 != null, "Region list for span3 should not be null");
+            assert(regionListSpan3.length == 1, "Region list for span3 should have 1 element, has " + regionListSpan3.length);
+            if (regionListSpan3.length > 0)
+                assert(regionListSpan3.item(0) == document.getElementById("region2"), "First region for span node 3 should be the second region, it is " + regionListSpan3.item(0).id);
+
+            var textNode = document.createTextNode("Text node. Text node. Text node. Text node. Text node. Text node. Text node. ");
+            document.getElementById("article").appendChild(textNode);
+            var regionListTextNode = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode != null, "Region list for text node should not be null");
+            assert(regionListTextNode.length == 1, "Region list for text node should have 1 element, has " + regionListTextNode.length);
+            if (regionListTextNode.length > 0)
+                assert(regionListTextNode.item(0) == document.getElementById("region2"), "First region for text node should be second region, it is " + regionListTextNode.item(0).id);
+
+            // Add another text node that will overflow the region2.
+            var textNode2 = document.createTextNode("Text node2.");
+            document.getElementById("article").appendChild(textNode2);
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode2);
+            assert(regionListTextNode2 != null, "Region list for text node 2 should not be null");
+            assert(regionListTextNode2.length == 1, "Region list for text node 2 should have 1 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node 2 should be second region, it is " + regionListTextNode2.item(0).id);
+
+            // Add another text node that is in the overflow of the last region.
+            var textNode3 = document.createTextNode("Text node3.");
+            document.getElementById("article").appendChild(textNode3);
+            var regionListTextNode3 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 != null, "Region list for text node 3 should not be null");
+            assert(regionListTextNode3.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode3.length > 0)
+                assert(regionListTextNode3.item(0) == document.getElementById("region2"), "First region for text node 3 should be second region, it is " + regionListTextNode3.item(0).id);
+
+            // Add another region to take the overflowing elements from second region.
+            var region3 = document.createElement("div");
+            region3.id = "region3";
+            region3.className = "regionBox";
+            document.body.appendChild(region3);
+
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode == regionListTextNode2, "Region lists for text node should reference the same object");
+            assert(regionListTextNode2.length == 2, "Region list for text node should have 2 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node should be the second region from flow, it is " + regionListTextNode2.item(0).id);
+            if (regionListTextNode2.length > 1)
+                assert(regionListTextNode2.item(1) == document.getElementById("region3"), "Second region for text node should be the third region from flow, it is " + regionListTextNode2.item(1).id);
+
+            var regionListTextNode32 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 == regionListTextNode32, "Region lists for text node 3 should reference the same object");
+            assert(regionListTextNode32.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode32.length > 0)
+                assert(regionListTextNode32.item(0) == document.getElementById("region3"), "First region for text node 3 should be the third region from flow, it is " + regionListTextNode32.item(0).id);
+
+            var namedFlow2 = document.webkitGetFlowByName("flow2");
+            var regionListP1 = namedFlow2.getRegionsByContentNode(document.getElementById("p1"));
+            assert(regionListP1 != null, "Region list for p1 node should not be null");
+            assert(regionListP1.length == 1, "Region list for p1 node should have 1 element, has " + regionListP1.length);
+            if (regionListP1.length > 0)
+                assert(regionListP1.item(0) == document.getElementById("region4"), "First region for p1 node should be region4, it is " + regionListP1.item(0).id);
+
+            var p2 = document.createElement("p");
+            p2.id = "p2";
+            p2.appendChild(document.createTextNode("Text inside paragraph p2."));
+            document.getElementById("article2").appendChild(p2);
+            var regionListP2 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 != null, "Region list for p2 node should not be null");
+            assert(regionListP2.length == 1, "Region list for p2 node should have 1 element, has " + regionListP2.length);
+            if (regionListP2.length > 0)
+                assert(regionListP2.item(0) == document.getElementById("region4"), "First region for p2 should be region4, it is " + regionListP2.item(0).id);
+            // add another element p, in the overflow part of the region4
+            var p3 = document.createElement("p");
+            p3.id = "p3";
+            p3.appendChild(document.createTextNode("Text inside paragraph p3."));
+            document.getElementById("article2").appendChild(p3);
+            var regionListP3 = namedFlow2.getRegionsByContentNode(p3);
+            assert(regionListP3 != null, "Region list for p3 node should not be null");
+            assert(regionListP3.length == 1, "Region list for p3 should have 1 element, has " + regionListP3.length);
+            if (regionListP3.length > 0)
+                assert(regionListP3.item(0) == document.getElementById("region4"), "First region for p3 should be region4, it is " + regionListP3.item(0).id);
+
+            // add another region to flow2, p2 and p3 go to region5
+            var region5 = document.createElement("div");
+            region5.id = "region5";
+            region5.className = "regionBox";
+            document.body.appendChild(region5);
+
+            var regionListP22 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 == regionListP22, "Region lists for p2 should refer the same region list");
+            assert(regionListP22.length == 1, "Region list for p2 should have 1 element, has " + regionListP2.length);
+            if (regionListP22.length > 0)
+                assert(regionListP22.item(0) == region5, "First region for p2 should be region5, it is " + regionListP2.item(0).id);
+
+            hideRegions();
+        </script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-vert-rl-expected.txt b/LayoutTests/fast/regions/get-regions-by-content-node-vert-rl-expected.txt
new file mode 100644 (file)
index 0000000..5ddc201
--- /dev/null
@@ -0,0 +1,48 @@
+Test for 77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+
+On success, you should see a series of PASS below.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
+
+
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node-vert-rl.html b/LayoutTests/fast/regions/get-regions-by-content-node-vert-rl.html
new file mode 100644 (file)
index 0000000..a0f7702
--- /dev/null
@@ -0,0 +1,172 @@
+<!doctype html>
+<html>
+    <head>
+        <link rel="stylesheet" href="resources/region-style.css">
+        <script src="resources/helper.js"></script>
+        <style>
+            html { -webkit-writing-mode: vertical-rl; }
+            body { font-family: monospace; }
+            .regionBox {  height: 250px; width: 50px; }
+            #article { -webkit-flow-into: flow; }
+            #region, #region2, #region3 { -webkit-flow-from: flow; }
+
+            #article2 { -webkit-flow-into: flow2; }
+            #region4, #region5 { -webkit-flow-from: flow2; }
+        </style>
+    </head>
+    <body>
+        <div id="containerMessage">
+            <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=77746">
+            77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode</a></p>
+            <p>On success, you should see a series of PASS below.</p>
+        </div>
+        <div id="console"></div>
+        <!-- some tests with inline elements -->
+        <div id="article">
+            <span id="spanNode">Text inside span.</span>
+            Text outside span. Text outside span. Text outside span.
+            <span id="spanNode2">Text inside span2. Text.</span>
+            <span id="spanNode3">Text inside span3</span>
+        </div>
+        <div id="region" class="regionBox"></div>
+        <div id="region2" class="regionBox"></div>
+
+        <!-- some tests with block elements -->
+        <div id="article2">
+            <p id="p1">Text inside paragraph p1.</p>
+        </div>
+        <div id="region4" class="regionBox"></region>
+        <script>
+            if (window.layoutTestController)
+                window.layoutTestController.dumpAsText();
+            var namedFlow = document.webkitGetFlowByName("flow");
+
+            function hideRegions()
+            {
+                document.getElementById("article").style.visibility = "hidden";
+                document.getElementById("article2").style.visibility = "hidden";
+                document.getElementById("region").style.visibility = "hidden";
+                document.getElementById("region2").style.visibility = "hidden";
+                document.getElementById("region3").style.visibility = "hidden";
+                document.getElementById("region4").style.visibility = "hidden";
+                document.getElementById("region5").style.visibility = "hidden";
+            }
+
+            var regionListArticle = namedFlow.getRegionsByContentNode(document.getElementById("article"));
+            assert(regionListArticle != null, "Region list for article should not be null");
+            assert(regionListArticle.length == 2, "Region list for article should have 2 elements, has " + regionListArticle.length);
+            if (regionListArticle.length > 0)
+                assert(regionListArticle.item(0) == document.getElementById("region"), "First element in region list for article should be region, it is " + regionListArticle.item(0).id);
+            if (regionListArticle.length > 1)
+                assert(regionListArticle.item(1) == document.getElementById("region2"), "Second element in region list for article should be region2, it is " + regionListArticle.item(1).id);
+
+            var spanNode = document.getElementById("spanNode");
+            var regionListSpan = namedFlow.getRegionsByContentNode(spanNode);
+            assert(regionListSpan != null, "Region list for span should not be null");
+            assert(regionListSpan.length == 1, "Region list for span should have 1 element, has " + regionListSpan.length);
+            if (regionListSpan.length > 0)
+                assert(regionListSpan.item(0) == document.getElementById("region"), "First region for span should be region, it is " + regionListSpan.item(0).id);
+
+            var spanNode2 = document.getElementById("spanNode2");
+            var regionListSpan2 = namedFlow.getRegionsByContentNode(spanNode2);
+            assert(regionListSpan2 != null, "Region list for span2 should not be null");
+            assert(regionListSpan2.length == 2, "Region list for span2 should have 2 elements, has " + regionListSpan2.length);
+
+            var spanNode3 = document.getElementById("spanNode3");
+            var regionListSpan3 = namedFlow.getRegionsByContentNode(spanNode3);
+            assert(regionListSpan3 != null, "Region list for span3 should not be null");
+            assert(regionListSpan3.length == 1, "Region list for span3 should have 1 element, has " + regionListSpan3.length);
+            if (regionListSpan3.length > 0)
+                assert(regionListSpan3.item(0) == document.getElementById("region2"), "First region for span node 3 should be the second region, it is " + regionListSpan3.item(0).id);
+
+            var textNode = document.createTextNode("Text node. Text node. Text node. Text node. Text node. Text node. Text node. ");
+            document.getElementById("article").appendChild(textNode);
+            var regionListTextNode = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode != null, "Region list for text node should not be null");
+            assert(regionListTextNode.length == 1, "Region list for text node should have 1 element, has " + regionListTextNode.length);
+            if (regionListTextNode.length > 0)
+                assert(regionListTextNode.item(0) == document.getElementById("region2"), "First region for text node should be second region, it is " + regionListTextNode.item(0).id);
+
+            // Add another text node that will overflow the region2.
+            var textNode2 = document.createTextNode("Text node2.");
+            document.getElementById("article").appendChild(textNode2);
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode2);
+            assert(regionListTextNode2 != null, "Region list for text node 2 should not be null");
+            assert(regionListTextNode2.length == 1, "Region list for text node 2 should have 1 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node 2 should be second region, it is " + regionListTextNode2.item(0).id);
+
+            // Add another text node that is in the overflow of the last region.
+            var textNode3 = document.createTextNode("Text node3.");
+            document.getElementById("article").appendChild(textNode3);
+            var regionListTextNode3 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 != null, "Region list for text node 3 should not be null");
+            assert(regionListTextNode3.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode3.length > 0)
+                assert(regionListTextNode3.item(0) == document.getElementById("region2"), "First region for text node 3 should be second region, it is " + regionListTextNode3.item(0).id);
+
+            // Add another region to take the overflowing elements from second region.
+            var region3 = document.createElement("div");
+            region3.id = "region3";
+            region3.className = "regionBox";
+            document.body.appendChild(region3);
+
+            var regionListTextNode2 = namedFlow.getRegionsByContentNode(textNode);
+            assert(regionListTextNode == regionListTextNode2, "Region lists for text node should reference the same object");
+            assert(regionListTextNode2.length == 2, "Region list for text node should have 2 element, has " + regionListTextNode2.length);
+            if (regionListTextNode2.length > 0)
+                assert(regionListTextNode2.item(0) == document.getElementById("region2"), "First region for text node should be the second region from flow, it is " + regionListTextNode2.item(0).id);
+            if (regionListTextNode2.length > 1)
+                assert(regionListTextNode2.item(1) == document.getElementById("region3"), "Second region for text node should be the third region from flow, it is " + regionListTextNode2.item(1).id);
+
+            var regionListTextNode32 = namedFlow.getRegionsByContentNode(textNode3);
+            assert(regionListTextNode3 == regionListTextNode32, "Region lists for text node 3 should reference the same object");
+            assert(regionListTextNode32.length == 1, "Region list for text node 3 should have 1 element, has " + regionListTextNode3.length);
+            if (regionListTextNode32.length > 0)
+                assert(regionListTextNode32.item(0) == document.getElementById("region3"), "First region for text node 3 should be the third region from flow, it is " + regionListTextNode32.item(0).id);
+
+            var namedFlow2 = document.webkitGetFlowByName("flow2");
+            var regionListP1 = namedFlow2.getRegionsByContentNode(document.getElementById("p1"));
+            assert(regionListP1 != null, "Region list for p1 node should not be null");
+            assert(regionListP1.length == 1, "Region list for p1 node should have 1 element, has " + regionListP1.length);
+            if (regionListP1.length > 0)
+                assert(regionListP1.item(0) == document.getElementById("region4"), "First region for p1 node should be region4, it is " + regionListP1.item(0).id);
+
+            var p2 = document.createElement("p");
+            p2.id = "p2";
+            p2.appendChild(document.createTextNode("Text inside paragraph p2."));
+            document.getElementById("article2").appendChild(p2);
+            var regionListP2 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 != null, "Region list for p2 node should not be null");
+            assert(regionListP2.length == 1, "Region list for p2 node should have 1 element, has " + regionListP2.length);
+            if (regionListP2.length > 0)
+                assert(regionListP2.item(0) == document.getElementById("region4"), "First region for p2 should be region4, it is " + regionListP2.item(0).id);
+            // add another element p, in the overflow part of the region4
+            var p3 = document.createElement("p");
+            p3.id = "p3";
+            p3.appendChild(document.createTextNode("Text inside paragraph p3."));
+            document.getElementById("article2").appendChild(p3);
+            var regionListP3 = namedFlow2.getRegionsByContentNode(p3);
+            assert(regionListP3 != null, "Region list for p3 node should not be null");
+            assert(regionListP3.length == 1, "Region list for p3 should have 1 element, has " + regionListP3.length);
+            if (regionListP3.length > 0)
+                assert(regionListP3.item(0) == document.getElementById("region4"), "First region for p3 should be region4, it is " + regionListP3.item(0).id);
+
+            // add another region to flow2, p2 and p3 go to region5
+            var region5 = document.createElement("div");
+            region5.id = "region5";
+            region5.className = "regionBox";
+            document.body.appendChild(region5);
+
+            var regionListP22 = namedFlow2.getRegionsByContentNode(p2);
+            assert(regionListP2 == regionListP22, "Region lists for p2 should refer the same region list");
+            assert(regionListP22.length == 1, "Region list for p2 should have 1 element, has " + regionListP2.length);
+            if (regionListP22.length > 0)
+                assert(regionListP22.item(0) == region5, "First region for p2 should be region5, it is " + regionListP2.item(0).id);
+
+            hideRegions();
+        </script>
+    </body>
+</html>
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node.html b/LayoutTests/fast/regions/get-regions-by-content-node.html
new file mode 100644 (file)
index 0000000..1e2a722
--- /dev/null
@@ -0,0 +1,89 @@
+<!doctype html>
+<html>
+    <head>
+        <link rel="stylesheet" href="resources/region-style.css">
+        <script src="resources/helper.js"></script>
+        <style>
+            body { font-family: monospace; }
+            #article { -webkit-flow-into: flow; }
+            .border { border: 1px solid red; }
+            #region { -webkit-flow-from: flow; width: 250px; height: 50px; position: absolute; left: 10px; top: 200px; }
+
+            #article2 { -webkit-flow-into: flow2; }
+            #region21 { -webkit-flow-from: flow2; width: 250px; height: 50px; position: absolute; left: 20px; top: 300px;}
+            #region22 { -webkit-flow-from: flow2; width: 250px; height: 50px; position: absolute; left: 20px; top: 350px;}
+        </style>
+    </head>
+    <body>
+        <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=77746">
+        77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode</a></p>
+        <p>On success, you should see a series of PASS below.</p>
+
+        <div id="console"></div>
+        <div id="article">
+            <p id="p1">Text flown into region.</p>
+        </div>
+        <div id="region" class="border"></div>
+
+        <div id="article2">
+            <p id="p2">Text flown in two regions. Text flown in two regions. Text flown in two regions.</p>
+        </div>
+        <div id="region21" class="border"></div>
+        <div id="region22" class="border"></div>
+        <script>
+            if (window.layoutTestController)
+                layoutTestController.dumpAsText();
+
+            var namedFlow1 = document.webkitGetFlowByName("flow");
+            var p1RegionsInFlow1 = namedFlow1.getRegionsByContentNode(document.getElementById("p1"));
+            var namedFlow2 = document.webkitGetFlowByName("flow2");
+            var p2RegionsInFlow2 = namedFlow2.getRegionsByContentNode(document.getElementById("p2"));
+
+            function testGetRegionsByContentNode1()
+            {
+                var namedFlow = document.webkitGetFlowByName("flow");
+                var targetNode = document.getElementById("p1");
+                var regionsList = namedFlow.getRegionsByContentNode(targetNode);
+
+                assert(regionsList == p1RegionsInFlow1, "Region list for p1 in flow1 should be a live object");
+                assert(regionsList.length == 1, "The region list count should be 1, it is " + regionsList.length);
+                if (regionsList.length > 0)
+                    assert(regionsList.item(0) == document.getElementById("region"), "First region for p1 should be region, it is " + regionsList.item(0).id);
+            }
+
+            function testGetRegionsByContentNode2()
+            {
+                var namedFlow = document.webkitGetFlowByName("flow2");
+
+                // Test that the p2 element is flown into 2 regions
+                var targetNode = document.getElementById("p2");
+                var regionList = namedFlow.getRegionsByContentNode(targetNode);
+
+                assert(regionList == p2RegionsInFlow2, "Region list for p2 in flow2 should be a live object");
+                assert(regionList.length == 2, "The region list count should be 2, it is " + regionList.length);
+                if (regionList.length > 0)
+                    assert(regionList.item(0) == document.getElementById("region21"), "First region for p2 should be region21, it is " + regionList.item(0).id);
+                if (regionList.length > 1)
+                    assert(regionList.item(1) == document.getElementById("region22"), "First region for p2 should be region22, it is " + regionList.item(1).id);
+
+                // Test that p1 element is not in flow2
+                targetNode = document.getElementById("p1");
+                regionList = namedFlow.getRegionsByContentNode(targetNode);
+                assert(regionList.length == 0, "The region list count should be 0, it is " + regionList.length);
+            }
+
+            function hideRegionsAndFlows() {
+                document.getElementById("article").style.visibility = "hidden";
+                document.getElementById("article2").style.visibility = "hidden";
+                document.getElementById("region").style.visibility = "hidden";
+                document.getElementById("region21").style.visibility = "hidden";
+                document.getElementById("region22").style.visibility = "hidden";
+            }
+
+            testGetRegionsByContentNode1();
+            testGetRegionsByContentNode2();
+
+            hideRegionsAndFlows();
+        </script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node2-expected.txt b/LayoutTests/fast/regions/get-regions-by-content-node2-expected.txt
new file mode 100644 (file)
index 0000000..ccb5692
--- /dev/null
@@ -0,0 +1,32 @@
+Test for 77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+
+On success, you should see a series of PASS below.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
diff --git a/LayoutTests/fast/regions/get-regions-by-content-node2.html b/LayoutTests/fast/regions/get-regions-by-content-node2.html
new file mode 100644 (file)
index 0000000..669a893
--- /dev/null
@@ -0,0 +1,102 @@
+<!doctype html>
+<html>
+    <head>
+        <link rel="stylesheet" href="resources/region-style.css">
+        <script src="resources/helper.js"></script>
+        <style>
+            body { font-family: monospace; }
+            #region, #region2 { width: 250px; height: 50px; }
+            .article { -webkit-flow-into: flow; }
+            .article2 { -webkit-flow-into: flow2; }
+            .region { -webkit-flow-from: flow; }
+            .region2 { -webkit-flow-from: flow2; }
+            .noRegion { -webkit-flow-from: none; }
+        </style>
+    </head>
+    <body>
+        <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=77746">
+        77746: [CSSRegions]Implement NamedFlow::getRegionsByContentNode</a></p>
+        <p>On success, you should see a series of PASS below.</p>
+        <div id="console"></div>
+        <div id="article" class="article"></div>
+        <div id="region" class="region"></div>
+        <div id="region2"></div>
+        <script>
+            if (window.layoutTestController)
+                layoutTestController.dumpAsText();
+
+            var namedFlow = document.webkitGetFlowByName("flow");
+
+            // Getting the regions for a non existant node should return null.
+            var pElement;
+            var regionList = namedFlow.getRegionsByContentNode(pElement);
+            assert(regionList == null, "Region list for a non-existant node should return null");
+
+            // Getting the regions for an element that was not added to the dom should return an empty list.
+            pElement = document.createElement("p");
+
+            var regionList2 = namedFlow.getRegionsByContentNode(pElement);
+            assert(regionList2 != null, "Region list 2 should not be null");
+            assert(regionList2.length == 0, "Region list 2 should be empty, has " + regionList2.length + " elements.");
+            assert(regionList != regionList2, "Region lists should be different");
+
+            // Add the element to the dom but not in the flow. The region list should be empty.
+            document.body.appendChild(pElement);
+            var regionList3 = namedFlow.getRegionsByContentNode(pElement);
+            assert(regionList3 != null, "Region list 3 should not be null");
+            assert(regionList3.length == 0, "Region list 3 should be empty, has " + regionList3.length + " elements.");
+            assert(regionList2 == regionList3, "Regions list 2 and 3 should refer the same NodeList object");
+
+            // Add the same element to the flow. The region list should contain one region.
+            document.body.removeChild(pElement);
+            document.getElementById("article").appendChild(pElement);
+            var regionList4 = namedFlow.getRegionsByContentNode(pElement);
+            assert(regionList4 != null, "Region list 4 for node in flow should not be null");
+            assert(regionList4.length == 1, "Region list 4 for node in flow should have 1 region, has " + regionList4.length + " elements");
+            if (regionList4.length > 0)
+                assert(regionList4.item(0) == document.getElementById("region"), "First element in region list 4 should be the first region, it is " + regionList4.item(0).id);
+            assert(regionList4 == regionList3, "Regions list 3 and 4 should refer the same NodeList object");
+
+            // Remove the region node and get the region list. The list should be empty.
+            document.getElementById("region").className = "noRegion";
+            var regionList5 = namedFlow.getRegionsByContentNode(pElement);
+            assert(regionList5 != null, "Region list 5 should not be null");
+            assert(regionList5.length == 0, "Region list 5 should be empty, has " + regionList5.length + " elements");
+            assert(regionList5 == regionList4, "Regions list 4 and 5 should refer the same NodeList object");
+
+            // Bring back the region and get the region list. The list should have one element.
+            document.getElementById("region").className = "region";
+            var regionList6 = namedFlow.getRegionsByContentNode(pElement);
+            assert(regionList6 != null, "Region list 6 should not be null");
+            assert(regionList6.length == 1, "Region list 6 should have 1 region, has " + regionList6.length + " elements");
+            if (regionList6.length > 0)
+                assert(regionList6.item(0) == document.getElementById("region"), "First element in region list 6 should be the first region, it is " + regionList6.item(0).id);
+            assert(regionList6 == regionList5, "Region list 5 and 6 should refer the same NodeList object");
+
+            // Remove the named flow, the region list should be empty.
+            document.getElementById("article").className = "";
+            var regionList7 = namedFlow.getRegionsByContentNode(pElement);
+            assert(regionList7 != null, "Region list 7 should not be null");
+            assert(regionList7.length == 0, "Region list 7 should be empty, it has " + regionList7.length + " elements");
+            assert(regionList7 == regionList6, "Region list 6 and 7 should refer the same NodeList object");
+
+            // Move the article to another named flow, the region list should be empty.
+            document.getElementById("article").className = "article2";
+            var namedFlow2 = document.webkitGetFlowByName("flow2");
+            var regionList8 = namedFlow2.getRegionsByContentNode(pElement);
+            assert(regionList8 != null, "Region list 8 should not be null");
+            assert(regionList8.length == 0, "Region list 8 should be empty, it has " + regionList8.length + " elements");
+            assert(regionList8 != regionList7, "Region list 7 and 8 should refer different NodeList objects");
+
+            // Add a region to the second named flow, the region list should contain one element
+            // since the p element is a child of article that is collected by flow2.
+            document.getElementById("region2").className = "region2";
+            var regionList9 = namedFlow2.getRegionsByContentNode(pElement);
+            assert(regionList9 != null, "Region list 9 should not be null");
+            assert(regionList9.length == 1, "Region list 9 should have 1 element, it has " + regionList9.length + " elements");
+            if (regionList9.length > 0)
+                assert(regionList9 == regionList8, "Region list 8 and 9 should refere the same NodeList object");
+        </script>
+    </body>
+</html>
+
index e17c8a3..dcd6d1e 100644 (file)
@@ -606,6 +606,7 @@ SET(WebCore_SOURCES
     dom/QualifiedName.cpp
     dom/Range.cpp
     dom/RangeException.cpp
+    dom/RegionNodeList.cpp
     dom/RegisteredEventListener.cpp
     dom/ScopedEventQueue.cpp
     dom/ScriptableDocumentParser.cpp
index 855ec21..7c48d57 100644 (file)
@@ -1,3 +1,58 @@
+2012-02-27  Mihnea Ovidenie  <mihnea@adobe.com>
+
+        [CSSRegions]Implement NamedFlow::getRegionsByContentNode
+        https://bugs.webkit.org/show_bug.cgi?id=77746
+
+        Reviewed by David Hyatt.
+
+        Tests: fast/regions/get-regions-by-content-node-horiz-bt.html
+               fast/regions/get-regions-by-content-node-horiz-tb.html
+               fast/regions/get-regions-by-content-node-vert-lr.html
+               fast/regions/get-regions-by-content-node-vert-rl.html
+               fast/regions/get-regions-by-content-node.html
+               fast/regions/get-regions-by-content-node2.html
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Node.cpp:
+        (WebCore::Node::removeCachedRegionNodeList):
+        (WebCore):
+        (WebCore::Node::getRegionsByContentNode):
+        (WebCore::NodeListsNodeData::invalidateCaches):
+        (WebCore::NodeListsNodeData::isEmpty):
+        * dom/Node.h:
+        (WebCore):
+        (Node):
+        * dom/NodeRareData.h:
+        (NodeListsNodeData):
+        * dom/RegionNodeList.cpp:
+        (WebCore):
+        (WebCore::RegionNodeList::RegionNodeList):
+        (WebCore::RegionNodeList::~RegionNodeList):
+        (WebCore::RegionNodeList::nodeMatches):
+        * dom/RegionNodeList.h:
+        (WebCore):
+        (RegionNodeList):
+        (WebCore::RegionNodeList::create):
+        * dom/WebKitNamedFlow.cpp:
+        (WebCore::WebKitNamedFlow::getRegionsByContentNode):
+        (WebCore):
+        * dom/WebKitNamedFlow.h:
+        (WebCore):
+        (WebKitNamedFlow):
+        * dom/WebKitNamedFlow.idl:
+        * rendering/RenderFlowThread.cpp:
+        (WebCore::RenderFlowThread::regionInRange):
+        (WebCore):
+        (WebCore::RenderFlowThread::objectInFlowRegion):
+        * rendering/RenderFlowThread.h:
+        * rendering/RenderRegion.h:
+        (WebCore::RenderRegion::flowThread):
+
 2012-02-27  Yury Semikhatsky  <yurys@chromium.org>
 
         Web Inspector: counter graphs should resize after console showing
index aae777c..dd3db01 100644 (file)
@@ -1719,6 +1719,8 @@ webcore_sources += \
        Source/WebCore/dom/RangeException.h \
        Source/WebCore/dom/Range.h \
        Source/WebCore/dom/RawDataDocumentParser.h \
+       Source/WebCore/dom/RegionNodeList.cpp \
+       Source/WebCore/dom/RegionNodeList.h \
        Source/WebCore/dom/RegisteredEventListener.cpp \
        Source/WebCore/dom/RegisteredEventListener.h \
        Source/WebCore/dom/RenderedDocumentMarker.h \
index fa7f960..f1baa8f 100644 (file)
@@ -561,6 +561,7 @@ SOURCES += \
     dom/Range.cpp \
     dom/RangeException.cpp \
     dom/RawDataDocumentParser.h \
+    dom/RegionNodeList.cpp \
     dom/RegisteredEventListener.cpp \
     dom/ScopedEventQueue.cpp \
     dom/ScriptedAnimationController.cpp \
index 0fa5885..bc5ad7d 100644 (file)
             'dom/Range.cpp',
             'dom/RangeException.cpp',
             'dom/RangeException.h',
+            'dom/RegionNodeList.cpp',
+            'dom/RegionNodeList.h',
             'dom/RawDataDocumentParser.h',
             'dom/RegisteredEventListener.cpp',
             'dom/RequestAnimationFrameCallback.h',
index 79a3e11..f1ccc1b 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\dom\RegionNodeList.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\dom\RegionNodeList.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\dom\RegisteredEventListener.cpp"
                                >
                                <FileConfiguration
index d4bd339..14850a8 100644 (file)
                8AA61CFF144D595B00F37350 /* WebKitCSSRegionRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8AA61CFD144D595B00F37350 /* WebKitCSSRegionRule.cpp */; };
                8AA61D00144D595B00F37350 /* WebKitCSSRegionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AA61CFE144D595B00F37350 /* WebKitCSSRegionRule.h */; };
                8AB4BC77126FDB7100DEB727 /* IgnoreDestructiveWriteCountIncrementer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AB4BC76126FDB7100DEB727 /* IgnoreDestructiveWriteCountIncrementer.h */; };
+               8ABAFB9F14F5107500A4984B /* RegionNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8ABAFB9D14F5107500A4984B /* RegionNodeList.cpp */; };
+               8ABAFBA014F5107500A4984B /* RegionNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ABAFB9E14F5107500A4984B /* RegionNodeList.h */; };
                8AD0A59414C88336000D83C5 /* JSWebKitCSSRegionRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8ACC24CD148E24B200EFCC0D /* JSWebKitCSSRegionRule.cpp */; };
                8AD0A59514C88336000D83C5 /* JSWebKitCSSRegionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ACC24CE148E24B200EFCC0D /* JSWebKitCSSRegionRule.h */; };
                8AD0A59614C88358000D83C5 /* DOMWebKitCSSRegionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ACC2817148E47E700EFCC0D /* DOMWebKitCSSRegionRule.h */; };
                8AA61CFD144D595B00F37350 /* WebKitCSSRegionRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitCSSRegionRule.cpp; sourceTree = "<group>"; };
                8AA61CFE144D595B00F37350 /* WebKitCSSRegionRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSRegionRule.h; sourceTree = "<group>"; };
                8AB4BC76126FDB7100DEB727 /* IgnoreDestructiveWriteCountIncrementer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IgnoreDestructiveWriteCountIncrementer.h; sourceTree = "<group>"; };
+               8ABAFB9D14F5107500A4984B /* RegionNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegionNodeList.cpp; sourceTree = "<group>"; };
+               8ABAFB9E14F5107500A4984B /* RegionNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegionNodeList.h; sourceTree = "<group>"; };
                8ACC24CD148E24B200EFCC0D /* JSWebKitCSSRegionRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebKitCSSRegionRule.cpp; sourceTree = "<group>"; };
                8ACC24CE148E24B200EFCC0D /* JSWebKitCSSRegionRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebKitCSSRegionRule.h; sourceTree = "<group>"; };
                8ACC2817148E47E700EFCC0D /* DOMWebKitCSSRegionRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWebKitCSSRegionRule.h; sourceTree = "<group>"; };
                                D23CA56B0AB0EB8D005108A5 /* RangeException.h */,
                                D23CA5480AB0E983005108A5 /* RangeException.idl */,
                                A84D827B11D333ED00972990 /* RawDataDocumentParser.h */,
+                               8ABAFB9D14F5107500A4984B /* RegionNodeList.cpp */,
+                               8ABAFB9E14F5107500A4984B /* RegionNodeList.h */,
                                85031B350A44EFC700F992E0 /* RegisteredEventListener.cpp */,
                                85031B360A44EFC700F992E0 /* RegisteredEventListener.h */,
                                A76E5F7E135E0DCF00A69837 /* RenderedDocumentMarker.h */,
                                E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
                                977E2E0F12F0FC9C00C13379 /* XSSAuditor.h in Headers */,
                                FD537353137B651800008DCE /* ZeroPole.h in Headers */,
+                               8ABAFBA014F5107500A4984B /* RegionNodeList.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */,
                                977E2E0E12F0FC9C00C13379 /* XSSAuditor.cpp in Sources */,
                                FD537352137B651800008DCE /* ZeroPole.cpp in Sources */,
+                               8ABAFB9F14F5107500A4984B /* RegionNodeList.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 12b0dab..53d7b25 100644 (file)
@@ -1031,6 +1031,16 @@ void Node::removeCachedClassNodeList(ClassNodeList* list, const String& classNam
     data->m_classNodeListCache.remove(className);
 }
 
+void Node::removeCachedRegionNodeList(RegionNodeList* list, const AtomicString& flowName)
+{
+    ASSERT(rareData());
+    ASSERT(rareData()->nodeLists());
+
+    NodeListsNodeData* data = rareData()->nodeLists();
+    ASSERT_UNUSED(list, list == data->m_regionNodeListCache.get(flowName));
+    data->m_regionNodeListCache.remove(flowName);
+}
+
 void Node::removeCachedNameNodeList(NameNodeList* list, const String& nodeName)
 {
     ASSERT(rareData());
@@ -1667,6 +1677,18 @@ PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
     return list.release();
 }
 
+PassRefPtr<NodeList> Node::getRegionsByContentNode(const AtomicString& flowName)
+{
+    pair<NodeListsNodeData::RegionNodeListCache::iterator, bool> result
+    = ensureRareData()->ensureNodeLists(this)->m_regionNodeListCache.add(flowName, 0);
+    if (!result.second)
+        return PassRefPtr<NodeList>(result.first->second);
+    
+    RefPtr<RegionNodeList> list = RegionNodeList::create(this, flowName);
+    result.first->second = list.get();
+    return list.release();
+}
+
 PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode& ec)
 {
     if (selectors.isEmpty()) {
@@ -2352,6 +2374,9 @@ void NodeListsNodeData::invalidateCaches()
     TagNodeListCacheNS::const_iterator tagCacheNSEnd = m_tagNodeListCacheNS.end();
     for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheNSEnd; ++it)
         it->second->invalidateCache();
+    RegionNodeListCache::const_iterator regionListCacheEnd = m_regionNodeListCache.end();
+    for (RegionNodeListCache::const_iterator it = m_regionNodeListCache.begin(); it != regionListCacheEnd; ++it)
+        it->second->invalidateCache();
     invalidateCachesThatDependOnAttributes();
 }
 
@@ -2398,10 +2423,12 @@ bool NodeListsNodeData::isEmpty() const
     if (!m_microDataItemListCache.isEmpty())
         return false;
 #endif
+    if (!m_regionNodeListCache.isEmpty())
+        return false;
 
     if (m_labelsNodeListCache)
         return false;
-
+    
     return true;
 }
 
index ad46dcd..45616a1 100644 (file)
@@ -72,6 +72,7 @@ class PlatformKeyboardEvent;
 class PlatformMouseEvent;
 class PlatformWheelEvent;
 class QualifiedName;
+class RegionNodeList;
 class RegisteredEventListener;
 class RenderArena;
 class RenderBox;
@@ -550,6 +551,7 @@ public:
     void unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
     void invalidateNodeListsCacheAfterAttributeChanged(const QualifiedName&);
     void invalidateNodeListsCacheAfterChildrenChanged();
+    void invalidateRegionListCache();
     void notifyLocalNodeListsLabelChanged();
     void removeCachedClassNodeList(ClassNodeList*, const String&);
 
@@ -557,6 +559,7 @@ public:
     void removeCachedTagNodeList(TagNodeList*, const AtomicString&);
     void removeCachedTagNodeList(TagNodeList*, const QualifiedName&);
     void removeCachedLabelsNodeList(DynamicSubtreeNodeList*);
+    void removeCachedRegionNodeList(RegionNodeList*, const AtomicString&);
 
     void removeCachedChildNodeList();
 
@@ -564,6 +567,7 @@ public:
     PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
     PassRefPtr<NodeList> getElementsByName(const String& elementName);
     PassRefPtr<NodeList> getElementsByClassName(const String& classNames);
+    PassRefPtr<NodeList> getRegionsByContentNode(const AtomicString& flowName);
 
     PassRefPtr<Element> querySelector(const String& selectors, ExceptionCode&);
     PassRefPtr<NodeList> querySelectorAll(const String& selectors, ExceptionCode&);
index 0864b26..d047791 100644 (file)
@@ -29,6 +29,7 @@
 #include "MutationObserverRegistration.h"
 #include "NameNodeList.h"
 #include "QualifiedName.h"
+#include "RegionNodeList.h"
 #include "TagNodeList.h"
 #include "WebKitMutationObserver.h"
 #include <wtf/HashSet.h>
@@ -71,6 +72,9 @@ public:
 #endif
 
     LabelsNodeList* m_labelsNodeListCache;
+
+    typedef HashMap<AtomicString, RegionNodeList*> RegionNodeListCache;
+    RegionNodeListCache m_regionNodeListCache;
  
     static PassOwnPtr<NodeListsNodeData> create()
     {
diff --git a/Source/WebCore/dom/RegionNodeList.cpp b/Source/WebCore/dom/RegionNodeList.cpp
new file mode 100644 (file)
index 0000000..2116d3b
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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 "RegionNodeList.h"
+
+#include "Document.h"
+#include "RenderFlowThread.h"
+#include "RenderRegion.h"
+#include "WebKitNamedFlow.h"
+
+namespace WebCore {
+
+RegionNodeList::RegionNodeList(PassRefPtr<Node> node, const AtomicString& flowName)
+: DynamicSubtreeNodeList(node->document())
+, m_contentNode(node)
+, m_flowName(flowName)
+{
+}
+
+RegionNodeList::~RegionNodeList()
+{
+    m_contentNode->removeCachedRegionNodeList(this, m_flowName);
+} 
+
+bool RegionNodeList::nodeMatches(Element* testNode) const
+{
+    if (!m_contentNode->renderer())
+        return false;
+
+    if (!testNode->renderer() || !testNode->renderer()->isRenderRegion())
+        return false;
+
+    RenderRegion* region = toRenderRegion(testNode->renderer());
+    if (!region->isValid() || (region->style()->regionThread() != m_flowName))
+        return false;
+
+    return region->flowThread()->objectInFlowRegion(m_contentNode->renderer(), region);
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/dom/RegionNodeList.h b/Source/WebCore/dom/RegionNodeList.h
new file mode 100644 (file)
index 0000000..813957d
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. 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.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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 RegionNodeList_h
+#define RegionNodeList_h
+
+#include "DynamicNodeList.h"
+#include "Node.h"
+
+namespace WebCore {
+
+class RegionNodeList : public DynamicSubtreeNodeList {
+public:
+    static PassRefPtr<RegionNodeList> create(PassRefPtr<Node> node, const AtomicString& flowName)
+    {
+        return adoptRef(new RegionNodeList(node, flowName));
+    }
+    
+    virtual ~RegionNodeList();
+
+protected:
+    virtual bool nodeMatches(Element*) const;
+
+private:
+    RegionNodeList(PassRefPtr<Node>, const AtomicString& flowName);
+    
+    RefPtr<Node> m_contentNode;
+    AtomicString m_flowName;
+};
+    
+} // namespace WebCore
+
+#endif
+
index 6d3b8e0..c362994 100644 (file)
@@ -30,6 +30,8 @@
 #include "config.h"
 #include "WebKitNamedFlow.h"
 
+#include "Node.h"
+#include "NodeList.h"
 #include "RenderFlowThread.h"
 
 namespace WebCore {
@@ -49,4 +51,13 @@ bool WebKitNamedFlow::overflow() const
     return m_parentFlowThread->overflow();
 }
 
+PassRefPtr<NodeList> WebKitNamedFlow::getRegionsByContentNode(Node* contentNode)
+{
+    if (!contentNode)
+        return 0;
+    m_parentFlowThread->document()->updateLayoutIgnorePendingStylesheets(); 
+    return contentNode->getRegionsByContentNode(m_parentFlowThread->flowThread());
+}
+
 } // namespace WebCore
+
index 9ef3c5a..b6f58c1 100644 (file)
@@ -35,6 +35,8 @@
 
 namespace WebCore {
 
+class Node;
+class NodeList;
 class RenderFlowThread;
 
 class WebKitNamedFlow : public RefCounted<WebKitNamedFlow> {
@@ -47,6 +49,8 @@ public:
     ~WebKitNamedFlow();
 
     bool overflow() const;
+    PassRefPtr<NodeList> getRegionsByContentNode(Node*);
+
 private:
     WebKitNamedFlow(RenderFlowThread*);
 
index a368188..10a4d9e 100644 (file)
@@ -32,5 +32,7 @@ module core {
         JSGenerateToJSObject
     ] WebKitNamedFlow {
         readonly attribute boolean overflow;
+        NodeList getRegionsByContentNode(in Node contentNode);
     };
 }
+
index 79816aa..e241d96 100644 (file)
@@ -13,7 +13,7 @@
  *    disclaimer in the documentation and/or other materials
  *    provided with the distribution.
  * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER BE
@@ -905,4 +905,70 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE
     m_overflow = lastReg && (lastReg->regionState() == RenderRegion::RegionOverflow);
 }
 
+bool RenderFlowThread::regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const
+{
+    ASSERT(targetRegion);
+
+    for (RenderRegionList::const_iterator it = m_regionList.find(const_cast<RenderRegion*>(startRegion)); it != m_regionList.end(); ++it) {
+        const RenderRegion* currRegion = *it;
+        if (!currRegion->isValid())
+            continue;
+        if (targetRegion == currRegion)
+            return true;
+        if (currRegion == endRegion)
+            break;
+    }
+
+    return false;
+}
+
+bool RenderFlowThread::objectInFlowRegion(const RenderObject* object, const RenderRegion* region) const
+{
+    ASSERT(object);
+    ASSERT(region);
+
+    if (!object->inRenderFlowThread())
+        return false;
+    if (object->enclosingRenderFlowThread() != this)
+        return false;
+    if (!m_regionList.contains(const_cast<RenderRegion*>(region)))
+        return false;
+
+    RenderBox* enclosingBox = object->enclosingBox();
+    RenderRegion* enclosingBoxStartRegion = 0;
+    RenderRegion* enclosingBoxEndRegion = 0;
+    getRegionRangeForBox(enclosingBox, enclosingBoxStartRegion, enclosingBoxEndRegion);
+    if (!regionInRange(region, enclosingBoxStartRegion, enclosingBoxEndRegion))
+        return false;
+
+    if (object->isBox())
+        return true;
+
+    LayoutRect objectABBRect = object->absoluteBoundingBoxRect(true);
+    if (!objectABBRect.width())
+        objectABBRect.setWidth(1);
+    if (!objectABBRect.height())
+        objectABBRect.setHeight(1); 
+    if (objectABBRect.intersects(region->absoluteBoundingBoxRect(true)))
+        return true;
+
+    if (region == lastRegion()) {
+        // If the object does not intersect any of the enclosing box regions
+        // then the object is in last region.
+        for (RenderRegionList::const_iterator it = m_regionList.find(enclosingBoxStartRegion); it != m_regionList.end(); ++it) {
+            const RenderRegion* currRegion = *it;
+            if (!region->isValid())
+                continue;
+            if (currRegion == region)
+                break;
+            if (objectABBRect.intersects(currRegion->absoluteBoundingBoxRect(true)))
+                return false;
+        }
+        return true;
+    }
+
+    return false;
+}
+
 } // namespace WebCore
+
index bda785d..b958eb1 100644 (file)
@@ -13,7 +13,7 @@
  *    disclaimer in the documentation and/or other materials
  *    provided with the distribution.
  * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER BE
@@ -136,6 +136,10 @@ public:
     void computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge);
 
     bool overflow() const { return m_overflow; }
+
+    // Check if the object is in region and the region is part of this flow thread.
+    bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const;
+
 private:
     virtual const char* renderName() const { return "RenderFlowThread"; }
 
@@ -146,6 +150,8 @@ private:
 
     bool shouldRepaint(const LayoutRect&) const;
 
+    bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const;
+
     typedef ListHashSet<RenderObject*> FlowThreadChildList;
     FlowThreadChildList m_flowThreadChildList;
 
index 143eacd..70fa23b 100644 (file)
@@ -56,6 +56,7 @@ public:
     void attachRegion();
     void detachRegion();
 
+    RenderFlowThread* flowThread() const { return m_flowThread; }
     RenderFlowThread* parentFlowThread() const { return m_parentFlowThread; }
 
     // Valid regions do not create circular dependencies with other flows.