Chromium Code Reviews| Index: src/core/SkCanvas.cpp |
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp |
| index 68ced602f62da23dc3094de28326797c5502652b..0bd9eb357944bf4de88f101f68382cbf68ecab07 100644 |
| --- a/src/core/SkCanvas.cpp |
| +++ b/src/core/SkCanvas.cpp |
| @@ -308,17 +308,32 @@ public: |
| fFilter = canvas->getDrawFilter(); |
| fPaint = &fOrigPaint; |
| fSaveCount = canvas->getSaveCount(); |
| - fDoClearImageFilter = false; |
| + fTempLayerForImageFilter = false; |
| fDone = false; |
| if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { |
| + /** |
| + * We implement ImageFilters for a given draw by creating a layer, then applying the |
| + * imagefilter to the pixels of that layer (its backing surface/image), and then |
| + * we call restore() to xfer that layer to the main canvas. |
| + * |
| + * 1. SaveLayer (with a paint containing the current imagefilter and xfermode) |
| + * 2. Generate the src pixels: |
| + * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper) |
| + * return (fPaint). We then draw the primitive (using srcover) into a cleared |
|
Stephen White
2015/04/20 14:55:45
Out of curiosity, would it be equivalent to use Sr
|
| + * buffer/surface. |
| + * 3. Restore the layer created in #1 |
| + * The imagefilter is passed the buffer/surface from the layer (now filled with the |
| + * src pixels of the primitive). It returns a new "filtered" buffer, which we |
| + * draw onto the previous layer using the xfermode from the original paint. |
| + */ |
| SkPaint tmp; |
| tmp.setImageFilter(fOrigPaint.getImageFilter()); |
| + tmp.setXfermode(fOrigPaint.getXfermode()); |
| (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, |
| SkCanvas::kFullLayer_SaveLayerStrategy); |
| - // we'll clear the imageFilter for the actual draws in next(), so |
| - // it will only be applied during the restore(). |
| - fDoClearImageFilter = true; |
| + fTempLayerForImageFilter = true; |
| + // we remove the imagefilter/xfermode inside doNext() |
| } |
| if (SkDrawLooper* looper = paint.getLooper()) { |
| @@ -329,7 +344,7 @@ public: |
| } else { |
| fLooperContext = NULL; |
| // can we be marked as simple? |
| - fIsSimple = !fFilter && !fDoClearImageFilter; |
| + fIsSimple = !fFilter && !fTempLayerForImageFilter; |
| } |
| uint32_t oldFlags = paint.getFlags(); |
| @@ -343,7 +358,7 @@ public: |
| } |
| ~AutoDrawLooper() { |
| - if (fDoClearImageFilter) { |
| + if (fTempLayerForImageFilter) { |
| fCanvas->internalRestore(); |
| } |
| SkASSERT(fCanvas->getSaveCount() == fSaveCount); |
| @@ -373,7 +388,7 @@ private: |
| const SkPaint* fPaint; |
| int fSaveCount; |
| uint32_t fNewPaintFlags; |
| - bool fDoClearImageFilter; |
| + bool fTempLayerForImageFilter; |
| bool fDone; |
| bool fIsSimple; |
| SkDrawLooper::Context* fLooperContext; |
| @@ -385,13 +400,14 @@ private: |
| bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { |
| fPaint = NULL; |
| SkASSERT(!fIsSimple); |
| - SkASSERT(fLooperContext || fFilter || fDoClearImageFilter); |
| + SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter); |
| SkPaint* paint = fLazyPaint.set(fOrigPaint); |
| paint->setFlags(fNewPaintFlags); |
| - if (fDoClearImageFilter) { |
| + if (fTempLayerForImageFilter) { |
| paint->setImageFilter(NULL); |
| + paint->setXfermode(NULL); |
| } |
| if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { |