1/*
2 * Copyright 2013 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
8#include "gm.h"
9#include "SkBlurDrawLooper.h"
10#include "SkBlurMask.h"
11#include "SkBlurMaskFilter.h"
12#include "SkGradientShader.h"
13#include "SkMatrix.h"
14#include "SkTArray.h"
15
16namespace skiagm {
17
18class RectsGM : public GM {
19public:
20    RectsGM() {
21        this->setBGColor(0xFF000000);
22        this->makePaints();
23        this->makeMatrices();
24        this->makeRects();
25    }
26
27protected:
28    virtual uint32_t onGetFlags() const SK_OVERRIDE {
29        return kSkipTiled_Flag;
30    }
31
32    virtual SkString onShortName() SK_OVERRIDE {
33        return SkString("rects");
34    }
35
36    virtual SkISize onISize() SK_OVERRIDE {
37        return SkISize::Make(1200, 900);
38    }
39
40    void makePaints() {
41        {
42            // no AA
43            SkPaint p;
44            p.setColor(SK_ColorWHITE);
45            fPaints.push_back(p);
46        }
47
48        {
49            // AA
50            SkPaint p;
51            p.setColor(SK_ColorWHITE);
52            p.setAntiAlias(true);
53            fPaints.push_back(p);
54        }
55
56        {
57            // AA with translucent
58            SkPaint p;
59            p.setColor(SK_ColorWHITE);
60            p.setAntiAlias(true);
61            p.setAlpha(0x66);
62            fPaints.push_back(p);
63        }
64
65        {
66            // AA with mask filter
67            SkPaint p;
68            p.setColor(SK_ColorWHITE);
69            p.setAntiAlias(true);
70            SkMaskFilter* mf = SkBlurMaskFilter::Create(
71                                   kNormal_SkBlurStyle,
72                                   SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)),
73                                   SkBlurMaskFilter::kHighQuality_BlurFlag);
74            p.setMaskFilter(mf)->unref();
75            fPaints.push_back(p);
76        }
77
78        {
79            // AA with radial shader
80            SkPaint p;
81            p.setColor(SK_ColorWHITE);
82            p.setAntiAlias(true);
83            SkPoint center = SkPoint::Make(SkIntToScalar(-5), SkIntToScalar(30));
84            SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
85            SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
86            SkShader* s = SkGradientShader::CreateRadial(center,
87                                                         SkIntToScalar(20),
88                                                         colors,
89                                                         pos,
90                                                         SK_ARRAY_COUNT(colors),
91                                                         SkShader::kClamp_TileMode);
92            p.setShader(s)->unref();
93            fPaints.push_back(p);
94        }
95
96        {
97            // AA with blur
98            SkPaint p;
99            p.setColor(SK_ColorWHITE);
100            p.setAntiAlias(true);
101            SkBlurDrawLooper* shadowLooper =
102                SkBlurDrawLooper::Create(SK_ColorWHITE,
103                                         SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(10)),
104                                         SkIntToScalar(5), SkIntToScalar(10),
105                                         SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
106                                         SkBlurDrawLooper::kOverrideColor_BlurFlag |
107                                         SkBlurDrawLooper::kHighQuality_BlurFlag);
108            SkAutoUnref aurL0(shadowLooper);
109            p.setLooper(shadowLooper);
110            fPaints.push_back(p);
111        }
112
113        {
114            // AA with stroke style
115            SkPaint p;
116            p.setColor(SK_ColorWHITE);
117            p.setAntiAlias(true);
118            p.setStyle(SkPaint::kStroke_Style);
119            p.setStrokeWidth(SkIntToScalar(3));
120            fPaints.push_back(p);
121        }
122
123        {
124            // AA with bevel-stroke style
125            SkPaint p;
126            p.setColor(SK_ColorWHITE);
127            p.setAntiAlias(true);
128            p.setStyle(SkPaint::kStroke_Style);
129            p.setStrokeJoin(SkPaint::kBevel_Join);
130            p.setStrokeWidth(SkIntToScalar(3));
131            fPaints.push_back(p);
132        }
133
134        {
135            // AA with round-stroke style
136            SkPaint p;
137            p.setColor(SK_ColorWHITE);
138            p.setAntiAlias(true);
139            p.setStyle(SkPaint::kStroke_Style);
140            p.setStrokeJoin(SkPaint::kRound_Join);
141            p.setStrokeWidth(SkIntToScalar(3));
142            fPaints.push_back(p);
143        }
144
145        {
146            // AA with stroke style, width = 0
147            SkPaint p;
148            p.setColor(SK_ColorWHITE);
149            p.setAntiAlias(true);
150            p.setStyle(SkPaint::kStroke_Style);
151            fPaints.push_back(p);
152        }
153
154        {
155            // AA with stroke style, width wider than rect width and/or height
156            SkPaint p;
157            p.setColor(SK_ColorWHITE);
158            p.setAntiAlias(true);
159            p.setStyle(SkPaint::kStroke_Style);
160            p.setStrokeWidth(SkIntToScalar(40));
161            fPaints.push_back(p);
162        }
163
164        {
165            // AA with stroke and fill style
166            SkPaint p;
167            p.setColor(SK_ColorWHITE);
168            p.setAntiAlias(true);
169            p.setStyle(SkPaint::kStrokeAndFill_Style);
170            p.setStrokeWidth(SkIntToScalar(2));
171            fPaints.push_back(p);
172        }
173    }
174
175    void makeMatrices() {
176        {
177            // 1x1.5 scale
178            SkMatrix m;
179            m.setScale(1, 1.5f);
180            fMatrices.push_back(m);
181        }
182
183        {
184            // 1.5x1.5 scale
185            SkMatrix m;
186            m.setScale(1.5f, 1.5f);
187            fMatrices.push_back(m);
188        }
189
190        {
191            // 1x1.5 skew
192            SkMatrix m;
193            m.setSkew(1, 1.5f);
194            fMatrices.push_back(m);
195        }
196
197        {
198            // 1.5x1.5 skew
199            SkMatrix m;
200            m.setSkew(1.5f, 1.5f);
201            fMatrices.push_back(m);
202        }
203
204        {
205            // 30 degree rotation
206            SkMatrix m;
207            m.setRotate(SkIntToScalar(30));
208            fMatrices.push_back(m);
209        }
210
211        {
212            // 90 degree rotation
213            SkMatrix m;
214            m.setRotate(SkIntToScalar(90));
215            fMatrices.push_back(m);
216        }
217    }
218
219    void makeRects() {
220        {
221            // small square
222            SkRect r = SkRect::MakeLTRB(0, 0, 30, 30);
223            fRects.push_back(r);
224        }
225
226        {
227            // thin vertical
228            SkRect r = SkRect::MakeLTRB(0, 0, 2, 40);
229            fRects.push_back(r);
230        }
231
232        {
233            // thin horizontal
234            SkRect r = SkRect::MakeLTRB(0, 0, 40, 2);
235            fRects.push_back(r);
236        }
237
238        {
239            // very thin
240            SkRect r = SkRect::MakeLTRB(0, 0, 0.25f, 10);
241            fRects.push_back(r);
242        }
243
244        {
245            // zaftig
246            SkRect r = SkRect::MakeLTRB(0, 0, 60, 60);
247            fRects.push_back(r);
248        }
249    }
250
251    // position the current test on the canvas
252    static void position(SkCanvas* canvas, int testCount) {
253        canvas->translate(SK_Scalar1 * 100 * (testCount % 10) + SK_Scalar1 / 4,
254                          SK_Scalar1 * 100 * (testCount / 10) + 3 * SK_Scalar1 / 4);
255    }
256
257    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
258        SkAutoCommentBlock acb(canvas, "onDraw");
259
260        canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
261
262        int testCount = 0;
263
264        canvas->addComment("Test", "Various Paints");
265
266        for (int i = 0; i < fPaints.count(); ++i) {
267            for (int j = 0; j < fRects.count(); ++j, ++testCount) {
268                canvas->save();
269                this->position(canvas, testCount);
270                canvas->drawRect(fRects[j], fPaints[i]);
271                canvas->restore();
272            }
273        }
274
275        canvas->addComment("Test", "Matrices");
276
277        SkPaint paint;
278        paint.setColor(SK_ColorWHITE);
279        paint.setAntiAlias(true);
280
281        for (int i = 0; i < fMatrices.count(); ++i) {
282            for (int j = 0; j < fRects.count(); ++j, ++testCount) {
283                canvas->save();
284                this->position(canvas, testCount);
285                canvas->concat(fMatrices[i]);
286                canvas->drawRect(fRects[j], paint);
287                canvas->restore();
288            }
289        }
290    }
291
292private:
293    SkTArray<SkPaint>  fPaints;
294    SkTArray<SkMatrix> fMatrices;
295    SkTArray<SkRect>   fRects;
296
297    typedef GM INHERITED;
298};
299
300//////////////////////////////////////////////////////////////////////////////
301
302static GM* MyFactory(void*) { return new RectsGM; }
303static GMRegistry reg(MyFactory);
304
305}
306