This source file includes following definitions.
- updateClipRects
- clearClipRectsIncludingDescendants
- clearClipRects
- childrenClipRect
- selfClipRect
- localClipRect
- calculateRects
- calculateClipRects
- backgroundClipRectForPosition
- setCompositingClipRectsDirty
- backgroundClipRect
- isClippingRootForContext
- parentClipRects
- clippingRootForPainting
#include "config.h"
#include "core/rendering/RenderLayerClipper.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
namespace WebCore {
void RenderLayerClipper::updateClipRects(const ClipRectsContext& clipRectsContext)
{
ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
ASSERT(clipRectsType < NumCachedClipRectsTypes);
if (m_clipRectsCache && m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip)) {
ASSERT(clipRectsContext.rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
ASSERT(m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] == clipRectsContext.overlayScrollbarSizeRelevancy);
#ifdef CHECK_CACHED_CLIP_RECTS
ClipRectsContext tempContext(clipRectsContext);
tempContext.clipRectsType = TemporaryClipRects;
ClipRects clipRects;
calculateClipRects(tempContext, clipRects);
ASSERT(clipRects == *m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip).get());
#endif
return;
}
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));
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)
{
if (!m_clipRectsCache)
return;
clearClipRects(typeToClear);
for (RenderLayer* layer = m_renderer->layer()->firstChild(); layer; layer = layer->nextSibling())
layer->clipper().clearClipRectsIncludingDescendants(typeToClear);
}
void RenderLayerClipper::clearClipRects(ClipRectsType typeToClear)
{
if (typeToClear == AllClipRectTypes) {
m_clipRectsCache = nullptr;
m_compositingClipRectsDirty = false;
} else {
if (typeToClear == CompositingClipRects)
m_compositingClipRectsDirty = false;
ASSERT(typeToClear < NumCachedClipRectsTypes);
RefPtr<ClipRects> dummy;
m_clipRectsCache->setClipRects(typeToClear, RespectOverflowClip, dummy);
m_clipRectsCache->setClipRects(typeToClear, IgnoreOverflowClip, dummy);
}
}
LayoutRect RenderLayerClipper::childrenClipRect() const
{
RenderView* renderView = m_renderer->view();
RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
ClipRectsContext clipRectsContext(clippingRootLayer, TemporaryClipRects);
calculateRects(clipRectsContext, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
}
LayoutRect RenderLayerClipper::selfClipRect() const
{
RenderView* renderView = m_renderer->view();
RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
ClipRectsContext clipRectsContext(clippingRootLayer, PaintingClipRects);
calculateRects(clipRectsContext, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect.rect())).enclosingBoundingBox();
}
LayoutRect RenderLayerClipper::localClipRect() const
{
RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
ClipRectsContext clipRectsContext(clippingRootLayer, PaintingClipRects);
calculateRects(clipRectsContext, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
LayoutRect clipRect = backgroundRect.rect();
if (clipRect == PaintInfo::infiniteRect())
return clipRect;
LayoutPoint clippingRootOffset;
m_renderer->layer()->convertToLayerCoords(clippingRootLayer, clippingRootOffset);
clipRect.moveBy(-clippingRootOffset);
return clipRect;
}
void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
{
bool isClippingRoot = isClippingRootForContext(clipRectsContext);
if (!isClippingRoot && m_renderer->layer()->parent()) {
backgroundRect = backgroundClipRect(clipRectsContext);
backgroundRect.move(roundedIntSize(clipRectsContext.subPixelAccumulation));
backgroundRect.intersect(paintDirtyRect);
} else {
backgroundRect = paintDirtyRect;
}
foregroundRect = backgroundRect;
outlineRect = backgroundRect;
LayoutPoint offset;
if (offsetFromRoot)
offset = *offsetFromRoot;
else
m_renderer->layer()->convertToLayerCoords(clipRectsContext.rootLayer, offset);
layerBounds = LayoutRect(offset, m_renderer->layer()->size());
if (m_renderer->hasOverflowClip()) {
if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip) {
foregroundRect.intersect(toRenderBox(m_renderer)->overflowClipRect(offset, clipRectsContext.overlayScrollbarSizeRelevancy));
if (m_renderer->style()->hasBorderRadius())
foregroundRect.setHasRadius(true);
}
if (toRenderBox(m_renderer)->hasVisualOverflow()) {
LayoutRect layerBoundsWithVisualOverflow = toRenderBox(m_renderer)->visualOverflowRect();
toRenderBox(m_renderer)->flipForWritingMode(layerBoundsWithVisualOverflow);
layerBoundsWithVisualOverflow.moveBy(offset);
if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
backgroundRect.intersect(layerBoundsWithVisualOverflow);
} else {
LayoutRect bounds = toRenderBox(m_renderer)->borderBoxRect();
bounds.moveBy(offset);
if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
backgroundRect.intersect(bounds);
}
}
if (m_renderer->hasClip()) {
LayoutRect newPosClip = toRenderBox(m_renderer)->clipRect(offset);
backgroundRect.intersect(newPosClip);
foregroundRect.intersect(newPosClip);
outlineRect.intersect(newPosClip);
}
}
void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
{
if (!m_renderer->layer()->parent()) {
clipRects.reset(PaintInfo::infiniteRect());
return;
}
ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
bool useCached = clipRectsType != TemporaryClipRects;
bool isClippingRoot = isClippingRootForContext(clipRectsContext);
RenderLayer* parentLayer = !isClippingRoot ? m_renderer->layer()->parent() : 0;
if (parentLayer) {
if (useCached && parentLayer->clipper().clipRects(clipRectsContext)) {
clipRects = *parentLayer->clipper().clipRects(clipRectsContext);
} else {
ClipRectsContext parentContext(clipRectsContext);
parentContext.overlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize;
parentLayer->clipper().calculateClipRects(parentContext, clipRects);
}
} else {
clipRects.reset(PaintInfo::infiniteRect());
}
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());
}
if ((m_renderer->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || !isClippingRoot)) || m_renderer->hasClip()) {
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()));
}
}
}
static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
{
if (position == FixedPosition)
return parentRects.fixedClipRect();
if (position == AbsolutePosition)
return parentRects.posClipRect();
return parentRects.overflowClipRect();
}
void RenderLayerClipper::setCompositingClipRectsDirty()
{
m_compositingClipRectsDirty = true;
}
ClipRect RenderLayerClipper::backgroundClipRect(const ClipRectsContext& clipRectsContext) const
{
ASSERT(m_renderer->layer()->parent());
if (clipRectsContext.clipRectsType == CompositingClipRects)
const_cast<RenderLayerClipper*>(this)->clearClipRectsIncludingDescendants(CompositingClipRects);
ClipRects parentRects;
if (clipRectsContext.clipRectsType != TemporaryClipRects && m_renderer->layer()->parent()->enclosingPaginationLayer() != m_renderer->layer()->enclosingPaginationLayer()) {
ClipRectsContext tempContext(clipRectsContext);
tempContext.clipRectsType = TemporaryClipRects;
parentClipRects(tempContext, parentRects);
} else {
parentClipRects(clipRectsContext, parentRects);
}
ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, m_renderer->style()->position());
RenderView* view = m_renderer->view();
ASSERT(view);
if (parentRects.fixed() && clipRectsContext.rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition());
return backgroundClipRect;
}
bool RenderLayerClipper::isClippingRootForContext(const ClipRectsContext& clipRectsContext) const
{
return clipRectsContext.rootLayer == m_renderer->layer();
}
void RenderLayerClipper::parentClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
{
if (isClippingRootForContext(clipRectsContext)) {
clipRects.reset(PaintInfo::infiniteRect());
return;
}
ASSERT(m_renderer->layer()->parent());
RenderLayerClipper& parentClipper = m_renderer->layer()->parent()->clipper();
if (clipRectsContext.clipRectsType == TemporaryClipRects) {
parentClipper.calculateClipRects(clipRectsContext, clipRects);
return;
}
parentClipper.updateClipRects(clipRectsContext);
clipRects = *parentClipper.clipRects(clipRectsContext);
}
RenderLayer* RenderLayerClipper::clippingRootForPainting() const
{
if (m_renderer->hasCompositedLayerMapping() || m_renderer->groupedMapping())
return const_cast<RenderLayer*>(m_renderer->layer());
const RenderLayer* current = m_renderer->layer();
while (current) {
if (current->isRootLayer())
return const_cast<RenderLayer*>(current);
current = current->compositingContainer();
ASSERT(current);
if (current->transform() || (current->compositingState() == PaintsIntoOwnBacking) || current->groupedMapping())
return const_cast<RenderLayer*>(current);
}
ASSERT_NOT_REACHED();
return 0;
}
}