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