Index: src/core/SkCanvas.cpp |
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp |
index fbf6c9e83b904acc7df0b08a8b245097d768002d..95f9560f1fe2004db03ee12aa65017f94f830310 100644 |
--- a/src/core/SkCanvas.cpp |
+++ b/src/core/SkCanvas.cpp |
@@ -8,6 +8,7 @@ |
#include "SkCanvas.h" |
#include "SkCanvasPriv.h" |
#include "SkBitmapDevice.h" |
+#include "SkColorFilter.h" |
#include "SkDeviceImageFilterProxy.h" |
#include "SkDraw.h" |
#include "SkDrawable.h" |
@@ -299,6 +300,41 @@ private: |
///////////////////////////////////////////////////////////////////////////// |
+static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) { |
+ return lazy->isValid() ? lazy->get() : lazy->set(orig); |
+} |
+ |
+/** |
+ * If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that |
+ * colorfilter, else return NULL. |
+ */ |
+static SkColorFilter* image_to_color_filter(const SkPaint& paint) { |
+#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_TO_COLORFILTER |
+ return NULL; |
+#else |
+ SkImageFilter* imgf = paint.getImageFilter(); |
+ if (!imgf) { |
+ return NULL; |
+ } |
+ |
+ SkColorFilter* imgCF; |
+ if (!imgf->asAColorFilter(&imgCF)) { |
+ return NULL; |
+ } |
+ |
+ SkColorFilter* paintCF = paint.getColorFilter(); |
+ if (NULL == paintCF) { |
+ // there is no existing paint colorfilter, so we can just return the imagefilter's |
+ return imgCF; |
+ } |
+ |
+ // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF) |
+ // and we need to combine them into a single colorfilter. |
+ SkAutoTUnref<SkColorFilter> autoImgCF(imgCF); |
+ return SkColorFilter::CreateComposeFilter(imgCF, paintCF); |
+#endif |
+} |
+ |
class AutoDrawLooper { |
public: |
AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, |
@@ -311,7 +347,15 @@ public: |
fTempLayerForImageFilter = false; |
fDone = false; |
- if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { |
+ SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint); |
+ if (simplifiedCF) { |
+ SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint); |
+ paint->setColorFilter(simplifiedCF)->unref(); |
+ paint->setImageFilter(NULL); |
+ fPaint = paint; |
+ } |
+ |
+ if (!skipLayerForImageFilter && fPaint->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 |
@@ -328,8 +372,8 @@ public: |
* draw onto the previous layer using the xfermode from the original paint. |
*/ |
SkPaint tmp; |
- tmp.setImageFilter(fOrigPaint.getImageFilter()); |
- tmp.setXfermode(fOrigPaint.getXfermode()); |
+ tmp.setImageFilter(fPaint->getImageFilter()); |
+ tmp.setXfermode(fPaint->getXfermode()); |
(void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, |
SkCanvas::kFullLayer_SaveLayerStrategy); |
fTempLayerForImageFilter = true; |
@@ -350,7 +394,7 @@ public: |
uint32_t oldFlags = paint.getFlags(); |
fNewPaintFlags = filter_paint_flags(props, oldFlags); |
if (fIsSimple && (fNewPaintFlags != oldFlags)) { |
- SkPaint* paint = fLazyPaint.set(fOrigPaint); |
+ SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint); |
paint->setFlags(fNewPaintFlags); |
fPaint = paint; |
// if we're not simple, doNext() will take care of calling setFlags() |
@@ -381,7 +425,8 @@ public: |
} |
private: |
- SkLazyPaint fLazyPaint; |
+ SkLazyPaint fLazyPaintInit; // base paint storage in case we need to modify it |
+ SkLazyPaint fLazyPaintPerLooper; // per-draw-looper storage, so the looper can modify it |
SkCanvas* fCanvas; |
const SkPaint& fOrigPaint; |
SkDrawFilter* fFilter; |
@@ -402,7 +447,8 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { |
SkASSERT(!fIsSimple); |
SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter); |
- SkPaint* paint = fLazyPaint.set(fOrigPaint); |
+ SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ? |
+ *fLazyPaintInit.get() : fOrigPaint); |
paint->setFlags(fNewPaintFlags); |
if (fTempLayerForImageFilter) { |