Index: src/core/SkRecordDraw.cpp |
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp |
index ac1e429f1227a575e27cb0342171842ac46a41b7..e1975e1fe3649e2fb372c8804251017ddd20f7c6 100644 |
--- a/src/core/SkRecordDraw.cpp |
+++ b/src/core/SkRecordDraw.cpp |
@@ -229,8 +229,43 @@ private: |
} |
static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { |
- // FIXME: this is very conservative |
- return paint && (paint->getImageFilter() || paint->getColorFilter()); |
+ if (paint) { |
+ // FIXME: this is very conservative |
+ if (paint->getImageFilter() || paint->getColorFilter()) { |
+ return true; |
+ } |
+ |
+ // 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 |
+ // https://crbug.com/401593 |
+ SkXfermode* xfermode = paint->getXfermode(); |
+ SkXfermode::Mode mode; |
+ // SrcOver is ok, and is also 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) { |
+ // For each of the following transfer modes, if the source |
+ // alpha is zero (our transparent black), the resulting |
+ // blended alpha is not necessarily equal to the original |
+ // destination alpha. |
+ 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: |
+ return true; |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ } |
+ return false; |
} |
Bounds popSaveBlock() { |