webengine/osswebengine/WebCore/rendering/RenderLayer.cpp
changeset 0 dd21522fd290
child 62 c711bdda59f4
child 68 92a765b5b3e7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebCore/rendering/RenderLayer.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,2408 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <roc+@cs.cmu.edu>
+ *   David Baron <dbaron@fas.harvard.edu>
+ *   Christian Biesinger <cbiesinger@web.de>
+ *   Randall Jesup <rjesup@wgate.com>
+ *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *   Josh Soref <timeless@mac.com>
+ *   Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "RenderLayer.h"
+
+#include "CSSPropertyNames.h"
+#include "Document.h"
+#include "EventHandler.h"
+#include "EventNames.h"
+#include "FloatRect.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "FrameTree.h"
+#include "GraphicsContext.h"
+#include "HTMLMarqueeElement.h"
+#include "HTMLNames.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
+#include "OverflowEvent.h"
+#include "PlatformMouseEvent.h"
+#include "PlatformScrollBar.h" 
+#include "RenderArena.h"
+#include "RenderInline.h"
+#include "RenderTheme.h"
+#include "RenderView.h"
+#include "SelectionController.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+#define MIN_INTERSECT_FOR_REVEAL 32
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace EventNames;
+using namespace HTMLNames;
+
+#ifndef NDEBUG
+static bool inRenderLayerDestroy;
+#endif
+
+const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterIfNeeded = { RenderLayer::noScroll, RenderLayer::alignCenter, RenderLayer::alignToClosestEdge };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignToEdgeIfNeeded = { RenderLayer::noScroll, RenderLayer::alignToClosestEdge, RenderLayer::alignToClosestEdge };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterAlways = { RenderLayer::alignCenter, RenderLayer::alignCenter, RenderLayer::alignCenter };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignTopAlways = { RenderLayer::alignTop, RenderLayer::alignTop, RenderLayer::alignTop };
+const RenderLayer::ScrollAlignment RenderLayer::gAlignBottomAlways = { RenderLayer::alignBottom, RenderLayer::alignBottom, RenderLayer::alignBottom };
+
+const int MinimumWidthWhileResizing = 100;
+const int MinimumHeightWhileResizing = 40;
+
+void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void ClipRects::operator delete(void* ptr, size_t sz)
+{
+    // Stash size where destroy can find it.
+    *(size_t *)ptr = sz;
+}
+
+void ClipRects::destroy(RenderArena* renderArena)
+{
+    delete this;
+    
+    // Recover the size left there for us by operator delete and free the memory.
+    renderArena->free(*(size_t *)this, this);
+}
+
+RenderLayer::RenderLayer(RenderObject* object)
+    : m_object(object)
+    , m_parent(0)
+    , m_previous(0)
+    , m_next(0)
+    , m_first(0)
+    , m_last(0)
+    , m_relX(0)
+    , m_relY(0)
+    , m_x(0)
+    , m_y(0)
+    , m_width(0)
+    , m_height(0)
+    , m_scrollX(0)
+    , m_scrollY(0)
+    , m_scrollOriginX(0)
+    , m_scrollLeftOverflow(0)
+    , m_scrollWidth(0)
+    , m_scrollHeight(0)
+    , m_inResizeMode(false)
+    , m_posZOrderList(0)
+    , m_negZOrderList(0)
+    , m_overflowList(0)
+    , m_clipRects(0) 
+    , m_scrollDimensionsDirty(true)
+    , m_zOrderListsDirty(true)
+    , m_overflowListDirty(true)
+    , m_isOverflowOnly(shouldBeOverflowOnly())
+    , m_usedTransparency(false)
+    , m_inOverflowRelayout(false)
+    , m_needsFullRepaint(false)
+    , m_overflowStatusDirty(true)
+    , m_visibleContentStatusDirty(true)
+    , m_hasVisibleContent(false)
+    , m_visibleDescendantStatusDirty(false)
+    , m_hasVisibleDescendant(false)
+    , m_marquee(0)
+    , m_staticX(0)
+    , m_staticY(0)
+{
+    if (!object->firstChild() && object->style()) {
+        m_visibleContentStatusDirty = false;
+        m_hasVisibleContent = object->style()->visibility() == VISIBLE;
+    }
+}
+
+RenderLayer::~RenderLayer()
+{
+    destroyScrollbar(HorizontalScrollbar);
+    destroyScrollbar(VerticalScrollbar);
+
+    // Child layers will be deleted by their corresponding render objects, so
+    // we don't need to delete them ourselves.
+
+    delete m_posZOrderList;
+    delete m_negZOrderList;
+    delete m_overflowList;
+    delete m_marquee;
+    
+    // Make sure we have no lingering clip rects.
+    ASSERT(!m_clipRects);
+}
+
+void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
+{
+    if (doFullRepaint) {
+        m_object->repaint();
+        checkForRepaint = doFullRepaint = false;
+    }
+    
+    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
+                           // we need to keep in sync, since we may have shifted relative
+                           // to our parent layer.
+
+    positionOverflowControls();
+
+    updateVisibilityStatus();
+        
+    if (m_hasVisibleContent) {
+        RenderView* view = m_object->view();
+        ASSERT(view);
+        // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
+        // from updateScrollInfoAfterLayout().
+        ASSERT(!view->layoutState());
+
+        IntRect newRect = m_object->absoluteClippedOverflowRect();
+        IntRect newOutlineBox = m_object->absoluteOutlineBox();
+        if (checkForRepaint) {
+            if (view && !view->printing()) {
+                if (m_needsFullRepaint) {
+                    view->repaintViewRectangle(m_repaintRect);
+                    if (newRect != m_repaintRect)
+                        view->repaintViewRectangle(newRect);
+                } else
+                    m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_outlineBox);
+            }
+        }
+        m_repaintRect = newRect;
+        m_outlineBox = newOutlineBox;
+    } else {
+        m_repaintRect = IntRect();
+        m_outlineBox = IntRect();
+    }
+
+    m_needsFullRepaint = false;
+    
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->updateLayerPositions(doFullRepaint, checkForRepaint);
+        
+    // With all our children positioned, now update our marquee if we need to.
+    if (m_marquee)
+        m_marquee->updateMarqueePosition();
+}
+
+void RenderLayer::setHasVisibleContent(bool b) 
+{ 
+    if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
+        return;
+    m_visibleContentStatusDirty = false; 
+    m_hasVisibleContent = b;
+    if (m_hasVisibleContent) {
+        m_repaintRect = renderer()->absoluteClippedOverflowRect();
+        m_outlineBox = renderer()->absoluteOutlineBox();
+    }
+    if (parent())
+        parent()->childVisibilityChanged(m_hasVisibleContent);
+}
+
+void RenderLayer::dirtyVisibleContentStatus() 
+{ 
+    m_visibleContentStatusDirty = true; 
+    if (parent())
+        parent()->dirtyVisibleDescendantStatus();
+}
+
+void RenderLayer::childVisibilityChanged(bool newVisibility) 
+{ 
+    if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
+        return;
+    if (newVisibility) {
+        RenderLayer* l = this;
+        while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) {
+            l->m_hasVisibleDescendant = true;
+            l = l->parent();
+        }
+    } else 
+        dirtyVisibleDescendantStatus();
+}
+
+void RenderLayer::dirtyVisibleDescendantStatus()
+{
+    RenderLayer* l = this;
+    while (l && !l->m_visibleDescendantStatusDirty) {
+        l->m_visibleDescendantStatusDirty = true;
+        l = l->parent();
+    }
+}
+
+void RenderLayer::updateVisibilityStatus()
+{
+    if (m_visibleDescendantStatusDirty) {
+        m_hasVisibleDescendant = false;
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+            child->updateVisibilityStatus();        
+            if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
+                m_hasVisibleDescendant = true;
+                break;
+            }
+        }
+        m_visibleDescendantStatusDirty = false;
+    }
+
+    if (m_visibleContentStatusDirty) {
+        if (m_object->style()->visibility() == VISIBLE)
+            m_hasVisibleContent = true;
+        else {
+            // layer may be hidden but still have some visible content, check for this
+            m_hasVisibleContent = false;
+            RenderObject* r = m_object->firstChild();
+            while (r) {
+                if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
+                    m_hasVisibleContent = true;
+                    break;
+                }
+                if (r->firstChild() && !r->hasLayer())
+                    r = r->firstChild();
+                else if (r->nextSibling())
+                    r = r->nextSibling();
+                else {
+                    do {
+                        r = r->parent();
+                        if (r==m_object)
+                            r = 0;
+                    } while (r && !r->nextSibling());
+                    if (r)
+                        r = r->nextSibling();
+                }
+            }
+        }    
+        m_visibleContentStatusDirty = false; 
+    }
+}
+
+void RenderLayer::updateLayerPosition()
+{
+    // Clear our cached clip rect information.
+    clearClipRect();
+
+    int x = m_object->xPos();
+    int y = m_object->yPos() - m_object->borderTopExtra();
+
+    if (!m_object->isPositioned() && m_object->parent()) {
+        // We must adjust our position by walking up the render tree looking for the
+        // nearest enclosing object with a layer.
+        RenderObject* curr = m_object->parent();
+        while (curr && !curr->hasLayer()) {
+            if (!curr->isTableRow()) {
+                // Rows and cells share the same coordinate space (that of the section).
+                // Omit them when computing our xpos/ypos.
+                x += curr->xPos();
+                y += curr->yPos();
+            }
+            curr = curr->parent();
+        }
+        y += curr->borderTopExtra();
+        if (curr->isTableRow()) {
+            // Put ourselves into the row coordinate space.
+            x -= curr->xPos();
+            y -= curr->yPos();
+        }
+    }
+
+    m_relX = m_relY = 0;
+    if (m_object->isRelPositioned()) {
+        m_relX = static_cast<RenderBox*>(m_object)->relativePositionOffsetX();
+        m_relY = static_cast<RenderBox*>(m_object)->relativePositionOffsetY();
+        x += m_relX; y += m_relY;
+    }
+    
+    // Subtract our parent's scroll offset.
+    if (m_object->isPositioned() && enclosingPositionedAncestor()) {
+        RenderLayer* positionedParent = enclosingPositionedAncestor();
+
+        // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
+        positionedParent->subtractScrollOffset(x, y);
+        
+        if (m_object->isPositioned()) {
+            IntSize offset = static_cast<RenderBox*>(m_object)->offsetForPositionedInContainer(positionedParent->renderer());
+            x += offset.width();
+            y += offset.height();
+        }
+    } else if (parent())
+        parent()->subtractScrollOffset(x, y);
+    
+    setPos(x,y);
+
+    setWidth(m_object->width());
+    setHeight(m_object->height() + m_object->borderTopExtra() + m_object->borderBottomExtra());
+
+    if (!m_object->hasOverflowClip()) {
+        if (m_object->overflowWidth() > m_object->width())
+            setWidth(m_object->overflowWidth());
+        if (m_object->overflowHeight() > m_object->height())
+            setHeight(m_object->overflowHeight());
+    }
+}
+
+RenderLayer *RenderLayer::stackingContext() const
+{
+    RenderLayer* curr = parent();
+    for ( ; curr && !curr->m_object->isRenderView() && !curr->m_object->isRoot() &&
+          curr->m_object->style()->hasAutoZIndex();
+          curr = curr->parent());
+    return curr;
+}
+
+RenderLayer*
+RenderLayer::enclosingPositionedAncestor() const
+{
+    RenderLayer* curr = parent();
+    for ( ; curr && !curr->m_object->isRenderView() && !curr->m_object->isRoot() &&
+         !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
+         curr = curr->parent());
+         
+    return curr;
+}
+
+bool
+RenderLayer::isTransparent() const
+{
+#if ENABLE(SVG)
+    if (m_object->node()->namespaceURI() == SVGNames::svgNamespaceURI)
+        return false;
+#endif
+    return m_object->isTransparent();
+}
+
+RenderLayer*
+RenderLayer::transparentAncestor()
+{
+    RenderLayer* curr = parent();
+    for ( ; curr && !curr->isTransparent(); curr = curr->parent());
+    return curr;
+}
+
+static IntRect transparencyClipBox(RenderLayer* l)
+{
+    // FIXME: Although this completely ignores clipping, we ultimately intersect with the
+    // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
+    // would be better to respect clips.
+    IntRect clipRect = l->absoluteBoundingBox();
+    
+    // Note: we don't have to walk z-order lists since transparent elements always establish
+    // a stacking context.  This means we can just walk the layer tree directly. 
+    for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling())
+        clipRect.unite(transparencyClipBox(curr));
+    
+    return clipRect;
+}
+
+void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const IntRect& paintDirtyRect)
+{
+    if (p->paintingDisabled() || (isTransparent() && m_usedTransparency))
+        return;
+    
+    RenderLayer* ancestor = transparentAncestor();
+    if (ancestor)
+        ancestor->beginTransparencyLayers(p, paintDirtyRect);
+    
+    if (isTransparent()) {
+        m_usedTransparency = true;
+        IntRect clipRect = transparencyClipBox(this);
+        clipRect.intersect(paintDirtyRect);
+        p->save();
+        p->clip(clipRect);
+        p->beginTransparencyLayer(renderer()->opacity());
+    }
+}
+
+void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void RenderLayer::operator delete(void* ptr, size_t sz)
+{
+    ASSERT(inRenderLayerDestroy);
+    
+    // Stash size where destroy can find it.
+    *(size_t *)ptr = sz;
+}
+
+void RenderLayer::destroy(RenderArena* renderArena)
+{
+#ifndef NDEBUG
+    inRenderLayerDestroy = true;
+#endif
+    delete this;
+#ifndef NDEBUG
+    inRenderLayerDestroy = false;
+#endif
+    
+    // Recover the size left there for us by operator delete and free the memory.
+    renderArena->free(*(size_t *)this, this);
+}
+
+void RenderLayer::addChild(RenderLayer *child, RenderLayer* beforeChild)
+{
+    RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
+    if (prevSibling) {
+        child->setPreviousSibling(prevSibling);
+        prevSibling->setNextSibling(child);
+    }
+    else
+        setFirstChild(child);
+
+    if (beforeChild) {
+        beforeChild->setPreviousSibling(child);
+        child->setNextSibling(beforeChild);
+    }
+    else
+        setLastChild(child);
+   
+    child->setParent(this);
+
+    if (child->isOverflowOnly())
+        dirtyOverflowList();
+    else {
+        // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
+        // case where we're building up generated content layers.  This is ok, since the lists will start
+        // off dirty in that case anyway.
+        RenderLayer* stackingContext = child->stackingContext();
+        if (stackingContext)
+            stackingContext->dirtyZOrderLists();
+    }
+    
+    child->updateVisibilityStatus();
+    if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
+        childVisibilityChanged(true);
+}
+
+RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
+{
+    // remove the child
+    if (oldChild->previousSibling())
+        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+    if (oldChild->nextSibling())
+        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+    if (m_first == oldChild)
+        m_first = oldChild->nextSibling();
+    if (m_last == oldChild)
+        m_last = oldChild->previousSibling();
+
+    if (oldChild->isOverflowOnly())
+        dirtyOverflowList();
+    else { 
+        // Dirty the z-order list in which we are contained.  When called via the
+        // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
+        // from the main layer tree, so we need to null-check the |stackingContext| value.
+        RenderLayer* stackingContext = oldChild->stackingContext();
+        if (stackingContext)
+            stackingContext->dirtyZOrderLists();
+    }
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParent(0);
+    
+    oldChild->updateVisibilityStatus();
+    if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
+        childVisibilityChanged(false);
+    
+    return oldChild;
+}
+
+void RenderLayer::removeOnlyThisLayer()
+{
+    if (!m_parent)
+        return;
+    
+    // Dirty the clip rects.
+    clearClipRects();
+
+    // Remove us from the parent.
+    RenderLayer* parent = m_parent;
+    RenderLayer* nextSib = nextSibling();
+    parent->removeChild(this);
+    
+    // Now walk our kids and reattach them to our parent.
+    RenderLayer* current = m_first;
+    while (current) {
+        RenderLayer* next = current->nextSibling();
+        removeChild(current);
+        parent->addChild(current, nextSib);
+        current->updateLayerPositions();
+        current = next;
+    }
+    
+    destroy(renderer()->renderArena());
+}
+
+void RenderLayer::insertOnlyThisLayer()
+{
+    if (!m_parent && renderer()->parent()) {
+        // We need to connect ourselves when our renderer() has a parent.
+        // Find our enclosingLayer and add ourselves.
+        RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
+        if (parentLayer)
+            parentLayer->addChild(this, 
+                                  renderer()->parent()->findNextLayer(parentLayer, renderer()));
+    }
+    
+    // Remove all descendant layers from the hierarchy and add them to the new position.
+    for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
+        curr->moveLayers(m_parent, this);
+        
+    // Clear out all the clip rects.
+    clearClipRects();
+}
+
+void 
+RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
+{
+    if (ancestorLayer == this)
+        return;
+        
+    if (m_object->style()->position() == FixedPosition) {
+        // Add in the offset of the view.  We can obtain this by calling
+        // absolutePosition() on the RenderView.
+        int xOff, yOff;
+        m_object->absolutePosition(xOff, yOff, true);
+        x += xOff;
+        y += yOff;
+        return;
+    }
+ 
+    RenderLayer* parentLayer;
+    if (m_object->style()->position() == AbsolutePosition)
+        parentLayer = enclosingPositionedAncestor();
+    else
+        parentLayer = parent();
+    
+    if (!parentLayer) return;
+    
+    parentLayer->convertToLayerCoords(ancestorLayer, x, y);
+
+    x += xPos();
+    y += yPos();
+}
+
+void
+RenderLayer::scrollOffset(int& x, int& y)
+{
+    x += scrollXOffset() + m_scrollLeftOverflow;
+    y += scrollYOffset();
+}
+
+void
+RenderLayer::subtractScrollOffset(int& x, int& y)
+{
+    x -= scrollXOffset() + m_scrollLeftOverflow;
+    y -= scrollYOffset();
+}
+
+void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
+{
+    if (renderer()->style()->overflowX() != OMARQUEE) {
+        if (x < 0) x = 0;
+        if (y < 0) y = 0;
+    
+        // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
+        // to be (for overflow:hidden blocks).
+        int maxX = scrollWidth() - m_object->clientWidth();
+        int maxY = scrollHeight() - m_object->clientHeight();
+        
+        if (x > maxX) x = maxX;
+        if (y > maxY) y = maxY;
+    }
+    
+    // FIXME: Eventually, we will want to perform a blit.  For now never
+    // blit, since the check for blitting is going to be very
+    // complicated (since it will involve testing whether our layer
+    // is either occluded by another layer or clipped by an enclosing
+    // layer or contains fixed backgrounds, etc.).
+    m_scrollX = x - m_scrollOriginX;
+    m_scrollY = y;
+
+    // Update the positions of our child layers.
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->updateLayerPositions(false, false);
+    
+    RenderView* view = renderer()->view();
+    
+    // We should have a RenderView if we're trying to scroll.
+    ASSERT(view);
+    if (view) {
+        // Update dashboard regions, scrolling may change the clip of a
+        // particular region.
+        view->frameView()->updateDashboardRegions();
+
+        view->updateWidgetPositions();
+    }
+
+    // Just schedule a full repaint of our object.
+    if (repaint)
+        m_object->repaint();
+    
+    if (updateScrollbars) {
+        if (m_hBar)
+            m_hBar->setValue(scrollXOffset());
+        if (m_vBar)
+            m_vBar->setValue(m_scrollY);
+    }
+
+    // Schedule the scroll DOM event.
+    if (view)
+        if (FrameView* frameView = view->frameView())
+            frameView->scheduleEvent(new Event(scrollEvent, true, false), EventTargetNodeCast(renderer()->element()), true);
+}
+
+void RenderLayer::scrollRectToVisible(const IntRect &rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+    RenderLayer* parentLayer = 0;
+    IntRect newRect = rect;
+    int xOffset = 0, yOffset = 0;
+
+    // We may end up propagating a scroll event. It is important that we suspend events until 
+    // the end of the function since they could delete the layer or the layer's m_object.
+    FrameView* frameView = m_object->document()->view();
+    if (frameView)
+        frameView->pauseScheduledEvents();
+
+    bool restrictedByLineClamp = false;
+    if (m_object->parent()) {
+        parentLayer = m_object->parent()->enclosingLayer();
+        restrictedByLineClamp = m_object->parent()->style()->lineClamp() >= 0;
+    }
+
+    if (m_object->hasOverflowClip() && !restrictedByLineClamp) {
+        // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
+        // This will prevent us from revealing text hidden by the slider in Safari RSS.
+        int x, y;
+        m_object->absolutePosition(x, y);
+        x += m_object->borderLeft();
+        y += m_object->borderTop();
+
+        IntRect layerBounds = IntRect(x + scrollXOffset(), y + scrollYOffset(), m_object->clientWidth(), m_object->clientHeight());
+        IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
+        IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
+        
+        xOffset = r.x() - x;
+        yOffset = r.y() - y;
+        // Adjust offsets if they're outside of the allowable range.
+        xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
+        yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
+        
+        if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {
+            int diffX = scrollXOffset();
+            int diffY = scrollYOffset();
+            scrollToOffset(xOffset, yOffset);
+            diffX = scrollXOffset() - diffX;
+            diffY = scrollYOffset() - diffY;
+            newRect.setX(rect.x() - diffX);
+            newRect.setY(rect.y() - diffY);
+        }
+    } else if (!parentLayer) {
+        if (frameView) {
+            if (m_object->document() && m_object->document()->ownerElement() && m_object->document()->ownerElement()->renderer()) {
+                IntRect viewRect = enclosingIntRect(frameView->visibleContentRect());
+                IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
+                
+                xOffset = r.x();
+                yOffset = r.y();
+                // Adjust offsets if they're outside of the allowable range.
+                xOffset = max(0, min(frameView->contentsWidth(), xOffset));
+                yOffset = max(0, min(frameView->contentsHeight(), yOffset));
+
+                frameView->setContentsPos(xOffset, yOffset);
+                parentLayer = m_object->document()->ownerElement()->renderer()->enclosingLayer();
+                newRect.setX(rect.x() - frameView->contentsX() + frameView->x());
+                newRect.setY(rect.y() - frameView->contentsY() + frameView->y());
+            } else {
+                IntRect viewRect = enclosingIntRect(frameView->visibleContentRectConsideringExternalScrollers());
+                IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
+                
+                // If this is the outermost view that RenderLayer needs to scroll, then we should scroll the view recursively
+                // Other apps, like Mail, rely on this feature.
+                frameView->scrollRectIntoViewRecursively(r);
+            }
+        }
+    }
+    
+    if (parentLayer)
+        parentLayer->scrollRectToVisible(newRect, alignX, alignY);
+
+    if (frameView)
+        frameView->resumeScheduledEvents();
+}
+
+IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+    // Determine the appropriate X behavior.
+    ScrollBehavior scrollX;
+    IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
+    int intersectWidth = intersection(visibleRect, exposeRectX).width();
+    if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
+        // If the rectangle is fully visible, use the specified visible behavior.
+        // If the rectangle is partially visible, but over a certain threshold,
+        // then treat it as fully visible to avoid unnecessary horizontal scrolling
+        scrollX = getVisibleBehavior(alignX);
+    else if (intersectWidth == visibleRect.width()) {
+        // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
+        scrollX = getVisibleBehavior(alignX);
+        if (scrollX == alignCenter)
+            scrollX = noScroll;
+    } else if (intersectWidth > 0)
+        // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
+        scrollX = getPartialBehavior(alignX);
+    else
+        scrollX = getHiddenBehavior(alignX);
+    // If we're trying to align to the closest edge, and the exposeRect is further right
+    // than the visibleRect, and not bigger than the visible area, then align with the right.
+    if (scrollX == alignToClosestEdge && exposeRect.right() > visibleRect.right() && exposeRect.width() < visibleRect.width())
+        scrollX = alignRight;
+
+    // Given the X behavior, compute the X coordinate.
+    int x;
+    if (scrollX == noScroll) 
+        x = visibleRect.x();
+    else if (scrollX == alignRight)
+        x = exposeRect.right() - visibleRect.width();
+    else if (scrollX == alignCenter)
+        x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
+    else
+        x = exposeRect.x();
+
+    // Determine the appropriate Y behavior.
+    ScrollBehavior scrollY;
+    IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
+    int intersectHeight = intersection(visibleRect, exposeRectY).height();
+    if (intersectHeight == exposeRect.height())
+        // If the rectangle is fully visible, use the specified visible behavior.
+        scrollY = getVisibleBehavior(alignY);
+    else if (intersectHeight == visibleRect.height()) {
+        // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
+        scrollY = getVisibleBehavior(alignY);
+        if (scrollY == alignCenter)
+            scrollY = noScroll;
+    } else if (intersectHeight > 0)
+        // If the rectangle is partially visible, use the specified partial behavior
+        scrollY = getPartialBehavior(alignY);
+    else
+        scrollY = getHiddenBehavior(alignY);
+    // If we're trying to align to the closest edge, and the exposeRect is further down
+    // than the visibleRect, and not bigger than the visible area, then align with the bottom.
+    if (scrollY == alignToClosestEdge && exposeRect.bottom() > visibleRect.bottom() && exposeRect.height() < visibleRect.height())
+        scrollY = alignBottom;
+
+    // Given the Y behavior, compute the Y coordinate.
+    int y;
+    if (scrollY == noScroll) 
+        y = visibleRect.y();
+    else if (scrollY == alignBottom)
+        y = exposeRect.bottom() - visibleRect.height();
+    else if (scrollY == alignCenter)
+        y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
+    else
+        y = exposeRect.y();
+
+    return IntRect(IntPoint(x, y), visibleRect.size());
+}
+
+void RenderLayer::autoscroll()
+{
+    Frame* frame = renderer()->document()->frame();
+    if (!frame)
+        return;
+
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return;
+
+    frame->eventHandler()->updateSelectionForMouseDrag();
+
+    IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
+    scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), gAlignToEdgeIfNeeded, gAlignToEdgeIfNeeded);    
+}
+
+void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
+{
+    if (!inResizeMode() || !m_object->hasOverflowClip())
+        return;
+
+    // Set the width and height of the shadow ancestor node if there is one.
+    // This is necessary for textarea elements since the resizable layer is in the shadow content.
+    Element* element = static_cast<Element*>(m_object->node()->shadowAncestorNode());
+    RenderBox* renderer = static_cast<RenderBox*>(element->renderer());
+
+    EResize resize = renderer->style()->resize();
+    if (resize == RESIZE_NONE)
+        return;
+
+    Document* document = element->document();
+    if (!document->frame()->eventHandler()->mousePressed())
+        return;
+
+    IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos()));
+
+    IntSize currentSize = IntSize(renderer->width(), renderer->height());
+
+    IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
+    element->setMinimumSizeForResizing(minimumSize);
+
+    IntSize difference = (currentSize + newOffset - oldOffset).expandedTo(minimumSize) - currentSize;
+
+    CSSStyleDeclaration* style = element->style();
+    bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
+
+    ExceptionCode ec;
+
+    if (difference.width()) {
+        if (element && element->isControl()) {
+            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
+            style->setProperty(CSS_PROP_MARGIN_LEFT, String::number(renderer->marginLeft()) + "px", false, ec);
+            style->setProperty(CSS_PROP_MARGIN_RIGHT, String::number(renderer->marginRight()) + "px", false, ec);
+        }
+        int baseWidth = renderer->width() - (isBoxSizingBorder ? 0
+            : renderer->borderLeft() + renderer->paddingLeft() + renderer->borderRight() + renderer->paddingRight());
+        style->setProperty(CSS_PROP_WIDTH, String::number(baseWidth + difference.width()) + "px", false, ec);
+    }
+
+    if (difference.height()) {
+        if (element && element->isControl()) {
+            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
+            style->setProperty(CSS_PROP_MARGIN_TOP, String::number(renderer->marginTop()) + "px", false, ec);
+            style->setProperty(CSS_PROP_MARGIN_BOTTOM, String::number(renderer->marginBottom()) + "px", false, ec);
+        }
+        int baseHeight = renderer->height() - (isBoxSizingBorder ? 0
+            : renderer->borderTop() + renderer->paddingTop() + renderer->borderBottom() + renderer->paddingBottom());
+        style->setProperty(CSS_PROP_HEIGHT, String::number(baseHeight + difference.height()) + "px", false, ec);
+    }
+
+    document->updateLayout();
+
+    // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
+}
+
+PlatformScrollbar* RenderLayer::horizontalScrollbarWidget() const
+{
+    if (m_hBar && m_hBar->isWidget())
+        return static_cast<PlatformScrollbar*>(m_hBar.get());
+    return 0;
+}
+
+PlatformScrollbar* RenderLayer::verticalScrollbarWidget() const
+{
+    if (m_vBar && m_vBar->isWidget())
+        return static_cast<PlatformScrollbar*>(m_vBar.get());
+    return 0;
+}
+
+void RenderLayer::valueChanged(Scrollbar*)
+{
+    // Update scroll position from scrollbars.
+
+    bool needUpdate = false;
+    int newX = scrollXOffset();
+    int newY = m_scrollY;
+    
+    if (m_hBar) {
+        newX = m_hBar->value();
+        if (newX != scrollXOffset())
+           needUpdate = true;
+    }
+
+    if (m_vBar) {
+        newY = m_vBar->value();
+        if (newY != m_scrollY)
+           needUpdate = true;
+    }
+
+    if (needUpdate)
+        scrollToOffset(newX, newY, false);
+}
+
+IntRect RenderLayer::windowClipRect() const
+{
+    RenderView* view = renderer()->view();
+    ASSERT(view);
+    FrameView* frameView = view->frameView();
+    if (!frameView)
+        return IntRect();
+    return frameView->windowClipRectForLayer(this, false);
+}
+
+PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
+{
+    if (Scrollbar::hasPlatformScrollbars()) {
+        RefPtr<PlatformScrollbar> widget = new PlatformScrollbar(this, orientation, RegularScrollbar);
+        m_object->document()->view()->addChild(widget.get());
+        return widget.release();
+    }
+    
+    // FIXME: Create scrollbars using the engine.
+    return 0;
+}
+
+void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
+{
+    RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
+    if (scrollbar) {
+        if (scrollbar->isWidget())
+            static_cast<PlatformScrollbar*>(scrollbar.get())->removeFromParent();
+
+        // FIXME: Destroy the engine scrollbar.
+        scrollbar = 0;
+    }
+}
+
+void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar == (m_hBar != 0))
+        return;
+
+    if (hasScrollbar)
+        m_hBar = createScrollbar(HorizontalScrollbar);
+    else
+        destroyScrollbar(HorizontalScrollbar);
+
+    // Force an update since we know the scrollbars have changed things.
+    if (m_object->document()->hasDashboardRegions())
+        m_object->document()->setDashboardRegionsDirty(true);
+}
+
+void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar == (m_vBar != 0))
+        return;
+
+    if (hasScrollbar)
+        m_vBar = createScrollbar(VerticalScrollbar);
+    else
+        destroyScrollbar(VerticalScrollbar);
+
+    // Force an update since we know the scrollbars have changed things.
+    if (m_object->document()->hasDashboardRegions())
+        m_object->document()->setDashboardRegionsDirty(true);
+}
+
+int RenderLayer::verticalScrollbarWidth() const
+{
+    if (!m_vBar)
+        return 0;
+    return m_vBar->width();
+}
+
+int RenderLayer::horizontalScrollbarHeight() const
+{
+    if (!m_hBar)
+        return 0;
+    return m_hBar->height();
+}
+
+IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& p) const
+{
+    // Currently the resize corner is always the bottom right corner
+    int x = width();
+    int y = height();
+    convertToLayerCoords(root(), x, y);
+    return p - IntPoint(x, y);
+}
+
+static IntRect scrollCornerRect(RenderObject* renderer, const IntRect& absBounds)
+{
+    int resizerWidth = PlatformScrollbar::verticalScrollbarWidth();
+    int resizerHeight = PlatformScrollbar::horizontalScrollbarHeight();
+    return IntRect(absBounds.right() - resizerWidth - renderer->style()->borderRightWidth(), 
+                   absBounds.bottom() - resizerHeight - renderer->style()->borderBottomWidth(), resizerWidth, resizerHeight);
+}
+
+void RenderLayer::positionOverflowControls()
+{
+    if (!m_hBar && !m_vBar && (!m_object->hasOverflowClip() || m_object->style()->resize() == RESIZE_NONE))
+        return;
+    
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(root(), x, y);
+    IntRect absBounds(x, y, m_object->width(), m_object->height());
+    
+    IntRect resizeControlRect;
+    if (m_object->style()->resize() != RESIZE_NONE)
+        resizeControlRect = scrollCornerRect(m_object, absBounds);
+    
+    int resizeControlSize = max(resizeControlRect.height(), 0);
+    if (m_vBar)
+        m_vBar->setRect(IntRect(absBounds.right() - m_object->borderRight() - m_vBar->width(),
+                                absBounds.y() + m_object->borderTop(),
+                                m_vBar->width(),
+                                absBounds.height() - (m_object->borderTop() + m_object->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize)));
+
+    resizeControlSize = max(resizeControlRect.width(), 0);
+    if (m_hBar)
+        m_hBar->setRect(IntRect(absBounds.x() + m_object->borderLeft(),
+                                absBounds.bottom() - m_object->borderBottom() - m_hBar->height(),
+                                absBounds.width() - (m_object->borderLeft() + m_object->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
+                                m_hBar->height()));
+}
+
+int RenderLayer::scrollWidth()
+{
+    if (m_scrollDimensionsDirty)
+        computeScrollDimensions();
+    return m_scrollWidth;
+}
+
+int RenderLayer::scrollHeight()
+{
+    if (m_scrollDimensionsDirty)
+        computeScrollDimensions();
+    return m_scrollHeight;
+}
+
+void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
+{
+    m_scrollDimensionsDirty = false;
+    
+    bool ltr = m_object->style()->direction() == LTR;
+
+    int clientWidth = m_object->clientWidth();
+    int clientHeight = m_object->clientHeight();
+
+    m_scrollLeftOverflow = ltr ? 0 : min(0, m_object->leftmostPosition(true, false) - m_object->borderLeft());
+
+    int rightPos = ltr ?
+                    m_object->rightmostPosition(true, false) - m_object->borderLeft() :
+                    clientWidth - m_scrollLeftOverflow;
+    int bottomPos = m_object->lowestPosition(true, false) - m_object->borderTop();
+
+    m_scrollWidth = max(rightPos, clientWidth);
+    m_scrollHeight = max(bottomPos, clientHeight);
+    
+    m_scrollOriginX = ltr ? 0 : m_scrollWidth - clientWidth;
+
+    if (needHBar)
+        *needHBar = rightPos > clientWidth;
+    if (needVBar)
+        *needVBar = bottomPos > clientHeight;
+}
+
+void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
+{
+    if (m_overflowStatusDirty) {
+        m_horizontalOverflow = horizontalOverflow;
+        m_verticalOverflow = verticalOverflow;
+        m_overflowStatusDirty = false;
+        
+        return;
+    }
+    
+    bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
+    bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
+    
+    if (horizontalOverflowChanged || verticalOverflowChanged) {
+        m_horizontalOverflow = horizontalOverflow;
+        m_verticalOverflow = verticalOverflow;
+        
+        if (FrameView* frameView = m_object->document()->view())
+            frameView->scheduleEvent(new OverflowEvent(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
+            EventTargetNodeCast(m_object->element()), true);
+    }
+}
+
+void
+RenderLayer::updateScrollInfoAfterLayout()
+{
+    m_scrollDimensionsDirty = true;
+
+    bool horizontalOverflow, verticalOverflow;
+    computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
+
+    if (m_object->style()->overflowX() != OMARQUEE) {
+        // Layout may cause us to be in an invalid scroll position.  In this case we need
+        // to pull our scroll offsets back to the max (or push them up to the min).
+        int newX = max(0, min(scrollXOffset(), scrollWidth() - m_object->clientWidth()));
+        int newY = max(0, min(m_scrollY, scrollHeight() - m_object->clientHeight()));
+        if (newX != scrollXOffset() || newY != m_scrollY) {
+            RenderView* view = m_object->view();
+            ASSERT(view);
+            // scrollToOffset() may call updateLayerPositions(), which doesn't work
+            // with LayoutState.
+            // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes.
+            if (view)
+                view->disableLayoutState();
+            scrollToOffset(newX, newY);
+            if (view)
+                view->enableLayoutState();
+        }
+    }
+
+    bool haveHorizontalBar = m_hBar;
+    bool haveVerticalBar = m_vBar;
+    
+    // overflow:scroll should just enable/disable.
+    if (m_object->style()->overflowX() == OSCROLL)
+        m_hBar->setEnabled(horizontalOverflow);
+    if (m_object->style()->overflowY() == OSCROLL)
+        m_vBar->setEnabled(verticalOverflow);
+
+    // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
+    // scrollbars that may be present.
+    if (m_object->style()->overflowX() == OHIDDEN && haveHorizontalBar)
+        setHasHorizontalScrollbar(false);
+    if (m_object->style()->overflowY() == OHIDDEN && haveVerticalBar)
+        setHasVerticalScrollbar(false);
+    
+    // overflow:auto may need to lay out again if scrollbars got added/removed.
+    bool scrollbarsChanged = (m_object->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) || 
+                             (m_object->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);    
+    if (scrollbarsChanged) {
+        if (m_object->hasAutoHorizontalScrollbar())
+            setHasHorizontalScrollbar(horizontalOverflow);
+        if (m_object->hasAutoVerticalScrollbar())
+            setHasVerticalScrollbar(verticalOverflow);
+
+        // Force an update since we know the scrollbars have changed things.
+        if (m_object->document()->hasDashboardRegions())
+            m_object->document()->setDashboardRegionsDirty(true);
+
+        m_object->repaint();
+
+        if (m_object->style()->overflowX() == OAUTO || m_object->style()->overflowY() == OAUTO) {
+            if (!m_inOverflowRelayout) {
+                // Our proprietary overflow: overlay value doesn't trigger a layout.
+                m_inOverflowRelayout = true;
+                m_object->setNeedsLayout(true);
+                if (m_object->isRenderBlock())
+                    static_cast<RenderBlock*>(m_object)->layoutBlock(true);
+                else
+                    m_object->layout();
+                m_inOverflowRelayout = false;
+            }
+        }
+    }
+    
+    // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
+    if (m_hBar && m_object->hasAutoHorizontalScrollbar())
+        m_hBar->setEnabled(true);
+    if (m_vBar && m_object->hasAutoVerticalScrollbar())
+        m_vBar->setEnabled(true);
+
+    // Set up the range (and page step/line step).
+    if (m_hBar) {
+        int clientWidth = m_object->clientWidth();
+        int pageStep = (clientWidth-PAGE_KEEP);
+        if (pageStep < 0) pageStep = clientWidth;
+        m_hBar->setSteps(LINE_STEP, pageStep);
+        m_hBar->setProportion(clientWidth, m_scrollWidth);
+        m_hBar->setValue(scrollXOffset());
+    }
+    if (m_vBar) {
+        int clientHeight = m_object->clientHeight();
+        int pageStep = (clientHeight-PAGE_KEEP);
+        if (pageStep < 0) pageStep = clientHeight;
+        m_vBar->setSteps(LINE_STEP, pageStep);
+        m_vBar->setProportion(clientHeight, m_scrollHeight);
+        m_object->repaintRectangle(IntRect(m_object->borderLeft() + m_object->clientWidth(),
+                                   m_object->borderTop(), verticalScrollbarWidth(), 
+                                   m_object->height() - m_object->borderTop() - m_object->borderBottom()));
+    }
+ 
+    if (m_object->element() && m_object->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
+        updateOverflowStatus(horizontalOverflow, verticalOverflow);
+}
+
+void RenderLayer::paintOverflowControls(GraphicsContext* p, int tx, int ty, const IntRect& damageRect)
+{
+    // Don't do anything if we have no overflow.
+    if (!m_object->hasOverflowClip())
+        return;
+    
+    // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes
+    // widgets can move without layout occurring (most notably when you scroll a document that
+    // contains fixed positioned elements).
+    positionOverflowControls();
+
+    // Now that we're sure the scrollbars are in the right place, paint them.
+    if (m_hBar)
+        m_hBar->paint(p, damageRect);
+    if (m_vBar)
+        m_vBar->paint(p, damageRect);
+    
+    // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
+    // edge of the box.
+    IntRect paddingBox(m_object->xPos() + m_object->borderLeft() + tx, 
+                       m_object->yPos() + m_object->borderTop() + ty, 
+                       m_object->width() - m_object->borderLeft() - m_object->borderRight(),
+                       m_object->height() - m_object->borderTop() - m_object->borderBottom());
+    IntRect hCorner;
+    if (m_hBar && paddingBox.width() - m_hBar->width() > 0) {
+        hCorner = IntRect(paddingBox.x() + m_hBar->width(),
+                          paddingBox.y() + paddingBox.height() - m_hBar->height(),
+                          paddingBox.width() - m_hBar->width(),
+                          m_hBar->height());
+        if (hCorner.intersects(damageRect))
+            p->fillRect(hCorner, Color::white);
+    }
+    if (m_vBar && paddingBox.height() - m_vBar->height() > 0) {
+        IntRect vCorner(paddingBox.x() + paddingBox.width() - m_vBar->width(),
+                        paddingBox.y() + m_vBar->height(),
+                        m_vBar->width(),
+                        paddingBox.height() - m_vBar->height());
+        if (vCorner != hCorner && vCorner.intersects(damageRect))
+            p->fillRect(vCorner, Color::white);
+    }
+
+    if (m_object->style()->resize() != RESIZE_NONE)  {
+        IntRect absBounds(m_object->xPos() + tx, m_object->yPos() + ty, m_object->width(), m_object->height());
+        IntRect scrollCorner = scrollCornerRect(m_object, absBounds);
+        if (!scrollCorner.intersects(damageRect))
+            return;
+
+        // Paint the resizer control.
+        static Image* resizeCornerImage;
+        if (!resizeCornerImage)
+            resizeCornerImage = Image::loadPlatformResource("textAreaResizeCorner");
+        IntPoint imagePoint(scrollCorner.right() - resizeCornerImage->width(), scrollCorner.bottom() - resizeCornerImage->height());
+        p->drawImage(resizeCornerImage, imagePoint);
+
+        // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
+        // Clipping will exclude the right and bottom edges of this frame.
+        if (m_hBar || m_vBar) {
+            p->save();
+            scrollCorner.setSize(IntSize(scrollCorner.width() + 1, scrollCorner.height() + 1));
+            p->setStrokeColor(Color(makeRGB(217, 217, 217)));
+            p->setStrokeThickness(1.0f);
+            p->setFillColor(Color::transparent);
+            p->drawRect(scrollCorner);
+            p->restore();
+        }
+    }
+}
+
+bool RenderLayer::isPointInResizeControl(const IntPoint& point)
+{
+    if (!m_object->hasOverflowClip() || m_object->style()->resize() == RESIZE_NONE)
+        return false;
+    
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(root(), x, y);
+    IntRect absBounds(x, y, m_object->width(), m_object->height());
+    return scrollCornerRect(m_object, absBounds).contains(point);
+}
+    
+bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
+{
+    if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
+        return false;
+
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(root(), x, y);
+    IntRect absBounds(x, y, renderer()->width(), renderer()->height());
+    
+    IntRect resizeControlRect;
+    if (renderer()->style()->resize() != RESIZE_NONE) {
+        resizeControlRect = scrollCornerRect(renderer(), absBounds);
+        if (resizeControlRect.contains(result.point()))
+            return true;
+    }
+
+    int resizeControlSize = max(resizeControlRect.height(), 0);
+
+    if (m_vBar) {
+        IntRect vBarRect(absBounds.right() - renderer()->borderRight() - m_vBar->width(), absBounds.y() + renderer()->borderTop(), m_vBar->width(), absBounds.height() - (renderer()->borderTop() + renderer()->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+        if (vBarRect.contains(result.point())) {
+            result.setScrollbar(verticalScrollbarWidget());
+            return true;
+        }
+    }
+
+    resizeControlSize = max(resizeControlRect.width(), 0);
+    if (m_hBar) {
+        IntRect hBarRect(absBounds.x() + renderer()->borderLeft(), absBounds.bottom() - renderer()->borderBottom() - m_hBar->height(), absBounds.width() - (renderer()->borderLeft() + renderer()->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize), m_hBar->height());
+        if (hBarRect.contains(result.point())) {
+            result.setScrollbar(horizontalScrollbarWidget());
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+    bool didHorizontalScroll = false;
+    bool didVerticalScroll = false;
+    
+    if (m_hBar) {
+        if (granularity == ScrollByDocument) {
+            // Special-case for the ScrollByDocument granularity. A document scroll can only be up 
+            // or down and in both cases the horizontal bar goes all the way to the left.
+            didHorizontalScroll = m_hBar->scroll(ScrollLeft, ScrollByDocument, multiplier);
+        } else
+            didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier);
+    }
+
+    if (m_vBar)
+        didVerticalScroll = m_vBar->scroll(direction, granularity, multiplier);
+
+    return (didHorizontalScroll || didVerticalScroll);
+}
+
+void
+RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot)
+{
+    paintLayer(this, p, damageRect, false, paintRestriction, paintingRoot);
+}
+
+static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
+{
+    // Work around bugs in focus ring clipping on Mac.
+    p->setFocusRingClip(clipRect);
+    if (paintDirtyRect == clipRect)
+        return;
+    p->save();
+    p->clip(clipRect);
+}
+
+static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
+{
+    // Work around bugs in focus ring clipping on Mac.
+    p->clearFocusRingClip();
+    if (paintDirtyRect == clipRect)
+        return;
+    p->restore();
+}
+
+void
+RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
+                        const IntRect& paintDirtyRect, bool haveTransparency, PaintRestriction paintRestriction,
+                        RenderObject *paintingRoot)
+{
+    // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
+    // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
+    // will do a full repaint().
+    if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
+        return;
+    
+    // Calculate the clip rects we should use.
+    IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
+    calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+    int x = layerBounds.x();
+    int y = layerBounds.y();
+    int tx = x - renderer()->xPos();
+    int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
+                             
+    // Ensure our lists are up-to-date.
+    updateZOrderLists();
+    updateOverflowList();
+
+    // If this layer is totally invisible then there is nothing to paint.
+    if (!m_object->opacity())
+        return;
+        
+    bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
+    bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
+
+    if (isTransparent())
+        haveTransparency = true;
+
+    // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
+    // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
+    // Else, our renderer tree may or may not contain the painting root, so we pass that root along
+    // so it will be tested against as we decend through the renderers.
+    RenderObject *paintingRootForRenderer = 0;
+    if (paintingRoot && !m_object->isDescendantOf(paintingRoot))
+        paintingRootForRenderer = paintingRoot;
+    
+    // We want to paint our layer, but only if we intersect the damage rect.
+    bool shouldPaint = intersectsDamageRect(layerBounds, damageRect) && m_hasVisibleContent;
+    if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
+        // Begin transparency layers lazily now that we know we have to paint something.
+        if (haveTransparency)
+            beginTransparencyLayers(p, paintDirtyRect);
+        
+        // Paint our background first, before painting any child layers.
+        // Establish the clip used to paint our background.
+        setClip(p, paintDirtyRect, damageRect);
+
+        // Paint the background.
+        RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
+        renderer()->paint(paintInfo, tx, ty);
+
+        // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
+        // z-index.  We paint after we painted the background/border, so that the scrollbars will
+        // sit above the background/border.
+        paintOverflowControls(p, tx, ty, damageRect);
+        
+        // Restore the clip.
+        restoreClip(p, paintDirtyRect, damageRect);
+    }
+
+    // Now walk the sorted list of children with negative z-indices.
+    if (m_negZOrderList)
+        for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it)
+            it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+    
+    // Now establish the appropriate clip and paint our child RenderObjects.
+    if (shouldPaint && !clipRectToApply.isEmpty()) {
+        // Begin transparency layers lazily now that we know we have to paint something.
+        if (haveTransparency)
+            beginTransparencyLayers(p, paintDirtyRect);
+
+        // Set up the clip used when painting our children.
+        setClip(p, paintDirtyRect, clipRectToApply);
+        RenderObject::PaintInfo paintInfo(p, clipRectToApply, 
+                                          selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
+                                          forceBlackText, paintingRootForRenderer, 0);
+        renderer()->paint(paintInfo, tx, ty);
+        if (!selectionOnly) {
+            paintInfo.phase = PaintPhaseFloat;
+            renderer()->paint(paintInfo, tx, ty);
+            paintInfo.phase = PaintPhaseForeground;
+            renderer()->paint(paintInfo, tx, ty);
+            paintInfo.phase = PaintPhaseChildOutlines;
+            renderer()->paint(paintInfo, tx, ty);
+        }
+
+        // Now restore our clip.
+        restoreClip(p, paintDirtyRect, clipRectToApply);
+    }
+    
+    if (!outlineRect.isEmpty()) {
+        // Paint our own outline
+        RenderObject::PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
+        setClip(p, paintDirtyRect, outlineRect);
+        renderer()->paint(paintInfo, tx, ty);
+        restoreClip(p, paintDirtyRect, outlineRect);
+    }
+    
+    // Paint any child layers that have overflow.
+    if (m_overflowList)
+        for (Vector<RenderLayer*>::iterator it = m_overflowList->begin(); it != m_overflowList->end(); ++it)
+            it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+    
+    // Now walk the sorted list of children with positive z-indices.
+    if (m_posZOrderList)
+        for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
+            it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+    
+    // End our transparency layer
+    if (isTransparent() && m_usedTransparency) {
+        p->endTransparencyLayer();
+        p->restore();
+        m_usedTransparency = false;
+    }
+}
+
+static inline IntRect frameVisibleRect(RenderObject* renderer)
+{
+    FrameView* frameView = renderer->document()->view();
+    if (!frameView)
+        return IntRect();
+
+    return enclosingIntRect(frameView->visibleContentRect());
+}
+
+bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
+{
+    renderer()->document()->updateLayout();
+    
+    IntRect boundsRect(m_x, m_y, width(), height());
+    boundsRect.intersect(frameVisibleRect(renderer()));
+
+    RenderLayer* insideLayer = hitTestLayer(this, request, result, boundsRect);
+
+    // Now determine if the result is inside an anchor; make sure an image map wins if
+    // it already set URLElement and only use the innermost.
+    Node* node = result.innerNode();
+    while (node) {
+        // for imagemaps, URLElement is the associated area element not the image itself
+        if (node->isLink() && !result.URLElement() && !node->hasTagName(imgTag))
+            result.setURLElement(static_cast<Element*>(node));
+        node = node->parentNode();
+    }
+
+    // Next set up the correct :hover/:active state along the new chain.
+    updateHoverActiveState(request, result);
+    
+    // Now return whether we were inside this layer (this will always be true for the root
+    // layer).
+    return insideLayer;
+}
+
+Node* RenderLayer::enclosingElement() const
+{
+    for (RenderObject* r = renderer(); r; r = r->parent()) {
+        if (Node* e = r->element())
+            return e;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequest& request,
+    HitTestResult& result, const IntRect& hitTestRect)
+{
+    // Calculate the clip rects we should use.
+    IntRect layerBounds;
+    IntRect bgRect;
+    IntRect fgRect;
+    IntRect outlineRect;
+    calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
+    
+    // Ensure our lists are up-to-date.
+    updateZOrderLists();
+    updateOverflowList();
+
+    // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,
+    // we are done and can return it.
+    RenderLayer* insideLayer = 0;
+    
+    // Begin by walking our list of positive layers from highest z-index down to the lowest
+    // z-index.
+    if (m_posZOrderList) {
+        for (int i = m_posZOrderList->size() - 1; i >= 0; --i) {
+            insideLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect);
+            if (insideLayer)
+                return insideLayer;
+        }
+    }
+
+    // Now check our overflow objects.
+    if (m_overflowList) {
+        for (int i = m_overflowList->size() - 1; i >= 0; --i) {
+            insideLayer = m_overflowList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect);
+            if (insideLayer)
+                return insideLayer;
+        }
+    }
+
+    // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
+    if (fgRect.contains(result.point()) && 
+        renderer()->hitTest(request, result, result.point().x(), result.point().y(),
+                            layerBounds.x() - renderer()->xPos(),
+                            layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(), 
+                            HitTestDescendants)) {
+        // For positioned generated content, we might still not have a
+        // node by the time we get to the layer level, since none of
+        // the content in the layer has an element. So just walk up
+        // the tree.
+        if (!result.innerNode() || !result.innerNonSharedNode()) {
+            Node* e = enclosingElement();
+            if (!result.innerNode())
+                result.setInnerNode(e);
+            if (!result.innerNonSharedNode())
+                result.setInnerNonSharedNode(e);
+        }
+
+        return this;
+    }
+        
+    // Now check our negative z-index children.
+    if (m_negZOrderList) {
+        for (int i = m_negZOrderList->size() - 1; i >= 0; --i) {
+            insideLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect);
+            if (insideLayer)
+                return insideLayer;
+        }
+    }
+
+    // Next we want to see if the mouse is inside this layer but not any of its children.
+    if (bgRect.contains(result.point()) &&
+        renderer()->hitTest(request, result, result.point().x(), result.point().y(),
+                            layerBounds.x() - renderer()->xPos(),
+                            layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
+                            HitTestSelf)) {
+        if (!result.innerNode() || !result.innerNonSharedNode()) {
+            Node* e = enclosingElement();
+            if (!result.innerNode())
+                result.setInnerNode(e);
+            if (!result.innerNonSharedNode())
+                result.setInnerNonSharedNode(e);
+        }
+
+        return this;
+    }
+
+    // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, 
+    // return ourselves. We do this so mouse events continue getting delivered after a drag has 
+    // exited the WebView, and so hit testing over a scrollbar hits the content document.
+    if ((request.active || request.mouseUp) && renderer()->isRenderView()) {
+        renderer()->updateHitTestResult(result, result.point());
+        return this;
+    }
+
+    return 0;
+}
+
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer)
+{
+    if (m_clipRects)
+        return; // We have the correct cached value.
+
+    if (!parent()) {
+        // The root layer's clip rect is always just its dimensions.
+        m_clipRects = new (m_object->renderArena()) ClipRects(IntRect(0,0,width(),height()));
+        m_clipRects->ref();
+        return;
+    }
+
+    // Ensure that our parent's clip has been calculated so that we can examine the values.
+    parent()->calculateClipRects(rootLayer);
+
+    // Set up our three rects to initially match the parent rects.
+    IntRect posClipRect(parent()->clipRects()->posClipRect());
+    IntRect overflowClipRect(parent()->clipRects()->overflowClipRect());
+    IntRect fixedClipRect(parent()->clipRects()->fixedClipRect());
+    bool fixed = parent()->clipRects()->fixed();
+
+    // A fixed object is essentially the root of its containing block hierarchy, so when
+    // we encounter such an object, we reset our clip rects to the fixedClipRect.
+    if (m_object->style()->position() == FixedPosition) {
+        posClipRect = fixedClipRect;
+        overflowClipRect = fixedClipRect;
+        fixed = true;
+    }
+    else if (m_object->style()->position() == RelativePosition)
+        posClipRect = overflowClipRect;
+    else if (m_object->style()->position() == AbsolutePosition)
+        overflowClipRect = posClipRect;
+    
+    // Update the clip rects that will be passed to child layers.
+    if (m_object->hasOverflowClip() || m_object->hasClip()) {
+        // This layer establishes a clip of some kind.
+        int x = 0;
+        int y = 0;
+        convertToLayerCoords(rootLayer, x, y);
+        RenderView* view = renderer()->view();
+        ASSERT(view);
+        if (view && fixed) {
+            x -= view->frameView()->contentsX();
+            y -= view->frameView()->contentsY();
+        }
+        
+        if (m_object->hasOverflowClip()) {
+            IntRect newOverflowClip = m_object->getOverflowClipRect(x,y);
+            overflowClipRect.intersect(newOverflowClip);
+            if (m_object->isPositioned() || m_object->isRelPositioned())
+                posClipRect.intersect(newOverflowClip);
+        }
+        if (m_object->hasClip()) {
+            IntRect newPosClip = m_object->getClipRect(x,y);
+            posClipRect.intersect(newPosClip);
+            overflowClipRect.intersect(newPosClip);
+            fixedClipRect.intersect(newPosClip);
+        }
+    }
+    
+    // If our clip rects match our parent's clip, then we can just share its data structure and
+    // ref count.
+    if (fixed == parent()->clipRects()->fixed() &&
+        posClipRect == parent()->clipRects()->posClipRect() &&
+        overflowClipRect == parent()->clipRects()->overflowClipRect() &&
+        fixedClipRect == parent()->clipRects()->fixedClipRect())
+        m_clipRects = parent()->clipRects();
+    else
+        m_clipRects = new (m_object->renderArena()) ClipRects(overflowClipRect, fixedClipRect, posClipRect, fixed);
+    m_clipRects->ref();
+}
+
+void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
+                                 IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect) const
+{
+    if (parent()) {
+        parent()->calculateClipRects(rootLayer);
+
+        backgroundRect = m_object->style()->position() == FixedPosition ? parent()->clipRects()->fixedClipRect() :
+                         (m_object->isPositioned() ? parent()->clipRects()->posClipRect() : 
+                                                     parent()->clipRects()->overflowClipRect());
+        RenderView* view = renderer()->view();
+        ASSERT(view);
+        if (view && parent()->clipRects()->fixed())
+            backgroundRect.move(view->frameView()->contentsX(), view->frameView()->contentsY());
+
+        backgroundRect.intersect(paintDirtyRect);
+    } else
+        backgroundRect = paintDirtyRect;
+    foregroundRect = backgroundRect;
+    outlineRect = backgroundRect;
+    
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(rootLayer, x, y);
+    layerBounds = IntRect(x,y,width(),height());
+    
+    // Update the clip rects that will be passed to child layers.
+    if (m_object->hasOverflowClip() || m_object->hasClip()) {
+        // This layer establishes a clip of some kind.
+        if (m_object->hasOverflowClip())
+            foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
+        if (m_object->hasClip()) {
+            // Clip applies to *us* as well, so go ahead and update the damageRect.
+            IntRect newPosClip = m_object->getClipRect(x,y);
+            backgroundRect.intersect(newPosClip);
+            foregroundRect.intersect(newPosClip);
+            outlineRect.intersect(newPosClip);
+        }
+
+        // If we establish a clip at all, then go ahead and make sure our background
+        // rect is intersected with our layer's bounds.
+        if (ShadowData* boxShadow = renderer()->style()->boxShadow()) {
+            IntRect shadowRect = layerBounds;
+            shadowRect.move(boxShadow->x, boxShadow->y);
+            shadowRect.inflate(boxShadow->blur);
+            shadowRect.unite(layerBounds);
+            backgroundRect.intersect(shadowRect);
+        } else
+            backgroundRect.intersect(layerBounds);
+    }
+}
+
+IntRect RenderLayer::childrenClipRect() const
+{
+    RenderLayer* rootLayer = renderer()->document()->renderer()->layer();
+    IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
+    calculateRects(rootLayer, rootLayer->absoluteBoundingBox(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+    return foregroundRect;
+}
+
+IntRect RenderLayer::selfClipRect() const
+{
+    RenderLayer* rootLayer = renderer()->document()->renderer()->layer();
+    IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
+    calculateRects(rootLayer, rootLayer->absoluteBoundingBox(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+    return backgroundRect;
+}
+
+bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect) const
+{
+    // Always examine the canvas and the root.
+    // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
+    // paints the root's background.
+    if (renderer()->isRenderView() || renderer()->isRoot())
+        return true;
+
+    // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we 
+    // can go ahead and return true.
+    RenderView* view = renderer()->view();
+    ASSERT(view);
+    if (view && !renderer()->isInlineFlow()) {
+        IntRect b = layerBounds;
+        b.inflate(view->maximalOutlineSize());
+        if (b.intersects(damageRect))
+            return true;
+    }
+        
+    // Otherwise we need to compute the bounding box of this single layer and see if it intersects
+    // the damage rect.
+    return absoluteBoundingBox().intersects(damageRect);
+}
+
+IntRect RenderLayer::absoluteBoundingBox() const
+{
+    // There are three special cases we need to consider.
+    // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
+    // inline.  In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the root
+    // line boxes of all three lines (including overflow on those lines).
+    // (2) Left/Top Overflow.  The width/height of layers already includes right/bottom overflow.  However, in the case of left/top
+    // overflow, we have to create a bounding box that will extend to include this overflow.
+    // (3) Floats.  When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
+    // as part of our bounding box.  We do this because we are the responsible layer for both hit testing and painting those
+    // floats.
+    IntRect result;
+    if (renderer()->isInlineFlow()) {
+        // Go from our first line box to our last line box.
+        RenderInline* inlineFlow = static_cast<RenderInline*>(renderer());
+        InlineFlowBox* firstBox = inlineFlow->firstLineBox();
+        if (!firstBox)
+            return result;
+        int top = firstBox->root()->topOverflow();
+        int bottom = inlineFlow->lastLineBox()->root()->bottomOverflow();
+        int left = firstBox->xPos();
+        for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
+            left = min(left, curr->xPos());
+        result = IntRect(m_x + left, m_y + (top - renderer()->yPos()), width(), bottom - top);
+    } else if (renderer()->isTableRow()) {
+        // Our bounding box is just the union of all of our cells' border/overflow rects.
+        for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+            if (child->isTableCell()) {
+                IntRect bbox = child->borderBox();
+                bbox.move(0, child->borderTopExtra());
+                result.unite(bbox);
+                IntRect overflowRect = renderer()->overflowRect(false);
+                overflowRect.move(0, child->borderTopExtra());
+                if (bbox != overflowRect)
+                    result.unite(overflowRect);
+            }
+        }
+        result.move(m_x, m_y);
+    } else {
+        IntRect bbox = renderer()->borderBox();
+        result = bbox;
+        IntRect overflowRect = renderer()->overflowRect(false);
+        if (bbox != overflowRect)
+            result.unite(overflowRect);
+        
+        // We have to adjust the x/y of this result so that it is in the coordinate space of the layer.
+        // We also have to add in borderTopExtra here, since borderBox(), in order to play well with methods like
+        // floatRect that deal with child content, uses an origin of (0,0) that is at the child content box (so
+        // border box returns a y coord of -borderTopExtra().  The layer, however, uses the outer box.  This is all
+        // really confusing.
+        result.move(m_x, m_y + renderer()->borderTopExtra());
+    }
+    
+    // Convert the bounding box to an absolute position.  We can do this easily by looking at the delta
+    // between the bounding box's xpos and our layer's xpos and then applying that to the absolute layerBounds
+    // passed in.
+    int absX = 0, absY = 0;
+    convertToLayerCoords(root(), absX, absY);
+    result.move(absX - m_x, absY - m_y);
+    RenderView* view = renderer()->view();
+    ASSERT(view);
+    if (view)
+        result.inflate(view->maximalOutlineSize());
+    return result;
+}
+
+void RenderLayer::clearClipRects()
+{
+    if (!m_clipRects)
+        return;
+
+    clearClipRect();
+    
+    for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
+        l->clearClipRects();
+}
+
+void RenderLayer::clearClipRect()
+{
+    if (m_clipRects) {
+        m_clipRects->deref(m_object->renderArena());
+        m_clipRects = 0;
+    }
+}
+
+static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
+{
+    if (!obj1 || !obj2)
+        return 0;
+
+    for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
+        for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
+            if (currObj1 == currObj2)
+                return currObj1;
+
+    return 0;
+}
+
+void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
+{
+    // We don't update :hover/:active state when the result is marked as readonly.
+    if (request.readonly)
+        return;
+
+    Document* doc = renderer()->document();
+
+    Node* activeNode = doc->activeNode();
+    if (activeNode && !request.active) {
+        // We are clearing the :active chain because the mouse has been released.
+        for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
+            if (curr->element() && !curr->isText())
+                curr->element()->setInActiveChain(false);
+        }
+        doc->setActiveNode(0);
+    } else {
+        Node* newActiveNode = result.innerNode();
+        if (!activeNode && newActiveNode && request.active) {
+            // We are setting the :active chain and freezing it. If future moves happen, they
+            // will need to reference this chain.
+            for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
+                if (curr->element() && !curr->isText()) {
+                    curr->element()->setInActiveChain(true);
+                }
+            }
+            doc->setActiveNode(newActiveNode);
+        }
+    }
+
+    // If the mouse is down and if this is a mouse move event, we want to restrict changes in 
+    // :hover/:active to only apply to elements that are in the :active chain that we froze
+    // at the time the mouse went down.
+    bool mustBeInActiveChain = request.active && request.mouseMove;
+
+    // Check to see if the hovered node has changed.  If not, then we don't need to
+    // do anything.  
+    RefPtr<Node> oldHoverNode = doc->hoverNode();
+    Node* newHoverNode = result.innerNode();
+
+    // Update our current hover node.
+    doc->setHoverNode(newHoverNode);
+
+    // We have two different objects.  Fetch their renderers.
+    RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
+    RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
+    
+    // Locate the common ancestor render object for the two renderers.
+    RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
+
+    if (oldHoverObj != newHoverObj) {
+        // The old hover path only needs to be cleared up to (and not including) the common ancestor;
+        for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
+            if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
+                curr->element()->setActive(false);
+                curr->element()->setHovered(false);
+            }
+        }
+    }
+
+    // Now set the hover state for our new object up to the root.
+    for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
+        if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
+            curr->element()->setActive(request.active);
+            curr->element()->setHovered(true);
+        }
+    }
+}
+
+// Helper for the sorting of layers by z-index.
+static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
+{
+    return first->zIndex() < second->zIndex();
+}
+
+void RenderLayer::dirtyZOrderLists()
+{
+    if (m_posZOrderList)
+        m_posZOrderList->clear();
+    if (m_negZOrderList)
+        m_negZOrderList->clear();
+    m_zOrderListsDirty = true;
+}
+
+void RenderLayer::dirtyOverflowList()
+{
+    if (m_overflowList)
+        m_overflowList->clear();
+    m_overflowListDirty = true;
+}
+
+void RenderLayer::updateZOrderLists()
+{
+    if (!isStackingContext() || !m_zOrderListsDirty)
+        return;
+        
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->collectLayers(m_posZOrderList, m_negZOrderList);
+
+    // Sort the two lists.
+    if (m_posZOrderList)
+        std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
+    if (m_negZOrderList)
+        std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
+
+    m_zOrderListsDirty = false;
+}
+
+void RenderLayer::updateOverflowList()
+{
+    if (!m_overflowListDirty)
+        return;
+        
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isOverflowOnly()) {
+            if (!m_overflowList)
+                m_overflowList = new Vector<RenderLayer*>;
+            m_overflowList->append(child);
+        }
+    }
+    
+    m_overflowListDirty = false;
+}
+
+void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
+{
+    updateVisibilityStatus();
+        
+    // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
+    if (m_hasVisibleContent && !isOverflowOnly()) {
+        // Determine which buffer the child should be in.
+        Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
+
+        // Create the buffer if it doesn't exist yet.
+        if (!buffer)
+            buffer = new Vector<RenderLayer*>;
+        
+        // Append ourselves at the end of the appropriate buffer.
+        buffer->append(this);
+    }
+
+    // Recur into our children to collect more layers, but only if we don't establish
+    // a stacking context.
+    if (m_hasVisibleDescendant && !isStackingContext())
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+            child->collectLayers(posBuffer, negBuffer);
+}
+
+void RenderLayer::repaintIncludingDescendants()
+{
+    m_object->repaint();
+    for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->repaintIncludingDescendants();
+}
+
+bool RenderLayer::shouldBeOverflowOnly() const
+{
+    return renderer()->hasOverflowClip() && 
+           !renderer()->isPositioned() &&
+           !renderer()->isRelPositioned() &&
+           !isTransparent();
+}
+
+void RenderLayer::styleChanged()
+{
+    bool isOverflowOnly = shouldBeOverflowOnly();
+    if (isOverflowOnly != m_isOverflowOnly) {
+        m_isOverflowOnly = isOverflowOnly;
+        RenderLayer* p = parent();
+        RenderLayer* sc = stackingContext();
+        if (p)
+            p->dirtyOverflowList();
+        if (sc)
+            sc->dirtyZOrderLists();
+    }
+
+    if (m_object->style()->overflowX() == OMARQUEE && m_object->style()->marqueeBehavior() != MNONE) {
+        if (!m_marquee)
+            m_marquee = new Marquee(this);
+        m_marquee->updateMarqueeStyle();
+    }
+    else if (m_marquee) {
+        delete m_marquee;
+        m_marquee = 0;
+    }
+}
+
+void RenderLayer::suspendMarquees()
+{
+    if (m_marquee)
+        m_marquee->suspend();
+    
+    for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->suspendMarquees();
+}
+
+// --------------------------------------------------------------------------
+// Marquee implementation
+
+Marquee::Marquee(RenderLayer* l)
+    : m_layer(l), m_currentLoop(0)
+    , m_totalLoops(0)
+    , m_timer(this, &Marquee::timerFired)
+    , m_start(0), m_end(0), m_speed(0), m_reset(false)
+    , m_suspended(false), m_stopped(false), m_direction(MAUTO)
+{
+}
+
+int Marquee::marqueeSpeed() const
+{
+    int result = m_layer->renderer()->style()->marqueeSpeed();
+    Node* elt = m_layer->renderer()->element();
+    if (elt && elt->hasTagName(marqueeTag)) {
+        HTMLMarqueeElement* marqueeElt = static_cast<HTMLMarqueeElement*>(elt);
+        result = max(result, marqueeElt->minimumDelay());
+    }
+    return result;
+}
+
+EMarqueeDirection Marquee::direction() const
+{
+    // FIXME: Support the CSS3 "auto" value for determining the direction of the marquee.
+    // For now just map MAUTO to MBACKWARD
+    EMarqueeDirection result = m_layer->renderer()->style()->marqueeDirection();
+    TextDirection dir = m_layer->renderer()->style()->direction();
+    if (result == MAUTO)
+        result = MBACKWARD;
+    if (result == MFORWARD)
+        result = (dir == LTR) ? MRIGHT : MLEFT;
+    if (result == MBACKWARD)
+        result = (dir == LTR) ? MLEFT : MRIGHT;
+    
+    // Now we have the real direction.  Next we check to see if the increment is negative.
+    // If so, then we reverse the direction.
+    Length increment = m_layer->renderer()->style()->marqueeIncrement();
+    if (increment.isNegative())
+        result = static_cast<EMarqueeDirection>(-result);
+    
+    return result;
+}
+
+bool Marquee::isHorizontal() const
+{
+    return direction() == MLEFT || direction() == MRIGHT;
+}
+
+int Marquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
+{
+    RenderObject* o = m_layer->renderer();
+    RenderStyle* s = o->style();
+    if (isHorizontal()) {
+        bool ltr = s->direction() == LTR;
+        int clientWidth = o->clientWidth();
+        int contentWidth = ltr ? o->rightmostPosition(true, false) : o->leftmostPosition(true, false);
+        if (ltr)
+            contentWidth += (o->paddingRight() - o->borderLeft());
+        else {
+            contentWidth = o->width() - contentWidth;
+            contentWidth += (o->paddingLeft() - o->borderRight());
+        }
+        if (dir == MRIGHT) {
+            if (stopAtContentEdge)
+                return max(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+            else
+                return ltr ? contentWidth : clientWidth;
+        }
+        else {
+            if (stopAtContentEdge)
+                return min(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+            else
+                return ltr ? -clientWidth : -contentWidth;
+        }
+    }
+    else {
+        int contentHeight = m_layer->renderer()->lowestPosition(true, false) - 
+                            m_layer->renderer()->borderTop() + m_layer->renderer()->paddingBottom();
+        int clientHeight = m_layer->renderer()->clientHeight();
+        if (dir == MUP) {
+            if (stopAtContentEdge)
+                 return min(contentHeight - clientHeight, 0);
+            else
+                return -clientHeight;
+        }
+        else {
+            if (stopAtContentEdge)
+                return max(contentHeight - clientHeight, 0);
+            else 
+                return contentHeight;
+        }
+    }    
+}
+
+void Marquee::start()
+{
+    if (m_timer.isActive() || m_layer->renderer()->style()->marqueeIncrement().isZero())
+        return;
+
+    // We may end up propagating a scroll event. It is important that we suspend events until 
+    // the end of the function since they could delete the layer, including the marquee.
+    FrameView* frameView = m_layer->renderer()->document()->view();
+    if (frameView)
+        frameView->pauseScheduledEvents();
+
+    if (!m_suspended && !m_stopped) {
+        if (isHorizontal())
+            m_layer->scrollToOffset(m_start, 0, false, false);
+        else
+            m_layer->scrollToOffset(0, m_start, false, false);
+    }
+    else {
+        m_suspended = false;
+        m_stopped = false;
+    }
+
+    m_timer.startRepeating(speed() * 0.001);
+
+    if (frameView)
+        frameView->resumeScheduledEvents();
+}
+
+void Marquee::suspend()
+{
+    m_timer.stop();
+    m_suspended = true;
+}
+
+void Marquee::stop()
+{
+    m_timer.stop();
+    m_stopped = true;
+}
+
+void Marquee::updateMarqueePosition()
+{
+    bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
+    
+#if PLATFORM(SYMBIAN)
+    // wap-marquee requests loop 0 as inactive marquee
+    if (m_totalLoops == 0 && m_layer->renderer()->style()->display() == WAP_MARQUEE)
+        activate = false;
+#endif
+
+    if (activate) {
+        EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
+        m_start = computePosition(direction(), behavior == MALTERNATE);
+        m_end = computePosition(reverseDirection(), behavior == MALTERNATE || behavior == MSLIDE);
+        if (!m_stopped)
+            start();
+    }
+}
+
+void Marquee::updateMarqueeStyle()
+{
+    RenderStyle* s = m_layer->renderer()->style();
+    
+    if (m_direction != s->marqueeDirection() || (m_totalLoops != s->marqueeLoopCount() && m_currentLoop >= m_totalLoops))
+        m_currentLoop = 0; // When direction changes or our loopCount is a smaller number than our current loop, reset our loop.
+    
+    m_totalLoops = s->marqueeLoopCount();
+    m_direction = s->marqueeDirection();
+    
+    if (m_layer->renderer()->isHTMLMarquee()) {
+        // Hack for WinIE.  In WinIE, a value of 0 or lower for the loop count for SLIDE means to only do
+        // one loop.
+        if (m_totalLoops <= 0 && s->marqueeBehavior() == MSLIDE)
+            m_totalLoops = 1;
+        
+        // Hack alert: Set the white-space value to nowrap for horizontal marquees with inline children, thus ensuring
+        // all the text ends up on one line by default.  Limit this hack to the <marquee> element to emulate
+        // WinIE's behavior.  Someone using CSS3 can use white-space: nowrap on their own to get this effect.
+        // Second hack alert: Set the text-align back to auto.  WinIE completely ignores text-align on the
+        // marquee element.
+        // FIXME: Bring these up with the CSS WG.
+        if (isHorizontal() && m_layer->renderer()->childrenInline()) {
+            s->setWhiteSpace(NOWRAP);
+            s->setTextAlign(TAAUTO);
+        }
+    }
+    
+    // Marquee height hack!! Make sure that, if it is a horizontal marquee, the height attribute is overridden 
+    // if it is smaller than the font size. If it is a vertical marquee and height is not specified, we default
+    // to a marquee of 200px.
+    if (isHorizontal()) {
+        if (s->height().isFixed() && s->height().value() < s->fontSize())
+            s->setHeight(Length(s->fontSize(),Fixed));
+    } else if (s->height().isAuto())  //vertical marquee with no specified height
+        s->setHeight(Length(200, Fixed)); 
+   
+    if (speed() != marqueeSpeed()) {
+        m_speed = marqueeSpeed();
+        if (m_timer.isActive())
+            m_timer.startRepeating(speed() * 0.001);
+    }
+    
+    // Check the loop count to see if we should now stop.
+    bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
+    if (activate && !m_timer.isActive())
+        m_layer->renderer()->setNeedsLayout(true);
+    else if (!activate && m_timer.isActive())
+        m_timer.stop();
+}
+
+void Marquee::timerFired(Timer<Marquee>*)
+{
+    if (m_layer->renderer()->needsLayout())
+        return;
+    
+    if (m_reset) {
+        m_reset = false;
+        if (isHorizontal())
+            m_layer->scrollToXOffset(m_start);
+        else
+            m_layer->scrollToYOffset(m_start);
+        return;
+    }
+    
+    RenderStyle* s = m_layer->renderer()->style();
+    
+    int endPoint = m_end;
+    int range = m_end - m_start;
+    int newPos;
+    if (range == 0)
+        newPos = m_end;
+    else {  
+        bool addIncrement = direction() == MUP || direction() == MLEFT;
+        bool isReversed = s->marqueeBehavior() == MALTERNATE && m_currentLoop % 2;
+        if (isReversed) {
+            // We're going in the reverse direction.
+            endPoint = m_start;
+            range = -range;
+            addIncrement = !addIncrement;
+        }
+        bool positive = range > 0;
+        int clientSize = (isHorizontal() ? m_layer->renderer()->clientWidth() : m_layer->renderer()->clientHeight());
+        int increment = max(1, abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize)));
+        int currentPos = (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
+        newPos =  currentPos + (addIncrement ? increment : -increment);
+        if (positive)
+            newPos = min(newPos, endPoint);
+        else
+            newPos = max(newPos, endPoint);
+    }
+
+    if (newPos == endPoint) {
+        m_currentLoop++;
+        if (m_totalLoops > 0 && m_currentLoop >= m_totalLoops)
+            m_timer.stop();
+        else if (s->marqueeBehavior() != MALTERNATE)
+            m_reset = true;
+    }
+    
+    if (isHorizontal())
+        m_layer->scrollToXOffset(newPos);
+    else
+        m_layer->scrollToYOffset(newPos);
+/* HLUU-7D3SDH: This special handling here is not compatible with 3.2 and 3.1 behavior. 
+#if PLATFORM(SYMBIAN)
+    if( m_totalLoops>0 && m_currentLoop >= m_totalLoops ) {
+        // -wap-marquee requires "the element MUST be rendered as if the 'display' property was set
+        // to block" after looping
+        if(s->display() == WAP_MARQUEE) {
+            s->setDisplay(BLOCK);
+            s->setOverflowX(OVISIBLE);
+            m_layer->renderer()->setHasOverflowClip( false );
+            m_layer->styleChanged();
+        }
+    }
+#endif
+*/
+}
+
+} // namespace WebCore