[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75

weinig at apple.com weinig at apple.com
Thu Oct 29 20:34:54 UTC 2009


The following commit has been merged in the webkit-1.1 branch:
commit a09f52010ca93a9ba26c81fbbb64e4f281626283
Author: weinig at apple.com <weinig at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sun Sep 27 23:59:05 2009 +0000

    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

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index ec824bb..6356ee0 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,30 @@
+2009-09-27  Sam Weinig  <sam at 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 at gmail.com>
 
         Reviewed by Simon Hausmann.
diff --git a/LayoutTests/fast/dom/getBoundingClientRect-expected.txt b/LayoutTests/fast/dom/Element/getBoundingClientRect-expected.txt
similarity index 100%
rename from LayoutTests/fast/dom/getBoundingClientRect-expected.txt
rename to LayoutTests/fast/dom/Element/getBoundingClientRect-expected.txt
diff --git a/LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt b/LayoutTests/fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt
similarity index 100%
copy from LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt
copy to LayoutTests/fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt
diff --git a/LayoutTests/fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport.html b/LayoutTests/fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport.html
new file mode 100644
index 0000000..bf45b79
--- /dev/null
+++ b/LayoutTests/fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport.html
@@ -0,0 +1,54 @@
+<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 element = document.getElementById('test');
+
+    // Get base numbers
+    var unScrolledBoundingBox = element.getBoundingClientRect();
+    var unScrolledBoundingBoxes = element.getClientRects();
+
+    // Test scrolling down
+    window.scrollBy(0, 50);
+    var scrolledDownBoundingBox = element.getBoundingClientRect();
+    var scrolledDownBoundingBoxes = element.getClientRects();
+
+    // Reset
+    window.scrollTo(0, 0);
+
+    // Test scrolling right
+    window.scrollBy(50, 0);
+    var scrolledRightBoundingBox = element.getBoundingClientRect();
+    var scrolledRightBoundingBoxes = element.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>
diff --git a/LayoutTests/fast/dom/Element/getBoundingClientRect.html b/LayoutTests/fast/dom/Element/getBoundingClientRect.html
new file mode 100644
index 0000000..98da9cc
--- /dev/null
+++ b/LayoutTests/fast/dom/Element/getBoundingClientRect.html
@@ -0,0 +1,180 @@
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+<style>
+    #base {
+        width: 300px;
+        height: 100px;
+    }
+
+    #border {
+        border: 10px solid #999;
+        width: 300px;
+        height: 100px;
+    }
+
+    #margin {
+        margin: 10px;
+        width: 300px;
+        height: 100px;
+    }
+
+    #transform {
+        -webkit-transform: translateX(50px) rotate(45deg);
+        width: 100px;
+        height: 100px;
+    }
+
+    #columns {
+        -webkit-column-count: 3;
+        width: 300px;
+    }
+
+    #inline {
+        display: inline;
+    }
+
+    #outer {
+        width: 100px;
+        height: 100px;
+    }
+
+    #inner {
+        width: 200px;
+        height: 200px;
+    }
+
+    table {
+        width: 300px;
+    }
+
+    img {
+        width: 100px;
+        height: 100px;
+    }
+
+    .testBox {
+        background-color: green;
+    }
+
+    #testArea {
+        width: 300px;
+    }
+
+    .bbox {
+        position:absolute;
+        outline: 5px solid rgba(255, 0, 0, .75);
+    }
+
+    #console {
+        position:absolute;
+        left: 500px;
+    }
+</style>
+
+<div id="console"></div>
+<div id="testArea">
+
+<p>1. Base</p>                  <div id="base" class="testBox"></div>
+<p>2. Border</p>                <div id="border" class="testBox"></div>
+<p>3. Margin</p>                <div id="margin" class="testBox"></div>
+<p>4. Transform</p>             <div id="transform" class="testBox"></div>
+<p>5. Column</p>                <div id="columns" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
+<p>6. In a column</p>           <div id="columns">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.<span id="in-columns" class="testBox knownFailure">In columns</span> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
+<p>7. Inline</p>                <div id="inline" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
+<p>8. Table</p>                 <table class="testBox"><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>9. Table with Caption</p>    <table class="testBox"><caption>caption</caption><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>10. Table Row</p>            <table><tr class="testBox"><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>11. Table Cell</p>           <table><tr><td class="testBox">table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>12. Big block in little</p>  <div id="outer" class="testBox"><div id="inner"></div></div>
+<p>13. Replaced in inline</p>   <span class="testBox">Lorem<img>ipsum</span>
+<p>14. Block in inline</p>      <span class="testBox">Lorem<div id="inner"></div>ipsum</span>
+<p>15. Float in inline</p>      <span class="testBox"><img style="float:right"></span>
+
+</div>
+
+<script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    var testRect;
+    function testClientRect(toTest, expectedRect)
+    {
+        testRect = toTest;
+        
+        debug("testRect.top " + testRect.top);
+        debug("testRect.left " + testRect.left);
+        debug("testRect.width " + testRect.width);
+        debug("testRect.height " + testRect.height);
+        debug("testRect.bottom " + testRect.bottom);
+        debug("testRect.right " + testRect.right);
+        debug("");
+
+        shouldBe("testRect.top", String(expectedRect.top));
+        shouldBe("testRect.left", String(expectedRect.left));
+        shouldBe("testRect.width", String(expectedRect.width));
+        shouldBe("testRect.height", String(expectedRect.height));
+        shouldBe("testRect.bottom", "testRect.top + testRect.height");
+        shouldBe("testRect.right", "testRect.left + testRect.width");
+        debug("");
+    }
+
+    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);
+    }
+
+    var fail = undefined;
+
+    var expectedResults = [
+        /*1*/  { top: 42, left: 8, width: 300, height: 100 },
+        /*2*/  { top: 192, left: 8, width: 320, height: 120 },
+        /*3*/  { top: 362, left: 18, width: 300, height: 100 },
+        /*4*/  { top: 491, left: 37, width: 142, height: 142 },
+        /*5*/  { top: 662, left: 8, width: 300, height: 234 },
+        /*6*/  { top: fail, left: fail, width: fail, height: fail },
+        /*7*/  { top: 1230, left: 8, width: 299, height: 180 },
+        /*8*/  { top: 1460, left: 8, width: 300, height: 46 },
+        /*9*/  { top: 1556, left: 8, width: 300, height: 64 },
+        /*10*/ { top: 1672, left: 8, width: 300, height: 20 },
+        /*11*/ { top: 1768, left: 10, width: 147, height: 20 },
+        /*12*/ { top: 1862, left: 8, width: 100, height: 100 },
+        /*13*/ { top: 2098, left: 8, width: 180, height: 18 },
+        /*14*/ { top: 2166, left: 8, width: 200, height: 236 },
+        /*15*/ { top: 2452, left: 8, width: 0, height: 0 }
+    ];
+
+    function test(number, element)
+    {
+        debug("Client bounding rect for #" + number);
+
+        if (element.className.match("knownFailure")) {
+            debug("Known failure. Skipping.");
+            debug("");
+            return;
+        }
+
+        var boundingRect = element.getBoundingClientRect();
+        addBBoxOverClientRect(boundingRect);
+        testClientRect(boundingRect, expectedResults[number - 1]);
+    }
+
+    var tests = document.getElementsByClassName("testBox");
+    for (var i = 0; i < tests.length; ++i)
+        test(i + 1, tests[i]);
+
+    if (window.layoutTestController) {
+        var area = document.getElementById('testArea');
+        area.parentNode.removeChild(area);
+    }
+
+    successfullyParsed = true;
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
diff --git a/LayoutTests/fast/dom/getClientRects-expected.txt b/LayoutTests/fast/dom/Element/getClientRects-expected.txt
similarity index 100%
rename from LayoutTests/fast/dom/getClientRects-expected.txt
rename to LayoutTests/fast/dom/Element/getClientRects-expected.txt
diff --git a/LayoutTests/fast/dom/Element/getClientRects.html b/LayoutTests/fast/dom/Element/getClientRects.html
new file mode 100644
index 0000000..245f405
--- /dev/null
+++ b/LayoutTests/fast/dom/Element/getClientRects.html
@@ -0,0 +1,169 @@
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+<style>
+    #base {
+        width: 300px;
+        height: 100px;
+    }
+
+    #border {
+        border: 10px solid #999;
+        width: 300px;
+        height: 100px;
+    }
+
+    #margin {
+        margin: 10px;
+        width: 300px;
+        height: 100px;
+    }
+
+    #transform {
+        -webkit-transform: translateX(50px) rotate(45deg);
+        width: 100px;
+        height: 100px;
+    }
+
+    #columns {
+        -webkit-column-count: 3;
+        width: 300px;
+    }
+
+    #inline {
+        display: inline;
+    }
+
+    #outer {
+        width: 100px;
+        height: 100px;
+    }
+
+    #inner {
+        width: 200px;
+        height: 200px;
+    }
+
+    table {
+        width: 300px;
+    }
+
+    img {
+        width: 100px;
+        height: 100px;
+    }
+
+    .testBox {
+        background-color: green;
+    }
+
+    #testArea {
+        width: 300px;
+    }
+
+    .bbox {
+        position:absolute;
+        outline: 5px solid rgba(255, 0, 0, .75);
+    }
+
+    #console {
+        position:absolute;
+        left: 500px;
+    }
+</style>
+
+<div id="console"></div>
+<div id="testArea">
+
+<p>1. Base</p>                  <div id="base" class="testBox"></div>
+<p>2. Border</p>                <div id="border" class="testBox"></div>
+<p>3. Margin</p>                <div id="margin" class="testBox"></div>
+<p>4. Transform</p>             <div id="transform" class="testBox"></div>
+<p>5. Column</p>                <div id="columns" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
+<p>6. In a column</p>           <div id="columns">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.<span id="in-columns" class="testBox knownFailure">In columns</span> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
+<p>7. Inline</p>                <div id="inline" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
+<p>8. Table</p>                 <table class="testBox"><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>9. Table with Caption</p>    <table class="testBox"><caption>caption</caption><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>10. Table Row</p>            <table><tr class="testBox"><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>11. Table Cell</p>           <table><tr><td class="testBox">table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
+<p>12. Big block in little</p>  <div id="outer" class="testBox"><div id="inner"></div></div>
+<p>13. Replaced in inline</p>   <span class="testBox">Lorem<img>ipsum</span>
+<p>14. Block in inline</p>      <span class="testBox">Lorem<div id="inner"></div>ipsum</span>
+<p>15. Float in inline</p>      <span class="testBox"><img style="float:right"></span>
+
+</div>
+<script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    var testRects;
+    function testClientRects(rects, expectedNumberOfRects)
+    {
+        testRects = rects;
+        shouldBe("testRects.length", String(expectedNumberOfRects));
+        debug("");
+    }
+
+    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]);
+    }
+
+    var expectedResults = [
+        1,
+        1,
+        1,
+        1,
+        1,
+        1,
+        10,
+        1,
+        2,
+        1,
+        1,
+        1,
+        1,
+        3,
+        1
+    ];
+
+    function test(number, element)
+    {
+        debug("Client bounding rects for #" + number);
+
+        if (element.className.match("knownFailure")) {
+            debug("Known failure. Skipping.");
+            debug("");
+            return;
+        }
+
+        var boundingRects = element.getClientRects();
+        addBBoxOverClientRects(boundingRects);
+        testClientRects(boundingRects, expectedResults[number - 1]);
+    }
+
+    var tests = document.getElementsByClassName("testBox");
+    for (var i = 0; i < tests.length; ++i)
+        test(i + 1, tests[i]);
+
+    if (window.layoutTestController) {
+        var area = document.getElementById('testArea');
+        area.parentNode.removeChild(area);
+    }
+
+    successfullyParsed = true;
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
diff --git a/LayoutTests/fast/dom/Range/getBoundingClientRect-expected.txt b/LayoutTests/fast/dom/Range/getBoundingClientRect-expected.txt
new file mode 100644
index 0000000..d4f0a65
--- /dev/null
+++ b/LayoutTests/fast/dom/Range/getBoundingClientRect-expected.txt
@@ -0,0 +1,24 @@
+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
+
diff --git a/LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt b/LayoutTests/fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt
similarity index 100%
rename from LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt
rename to LayoutTests/fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport-expected.txt
diff --git a/LayoutTests/fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport.html b/LayoutTests/fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport.html
new file mode 100644
index 0000000..037df40
--- /dev/null
+++ b/LayoutTests/fast/dom/Range/getBoundingClientRect-getClientRects-relative-to-viewport.html
@@ -0,0 +1,55 @@
+<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>
diff --git a/LayoutTests/fast/dom/Range/getBoundingClientRect.html b/LayoutTests/fast/dom/Range/getBoundingClientRect.html
new file mode 100644
index 0000000..0fe7b27
--- /dev/null
+++ b/LayoutTests/fast/dom/Range/getBoundingClientRect.html
@@ -0,0 +1,134 @@
+<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>
diff --git a/LayoutTests/fast/dom/Range/getClientRects-expected.txt b/LayoutTests/fast/dom/Range/getClientRects-expected.txt
new file mode 100644
index 0000000..a08a2cf
--- /dev/null
+++ b/LayoutTests/fast/dom/Range/getClientRects-expected.txt
@@ -0,0 +1,192 @@
+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
+
diff --git a/LayoutTests/fast/dom/Range/getClientRects.html b/LayoutTests/fast/dom/Range/getClientRects.html
new file mode 100644
index 0000000..d6de3f3
--- /dev/null
+++ b/LayoutTests/fast/dom/Range/getClientRects.html
@@ -0,0 +1,349 @@
+<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", "18");
+    shouldBe("rects[3].left", "8");
+    shouldBe("rects[3].top", "99");
+    shouldBe("rects[3].width", "360");
+    shouldBe("rects[3].height", "18");
+    shouldBe("rects[4].left", "8");
+    shouldBe("rects[4].top", "139");
+    shouldBe("rects[4].width", "306");
+    shouldBe("rects[4].height", "18");
+
+    // Test 2
+    debug("Test 2")
+    var range2 = document.createRange();
+    range2.selectNodeContents(document.getElementById('test2'));
+    show(range2);
+    rects = range2.getClientRects();
+    shouldBe("rects.length", "4");
+    shouldBe("rects[0].left", "8");
+    shouldBe("rects[0].top", "215");
+    shouldBe("rects[0].width", "396");
+    shouldBe("rects[0].height", "18");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "255");
+    shouldBe("rects[1].width", "398");
+    shouldBe("rects[1].height", "18");
+    shouldBe("rects[2].left", "8");
+    shouldBe("rects[2].top", "295");
+    shouldBe("rects[2].width", "360");
+    shouldBe("rects[2].height", "18");
+    shouldBe("rects[3].left", "8");
+    shouldBe("rects[3].top", "335");
+    shouldBe("rects[3].width", "306");
+    shouldBe("rects[3].height", "18");
+
+    // Test 3
+    debug("Test 3")
+    var range3 = document.createRange();
+    range3.setStart(document.getElementById('test3').firstChild, 10);
+    range3.setEnd(document.getElementById('test3').lastChild, 200);
+    show(range3);
+    rects = range3.getClientRects();
+    shouldBe("rects.length", "4");
+    shouldBe("rects[0].left", "80");
+    shouldBe("rects[0].top", "411");
+    shouldBe("rects[0].width", "324");
+    shouldBe("rects[0].height", "18");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "451");
+    shouldBe("rects[1].width", "398");
+    shouldBe("rects[1].height", "18");
+    shouldBe("rects[2].left", "8");
+    shouldBe("rects[2].top", "491");
+    shouldBe("rects[2].width", "360");
+    shouldBe("rects[2].height", "18");
+    shouldBe("rects[3].left", "8");
+    shouldBe("rects[3].top", "531");
+    shouldBe("rects[3].width", "88");
+    shouldBe("rects[3].height", "18");
+
+    // Test 4 - Should not include rect of the img.
+    debug("Test 4")
+    var range4 = document.createRange();
+    range4.selectNode(document.getElementById('test4'));
+    show(range4);
+    rects = range4.getClientRects();
+    shouldBe("rects.length", "7");
+    shouldBe("rects[0].left", "8");
+    shouldBe("rects[0].top", "596");
+    shouldBe("rects[0].width", "400");
+    shouldBe("rects[0].height", "278");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "607");
+    shouldBe("rects[1].width", "396");
+    shouldBe("rects[1].height", "18");
+    shouldBe("rects[2].left", "8");
+    shouldBe("rects[2].top", "725");
+    shouldBe("rects[2].width", "242");
+    shouldBe("rects[2].height", "18");
+    shouldBe("rects[3].left", "326");
+    shouldBe("rects[3].top", "725");
+    shouldBe("rects[3].width", "44");
+    shouldBe("rects[3].height", "18");
+    shouldBe("rects[4].left", "8");
+    shouldBe("rects[4].top", "765");
+    shouldBe("rects[4].width", "341");
+    shouldBe("rects[4].height", "18");
+    shouldBe("rects[5].left", "8");
+    shouldBe("rects[5].top", "805");
+    shouldBe("rects[5].width", "366");
+    shouldBe("rects[5].height", "18");
+    shouldBe("rects[6].left", "8");
+    shouldBe("rects[6].top", "845");
+    shouldBe("rects[6].width", "67");
+    shouldBe("rects[6].height", "18");
+    
+    // Test 5 - Should include rect of the img.
+    debug("Test 5");
+    var range5 = document.createRange();
+    range5.setStart(document.getElementById('test5').firstChild, 10);
+    range5.setEnd(document.getElementById('test5').lastChild, 50);
+    show(range5);
+    rects = range5.getClientRects();
+    shouldBe("rects.length", "5");
+    shouldBe("rects[0].left", "80");
+    shouldBe("rects[0].top", "921");
+    shouldBe("rects[0].width", "324");
+    shouldBe("rects[0].height", "18");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "1039");
+    shouldBe("rects[1].width", "242");
+    shouldBe("rects[1].height", "18");
+    shouldBe("rects[2].left", "250");
+    shouldBe("rects[2].top", "950");
+    shouldBe("rects[2].width", "76");
+    shouldBe("rects[2].height", "103");
+    shouldBe("rects[3].left", "326");
+    shouldBe("rects[3].top", "1039");
+    shouldBe("rects[3].width", "44");
+    shouldBe("rects[3].height", "18");
+    shouldBe("rects[4].left", "8");
+    shouldBe("rects[4].top", "1079");
+    shouldBe("rects[4].width", "284");
+    shouldBe("rects[4].height", "18");
+
+    // Test 6 - Should not include green or blue boxes
+    debug("Test 6");
+    var range6 = document.createRange();
+    range6.selectNode(document.getElementById('test6'));
+    show(range6);
+    rects = range6.getClientRects();
+    shouldBe("rects.length", "7");
+    shouldBe("rects[0].left", "8");
+    shouldBe("rects[0].top", "1224");
+    shouldBe("rects[0].width", "400");
+    shouldBe("rects[0].height", "200");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "1235");
+    shouldBe("rects[1].width", "396");
+    shouldBe("rects[1].height", "18");
+    shouldBe("rects[2].left", "8");
+    shouldBe("rects[2].top", "1275");
+    shouldBe("rects[2].width", "57");
+    shouldBe("rects[2].height", "18");
+    shouldBe("rects[3].left", "105");
+    shouldBe("rects[3].top", "1275");
+    shouldBe("rects[3].width", "44");
+    shouldBe("rects[3].height", "18");
+    shouldBe("rects[4].left", "8");
+    shouldBe("rects[4].top", "1315");
+    shouldBe("rects[4].width", "387");
+    shouldBe("rects[4].height", "18");
+    shouldBe("rects[5].left", "8");
+    shouldBe("rects[5].top", "1355");
+    shouldBe("rects[5].width", "397");
+    shouldBe("rects[5].height", "18");
+    shouldBe("rects[6].left", "8");
+    shouldBe("rects[6].top", "1395");
+    shouldBe("rects[6].width", "171");
+    shouldBe("rects[6].height", "18");
+
+    // Test 7 - Should include green but not blue box
+    debug("Test 7");
+    var range7 = document.createRange();
+    range7.selectNodeContents(document.getElementById('test7'));
+    show(range7);
+    rects = range7.getClientRects();
+    shouldBe("rects.length", "7");
+    shouldBe("rects[0].left", "8");
+    shouldBe("rects[0].top", "1471");
+    shouldBe("rects[0].width", "396");
+    shouldBe("rects[0].height", "18");
+    shouldBe("rects[1].left", "8");
+    shouldBe("rects[1].top", "1500");
+    shouldBe("rects[1].width", "400");
+    shouldBe("rects[1].height", "40");
+    shouldBe("rects[2].left", "8");
+    shouldBe("rects[2].top", "1511");
+    shouldBe("rects[2].width", "57");
+    shouldBe("rects[2].height", "18");
+    shouldBe("rects[3].left", "105");
+    shouldBe("rects[3].top", "1511");
+    shouldBe("rects[3].width", "44");
+    shouldBe("rects[3].height", "18");
+    shouldBe("rects[4].left", "8");
+    shouldBe("rects[4].top", "1551");
+    shouldBe("rects[4].width", "387");
+    shouldBe("rects[4].height", "18");
+    shouldBe("rects[5].left", "8");
+    shouldBe("rects[5].top", "1591");
+    shouldBe("rects[5].width", "397");
+    shouldBe("rects[5].height", "18");
+    shouldBe("rects[6].left", "8");
+    shouldBe("rects[6].top", "1631");
+    shouldBe("rects[6].width", "171");
+    shouldBe("rects[6].height", "18");
+
+    // Test 8
+    debug("Test 8");
+    var range8 = document.createRange();
+    range8.selectNodeContents(document.getElementById('test8'));
+    show(range8);
+    rects = range8.getClientRects();
+    shouldBe("rects.length", "4");
+    shouldBe("rects[0].left", "168");
+    shouldBe("rects[0].top", "1678");
+    shouldBe("rects[0].width", "269");
+    shouldBe("rects[0].height", "316");
+    shouldBe("rects[1].left", "137");
+    shouldBe("rects[1].top", "1704");
+    shouldBe("rects[1].width", "271");
+    shouldBe("rects[1].height", "317");
+    shouldBe("rects[2].left", "107");
+    shouldBe("rects[2].top", "1729");
+    shouldBe("rects[2].width", "246");
+    shouldBe("rects[2].height", "289");
+    shouldBe("rects[3].left", "76");
+    shouldBe("rects[3].top", "1755");
+    shouldBe("rects[3].width", "212");
+    shouldBe("rects[3].height", "247");
+
+    if (window.layoutTestController) {
+        var area = document.getElementById('testArea');
+        area.parentNode.removeChild(area);
+    }
+
+    successfullyParsed = true;
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
diff --git a/LayoutTests/fast/dom/Window/window-properties-expected.txt b/LayoutTests/fast/dom/Window/window-properties-expected.txt
index c34542c..e48650e 100644
--- a/LayoutTests/fast/dom/Window/window-properties-expected.txt
+++ b/LayoutTests/fast/dom/Window/window-properties-expected.txt
@@ -1219,6 +1219,8 @@ window.Range.prototype.deleteContents [function]
 window.Range.prototype.detach [function]
 window.Range.prototype.expand [function]
 window.Range.prototype.extractContents [function]
+window.Range.prototype.getBoundingClientRect [function]
+window.Range.prototype.getClientRects [function]
 window.Range.prototype.insertNode [function]
 window.Range.prototype.intersectsNode [function]
 window.Range.prototype.isPointInRange [function]
diff --git a/LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport.html b/LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport.html
deleted file mode 100644
index c6777a1..0000000
--- a/LayoutTests/fast/dom/getBoundingClientRect-getClientRects-relative-to-viewport.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<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 element = document.getElementById('test');
-
-    // Get base numbers
-    var unScrolledBoundingBox = element.getBoundingClientRect();
-    var unScrolledBoundingBoxes = element.getClientRects();
-
-    // Test scrolling down
-    window.scrollBy(0, 50);
-    var scrolledDownBoundingBox = element.getBoundingClientRect();
-    var scrolledDownBoundingBoxes = element.getClientRects();
-
-    // Reset
-    window.scrollTo(0, 0);
-
-    // Test scrolling right
-    window.scrollBy(50, 0);
-    var scrolledRightBoundingBox = element.getBoundingClientRect();
-    var scrolledRightBoundingBoxes = element.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>
diff --git a/LayoutTests/fast/dom/getBoundingClientRect.html b/LayoutTests/fast/dom/getBoundingClientRect.html
deleted file mode 100644
index 51d038b..0000000
--- a/LayoutTests/fast/dom/getBoundingClientRect.html
+++ /dev/null
@@ -1,180 +0,0 @@
-<link rel="stylesheet" href="../js/resources/js-test-style.css">
-<script src="../js/resources/js-test-pre.js"></script>
-<style>
-    #base {
-        width: 300px;
-        height: 100px;
-    }
-
-    #border {
-        border: 10px solid #999;
-        width: 300px;
-        height: 100px;
-    }
-
-    #margin {
-        margin: 10px;
-        width: 300px;
-        height: 100px;
-    }
-
-    #transform {
-        -webkit-transform: translateX(50px) rotate(45deg);
-        width: 100px;
-        height: 100px;
-    }
-
-    #columns {
-        -webkit-column-count: 3;
-        width: 300px;
-    }
-
-    #inline {
-        display: inline;
-    }
-
-    #outer {
-        width: 100px;
-        height: 100px;
-    }
-
-    #inner {
-        width: 200px;
-        height: 200px;
-    }
-
-    table {
-        width: 300px;
-    }
-
-    img {
-        width: 100px;
-        height: 100px;
-    }
-
-    .testBox {
-        background-color: green;
-    }
-
-    #testArea {
-        width: 300px;
-    }
-
-    .bbox {
-        position:absolute;
-        outline: 5px solid rgba(255, 0, 0, .75);
-    }
-
-    #console {
-        position:absolute;
-        left: 500px;
-    }
-</style>
-
-<div id="console"></div>
-<div id="testArea">
-
-<p>1. Base</p>                  <div id="base" class="testBox"></div>
-<p>2. Border</p>                <div id="border" class="testBox"></div>
-<p>3. Margin</p>                <div id="margin" class="testBox"></div>
-<p>4. Transform</p>             <div id="transform" class="testBox"></div>
-<p>5. Column</p>                <div id="columns" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
-<p>6. In a column</p>           <div id="columns">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.<span id="in-columns" class="testBox knownFailure">In columns</span> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
-<p>7. Inline</p>                <div id="inline" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
-<p>8. Table</p>                 <table class="testBox"><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>9. Table with Caption</p>    <table class="testBox"><caption>caption</caption><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>10. Table Row</p>            <table><tr class="testBox"><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>11. Table Cell</p>           <table><tr><td class="testBox">table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>12. Big block in little</p>  <div id="outer" class="testBox"><div id="inner"></div></div>
-<p>13. Replaced in inline</p>   <span class="testBox">Lorem<img>ipsum</span>
-<p>14. Block in inline</p>      <span class="testBox">Lorem<div id="inner"></div>ipsum</span>
-<p>15. Float in inline</p>      <span class="testBox"><img style="float:right"></span>
-
-</div>
-
-<script>
-    if (window.layoutTestController)
-        layoutTestController.dumpAsText();
-
-    var testRect;
-    function testClientRect(toTest, expectedRect)
-    {
-        testRect = toTest;
-        
-        debug("testRect.top " + testRect.top);
-        debug("testRect.left " + testRect.left);
-        debug("testRect.width " + testRect.width);
-        debug("testRect.height " + testRect.height);
-        debug("testRect.bottom " + testRect.bottom);
-        debug("testRect.right " + testRect.right);
-        debug("");
-
-        shouldBe("testRect.top", String(expectedRect.top));
-        shouldBe("testRect.left", String(expectedRect.left));
-        shouldBe("testRect.width", String(expectedRect.width));
-        shouldBe("testRect.height", String(expectedRect.height));
-        shouldBe("testRect.bottom", "testRect.top + testRect.height");
-        shouldBe("testRect.right", "testRect.left + testRect.width");
-        debug("");
-    }
-
-    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);
-    }
-
-    var fail = undefined;
-
-    var expectedResults = [
-        /*1*/  { top: 42, left: 8, width: 300, height: 100 },
-        /*2*/  { top: 192, left: 8, width: 320, height: 120 },
-        /*3*/  { top: 362, left: 18, width: 300, height: 100 },
-        /*4*/  { top: 491, left: 37, width: 142, height: 142 },
-        /*5*/  { top: 662, left: 8, width: 300, height: 234 },
-        /*6*/  { top: fail, left: fail, width: fail, height: fail },
-        /*7*/  { top: 1230, left: 8, width: 299, height: 180 },
-        /*8*/  { top: 1460, left: 8, width: 300, height: 46 },
-        /*9*/  { top: 1556, left: 8, width: 300, height: 64 },
-        /*10*/ { top: 1672, left: 8, width: 300, height: 20 },
-        /*11*/ { top: 1768, left: 10, width: 147, height: 20 },
-        /*12*/ { top: 1862, left: 8, width: 100, height: 100 },
-        /*13*/ { top: 2098, left: 8, width: 180, height: 18 },
-        /*14*/ { top: 2166, left: 8, width: 200, height: 236 },
-        /*15*/ { top: 2452, left: 8, width: 0, height: 0 }
-    ];
-
-    function test(number, element)
-    {
-        debug("Client bounding rect for #" + number);
-
-        if (element.className.match("knownFailure")) {
-            debug("Known failure. Skipping.");
-            debug("");
-            return;
-        }
-
-        var boundingRect = element.getBoundingClientRect();
-        addBBoxOverClientRect(boundingRect);
-        testClientRect(boundingRect, expectedResults[number - 1]);
-    }
-
-    var tests = document.getElementsByClassName("testBox");
-    for (var i = 0; i < tests.length; ++i)
-        test(i + 1, tests[i]);
-
-    if (window.layoutTestController) {
-        var area = document.getElementById('testArea');
-        area.parentNode.removeChild(area);
-    }
-
-    successfullyParsed = true;
-</script>
-<script src="../js/resources/js-test-post.js"></script>
diff --git a/LayoutTests/fast/dom/getClientRects.html b/LayoutTests/fast/dom/getClientRects.html
deleted file mode 100644
index a7c117e..0000000
--- a/LayoutTests/fast/dom/getClientRects.html
+++ /dev/null
@@ -1,169 +0,0 @@
-<link rel="stylesheet" href="../js/resources/js-test-style.css">
-<script src="../js/resources/js-test-pre.js"></script>
-<style>
-    #base {
-        width: 300px;
-        height: 100px;
-    }
-
-    #border {
-        border: 10px solid #999;
-        width: 300px;
-        height: 100px;
-    }
-
-    #margin {
-        margin: 10px;
-        width: 300px;
-        height: 100px;
-    }
-
-    #transform {
-        -webkit-transform: translateX(50px) rotate(45deg);
-        width: 100px;
-        height: 100px;
-    }
-
-    #columns {
-        -webkit-column-count: 3;
-        width: 300px;
-    }
-
-    #inline {
-        display: inline;
-    }
-
-    #outer {
-        width: 100px;
-        height: 100px;
-    }
-
-    #inner {
-        width: 200px;
-        height: 200px;
-    }
-
-    table {
-        width: 300px;
-    }
-
-    img {
-        width: 100px;
-        height: 100px;
-    }
-
-    .testBox {
-        background-color: green;
-    }
-
-    #testArea {
-        width: 300px;
-    }
-
-    .bbox {
-        position:absolute;
-        outline: 5px solid rgba(255, 0, 0, .75);
-    }
-
-    #console {
-        position:absolute;
-        left: 500px;
-    }
-</style>
-
-<div id="console"></div>
-<div id="testArea">
-
-<p>1. Base</p>                  <div id="base" class="testBox"></div>
-<p>2. Border</p>                <div id="border" class="testBox"></div>
-<p>3. Margin</p>                <div id="margin" class="testBox"></div>
-<p>4. Transform</p>             <div id="transform" class="testBox"></div>
-<p>5. Column</p>                <div id="columns" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
-<p>6. In a column</p>           <div id="columns">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.<span id="in-columns" class="testBox knownFailure">In columns</span> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
-<p>7. Inline</p>                <div id="inline" class="testBox">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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
-<p>8. Table</p>                 <table class="testBox"><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>9. Table with Caption</p>    <table class="testBox"><caption>caption</caption><tr><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>10. Table Row</p>            <table><tr class="testBox"><td>table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>11. Table Cell</p>           <table><tr><td class="testBox">table data</td><td>table data</td></tr><tr><td>table data</td><td>table data</td></tr></table>
-<p>12. Big block in little</p>  <div id="outer" class="testBox"><div id="inner"></div></div>
-<p>13. Replaced in inline</p>   <span class="testBox">Lorem<img>ipsum</span>
-<p>14. Block in inline</p>      <span class="testBox">Lorem<div id="inner"></div>ipsum</span>
-<p>15. Float in inline</p>      <span class="testBox"><img style="float:right"></span>
-
-</div>
-<script>
-    if (window.layoutTestController)
-        layoutTestController.dumpAsText();
-
-    var testRects;
-    function testClientRects(rects, expectedNumberOfRects)
-    {
-        testRects = rects;
-        shouldBe("testRects.length", String(expectedNumberOfRects));
-        debug("");
-    }
-
-    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]);
-    }
-
-    var expectedResults = [
-        1,
-        1,
-        1,
-        1,
-        1,
-        1,
-        10,
-        1,
-        2,
-        1,
-        1,
-        1,
-        1,
-        3,
-        1
-    ];
-
-    function test(number, element)
-    {
-        debug("Client bounding rects for #" + number);
-
-        if (element.className.match("knownFailure")) {
-            debug("Known failure. Skipping.");
-            debug("");
-            return;
-        }
-
-        var boundingRects = element.getClientRects();
-        addBBoxOverClientRects(boundingRects);
-        testClientRects(boundingRects, expectedResults[number - 1]);
-    }
-
-    var tests = document.getElementsByClassName("testBox");
-    for (var i = 0; i < tests.length; ++i)
-        test(i + 1, tests[i]);
-
-    if (window.layoutTestController) {
-        var area = document.getElementById('testArea');
-        area.parentNode.removeChild(area);
-    }
-
-    successfullyParsed = true;
-</script>
-<script src="../js/resources/js-test-post.js"></script>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 940fdab..036fb5e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,32 @@
+2009-09-27  Sam Weinig  <sam at webkit.org>
+
+        Reviewed by Dan Bernstein.
+
+        Fix for https://bugs.webkit.org/show_bug.cgi?id=29760
+        Implement CSSOM Range.getClientRects/getBoundingClientRect 
+
+        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.
+
 2009-09-27  Simon Hausmann  <hausmann at webkit.org>
 
         Unreviewed fix for WebInspector with Qt build.
diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp
index 2730a43..50ff033 100644
--- a/WebCore/dom/Element.cpp
+++ b/WebCore/dom/Element.cpp
@@ -282,42 +282,6 @@ static int adjustForLocalZoom(int value, RenderObject* renderer)
     return static_cast<int>(value / zoomFactor);
 }
 
-static int adjustForAbsoluteZoom(int value, RenderObject* renderer)
-{
-    float zoomFactor = renderer->style()->effectiveZoom();
-    if (zoomFactor == 1)
-        return value;
-    // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
-    if (zoomFactor > 1)
-        value++;
-    return static_cast<int>(value / zoomFactor);
-}
-
-static FloatPoint adjustFloatPointForAbsoluteZoom(const FloatPoint& point, RenderObject* renderer)
-{
-    // The result here is in floats, so we don't need the truncation hack from the integer version above.
-    float zoomFactor = renderer->style()->effectiveZoom();
-    if (zoomFactor == 1)
-        return point;
-    return FloatPoint(point.x() / zoomFactor, point.y() / zoomFactor);
-}
-
-static void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* renderer)
-{
-    quad.setP1(adjustFloatPointForAbsoluteZoom(quad.p1(), renderer));
-    quad.setP2(adjustFloatPointForAbsoluteZoom(quad.p2(), renderer));
-    quad.setP3(adjustFloatPointForAbsoluteZoom(quad.p3(), renderer));
-    quad.setP4(adjustFloatPointForAbsoluteZoom(quad.p4(), renderer));
-}
-
-static void adjustIntRectForAbsoluteZoom(IntRect& rect, RenderObject* renderer)
-{
-    rect.setX(adjustForAbsoluteZoom(rect.x(), renderer));
-    rect.setY(adjustForAbsoluteZoom(rect.y(), renderer));
-    rect.setWidth(adjustForAbsoluteZoom(rect.width(), renderer));
-    rect.setHeight(adjustForAbsoluteZoom(rect.height(), renderer));
-}
-
 int Element::offsetLeft()
 {
     document()->updateLayoutIgnorePendingStylesheets();
diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp
index 0503597..122130d 100644
--- a/WebCore/dom/Range.cpp
+++ b/WebCore/dom/Range.cpp
@@ -3,7 +3,7 @@
  * (C) 2000 Gunnstein Lye (gunnstein at netcom.no)
  * (C) 2000 Frederik Holljen (frederik.holljen at hig.no)
  * (C) 2001 Peter Kelly (pmk at post.com)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -26,7 +26,10 @@
 #include "RangeException.h"
 
 #include "CString.h"
+#include "ClientRect.h"
+#include "ClientRectList.h"
 #include "DocumentFragment.h"
+#include "FrameView.h"
 #include "HTMLElement.h"
 #include "NodeWithIndex.h"
 #include "ProcessingInstruction.h"
@@ -1821,4 +1824,89 @@ void Range::expand(const String& unit, ExceptionCode& ec)
     setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), ec);
 }
 
+PassRefPtr<ClientRectList> Range::getClientRects() const
+{
+    if (!m_start.container())
+        return 0;
+
+    m_ownerDocument->updateLayoutIgnorePendingStylesheets();
+
+    Vector<FloatQuad> quads;
+    getBorderAndTextQuads(quads);
+
+    return ClientRectList::create(quads);
+}
+
+PassRefPtr<ClientRect> Range::getBoundingClientRect() const
+{
+    if (!m_start.container())
+        return 0;
+
+    m_ownerDocument->updateLayoutIgnorePendingStylesheets();
+
+    Vector<FloatQuad> quads;
+    getBorderAndTextQuads(quads);
+
+    if (quads.isEmpty())
+        return ClientRect::create();
+
+    IntRect result;
+    for (size_t i = 0; i < quads.size(); ++i)
+        result.unite(quads[i].enclosingBoundingBox());
+
+    return ClientRect::create(result);
+}
+
+static void adjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad>& quads, Document* document, RenderObject* renderer)
+{
+    FrameView* view = document->view();
+    if (!view)
+        return;
+
+    IntRect visibleContentRect = view->visibleContentRect();
+    for (size_t i = 0; i < quads.size(); ++i) {
+        quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
+        adjustFloatQuadForAbsoluteZoom(quads[i], renderer);
+    }
+}
+
+void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const
+{
+    Node* startContainer = m_start.container();
+    Node* endContainer = m_end.container();
+    Node* stopNode = pastLastNode();
+
+    HashSet<Node*> nodeSet;
+    for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
+        if (node->isElementNode())
+            nodeSet.add(node);
+    }
+
+    for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
+        if (node->isElementNode()) {
+            if (!nodeSet.contains(node->parentNode())) {
+                if (RenderBoxModelObject* renderBoxModelObject = static_cast<Element*>(node)->renderBoxModelObject()) {
+                    Vector<FloatQuad> elementQuads;
+                    renderBoxModelObject->absoluteQuads(elementQuads);
+                    adjustFloatQuadsForScrollAndAbsoluteZoom(elementQuads, m_ownerDocument.get(), renderBoxModelObject);
+
+                    quads.append(elementQuads);
+                }
+            }
+        } else if (node->isTextNode()) {
+            if (RenderObject* renderer = static_cast<Text*>(node)->renderer()) {
+                RenderText* renderText = toRenderText(renderer);
+                int startOffset = (node == startContainer) ? m_start.offset() : 0;
+                int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX;
+                
+                Vector<FloatQuad> textQuads;
+                renderText->absoluteQuadsForRange(textQuads, startOffset, endOffset);
+                adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, m_ownerDocument.get(), renderText);
+
+                quads.append(textQuads);
+            }
+        }
+    }
 }
+
+} // namespace WebCore
diff --git a/WebCore/dom/Range.h b/WebCore/dom/Range.h
index 3382c84..e2e282b 100644
--- a/WebCore/dom/Range.h
+++ b/WebCore/dom/Range.h
@@ -3,7 +3,7 @@
  * (C) 2000 Gunnstein Lye (gunnstein at netcom.no)
  * (C) 2000 Frederik Holljen (frederik.holljen at hig.no)
  * (C) 2001 Peter Kelly (pmk at post.com)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -25,12 +25,15 @@
 #ifndef Range_h
 #define Range_h
 
+#include "FloatQuad.h"
 #include "RangeBoundaryPoint.h"
+#include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
-#include <wtf/Vector.h>
 
 namespace WebCore {
 
+class ClientRect;
+class ClientRectList;
 class DocumentFragment;
 class NodeWithIndex;
 class Text;
@@ -117,6 +120,9 @@ public:
     // for details.
     void expand(const String&, ExceptionCode&);
 
+    PassRefPtr<ClientRectList> getClientRects() const;
+    PassRefPtr<ClientRect> getBoundingClientRect() const;
+
 #ifndef NDEBUG
     void formatForDebugger(char* buffer, unsigned length) const;
 #endif
@@ -135,6 +141,8 @@ private:
     enum ActionType { DELETE_CONTENTS, EXTRACT_CONTENTS, CLONE_CONTENTS };
     PassRefPtr<DocumentFragment> processContents(ActionType, ExceptionCode&);
 
+    void getBorderAndTextQuads(Vector<FloatQuad>&) const;
+
     RefPtr<Document> m_ownerDocument;
     RangeBoundaryPoint m_start;
     RangeBoundaryPoint m_end;
diff --git a/WebCore/dom/Range.idl b/WebCore/dom/Range.idl
index 633bd90..9024e09 100644
--- a/WebCore/dom/Range.idl
+++ b/WebCore/dom/Range.idl
@@ -85,6 +85,13 @@ module ranges {
         void detach()
             raises(DOMException);
 
+#if defined(LANGUAGE_JAVASCRIPT) || LANGUAGE_JAVASCRIPT
+        // CSSOM View Module API extensions
+
+        ClientRectList getClientRects();
+        ClientRect getBoundingClientRect();
+#endif
+
         // extensions
 
         DocumentFragment createContextualFragment(in DOMString html)
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index e5a0c16..34f2b8b 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/WebCore/rendering/RenderObject.h
@@ -985,6 +985,42 @@ inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRenderi
 #endif
 }
 
+inline int adjustForAbsoluteZoom(int value, RenderObject* renderer)
+{
+    float zoomFactor = renderer->style()->effectiveZoom();
+    if (zoomFactor == 1)
+        return value;
+    // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
+    if (zoomFactor > 1)
+        value++;
+    return static_cast<int>(value / zoomFactor);
+}
+
+inline void adjustIntRectForAbsoluteZoom(IntRect& rect, RenderObject* renderer)
+{
+    rect.setX(adjustForAbsoluteZoom(rect.x(), renderer));
+    rect.setY(adjustForAbsoluteZoom(rect.y(), renderer));
+    rect.setWidth(adjustForAbsoluteZoom(rect.width(), renderer));
+    rect.setHeight(adjustForAbsoluteZoom(rect.height(), renderer));
+}
+
+inline FloatPoint adjustFloatPointForAbsoluteZoom(const FloatPoint& point, RenderObject* renderer)
+{
+    // The result here is in floats, so we don't need the truncation hack from the integer version above.
+    float zoomFactor = renderer->style()->effectiveZoom();
+    if (zoomFactor == 1)
+        return point;
+    return FloatPoint(point.x() / zoomFactor, point.y() / zoomFactor);
+}
+
+inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* renderer)
+{
+    quad.setP1(adjustFloatPointForAbsoluteZoom(quad.p1(), renderer));
+    quad.setP2(adjustFloatPointForAbsoluteZoom(quad.p2(), renderer));
+    quad.setP3(adjustFloatPointForAbsoluteZoom(quad.p3(), renderer));
+    quad.setP4(adjustFloatPointForAbsoluteZoom(quad.p4(), renderer));
+}
+
 } // namespace WebCore
 
 #ifndef NDEBUG

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list