webengine/osswebengine/WebCore/rendering/RenderContainer.cpp
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebCore/rendering/RenderContainer.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,655 @@
+/**
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderContainer.h"
+
+#include "AXObjectCache.h"
+#include "Document.h"
+#include "RenderCounter.h"
+#include "RenderImage.h"
+#include "RenderLayer.h"
+#include "RenderListItem.h"
+#include "RenderTable.h"
+#include "RenderTextFragment.h"
+#include "RenderView.h"
+#include "htmlediting.h"
+
+namespace WebCore {
+
+RenderContainer::RenderContainer(Node* node)
+    : RenderBox(node)
+    , m_firstChild(0)
+    , m_lastChild(0)
+{
+}
+
+RenderContainer::~RenderContainer()
+{
+}
+
+void RenderContainer::destroy()
+{
+    destroyLeftoverChildren();
+    RenderBox::destroy();
+}
+
+void RenderContainer::destroyLeftoverChildren()
+{
+    while (m_firstChild) {
+        if (m_firstChild->isListMarker() || (m_firstChild->style()->styleType() == RenderStyle::FIRST_LETTER && !m_firstChild->isText()))
+            m_firstChild->remove();  // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
+        else {
+        // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
+            if (m_firstChild->element())
+                m_firstChild->element()->setRenderer(0);
+            m_firstChild->destroy();
+        }
+    }
+}
+
+bool RenderContainer::canHaveChildren() const
+{
+    return true;
+}
+
+static void updateListMarkerNumbers(RenderObject* child)
+{
+    for (RenderObject* r = child; r; r = r->nextSibling())
+        if (r->isListItem())
+            static_cast<RenderListItem*>(r)->updateValue();
+}
+
+void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    bool needsTable = false;
+
+    if (newChild->isListItem())
+        updateListMarkerNumbers(beforeChild ? beforeChild : m_lastChild);
+    else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
+        needsTable = !isTable();
+    else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
+        needsTable = !isTable();
+    else if (newChild->isTableSection())
+        needsTable = !isTable();
+    else if (newChild->isTableRow())
+        needsTable = !isTableSection();
+    else if (newChild->isTableCell()) {
+        needsTable = !isTableRow();
+        // I'm not 100% sure this is the best way to fix this, but without this
+        // change we recurse infinitely when trying to render the CSS2 test page:
+        // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
+        // See Radar 2925291.
+        if (needsTable && isTableCell() && !m_firstChild && !newChild->isTableCell())
+            needsTable = false;
+    }
+
+    if (needsTable) {
+        RenderTable *table;
+        if(!beforeChild)
+            beforeChild = m_lastChild;
+        if(beforeChild && beforeChild->isAnonymous() && beforeChild->isTable())
+            table = static_cast<RenderTable*>(beforeChild);
+        else {
+            table = new (renderArena()) RenderTable(document() /* is anonymous */);
+            RenderStyle *newStyle = new (renderArena()) RenderStyle;
+            newStyle->inheritFrom(style());
+            newStyle->setDisplay(TABLE);
+            table->setStyle(newStyle);
+            addChild(table, beforeChild);
+        }
+        table->addChild(newChild);
+    } else {
+        // just add it...
+        insertChildNode(newChild, beforeChild);
+    }
+    
+    if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
+        RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
+        if (textToTransform)
+            static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
+    }
+}
+
+RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
+{
+    ASSERT(oldChild->parent() == this);
+
+    // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
+    // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
+    // disappears gets repainted properly.
+    if (!documentBeingDestroyed() && fullRemove) {
+        oldChild->setNeedsLayoutAndPrefWidthsRecalc();
+        oldChild->repaint();
+    }
+        
+    // If we have a line box wrapper, delete it.
+    oldChild->deleteLineBoxWrapper();
+
+    if (!documentBeingDestroyed() && fullRemove) {
+        // if we remove visible child from an invisible parent, we don't know the layer visibility any more
+        RenderLayer* layer = 0;
+        if (m_style->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
+            layer = enclosingLayer();
+            layer->dirtyVisibleContentStatus();
+        }
+
+         // Keep our layer hierarchy updated.
+        if (oldChild->firstChild() || oldChild->hasLayer()) {
+            if (!layer) layer = enclosingLayer();            
+            oldChild->removeLayers(layer);
+        }
+        
+        // renumber ordered lists
+        if (oldChild->isListItem())
+            updateListMarkerNumbers(oldChild->nextSibling());
+        
+        if (oldChild->isPositioned() && childrenInline())
+            dirtyLinesFromChangedChild(oldChild);
+    }
+    
+    // If oldChild is the start or end of the selection, then clear the selection to
+    // avoid problems of invalid pointers.
+    // FIXME: The SelectionController should be responsible for this when it
+    // is notified of DOM mutations.
+    if (!documentBeingDestroyed() && oldChild->isSelectionBorder())
+        view()->clearSelection();
+
+    // remove the child
+    if (oldChild->previousSibling())
+        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+    if (oldChild->nextSibling())
+        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+    if (m_firstChild == oldChild)
+        m_firstChild = oldChild->nextSibling();
+    if (m_lastChild == oldChild)
+        m_lastChild = oldChild->previousSibling();
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParent(0);
+
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+
+    return oldChild;
+}
+
+void RenderContainer::removeChild(RenderObject* oldChild)
+{
+    // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
+    // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
+    // layout anyway).
+    oldChild->removeFromObjectLists();
+    
+    removeChildNode(oldChild);
+}
+
+RenderObject* RenderContainer::beforeAfterContainer(RenderStyle::PseudoId type)
+{
+    if (type == RenderStyle::BEFORE) {
+        RenderObject* first = this;
+        do {
+            // Skip list markers.
+            first = first->firstChild();
+            while (first && first->isListMarker())
+                first = first->nextSibling();
+        } while (first && first->isAnonymous() && first->style()->styleType() == RenderStyle::NOPSEUDO);
+        if (first && first->style()->styleType() != type)
+            return 0;
+        return first;
+    }
+    if (type == RenderStyle::AFTER) {
+        RenderObject* last = this;
+        do {
+            last = last->lastChild();
+        } while (last && last->isAnonymous() && last->style()->styleType() == RenderStyle::NOPSEUDO && !last->isListMarker());
+        if (last && last->style()->styleType() != type)
+            return 0;
+        return last;
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void RenderContainer::updateBeforeAfterContent(RenderStyle::PseudoId type)
+{
+    // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
+    if (parent() && parent()->createsAnonymousWrapper())
+        return;
+    updateBeforeAfterContentForContainer(type, this);
+}
+
+void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId type, RenderContainer* styledObject)
+{
+    // In CSS2, before/after pseudo-content cannot nest.  Check this first.
+    if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
+        return;
+    
+    RenderStyle* pseudoElementStyle = styledObject->getPseudoStyle(type);
+    RenderObject* child = beforeAfterContainer(type);
+
+    // Whether or not we currently have generated content attached.
+    bool oldContentPresent = child;
+
+    // Whether or not we now want generated content.  
+    bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
+
+    // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
+    // :after content and not :before content.
+    if (newContentWanted && type == RenderStyle::BEFORE && isInlineContinuation())
+        newContentWanted = false;
+
+    // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
+    // then we don't generate the :after content.
+    if (newContentWanted && type == RenderStyle::AFTER && isRenderInline() && continuation())
+        newContentWanted = false;
+    
+    // If we don't want generated content any longer, or if we have generated content, but it's no longer
+    // identical to the new content data we want to build render objects for, then we nuke all
+    // of the old generated content.
+    if (!newContentWanted || (oldContentPresent && !child->style()->contentDataEquivalent(pseudoElementStyle))) {
+        // Nuke the child. 
+        if (child && child->style()->styleType() == type) {
+            oldContentPresent = false;
+            child->destroy();
+            child = (type == RenderStyle::BEFORE) ? m_firstChild : m_lastChild;
+        }
+    }
+
+    // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
+    // have no generated content and can now return.
+    if (!newContentWanted)
+        return;
+
+    if (isInlineFlow() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
+        !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
+        // According to the CSS2 spec (the end of section 12.1), the only allowed
+        // display values for the pseudo style are NONE and INLINE for inline flows.
+        // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
+        // For now we at least relax the restriction to allow all inline types like inline-block
+        // and inline-table.
+        pseudoElementStyle->setDisplay(INLINE);
+
+    if (oldContentPresent) {
+        if (child && child->style()->styleType() == type) {
+            // We have generated content present still.  We want to walk this content and update our
+            // style information with the new pseudo-element style.
+            child->setStyle(pseudoElementStyle);
+
+            // Note that if we ever support additional types of generated content (which should be way off
+            // in the future), this code will need to be patched.
+            for (RenderObject* genChild = child->firstChild(); genChild; genChild = genChild->nextSibling()) {
+                if (genChild->isText())
+                    // Generated text content is a child whose style also needs to be set to the pseudo-element style.
+                    genChild->setStyle(pseudoElementStyle);
+                else if (genChild->isImage()) {
+                    // Images get an empty style that inherits from the pseudo.
+                    RenderStyle* style = new (renderArena()) RenderStyle;
+                    style->inheritFrom(pseudoElementStyle);
+                    genChild->setStyle(style);
+                } else
+                    // Must be a first-letter container. updateFirstLetter() will take care of it.
+                    ASSERT(genChild->style()->styleType() == RenderStyle::FIRST_LETTER);
+            }
+        }
+        return; // We've updated the generated content. That's all we needed to do.
+    }
+    
+    RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? firstChild() : 0;
+
+    // Generated content consists of a single container that houses multiple children (specified
+    // by the content property).  This generated content container gets the pseudo-element style set on it.
+    RenderObject* generatedContentContainer = 0;
+    
+    // Walk our list of generated content and create render objects for each.
+    for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->m_next) {
+        RenderObject* renderer = 0;
+        switch (content->m_type) {
+            case CONTENT_NONE:
+                break;
+            case CONTENT_TEXT:
+                renderer = new (renderArena()) RenderTextFragment(document() /* anonymous object */, content->m_content.m_text);
+                renderer->setStyle(pseudoElementStyle);
+                break;
+            case CONTENT_OBJECT:
+                if (CachedResource* resource = content->m_content.m_object)
+                    if (resource->type() == CachedResource::ImageResource) {
+                        RenderImage* image = new (renderArena()) RenderImage(document()); // anonymous object
+                        RenderStyle* style = new (renderArena()) RenderStyle;
+                        style->inheritFrom(pseudoElementStyle);
+                        image->setStyle(style);
+                        image->setCachedImage(static_cast<CachedImage*>(resource));
+                        image->setIsAnonymousImage(true);
+                        renderer = image;
+                    }
+                break;
+            case CONTENT_COUNTER:
+                renderer = new (renderArena()) RenderCounter(document(), *content->m_content.m_counter);
+                renderer->setStyle(pseudoElementStyle);
+                break;
+        }
+
+        if (renderer) {
+            if (!generatedContentContainer) {
+                // Make a generated box that might be any display type now that we are able to drill down into children
+                // to find the original content properly.
+                generatedContentContainer = RenderObject::createObject(document(), pseudoElementStyle);
+                generatedContentContainer->setStyle(pseudoElementStyle);
+            }
+            generatedContentContainer->addChild(renderer);
+        }
+    }
+
+    // Add the pseudo after we've installed all our content so that addChild will be able to find the text
+    // inside the inline for e.g., first-letter styling.
+    if (generatedContentContainer)
+        addChild(generatedContentContainer, insertBefore);
+}
+
+bool RenderContainer::isAfterContent(RenderObject* child) const
+{
+    if (!child)
+        return false;
+    if (child->style()->styleType() != RenderStyle::AFTER)
+        return false;
+    // Text nodes don't have their own styles, so ignore the style on a text node.
+    if (child->isText() && !child->isBR())
+        return false;
+    return true;
+}
+
+void RenderContainer::appendChildNode(RenderObject* newChild, bool fullAppend)
+{
+    ASSERT(newChild->parent() == 0);
+    ASSERT(!isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
+
+    newChild->setParent(this);
+    RenderObject* lChild = m_lastChild;
+
+    if (lChild) {
+        newChild->setPreviousSibling(lChild);
+        lChild->setNextSibling(newChild);
+    } else
+        m_firstChild = newChild;
+
+    m_lastChild = newChild;
+    
+    if (fullAppend) {
+        // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
+        // and don't have a layer attached to ourselves.
+        RenderLayer* layer = 0;
+        if (newChild->firstChild() || newChild->hasLayer()) {
+            layer = enclosingLayer();
+            newChild->addLayers(layer, newChild);
+        }
+
+        // if the new child is visible but this object was not, tell the layer it has some visible content
+        // that needs to be drawn and layer visibility optimization can't be used
+        if (style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
+            if (!layer)
+                layer = enclosingLayer();
+            if (layer)
+                layer->setHasVisibleContent(true);
+        }
+        
+        if (!newChild->isFloatingOrPositioned() && childrenInline())
+            dirtyLinesFromChangedChild(newChild);
+    }
+
+    newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
+    if (!normalChildNeedsLayout())
+        setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+    
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+}
+
+void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool fullInsert)
+{
+    if (!beforeChild) {
+        appendChildNode(child);
+        return;
+    }
+
+    ASSERT(!child->parent());
+    while (beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock())
+        beforeChild = beforeChild->parent();
+    ASSERT(beforeChild->parent() == this);
+
+    ASSERT(!isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
+
+    if (beforeChild == m_firstChild)
+        m_firstChild = child;
+
+    RenderObject* prev = beforeChild->previousSibling();
+    child->setNextSibling(beforeChild);
+    beforeChild->setPreviousSibling(child);
+    if(prev) prev->setNextSibling(child);
+    child->setPreviousSibling(prev);
+
+    child->setParent(this);
+    
+    if (fullInsert) {
+        // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
+        // and don't have a layer attached to ourselves.
+        RenderLayer* layer = 0;
+        if (child->firstChild() || child->hasLayer()) {
+            layer = enclosingLayer();
+            child->addLayers(layer, child);
+        }
+
+        // if the new child is visible but this object was not, tell the layer it has some visible content
+        // that needs to be drawn and layer visibility optimization can't be used
+        if (style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
+            if (!layer)
+                layer = enclosingLayer();
+            if (layer)
+                layer->setHasVisibleContent(true);
+        }
+
+        
+        if (!child->isFloating() && childrenInline())
+            dirtyLinesFromChangedChild(child);
+    }
+
+    child->setNeedsLayoutAndPrefWidthsRecalc();
+    if (!normalChildNeedsLayout())
+        setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+    
+    if (AXObjectCache::accessibilityEnabled())
+        document()->axObjectCache()->childrenChanged(this);
+}
+
+void RenderContainer::layout()
+{
+    ASSERT(needsLayout());
+
+    view()->pushLayoutState(this, IntSize(m_x, m_y));
+
+    RenderObject* child = m_firstChild;
+    while (child) {
+        child->layoutIfNeeded();
+        ASSERT(child->isRenderInline() || !child->needsLayout());
+        child = child->nextSibling();
+    }
+
+    view()->popLayoutState();
+    setNeedsLayout(false);
+}
+
+void RenderContainer::removeLeftoverAnonymousBlock(RenderBlock* child)
+{
+    ASSERT(child->isAnonymousBlock());
+    ASSERT(!child->childrenInline());
+    
+    if (child->continuation()) 
+        return;
+    
+    RenderObject* firstAnChild = child->firstChild();
+    RenderObject* lastAnChild = child->lastChild();
+    if (firstAnChild) {
+        RenderObject* o = firstAnChild;
+        while(o) {
+            o->setParent(this);
+            o = o->nextSibling();
+        }
+        firstAnChild->setPreviousSibling(child->previousSibling());
+        lastAnChild->setNextSibling(child->nextSibling());
+        if (child->previousSibling())
+            child->previousSibling()->setNextSibling(firstAnChild);
+        if (child->nextSibling())
+            child->nextSibling()->setPreviousSibling(lastAnChild);
+    } else {
+        if (child->previousSibling())
+            child->previousSibling()->setNextSibling(child->nextSibling());
+        if (child->nextSibling())
+            child->nextSibling()->setPreviousSibling(child->previousSibling());
+    }
+    if (child == m_firstChild)
+        m_firstChild = firstAnChild;
+    if (child == m_lastChild)
+        m_lastChild = lastAnChild;
+    child->setParent(0);
+    child->setPreviousSibling(0);
+    child->setNextSibling(0);
+    if (!child->isText()) {
+        RenderContainer *c = static_cast<RenderContainer*>(child);
+        c->m_firstChild = 0;
+        c->m_next = 0;
+    }
+    child->destroy();
+}
+
+VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
+{
+    // no children...return this render object's element, if there is one, and offset 0
+    if (!m_firstChild)
+        return VisiblePosition(element(), 0, DOWNSTREAM);
+        
+    if (isTable() && element()) {
+        int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
+        int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
+        
+        if (x < 0 || x > right || y < 0 || y > bottom) {
+            if (x <= right / 2)
+                return VisiblePosition(Position(element(), 0));
+            else
+                return VisiblePosition(Position(element(), maxDeepOffset(element())));
+        }
+    }
+
+    // Pass off to the closest child.
+    int minDist = INT_MAX;
+    RenderObject* closestRenderer = 0;
+    int newX = x;
+    int newY = y;
+    if (isTableRow()) {
+        newX += xPos();
+        newY += yPos();
+    }
+    for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) {
+        if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow() 
+            || renderer->style()->visibility() != VISIBLE)
+            continue;
+        
+        int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->yPos());
+        int bottom = top + renderer->contentHeight();
+        int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->xPos());
+        int right = left + renderer->contentWidth();
+        
+        if (x <= right && x >= left && y <= top && y >= bottom) {
+            if (renderer->isTableRow())
+                return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos());
+            return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos());
+        }
+
+        // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
+        // and use a different compare depending on which piece (x, y) is in.
+        IntPoint cmp;
+        if (x > right) {
+            if (y < top)
+                cmp = IntPoint(right, top);
+            else if (y > bottom)
+                cmp = IntPoint(right, bottom);
+            else
+                cmp = IntPoint(right, y);
+        } else if (x < left) {
+            if (y < top)
+                cmp = IntPoint(left, top);
+            else if (y > bottom)
+                cmp = IntPoint(left, bottom);
+            else
+                cmp = IntPoint(left, y);
+        } else {
+            if (y < top)
+                cmp = IntPoint(x, top);
+            else
+                cmp = IntPoint(x, bottom);
+        }
+        
+        int x1minusx2 = cmp.x() - x;
+        int y1minusy2 = cmp.y() - y;
+        
+        int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
+        if (dist < minDist) {
+            closestRenderer = renderer;
+            minDist = dist;
+        }
+    }
+    
+    if (closestRenderer)
+        return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos());
+    
+    return VisiblePosition(element(), 0, DOWNSTREAM);
+}
+
+void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end)
+{
+    if (!m_firstChild && (isInline() || isAnonymousBlock())) {
+        int x, y;
+        absolutePositionForContent(x, y);
+        absoluteRects(rects, x, y);
+        return;
+    }
+
+    if (!m_firstChild)
+        return;
+
+    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);
+            child->absoluteRects(rects, x, y);
+        }
+    }
+}
+
+#undef DEBUG_LAYOUT
+
+} // namespace WebCore