OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/paint/ClipRecorder.h" | 6 #include "core/paint/ClipRecorder.h" |
7 | 7 |
8 #include "core/paint/ViewDisplayList.h" | 8 #include "core/rendering/ClipRect.h" |
9 #include "core/rendering/PaintInfo.h" | 9 #include "core/rendering/RenderLayer.h" |
10 #include "core/rendering/RenderLayerModelObject.h" | |
11 #include "core/rendering/RenderView.h" | 10 #include "core/rendering/RenderView.h" |
12 #include "platform/RuntimeEnabledFeatures.h" | 11 #include "platform/RuntimeEnabledFeatures.h" |
| 12 #include "platform/geometry/IntRect.h" |
| 13 #include "platform/graphics/GraphicsContext.h" |
13 | 14 |
14 namespace blink { | 15 namespace blink { |
15 | 16 |
16 ClipRecorder::ClipRecorder(RenderLayerModelObject& canvas, const PaintInfo& pain
tInfo, const LayoutRect& clipRect) | 17 void ClipDisplayItem::replay(GraphicsContext* context) |
17 : m_clipRect(clipRect) | |
18 , m_paintInfo(paintInfo) | |
19 , m_canvas(canvas) | |
20 { | 18 { |
21 DisplayItem::Type type = paintPhaseToClipType(paintInfo.phase); | 19 context->save(); |
22 OwnPtr<ClipDisplayItem> clipDisplayItem = adoptPtr(new ClipDisplayItem(&m_ca
nvas, type, pixelSnappedIntRect(clipRect))); | 20 context->clip(m_clipRect); |
| 21 for (RoundedRect roundedRect : m_roundedRectClips) |
| 22 context->clipRoundedRect(roundedRect); |
| 23 } |
23 | 24 |
24 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) | 25 void EndClipDisplayItem::replay(GraphicsContext* context) |
25 m_canvas.view()->viewDisplayList().add(clipDisplayItem.release()); | 26 { |
26 else | 27 context->restore(); |
27 clipDisplayItem->replay(paintInfo.context); | 28 } |
| 29 |
| 30 ClipRecorder::ClipRecorder(const RenderLayerModelObject* renderer, GraphicsConte
xt* graphicsContext, DisplayItem::Type clipType, const ClipRect& clipRect, |
| 31 const LayerPaintingInfo* localPaintingInfo, const LayoutPoint& fragmentOffse
t, PaintLayerFlags paintFlags, BorderRadiusClippingRule rule) |
| 32 : m_graphicsContext(graphicsContext) |
| 33 , m_renderer(renderer) |
| 34 { |
| 35 IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect()); |
| 36 OwnPtr<ClipDisplayItem> clipDisplayItem = adoptPtr(new ClipDisplayItem(rende
rer, clipType, snappedClipRect)); |
| 37 if (localPaintingInfo && clipRect.hasRadius()) |
| 38 collectRoundedRectClips(*renderer->layer(), *localPaintingInfo, graphics
Context, fragmentOffset, paintFlags, rule, clipDisplayItem->roundedRectClips()); |
| 39 if (!RuntimeEnabledFeatures::slimmingPaintEnabled()) { |
| 40 clipDisplayItem->replay(graphicsContext); |
| 41 } else { |
| 42 m_renderer->view()->viewDisplayList().add(clipDisplayItem.release()); |
| 43 } |
| 44 } |
| 45 |
| 46 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
r) |
| 47 { |
| 48 if (startLayer == endLayer) |
| 49 return true; |
| 50 |
| 51 RenderView* view = startLayer->renderer()->view(); |
| 52 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock();
currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlo
ck()) { |
| 53 if (currentBlock->layer() == endLayer) |
| 54 return true; |
| 55 } |
| 56 |
| 57 return false; |
| 58 } |
| 59 |
| 60 void ClipRecorder::collectRoundedRectClips(RenderLayer& renderLayer, const Layer
PaintingInfo& localPaintingInfo, GraphicsContext* context, const LayoutPoint& fr
agmentOffset, PaintLayerFlags paintFlags, |
| 61 BorderRadiusClippingRule rule, Vector<RoundedRect>& roundedRectClips) |
| 62 { |
| 63 // If the clip rect has been tainted by a border radius, then we have to wal
k up our layer chain applying the clips from |
| 64 // any layers with overflow. The condition for being able to apply these cli
ps is that the overflow object be in our |
| 65 // containing block chain so we check that also. |
| 66 for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? &renderLayer
: renderLayer.parent(); layer; layer = layer->parent()) { |
| 67 // Composited scrolling layers handle border-radius clip in the composit
or via a mask layer. We do not |
| 68 // want to apply a border-radius clip to the layer contents itself, beca
use that would require re-rastering |
| 69 // every frame to update the clip. We only want to make sure that the ma
sk layer is properly clipped so |
| 70 // that it can in turn clip the scrolled contents in the compositor. |
| 71 if (layer->needsCompositedScrolling() && !(paintFlags & PaintLayerPainti
ngChildClippingMaskPhase)) |
| 72 break; |
| 73 |
| 74 if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->
hasBorderRadius() && inContainingBlockChain(&renderLayer, layer)) { |
| 75 LayoutPoint delta(fragmentOffset); |
| 76 layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta); |
| 77 roundedRectClips.append(layer->renderer()->style()->getRoundedInnerB
orderFor(LayoutRect(delta, LayoutSize(layer->size())))); |
| 78 } |
| 79 |
| 80 if (layer == localPaintingInfo.rootLayer) |
| 81 break; |
| 82 } |
28 } | 83 } |
29 | 84 |
30 ClipRecorder::~ClipRecorder() | 85 ClipRecorder::~ClipRecorder() |
31 { | 86 { |
32 OwnPtr<EndClipDisplayItem> endClipDisplayItem = adoptPtr(new EndClipDisplayI
tem(&m_canvas)); | |
33 | |
34 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) { | 87 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) { |
35 m_canvas.view()->viewDisplayList().add(endClipDisplayItem.release()); | 88 OwnPtr<EndClipDisplayItem> endClip = adoptPtr(new EndClipDisplayItem(m_r
enderer)); |
| 89 m_renderer->view()->viewDisplayList().add(endClip.release()); |
36 } else { | 90 } else { |
37 endClipDisplayItem->replay(m_paintInfo.context); | 91 m_graphicsContext->restore(); |
38 } | 92 } |
39 } | 93 } |
40 | 94 |
41 DisplayItem::Type ClipRecorder::paintPhaseToClipType(PaintPhase paintPhase) | 95 #ifndef NDEBUG |
| 96 WTF::String ClipDisplayItem::asDebugString() const |
42 { | 97 { |
43 switch (paintPhase) { | 98 return String::format("{%s, type: \"%s\", clipRect: [%d,%d,%d,%d]}", |
44 case PaintPhaseChildBlockBackgrounds: | 99 rendererDebugString(renderer()).utf8().data(), typeAsDebugString(type())
.utf8().data(), |
45 return DisplayItem::ClipBoxChildBlockBackgrounds; | 100 m_clipRect.x(), m_clipRect.y(), m_clipRect.width(), m_clipRect.height())
; |
46 break; | |
47 case PaintPhaseFloat: | |
48 return DisplayItem::ClipBoxFloat; | |
49 break; | |
50 case PaintPhaseForeground: | |
51 return DisplayItem::ClipBoxChildBlockBackgrounds; | |
52 break; | |
53 case PaintPhaseChildOutlines: | |
54 return DisplayItem::ClipBoxChildOutlines; | |
55 break; | |
56 case PaintPhaseSelection: | |
57 return DisplayItem::ClipBoxSelection; | |
58 break; | |
59 case PaintPhaseCollapsedTableBorders: | |
60 return DisplayItem::ClipBoxCollapsedTableBorders; | |
61 break; | |
62 case PaintPhaseTextClip: | |
63 return DisplayItem::ClipBoxTextClip; | |
64 break; | |
65 case PaintPhaseClippingMask: | |
66 return DisplayItem::ClipBoxClippingMask; | |
67 break; | |
68 case PaintPhaseChildBlockBackground: | |
69 case PaintPhaseOutline: | |
70 case PaintPhaseBlockBackground: | |
71 case PaintPhaseSelfOutline: | |
72 case PaintPhaseMask: | |
73 ASSERT_NOT_REACHED(); | |
74 } | |
75 // This should never happen. | |
76 return DisplayItem::ClipBoxForeground; | |
77 } | 101 } |
| 102 #endif |
78 | 103 |
79 } // namespace blink | 104 } // namespace blink |
OLD | NEW |