tilemodes_scaled.cpp revision a90c6803865766d28e92091f56f718f5e41fe80f
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 "SkPath.h"
10#include "SkRegion.h"
11#include "SkShader.h"
12#include "SkUtils.h"
13#include "SkColorPriv.h"
14#include "SkColorFilter.h"
15#include "SkTypeface.h"
16#include "SkBlurMask.h"
17
18// effects
19#include "SkGradientShader.h"
20#include "SkUnitMappers.h"
21#include "SkBlurDrawLooper.h"
22
23static void makebm(SkBitmap* bm, SkColorType ct, int w, int h) {
24    bm->allocPixels(SkImageInfo::Make(w, h, ct, kPremul_SkAlphaType));
25    bm->eraseColor(SK_ColorTRANSPARENT);
26
27    SkCanvas    canvas(*bm);
28    SkPoint     pts[] = { { 0, 0 }, { SkIntToScalar(w), SkIntToScalar(h)} };
29    SkColor     colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
30    SkScalar    pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
31    SkPaint     paint;
32
33    SkUnitMapper*   um = NULL;
34
35    um = new SkCosineMapper;
36//    um = new SkDiscreteMapper(12);
37
38    SkAutoUnref au(um);
39
40    paint.setDither(true);
41    paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos,
42                SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode, um))->unref();
43    canvas.drawPaint(paint);
44}
45
46static void setup(SkPaint* paint, const SkBitmap& bm, SkPaint::FilterLevel filter_level,
47                  SkShader::TileMode tmx, SkShader::TileMode tmy) {
48    SkShader* shader = SkShader::CreateBitmapShader(bm, tmx, tmy);
49    paint->setShader(shader)->unref();
50    paint->setFilterLevel(filter_level);
51}
52
53static const SkColorType gColorTypes[] = {
54    kN32_SkColorType,
55    kRGB_565_SkColorType,
56};
57
58class ScaledTilingGM : public skiagm::GM {
59    SkAutoTUnref<SkBlurDrawLooper> fLooper;
60public:
61    ScaledTilingGM(bool powerOfTwoSize)
62            : fLooper(SkBlurDrawLooper::Create(0x88000000,
63                                               SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(1)),
64                                               SkIntToScalar(2), SkIntToScalar(2)))
65            , fPowerOfTwoSize(powerOfTwoSize) {
66    }
67
68    SkBitmap    fTexture[SK_ARRAY_COUNT(gColorTypes)];
69
70protected:
71    enum {
72        kPOTSize = 4,
73        kNPOTSize = 3,
74    };
75
76    virtual uint32_t onGetFlags() const SK_OVERRIDE {
77        if (!fPowerOfTwoSize) {
78            return kSkipTiled_Flag;  // Only for 565.  8888 is fine.
79        }
80        return 0;
81    }
82
83    SkString onShortName() {
84        SkString name("scaled_tilemodes");
85        if (!fPowerOfTwoSize) {
86            name.append("_npot");
87        }
88        return name;
89    }
90
91    SkISize onISize() { return SkISize::Make(880, 760); }
92
93    virtual void onOnceBeforeDraw() SK_OVERRIDE {
94        int size = fPowerOfTwoSize ? kPOTSize : kNPOTSize;
95        for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypes); i++) {
96            makebm(&fTexture[i], gColorTypes[i], size, size);
97        }
98    }
99
100    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
101
102        float scale = 32.f/kPOTSize;
103
104        int size = fPowerOfTwoSize ? kPOTSize : kNPOTSize;
105
106        SkRect r = { 0, 0, SkIntToScalar(size*2), SkIntToScalar(size*2) };
107
108        static const char* gColorTypeNames[] = { "8888" , "565", "4444" };
109
110        static const SkPaint::FilterLevel           gFilterLevels[] =
111            { SkPaint::kNone_FilterLevel,
112              SkPaint::kLow_FilterLevel,
113              SkPaint::kMedium_FilterLevel,
114              SkPaint::kHigh_FilterLevel };
115        static const char*          gFilterNames[] = { "None", "Low", "Medium", "High" };
116
117        static const SkShader::TileMode gModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode };
118        static const char*          gModeNames[] = {    "C",                    "R",                   "M" };
119
120        SkScalar y = SkIntToScalar(24);
121        SkScalar x = SkIntToScalar(10)/scale;
122
123        for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
124            for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
125                SkPaint p;
126                SkString str;
127                p.setAntiAlias(true);
128                p.setDither(true);
129                p.setLooper(fLooper);
130                str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]);
131
132                p.setTextAlign(SkPaint::kCenter_Align);
133                canvas->drawText(str.c_str(), str.size(), scale*(x + r.width()/2), y, p);
134
135                x += r.width() * 4 / 3;
136            }
137        }
138
139        y = SkIntToScalar(40) / scale;
140
141        for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypes); i++) {
142            for (size_t j = 0; j < SK_ARRAY_COUNT(gFilterLevels); j++) {
143                x = SkIntToScalar(10)/scale;
144                for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
145                    for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
146                        SkPaint paint;
147#if 1 // Temporary change to regen bitmap before each draw. This may help tracking down an issue
148      // on SGX where resizing NPOT textures to POT textures exhibits a driver bug.
149                        if (!fPowerOfTwoSize) {
150                            makebm(&fTexture[i], gColorTypes[i], size, size);
151                        }
152#endif
153                        setup(&paint, fTexture[i], gFilterLevels[j], gModes[kx], gModes[ky]);
154                        paint.setDither(true);
155
156                        canvas->save();
157                        canvas->scale(scale,scale);
158                        canvas->translate(x, y);
159                        canvas->drawRect(r, paint);
160                        canvas->restore();
161
162                        x += r.width() * 4 / 3;
163                    }
164                }
165                {
166                    SkPaint p;
167                    SkString str;
168                    p.setAntiAlias(true);
169                    p.setLooper(fLooper);
170                    str.printf("%s, %s", gColorTypeNames[i], gFilterNames[j]);
171                    canvas->drawText(str.c_str(), str.size(), scale*x, scale*(y + r.height() * 2 / 3), p);
172                }
173
174                y += r.height() * 4 / 3;
175            }
176        }
177    }
178
179private:
180    bool fPowerOfTwoSize;
181    typedef skiagm::GM INHERITED;
182};
183
184static const int gWidth = 32;
185static const int gHeight = 32;
186
187static SkShader* make_bm(SkShader::TileMode tx, SkShader::TileMode ty) {
188    SkBitmap bm;
189    makebm(&bm, kN32_SkColorType, gWidth, gHeight);
190    return SkShader::CreateBitmapShader(bm, tx, ty);
191}
192
193static SkShader* make_grad(SkShader::TileMode tx, SkShader::TileMode ty) {
194    SkPoint pts[] = { { 0, 0 }, { SkIntToScalar(gWidth), SkIntToScalar(gHeight)} };
195    SkPoint center = { SkIntToScalar(gWidth)/2, SkIntToScalar(gHeight)/2 };
196    SkScalar rad = SkIntToScalar(gWidth)/2;
197    SkColor colors[] = { 0xFFFF0000, 0xFF0044FF };
198
199    int index = (int)ty;
200    switch (index % 3) {
201        case 0:
202            return SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors), tx);
203        case 1:
204            return SkGradientShader::CreateRadial(center, rad, colors, NULL, SK_ARRAY_COUNT(colors), tx);
205        case 2:
206            return SkGradientShader::CreateSweep(center.fX, center.fY, colors, NULL, SK_ARRAY_COUNT(colors));
207    }
208
209    return NULL;
210}
211
212typedef SkShader* (*ShaderProc)(SkShader::TileMode, SkShader::TileMode);
213
214class ScaledTiling2GM : public skiagm::GM {
215    ShaderProc fProc;
216    SkString   fName;
217public:
218    ScaledTiling2GM(ShaderProc proc, const char name[]) : fProc(proc) {
219        fName.printf("scaled_tilemode_%s", name);
220    }
221
222protected:
223    virtual uint32_t onGetFlags() const SK_OVERRIDE {
224        return kSkipTiled_Flag;
225    }
226
227    SkString onShortName() {
228        return fName;
229    }
230
231    SkISize onISize() { return SkISize::Make(880, 560); }
232
233    virtual void onDraw(SkCanvas* canvas) {
234        canvas->scale(SkIntToScalar(3)/2, SkIntToScalar(3)/2);
235
236        const SkScalar w = SkIntToScalar(gWidth);
237        const SkScalar h = SkIntToScalar(gHeight);
238        SkRect r = { -w, -h, w*2, h*2 };
239
240        static const SkShader::TileMode gModes[] = {
241            SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode
242        };
243        static const char* gModeNames[] = {
244            "Clamp", "Repeat", "Mirror"
245        };
246
247        SkScalar y = SkIntToScalar(24);
248        SkScalar x = SkIntToScalar(66);
249
250        SkPaint p;
251        p.setAntiAlias(true);
252        p.setTextAlign(SkPaint::kCenter_Align);
253
254        for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
255            SkString str(gModeNames[kx]);
256            canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
257            x += r.width() * 4 / 3;
258        }
259
260        y += SkIntToScalar(16) + h;
261        p.setTextAlign(SkPaint::kRight_Align);
262
263        for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
264            x = SkIntToScalar(16) + w;
265
266            SkString str(gModeNames[ky]);
267            canvas->drawText(str.c_str(), str.size(), x, y + h/2, p);
268
269            x += SkIntToScalar(50);
270            for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
271                SkPaint paint;
272                paint.setShader(fProc(gModes[kx], gModes[ky]))->unref();
273
274                canvas->save();
275                canvas->translate(x, y);
276                canvas->drawRect(r, paint);
277                canvas->restore();
278
279                x += r.width() * 4 / 3;
280            }
281            y += r.height() * 4 / 3;
282        }
283    }
284
285private:
286    typedef skiagm::GM INHERITED;
287};
288
289//////////////////////////////////////////////////////////////////////////////
290
291DEF_GM( return new ScaledTilingGM(true); )
292DEF_GM( return new ScaledTilingGM(false); )
293DEF_GM( return new ScaledTiling2GM(make_bm, "bitmap"); )
294DEF_GM( return new ScaledTiling2GM(make_grad, "gradient"); )
295