aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-04-20 08:04:21 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-20 08:04:21 -0700
commit5c476fb2776639bdbf0e974dd38d1c5d4c4ff1aa (patch)
treef80d8705adc81c989ae61179f00ebc71f2f73931 /src
parent7e4186accea094276c9f3c65c64e63ffc59aa644 (diff)
apply xfermode after imagefilter when we create a tmp layer
Diffstat (limited to 'src')
-rw-r--r--src/core/SkCanvas.cpp34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 68ced602f6..0bd9eb3579 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
+ * 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)) {