Reviewed by Darin.
authorthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Nov 2006 22:24:26 +0000 (22:24 +0000)
committerthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Nov 2006 22:24:26 +0000 (22:24 +0000)
        <rdar://problem/4713280> Would like to get an array of bounding rects rather than just the union of them for a DOMRange
        <rdar://problem/4804317> Would like SPI to get bounding box for a DOM range without having to change the selection

        Added lineBoxRects and boundingBox to Range and DOMRange. These methods correspond to the DOMNode methods.

        * bindings/objc/DOM.mm:
        (WebCore::kit):
        (-[DOMNode lineBoxRects]):
        (-[DOMRange boundingBox]):
        (-[DOMRange lineBoxRects]):
        * bindings/objc/DOMPrivate.h:
        * dom/Range.cpp:
        (WebCore::Range::boundingBox):
        (WebCore::Range::addLineBoxRects):
        * dom/Range.h:
        * rendering/RenderContainer.cpp:
        (WebCore::RenderContainer::addLineBoxRects):
        * rendering/RenderContainer.h:
        * rendering/RenderObject.cpp:
        (WebCore::RenderObject::addLineBoxRects):
        * rendering/RenderObject.h:
        * rendering/RenderText.cpp:
        (WebCore::RenderText::addLineBoxRects):
        * rendering/RenderText.h:

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

12 files changed:
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/objc/DOM.mm
WebCore/bindings/objc/DOMPrivate.h
WebCore/dom/Range.cpp
WebCore/dom/Range.h
WebCore/rendering/RenderContainer.cpp
WebCore/rendering/RenderContainer.h
WebCore/rendering/RenderObject.cpp
WebCore/rendering/RenderObject.h
WebCore/rendering/RenderText.cpp
WebCore/rendering/RenderText.h

index c1d8ac3c3f4951e229a71aa9508b84949e80da9f..fcc1e8a2f97a492369ac99c03455daaeb941d52c 100644 (file)
@@ -1,3 +1,32 @@
+2006-11-08  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Darin.
+
+        <rdar://problem/4713280> Would like to get an array of bounding rects rather than just the union of them for a DOMRange
+        <rdar://problem/4804317> Would like SPI to get bounding box for a DOM range without having to change the selection
+
+        Added lineBoxRects and boundingBox to Range and DOMRange. These methods correspond to the DOMNode methods.
+
+        * bindings/objc/DOM.mm:
+        (WebCore::kit):
+        (-[DOMNode lineBoxRects]):
+        (-[DOMRange boundingBox]):
+        (-[DOMRange lineBoxRects]):
+        * bindings/objc/DOMPrivate.h:
+        * dom/Range.cpp:
+        (WebCore::Range::boundingBox):
+        (WebCore::Range::addLineBoxRects):
+        * dom/Range.h:
+        * rendering/RenderContainer.cpp:
+        (WebCore::RenderContainer::addLineBoxRects):
+        * rendering/RenderContainer.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::addLineBoxRects):
+        * rendering/RenderObject.h:
+        * rendering/RenderText.cpp:
+        (WebCore::RenderText::addLineBoxRects):
+        * rendering/RenderText.h:
+
 2006-11-08  Anders Carlsson  <acarlsson@apple.com>
 
         Reviewed by Oliver.
index 5ec2fb4aa9530c76605ff757795fbcc9eaddcb46..148bf2b71a3b759108db045624494d47bd232776 100644 (file)
                0867D690FE84028FC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
                        mainGroup = 0867D691FE84028FC02AAC07 /* WebKit */;
                        productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
                        projectDirPath = "";
+                       projectRoot = "";
+                       shouldCheckCompatibility = 1;
                        targets = (
                                93F198A508245E59001E9ABC /* WebCore */,
                                DD041FBE09D9DDBE0010AF2A /* Derived Sources */,
index 581b09285a186c45013c501e31ad4910e8e27dbc..e71907569bef6269642b29251781a744e38aef58 100644 (file)
@@ -250,6 +250,15 @@ static Class elementClass(const QualifiedName& tag, Class defaultClass)
     return objcClass;
 }
 
+static NSArray *kit(const Vector<IntRect>& rects)
+{
+    size_t size = rects.size();
+    NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
+    for (size_t i = 0; i < size; ++i)
+        [array addObject:[NSValue valueWithRect:rects[i]]];
+    return array;
+}
+
 } // namespace WebCore
 
 @implementation DOMNode (WebCoreInternal)
@@ -367,7 +376,8 @@ static Class elementClass(const QualifiedName& tag, Class defaultClass)
 
 @implementation DOMNode (DOMNodeExtensions)
 
-// FIXME: this should be implemented in the implementation
+// FIXME: This should be implemented in Node so we don't have to fetch the renderer.
+// If it was, we could even autogenerate.
 - (NSRect)boundingBox
 {
     WebCore::RenderObject *renderer = [self _node]->renderer();
@@ -376,24 +386,37 @@ static Class elementClass(const QualifiedName& tag, Class defaultClass)
     return NSZeroRect;
 }
 
-// FIXME: this should be implemented in the implementation
+// FIXME: This should be implemented in Node so we don't have to fetch the renderer.
+// If it was, we could even autogenerate.
 - (NSArray *)lineBoxRects
 {
     WebCore::RenderObject *renderer = [self _node]->renderer();
     if (renderer) {
         Vector<WebCore::IntRect> rects;
-        renderer->lineBoxRects(rects);
-        size_t size = rects.size();
-        NSMutableArray *results = [NSMutableArray arrayWithCapacity:size];
-        for (size_t i = 0; i < size; ++i)
-            [results addObject:[NSValue valueWithRect:rects[i]]];
-        return results;
+        renderer->addLineBoxRects(rects);
+        return kit(rects);
     }
     return nil;
 }
 
 @end
 
+@implementation DOMRange (DOMRangeExtensions)
+
+- (NSRect)boundingBox
+{
+    return [self _range]->boundingBox();
+}
+
+- (NSArray *)lineBoxRects
+{
+    Vector<WebCore::IntRect> rects;
+    [self _range]->addLineBoxRects(rects);
+    return kit(rects);
+}
+
+@end
+
 // FIXME: this should be auto-generated
 @implementation DOMNode (DOMEventTarget)
 
index 067bba0bd22ea9f93079ef483f2e124563bca3bd..b622b2e5189d8e646f305af57a680ea76028bcae 100644 (file)
 - (NSString *)_text;
 @end
 
+@interface DOMRange (DOMRangeExtensions)
+- (NSRect)boundingBox;
+- (NSArray *)lineBoxRects;
+@end
+
 @interface DOMElement (WebPrivate)
 - (NSFont *)_font;
 - (NSData *)_imageTIFFRepresentation;
index 11c4156f443e04a70862fc0959c65a947f665cbc..6647ee85a743a03f6a389c7f46dcc4ff467199e5 100644 (file)
@@ -1494,6 +1494,38 @@ Node *Range::pastEndNode() const
     return m_endContainer->traverseNextSibling();
 }
 
+IntRect Range::boundingBox()
+{
+    IntRect result;
+    Vector<IntRect> rects;
+    addLineBoxRects(rects);
+    const size_t n = rects.size();
+    for (size_t i = 0; i < n; ++i)
+        result.unite(rects[i]);
+    return result;
+}
+
+void Range::addLineBoxRects(Vector<IntRect>& rects)
+{
+    if (!m_startContainer || !m_endContainer)
+        return;
+
+    RenderObject* start = m_startContainer->renderer();
+    RenderObject* end = m_endContainer->renderer();
+    if (!start || !end)
+        return;
+
+    RenderObject* stop = end->nextInPreOrderAfterChildren();
+    for (RenderObject* r = start; r && r != stop; r = r->nextInPreOrder()) {
+        // only ask leaf render objects for their line box rects
+        if (!r->firstChild()) {
+            int startOffset = r == start ? m_startOffset : 0;
+            int endOffset = r == end ? m_endOffset : UINT_MAX;
+            r->addLineBoxRects(rects, startOffset, endOffset);
+        }
+    }
+}
+
 #ifndef NDEBUG
 #define FormatBufferSize 1024
 void Range::formatForDebugger(char *buffer, unsigned length) const
index f14ad3818a1a6b409c5a244af70634b787870416..33a8568db430cbffafe1070758a41ddaea89f30c 100644 (file)
@@ -30,6 +30,7 @@
 #include "Shared.h"
 #include <wtf/Forward.h>
 #include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
 
 namespace WebCore {
 
@@ -37,6 +38,7 @@ typedef int ExceptionCode;
 
 class DocumentFragment;
 class Document;
+class IntRect;
 class Node;
 class Position;
 class String;
@@ -109,6 +111,9 @@ public:
 
     Position editingStartPosition() const;
 
+    IntRect boundingBox();
+    void addLineBoxRects(Vector<IntRect>&);
+
 #ifndef NDEBUG
     void formatForDebugger(char* buffer, unsigned length) const;
 #endif
index 4c5f94ec49a2ca6322f1377c84383579663479f3..ecfbf3ce2fcc197e5c71030cf8a30a607e7b484b 100644 (file)
@@ -613,7 +613,7 @@ VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
     return VisiblePosition(element(), 0, DOWNSTREAM);
 }
 
-void RenderContainer::lineBoxRects(Vector<IntRect>& rects)
+void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end)
 {
     if (!firstChild() && (isInline() || isAnonymousBlock())) {
         int x, y;
@@ -625,7 +625,8 @@ void RenderContainer::lineBoxRects(Vector<IntRect>& rects)
     if (!firstChild())
         return;
 
-    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+    unsigned offset = start;
+    for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset) {
         if (child->isText() || child->isInline() || child->isAnonymousBlock()) {
             int x, y;
             child->absolutePositionForContent(x, y);
index f63bf157b46c5dc59c0be60a67c3514a47210e74..d873b61b2e215a578fd200eea88d644d7426b15c 100644 (file)
@@ -62,7 +62,7 @@ public:
 
     virtual VisiblePosition positionForCoordinates(int x, int y);
 
-    virtual void lineBoxRects(Vector<IntRect>&);
+    virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX);
 
 protected:
     void setFirstChild(RenderObject* first) { m_first = first; }
index a84a05b85986a481fa71c46ad166d8435b0642be..7fca61a2ae650b8e1fd9d6400bc4d51bf3ea620a 100644 (file)
@@ -1590,7 +1590,7 @@ void RenderObject::paintBorder(GraphicsContext* p, int _tx, int _ty, int w, int
         p->restore(); // Undo the clip.
 }
 
-void RenderObject::lineBoxRects(Vector<IntRect>&)
+void RenderObject::addLineBoxRects(Vector<IntRect>&, unsigned startOffset, unsigned endOffset)
 {
 }
 
index 5b9ea44fc0778f8a8bf830b5a087068482ddb3b5..789a809ff29bd3368051be347318cbefc9cc8ecc 100644 (file)
@@ -676,7 +676,7 @@ public:
     virtual int borderLeft() const { return style()->borderLeftWidth(); }
     virtual int borderRight() const { return style()->borderRightWidth(); }
 
-    virtual void lineBoxRects(Vector<IntRect>&);
+    virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX);
 
     virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
     IntRect absoluteBoundingBoxRect();
index 0e5be5467a9b507d6fa474c9ef0f1a4c8b26d5a2..1eb402816f4808de2d00d326c1c2df5867bcfa4a 100644 (file)
@@ -216,11 +216,24 @@ void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
         rects.append(IntRect(tx + box->xPos(), ty + box->yPos(), box->width(), box->height()));
 }
 
-void RenderText::lineBoxRects(Vector<IntRect>& rects)
+void RenderText::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end)
 {
     int x, y;
     absolutePositionForContent(x, y);
-    absoluteRects(rects, x, y);
+
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        if (start <= box->start() && box->end() <= end)
+            rects.append(IntRect(x + box->xPos(), y + box->yPos(), box->width(), box->height()));
+        else {
+            IntRect r = box->selectionRect(x, y, start, end);
+            if (!r.isEmpty()) {
+                // change the height and y position because selectionRect uses selection-specific values
+                r.setHeight(box->height());
+                r.setY(y + box->yPos());
+                rects.append(r);
+            }
+        }
+    }
 }
 
 InlineTextBox* RenderText::findNextInlineTextBox(int offset, int &pos) const
index 85a61ad99df045447b6aaf6fbed0ae5220cf30e3..64ab60328af1c5a4caa7201ee823e96a15214204 100644 (file)
@@ -73,7 +73,7 @@ public:
     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { assert(false); return false; }
 
     virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
-    virtual void lineBoxRects(Vector<IntRect>&);
+    virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX);
 
     virtual VisiblePosition positionForCoordinates(int x, int y);