1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/paint/LayerClipRecorder.h"
#include "core/rendering/ClipRect.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/geometry/IntRect.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/graphics/paint/ClipRecorder.h"
#include "platform/graphics/paint/DisplayItemList.h"
namespace blink {
LayerClipRecorder::LayerClipRecorder(const RenderLayerModelObject* renderer, GraphicsContext* graphicsContext, DisplayItem::Type clipType, const ClipRect& clipRect,
const LayerPaintingInfo* localPaintingInfo, const LayoutPoint& fragmentOffset, PaintLayerFlags paintFlags, BorderRadiusClippingRule rule)
: m_graphicsContext(graphicsContext)
, m_renderer(renderer)
{
ASSERT(renderer);
IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect());
OwnPtr<ClipDisplayItem> clipDisplayItem = ClipDisplayItem::create(renderer->displayItemClient(), clipType, snappedClipRect);
if (localPaintingInfo && clipRect.hasRadius())
collectRoundedRectClips(*renderer->layer(), *localPaintingInfo, graphicsContext, fragmentOffset, paintFlags, rule, clipDisplayItem->roundedRectClips());
if (!RuntimeEnabledFeatures::slimmingPaintEnabled()) {
clipDisplayItem->replay(graphicsContext);
} else {
ASSERT(m_graphicsContext->displayItemList());
m_graphicsContext->displayItemList()->add(clipDisplayItem.release());
}
}
static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer)
{
if (startLayer == endLayer)
return true;
RenderView* view = startLayer->renderer()->view();
for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlock()) {
if (currentBlock->layer() == endLayer)
return true;
}
return false;
}
void LayerClipRecorder::collectRoundedRectClips(RenderLayer& renderLayer, const LayerPaintingInfo& localPaintingInfo, GraphicsContext* context, const LayoutPoint& fragmentOffset, PaintLayerFlags paintFlags,
BorderRadiusClippingRule rule, Vector<FloatRoundedRect>& roundedRectClips)
{
// If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
// any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
// containing block chain so we check that also.
for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? &renderLayer : renderLayer.parent(); layer; layer = layer->parent()) {
// Composited scrolling layers handle border-radius clip in the compositor via a mask layer. We do not
// want to apply a border-radius clip to the layer contents itself, because that would require re-rastering
// every frame to update the clip. We only want to make sure that the mask layer is properly clipped so
// that it can in turn clip the scrolled contents in the compositor.
if (layer->needsCompositedScrolling() && !(paintFlags & PaintLayerPaintingChildClippingMaskPhase))
break;
if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(&renderLayer, layer)) {
LayoutPoint delta(fragmentOffset);
layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta);
roundedRectClips.append(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, LayoutSize(layer->size()))));
}
if (layer == localPaintingInfo.rootLayer)
break;
}
}
LayerClipRecorder::~LayerClipRecorder()
{
if (RuntimeEnabledFeatures::slimmingPaintEnabled()) {
OwnPtr<EndClipDisplayItem> endClip = EndClipDisplayItem::create(m_renderer->displayItemClient());
ASSERT(m_graphicsContext->displayItemList());
m_graphicsContext->displayItemList()->add(endClip.release());
} else {
m_graphicsContext->restore();
}
}
} // namespace blink
|