Commit 076fc429 authored by chrishtr@chromium.org's avatar chrishtr@chromium.org

Return an infinite rect when calling RenderLayerClipper::parentClipRects on the root context layer

When calling RenderLayerClipper::backgroundClipRect on the
RenderLayerClipper object corresponding to the RenderLayer
which is equal to clipRectsContext.rootLayer, it first calls
parentClipRects on the clipper of that RenderLayer's parent.
In turn, this starts a recursive walk up the RenderLayer
tree in updateClipRects. This is incorrect, since a
RenderLayerClipper object is unable to clip above rootLayer
in the render tree. In particular, the recursion condition
in updateClipRects
depends on the recursion starting at a layer which is below
or equal to rootLayer.

BUG=336563

Review URL: https://codereview.chromium.org/211683003

git-svn-id: svn://svn.chromium.org/blink/trunk@170234 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent ebfa51e8
<style type="text/css">
.first {
height:400px;
background-color: red;
}
.second {
left: 100px;
bottom: 0px;
background-color:blue;
width:7px;
height:562px;
position: absolute;
}
.outer {
overflow: scroll;
/* FIXME: make this height: 500px to expose another bug */
height: 600px;
width: 500px;
position: absolute;
bottom:10px;
background-color: grey;
}
</style>
<div class="outer">
<div class="first"> </div>
<div class="second"> </div>
</div>
<script>
if (window.internals)
window.internals.settings.setLayerSquashingEnabled(true);
</script>
\ No newline at end of file
<style type="text/css">
.first {
height:400px;
background-color: red;
-webkit-transform: translateZ(0);
}
.second {
left: 100px;
bottom: 0px;
background-color:blue;
width:7px;
height:562px;
position: absolute; -webkit-transform: translateX(0)
}
.outer {
overflow: scroll;
/* FIXME: make this height: 500px to expose another bug */
height: 600px;
width: 500px;
position: absolute;
bottom:10px;
background-color: grey;
}
</style>
<div class="outer">
<div class="first"> </div>
<div class="second"> </div>
</div>
<script>
if (window.internals)
window.internals.settings.setLayerSquashingEnabled(true);
</script>
\ No newline at end of file
......@@ -71,7 +71,7 @@ void RenderLayerClipper::updateClipRects(const ClipRectsContext& clipRectsContex
// For transformed layers, the root layer was shifted to be us, so there is no need to
// examine the parent. We want to cache clip rects with us as the root.
RenderLayer* parentLayer = clipRectsContext.rootLayer != m_renderer->layer() ? m_renderer->layer()->parent() : 0;
RenderLayer* parentLayer = !isClippingRootForContext(clipRectsContext) ? m_renderer->layer()->parent() : 0;
if (parentLayer)
parentLayer->clipper().updateClipRects(clipRectsContext);
......@@ -169,7 +169,9 @@ LayoutRect RenderLayerClipper::localClipRect() const
void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
{
if (clipRectsContext.rootLayer != m_renderer->layer() && m_renderer->layer()->parent()) {
bool isClippingRoot = isClippingRootForContext(clipRectsContext);
if (!isClippingRoot && m_renderer->layer()->parent()) {
backgroundRect = backgroundClipRect(clipRectsContext);
backgroundRect.move(roundedIntSize(clipRectsContext.subPixelAccumulation));
backgroundRect.intersect(paintDirtyRect);
......@@ -190,7 +192,7 @@ void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext
// Update the clip rects that will be passed to child layers.
if (m_renderer->hasOverflowClip()) {
// This layer establishes a clip of some kind.
if (m_renderer->layer() != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip) {
if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip) {
foregroundRect.intersect(toRenderBox(m_renderer)->overflowClipRect(offset, clipRectsContext.overlayScrollbarSizeRelevancy));
if (m_renderer->style()->hasBorderRadius())
foregroundRect.setHasRadius(true);
......@@ -207,12 +209,12 @@ void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext
LayoutRect layerBoundsWithVisualOverflow = toRenderBox(m_renderer)->visualOverflowRect();
toRenderBox(m_renderer)->flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
layerBoundsWithVisualOverflow.moveBy(offset);
if (m_renderer->layer() != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
backgroundRect.intersect(layerBoundsWithVisualOverflow);
} else {
LayoutRect bounds = toRenderBox(m_renderer)->borderBoxRect();
bounds.moveBy(offset);
if (m_renderer->layer() != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
backgroundRect.intersect(bounds);
}
}
......@@ -238,9 +240,11 @@ void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsCon
ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
bool useCached = clipRectsType != TemporaryClipRects;
bool isClippingRoot = isClippingRootForContext(clipRectsContext);
// For transformed layers, the root layer was shifted to be us, so there is no need to
// examine the parent. We want to cache clip rects with us as the root.
RenderLayer* parentLayer = clipRectsContext.rootLayer != m_renderer->layer() ? m_renderer->layer()->parent() : 0;
RenderLayer* parentLayer = !isClippingRoot ? m_renderer->layer()->parent() : 0;
// Ensure that our parent's clip has been calculated so that we can examine the values.
if (parentLayer) {
......@@ -268,7 +272,7 @@ void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsCon
}
// Update the clip rects that will be passed to child layers.
if ((m_renderer->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || m_renderer->layer() != clipRectsContext.rootLayer)) || m_renderer->hasClip()) {
if ((m_renderer->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || !isClippingRoot)) || m_renderer->hasClip()) {
// This layer establishes a clip of some kind.
// This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
......@@ -345,8 +349,19 @@ ClipRect RenderLayerClipper::backgroundClipRect(const ClipRectsContext& clipRect
return backgroundClipRect;
}
bool RenderLayerClipper::isClippingRootForContext(const ClipRectsContext& clipRectsContext) const
{
return clipRectsContext.rootLayer == m_renderer->layer();
}
void RenderLayerClipper::parentClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
{
// The root is not clipped.
if (isClippingRootForContext(clipRectsContext)) {
clipRects.reset(PaintInfo::infiniteRect());
return;
}
ASSERT(m_renderer->layer()->parent());
RenderLayerClipper& parentClipper = m_renderer->layer()->parent()->clipper();
......
......@@ -115,6 +115,8 @@ private:
// The layer relative to which clipping rects for this layer are computed.
RenderLayer* clippingRootForPainting() const;
bool isClippingRootForContext(const ClipRectsContext&) const;
// FIXME: Could this be a RenderBox?
RenderLayerModelObject* m_renderer;
OwnPtr<ClipRectsCache> m_clipRectsCache;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment