• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkPath.h"
14 #include "include/core/SkPathTypes.h"
15 #include "include/core/SkPoint.h"
16 #include "include/core/SkRect.h"
17 #include "include/core/SkScalar.h"
18 #include "include/core/SkShader.h"
19 #include "include/core/SkSize.h"
20 #include "include/core/SkString.h"
21 #include "include/core/SkTileMode.h"
22 #include "include/core/SkTypes.h"
23 #include "include/effects/SkGradientShader.h"
24 #include "include/private/base/SkTArray.h"
25 #include "src/base/SkRandom.h"
26 #include "tools/ToolUtils.h"
27 
28 using namespace skia_private;
29 
30 namespace skiagm {
31 
32 class OvalGM : public GM {
33 public:
OvalGM()34     OvalGM() {
35         this->setBGColor(0xFF000000);
36         this->makePaints();
37         this->makeMatrices();
38     }
39 
40 protected:
getName() const41     SkString getName() const override { return SkString("ovals"); }
42 
getISize()43     SkISize getISize() override { return SkISize::Make(1200, 900); }
44 
makePaints()45     void makePaints() {
46         {
47         // no AA
48         SkPaint p;
49         fPaints.push_back(p);
50         }
51 
52         {
53         // AA
54         SkPaint p;
55         p.setAntiAlias(true);
56         fPaints.push_back(p);
57         }
58 
59         {
60         // AA with stroke style
61         SkPaint p;
62         p.setAntiAlias(true);
63         p.setStyle(SkPaint::kStroke_Style);
64         p.setStrokeWidth(SkIntToScalar(5));
65         fPaints.push_back(p);
66         }
67 
68         {
69         // AA with stroke style, width = 0
70         SkPaint p;
71         p.setAntiAlias(true);
72         p.setStyle(SkPaint::kStroke_Style);
73         fPaints.push_back(p);
74         }
75 
76         {
77         // AA with stroke and fill style
78         SkPaint p;
79         p.setAntiAlias(true);
80         p.setStyle(SkPaint::kStrokeAndFill_Style);
81         p.setStrokeWidth(SkIntToScalar(3));
82         fPaints.push_back(p);
83         }
84     }
85 
makeMatrices()86     void makeMatrices() {
87         {
88         SkMatrix m;
89         m.setIdentity();
90         fMatrices.push_back(m);
91         }
92 
93         {
94         SkMatrix m;
95         m.setScale(SkIntToScalar(3), SkIntToScalar(2));
96         fMatrices.push_back(m);
97         }
98 
99         {
100         SkMatrix m;
101         m.setScale(SkIntToScalar(2), SkIntToScalar(2));
102         fMatrices.push_back(m);
103         }
104 
105         {
106         SkMatrix m;
107         m.setScale(SkIntToScalar(1), SkIntToScalar(2));
108         fMatrices.push_back(m);
109         }
110 
111         {
112         SkMatrix m;
113         m.setScale(SkIntToScalar(4), SkIntToScalar(1));
114         fMatrices.push_back(m);
115         }
116 
117         {
118         SkMatrix m;
119         m.setRotate(SkIntToScalar(90));
120         fMatrices.push_back(m);
121         }
122 
123         {
124         SkMatrix m;
125         m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
126         fMatrices.push_back(m);
127         }
128 
129         {
130         SkMatrix m;
131         m.setRotate(SkIntToScalar(60));
132         fMatrices.push_back(m);
133         }
134     }
135 
genColor(SkRandom * rand)136     SkColor genColor(SkRandom* rand) {
137         SkScalar hsv[3];
138         hsv[0] = rand->nextRangeF(0.0f, 360.0f);
139         hsv[1] = rand->nextRangeF(0.75f, 1.0f);
140         hsv[2] = rand->nextRangeF(0.75f, 1.0f);
141 
142         return ToolUtils::color_to_565(SkHSVToColor(hsv));
143     }
144 
onDraw(SkCanvas * canvas)145     void onDraw(SkCanvas* canvas) override {
146         SkRandom rand(1);
147         canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
148         const SkRect kOval = SkRect::MakeLTRB(-20, -30, 20, 30);
149 
150         const SkScalar kXStart = 60.0f;
151         const SkScalar kYStart = 80.0f;
152         const int kXStep = 150;
153         const int kYStep = 160;
154         int maxX = fMatrices.size();
155 
156         SkPaint rectPaint;
157         rectPaint.setAntiAlias(true);
158         rectPaint.setStyle(SkPaint::kStroke_Style);
159         rectPaint.setStrokeWidth(SkIntToScalar(0));
160         rectPaint.setColor(SK_ColorLTGRAY);
161 
162         int testCount = 0;
163         for (int i = 0; i < fPaints.size(); ++i) {
164             for (int j = 0; j < fMatrices.size(); ++j) {
165                 canvas->save();
166                 SkMatrix mat = fMatrices[j];
167                 // position the oval, and make it at off-integer coords.
168                 mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
169                                   SK_Scalar1 / 4,
170                                   kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
171                                   3 * SK_Scalar1 / 4);
172                 canvas->concat(mat);
173 
174                 SkColor color = genColor(&rand);
175                 fPaints[i].setColor(color);
176 
177                 canvas->drawRect(kOval, rectPaint);
178                 canvas->drawOval(kOval, fPaints[i]);
179 
180                 canvas->restore();
181 
182                 ++testCount;
183             }
184         }
185 
186         // special cases
187 
188         // non-scaled tall and skinny oval
189         for (int i = 0; i < fPaints.size(); ++i) {
190             SkRect oval = SkRect::MakeLTRB(-20, -60, 20, 60);
191             canvas->save();
192             // position the oval, and make it at off-integer coords.
193             canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
194                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
195 
196             SkColor color = genColor(&rand);
197             fPaints[i].setColor(color);
198 
199             canvas->drawRect(oval, rectPaint);
200             canvas->drawOval(oval, fPaints[i]);
201             canvas->restore();
202         }
203 
204         // non-scaled wide and short oval
205         for (int i = 0; i < fPaints.size(); ++i) {
206             SkRect oval = SkRect::MakeLTRB(-80, -30, 80, 30);
207             canvas->save();
208             // position the oval, and make it at off-integer coords.
209             canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
210                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
211                               SK_ScalarHalf * kYStep);
212 
213             SkColor color = genColor(&rand);
214             fPaints[i].setColor(color);
215 
216             canvas->drawRect(oval, rectPaint);
217             canvas->drawOval(oval, fPaints[i]);
218             canvas->restore();
219         }
220 
221         // super skinny oval
222         for (int i = 0; i < fPaints.size(); ++i) {
223             SkRect oval = SkRect::MakeLTRB(0, -60, 1, 60);
224             canvas->save();
225             // position the oval, and make it at off-integer coords.
226             canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
227                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
228 
229             SkColor color = genColor(&rand);
230             fPaints[i].setColor(color);
231 
232             canvas->drawOval(oval, fPaints[i]);
233             canvas->restore();
234         }
235 
236         // super short oval
237         for (int i = 0; i < fPaints.size(); ++i) {
238             SkRect oval = SkRect::MakeLTRB(-80, -1, 80, 0);
239             canvas->save();
240             // position the oval, and make it at off-integer coords.
241             canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
242                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
243                               SK_ScalarHalf * kYStep);
244 
245             SkColor color = genColor(&rand);
246             fPaints[i].setColor(color);
247 
248             canvas->drawOval(oval, fPaints[i]);
249             canvas->restore();
250         }
251 
252         // radial gradient
253         SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
254         SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
255         SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
256         auto shader = SkGradientShader::MakeRadial(center, 20, colors, pos, std::size(colors),
257                                                    SkTileMode::kClamp);
258 
259         for (int i = 0; i < fPaints.size(); ++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(kOval, rectPaint);
271             canvas->drawOval(kOval, fPaints[i]);
272 
273             fPaints[i].setShader(nullptr);
274 
275             canvas->restore();
276         }
277 
278         // reflected oval
279         for (int i = 0; i < fPaints.size(); ++i) {
280             SkRect oval = SkRect::MakeLTRB(-30, -30, 30, 30);
281             canvas->save();
282             // position the oval, and make it at off-integer coords.
283             canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
284                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
285                               SK_ScalarHalf * kYStep);
286             canvas->rotate(90);
287             canvas->scale(1, -1);
288             canvas->scale(1, 0.66f);
289 
290             SkColor color = genColor(&rand);
291             fPaints[i].setColor(color);
292 
293             canvas->drawRect(oval, rectPaint);
294             canvas->drawOval(oval, fPaints[i]);
295             canvas->restore();
296         }
297     }
298 
299 private:
300     TArray<SkPaint> fPaints;
301     TArray<SkMatrix> fMatrices;
302 
303     using INHERITED = GM;
304 };
305 
306 //////////////////////////////////////////////////////////////////////////////
307 
308 DEF_GM( return new OvalGM; )
309 
310 }  // namespace skiagm
311 
312 DEF_SIMPLE_GM(open_ovals, canvas, 225, 110) {
313     SkPaint paint;
314     paint.setAntiAlias(true);
315     paint.setStyle(SkPaint::kStroke_Style);
316 
317     const SkRect rect = SkRect::MakeWH(50, 100);
318     const SkPathDirection dir = SkPathDirection::kCW;
319     const int start = 1;
320 
321     // We stroke several open ovals to see how they behave
322     canvas->translate(5, 5);
323 
__anonacd42a350102(const SkPath& p) 324     auto doRow = [&](const SkPath& p) {
325         canvas->drawPath(p, paint);
326         canvas->translate(55, 0);
327     };
328 
329     // Default case (left open) looks like an oval
330     SkPath path;
331     path.addOpenOval(rect, dir, start);
332     doRow(path);
333 
334     // Closing makes us technically be an oval, but should look the same
335     path.close();
336     doRow(path);
337 
338     // Moving before the oval adds a line to the start
339     path.reset();
340     path.moveTo(rect.center());
341     path.addOpenOval(rect, dir, start);
342     doRow(path);
343 
344     // Similarly, lineTo after the oval starts from the start/end point
345     path.reset();
346     path.addOpenOval(rect, dir, start);
347     path.lineTo(rect.center());
348     doRow(path);
349 }
350