void RenderLayerClipper::calculateClipRects(const ClipRectsContext& context, ClipRects& clipRects) const { if (!m_renderer.layer()->parent()) { // The root layer's clip rect is always infinite. clipRects.reset(PaintInfo::infiniteRect()); return; } bool isClippingRoot = m_renderer.layer() == context.rootLayer; // 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 = !isClippingRoot ? m_renderer.layer()->parent() : 0; // Ensure that our parent's clip has been calculated so that we can examine the values. if (parentLayer) { // FIXME: Why don't we just call getClipRects here? if (context.usesCache() && parentLayer->clipper().cachedClipRects(context)) { clipRects = *parentLayer->clipper().cachedClipRects(context); } else { parentLayer->clipper().calculateClipRects(context, clipRects); } } else { clipRects.reset(PaintInfo::infiniteRect()); } if (m_renderer.style()->position() == AbsolutePosition) { clipRects.setOverflowClipRect(clipRects.posClipRect()); } // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where // clipRects are needed in view space. LayoutPoint offset = roundedLayoutPoint(m_renderer.localToContainerPoint(FloatPoint(), context.rootLayer->renderer())); if (m_renderer.hasOverflowClip()) { ClipRect newOverflowClip = m_renderer.overflowClipRect(offset); newOverflowClip.setHasRadius(m_renderer.style()->hasBorderRadius()); clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect())); if (m_renderer.isPositioned()) clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); } if (m_renderer.hasClip()) { LayoutRect newClip = m_renderer.clipRect(offset); clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect())); clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect())); } }
void RenderLayerClipper::clearClipRectsIncludingDescendants() { m_cache = nullptr; for (RenderLayer* layer = m_renderer.layer()->firstChild(); layer; layer = layer->nextSibling()) layer->clipper().clearClipRectsIncludingDescendants(); }
void RenderLayerClipper::clearClipRectsIncludingDescendants(ClipRectsCacheSlot cacheSlot) { if (m_cache) m_cache->clear(cacheSlot); for (RenderLayer* layer = m_renderer.layer()->firstChild(); layer; layer = layer->nextSibling()) layer->clipper().clearClipRectsIncludingDescendants(cacheSlot); }
void RenderLayerClipper::updateClipRects(const ClipRectsContext& clipRectsContext) { ClipRectsType clipRectsType = clipRectsContext.clipRectsType; ASSERT(clipRectsType < NumCachedClipRectsTypes); if (m_clipRectsCache && clipRectsContext.rootLayer == m_clipRectsCache->clipRectsRoot(clipRectsType) && m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip)) { // FIXME: We used to ASSERT that we always got a consistent root layer. // We should add a test that has an inconsistent root. See // http://crbug.com/366118 for an example. ASSERT(m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] == clipRectsContext.overlayScrollbarSizeRelevancy); #ifdef CHECK_CACHED_CLIP_RECTS // This code is useful to check cached clip rects, but is too expensive to leave enabled in debug builds by default. ClipRectsContext tempContext(clipRectsContext); tempContext.clipRectsType = TemporaryClipRects; ClipRects clipRects; calculateClipRects(tempContext, clipRects); ASSERT(clipRects == *m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip).get()); #endif return; // We have the correct cached value. } // 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 = !isClippingRootForContext(clipRectsContext) ? m_renderer.layer()->parent() : 0; if (parentLayer) parentLayer->clipper().updateClipRects(clipRectsContext); ClipRects clipRects; calculateClipRects(clipRectsContext, clipRects); if (!m_clipRectsCache) m_clipRectsCache = adoptPtr(new ClipRectsCache); if (parentLayer && parentLayer->clipper().clipRects(clipRectsContext) && clipRects == *parentLayer->clipper().clipRects(clipRectsContext)) m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, parentLayer->clipper().clipRects(clipRectsContext), clipRectsContext.rootLayer); else m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, ClipRects::create(clipRects), clipRectsContext.rootLayer); #ifndef NDEBUG m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] = clipRectsContext.overlayScrollbarSizeRelevancy; #endif }
void RenderLayerClipper::updateClipRects(const ClipRectsContext& clipRectsContext) { ClipRectsType clipRectsType = clipRectsContext.clipRectsType; ASSERT(clipRectsType < NumCachedClipRectsTypes); if (m_clipRectsCache && m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip)) { // FIXME: these asserts trigger for squashing. Need to update this code to support squashing as appropriate. ASSERT(clipRectsContext.rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]); ASSERT(m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] == clipRectsContext.overlayScrollbarSizeRelevancy); #ifdef CHECK_CACHED_CLIP_RECTS // This code is useful to check cached clip rects, but is too expensive to leave enabled in debug builds by default. ClipRectsContext tempContext(clipRectsContext); tempContext.clipRectsType = TemporaryClipRects; ClipRects clipRects; calculateClipRects(tempContext, clipRects); ASSERT(clipRects == *m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip).get()); #endif return; // We have the correct cached value. } // 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; if (parentLayer) parentLayer->clipper().updateClipRects(clipRectsContext); ClipRects clipRects; calculateClipRects(clipRectsContext, clipRects); if (!m_clipRectsCache) m_clipRectsCache = adoptPtr(new ClipRectsCache); if (parentLayer && parentLayer->clipper().clipRects(clipRectsContext) && clipRects == *parentLayer->clipper().clipRects(clipRectsContext)) m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, parentLayer->clipper().clipRects(clipRectsContext)); else m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, ClipRects::create(clipRects)); #ifndef NDEBUG m_clipRectsCache->m_clipRectsRoot[clipRectsType] = clipRectsContext.rootLayer; m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] = clipRectsContext.overlayScrollbarSizeRelevancy; #endif }
void RenderLayerClipper::clearClipRectsIncludingDescendants(ClipRectsType typeToClear) { // FIXME: it's not clear how this layer not having clip rects guarantees that no descendants have any. if (!m_clipRectsCache) return; clearClipRects(typeToClear); for (RenderLayer* layer = m_renderer->layer()->firstChild(); layer; layer = layer->nextSibling()) layer->clipper().clearClipRectsIncludingDescendants(typeToClear); }
void RenderLayerClipper::calculateClipRects(const ClipRectsContext& context, ClipRects& clipRects) const { if (!m_renderer.layer()->parent()) { // The root layer's clip rect is always infinite. clipRects.reset(PaintInfo::infiniteRect()); return; } bool isClippingRoot = m_renderer.layer() == context.rootLayer; // 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 = !isClippingRoot ? m_renderer.layer()->parent() : 0; // Ensure that our parent's clip has been calculated so that we can examine the values. if (parentLayer) { // FIXME: Why don't we just call getClipRects here? if (context.usesCache() && parentLayer->clipper().cachedClipRects(context)) { clipRects = *parentLayer->clipper().cachedClipRects(context); } else { parentLayer->clipper().calculateClipRects(context, clipRects); } } else { clipRects.reset(PaintInfo::infiniteRect()); } adjustClipRectsForChildren(m_renderer, clipRects); // FIXME: This logic looks wrong. We'll apply overflow clip rects even if we were told to IgnoreOverflowClip if m_renderer.hasClip(). if ((m_renderer.hasOverflowClip() && (context.respectOverflowClip == RespectOverflowClip || !isClippingRoot)) || m_renderer.hasClip()) { // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where // clipRects are needed in view space. applyClipRects(context, m_renderer, roundedLayoutPoint(m_renderer.localToContainerPoint(FloatPoint(), context.rootLayer->renderer())), clipRects); } }
void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const { if (!m_renderer->layer()->parent()) { // The root layer's clip rect is always infinite. clipRects.reset(PaintInfo::infiniteRect()); return; } ClipRectsType clipRectsType = clipRectsContext.clipRectsType; bool useCached = clipRectsType != TemporaryClipRects; // 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; // Ensure that our parent's clip has been calculated so that we can examine the values. if (parentLayer) { if (useCached && parentLayer->clipper().clipRects(clipRectsContext)) { clipRects = *parentLayer->clipper().clipRects(clipRectsContext); } else { ClipRectsContext parentContext(clipRectsContext); parentContext.overlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize; // FIXME: why? parentLayer->clipper().calculateClipRects(parentContext, clipRects); } } else { clipRects.reset(PaintInfo::infiniteRect()); } // 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_renderer->style()->position() == FixedPosition) { clipRects.setPosClipRect(clipRects.fixedClipRect()); clipRects.setOverflowClipRect(clipRects.fixedClipRect()); clipRects.setFixed(true); } else if (m_renderer->style()->hasInFlowPosition()) { clipRects.setPosClipRect(clipRects.overflowClipRect()); } else if (m_renderer->style()->position() == AbsolutePosition) { clipRects.setOverflowClipRect(clipRects.posClipRect()); } // 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()) { // This layer establishes a clip of some kind. // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where // clipRects are needed in view space. LayoutPoint offset; offset = roundedLayoutPoint(m_renderer->localToContainerPoint(FloatPoint(), clipRectsContext.rootLayer->renderer())); RenderView* view = m_renderer->view(); ASSERT(view); if (view && clipRects.fixed() && clipRectsContext.rootLayer->renderer() == view) { offset -= view->frameView()->scrollOffsetForFixedPosition(); } if (m_renderer->hasOverflowClip()) { ClipRect newOverflowClip = toRenderBox(m_renderer)->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy); if (m_renderer->style()->hasBorderRadius()) newOverflowClip.setHasRadius(true); clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect())); if (m_renderer->isPositioned()) clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); } if (m_renderer->hasClip()) { LayoutRect newPosClip = toRenderBox(m_renderer)->clipRect(offset, clipRectsContext.region); clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect())); clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect())); clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect())); } } }