1
2/*
3 * Copyright 2013 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
9#include "gm.h"
10#include "SkTArray.h"
11#include "SkRandom.h"
12#include "SkMatrix.h"
13#include "SkBlurMaskFilter.h"
14#include "SkGradientShader.h"
15#include "SkBlurDrawLooper.h"
16#include "SkRect.h"
17
18namespace skiagm {
19
20class OvalGM : public GM {
21public:
22    OvalGM() {
23        this->setBGColor(0xFF000000);
24        this->makePaints();
25        this->makeMatrices();
26    }
27
28protected:
29    virtual uint32_t onGetFlags() const SK_OVERRIDE {
30        return kSkipTiled_Flag;
31    }
32
33    virtual SkString onShortName() SK_OVERRIDE {
34        return SkString("ovals");
35    }
36
37    virtual SkISize onISize() SK_OVERRIDE {
38        return SkISize::Make(1200, 900);
39    }
40
41    void makePaints() {
42        {
43        // no AA
44        SkPaint p;
45        fPaints.push_back(p);
46        }
47
48        {
49        // AA
50        SkPaint p;
51        p.setAntiAlias(true);
52        fPaints.push_back(p);
53        }
54
55        {
56        // AA with stroke style
57        SkPaint p;
58        p.setAntiAlias(true);
59        p.setStyle(SkPaint::kStroke_Style);
60        p.setStrokeWidth(SkIntToScalar(5));
61        fPaints.push_back(p);
62        }
63
64        {
65        // AA with stroke style, width = 0
66        SkPaint p;
67        p.setAntiAlias(true);
68        p.setStyle(SkPaint::kStroke_Style);
69        fPaints.push_back(p);
70        }
71
72        {
73        // AA with stroke and fill style
74        SkPaint p;
75        p.setAntiAlias(true);
76        p.setStyle(SkPaint::kStrokeAndFill_Style);
77        p.setStrokeWidth(SkIntToScalar(3));
78        fPaints.push_back(p);
79        }
80    }
81
82    void makeMatrices() {
83        {
84        SkMatrix m;
85        m.setIdentity();
86        fMatrices.push_back(m);
87        }
88
89        {
90        SkMatrix m;
91        m.setScale(SkIntToScalar(3), SkIntToScalar(2));
92        fMatrices.push_back(m);
93        }
94
95        {
96        SkMatrix m;
97        m.setScale(SkIntToScalar(2), SkIntToScalar(2));
98        fMatrices.push_back(m);
99        }
100
101        {
102        SkMatrix m;
103        m.setScale(SkIntToScalar(1), SkIntToScalar(2));
104        fMatrices.push_back(m);
105        }
106
107        {
108        SkMatrix m;
109        m.setScale(SkIntToScalar(4), SkIntToScalar(1));
110        fMatrices.push_back(m);
111        }
112
113        {
114        SkMatrix m;
115        m.setRotate(SkIntToScalar(90));
116        fMatrices.push_back(m);
117        }
118
119        {
120        SkMatrix m;
121        m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
122        fMatrices.push_back(m);
123        }
124
125        {
126        SkMatrix m;
127        m.setRotate(SkIntToScalar(60));
128        fMatrices.push_back(m);
129        }
130    }
131
132    SkColor genColor(SkRandom* rand) {
133        SkScalar hsv[3];
134        hsv[0] = rand->nextRangeF(0.0f, 360.0f);
135        hsv[1] = rand->nextRangeF(0.75f, 1.0f);
136        hsv[2] = rand->nextRangeF(0.75f, 1.0f);
137
138        return SkHSVToColor(hsv);
139    }
140
141    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
142        SkRandom rand(1);
143        canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
144        SkRect oval = SkRect::MakeLTRB(-20, -30, 20, 30);
145
146        const SkScalar kXStart = 60.0f;
147        const SkScalar kYStart = 80.0f;
148        const int kXStep = 150;
149        const int kYStep = 160;
150        int maxX = fMatrices.count();
151
152        SkPaint rectPaint;
153        rectPaint.setAntiAlias(true);
154        rectPaint.setStyle(SkPaint::kStroke_Style);
155        rectPaint.setStrokeWidth(SkIntToScalar(0));
156        rectPaint.setColor(SK_ColorLTGRAY);
157
158        int testCount = 0;
159        for (int i = 0; i < fPaints.count(); ++i) {
160            for (int j = 0; j < fMatrices.count(); ++j) {
161                canvas->save();
162                SkMatrix mat = fMatrices[j];
163                // position the oval, and make it at off-integer coords.
164                mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
165                                  SK_Scalar1 / 4,
166                                  kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
167                                  3 * SK_Scalar1 / 4);
168                canvas->concat(mat);
169
170                SkColor color = genColor(&rand);
171                fPaints[i].setColor(color);
172
173                canvas->drawRect(oval, rectPaint);
174                canvas->drawOval(oval, fPaints[i]);
175
176                canvas->restore();
177
178                ++testCount;
179            }
180        }
181
182        // special cases
183
184        // non-scaled tall and skinny oval
185        for (int i = 0; i < fPaints.count(); ++i) {
186            SkRect oval = SkRect::MakeLTRB(-20, -60, 20, 60);
187            canvas->save();
188            // position the oval, and make it at off-integer coords.
189            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
190                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
191
192            SkColor color = genColor(&rand);
193            fPaints[i].setColor(color);
194
195            canvas->drawRect(oval, rectPaint);
196            canvas->drawOval(oval, fPaints[i]);
197            canvas->restore();
198        }
199
200        // non-scaled wide and short oval
201        for (int i = 0; i < fPaints.count(); ++i) {
202            SkRect oval = SkRect::MakeLTRB(-80, -30, 80, 30);
203            canvas->save();
204            // position the oval, and make it at off-integer coords.
205            canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
206                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
207                              SK_ScalarHalf * kYStep);
208
209            SkColor color = genColor(&rand);
210            fPaints[i].setColor(color);
211
212            canvas->drawRect(oval, rectPaint);
213            canvas->drawOval(oval, fPaints[i]);
214            canvas->restore();
215        }
216
217        // super skinny oval
218        for (int i = 0; i < fPaints.count(); ++i) {
219            SkRect oval = SkRect::MakeLTRB(0, -60, 1, 60);
220            canvas->save();
221            // position the oval, and make it at off-integer coords.
222            canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
223                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
224
225            SkColor color = genColor(&rand);
226            fPaints[i].setColor(color);
227
228            canvas->drawOval(oval, fPaints[i]);
229            canvas->restore();
230        }
231
232        // super short oval
233        for (int i = 0; i < fPaints.count(); ++i) {
234            SkRect oval = SkRect::MakeLTRB(-80, -1, 80, 0);
235            canvas->save();
236            // position the oval, and make it at off-integer coords.
237            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
238                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
239                              SK_ScalarHalf * kYStep);
240
241            SkColor color = genColor(&rand);
242            fPaints[i].setColor(color);
243
244            canvas->drawOval(oval, fPaints[i]);
245            canvas->restore();
246        }
247
248        // radial gradient
249        SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
250        SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
251        SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
252        SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center,
253                                                     SkIntToScalar(20),
254                                                     colors,
255                                                     pos,
256                                                     SK_ARRAY_COUNT(colors),
257                                                     SkShader::kClamp_TileMode));
258
259        for (int i = 0; i < fPaints.count(); ++i) {
260            canvas->save();
261            // position the path, and make it at off-integer coords.
262            canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4,
263                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
264                              SK_ScalarHalf * kYStep);
265
266            SkColor color = genColor(&rand);
267            fPaints[i].setColor(color);
268            fPaints[i].setShader(shader);
269
270            canvas->drawRect(oval, rectPaint);
271            canvas->drawOval(oval, fPaints[i]);
272
273            fPaints[i].setShader(NULL);
274
275            canvas->restore();
276        }
277    }
278
279private:
280    SkTArray<SkPaint> fPaints;
281    SkTArray<SkMatrix> fMatrices;
282
283    typedef GM INHERITED;
284};
285
286//////////////////////////////////////////////////////////////////////////////
287
288static GM* MyFactory(void*) { return new OvalGM; }
289static GMRegistry reg(MyFactory);
290
291}
292