blob: 18f1cd27c57dd13015b6b4440e540884efe80471 [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 Reed15a54032020-08-16 11:15:41 -040013#include "include/core/SkPathBuilder.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
Hal Canarybd865e22019-07-18 11:51:19 -040023namespace {
24
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000025class SkDoOnce : SkNoncopyable {
reed@google.comd42e3f62012-03-30 20:04:21 +000026public:
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000027 SkDoOnce() { fDidOnce = false; }
rmistry@google.comd6176b02012-08-23 18:14:13 +000028
reed@google.comd42e3f62012-03-30 20:04:21 +000029 bool needToDo() const { return !fDidOnce; }
30 bool alreadyDone() const { return fDidOnce; }
31 void accomplished() {
32 SkASSERT(!fDidOnce);
33 fDidOnce = true;
34 }
35
36private:
37 bool fDidOnce;
38};
39
Hal Canarybd865e22019-07-18 11:51:19 -040040class ConvexPathsGM : public skiagm::GM {
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000041 SkDoOnce fOnce;
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000042
Hal Canarybd865e22019-07-18 11:51:19 -040043 void onOnceBeforeDraw() override { this->setBGColor(0xFF000000); }
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000044
Hal Canarybd865e22019-07-18 11:51:19 -040045 SkString onShortName() override { return SkString("convexpaths"); }
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000046
47
Hal Canarybd865e22019-07-18 11:51:19 -040048 SkISize onISize() override { return {1200, 1100}; }
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000049
50 void makePaths() {
reed@google.comd42e3f62012-03-30 20:04:21 +000051 if (fOnce.alreadyDone()) {
52 return;
53 }
54 fOnce.accomplished();
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +000055
Mike Reed15a54032020-08-16 11:15:41 -040056 SkPathBuilder b;
57 fPaths.push_back(b.moveTo(0, 0)
58 .quadTo(50, 100, 0, 100)
59 .lineTo(0, 0)
60 .detach());
bsalomon@google.com278dc692012-02-15 16:52:51 +000061
Mike Reed15a54032020-08-16 11:15:41 -040062 fPaths.push_back(b.moveTo(0, 50)
63 .quadTo(50, 0, 100, 50)
64 .quadTo(50, 100, 0, 50)
65 .detach());
bsalomon@google.com278dc692012-02-15 16:52:51 +000066
Mike Reed15a54032020-08-16 11:15:41 -040067 fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCW));
68 fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCCW));
69 fPaths.push_back(SkPath::Circle(50, 50, 50, SkPathDirection::kCW));
70 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 50, 100), SkPathDirection::kCW));
71 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 100, 5), SkPathDirection::kCCW));
72 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 1, 100), SkPathDirection::kCCW));
73 fPaths.push_back(SkPath::RRect(SkRRect::MakeRectXY({0, 0, 100, 100}, 40, 20),
74 SkPathDirection::kCW));
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000075
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000076 // large number of points
77 enum {
78 kLength = 100,
79 kPtsPerSide = (1 << 12),
80 };
Mike Reed15a54032020-08-16 11:15:41 -040081 b.moveTo(0, 0);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000082 for (int i = 1; i < kPtsPerSide; ++i) { // skip the first point due to moveTo.
Mike Reed15a54032020-08-16 11:15:41 -040083 b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000084 }
85 for (int i = 0; i < kPtsPerSide; ++i) {
Mike Reed15a54032020-08-16 11:15:41 -040086 b.lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000087 }
88 for (int i = kPtsPerSide; i > 0; --i) {
Mike Reed15a54032020-08-16 11:15:41 -040089 b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000090 }
91 for (int i = kPtsPerSide; i > 0; --i) {
Mike Reed15a54032020-08-16 11:15:41 -040092 b.lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000093 }
Mike Reed15a54032020-08-16 11:15:41 -040094 fPaths.push_back(b.detach());
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000095
bsalomon@google.com72b55be2012-01-26 20:33:19 +000096 // shallow diagonals
Mike Reed15a54032020-08-16 11:15:41 -040097 fPaths.push_back(SkPath::Polygon({{0,0}, {100,1}, {98,100}, {3,96}}, false));
bsalomon@google.com9732f622012-01-31 15:19:21 +000098
Mike Reed15a54032020-08-16 11:15:41 -040099 fPaths.push_back(b.arcTo(SkRect::MakeXYWH(0, 0, 50, 100), 25, 130, false)
100 .detach());
rmistry@google.comd6176b02012-08-23 18:14:13 +0000101
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000102 // cubics
Mike Reed15a54032020-08-16 11:15:41 -0400103 fPaths.push_back(b.cubicTo( 1, 1, 10, 90, 0, 100).detach());
104 fPaths.push_back(b.cubicTo(100, 50, 20, 100, 0, 0).detach());
rmistry@google.comd6176b02012-08-23 18:14:13 +0000105
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000106 // path that has a cubic with a repeated first control point and
107 // a repeated last control point.
Mike Reed15a54032020-08-16 11:15:41 -0400108 fPaths.push_back(b.moveTo(10, 10)
109 .cubicTo(10, 10, 10, 0, 20, 0)
110 .lineTo(40, 0)
111 .cubicTo(40, 0, 50, 0, 50, 10)
112 .detach());
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000113
114 // path that has two cubics with repeated middle control points.
Mike Reed15a54032020-08-16 11:15:41 -0400115 fPaths.push_back(b.moveTo(10, 10)
116 .cubicTo(10, 0, 10, 0, 20, 0)
117 .lineTo(40, 0)
118 .cubicTo(50, 0, 50, 0, 50, 10)
119 .detach());
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000120
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000121 // cubic where last three points are almost a line
Mike Reed15a54032020-08-16 11:15:41 -0400122 fPaths.push_back(b.moveTo(0, 228.0f/8)
123 .cubicTo( 628.0f/ 8, 82.0f/8,
124 1255.0f/ 8, 141.0f/8,
125 1883.0f/ 8, 202.0f/8)
126 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000127
128 // flat cubic where the at end point tangents both point outward.
Mike Reed15a54032020-08-16 11:15:41 -0400129 fPaths.push_back(b.moveTo(10, 0)
130 .cubicTo(0, 1, 30, 1, 20, 0)
131 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000132
133 // flat cubic where initial tangent is in, end tangent out
Mike Reed15a54032020-08-16 11:15:41 -0400134 fPaths.push_back(b.moveTo(0, 0)
135 .cubicTo(10, 1, 30, 1, 20, 0)
136 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000137
138 // flat cubic where initial tangent is out, end tangent in
Mike Reed15a54032020-08-16 11:15:41 -0400139 fPaths.push_back(b.moveTo(10, 0)
140 .cubicTo(0, 1, 20, 1, 30, 0)
141 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000142
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000143 // triangle where one edge is a degenerate quad
Mike Reed15a54032020-08-16 11:15:41 -0400144 fPaths.push_back(b.moveTo(8.59375f, 45)
145 .quadTo(16.9921875f, 45,
146 31.25f, 45)
147 .lineTo(100, 100)
148 .lineTo(8.59375f, 45)
149 .detach());
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000150
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000151 // triangle where one edge is a quad with a repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400152 fPaths.push_back(b.moveTo(0, 25)
153 .lineTo(50, 0)
154 .quadTo(50, 50, 50, 50)
155 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000156
157 // triangle where one edge is a cubic with a 2x repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400158 fPaths.push_back(b.moveTo(0, 25)
159 .lineTo(50, 0)
160 .cubicTo(50, 0, 50, 50, 50, 50)
161 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000162
163 // triangle where one edge is a quad with a nearly repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400164 fPaths.push_back(b.moveTo(0, 25)
165 .lineTo(50, 0)
166 .quadTo(50, 49.95f, 50, 50)
167 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000168
169 // triangle where one edge is a cubic with a 3x nearly repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400170 fPaths.push_back(b.moveTo(0, 25)
171 .lineTo(50, 0)
172 .cubicTo(50, 49.95f, 50, 49.97f, 50, 50)
173 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000174
175 // triangle where there is a point degenerate cubic at one corner
Mike Reed15a54032020-08-16 11:15:41 -0400176 fPaths.push_back(b.moveTo(0, 25)
177 .lineTo(50, 0)
178 .lineTo(50, 50)
179 .cubicTo(50, 50, 50, 50, 50, 50)
180 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000181
182 // point line
Mike Reed15a54032020-08-16 11:15:41 -0400183 fPaths.push_back(SkPath::Line({50, 50}, {50, 50}));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000184
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000185 // point quad
Mike Reed15a54032020-08-16 11:15:41 -0400186 fPaths.push_back(b.moveTo(50, 50)
187 .quadTo(50, 50, 50, 50)
188 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000189
190 // point cubic
Mike Reed15a54032020-08-16 11:15:41 -0400191 fPaths.push_back(b.moveTo(50, 50)
192 .cubicTo(50, 50, 50, 50, 50, 50)
193 .detach());
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000194
bsalomon@google.com9732f622012-01-31 15:19:21 +0000195 // moveTo only paths
Mike Reed15a54032020-08-16 11:15:41 -0400196 fPaths.push_back(b.moveTo(0, 0)
197 .moveTo(0, 0)
198 .moveTo(1, 1)
199 .moveTo(1, 1)
200 .moveTo(10, 10)
201 .detach());
bsalomon@google.com9732f622012-01-31 15:19:21 +0000202
Mike Reed15a54032020-08-16 11:15:41 -0400203 fPaths.push_back(b.moveTo(0, 0)
204 .moveTo(0, 0)
205 .detach());
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000206
207 // line degenerate
Mike Reed15a54032020-08-16 11:15:41 -0400208 fPaths.push_back(b.lineTo(100, 100).detach());
209 fPaths.push_back(b.quadTo(100, 100, 0, 0).detach());
210 fPaths.push_back(b.quadTo(100, 100, 50, 50).detach());
211 fPaths.push_back(b.quadTo(50, 50, 100, 100).detach());
212 fPaths.push_back(b.cubicTo(0, 0, 0, 0, 100, 100).detach());
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000213
Brian Salomon73c6c9d2019-03-29 15:41:27 -0400214 // skbug.com/8928
Mike Reed15a54032020-08-16 11:15:41 -0400215 fPaths.push_back(b.moveTo(16.875f, 192.594f)
216 .cubicTo(45.625f, 192.594f, 74.375f, 192.594f, 103.125f, 192.594f)
217 .cubicTo(88.75f, 167.708f, 74.375f, 142.823f, 60, 117.938f)
218 .cubicTo(45.625f, 142.823f, 31.25f, 167.708f, 16.875f, 192.594f)
219 .close()
220 .detach());
Brian Salomon73c6c9d2019-03-29 15:41:27 -0400221 SkMatrix m;
222 m.setAll(0.1f, 0, -1, 0, 0.115207f, -2.64977f, 0, 0, 1);
223 fPaths.back().transform(m);
224
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000225 // small circle. This is listed last so that it has device coords far
226 // from the origin (small area relative to x,y values).
Mike Reed92f6eb12020-08-25 11:48:41 -0400227 fPaths.push_back(SkPath::Circle(0, 0, 1.2f));
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000228 }
229
Hal Canarybd865e22019-07-18 11:51:19 -0400230 void onDraw(SkCanvas* canvas) override {
reed@google.comd42e3f62012-03-30 20:04:21 +0000231 this->makePaths();
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000232
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500233 SkPaint paint;
234 paint.setAntiAlias(true);
235 SkRandom rand;
Mike Reed15a54032020-08-16 11:15:41 -0400236 canvas->translate(20, 20);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000237
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500238 // As we've added more paths this has gotten pretty big. Scale the whole thing down.
Mike Reed15a54032020-08-16 11:15:41 -0400239 canvas->scale(2.0f/3, 2.0f/3);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000240
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500241 for (int i = 0; i < fPaths.count(); ++i) {
242 canvas->save();
243 // position the path, and make it at off-integer coords.
Mike Reed15a54032020-08-16 11:15:41 -0400244 canvas->translate(200.0f * (i % 5) + 1.0f/10,
245 200.0f * (i / 5) + 9.0f/10);
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500246 SkColor color = rand.nextU();
247 color |= 0xff000000;
248 paint.setColor(color);
249#if 0 // This hitting on 32bit Linux builds for some paths. Temporarily disabling while it is
250 // debugged.
251 SkASSERT(fPaths[i].isConvex());
bsalomon@google.com44d662b2013-08-15 20:34:45 +0000252#endif
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500253 canvas->drawPath(fPaths[i], paint);
254 canvas->restore();
255 }
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000256 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000257
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000258 SkTArray<SkPath> fPaths;
259};
Hal Canarybd865e22019-07-18 11:51:19 -0400260} // namespace
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000261
Hal Canarye964c182019-01-23 10:22:01 -0500262DEF_GM( return new ConvexPathsGM; )