summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderLayer.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-10-08 17:19:54 +0100
committerSteve Block <steveblock@google.com>2009-10-20 00:41:58 +0100
commit231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch)
treea6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/rendering/RenderLayer.cpp
parente196732677050bd463301566a68a643b6d14b907 (diff)
downloadexternal_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.cpp210
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();