Title: [148898] trunk
Revision
148898
Author
[email protected]
Date
2013-04-22 11:23:33 -0700 (Mon, 22 Apr 2013)

Log Message

Range.getClientRects() should not include rects for partially selected elements
https://bugs.webkit.org/show_bug.cgi?id=76839

Reviewed by Sam Weinig.

Source/WebCore:

CSSOM says that Range.getClientRects() should include the border boxes
of each element selected by the range. However, we were also
incorrectly including border boxes for partially selected elements.
For instance, consider the following selection:

    <div>line one<br>line two</div>
    -------------

The <div> is two lines tall, but only the first line is selected.
Despite this, we'd include the <div>'s border box since its start tag
was included in the selection.

Fix this by excluding partially selected elements. This is accomplished
by skipping over elements that come after the start boundary point of
the range but are ancestors of the end boundary point.

Added test cases to LayoutTests/fast/dom/Range/getClientRects.html.

* dom/Range.cpp:
(WebCore::Range::getBorderAndTextQuads):

LayoutTests:

* fast/dom/Range/getClientRects-expected.txt: Updated expected result.
* fast/dom/Range/getClientRects.html: Added new test cases.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (148897 => 148898)


--- trunk/LayoutTests/ChangeLog	2013-04-22 18:21:10 UTC (rev 148897)
+++ trunk/LayoutTests/ChangeLog	2013-04-22 18:23:33 UTC (rev 148898)
@@ -1,3 +1,13 @@
+2013-04-22  Andy Estes  <[email protected]>
+
+        Range.getClientRects() should not include rects for partially selected elements
+        https://bugs.webkit.org/show_bug.cgi?id=76839
+
+        Reviewed by Sam Weinig.
+
+        * fast/dom/Range/getClientRects-expected.txt: Updated expected result.
+        * fast/dom/Range/getClientRects.html: Added new test cases.
+
 2013-04-22  Eric Carlson  <[email protected]>
 
         Unreviewed Mac gardening. Update a test and results now that forced text 

Modified: trunk/LayoutTests/fast/dom/Range/getClientRects-expected.txt (148897 => 148898)


--- trunk/LayoutTests/fast/dom/Range/getClientRects-expected.txt	2013-04-22 18:21:10 UTC (rev 148897)
+++ trunk/LayoutTests/fast/dom/Range/getClientRects-expected.txt	2013-04-22 18:23:33 UTC (rev 148898)
@@ -217,6 +217,40 @@
 PASS rects[3].width is 18
 PASS rects[3].height is 360
 Test 11
+PASS rects.length is 2
+PASS rects[0].left is 8
+PASS rects[0].top is 2524
+PASS rects[0].width is 400
+PASS rects[0].height is 40
+PASS rects[1].left is 8
+PASS rects[1].top is 2535
+PASS rects[1].width is 177
+PASS rects[1].height is 18
+Test 12
+PASS rects.length is 1
+PASS rects[0].left is 8
+PASS rects[0].top is 2760
+PASS rects[0].width is 400
+PASS rects[0].height is 160
+Test 13
+PASS rects.length is 4
+PASS rects[0].left is 8
+PASS rects[0].top is 2967
+PASS rects[0].width is 396
+PASS rects[0].height is 18
+PASS rects[1].left is 8
+PASS rects[1].top is 3007
+PASS rects[1].width is 398
+PASS rects[1].height is 18
+PASS rects[2].left is 8
+PASS rects[2].top is 3047
+PASS rects[2].width is 360
+PASS rects[2].height is 18
+PASS rects[3].left is 8
+PASS rects[3].top is 3087
+PASS rects[3].width is 306
+PASS rects[3].height is 18
+Test 14
 PASS rects.length is 0
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/dom/Range/getClientRects.html (148897 => 148898)


--- trunk/LayoutTests/fast/dom/Range/getClientRects.html	2013-04-22 18:21:10 UTC (rev 148897)
+++ trunk/LayoutTests/fast/dom/Range/getClientRects.html	2013-04-22 18:23:33 UTC (rev 148898)
@@ -81,6 +81,18 @@
 
 <div class="box" id="test10">weee! Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
 
+<br><br>
+
+<div class="box" id="test11"><div>Lorem ipsum dolor sit amet,</div> consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
+
+<br><br>
+
+<div class="box" id="test12">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
+
+<br><br>
+
+<div class="box" id="test13">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
+
 </div>
 
 <script>
@@ -398,9 +410,65 @@
     shouldBe("rects[3].width", "18");
     shouldBe("rects[3].height", "360");
 
+    // Test 11
     debug("Test 11");
     var range11 = document.createRange();
+    range11.setStartBefore(document.getElementById('test11'));
+    range11.setEndAfter(document.getElementById('test11').firstChild);
+    show(range11);
     rects = range11.getClientRects();
+    shouldBe("rects.length", "2");
+    shouldBe("rects[0].left", "8");
+    shouldBe("rects[0].top", "2524");
+    shouldBe("rects[0].width", "400");
+    shouldBe("rects[0].height", "40");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "2535");
+    shouldBe("rects[1].width", "177");
+    shouldBe("rects[1].height", "18");
+
+    // Test 12
+    debug("Test 12");
+    var range12 = document.createRange();
+    range12.setStartBefore(document.getElementById('test12'));
+    range12.setEndBefore(document.getElementById('test12').firstChild);
+    show(range12);
+    rects = range12.getClientRects();
+    shouldBe("rects.length", "1");
+    shouldBe("rects[0].left", "8");
+    shouldBe("rects[0].top", "2760");
+    shouldBe("rects[0].width", "400");
+    shouldBe("rects[0].height", "160");
+
+    // Test 13
+    debug("Test 13");
+    var range13 = document.createRange();
+    range13.setStartBefore(document.getElementById('test13'));
+    range13.setEndAfter(document.getElementById('test13').firstChild);
+    show(range13);
+    rects = range13.getClientRects();
+    shouldBe("rects.length", "4");
+    shouldBe("rects[0].left", "8");
+    shouldBe("rects[0].top", "2967");
+    shouldBe("rects[0].width", "396");
+    shouldBe("rects[0].height", "18");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "3007");
+    shouldBe("rects[1].width", "398");
+    shouldBe("rects[1].height", "18");
+    shouldBe("rects[2].left", "8");
+    shouldBe("rects[2].top", "3047");
+    shouldBe("rects[2].width", "360");
+    shouldBe("rects[2].height", "18");
+    shouldBe("rects[3].left", "8");
+    shouldBe("rects[3].top", "3087");
+    shouldBe("rects[3].width", "306");
+    shouldBe("rects[3].height", "18");
+
+    // Test 14
+    debug("Test 14");
+    var range14 = document.createRange();
+    rects = range14.getClientRects();
     shouldBe("rects.length", "0");
 
     if (window.testRunner) {

Modified: trunk/Source/WebCore/ChangeLog (148897 => 148898)


--- trunk/Source/WebCore/ChangeLog	2013-04-22 18:21:10 UTC (rev 148897)
+++ trunk/Source/WebCore/ChangeLog	2013-04-22 18:23:33 UTC (rev 148898)
@@ -1,3 +1,31 @@
+2013-04-22  Andy Estes  <[email protected]>
+
+        Range.getClientRects() should not include rects for partially selected elements
+        https://bugs.webkit.org/show_bug.cgi?id=76839
+
+        Reviewed by Sam Weinig.
+
+        CSSOM says that Range.getClientRects() should include the border boxes
+        of each element selected by the range. However, we were also
+        incorrectly including border boxes for partially selected elements.
+        For instance, consider the following selection:
+
+            <div>line one<br>line two</div>
+            -------------
+
+        The <div> is two lines tall, but only the first line is selected.
+        Despite this, we'd include the <div>'s border box since its start tag
+        was included in the selection.
+
+        Fix this by excluding partially selected elements. This is accomplished
+        by skipping over elements that come after the start boundary point of
+        the range but are ancestors of the end boundary point.
+
+        Added test cases to LayoutTests/fast/dom/Range/getClientRects.html.
+
+        * dom/Range.cpp:
+        (WebCore::Range::getBorderAndTextQuads):
+
 2013-04-22  Yi Shen  <[email protected]>
 
         Crash on OS X when shift clicking outside of input

Modified: trunk/Source/WebCore/dom/Range.cpp (148897 => 148898)


--- trunk/Source/WebCore/dom/Range.cpp	2013-04-22 18:21:10 UTC (rev 148897)
+++ trunk/Source/WebCore/dom/Range.cpp	2013-04-22 18:23:33 UTC (rev 148898)
@@ -1909,22 +1909,25 @@
     Node* endContainer = m_end.container();
     Node* stopNode = pastLastNode();
 
-    HashSet<Node*> nodeSet;
+    HashSet<Node*> selectedElementsSet;
     for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
         if (node->isElementNode())
-            nodeSet.add(node);
+            selectedElementsSet.add(node);
     }
 
+    // Don't include elements that are only partially selected.
+    Node* lastNode = m_end.childBefore() ? m_end.childBefore() : endContainer;
+    for (Node* parent = lastNode->parentNode(); parent; parent = parent->parentNode())
+        selectedElementsSet.remove(parent);
+
     for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
-        if (node->isElementNode()) {
-            if (!nodeSet.contains(node->parentNode())) {
-                if (RenderBoxModelObject* renderBoxModelObject = toElement(node)->renderBoxModelObject()) {
-                    Vector<FloatQuad> elementQuads;
-                    renderBoxModelObject->absoluteQuads(elementQuads);
-                    m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(elementQuads, renderBoxModelObject);
+        if (node->isElementNode() && selectedElementsSet.contains(node) && !selectedElementsSet.contains(node->parentNode())) {
+            if (RenderBoxModelObject* renderBoxModelObject = toElement(node)->renderBoxModelObject()) {
+                Vector<FloatQuad> elementQuads;
+                renderBoxModelObject->absoluteQuads(elementQuads);
+                m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(elementQuads, renderBoxModelObject);
 
-                    quads.append(elementQuads);
-                }
+                quads.append(elementQuads);
             }
         } else if (node->isTextNode()) {
             if (RenderObject* renderer = toText(node)->renderer()) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to