tilemodes.cpp revision 93a1215fe0ab007ce941c721f1fd3e9dcb5d4754
1451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
2451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray/*
3451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray * Copyright 2011 Google Inc.
4451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray *
5451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray * Use of this source code is governed by a BSD-style license that can be
6c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le * found in the LICENSE file.
7c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le */
8451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray#include "gm.h"
9451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray#include "SkPath.h"
10c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le#include "SkRegion.h"
11c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le#include "SkShader.h"
12451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray#include "SkUtils.h"
135555f62fedfdc36cc8c4911eb24299008d961263Arman Uguray#include "SkColorPriv.h"
145555f62fedfdc36cc8c4911eb24299008d961263Arman Uguray#include "SkColorFilter.h"
155555f62fedfdc36cc8c4911eb24299008d961263Arman Uguray#include "SkTypeface.h"
165555f62fedfdc36cc8c4911eb24299008d961263Arman Uguray
175555f62fedfdc36cc8c4911eb24299008d961263Arman Uguray// effects
18e94efecceed2a21d35c7a56b306498b53f0fa68eArman Uguray#include "SkGradientShader.h"
19e94efecceed2a21d35c7a56b306498b53f0fa68eArman Uguray#include "SkBlurDrawLooper.h"
20e94efecceed2a21d35c7a56b306498b53f0fa68eArman Uguray
21e94efecceed2a21d35c7a56b306498b53f0fa68eArman Uguraystatic void makebm(SkBitmap* bm, SkColorType ct, int w, int h) {
22e94efecceed2a21d35c7a56b306498b53f0fa68eArman Uguray    bm->allocPixels(SkImageInfo::Make(w, h, ct, kPremul_SkAlphaType));
235555f62fedfdc36cc8c4911eb24299008d961263Arman Uguray    bm->eraseColor(SK_ColorTRANSPARENT);
24c43ea562a0447330b26eeec3c7b1fb935958e985Prathmesh Prabhu
25c43ea562a0447330b26eeec3c7b1fb935958e985Prathmesh Prabhu    SkCanvas    canvas(*bm);
26a5b80d9fdb4d8a54bad447d9e78a6e0b6d4c2d23Arman Uguray    SkPoint     pts[] = { { 0, 0 }, { SkIntToScalar(w), SkIntToScalar(h)} };
27a5b80d9fdb4d8a54bad447d9e78a6e0b6d4c2d23Arman Uguray    SkColor     colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
28c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le    SkScalar    pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
29c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le    SkPaint     paint;
30c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
31a5b80d9fdb4d8a54bad447d9e78a6e0b6d4c2d23Arman Uguray    paint.setDither(true);
32c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le    paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos,
33c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le                SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode))->unref();
34a5b80d9fdb4d8a54bad447d9e78a6e0b6d4c2d23Arman Uguray    canvas.drawPaint(paint);
35bcbd42836b870f3e84d851eab4bb64c90cdb6afeArman Uguray}
36c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
37c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Lestatic void setup(SkPaint* paint, const SkBitmap& bm, bool filter,
38a5b80d9fdb4d8a54bad447d9e78a6e0b6d4c2d23Arman Uguray                  SkShader::TileMode tmx, SkShader::TileMode tmy) {
39c43ea562a0447330b26eeec3c7b1fb935958e985Prathmesh Prabhu    SkShader* shader = SkShader::CreateBitmapShader(bm, tmx, tmy);
40451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    paint->setShader(shader)->unref();
41451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    paint->setFilterQuality(filter ? kLow_SkFilterQuality : kNone_SkFilterQuality);
42451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray}
433ecbf9e5d6b26e75b59f7f631fae9e6150f6e936Arman Uguray
44c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Lestatic const SkColorType gColorTypes[] = {
45c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le    kN32_SkColorType,
46451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    kRGB_565_SkColorType,
47c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le};
48c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
49451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Ugurayclass TilingGM : public skiagm::GM {
50451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguraypublic:
51c43ea562a0447330b26eeec3c7b1fb935958e985Prathmesh Prabhu    TilingGM(bool powerOfTwoSize)
52451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray            : fPowerOfTwoSize(powerOfTwoSize) {
53451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    }
54451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
55451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    SkBitmap    fTexture[SK_ARRAY_COUNT(gColorTypes)];
56c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
57c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Leprotected:
58451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
59451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    enum {
60c43ea562a0447330b26eeec3c7b1fb935958e985Prathmesh Prabhu        kPOTSize = 32,
61451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        kNPOTSize = 21,
62451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    };
63451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
64451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    SkString onShortName() SK_OVERRIDE {
65451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        SkString name("tilemodes");
66e94efecceed2a21d35c7a56b306498b53f0fa68eArman Uguray        if (!fPowerOfTwoSize) {
67e94efecceed2a21d35c7a56b306498b53f0fa68eArman Uguray            name.append("_npot");
68451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        }
69451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        return name;
70451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    }
71c43ea562a0447330b26eeec3c7b1fb935958e985Prathmesh Prabhu
72451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    SkISize onISize() SK_OVERRIDE { return SkISize::Make(880, 560); }
73451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
74c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le    void onOnceBeforeDraw() SK_OVERRIDE {
75c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le        int size = fPowerOfTwoSize ? kPOTSize : kNPOTSize;
76c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le        for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypes); i++) {
77c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le            makebm(&fTexture[i], gColorTypes[i], size, size);
78c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le        }
79c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le    }
80451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
81451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
82c43ea562a0447330b26eeec3c7b1fb935958e985Prathmesh Prabhu
83451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        int size = fPowerOfTwoSize ? kPOTSize : kNPOTSize;
84c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
8533b35f950ee30c7bd5e969b73d00239aefa7ea63Arman Uguray        SkRect r = { 0, 0, SkIntToScalar(size*2), SkIntToScalar(size*2) };
86c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
8733b35f950ee30c7bd5e969b73d00239aefa7ea63Arman Uguray        static const char* gConfigNames[] = { "8888", "565", "4444" };
8833b35f950ee30c7bd5e969b73d00239aefa7ea63Arman Uguray
8933b35f950ee30c7bd5e969b73d00239aefa7ea63Arman Uguray        static const bool           gFilters[] = { false, true };
9033b35f950ee30c7bd5e969b73d00239aefa7ea63Arman Uguray        static const char*          gFilterNames[] = {     "point",                     "bilinear" };
91451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
92451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        static const SkShader::TileMode gModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode };
93b718932651a1f46e975d3a8aff3fae20c838bcbcArman Uguray        static const char*          gModeNames[] = {    "C",                    "R",                   "M" };
94b718932651a1f46e975d3a8aff3fae20c838bcbcArman Uguray
95b718932651a1f46e975d3a8aff3fae20c838bcbcArman Uguray        SkScalar y = SkIntToScalar(24);
96c45d1da740fbeeacedc7a1e605a3cc6d7505203eArman Uguray        SkScalar x = SkIntToScalar(10);
97c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
98451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
99451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray            for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
100451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray                SkPaint p;
101451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray                SkString str;
102c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le                p.setAntiAlias(true);
103c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le                sk_tool_utils::set_portable_typeface(&p);
104451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray                p.setDither(true);
105451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray                str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]);
106c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le
107451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray                p.setTextAlign(SkPaint::kCenter_Align);
108451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray                canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
109c45d1da740fbeeacedc7a1e605a3cc6d7505203eArman Uguray
110c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le                x += r.width() * 4 / 3;
111c569e99b922542e7ddbbc4cd465fc8328ec16214Thieu Le            }
112451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        }
113451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray
114451ce7ac8f6b7834dd01f94bb7f6ffa889a6da2cArman Uguray        y += SkIntToScalar(16);
115
116        for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypes); i++) {
117            for (size_t j = 0; j < SK_ARRAY_COUNT(gFilters); j++) {
118                x = SkIntToScalar(10);
119                for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
120                    for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
121                        SkPaint paint;
122#if 1 // Temporary change to regen bitmap before each draw. This may help tracking down an issue
123      // on SGX where resizing NPOT textures to POT textures exhibits a driver bug.
124                        if (!fPowerOfTwoSize) {
125                            makebm(&fTexture[i], gColorTypes[i], size, size);
126                        }
127#endif
128                        setup(&paint, fTexture[i], gFilters[j], gModes[kx], gModes[ky]);
129                        paint.setDither(true);
130
131                        canvas->save();
132                        canvas->translate(x, y);
133                        canvas->drawRect(r, paint);
134                        canvas->restore();
135
136                        x += r.width() * 4 / 3;
137                    }
138                }
139                {
140                    SkPaint p;
141                    SkString str;
142                    p.setAntiAlias(true);
143                    sk_tool_utils::set_portable_typeface(&p);
144                    str.printf("%s, %s", gConfigNames[i], gFilterNames[j]);
145                    canvas->drawText(str.c_str(), str.size(), x, y + r.height() * 2 / 3, p);
146                }
147
148                y += r.height() * 4 / 3;
149            }
150        }
151    }
152
153private:
154    bool fPowerOfTwoSize;
155    typedef skiagm::GM INHERITED;
156};
157
158static const int gWidth = 32;
159static const int gHeight = 32;
160
161static SkShader* make_bm(SkShader::TileMode tx, SkShader::TileMode ty) {
162    SkBitmap bm;
163    makebm(&bm, kN32_SkColorType, gWidth, gHeight);
164    return SkShader::CreateBitmapShader(bm, tx, ty);
165}
166
167static SkShader* make_grad(SkShader::TileMode tx, SkShader::TileMode ty) {
168    SkPoint pts[] = { { 0, 0 }, { SkIntToScalar(gWidth), SkIntToScalar(gHeight)} };
169    SkPoint center = { SkIntToScalar(gWidth)/2, SkIntToScalar(gHeight)/2 };
170    SkScalar rad = SkIntToScalar(gWidth)/2;
171    SkColor colors[] = { 0xFFFF0000, 0xFF0044FF };
172
173    int index = (int)ty;
174    switch (index % 3) {
175        case 0:
176            return SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors), tx);
177        case 1:
178            return SkGradientShader::CreateRadial(center, rad, colors, NULL, SK_ARRAY_COUNT(colors), tx);
179        case 2:
180            return SkGradientShader::CreateSweep(center.fX, center.fY, colors, NULL, SK_ARRAY_COUNT(colors));
181    }
182
183    return NULL;
184}
185
186typedef SkShader* (*ShaderProc)(SkShader::TileMode, SkShader::TileMode);
187
188class Tiling2GM : public skiagm::GM {
189    ShaderProc fProc;
190    SkString   fName;
191public:
192    Tiling2GM(ShaderProc proc, const char name[]) : fProc(proc) {
193        fName.printf("tilemode_%s", name);
194    }
195
196protected:
197
198    SkString onShortName() SK_OVERRIDE {
199        return fName;
200    }
201
202    SkISize onISize() SK_OVERRIDE { return SkISize::Make(880, 560); }
203
204    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
205        canvas->scale(SkIntToScalar(3)/2, SkIntToScalar(3)/2);
206
207        const SkScalar w = SkIntToScalar(gWidth);
208        const SkScalar h = SkIntToScalar(gHeight);
209        SkRect r = { -w, -h, w*2, h*2 };
210
211        static const SkShader::TileMode gModes[] = {
212            SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode
213        };
214        static const char* gModeNames[] = {
215            "Clamp", "Repeat", "Mirror"
216        };
217
218        SkScalar y = SkIntToScalar(24);
219        SkScalar x = SkIntToScalar(66);
220
221        SkPaint p;
222        p.setAntiAlias(true);
223        sk_tool_utils::set_portable_typeface(&p);
224        p.setTextAlign(SkPaint::kCenter_Align);
225
226        for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
227            SkString str(gModeNames[kx]);
228            canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
229            x += r.width() * 4 / 3;
230        }
231
232        y += SkIntToScalar(16) + h;
233        p.setTextAlign(SkPaint::kRight_Align);
234
235        for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
236            x = SkIntToScalar(16) + w;
237
238            SkString str(gModeNames[ky]);
239            canvas->drawText(str.c_str(), str.size(), x, y + h/2, p);
240
241            x += SkIntToScalar(50);
242            for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
243                SkPaint paint;
244                paint.setShader(fProc(gModes[kx], gModes[ky]))->unref();
245
246                canvas->save();
247                canvas->translate(x, y);
248                canvas->drawRect(r, paint);
249                canvas->restore();
250
251                x += r.width() * 4 / 3;
252            }
253            y += r.height() * 4 / 3;
254        }
255    }
256
257private:
258    typedef skiagm::GM INHERITED;
259};
260
261//////////////////////////////////////////////////////////////////////////////
262
263DEF_GM( return new TilingGM(true); )
264DEF_GM( return new TilingGM(false); )
265DEF_GM( return new Tiling2GM(make_bm, "bitmap"); )
266DEF_GM( return new Tiling2GM(make_grad, "gradient"); )
267