blob: f5cc6facaaed5cc50446dc5ee34fd0861aee13ea [file] [log] [blame]
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +00001/*
2 * Copyright 2011 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 */
Ben Wagner7fde8e12019-05-01 17:28:53 -04007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
11#include "include/core/SkMatrix.h"
12#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkPath.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040014#include "include/core/SkRect.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkSize.h"
17#include "include/core/SkString.h"
18#include "include/core/SkTypes.h"
19#include "include/private/SkNoncopyable.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "include/private/SkTArray.h"
21#include "include/utils/SkRandom.h"
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000022
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000023class SkDoOnce : SkNoncopyable {
reed@google.comd42e3f62012-03-30 20:04:21 +000024public:
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000025 SkDoOnce() { fDidOnce = false; }
rmistry@google.comd6176b02012-08-23 18:14:13 +000026
reed@google.comd42e3f62012-03-30 20:04:21 +000027 bool needToDo() const { return !fDidOnce; }
28 bool alreadyDone() const { return fDidOnce; }
29 void accomplished() {
30 SkASSERT(!fDidOnce);
31 fDidOnce = true;
32 }
33
34private:
35 bool fDidOnce;
36};
37
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000038namespace skiagm {
39
40class ConvexPathsGM : public GM {
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000041 SkDoOnce fOnce;
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000042public:
43 ConvexPathsGM() {
bsalomon@google.com72b55be2012-01-26 20:33:19 +000044 this->setBGColor(0xFF000000);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000045 }
46
47protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000048
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000049 virtual SkString onShortName() {
50 return SkString("convexpaths");
51 }
52
53
54 virtual SkISize onISize() {
tfarinaf5393182014-06-09 23:59:03 -070055 return SkISize::Make(1200, 1100);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000056 }
57
58 void makePaths() {
reed@google.comd42e3f62012-03-30 20:04:21 +000059 if (fOnce.alreadyDone()) {
60 return;
61 }
62 fOnce.accomplished();
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +000063
bsalomon@google.com278dc692012-02-15 16:52:51 +000064 fPaths.push_back().moveTo(0, 0);
65 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
66 0, 100 * SK_Scalar1);
67 fPaths.back().lineTo(0, 0);
68
bsalomon@google.com278dc692012-02-15 16:52:51 +000069 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
70 fPaths.back().quadTo(50 * SK_Scalar1, 0,
71 100 * SK_Scalar1, 50 * SK_Scalar1);
72 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
73 0, 50 * SK_Scalar1);
74
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000075 fPaths.push_back().addRect(0, 0,
76 100 * SK_Scalar1, 100 * SK_Scalar1,
77 SkPath::kCW_Direction);
78
79 fPaths.push_back().addRect(0, 0,
80 100 * SK_Scalar1, 100 * SK_Scalar1,
81 SkPath::kCCW_Direction);
82
83 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
84 50 * SK_Scalar1, SkPath::kCW_Direction);
85
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000086
87 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
88 50 * SK_Scalar1,
89 100 * SK_Scalar1),
90 SkPath::kCW_Direction);
91
92 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
93 100 * SK_Scalar1,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000094 5 * SK_Scalar1),
95 SkPath::kCCW_Direction);
96
97 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
98 SK_Scalar1,
99 100 * SK_Scalar1),
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000100 SkPath::kCCW_Direction);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000101
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000102 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
103 SK_Scalar1 * 100,
104 SK_Scalar1 * 100),
105 40 * SK_Scalar1, 20 * SK_Scalar1,
106 SkPath::kCW_Direction);
107
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +0000108 // large number of points
109 enum {
110 kLength = 100,
111 kPtsPerSide = (1 << 12),
112 };
113 fPaths.push_back().moveTo(0, 0);
114 for (int i = 1; i < kPtsPerSide; ++i) { // skip the first point due to moveTo.
115 fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0);
116 }
117 for (int i = 0; i < kPtsPerSide; ++i) {
118 fPaths.back().lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide);
119 }
120 for (int i = kPtsPerSide; i > 0; --i) {
121 fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength);
122 }
123 for (int i = kPtsPerSide; i > 0; --i) {
124 fPaths.back().lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide);
125 }
126
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000127 // shallow diagonals
128 fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1);
129 fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1);
130 fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1);
bsalomon@google.com9732f622012-01-31 15:19:21 +0000131
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +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);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000136
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);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000144
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.com54ad8512012-08-02 14:55:45 +0000166 // cubic where last three points are almost a line
167 fPaths.push_back().moveTo(0, 228 * SK_Scalar1 / 8);
168 fPaths.back().cubicTo(628 * SK_Scalar1 / 8, 82 * SK_Scalar1 / 8,
169 1255 * SK_Scalar1 / 8, 141 * SK_Scalar1 / 8,
170 1883 * SK_Scalar1 / 8, 202 * SK_Scalar1 / 8);
171
172 // flat cubic where the at end point tangents both point outward.
173 fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
174 fPaths.back().cubicTo(0, SK_Scalar1,
175 30 * SK_Scalar1, SK_Scalar1,
176 20 * SK_Scalar1, 0);
177
178 // flat cubic where initial tangent is in, end tangent out
179 fPaths.push_back().moveTo(0, 0 * SK_Scalar1);
180 fPaths.back().cubicTo(10 * SK_Scalar1, SK_Scalar1,
181 30 * SK_Scalar1, SK_Scalar1,
182 20 * SK_Scalar1, 0);
183
184 // flat cubic where initial tangent is out, end tangent in
185 fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
186 fPaths.back().cubicTo(0, SK_Scalar1,
187 20 * SK_Scalar1, SK_Scalar1,
188 30 * SK_Scalar1, 0);
189
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000190 // triangle where one edge is a degenerate quad
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000191 fPaths.push_back().moveTo(8.59375f, 45 * SK_Scalar1);
192 fPaths.back().quadTo(16.9921875f, 45 * SK_Scalar1,
193 31.25f, 45 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000194 fPaths.back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000195 fPaths.back().lineTo(8.59375f, 45 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000196
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000197 // triangle where one edge is a quad with a repeated point
198 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
199 fPaths.back().lineTo(50 * SK_Scalar1, 0);
200 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1, 50 * SK_Scalar1, 50 * SK_Scalar1);
201
202 // triangle where one edge is a cubic with a 2x repeated point
203 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
204 fPaths.back().lineTo(50 * SK_Scalar1, 0);
205 fPaths.back().cubicTo(50 * SK_Scalar1, 0,
206 50 * SK_Scalar1, 50 * SK_Scalar1,
207 50 * SK_Scalar1, 50 * SK_Scalar1);
208
209 // triangle where one edge is a quad with a nearly repeated point
210 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
211 fPaths.back().lineTo(50 * SK_Scalar1, 0);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000212 fPaths.back().quadTo(50 * SK_Scalar1, 49.95f,
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000213 50 * SK_Scalar1, 50 * SK_Scalar1);
214
215 // triangle where one edge is a cubic with a 3x nearly repeated point
216 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
217 fPaths.back().lineTo(50 * SK_Scalar1, 0);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000218 fPaths.back().cubicTo(50 * SK_Scalar1, 49.95f,
219 50 * SK_Scalar1, 49.97f,
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000220 50 * SK_Scalar1, 50 * SK_Scalar1);
221
222 // triangle where there is a point degenerate cubic at one corner
223 fPaths.push_back().moveTo(0, 25 * SK_Scalar1);
224 fPaths.back().lineTo(50 * SK_Scalar1, 0);
225 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
226 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
227 50 * SK_Scalar1, 50 * SK_Scalar1,
228 50 * SK_Scalar1, 50 * SK_Scalar1);
229
230 // point line
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000231 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
232 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000233
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000234 // point quad
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000235 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
236 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
237 50 * SK_Scalar1, 50 * SK_Scalar1);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000238
239 // point cubic
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000240 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
241 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
242 50 * SK_Scalar1, 50 * SK_Scalar1,
243 50 * SK_Scalar1, 50 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000244
bsalomon@google.com9732f622012-01-31 15:19:21 +0000245 // moveTo only paths
246 fPaths.push_back().moveTo(0, 0);
247 fPaths.back().moveTo(0, 0);
248 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
249 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
250 fPaths.back().moveTo(10 * SK_Scalar1, 10 * SK_Scalar1);
251
252 fPaths.push_back().moveTo(0, 0);
253 fPaths.back().moveTo(0, 0);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000254
255 // line degenerate
256 fPaths.push_back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
257 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 0, 0);
258 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1,
259 50 * SK_Scalar1, 50 * SK_Scalar1);
260 fPaths.push_back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
261 100 * SK_Scalar1, 100 * SK_Scalar1);
262 fPaths.push_back().cubicTo(0, 0,
263 0, 0,
264 100 * SK_Scalar1, 100 * SK_Scalar1);
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000265
Brian Salomon73c6c9d2019-03-29 15:41:27 -0400266 // skbug.com/8928
267 fPaths.push_back().moveTo(16.875f, 192.594f);
268 fPaths.back().cubicTo(45.625f, 192.594f, 74.375f, 192.594f, 103.125f, 192.594f);
269 fPaths.back().cubicTo(88.75f, 167.708f, 74.375f, 142.823f, 60, 117.938f);
270 fPaths.back().cubicTo(45.625f, 142.823f, 31.25f, 167.708f, 16.875f, 192.594f);
271 fPaths.back().close();
272 SkMatrix m;
273 m.setAll(0.1f, 0, -1, 0, 0.115207f, -2.64977f, 0, 0, 1);
274 fPaths.back().transform(m);
275
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000276 // small circle. This is listed last so that it has device coords far
277 // from the origin (small area relative to x,y values).
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000278 fPaths.push_back().addCircle(0, 0, 1.2f);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000279 }
280
281 virtual void onDraw(SkCanvas* canvas) {
reed@google.comd42e3f62012-03-30 20:04:21 +0000282 this->makePaths();
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000283
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500284 SkPaint paint;
285 paint.setAntiAlias(true);
286 SkRandom rand;
287 canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000288
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500289 // As we've added more paths this has gotten pretty big. Scale the whole thing down.
290 canvas->scale(2 * SK_Scalar1 / 3, 2 * SK_Scalar1 / 3);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000291
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500292 for (int i = 0; i < fPaths.count(); ++i) {
293 canvas->save();
294 // position the path, and make it at off-integer coords.
295 canvas->translate(SK_Scalar1 * 200 * (i % 5) + SK_Scalar1 / 10,
296 SK_Scalar1 * 200 * (i / 5) + 9 * SK_Scalar1 / 10);
297 SkColor color = rand.nextU();
298 color |= 0xff000000;
299 paint.setColor(color);
300#if 0 // This hitting on 32bit Linux builds for some paths. Temporarily disabling while it is
301 // debugged.
302 SkASSERT(fPaths[i].isConvex());
bsalomon@google.com44d662b2013-08-15 20:34:45 +0000303#endif
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500304 canvas->drawPath(fPaths[i], paint);
305 canvas->restore();
306 }
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000307 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000308
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000309private:
310 typedef GM INHERITED;
311 SkTArray<SkPath> fPaths;
312};
313
314//////////////////////////////////////////////////////////////////////////////
315
Hal Canarye964c182019-01-23 10:22:01 -0500316DEF_GM( return new ConvexPathsGM; )
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000317
318}