Index: Source/core/paint/LayerPainter.cpp |
diff --git a/Source/core/paint/LayerPainter.cpp b/Source/core/paint/LayerPainter.cpp |
index 4a2369183571a3f3535503d6ca8dd08ecb7d739a..1a2ff1a50ade6bfd7ab022c9ba6efba195a24a82 100644 |
--- a/Source/core/paint/LayerPainter.cpp |
+++ b/Source/core/paint/LayerPainter.cpp |
@@ -75,17 +75,8 @@ void LayerPainter::paintLayer(GraphicsContext* context, const LayerPaintingInfo& |
if (!layerTransform.isInvertible()) |
return; |
- // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency |
- // layer from the parent now, assuming there is a parent |
- if (paintFlags & PaintLayerHaveTransparency) { |
- // FIXME: can we get rid of this? It would mean transparency starts after clipping in these cases. |
- if (m_renderLayer.parent()) |
- LayerPainter(*m_renderLayer.parent()).beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); |
- else |
- beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); |
- } |
- |
if (m_renderLayer.enclosingPaginationLayer()) { |
+ // FIXME: unify this one-off path with the code below. |
paintTransformedLayerIntoFragments(context, paintingInfo, paintFlags); |
return; |
} |
@@ -116,39 +107,47 @@ void LayerPainter::paintLayer(GraphicsContext* context, const LayerPaintingInfo& |
paintLayerContentsAndReflection(context, paintingInfo, paintFlags); |
} |
-bool LayerPainter::shouldCreateTransparencyLayerForBlendMode() |
-{ |
- return !m_renderLayer.renderer()->isDocumentElement() && m_renderLayer.stackingNode()->isStackingContext() && m_renderLayer.hasNonIsolatedDescendantWithBlendMode(); |
-} |
- |
-void LayerPainter::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior) |
-{ |
- // Blending operations must be performed only with the nearest ancestor stacking context. |
- // Note that there is no need to create a transparency layer if we're painting the root. |
- // FIXME: this should be unified further into RenderLayer::paintsWithTransparency(). |
- if (!m_renderLayer.paintsWithTransparency(paintBehavior) && !shouldCreateTransparencyLayerForBlendMode()) |
- return; |
- |
- // FIXME: refactor to remove this. |
- if (m_renderLayer.usedTransparency()) |
- return; |
+class TransparencyLayerHelper { |
+public: |
+ TransparencyLayerHelper(GraphicsContext* context, RenderLayer& renderLayer, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior) |
+ : m_transparencyLayerInProgress(false) |
+ , m_context(context) |
+ { |
+ // Blending operations must be performed only with the nearest ancestor stacking context. |
+ // Note that there is no need to create a transparency layer if we're painting the root. |
+ // FIXME: this should be unified further into RenderLayer::paintsWithTransparency(). |
+ bool shouldUseTransparencyLayerForBlendMode = !renderLayer.renderer()->isDocumentElement() && renderLayer.stackingNode()->isStackingContext() && renderLayer.hasNonIsolatedDescendantWithBlendMode(); |
+ if (!shouldUseTransparencyLayerForBlendMode && !renderLayer.paintsWithTransparency(paintBehavior)) |
+ return; |
- m_renderLayer.setUsedTransparency(true); |
- context->save(); |
- LayoutRect clipRect = m_renderLayer.paintingExtent(rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior); |
- context->clip(clipRect); |
+ context->save(); |
+ LayoutRect clipRect = renderLayer.paintingExtent(rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior); |
+ context->clip(clipRect); |
- if (m_renderLayer.renderer()->hasBlendMode()) |
- context->setCompositeOperation(context->compositeOperation(), m_renderLayer.renderer()->style()->blendMode()); |
+ if (renderLayer.renderer()->hasBlendMode()) |
+ context->setCompositeOperation(context->compositeOperation(), renderLayer.renderer()->style()->blendMode()); |
- context->beginTransparencyLayer(m_renderLayer.renderer()->opacity()); |
+ context->beginTransparencyLayer(renderLayer.renderer()->opacity()); |
- if (m_renderLayer.renderer()->hasBlendMode()) |
- context->setCompositeOperation(context->compositeOperation(), WebBlendModeNormal); |
+ if (renderLayer.renderer()->hasBlendMode()) |
+ context->setCompositeOperation(context->compositeOperation(), WebBlendModeNormal); |
#ifdef REVEAL_TRANSPARENCY_LAYERS |
- context->fillRect(clipRect, Color(0.0f, 0.0f, 0.5f, 0.2f)); |
+ context->fillRect(clipRect, Color(0.0f, 0.0f, 0.5f, 0.2f)); |
#endif |
-} |
+ m_transparencyLayerInProgress = true; |
+ } |
+ |
+ ~TransparencyLayerHelper() |
+ { |
+ if (m_transparencyLayerInProgress) { |
+ m_context->endLayer(); |
+ m_context->restore(); |
+ } |
+ } |
+private: |
+ bool m_transparencyLayerInProgress; |
+ GraphicsContext* m_context; |
+}; |
void LayerPainter::paintLayerContentsAndReflection(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) |
{ |
@@ -270,9 +269,10 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint |
LayoutRect rootRelativeBounds; |
bool rootRelativeBoundsComputed = false; |
+ // These helpers output clip and transparency layers using a RAII pattern. Stack-allocated-varibles are destructed in the reverse order of construction, |
+ // so they are nested properly. |
ClipPathHelper clipPathHelper(context, m_renderLayer, paintingInfo, rootRelativeBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags); |
- |
- beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); |
+ TransparencyLayerHelper transparencyLayerHelper(context, m_renderLayer, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); |
LayerPaintingInfo localPaintingInfo(paintingInfo); |
@@ -334,26 +334,17 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint |
if (shouldPaintOverlayScrollbars) |
paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags); |
- } // Filter painter block |
+ } // FilterPainter block |
bool shouldPaintMask = (paintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && m_renderLayer.renderer()->hasMask() && !selectionOnly; |
bool shouldPaintClippingMask = (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && shouldPaintContent && !selectionOnly; |
if (shouldPaintMask) |
paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags); |
- |
if (shouldPaintClippingMask) { |
// Paint the border radius mask for the fragments. |
paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags); |
} |
- |
- // End our transparency layer |
- if (((paintFlags & PaintLayerHaveTransparency) || shouldCreateTransparencyLayerForBlendMode()) && m_renderLayer.usedTransparency() |
- && !(m_renderLayer.reflectionInfo() && m_renderLayer.reflectionInfo()->isPaintingInsideReflection())) { |
- context->endLayer(); |
- context->restore(); |
- m_renderLayer.setUsedTransparency(false); |
- } |
} |
static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer) |