blob: 8eb4cba49d7a1c80fd2ac35991702cba177daefb [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; }
rmistry@google.comd6176b02012-08-23 18:14:13 +000015
reed@google.comd42e3f62012-03-30 20:04:21 +000016 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() {
bsalomon@google.com54ad8512012-08-02 14:55:45 +000043 return make_isize(1200, 1100);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000044 }
45
46 void makePaths() {
reed@google.comd42e3f62012-03-30 20:04:21 +000047 if (fOnce.alreadyDone()) {
48 return;
49 }
50 fOnce.accomplished();
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +000051
bsalomon@google.com278dc692012-02-15 16:52:51 +000052 fPaths.push_back().moveTo(0, 0);
53 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
54 0, 100 * SK_Scalar1);
55 fPaths.back().lineTo(0, 0);
56
bsalomon@google.com278dc692012-02-15 16:52:51 +000057 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
58 fPaths.back().quadTo(50 * SK_Scalar1, 0,
59 100 * SK_Scalar1, 50 * SK_Scalar1);
60 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
61 0, 50 * SK_Scalar1);
62
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000063 fPaths.push_back().addRect(0, 0,
64 100 * SK_Scalar1, 100 * SK_Scalar1,
65 SkPath::kCW_Direction);
66
67 fPaths.push_back().addRect(0, 0,
68 100 * SK_Scalar1, 100 * SK_Scalar1,
69 SkPath::kCCW_Direction);
70
71 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
72 50 * SK_Scalar1, SkPath::kCW_Direction);
73
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000074
75 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
76 50 * SK_Scalar1,
77 100 * SK_Scalar1),
78 SkPath::kCW_Direction);
79
80 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
81 100 * SK_Scalar1,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000082 5 * SK_Scalar1),
83 SkPath::kCCW_Direction);
84
85 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
86 SK_Scalar1,
87 100 * SK_Scalar1),
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +000088 SkPath::kCCW_Direction);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000089
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000090 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
91 SK_Scalar1 * 100,
92 SK_Scalar1 * 100),
93 40 * SK_Scalar1, 20 * SK_Scalar1,
94 SkPath::kCW_Direction);
95
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000096 // large number of points
97 enum {
98 kLength = 100,
99 kPtsPerSide = (1 << 12),
100 };
101 fPaths.push_back().moveTo(0, 0);
102 for (int i = 1; i < kPtsPerSide; ++i) { // skip the first point due to moveTo.
103 fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0);
104 }
105 for (int i = 0; i < kPtsPerSide; ++i) {
106 fPaths.back().lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide);
107 }
108 for (int i = kPtsPerSide; i > 0; --i) {
109 fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength);
110 }
111 for (int i = kPtsPerSide; i > 0; --i) {
112 fPaths.back().lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide);
113 }
114
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000115 // shallow diagonals
116 fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1);
117 fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1);
118 fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1);
bsalomon@google.com9732f622012-01-31 15:19:21 +0000119
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000120 fPaths.push_back().arcTo(SkRect::MakeXYWH(0, 0,
121 50 * SK_Scalar1,
122 100 * SK_Scalar1),
123 25 * SK_Scalar1, 130 * SK_Scalar1, false);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000124
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000125 // cubics
126 fPaths.push_back().cubicTo( 1 * SK_Scalar1, 1 * SK_Scalar1,
127 10 * SK_Scalar1, 90 * SK_Scalar1,
128 0 * SK_Scalar1, 100 * SK_Scalar1);
129 fPaths.push_back().cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
130 20 * SK_Scalar1, 100 * SK_Scalar1,
131 0 * SK_Scalar1, 0 * SK_Scalar1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000132
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000133 // path that has a cubic with a repeated first control point and
134 // a repeated last control point.
135 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
136 fPaths.back().cubicTo(10 * SK_Scalar1, 10 * SK_Scalar1,
137 10 * SK_Scalar1, 0,
138 20 * SK_Scalar1, 0);
139 fPaths.back().lineTo(40 * SK_Scalar1, 0);
140 fPaths.back().cubicTo(40 * SK_Scalar1, 0,
141 50 * SK_Scalar1, 0,
142 50 * SK_Scalar1, 10 * SK_Scalar1);
143
144 // path that has two cubics with repeated middle control points.
145 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
146 fPaths.back().cubicTo(10 * SK_Scalar1, 0,
147 10 * SK_Scalar1, 0,
148 20 * SK_Scalar1, 0);
149 fPaths.back().lineTo(40 * SK_Scalar1, 0);
150 fPaths.back().cubicTo(50 * SK_Scalar1, 0,
151 50 * SK_Scalar1, 0,
152 50 * SK_Scalar1, 10 * SK_Scalar1);
153
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000154 // cubic where last three points are almost a line
155 fPaths.push_back().moveTo(0, 228 * SK_Scalar1 / 8);
156 fPaths.back().cubicTo(628 * SK_Scalar1 / 8, 82 * SK_Scalar1 / 8,
157 1255 * SK_Scalar1 / 8, 141 * SK_Scalar1 / 8,
158 1883 * SK_Scalar1 / 8, 202 * SK_Scalar1 / 8);
159
160 // flat cubic where the at end point tangents both point outward.
161 fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
162 fPaths.back().cubicTo(0, SK_Scalar1,
163 30 * SK_Scalar1, SK_Scalar1,
164 20 * SK_Scalar1, 0);
165
166 // flat cubic where initial tangent is in, end tangent out
167 fPaths.push_back().moveTo(0, 0 * SK_Scalar1);
168 fPaths.back().cubicTo(10 * SK_Scalar1, SK_Scalar1,
169 30 * SK_Scalar1, SK_Scalar1,
170 20 * SK_Scalar1, 0);
171
172 // flat cubic where initial tangent is out, end tangent in
173 fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
174 fPaths.back().cubicTo(0, SK_Scalar1,
175 20 * SK_Scalar1, SK_Scalar1,
176 30 * SK_Scalar1, 0);
177
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000178 // triangle where one edge is a degenerate quad
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000179 fPaths.push_back().moveTo(8.59375f, 45 * SK_Scalar1);
180 fPaths.back().quadTo(16.9921875f, 45 * SK_Scalar1,
181 31.25f, 45 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000182 fPaths.back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000183 fPaths.back().lineTo(8.59375f, 45 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000184
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000185 // triangle where one edge is a quad with a repeated point
186 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
187 fPaths.back().lineTo(50 * SK_Scalar1, 0);
188 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1, 50 * SK_Scalar1, 50 * SK_Scalar1);
189
190 // triangle where one edge is a cubic with a 2x repeated point
191 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
192 fPaths.back().lineTo(50 * SK_Scalar1, 0);
193 fPaths.back().cubicTo(50 * SK_Scalar1, 0,
194 50 * SK_Scalar1, 50 * SK_Scalar1,
195 50 * SK_Scalar1, 50 * SK_Scalar1);
196
197 // triangle where one edge is a quad with a nearly repeated point
198 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
199 fPaths.back().lineTo(50 * SK_Scalar1, 0);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000200 fPaths.back().quadTo(50 * SK_Scalar1, 49.95f,
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000201 50 * SK_Scalar1, 50 * SK_Scalar1);
202
203 // triangle where one edge is a cubic with a 3x nearly repeated point
204 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
205 fPaths.back().lineTo(50 * SK_Scalar1, 0);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000206 fPaths.back().cubicTo(50 * SK_Scalar1, 49.95f,
207 50 * SK_Scalar1, 49.97f,
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000208 50 * SK_Scalar1, 50 * SK_Scalar1);
209
210 // triangle where there is a point degenerate cubic at one corner
211 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
212 fPaths.back().lineTo(50 * SK_Scalar1, 0);
213 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
214 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
215 50 * SK_Scalar1, 50 * SK_Scalar1,
216 50 * SK_Scalar1, 50 * SK_Scalar1);
217
218 // point line
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000219 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
220 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000221
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000222 // point quad
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000223 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
224 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
225 50 * SK_Scalar1, 50 * SK_Scalar1);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000226
227 // point cubic
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000228 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
229 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
230 50 * SK_Scalar1, 50 * SK_Scalar1,
231 50 * SK_Scalar1, 50 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000232
bsalomon@google.com9732f622012-01-31 15:19:21 +0000233 // moveTo only paths
234 fPaths.push_back().moveTo(0, 0);
235 fPaths.back().moveTo(0, 0);
236 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
237 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
238 fPaths.back().moveTo(10 * SK_Scalar1, 10 * SK_Scalar1);
239
240 fPaths.push_back().moveTo(0, 0);
241 fPaths.back().moveTo(0, 0);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000242
243 // line degenerate
244 fPaths.push_back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
245 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 0, 0);
246 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1,
247 50 * SK_Scalar1, 50 * SK_Scalar1);
248 fPaths.push_back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
249 100 * SK_Scalar1, 100 * SK_Scalar1);
250 fPaths.push_back().cubicTo(0, 0,
251 0, 0,
252 100 * SK_Scalar1, 100 * SK_Scalar1);
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000253
254 // small circle. This is listed last so that it has device coords far
255 // from the origin (small area relative to x,y values).
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000256 fPaths.push_back().addCircle(0, 0, 1.2f);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000257 }
258
259 virtual void onDraw(SkCanvas* canvas) {
reed@google.comd42e3f62012-03-30 20:04:21 +0000260 this->makePaths();
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000261
262 SkPaint paint;
263 paint.setAntiAlias(true);
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000264 SkLCGRandom rand;
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000265 canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000266
267 // As we've added more paths this has gotten pretty big. Scale the whole thing down.
268 canvas->scale(2 * SK_Scalar1 / 3, 2 * SK_Scalar1 / 3);
269
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000270 for (int i = 0; i < fPaths.count(); ++i) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000271 canvas->save();
272 // position the path, and make it at off-integer coords.
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000273 canvas->translate(SK_Scalar1 * 200 * (i % 5) + SK_Scalar1 / 10,
274 SK_Scalar1 * 200 * (i / 5) + 9 * SK_Scalar1 / 10);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000275 SkColor color = rand.nextU();
276 color |= 0xff000000;
277 paint.setColor(color);
bsalomon@google.com44d662b2013-08-15 20:34:45 +0000278#if 0 // This hitting on 32bit Linux builds for some paths. Temporarily disabling while it is
279 // debugged.
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000280 SkASSERT(fPaths[i].isConvex());
bsalomon@google.com44d662b2013-08-15 20:34:45 +0000281#endif
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000282 canvas->drawPath(fPaths[i], paint);
283 canvas->restore();
284 }
285 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000286
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000287private:
288 typedef GM INHERITED;
289 SkTArray<SkPath> fPaths;
290};
291
292//////////////////////////////////////////////////////////////////////////////
293
294static GM* MyFactory(void*) { return new ConvexPathsGM; }
295static GMRegistry reg(MyFactory);
296
297}