blob: d1c6aeeff0411929ceeeadd9270b64788b7ba13e [file] [log] [blame]
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +00001
2/*
3 * Copyright 2011 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#include "gm.h"
9#include "SkRandom.h"
10#include "SkTArray.h"
11
reed@google.comd42e3f62012-03-30 20:04:21 +000012class SkOnce : SkNoncopyable {
13public:
14 SkOnce() { fDidOnce = false; }
15
16 bool needToDo() const { return !fDidOnce; }
17 bool alreadyDone() const { return fDidOnce; }
18 void accomplished() {
19 SkASSERT(!fDidOnce);
20 fDidOnce = true;
21 }
22
23private:
24 bool fDidOnce;
25};
26
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000027namespace skiagm {
28
29class ConvexPathsGM : public GM {
reed@google.comd42e3f62012-03-30 20:04:21 +000030 SkOnce fOnce;
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000031public:
32 ConvexPathsGM() {
bsalomon@google.com72b55be2012-01-26 20:33:19 +000033 this->setBGColor(0xFF000000);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000034 }
35
36protected:
37 virtual SkString onShortName() {
38 return SkString("convexpaths");
39 }
40
41
42 virtual SkISize onISize() {
43 return make_isize(1200, 900);
44 }
45
46 void makePaths() {
reed@google.comd42e3f62012-03-30 20:04:21 +000047 if (fOnce.alreadyDone()) {
48 return;
49 }
50 fOnce.accomplished();
51
bsalomon@google.com278dc692012-02-15 16:52:51 +000052 // CW
53 fPaths.push_back().moveTo(0, 0);
54 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
55 0, 100 * SK_Scalar1);
56 fPaths.back().lineTo(0, 0);
57
58 // CCW
59 fPaths.push_back().moveTo(0, 0);
60 fPaths.back().lineTo(0, 100 * SK_Scalar1);
61 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
62 0, 0);
63
64 // CW
65 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
66 fPaths.back().quadTo(50 * SK_Scalar1, 0,
67 100 * SK_Scalar1, 50 * SK_Scalar1);
68 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
69 0, 50 * SK_Scalar1);
70
71 // CCW
72 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
73 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
74 100 * SK_Scalar1, 50 * SK_Scalar1);
75 fPaths.back().quadTo(50 * SK_Scalar1, 0,
76 0, 50 * SK_Scalar1);
77
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000078 fPaths.push_back().addRect(0, 0,
79 100 * SK_Scalar1, 100 * SK_Scalar1,
80 SkPath::kCW_Direction);
81
82 fPaths.push_back().addRect(0, 0,
83 100 * SK_Scalar1, 100 * SK_Scalar1,
84 SkPath::kCCW_Direction);
85
86 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
87 50 * SK_Scalar1, SkPath::kCW_Direction);
88
89 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
90 40 * SK_Scalar1, SkPath::kCCW_Direction);
91
92 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
93 50 * SK_Scalar1,
94 100 * SK_Scalar1),
95 SkPath::kCW_Direction);
96
97 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
98 100 * SK_Scalar1,
99 50 * SK_Scalar1),
100 SkPath::kCCW_Direction);
101
102 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
103 100 * SK_Scalar1,
104 5 * SK_Scalar1),
105 SkPath::kCCW_Direction);
106
107 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
108 SK_Scalar1,
109 100 * SK_Scalar1),
110 SkPath::kCCW_Direction);
111
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000112 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
113 SK_Scalar1 * 100,
114 SK_Scalar1 * 100),
115 40 * SK_Scalar1, 20 * SK_Scalar1,
116 SkPath::kCW_Direction);
117
118 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
119 SK_Scalar1 * 100,
120 SK_Scalar1 * 100),
121 20 * SK_Scalar1, 40 * SK_Scalar1,
122 SkPath::kCCW_Direction);
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000123
124 // shallow diagonals
125 fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1);
126 fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1);
127 fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1);
bsalomon@google.com9732f622012-01-31 15:19:21 +0000128
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000129 /*
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000130 It turns out arcTos are not automatically marked as convex and they
131 may in fact be ever so slightly concave.
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000132 fPaths.push_back().arcTo(SkRect::MakeXYWH(0, 0,
133 50 * SK_Scalar1,
134 100 * SK_Scalar1),
135 25 * SK_Scalar1, 130 * SK_Scalar1, false);
136 */
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000137 // cubics
138 fPaths.push_back().cubicTo( 1 * SK_Scalar1, 1 * SK_Scalar1,
139 10 * SK_Scalar1, 90 * SK_Scalar1,
140 0 * SK_Scalar1, 100 * SK_Scalar1);
141 fPaths.push_back().cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
142 20 * SK_Scalar1, 100 * SK_Scalar1,
143 0 * SK_Scalar1, 0 * SK_Scalar1);
144
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000145 // path that has a cubic with a repeated first control point and
146 // a repeated last control point.
147 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
148 fPaths.back().cubicTo(10 * SK_Scalar1, 10 * SK_Scalar1,
149 10 * SK_Scalar1, 0,
150 20 * SK_Scalar1, 0);
151 fPaths.back().lineTo(40 * SK_Scalar1, 0);
152 fPaths.back().cubicTo(40 * SK_Scalar1, 0,
153 50 * SK_Scalar1, 0,
154 50 * SK_Scalar1, 10 * SK_Scalar1);
155
156 // path that has two cubics with repeated middle control points.
157 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
158 fPaths.back().cubicTo(10 * SK_Scalar1, 0,
159 10 * SK_Scalar1, 0,
160 20 * SK_Scalar1, 0);
161 fPaths.back().lineTo(40 * SK_Scalar1, 0);
162 fPaths.back().cubicTo(50 * SK_Scalar1, 0,
163 50 * SK_Scalar1, 0,
164 50 * SK_Scalar1, 10 * SK_Scalar1);
165
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000166 // triangle where one edge is a degenerate quad
167 fPaths.push_back().moveTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1);
168 fPaths.back().quadTo(SkFloatToScalar(16.9921875f), 45 * SK_Scalar1,
169 SkFloatToScalar(31.25f), 45 * SK_Scalar1);
170 fPaths.back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
171 fPaths.back().lineTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1);
172
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000173 // point degenerate
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000174 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
175 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
176
177 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
178 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
179 50 * SK_Scalar1, 50 * SK_Scalar1);
180 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
181 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
182 50 * SK_Scalar1, 50 * SK_Scalar1,
183 50 * SK_Scalar1, 50 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000184
bsalomon@google.com9732f622012-01-31 15:19:21 +0000185 // moveTo only paths
186 fPaths.push_back().moveTo(0, 0);
187 fPaths.back().moveTo(0, 0);
188 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
189 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
190 fPaths.back().moveTo(10 * SK_Scalar1, 10 * SK_Scalar1);
191
192 fPaths.push_back().moveTo(0, 0);
193 fPaths.back().moveTo(0, 0);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000194
195 // line degenerate
196 fPaths.push_back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
197 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 0, 0);
198 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1,
199 50 * SK_Scalar1, 50 * SK_Scalar1);
200 fPaths.push_back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
201 100 * SK_Scalar1, 100 * SK_Scalar1);
202 fPaths.push_back().cubicTo(0, 0,
203 0, 0,
204 100 * SK_Scalar1, 100 * SK_Scalar1);
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000205
206 // small circle. This is listed last so that it has device coords far
207 // from the origin (small area relative to x,y values).
208 fPaths.push_back().addCircle(0, 0, SkFloatToScalar(0.8f));
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000209 }
210
211 virtual void onDraw(SkCanvas* canvas) {
reed@google.comd42e3f62012-03-30 20:04:21 +0000212 this->makePaths();
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000213
214 SkPaint paint;
215 paint.setAntiAlias(true);
216 SkRandom rand;
217 canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000218 for (int i = 0; i < fPaths.count(); ++i) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000219 canvas->save();
220 // position the path, and make it at off-integer coords.
221 canvas->translate(SK_Scalar1 * 200 * (i % 5) + SK_Scalar1 / 4,
222 SK_Scalar1 * 200 * (i / 5) + 3 * SK_Scalar1 / 4);
223 SkColor color = rand.nextU();
224 color |= 0xff000000;
225 paint.setColor(color);
226 SkASSERT(fPaths[i].isConvex());
227 canvas->drawPath(fPaths[i], paint);
228 canvas->restore();
229 }
230 }
231
232private:
233 typedef GM INHERITED;
234 SkTArray<SkPath> fPaths;
235};
236
237//////////////////////////////////////////////////////////////////////////////
238
239static GM* MyFactory(void*) { return new ConvexPathsGM; }
240static GMRegistry reg(MyFactory);
241
242}
243