Commit a09f5201 authored by weinig@apple.com's avatar weinig@apple.com

WebCore: Fix for https://bugs.webkit.org/show_bug.cgi?id=29760

Implement CSSOM Range.getClientRects/getBoundingClientRect 

Reviewed by Dan Bernstein.

Tests: fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport.html
       fast/dom/Range/getBoundingClientRect.html
       fast/dom/Range/getClientRects.html

* dom/Range.cpp:
(WebCore::Range::getClientRects):
(WebCore::Range::getBoundingClientRect):
(WebCore::adjustFloatQuadsForScrollAndAbsoluteZoom):
(WebCore::Range::getBorderAndTextQuads):
* dom/Range.h:
* dom/Range.idl:
Implement Range.getClientRects/getBoundingClientRect.

* dom/Element.cpp:
* rendering/RenderObject.h: 
(WebCore::adjustForAbsoluteZoom):
(WebCore::adjustIntRectForAbsoluteZoom):
(WebCore::adjustFloatPointForAbsoluteZoom):
(WebCore::adjustFloatQuadForAbsoluteZoom):
Move point/quad adjustment methods from Element.cpp to RenderObject.h
so that Range.cpp can use them as well.

LayoutTests: Tests for https://bugs.webkit.org/show_bug.cgi?id=29760
Implement CSSOM Range.getClientRects/getBoundingClientRect 

Reviewed by Dan Bernstein.

* fast/dom/Element/getBoundingClientRect-expected.txt: Copied from LayoutTests/fast/dom/getBoundingClientRect-expected.txt.
* fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt: Copied from LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt.
* fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport.html: Copied from LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport.html.
* fast/dom/Element/getBoundingClientRect.html: Copied from LayoutTests/fast/dom/getBoundingClientRect.html.
* fast/dom/Element/getClientRects-expected.txt: Copied from LayoutTests/fast/dom/getClientRects-expected.txt.
* fast/dom/Element/getClientRects.html: Copied from LayoutTests/fast/dom/getClientRects.html.
* fast/dom/Range/getBoundingClientRect-expected.txt: Added.
* fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt: Added.
* fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport.html: Added.
* fast/dom/Range/getBoundingClientRect.html: Added.
* fast/dom/Range/getClientRects-expected.txt: Added.
* fast/dom/Range/getClientRects.html: Added.
* fast/dom/Window/window-properties-expected.txt:
* fast/dom/getBoundingClientRect-expected.txt: Removed.
* fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt: Removed.
* fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport.html: Removed.
* fast/dom/getBoundingClientRect.html: Removed.
* fast/dom/getClientRects-expected.txt: Removed.
* fast/dom/getClientRects.html: Removed.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48806 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ea151061
2009-09-27 Sam Weinig <sam@webkit.org>
Reviewed by Dan Bernstein.
Tests for https://bugs.webkit.org/show_bug.cgi?id=29760
Implement CSSOM Range.getClientRects/getBoundingClientRect
* fast/dom/Element/getBoundingClientRect-expected.txt: Copied from LayoutTests/fast/dom/getBoundingClientRect-expected.txt.
* fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt: Copied from LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt.
* fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport.html: Copied from LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport.html.
* fast/dom/Element/getBoundingClientRect.html: Copied from LayoutTests/fast/dom/getBoundingClientRect.html.
* fast/dom/Element/getClientRects-expected.txt: Copied from LayoutTests/fast/dom/getClientRects-expected.txt.
* fast/dom/Element/getClientRects.html: Copied from LayoutTests/fast/dom/getClientRects.html.
* fast/dom/Range/getBoundingClientRect-expected.txt: Added.
* fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt: Added.
* fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport.html: Added.
* fast/dom/Range/getBoundingClientRect.html: Added.
* fast/dom/Range/getClientRects-expected.txt: Added.
* fast/dom/Range/getClientRects.html: Added.
* fast/dom/Window/window-properties-expected.txt:
* fast/dom/getBoundingClientRect-expected.txt: Removed.
* fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt: Removed.
* fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport.html: Removed.
* fast/dom/getBoundingClientRect.html: Removed.
* fast/dom/getClientRects-expected.txt: Removed.
* fast/dom/getClientRects.html: Removed.
2009-09-27 Jakub Wieczorek <faw217@gmail.com>
Reviewed by Simon Hausmann.
......
<link rel="stylesheet" href="../js/resources/js-test-style.css">
<script src="../js/resources/js-test-pre.js"></script>
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
<style>
#pusher {
width: 1000px;
......@@ -51,4 +51,4 @@
successfullyParsed = true;
</script>
<script src="../js/resources/js-test-post.js"></script>
<script src="../../js/resources/js-test-post.js"></script>
<link rel="stylesheet" href="../js/resources/js-test-style.css">
<script src="../js/resources/js-test-pre.js"></script>
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
<style>
#base {
width: 300px;
......@@ -177,4 +177,4 @@
successfullyParsed = true;
</script>
<script src="../js/resources/js-test-post.js"></script>
<script src="../../js/resources/js-test-post.js"></script>
<link rel="stylesheet" href="../js/resources/js-test-style.css">
<script src="../js/resources/js-test-pre.js"></script>
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
<style>
#base {
width: 300px;
......@@ -166,4 +166,4 @@
successfullyParsed = true;
</script>
<script src="../js/resources/js-test-post.js"></script>
<script src="../../js/resources/js-test-post.js"></script>
Test 1
PASS rect.left is 8
PASS rect.top is 8
PASS rect.width is 400
PASS rect.height is 160
Test 2
PASS rect.left is 8
PASS rect.top is 215
PASS rect.width is 398
PASS rect.height is 138
Test 3
PASS rect.left is 8
PASS rect.top is 451
PASS rect.width is 398
PASS rect.height is 58
Test 4
PASS rect.left is 76
PASS rect.top is 578
PASS rect.width is 361
PASS rect.height is 343
PASS successfullyParsed is true
TEST COMPLETE
PASS unScrolledBoundingBox.top - scrolledDownBoundingBox.top is 50
PASS unScrolledBoundingBoxes[0].top - scrolledDownBoundingBoxes[0].top is 50
PASS unScrolledBoundingBox.left - scrolledRightBoundingBox.left is 50
PASS unScrolledBoundingBoxes[0].left - scrolledRightBoundingBoxes[0].left is 50
PASS successfullyParsed is true
TEST COMPLETE
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
<style>
#pusher {
width: 1000px;
height: 1000px;
outline: 1px solid black;
}
</style>
<div id="console"></div>
<div id="testArea">
<br>
<p id="test">Test content</p>
<div id="pusher">This box is here to create scrollbars.</div>
</div>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
var range = document.createRange();
range.selectNodeContents(document.getElementById('test'));
// Get base numbers
var unScrolledBoundingBox = range.getBoundingClientRect();
var unScrolledBoundingBoxes = range.getClientRects();
// Test scrolling down
window.scrollBy(0, 50);
var scrolledDownBoundingBox = range.getBoundingClientRect();
var scrolledDownBoundingBoxes = range.getClientRects();
// Reset
window.scrollTo(0, 0);
// Test scrolling right
window.scrollBy(50, 0);
var scrolledRightBoundingBox = range.getBoundingClientRect();
var scrolledRightBoundingBoxes = range.getClientRects();
// Reset
window.scrollTo(0, 0);
shouldBe("unScrolledBoundingBox.top - scrolledDownBoundingBox.top", "50");
shouldBe("unScrolledBoundingBoxes[0].top - scrolledDownBoundingBoxes[0].top", "50");
shouldBe("unScrolledBoundingBox.left - scrolledRightBoundingBox.left", "50");
shouldBe("unScrolledBoundingBoxes[0].left - scrolledRightBoundingBoxes[0].left", "50");
if (window.layoutTestController) {
var area = document.getElementById('testArea');
area.parentNode.removeChild(area);
}
successfullyParsed = true;
</script>
<script src="../../js/resources/js-test-post.js"></script>
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
<style>
.bbox {
position:absolute;
outline: 5px solid rgba(255, 0, 0, .75);
z-index: -1;
}
.box {
width: 400px;
line-height: 40px;
}
.outer {
outline: 2px solid green;
}
.inner {
display: inline-block;
width: 40px;
height: 20px;
outline: 2px solid blue;
}
#test4 {
-webkit-transform: translate(50px, 100px) rotate(50deg);
}
#console {
position:absolute;
left: 500px;
}
#testArea {
width: 300px;
}
</style>
<div id="console"></div>
<div id="testArea">
<div class="box" id="test1">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="test2">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="test3">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="test4">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>
if (window.layoutTestController)
layoutTestController.dumpAsText();
function addBBoxOverClientRect(rect)
{
var bbox = document.createElement('div');
bbox.className = "bbox";
var style = "";
style += "left: " + rect.left + "px;";
style += "top: " + rect.top + "px;";
style += "width: " + (rect.right - rect.left) + "px;";
style += "height: " + (rect.bottom - rect.top) + "px;";
bbox.setAttribute("style", style);
document.documentElement.appendChild(bbox);
}
function show(range)
{
if (window.layoutTestController)
return;
addBBoxOverClientRect(range.getBoundingClientRect());
}
// Test 1
debug("Test 1")
var range1 = document.createRange();
range1.selectNode(document.getElementById('test1'));
show(range1);
rect = range1.getBoundingClientRect()
shouldBe("rect.left", "8");
shouldBe("rect.top", "8");
shouldBe("rect.width", "400");
shouldBe("rect.height", "160");
// Test 2
debug("Test 2")
var range2 = document.createRange();
range2.selectNodeContents(document.getElementById('test2'));
show(range2);
rect = range2.getBoundingClientRect()
shouldBe("rect.left", "8");
shouldBe("rect.top", "215");
shouldBe("rect.width", "398");
shouldBe("rect.height", "138");
// Test 3
debug("Test 3")
var range3 = document.createRange();
range3.setStart(document.getElementById('test3').firstChild, 100);
range3.setEnd(document.getElementById('test3').lastChild, 150);
show(range3);
rect = range3.getBoundingClientRect()
shouldBe("rect.left", "8");
shouldBe("rect.top", "451");
shouldBe("rect.width", "398");
shouldBe("rect.height", "58");
// Test 4
debug("Test 4")
var range4 = document.createRange();
range4.selectNodeContents(document.getElementById('test4'));
show(range4);
rect = range4.getBoundingClientRect()
shouldBe("rect.left", "76");
shouldBe("rect.top", "578");
shouldBe("rect.width", "361");
shouldBe("rect.height", "343");
if (window.layoutTestController) {
var area = document.getElementById('testArea');
area.parentNode.removeChild(area);
}
successfullyParsed = true;
</script>
<script src="../../js/resources/js-test-post.js"></script>
Test 1
PASS rects.length is 5
PASS rects[0].left is 8
PASS rects[0].top is 8
PASS rects[0].width is 400
PASS rects[0].height is 160
PASS rects[1].left is 8
PASS rects[1].top is 19
PASS rects[1].width is 396
PASS rects[1].height is 18
PASS rects[2].left is 8
PASS rects[2].top is 59
PASS rects[2].width is 398
PASS rects[2].height is 18
PASS rects[3].left is 8
PASS rects[3].top is 99
PASS rects[3].width is 360
PASS rects[3].height is 18
PASS rects[4].left is 8
PASS rects[4].top is 139
PASS rects[4].width is 306
PASS rects[4].height is 18
Test 2
PASS rects.length is 4
PASS rects[0].left is 8
PASS rects[0].top is 215
PASS rects[0].width is 396
PASS rects[0].height is 18
PASS rects[1].left is 8
PASS rects[1].top is 255
PASS rects[1].width is 398
PASS rects[1].height is 18
PASS rects[2].left is 8
PASS rects[2].top is 295
PASS rects[2].width is 360
PASS rects[2].height is 18
PASS rects[3].left is 8
PASS rects[3].top is 335
PASS rects[3].width is 306
PASS rects[3].height is 18
Test 3
PASS rects.length is 4
PASS rects[0].left is 80
PASS rects[0].top is 411
PASS rects[0].width is 324
PASS rects[0].height is 18
PASS rects[1].left is 8
PASS rects[1].top is 451
PASS rects[1].width is 398
PASS rects[1].height is 18
PASS rects[2].left is 8
PASS rects[2].top is 491
PASS rects[2].width is 360
PASS rects[2].height is 18
PASS rects[3].left is 8
PASS rects[3].top is 531
PASS rects[3].width is 88
PASS rects[3].height is 18
Test 4
PASS rects.length is 7
PASS rects[0].left is 8
PASS rects[0].top is 596
PASS rects[0].width is 400
PASS rects[0].height is 278
PASS rects[1].left is 8
PASS rects[1].top is 607
PASS rects[1].width is 396
PASS rects[1].height is 18
PASS rects[2].left is 8
PASS rects[2].top is 725
PASS rects[2].width is 242
PASS rects[2].height is 18
PASS rects[3].left is 326
PASS rects[3].top is 725
PASS rects[3].width is 44
PASS rects[3].height is 18
PASS rects[4].left is 8
PASS rects[4].top is 765
PASS rects[4].width is 341
PASS rects[4].height is 18
PASS rects[5].left is 8
PASS rects[5].top is 805
PASS rects[5].width is 366
PASS rects[5].height is 18
PASS rects[6].left is 8
PASS rects[6].top is 845
PASS rects[6].width is 67
PASS rects[6].height is 18
Test 5
PASS rects.length is 5
PASS rects[0].left is 80
PASS rects[0].top is 921
PASS rects[0].width is 324
PASS rects[0].height is 18
PASS rects[1].left is 8
PASS rects[1].top is 1039
PASS rects[1].width is 242
PASS rects[1].height is 18
PASS rects[2].left is 250
PASS rects[2].top is 950
PASS rects[2].width is 76
PASS rects[2].height is 103
PASS rects[3].left is 326
PASS rects[3].top is 1039
PASS rects[3].width is 44
PASS rects[3].height is 18
PASS rects[4].left is 8
PASS rects[4].top is 1079
PASS rects[4].width is 284
PASS rects[4].height is 18
Test 6
PASS rects.length is 7
PASS rects[0].left is 8
PASS rects[0].top is 1224
PASS rects[0].width is 400
PASS rects[0].height is 200
PASS rects[1].left is 8
PASS rects[1].top is 1235
PASS rects[1].width is 396
PASS rects[1].height is 18
PASS rects[2].left is 8
PASS rects[2].top is 1275
PASS rects[2].width is 57
PASS rects[2].height is 18
PASS rects[3].left is 105
PASS rects[3].top is 1275
PASS rects[3].width is 44
PASS rects[3].height is 18
PASS rects[4].left is 8
PASS rects[4].top is 1315
PASS rects[4].width is 387
PASS rects[4].height is 18
PASS rects[5].left is 8
PASS rects[5].top is 1355
PASS rects[5].width is 397
PASS rects[5].height is 18
PASS rects[6].left is 8
PASS rects[6].top is 1395
PASS rects[6].width is 171
PASS rects[6].height is 18
Test 7
PASS rects.length is 7
PASS rects[0].left is 8
PASS rects[0].top is 1471
PASS rects[0].width is 396
PASS rects[0].height is 18
PASS rects[1].left is 8
PASS rects[1].top is 1500
PASS rects[1].width is 400
PASS rects[1].height is 40
PASS rects[2].left is 8
PASS rects[2].top is 1511
PASS rects[2].width is 57
PASS rects[2].height is 18
PASS rects[3].left is 105
PASS rects[3].top is 1511
PASS rects[3].width is 44
PASS rects[3].height is 18
PASS rects[4].left is 8
PASS rects[4].top is 1551
PASS rects[4].width is 387
PASS rects[4].height is 18
PASS rects[5].left is 8
PASS rects[5].top is 1591
PASS rects[5].width is 397
PASS rects[5].height is 18
PASS rects[6].left is 8
PASS rects[6].top is 1631
PASS rects[6].width is 171
PASS rects[6].height is 18
Test 8
PASS rects.length is 4
PASS rects[0].left is 168
PASS rects[0].top is 1678
PASS rects[0].width is 269
PASS rects[0].height is 316
PASS rects[1].left is 137
PASS rects[1].top is 1704
PASS rects[1].width is 271
PASS rects[1].height is 317
PASS rects[2].left is 107
PASS rects[2].top is 1729
PASS rects[2].width is 246
PASS rects[2].height is 289
PASS rects[3].left is 76
PASS rects[3].top is 1755
PASS rects[3].width is 212
PASS rects[3].height is 247
PASS successfullyParsed is true
TEST COMPLETE
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
<style>
.bbox {
position:absolute;
outline: 5px solid rgba(255, 0, 0, .75);
z-index: -1;
}
.box {
width: 400px;
line-height: 40px;
}
.outer {
outline: 2px solid green;
}
.inner {
display: inline-block;
width: 40px;
height: 20px;
outline: 2px solid blue;
}
#test8 {
-webkit-transform: translate(50px, 100px) rotate(50deg);
}
#console {
position:absolute;
left: 500px;
}
#testArea {
width: 300px;
}
</style>
<div id="console"></div>
<div id="testArea">
<div class="box" id="test1">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="test2">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="test3">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="test4">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et<img src="../resources/abe.png" width="76" height="103"> 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="test5">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et<img src="../resources/abe.png" width="76" height="103"> 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="test6">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do <div class="outer">eiusmod <span class="inner"></span>tempor</div> incididunt ut labore etdolore 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="test7">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do <div class="outer">eiusmod <span class="inner"></span>tempor</div> incididunt ut labore etdolore 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="test8">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>
if (window.layoutTestController)
layoutTestController.dumpAsText();
function addBBoxOverClientRect(rect)
{
var bbox = document.createElement('div');
bbox.className = "bbox";
var style = "";
style += "left: " + rect.left + "px;";
style += "top: " + rect.top + "px;";
style += "width: " + (rect.right - rect.left) + "px;";
style += "height: " + (rect.bottom - rect.top) + "px;";
bbox.setAttribute("style", style);
document.documentElement.appendChild(bbox);
}
function addBBoxOverClientRects(rects)
{
for (var i = 0; i < rects.length; ++i)
addBBoxOverClientRect(rects[i]);
}
function show(range)
{
if (window.layoutTestController)
return;
addBBoxOverClientRects(range.getClientRects());
}
// Test 1
debug("Test 1")
var range1 = document.createRange();
range1.selectNode(document.getElementById('test1'));
show(range1);
rects = range1.getClientRects();
shouldBe("rects.length", "5");
shouldBe("rects[0].left", "8");
shouldBe("rects[0].top", "8");
shouldBe("rects[0].width", "400");
shouldBe("rects[0].height", "160");
shouldBe("rects[1].left", "8");
shouldBe("rects[1].top", "19");
shouldBe("rects[1].width", "396");
shouldBe("rects[1].height", "18");
shouldBe("rects[2].left", "8");
shouldBe("rects[2].top", "59");
shouldBe("rects[2].width", "398");
shouldBe("rects[2].height", "1