11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
8e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "gm.h"
9e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "SkBitmap.h"
10e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "SkShader.h"
11e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "SkXfermode.h"
12e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
13e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reednamespace skiagm {
14e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
1535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
16e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
17e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    src->allocPixels();
18e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    src->eraseColor(0);
19e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
20e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkCanvas c(*src);
21e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkPaint p;
22e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkRect r;
23e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkScalar ww = SkIntToScalar(w);
24e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkScalar hh = SkIntToScalar(h);
25e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
26e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    p.setAntiAlias(true);
2735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    p.setColor(0xFFFFCC44);
28e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    r.set(0, 0, ww*3/4, hh*3/4);
29e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    c.drawOval(r, p);
3035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
31e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
32e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    dst->allocPixels();
33e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    dst->eraseColor(0);
34e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    c.setBitmapDevice(*dst);
35e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
36e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    p.setColor(0xFF66AAFF);
37e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    r.set(ww/3, hh/3, ww*19/20, hh*19/20);
38e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    c.drawRect(r, p);
39e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
40e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
41e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedclass XfermodesGM : public GM {
42e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkBitmap    fBG;
43e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkBitmap    fSrcB, fDstB;
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool        fOnce;
45e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
4640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
4740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                   SkScalar x, SkScalar y) {
48e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        SkPaint p;
4935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
5035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        canvas->drawBitmap(fSrcB, x, y, &p);
51e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        p.setAlpha(alpha);
52e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        p.setXfermode(mode);
5340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        canvas->drawBitmap(fDstB, x, y, &p);
54e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
5535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    void init() {
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (!fOnce) {
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // Do all this work in a temporary so we get a deep copy
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            uint16_t localData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkBitmap scratchBitmap;
611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            scratchBitmap.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            scratchBitmap.setPixels(localData);
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            scratchBitmap.setIsOpaque(true);
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            scratchBitmap.copyTo(&fBG, SkBitmap::kARGB_4444_Config);
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            make_bitmaps(W, H, &fSrcB, &fDstB);
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            fOnce = true;
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
71e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedpublic:
7240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    const static int W = 64;
7340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    const static int H = 64;
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    XfermodesGM() : fOnce(false) {}
7535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
76e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedprotected:
77e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    virtual SkString onShortName() {
78e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        return SkString("xfermodes");
79e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
80e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
8135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    virtual SkISize onISize() {
8240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return make_isize(790, 640);
83e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
84e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
85e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    virtual void onDraw(SkCanvas* canvas) {
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        this->init();
8735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
8935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
90e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        const struct {
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkXfermode::Mode  fMode;
92e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            const char*         fLabel;
93e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        } gModes[] = {
94e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kClear_Mode,    "Clear"     },
95e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kSrc_Mode,      "Src"       },
96e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kDst_Mode,      "Dst"       },
97e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
98e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kDstOver_Mode,  "DstOver"   },
99e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
100e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kDstIn_Mode,    "DstIn"     },
101e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
102e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kDstOut_Mode,   "DstOut"    },
103e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
104e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kDstATop_Mode,  "DstATop"   },
105e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kXor_Mode,      "Xor"       },
10635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
107e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kPlus_Mode,         "Plus"          },
108e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kMultiply_Mode,     "Multiply"      },
109e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kScreen_Mode,       "Screen"        },
110e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kOverlay_Mode,      "Overlay"       },
111e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kDarken_Mode,       "Darken"        },
112e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kLighten_Mode,      "Lighten"       },
113e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
114e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
115e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kHardLight_Mode,    "HardLight"     },
116e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
117e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kDifference_Mode,   "Difference"    },
118e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            { SkXfermode::kExclusion_Mode,    "Exclusion"     },
119e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        };
12035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        const SkScalar w = SkIntToScalar(W);
12240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        const SkScalar h = SkIntToScalar(H);
123e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        SkShader* s = SkShader::CreateBitmapShader(fBG,
124e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                                                   SkShader::kRepeat_TileMode,
125e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                                                   SkShader::kRepeat_TileMode);
126e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        SkMatrix m;
127e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
128e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        s->setLocalMatrix(m);
12935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
130e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        SkPaint labelP;
131e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        labelP.setAntiAlias(true);
132e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        labelP.setTextAlign(SkPaint::kCenter_Align);
13335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
134e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        const int W = 5;
13535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
136e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        SkScalar x0 = 0;
137e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        for (int twice = 0; twice < 2; twice++) {
138e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            SkScalar x = x0, y = 0;
139e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
140e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkAutoUnref aur(mode);
142e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                SkRect r;
143e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                r.set(x, y, x+w, y+h);
14435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPaint p;
146e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                p.setStyle(SkPaint::kFill_Style);
147e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                p.setShader(s);
148e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                canvas->drawRect(r, p);
14935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                canvas->restore();
15335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
15540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                p.setStyle(SkPaint::kStroke_Style);
15640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                p.setShader(NULL);
15740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                canvas->drawRect(r, p);
15835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#if 1
160e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
161e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                                 x + w/2, y - labelP.getTextSize()/2, labelP);
16240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
163e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                x += w + SkIntToScalar(10);
164e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                if ((i % W) == W - 1) {
165e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                    x = x0;
166e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                    y += h + SkIntToScalar(30);
167e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                }
168e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            }
169e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            x0 += SkIntToScalar(400);
170e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        }
171e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        s->unref();
172e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
173e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
174e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedprivate:
175e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    typedef GM INHERITED;
176e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed};
177e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
178e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed//////////////////////////////////////////////////////////////////////////////
179e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
180e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedstatic GM* MyFactory(void*) { return new XfermodesGM; }
181e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedstatic GMRegistry reg(MyFactory);
182e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
183e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
184