Add a GM that tests xfermode-based color filters.
Review URL: https://codereview.appspot.com/6736052

git-svn-id: http://skia.googlecode.com/svn/trunk@6022 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/modecolorfilters.cpp b/gm/modecolorfilters.cpp
new file mode 100644
index 0000000..40e65fc
--- /dev/null
+++ b/gm/modecolorfilters.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkBitmapProcShader.h"
+#include "SkColorFilter.h"
+#include "SkGradientShader.h"
+
+#define WIDTH 512
+#define HEIGHT 1024
+
+namespace skiagm {
+
+// Using gradients because GPU doesn't currently have an implementation of SkColorShader (duh!)
+static SkShader* make_color_shader(SkColor color) {
+    static const SkPoint kPts[] = {{0, 0}, {1, 1}};
+    SkColor colors[] = {color, color};
+
+    return SkGradientShader::CreateLinear(kPts, colors, NULL, 2, SkShader::kClamp_TileMode);
+}
+
+static SkShader* make_solid_shader() {
+    return make_color_shader(SkColorSetARGB(0xFF, 0x40, 0x80, 0x20));
+}
+
+static SkShader* make_transparent_shader() {
+    return make_color_shader(SkColorSetARGB(0x80, 0x10, 0x70, 0x20));
+}
+
+static SkShader* make_trans_black_shader() {
+    return make_color_shader(0x0);
+}
+
+// draws a background behind each test rect to see transparency
+static SkShader* make_bg_shader(int checkSize) {
+    SkBitmap bmp;
+    bmp.setConfig(SkBitmap::kARGB_8888_Config, 2 * checkSize, 2 * checkSize);
+    bmp.allocPixels();
+    SkCanvas canvas(bmp);
+    canvas.clear(0xFF800000);
+    SkPaint paint;
+    paint.setColor(0xFF000080);
+    SkRect rect0 = SkRect::MakeXYWH(0, 0,
+                                    SkIntToScalar(checkSize), SkIntToScalar(checkSize));
+    SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(checkSize), SkIntToScalar(checkSize),
+                                    SkIntToScalar(checkSize), SkIntToScalar(checkSize));
+    canvas.drawRect(rect1, paint);
+    canvas.drawRect(rect0, paint);
+    return SkNEW_ARGS(SkBitmapProcShader, (bmp, SkShader::kRepeat_TileMode,
+                                                SkShader::kRepeat_TileMode));
+}
+
+class ModeColorFilterGM : public GM {
+public:
+    ModeColorFilterGM() {
+        this->setBGColor(0xFF303030);
+    }
+
+protected:
+    virtual SkString onShortName() {
+        return SkString("modecolorfilters");
+    }
+
+    virtual SkISize onISize() {
+        return make_isize(WIDTH, HEIGHT);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) {
+        // size of rect for each test case
+        static const int kRectWidth  = 20;
+        static const int kRectHeight = 20;        
+
+        static const int kCheckSize  = 10;
+
+        if (!fBmpShader) {
+            fBmpShader.reset(make_bg_shader(kCheckSize));
+        }
+        SkPaint bgPaint;
+        bgPaint.setShader(fBmpShader);
+        bgPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+        SkShader* shaders[] = {
+            NULL,                                   // use a paint color instead of a shader
+            make_solid_shader(),
+            make_transparent_shader(),
+            make_trans_black_shader(),
+        };
+
+        // used without shader
+        SkColor colors[] = {
+            SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF),
+            SkColorSetARGB(0xFF, 0x00, 0x00, 0x00),
+            SkColorSetARGB(0x00, 0x00, 0x00, 0x00),
+            SkColorSetARGB(0xFF, 0x10, 0x20, 0x40),
+            SkColorSetARGB(0xA0, 0x20, 0x30, 0x90),
+        };
+
+        // used with shaders
+        SkColor alphas[] = {0xFFFFFFFF, 0x80808080};
+        
+        SkXfermode::Mode modes[]  = { // currently just doing the Modes expressible as Coeffs
+            SkXfermode::kClear_Mode,
+            SkXfermode::kSrc_Mode,
+            SkXfermode::kDst_Mode,
+            SkXfermode::kSrcOver_Mode,
+            SkXfermode::kDstOver_Mode,
+            SkXfermode::kSrcIn_Mode,
+            SkXfermode::kDstIn_Mode,
+            SkXfermode::kSrcOut_Mode,
+            SkXfermode::kDstOut_Mode,
+            SkXfermode::kSrcATop_Mode,
+            SkXfermode::kDstATop_Mode,
+            SkXfermode::kXor_Mode,
+            SkXfermode::kPlus_Mode,
+            SkXfermode::kMultiply_Mode,
+        };
+
+        SkPaint paint;
+        int idx = 0;
+        static const int kRectsPerRow = SkMax32(this->getISize().fWidth / kRectWidth, 1);
+        for (size_t cfm = 0; cfm < SK_ARRAY_COUNT(modes); ++cfm) {
+            for (int cfc = 0; cfc < SK_ARRAY_COUNT(colors); ++cfc) {
+                SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(colors[cfc],
+                                                                               modes[cfm]));
+                paint.setColorFilter(cf);
+                for (int s = 0; s < SK_ARRAY_COUNT(shaders); ++s) {
+                    paint.setShader(shaders[s]);
+                    bool hasShader = NULL == paint.getShader();
+                    int paintColorCnt = hasShader ? SK_ARRAY_COUNT(alphas) : SK_ARRAY_COUNT(colors);
+                    SkColor* paintColors = hasShader ? alphas : colors;
+                    for (int pc = 0; pc < paintColorCnt; ++pc) {
+                        paint.setColor(paintColors[pc]);
+                        SkScalar x = SkIntToScalar(idx % kRectsPerRow);
+                        SkScalar y = SkIntToScalar(idx / kRectsPerRow);
+                        SkRect rect = SkRect::MakeXYWH(x * kRectWidth, y * kRectHeight,
+                                                       kRectWidth, kRectHeight);
+                        canvas->drawRect(rect, bgPaint);
+                        canvas->drawRect(rect, paint);
+                        ++idx;
+                    }
+                }
+            }
+        }
+
+        for (int i = 0; i < SK_ARRAY_COUNT(shaders); ++i) {
+            SkSafeUnref(shaders[i]);
+        }
+    }
+
+private:
+    SkAutoTUnref<SkShader> fBmpShader;
+    typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new ModeColorFilterGM; }
+static GMRegistry reg(MyFactory);
+
+}