Index: Source/core/paint/ClipRecorder.cpp |
diff --git a/Source/core/paint/ClipRecorder.cpp b/Source/core/paint/ClipRecorder.cpp |
index 7aa6bead920b2b5d5acf85c33507207e5bbbc2e7..5c2e696bd3bd547ed5b772bfc43cce85e125acee 100644 |
--- a/Source/core/paint/ClipRecorder.cpp |
+++ b/Source/core/paint/ClipRecorder.cpp |
@@ -5,75 +5,100 @@ |
#include "config.h" |
#include "core/paint/ClipRecorder.h" |
-#include "core/paint/ViewDisplayList.h" |
-#include "core/rendering/PaintInfo.h" |
-#include "core/rendering/RenderLayerModelObject.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" |
namespace blink { |
-ClipRecorder::ClipRecorder(RenderLayerModelObject& canvas, const PaintInfo& paintInfo, const LayoutRect& clipRect) |
- : m_clipRect(clipRect) |
- , m_paintInfo(paintInfo) |
- , m_canvas(canvas) |
+void ClipDisplayItem::replay(GraphicsContext* context) |
{ |
- DisplayItem::Type type = paintPhaseToClipType(paintInfo.phase); |
- OwnPtr<ClipDisplayItem> clipDisplayItem = adoptPtr(new ClipDisplayItem(&m_canvas, type, pixelSnappedIntRect(clipRect))); |
+ context->save(); |
+ context->clip(m_clipRect); |
+ for (RoundedRect roundedRect : m_roundedRectClips) |
+ context->clipRoundedRect(roundedRect); |
+} |
- if (RuntimeEnabledFeatures::slimmingPaintEnabled()) |
- m_canvas.view()->viewDisplayList().add(clipDisplayItem.release()); |
- else |
- clipDisplayItem->replay(paintInfo.context); |
+void EndClipDisplayItem::replay(GraphicsContext* context) |
+{ |
+ context->restore(); |
+} |
+ |
+ClipRecorder::ClipRecorder(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) |
+{ |
+ IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect()); |
+ OwnPtr<ClipDisplayItem> clipDisplayItem = adoptPtr(new ClipDisplayItem(renderer, clipType, snappedClipRect)); |
+ if (localPaintingInfo && clipRect.hasRadius()) |
+ collectRoundedRectClips(*renderer->layer(), *localPaintingInfo, graphicsContext, fragmentOffset, paintFlags, rule, clipDisplayItem->roundedRectClips()); |
+ if (!RuntimeEnabledFeatures::slimmingPaintEnabled()) { |
+ clipDisplayItem->replay(graphicsContext); |
+ } else { |
+ m_renderer->view()->viewDisplayList().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 ClipRecorder::collectRoundedRectClips(RenderLayer& renderLayer, const LayerPaintingInfo& localPaintingInfo, GraphicsContext* context, const LayoutPoint& fragmentOffset, PaintLayerFlags paintFlags, |
+ BorderRadiusClippingRule rule, Vector<RoundedRect>& 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; |
+ } |
} |
ClipRecorder::~ClipRecorder() |
{ |
- OwnPtr<EndClipDisplayItem> endClipDisplayItem = adoptPtr(new EndClipDisplayItem(&m_canvas)); |
- |
if (RuntimeEnabledFeatures::slimmingPaintEnabled()) { |
- m_canvas.view()->viewDisplayList().add(endClipDisplayItem.release()); |
+ OwnPtr<EndClipDisplayItem> endClip = adoptPtr(new EndClipDisplayItem(m_renderer)); |
+ m_renderer->view()->viewDisplayList().add(endClip.release()); |
} else { |
- endClipDisplayItem->replay(m_paintInfo.context); |
+ m_graphicsContext->restore(); |
} |
} |
-DisplayItem::Type ClipRecorder::paintPhaseToClipType(PaintPhase paintPhase) |
+#ifndef NDEBUG |
+WTF::String ClipDisplayItem::asDebugString() const |
{ |
- switch (paintPhase) { |
- case PaintPhaseChildBlockBackgrounds: |
- return DisplayItem::ClipBoxChildBlockBackgrounds; |
- break; |
- case PaintPhaseFloat: |
- return DisplayItem::ClipBoxFloat; |
- break; |
- case PaintPhaseForeground: |
- return DisplayItem::ClipBoxChildBlockBackgrounds; |
- break; |
- case PaintPhaseChildOutlines: |
- return DisplayItem::ClipBoxChildOutlines; |
- break; |
- case PaintPhaseSelection: |
- return DisplayItem::ClipBoxSelection; |
- break; |
- case PaintPhaseCollapsedTableBorders: |
- return DisplayItem::ClipBoxCollapsedTableBorders; |
- break; |
- case PaintPhaseTextClip: |
- return DisplayItem::ClipBoxTextClip; |
- break; |
- case PaintPhaseClippingMask: |
- return DisplayItem::ClipBoxClippingMask; |
- break; |
- case PaintPhaseChildBlockBackground: |
- case PaintPhaseOutline: |
- case PaintPhaseBlockBackground: |
- case PaintPhaseSelfOutline: |
- case PaintPhaseMask: |
- ASSERT_NOT_REACHED(); |
- } |
- // This should never happen. |
- return DisplayItem::ClipBoxForeground; |
+ return String::format("{%s, type: \"%s\", clipRect: [%d,%d,%d,%d]}", |
+ rendererDebugString(renderer()).utf8().data(), typeAsDebugString(type()).utf8().data(), |
+ m_clipRect.x(), m_clipRect.y(), m_clipRect.width(), m_clipRect.height()); |
} |
+#endif |
} // namespace blink |