Index: src/core/SkBBoxHierarchyRecord.cpp |
diff --git a/src/core/SkBBoxHierarchyRecord.cpp b/src/core/SkBBoxHierarchyRecord.cpp |
index 4712abb2b260369233afa1a39c99ade2dfea6c39..a9cd05d85ff1dc3cf1028ac29982025e44b50d53 100644 |
--- a/src/core/SkBBoxHierarchyRecord.cpp |
+++ b/src/core/SkBBoxHierarchyRecord.cpp |
@@ -37,15 +37,42 @@ SkCanvas::SaveLayerStrategy SkBBoxHierarchyRecord::willSaveLayer(const SkRect* b |
bool paintAffectsTransparentBlack = paint && |
((paint->getImageFilter()) || |
(paint->getColorFilter())); |
+ bool needToHandleBBox = paintAffectsTransparentBlack; |
+ if (!needToHandleBBox && paint) { |
+ // Unusual Xfermodes require us to process a saved layer |
+ // even with operations outisde the clip. |
+ // For example, DstIn is used by masking layers. |
+ // https://code.google.com/p/skia/issues/detail?id=1291 |
+ SkXfermode* xfermode = paint->getXfermode(); |
+ SkXfermode::Mode mode; |
+ // SrcOver is the common case with a NULL xfermode, so we should |
+ // make that the fast path and bypass the mode extraction and test. |
+ if (xfermode && xfermode->asMode(&mode)) { |
+ switch (mode) { |
+ case SkXfermode::kClear_Mode: |
+ case SkXfermode::kSrc_Mode: |
+ case SkXfermode::kSrcIn_Mode: |
+ case SkXfermode::kDstIn_Mode: |
+ case SkXfermode::kSrcOut_Mode: |
+ case SkXfermode::kDstATop_Mode: |
+ case SkXfermode::kModulate_Mode: |
+ needToHandleBBox = true; |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ } |
+ |
SkRect drawBounds; |
- if (paintAffectsTransparentBlack) { |
+ if (needToHandleBBox) { |
SkIRect deviceBounds; |
this->getClipDeviceBounds(&deviceBounds); |
drawBounds.set(deviceBounds); |
} |
fStateTree->appendSaveLayer(this->writeStream().bytesWritten()); |
SkCanvas::SaveLayerStrategy strategy = this->INHERITED::willSaveLayer(bounds, paint, flags); |
- if (paintAffectsTransparentBlack) { |
+ if (needToHandleBBox) { |
this->handleBBox(drawBounds); |
this->addNoOp(); |
} |