Add a factory Create function for SkColorFilterImageFilter, and move the matrix optimization there.  This will allow the Chrome compositor to extract the optimized matrix, and potentially apply the color matrix itself, saving a buffer allocation & draw.

Review URL: https://codereview.appspot.com/6739057

git-svn-id: http://skia.googlecode.com/svn/trunk@6152 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/colorfilterimagefilter.cpp b/gm/colorfilterimagefilter.cpp
index 556e88a..60148b3 100644
--- a/gm/colorfilterimagefilter.cpp
+++ b/gm/colorfilterimagefilter.cpp
@@ -29,7 +29,7 @@
                             0, 0, 1, 0, amount255,
                             0, 0, 0, 1, 0 };
     SkAutoTUnref<SkColorFilter> filter(new SkColorMatrixFilter(matrix));
-    return new SkColorFilterImageFilter(filter, input);
+    return SkColorFilterImageFilter::Create(filter, input);
 }
 
 static SkImageFilter* make_grayscale(SkImageFilter* input = NULL) {
@@ -40,13 +40,13 @@
     matrix[2] = matrix[7] = matrix[12] = SkFloatToScalar(0.0722f);
     matrix[18] = SkFloatToScalar(1.0f);
     SkAutoTUnref<SkColorFilter> filter(new SkColorMatrixFilter(matrix));
-    return new SkColorFilterImageFilter(filter, input);
+    return SkColorFilterImageFilter::Create(filter, input);
 }
 
 static SkImageFilter* make_mode_blue(SkImageFilter* input = NULL) {
     SkAutoTUnref<SkColorFilter> filter(
         SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode));
-    return new SkColorFilterImageFilter(filter, input);
+    return SkColorFilterImageFilter::Create(filter, input);
 }
 
 class ColorFilterImageFilterGM : public skiagm::GM {
diff --git a/gm/imagefiltersbase.cpp b/gm/imagefiltersbase.cpp
index bcceb58..7f8aeaf 100644
--- a/gm/imagefiltersbase.cpp
+++ b/gm/imagefiltersbase.cpp
@@ -176,12 +176,10 @@
         SkColorFilter* cf = SkColorFilter::CreateModeFilter(SK_ColorRED,
                                                      SkXfermode::kSrcIn_Mode);
         SkImageFilter* filters[] = {
-#if 1
             NULL,
             new IdentityImageFilter,
             new FailImageFilter,
-            new SkColorFilterImageFilter(cf),
-#endif
+            SkColorFilterImageFilter::Create(cf),
             new SkBlurImageFilter(12.0f, 0.0f),
         };
         cf->unref();
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index a85aa6d..e61c85f 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -56,7 +56,7 @@
                                                          SkXfermode::kSrcIn_Mode));
             SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter(4.0f, 4.0f, bitmapSource));
             SkAutoTUnref<SkImageFilter> erode(new SkErodeImageFilter(4, 4, blur));
-            SkAutoTUnref<SkImageFilter> color(new SkColorFilterImageFilter(cf, erode));
+            SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
             SkAutoTUnref<SkImageFilter> merge(new SkMergeImageFilter(blur, color));
 
             SkPaint paint;
@@ -72,7 +72,7 @@
                                     0, 0, 0, SkFloatToScalar(0.5f), 0 };
 
             SkAutoTUnref<SkColorFilter> matrixFilter(new SkColorMatrixFilter(matrix));
-            SkAutoTUnref<SkImageFilter> colorMorph(new SkColorFilterImageFilter(matrixFilter, morph));
+            SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
             SkAutoTUnref<SkImageFilter> blendColor(new SkBlendImageFilter(SkBlendImageFilter::kNormal_Mode, colorMorph));
 
             SkPaint paint;
diff --git a/gm/testimagefilters.cpp b/gm/testimagefilters.cpp
index 39b974b..e046416 100644
--- a/gm/testimagefilters.cpp
+++ b/gm/testimagefilters.cpp
@@ -24,7 +24,7 @@
     SkColorFilter* cf = SkColorFilter::CreateModeFilter(SK_ColorBLUE,
                                                         SkXfermode::kSrcIn_Mode);
     SkAutoUnref aur(cf);
-    return new SkColorFilterImageFilter(cf);
+    return SkColorFilterImageFilter::Create(cf);
 }
 static SkImageFilter* make3() {
     return new SkBlurImageFilter(8, 0);
@@ -56,7 +56,7 @@
     SkColorFilter* cf = SkColorFilter::CreateModeFilter(0x880000FF,
                                                         SkXfermode::kSrcIn_Mode);
     SkAutoUnref aur3(cf);
-    SkImageFilter* blue = new SkColorFilterImageFilter(cf);
+    SkImageFilter* blue = SkColorFilterImageFilter::Create(cf);
     SkAutoUnref aur4(blue);
 
     return new SkMergeImageFilter(compose, blue);
@@ -73,7 +73,7 @@
     SkColorFilter* cf = SkColorFilter::CreateModeFilter(0x880000FF,
                                                         SkXfermode::kSrcIn_Mode);
     SkAutoUnref aur3(cf);
-    SkImageFilter* blue = new SkColorFilterImageFilter(cf);
+    SkImageFilter* blue = SkColorFilterImageFilter::Create(cf);
     SkAutoUnref aur4(blue);
 
     return new SkMergeImageFilter(compose, blue);
diff --git a/include/effects/SkColorFilterImageFilter.h b/include/effects/SkColorFilterImageFilter.h
index e9124f9..bff9293 100755
--- a/include/effects/SkColorFilterImageFilter.h
+++ b/include/effects/SkColorFilterImageFilter.h
@@ -14,7 +14,7 @@
 
 class SK_API SkColorFilterImageFilter : public SkSingleInputImageFilter {
 public:
-    SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input = NULL);
+    static SkColorFilterImageFilter* Create(SkColorFilter* cf, SkImageFilter* input = NULL);
     virtual ~SkColorFilterImageFilter();
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterImageFilter)
@@ -29,6 +29,7 @@
     virtual SkColorFilter* asColorFilter() const SK_OVERRIDE;
 
 private:
+    SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input);
     SkColorFilter*  fColorFilter;
 
     typedef SkSingleInputImageFilter INHERITED;
diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp
index 22b5d12..369f782 100755
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -56,6 +56,24 @@
 
 };
 
+SkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf,
+        SkImageFilter* input) {
+    SkASSERT(cf);
+    SkScalar colorMatrix[20], inputMatrix[20];
+    SkColorFilter* inputColorFilter;
+    if (input && cf->asColorMatrix(colorMatrix)
+              && (inputColorFilter = input->asColorFilter())
+              && inputColorFilter->asColorMatrix(inputMatrix)
+              && !matrix_needs_clamping(inputMatrix)) {
+        SkScalar combinedMatrix[20];
+        mult_color_matrix(inputMatrix, colorMatrix, combinedMatrix);
+        SkAutoTUnref<SkColorFilter> newCF(SkNEW_ARGS(SkColorMatrixFilter, (combinedMatrix)));
+        return SkNEW_ARGS(SkColorFilterImageFilter, (newCF, input->getInput(0)));
+    } else {
+        return SkNEW_ARGS(SkColorFilterImageFilter, (cf, input));
+    }
+}
+
 SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input) : INHERITED(input), fColorFilter(cf) {
     SkASSERT(cf);
     SkSafeRef(cf);
@@ -79,37 +97,13 @@
                                              const SkMatrix& matrix,
                                              SkBitmap* result,
                                              SkIPoint* loc) {
-    SkImageFilter* parent = getInput(0);
-    SkScalar colorMatrix[20];
-    SkBitmap src;
-    SkColorFilter* cf;
-    if (parent && fColorFilter->asColorMatrix(colorMatrix)) {
-        SkColorFilter* parentColorFilter;
-        SkScalar parentMatrix[20];
-        while (parent && (parentColorFilter = parent->asColorFilter())
-                      && parentColorFilter->asColorMatrix(parentMatrix)
-                      && !matrix_needs_clamping(parentMatrix)) {
-            SkScalar combinedMatrix[20];
-            mult_color_matrix(parentMatrix, colorMatrix, combinedMatrix);
-            memcpy(colorMatrix, combinedMatrix, 20 * sizeof(SkScalar));
-            parent = parent->getInput(0);
-        }
-        if (!parent || !parent->filterImage(proxy, source, matrix, &src, loc)) {
-            src = source;
-        }
-        cf = SkNEW_ARGS(SkColorMatrixFilter, (colorMatrix));
-    } else {
-        src = this->getInputResult(proxy, source, matrix, loc);
-        cf = fColorFilter;
-        cf->ref();
-    }
-
+    SkBitmap src = this->getInputResult(proxy, source, matrix, loc);
     SkAutoTUnref<SkDevice> device(proxy->createDevice(src.width(), src.height()));
     SkCanvas canvas(device.get());
     SkPaint paint;
 
     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-    paint.setColorFilter(cf)->unref();
+    paint.setColorFilter(fColorFilter);
     canvas.drawSprite(src, 0, 0, &paint);
 
     *result = device.get()->accessBitmap(false);