1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9#include "SkBitmapProcShader.h"
10#include "SkColorFilter.h"
11#include "SkGradientShader.h"
12
13#define WIDTH 512
14#define HEIGHT 1024
15
16namespace skiagm {
17
18// Using gradients because GPU doesn't currently have an implementation of SkColorShader (duh!)
19static SkShader* make_color_shader(SkColor color) {
20    static const SkPoint kPts[] = {{0, 0}, {1, 1}};
21    SkColor colors[] = {color, color};
22
23    return SkGradientShader::CreateLinear(kPts, colors, NULL, 2, SkShader::kClamp_TileMode);
24}
25
26static SkShader* make_solid_shader() {
27    return make_color_shader(SkColorSetARGB(0xFF, 0x40, 0x80, 0x20));
28}
29
30static SkShader* make_transparent_shader() {
31    return make_color_shader(SkColorSetARGB(0x80, 0x10, 0x70, 0x20));
32}
33
34static SkShader* make_trans_black_shader() {
35    return make_color_shader(0x0);
36}
37
38// draws a background behind each test rect to see transparency
39static SkShader* make_bg_shader(int checkSize) {
40    SkBitmap bmp;
41    bmp.allocN32Pixels(2 * checkSize, 2 * checkSize);
42    SkCanvas canvas(bmp);
43    canvas.clear(0xFF800000);
44    SkPaint paint;
45    paint.setColor(0xFF000080);
46    SkRect rect0 = SkRect::MakeXYWH(0, 0,
47                                    SkIntToScalar(checkSize), SkIntToScalar(checkSize));
48    SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(checkSize), SkIntToScalar(checkSize),
49                                    SkIntToScalar(checkSize), SkIntToScalar(checkSize));
50    canvas.drawRect(rect1, paint);
51    canvas.drawRect(rect0, paint);
52    return SkNEW_ARGS(SkBitmapProcShader, (bmp, SkShader::kRepeat_TileMode,
53                                                SkShader::kRepeat_TileMode));
54}
55
56class ModeColorFilterGM : public GM {
57public:
58    ModeColorFilterGM() {
59        this->setBGColor(0xFF303030);
60    }
61
62protected:
63    virtual SkString onShortName() {
64        return SkString("modecolorfilters");
65    }
66
67    virtual SkISize onISize() {
68        return SkISize::Make(WIDTH, HEIGHT);
69    }
70
71    virtual void onDraw(SkCanvas* canvas) {
72        // size of rect for each test case
73        static const int kRectWidth  = 20;
74        static const int kRectHeight = 20;
75
76        static const int kCheckSize  = 10;
77
78        if (!fBmpShader) {
79            fBmpShader.reset(make_bg_shader(kCheckSize));
80        }
81        SkPaint bgPaint;
82        bgPaint.setShader(fBmpShader);
83        bgPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
84
85        SkShader* shaders[] = {
86            NULL,                                   // use a paint color instead of a shader
87            make_solid_shader(),
88            make_transparent_shader(),
89            make_trans_black_shader(),
90        };
91
92        // used without shader
93        SkColor colors[] = {
94            SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF),
95            SkColorSetARGB(0xFF, 0x00, 0x00, 0x00),
96            SkColorSetARGB(0x00, 0x00, 0x00, 0x00),
97            SkColorSetARGB(0xFF, 0x10, 0x20, 0x40),
98            SkColorSetARGB(0xA0, 0x20, 0x30, 0x90),
99        };
100
101        // used with shaders
102        SkColor alphas[] = {0xFFFFFFFF, 0x80808080};
103
104        SkXfermode::Mode modes[]  = { // currently just doing the Modes expressible as Coeffs
105            SkXfermode::kClear_Mode,
106            SkXfermode::kSrc_Mode,
107            SkXfermode::kDst_Mode,
108            SkXfermode::kSrcOver_Mode,
109            SkXfermode::kDstOver_Mode,
110            SkXfermode::kSrcIn_Mode,
111            SkXfermode::kDstIn_Mode,
112            SkXfermode::kSrcOut_Mode,
113            SkXfermode::kDstOut_Mode,
114            SkXfermode::kSrcATop_Mode,
115            SkXfermode::kDstATop_Mode,
116            SkXfermode::kXor_Mode,
117            SkXfermode::kPlus_Mode,
118            SkXfermode::kModulate_Mode,
119        };
120
121        SkPaint paint;
122        int idx = 0;
123        static const int kRectsPerRow = SkMax32(this->getISize().fWidth / kRectWidth, 1);
124        for (size_t cfm = 0; cfm < SK_ARRAY_COUNT(modes); ++cfm) {
125            for (size_t cfc = 0; cfc < SK_ARRAY_COUNT(colors); ++cfc) {
126                SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(colors[cfc],
127                                                                               modes[cfm]));
128                paint.setColorFilter(cf);
129                for (size_t s = 0; s < SK_ARRAY_COUNT(shaders); ++s) {
130                    paint.setShader(shaders[s]);
131                    bool hasShader = NULL == paint.getShader();
132                    int paintColorCnt = hasShader ? SK_ARRAY_COUNT(alphas) : SK_ARRAY_COUNT(colors);
133                    SkColor* paintColors = hasShader ? alphas : colors;
134                    for (int pc = 0; pc < paintColorCnt; ++pc) {
135                        paint.setColor(paintColors[pc]);
136                        SkScalar x = SkIntToScalar(idx % kRectsPerRow);
137                        SkScalar y = SkIntToScalar(idx / kRectsPerRow);
138                        SkRect rect = SkRect::MakeXYWH(x * kRectWidth, y * kRectHeight,
139                                                       SkIntToScalar(kRectWidth),
140                                                       SkIntToScalar(kRectHeight));
141                        canvas->saveLayer(&rect, NULL);
142                        canvas->drawRect(rect, bgPaint);
143                        canvas->drawRect(rect, paint);
144                        canvas->restore();
145                        ++idx;
146                    }
147                }
148            }
149        }
150
151        for (size_t i = 0; i < SK_ARRAY_COUNT(shaders); ++i) {
152            SkSafeUnref(shaders[i]);
153        }
154    }
155
156private:
157    SkAutoTUnref<SkShader> fBmpShader;
158    typedef GM INHERITED;
159};
160
161//////////////////////////////////////////////////////////////////////////////
162
163static GM* MyFactory(void*) { return new ModeColorFilterGM; }
164static GMRegistry reg(MyFactory);
165
166}
167