1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "gm.h"
9#include "SkBitmap.h"
10#include "SkShader.h"
11#include "SkXfermode.h"
12
13namespace skiagm {
14
15static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
16    src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
17    src->allocPixels();
18    src->eraseColor(SK_ColorTRANSPARENT);
19
20    SkPaint p;
21    p.setAntiAlias(true);
22
23    SkRect r;
24    SkScalar ww = SkIntToScalar(w);
25    SkScalar hh = SkIntToScalar(h);
26
27    {
28        SkCanvas c(*src);
29        p.setColor(0xFFFFCC44);
30        r.set(0, 0, ww*3/4, hh*3/4);
31        c.drawOval(r, p);
32    }
33
34    dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
35    dst->allocPixels();
36    dst->eraseColor(SK_ColorTRANSPARENT);
37
38    {
39        SkCanvas c(*dst);
40        p.setColor(0xFF66AAFF);
41        r.set(ww/3, hh/3, ww*19/20, hh*19/20);
42        c.drawRect(r, p);
43    }
44}
45
46static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
47
48class XfermodesGM : public GM {
49    SkBitmap    fBG;
50    SkBitmap    fSrcB, fDstB;
51
52    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
53                   SkScalar x, SkScalar y) {
54        SkPaint p;
55
56        canvas->drawBitmap(fSrcB, x, y, &p);
57        p.setAlpha(alpha);
58        p.setXfermode(mode);
59        canvas->drawBitmap(fDstB, x, y, &p);
60    }
61
62    virtual void onOnceBeforeDraw() SK_OVERRIDE {
63        fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
64        fBG.setPixels(gData);
65        fBG.setIsOpaque(true);
66
67        make_bitmaps(W, H, &fSrcB, &fDstB);
68    }
69
70public:
71    const static int W = 64;
72    const static int H = 64;
73    XfermodesGM() {}
74
75protected:
76    virtual SkString onShortName() {
77        return SkString("xfermodes");
78    }
79
80    virtual SkISize onISize() {
81        return make_isize(790, 640);
82    }
83
84    virtual void onDraw(SkCanvas* canvas) {
85        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
86
87        const struct {
88            SkXfermode::Mode  fMode;
89            const char*         fLabel;
90        } gModes[] = {
91            { SkXfermode::kClear_Mode,    "Clear"     },
92            { SkXfermode::kSrc_Mode,      "Src"       },
93            { SkXfermode::kDst_Mode,      "Dst"       },
94            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
95            { SkXfermode::kDstOver_Mode,  "DstOver"   },
96            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
97            { SkXfermode::kDstIn_Mode,    "DstIn"     },
98            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
99            { SkXfermode::kDstOut_Mode,   "DstOut"    },
100            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
101            { SkXfermode::kDstATop_Mode,  "DstATop"   },
102            { SkXfermode::kXor_Mode,      "Xor"       },
103
104            { SkXfermode::kPlus_Mode,         "Plus"          },
105            { SkXfermode::kModulate_Mode,     "Modulate"      },
106            { SkXfermode::kScreen_Mode,       "Screen"        },
107            { SkXfermode::kOverlay_Mode,      "Overlay"       },
108            { SkXfermode::kDarken_Mode,       "Darken"        },
109            { SkXfermode::kLighten_Mode,      "Lighten"       },
110            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
111            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
112            { SkXfermode::kHardLight_Mode,    "HardLight"     },
113            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
114            { SkXfermode::kDifference_Mode,   "Difference"    },
115            { SkXfermode::kExclusion_Mode,    "Exclusion"     },
116            { SkXfermode::kMultiply_Mode,     "Multiply"      },
117            { SkXfermode::kHue_Mode,          "Hue"           },
118            { SkXfermode::kSaturation_Mode,   "Saturation"    },
119            { SkXfermode::kColor_Mode,        "Color"         },
120            { SkXfermode::kLuminosity_Mode,   "Luminosity"    },
121        };
122
123        const SkScalar w = SkIntToScalar(W);
124        const SkScalar h = SkIntToScalar(H);
125        SkShader* s = SkShader::CreateBitmapShader(fBG,
126                                                   SkShader::kRepeat_TileMode,
127                                                   SkShader::kRepeat_TileMode);
128        SkMatrix m;
129        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
130        s->setLocalMatrix(m);
131
132        SkPaint labelP;
133        labelP.setAntiAlias(true);
134        labelP.setTextAlign(SkPaint::kCenter_Align);
135
136        const int W = 5;
137
138        SkScalar x0 = 0;
139        for (int twice = 0; twice < 2; twice++) {
140            SkScalar x = x0, y = 0;
141            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
142                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
143                SkAutoUnref aur(mode);
144                SkRect r;
145                r.set(x, y, x+w, y+h);
146
147                SkPaint p;
148                p.setStyle(SkPaint::kFill_Style);
149                p.setShader(s);
150                canvas->drawRect(r, p);
151
152                canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
153                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
154                canvas->restore();
155
156                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
157                p.setStyle(SkPaint::kStroke_Style);
158                p.setShader(NULL);
159                canvas->drawRect(r, p);
160
161#if 1
162                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
163                                 x + w/2, y - labelP.getTextSize()/2, labelP);
164#endif
165                x += w + SkIntToScalar(10);
166                if ((i % W) == W - 1) {
167                    x = x0;
168                    y += h + SkIntToScalar(30);
169                }
170            }
171            x0 += SkIntToScalar(400);
172        }
173        s->unref();
174    }
175
176private:
177    typedef GM INHERITED;
178};
179
180//////////////////////////////////////////////////////////////////////////////
181
182static GM* MyFactory(void*) { return new XfermodesGM; }
183static GMRegistry reg(MyFactory);
184
185}
186