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