void PaintLayerClipper::calculateRects( const ClipRectsContext& context, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds, ClipRect& backgroundRect, ClipRect& foregroundRect, const LayoutPoint* offsetFromRoot) const { if (m_geometryMapper) { calculateRectsWithGeometryMapper(context, paintDirtyRect, layerBounds, backgroundRect, foregroundRect, offsetFromRoot); return; } bool isClippingRoot = &m_layer == context.rootLayer; LayoutBoxModelObject& layoutObject = *m_layer.layoutObject(); if (!isClippingRoot && m_layer.parent()) { backgroundRect = backgroundClipRect(context); backgroundRect.move(context.subPixelAccumulation); backgroundRect.intersect(paintDirtyRect); } else { backgroundRect = paintDirtyRect; } foregroundRect = backgroundRect; LayoutPoint offset; if (offsetFromRoot) offset = *offsetFromRoot; else m_layer.convertToLayerCoords(context.rootLayer, offset); layerBounds = LayoutRect(offset, LayoutSize(m_layer.size())); // Update the clip rects that will be passed to child layers. if (shouldClipOverflow(context)) { foregroundRect.intersect( toLayoutBox(layoutObject) .overflowClipRect(offset, context.overlayScrollbarClipBehavior)); if (layoutObject.styleRef().hasBorderRadius()) foregroundRect.setHasRadius(true); // FIXME: Does not do the right thing with columns yet, since we don't yet // factor in the individual column boxes as overflow. // The LayoutView is special since its overflow clipping rect may be larger // than its box rect (crbug.com/492871). LayoutRect layerBoundsWithVisualOverflow = layoutObject.isLayoutView() ? toLayoutView(layoutObject).viewRect() : toLayoutBox(layoutObject).visualOverflowRect(); // PaintLayer are in physical coordinates, so the overflow has to be // flipped. toLayoutBox(layoutObject).flipForWritingMode(layerBoundsWithVisualOverflow); layerBoundsWithVisualOverflow.moveBy(offset); backgroundRect.intersect(layerBoundsWithVisualOverflow); } // CSS clip (different than clipping due to overflow) can clip to any box, // even if it falls outside of the border box. if (layoutObject.hasClip()) { // Clip applies to *us* as well, so go ahead and update the damageRect. LayoutRect newPosClip = toLayoutBox(layoutObject).clipRect(offset); backgroundRect.intersect(newPosClip); backgroundRect.setIsClippedByClipCss(); foregroundRect.intersect(newPosClip); foregroundRect.setIsClippedByClipCss(); } }
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.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); clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect())); clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect())); clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect())); } } }