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