diff options
author | Steve Block <steveblock@google.com> | 2009-10-08 17:19:54 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-10-20 00:41:58 +0100 |
commit | 231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch) | |
tree | a6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/rendering/RenderLayer.cpp | |
parent | e196732677050bd463301566a68a643b6d14b907 (diff) | |
download | external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2 |
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/rendering/RenderLayer.cpp')
-rw-r--r-- | WebCore/rendering/RenderLayer.cpp | 210 |
1 files changed, 149 insertions, 61 deletions
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index ab78f40..7a8b428 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -207,12 +207,8 @@ RenderLayer::~RenderLayer() // Make sure we have no lingering clip rects. ASSERT(!m_clipRects); - if (m_reflection) { - if (!m_reflection->documentBeingDestroyed()) - m_reflection->removeLayers(this); - m_reflection->setParent(0); - m_reflection->destroy(); - } + if (m_reflection) + removeReflection(); if (m_scrollCorner) m_scrollCorner->destroy(); @@ -584,10 +580,10 @@ void RenderLayer::updateLayerPosition() setHeight(box->height()); if (!box->hasOverflowClip()) { - if (box->overflowWidth() > box->width()) - setWidth(box->overflowWidth()); - if (box->overflowHeight() > box->height()) - setHeight(box->overflowHeight()); + if (box->rightLayoutOverflow() > box->width()) + setWidth(box->rightLayoutOverflow()); + if (box->bottomLayoutOverflow() > box->height()) + setHeight(box->bottomLayoutOverflow()); } } } @@ -642,37 +638,44 @@ RenderLayer* RenderLayer::stackingContext() const return layer; } +static inline bool isPositionedContainer(RenderLayer* layer) +{ + RenderObject* o = layer->renderer(); + return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform(); +} + RenderLayer* RenderLayer::enclosingPositionedAncestor() const { RenderLayer* curr = parent(); - for ( ; curr && !curr->renderer()->isRenderView() && !curr->renderer()->isPositioned() && !curr->renderer()->isRelPositioned() && !curr->hasTransform(); - curr = curr->parent()) { } + while (curr && !isPositionedContainer(curr)) + curr = curr->parent(); + return curr; } RenderLayer* RenderLayer::enclosingTransformedAncestor() const { RenderLayer* curr = parent(); - for ( ; curr && !curr->renderer()->isRenderView() && !curr->transform(); curr = curr->parent()) - { } + while (curr && !curr->renderer()->isRenderView() && !curr->transform()) + curr = curr->parent(); + return curr; } +static inline const RenderLayer* compositingContainer(const RenderLayer* layer) +{ + return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext(); +} + #if USE(ACCELERATED_COMPOSITING) RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const { if (includeSelf && isComposited()) return const_cast<RenderLayer*>(this); - // Compositing layers are parented according to stacking order and overflow list, - // so we have to check whether the parent is a stacking context, or whether - // the child is overflow-only. - bool inNormalFlowList = isNormalFlowOnly(); - for (RenderLayer* curr = parent(); curr; curr = curr->parent()) { - if (curr->isComposited() && (inNormalFlowList || curr->isStackingContext())) - return curr; - - inNormalFlowList = curr->isNormalFlowOnly(); + for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) { + if (curr->isComposited()) + return const_cast<RenderLayer*>(curr); } return 0; @@ -760,6 +763,19 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor } } + // If we have a reflection, then we need to account for that when we push the clip. Reflect our entire + // current transparencyClipBox to catch all child layers. + // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this + // size into the parent layer. + if (l->renderer()->hasReflection()) { + int deltaX = 0; + int deltaY = 0; + l->convertToLayerCoords(rootLayer, deltaX, deltaY); + clipRect.move(-deltaX, -deltaY); + clipRect.unite(l->renderBox()->reflectedRect(clipRect)); + clipRect.move(deltaX, deltaY); + } + // Now map the clipRect via the enclosing transform return enclosingTransform.mapRect(clipRect); } @@ -946,12 +962,44 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i } RenderLayer* parentLayer; - if (renderer()->style()->position() == AbsolutePosition) - parentLayer = enclosingPositionedAncestor(); - else + if (renderer()->style()->position() == AbsolutePosition) { + // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way + parentLayer = parent(); + bool foundAncestorFirst = false; + while (parentLayer) { + if (isPositionedContainer(parentLayer)) + break; + + if (parentLayer == ancestorLayer) { + foundAncestorFirst = true; + break; + } + + parentLayer = parentLayer->parent(); + } + + if (foundAncestorFirst) { + // Found ancestorLayer before the abs. positioned container, so compute offset of both relative + // to enclosingPositionedAncestor and subtract. + RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor(); + + int thisX = 0; + int thisY = 0; + convertToLayerCoords(positionedAncestor, thisX, thisY); + + int ancestorX = 0; + int ancestorY = 0; + ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorX, ancestorY); + + xPos += (thisX - ancestorX); + yPos += (thisY - ancestorY); + return; + } + } else parentLayer = parent(); - if (!parentLayer) return; + if (!parentLayer) + return; parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos); @@ -959,12 +1007,22 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i yPos += y(); } +static inline int adjustedScrollDelta(int beginningDelta) { + // This implemention matches Firefox's. + // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856. + const int speedReducer = 12; + + int adjustedDelta = beginningDelta / speedReducer; + if (adjustedDelta > 1) + adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1; + else if (adjustedDelta < -1) + adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1; + + return adjustedDelta; +} + void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint) { - // We want to reduce the speed if we're close from the original point to improve the handleability of the scroll - const int shortDistanceLimit = 100; // We delimit a 200 pixels long square enclosing the original point - const int speedReducer = 2; // Within this square we divide the scrolling speed by 2 - Frame* frame = renderer()->document()->frame(); if (!frame) return; @@ -981,22 +1039,19 @@ void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint) int xDelta = currentMousePosition.x() - sourcePoint.x(); int yDelta = currentMousePosition.y() - sourcePoint.y(); - if (abs(xDelta) < ScrollView::noPanScrollRadius) // at the center we let the space for the icon + if (abs(xDelta) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon xDelta = 0; - if (abs(yDelta) < ScrollView::noPanScrollRadius) + if (abs(yDelta) <= ScrollView::noPanScrollRadius) yDelta = 0; - // Let's attenuate the speed for the short distances - if (abs(xDelta) < shortDistanceLimit) - xDelta /= speedReducer; - if (abs(yDelta) < shortDistanceLimit) - yDelta /= speedReducer; - - scrollByRecursively(xDelta, yDelta); + scrollByRecursively(adjustedScrollDelta(xDelta), adjustedScrollDelta(yDelta)); } void RenderLayer::scrollByRecursively(int xDelta, int yDelta) { + if (!xDelta && !yDelta) + return; + bool restrictedByLineClamp = false; if (renderer()->parent()) restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0; @@ -1006,17 +1061,30 @@ void RenderLayer::scrollByRecursively(int xDelta, int yDelta) int newOffsetY = scrollYOffset() + yDelta; scrollToOffset(newOffsetX, newOffsetY); - // If this layer can't do the scroll we ask its parent + // If this layer can't do the scroll we ask the next layer up that can scroll to try int leftToScrollX = newOffsetX - scrollXOffset(); int leftToScrollY = newOffsetY - scrollYOffset(); if ((leftToScrollX || leftToScrollY) && renderer()->parent()) { - renderer()->parent()->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY); + RenderObject* nextRenderer = renderer()->parent(); + while (nextRenderer) { + if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea()) { + nextRenderer->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY); + break; + } + nextRenderer = nextRenderer->parent(); + } + Frame* frame = renderer()->document()->frame(); if (frame) frame->eventHandler()->updateAutoscrollRenderer(); } - } else if (renderer()->view()->frameView()) + } else if (renderer()->view()->frameView()) { + // If we are here, we were called on a renderer that can be programatically scrolled, but doesn't + // have an overflow clip. Which means that it is a document node that can be scrolled. renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta)); + // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement? + // https://bugs.webkit.org/show_bug.cgi?id=28237 + } } @@ -1275,7 +1343,9 @@ void RenderLayer::autoscroll() if (!frameView) return; +#if ENABLE(DRAG_SUPPORT) frame->eventHandler()->updateSelectionForMouseDrag(); +#endif IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition()); scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); @@ -2056,9 +2126,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Make sure the parent's clip rects have been calculated. IntRect clipRect = paintDirtyRect; if (parent()) { - ClipRects parentRects; - parentClipRects(rootLayer, parentRects, paintFlags & PaintLayerTemporaryClipRects); - clipRect = parentRects.overflowClipRect(); + clipRect = backgroundClipRect(rootLayer, paintFlags & PaintLayerTemporaryClipRects); clipRect.intersect(paintDirtyRect); } @@ -2368,9 +2436,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont if (transform() && !appliedTransform) { // Make sure the parent's clip rects have been calculated. if (parent()) { - ClipRects parentRects; - parentClipRects(rootLayer, parentRects, useTemporaryClipRects); - IntRect clipRect = parentRects.overflowClipRect(); + IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects); // Go ahead and test the enclosing clip now. if (!clipRect.contains(hitTestPoint)) return 0; @@ -2668,10 +2734,10 @@ void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipR clipRects = *parent()->clipRects(); } -void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds, - IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const +IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const { - if (rootLayer != this && parent()) { + IntRect backgroundRect; + if (parent()) { ClipRects parentRects; parentClipRects(rootLayer, parentRects, temporaryClipRects); backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() : @@ -2681,7 +2747,15 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa ASSERT(view); if (view && parentRects.fixed() && rootLayer->renderer() == view) backgroundRect.move(view->frameView()->scrollX(), view->frameView()->scrollY()); + } + return backgroundRect; +} +void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds, + IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const +{ + if (rootLayer != this && parent()) { + backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects); backgroundRect.intersect(paintDirtyRect); } else backgroundRect = paintDirtyRect; @@ -2771,7 +2845,7 @@ IntRect RenderLayer::localBoundingBox() 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 + // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the // 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. @@ -2785,8 +2859,8 @@ IntRect RenderLayer::localBoundingBox() const InlineFlowBox* firstBox = inlineFlow->firstLineBox(); if (!firstBox) return result; - int top = firstBox->root()->topOverflow(); - int bottom = inlineFlow->lastLineBox()->root()->bottomOverflow(); + int top = firstBox->topVisibleOverflow(); + int bottom = inlineFlow->lastLineBox()->bottomVisibleOverflow(); int left = firstBox->x(); for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox()) left = min(left, curr->x()); @@ -2797,7 +2871,7 @@ IntRect RenderLayer::localBoundingBox() const if (child->isTableCell()) { IntRect bbox = toRenderBox(child)->borderBoxRect(); result.unite(bbox); - IntRect overflowRect = renderBox()->overflowRect(false); + IntRect overflowRect = renderBox()->visibleOverflowRect(); if (bbox != overflowRect) result.unite(overflowRect); } @@ -2810,7 +2884,7 @@ IntRect RenderLayer::localBoundingBox() const else { IntRect bbox = box->borderBoxRect(); result = bbox; - IntRect overflowRect = box->overflowRect(false); + IntRect overflowRect = box->visibleOverflowRect(); if (bbox != overflowRect) result.unite(overflowRect); } @@ -2873,6 +2947,11 @@ void RenderLayer::clearBacking() { m_backing.clear(); } + +bool RenderLayer::hasCompositedMask() const +{ + return m_backing && m_backing->hasMaskLayer(); +} #endif void RenderLayer::setParent(RenderLayer* parent) @@ -3183,10 +3262,9 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*) m_marquee = 0; } - if (!hasReflection() && m_reflection) { - m_reflection->destroy(); - m_reflection = 0; - } else if (hasReflection()) { + if (!hasReflection() && m_reflection) + removeReflection(); + else if (hasReflection()) { if (!m_reflection) createReflection(); updateReflectionStyle(); @@ -3260,6 +3338,16 @@ void RenderLayer::createReflection() m_reflection->setParent(renderer()); // We create a 1-way connection. } +void RenderLayer::removeReflection() +{ + if (!m_reflection->documentBeingDestroyed()) + m_reflection->removeLayers(this); + + m_reflection->setParent(0); + m_reflection->destroy(); + m_reflection = 0; +} + void RenderLayer::updateReflectionStyle() { RefPtr<RenderStyle> newStyle = RenderStyle::create(); |