blob: cca7fdc6f873c3659cb4f181ac045ff6d73c4813 [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"
Kevin Lubick2d86f6f2022-02-23 12:17:12 -050014#include "include/core/SkRRect.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040015#include "include/core/SkRect.h"
16#include "include/core/SkScalar.h"
17#include "include/core/SkSize.h"
18#include "include/core/SkString.h"
19#include "include/core/SkTypes.h"
Kevin Lubickdc6cc022023-01-13 11:24:27 -050020#include "include/private/base/SkTArray.h"
Kevin Lubick0d4d1142023-02-13 09:13:10 -050021#include "src/base/SkRandom.h"
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000022
Herb Derbyec96c212023-03-06 10:31:22 -050023using namespace skia_private;
24
Hal Canarybd865e22019-07-18 11:51:19 -040025namespace {
26
Jim Van Verth4cf8c752023-02-21 17:06:41 -050027class SkDoOnce {
reed@google.comd42e3f62012-03-30 20:04:21 +000028public:
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000029 SkDoOnce() { fDidOnce = false; }
Jim Van Verth4cf8c752023-02-21 17:06:41 -050030 // Make noncopyable
31 SkDoOnce(SkDoOnce&) = delete;
32 SkDoOnce& operator=(SkDoOnce&) = delete;
rmistry@google.comd6176b02012-08-23 18:14:13 +000033
reed@google.comd42e3f62012-03-30 20:04:21 +000034 bool needToDo() const { return !fDidOnce; }
35 bool alreadyDone() const { return fDidOnce; }
36 void accomplished() {
37 SkASSERT(!fDidOnce);
38 fDidOnce = true;
39 }
40
41private:
42 bool fDidOnce;
43};
44
Hal Canarybd865e22019-07-18 11:51:19 -040045class ConvexPathsGM : public skiagm::GM {
commit-bot@chromium.org2ab1ba02014-01-17 17:55:02 +000046 SkDoOnce fOnce;
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000047
Hal Canarybd865e22019-07-18 11:51:19 -040048 void onOnceBeforeDraw() override { this->setBGColor(0xFF000000); }
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000049
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000050 SkString getName() const override { return SkString("convexpaths"); }
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000051
Leandro Lovisolo8f023882023-08-15 21:13:52 +000052 SkISize getISize() override { return {1200, 1100}; }
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000053
54 void makePaths() {
reed@google.comd42e3f62012-03-30 20:04:21 +000055 if (fOnce.alreadyDone()) {
56 return;
57 }
58 fOnce.accomplished();
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +000059
Mike Reed15a54032020-08-16 11:15:41 -040060 SkPathBuilder b;
61 fPaths.push_back(b.moveTo(0, 0)
62 .quadTo(50, 100, 0, 100)
63 .lineTo(0, 0)
64 .detach());
bsalomon@google.com278dc692012-02-15 16:52:51 +000065
Mike Reed15a54032020-08-16 11:15:41 -040066 fPaths.push_back(b.moveTo(0, 50)
67 .quadTo(50, 0, 100, 50)
68 .quadTo(50, 100, 0, 50)
69 .detach());
bsalomon@google.com278dc692012-02-15 16:52:51 +000070
Mike Reed15a54032020-08-16 11:15:41 -040071 fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCW));
72 fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCCW));
73 fPaths.push_back(SkPath::Circle(50, 50, 50, SkPathDirection::kCW));
74 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 50, 100), SkPathDirection::kCW));
75 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 100, 5), SkPathDirection::kCCW));
76 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 1, 100), SkPathDirection::kCCW));
77 fPaths.push_back(SkPath::RRect(SkRRect::MakeRectXY({0, 0, 100, 100}, 40, 20),
78 SkPathDirection::kCW));
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000079
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000080 // large number of points
81 enum {
82 kLength = 100,
83 kPtsPerSide = (1 << 12),
84 };
Mike Reed15a54032020-08-16 11:15:41 -040085 b.moveTo(0, 0);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000086 for (int i = 1; i < kPtsPerSide; ++i) { // skip the first point due to moveTo.
Mike Reed15a54032020-08-16 11:15:41 -040087 b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000088 }
89 for (int i = 0; i < kPtsPerSide; ++i) {
Mike Reed15a54032020-08-16 11:15:41 -040090 b.lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000091 }
92 for (int i = kPtsPerSide; i > 0; --i) {
Mike Reed15a54032020-08-16 11:15:41 -040093 b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000094 }
95 for (int i = kPtsPerSide; i > 0; --i) {
Mike Reed15a54032020-08-16 11:15:41 -040096 b.lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide);
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000097 }
Mike Reed15a54032020-08-16 11:15:41 -040098 fPaths.push_back(b.detach());
bsalomon@google.com7d9ffc82013-05-14 14:20:28 +000099
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000100 // shallow diagonals
Mike Reed15a54032020-08-16 11:15:41 -0400101 fPaths.push_back(SkPath::Polygon({{0,0}, {100,1}, {98,100}, {3,96}}, false));
bsalomon@google.com9732f622012-01-31 15:19:21 +0000102
Mike Reed15a54032020-08-16 11:15:41 -0400103 fPaths.push_back(b.arcTo(SkRect::MakeXYWH(0, 0, 50, 100), 25, 130, false)
104 .detach());
rmistry@google.comd6176b02012-08-23 18:14:13 +0000105
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000106 // cubics
Mike Reed15a54032020-08-16 11:15:41 -0400107 fPaths.push_back(b.cubicTo( 1, 1, 10, 90, 0, 100).detach());
108 fPaths.push_back(b.cubicTo(100, 50, 20, 100, 0, 0).detach());
rmistry@google.comd6176b02012-08-23 18:14:13 +0000109
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000110 // path that has a cubic with a repeated first control point and
111 // a repeated last control point.
Mike Reed15a54032020-08-16 11:15:41 -0400112 fPaths.push_back(b.moveTo(10, 10)
113 .cubicTo(10, 10, 10, 0, 20, 0)
114 .lineTo(40, 0)
115 .cubicTo(40, 0, 50, 0, 50, 10)
116 .detach());
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000117
118 // path that has two cubics with repeated middle control points.
Mike Reed15a54032020-08-16 11:15:41 -0400119 fPaths.push_back(b.moveTo(10, 10)
120 .cubicTo(10, 0, 10, 0, 20, 0)
121 .lineTo(40, 0)
122 .cubicTo(50, 0, 50, 0, 50, 10)
123 .detach());
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000124
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000125 // cubic where last three points are almost a line
Mike Reed15a54032020-08-16 11:15:41 -0400126 fPaths.push_back(b.moveTo(0, 228.0f/8)
127 .cubicTo( 628.0f/ 8, 82.0f/8,
128 1255.0f/ 8, 141.0f/8,
129 1883.0f/ 8, 202.0f/8)
130 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000131
132 // flat cubic where the at end point tangents both point outward.
Mike Reed15a54032020-08-16 11:15:41 -0400133 fPaths.push_back(b.moveTo(10, 0)
134 .cubicTo(0, 1, 30, 1, 20, 0)
135 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000136
137 // flat cubic where initial tangent is in, end tangent out
Mike Reed15a54032020-08-16 11:15:41 -0400138 fPaths.push_back(b.moveTo(0, 0)
139 .cubicTo(10, 1, 30, 1, 20, 0)
140 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000141
142 // flat cubic where initial tangent is out, end tangent in
Mike Reed15a54032020-08-16 11:15:41 -0400143 fPaths.push_back(b.moveTo(10, 0)
144 .cubicTo(0, 1, 20, 1, 30, 0)
145 .detach());
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000146
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000147 // triangle where one edge is a degenerate quad
Mike Reed15a54032020-08-16 11:15:41 -0400148 fPaths.push_back(b.moveTo(8.59375f, 45)
149 .quadTo(16.9921875f, 45,
150 31.25f, 45)
151 .lineTo(100, 100)
152 .lineTo(8.59375f, 45)
153 .detach());
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000154
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000155 // triangle where one edge is a quad with a repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400156 fPaths.push_back(b.moveTo(0, 25)
157 .lineTo(50, 0)
158 .quadTo(50, 50, 50, 50)
159 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000160
161 // triangle where one edge is a cubic with a 2x repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400162 fPaths.push_back(b.moveTo(0, 25)
163 .lineTo(50, 0)
164 .cubicTo(50, 0, 50, 50, 50, 50)
165 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000166
167 // triangle where one edge is a quad with a nearly repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400168 fPaths.push_back(b.moveTo(0, 25)
169 .lineTo(50, 0)
170 .quadTo(50, 49.95f, 50, 50)
171 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000172
173 // triangle where one edge is a cubic with a 3x nearly repeated point
Mike Reed15a54032020-08-16 11:15:41 -0400174 fPaths.push_back(b.moveTo(0, 25)
175 .lineTo(50, 0)
176 .cubicTo(50, 49.95f, 50, 49.97f, 50, 50)
177 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000178
179 // triangle where there is a point degenerate cubic at one corner
Mike Reed15a54032020-08-16 11:15:41 -0400180 fPaths.push_back(b.moveTo(0, 25)
181 .lineTo(50, 0)
182 .lineTo(50, 50)
183 .cubicTo(50, 50, 50, 50, 50, 50)
184 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000185
186 // point line
Mike Reed15a54032020-08-16 11:15:41 -0400187 fPaths.push_back(SkPath::Line({50, 50}, {50, 50}));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000188
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000189 // point quad
Mike Reed15a54032020-08-16 11:15:41 -0400190 fPaths.push_back(b.moveTo(50, 50)
191 .quadTo(50, 50, 50, 50)
192 .detach());
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000193
194 // point cubic
Mike Reed15a54032020-08-16 11:15:41 -0400195 fPaths.push_back(b.moveTo(50, 50)
196 .cubicTo(50, 50, 50, 50, 50, 50)
197 .detach());
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000198
bsalomon@google.com9732f622012-01-31 15:19:21 +0000199 // moveTo only paths
Mike Reed15a54032020-08-16 11:15:41 -0400200 fPaths.push_back(b.moveTo(0, 0)
201 .moveTo(0, 0)
202 .moveTo(1, 1)
203 .moveTo(1, 1)
204 .moveTo(10, 10)
205 .detach());
bsalomon@google.com9732f622012-01-31 15:19:21 +0000206
Mike Reed15a54032020-08-16 11:15:41 -0400207 fPaths.push_back(b.moveTo(0, 0)
208 .moveTo(0, 0)
209 .detach());
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000210
211 // line degenerate
Mike Reed15a54032020-08-16 11:15:41 -0400212 fPaths.push_back(b.lineTo(100, 100).detach());
213 fPaths.push_back(b.quadTo(100, 100, 0, 0).detach());
214 fPaths.push_back(b.quadTo(100, 100, 50, 50).detach());
215 fPaths.push_back(b.quadTo(50, 50, 100, 100).detach());
216 fPaths.push_back(b.cubicTo(0, 0, 0, 0, 100, 100).detach());
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000217
Brian Salomon73c6c9d2019-03-29 15:41:27 -0400218 // skbug.com/8928
Mike Reed15a54032020-08-16 11:15:41 -0400219 fPaths.push_back(b.moveTo(16.875f, 192.594f)
220 .cubicTo(45.625f, 192.594f, 74.375f, 192.594f, 103.125f, 192.594f)
221 .cubicTo(88.75f, 167.708f, 74.375f, 142.823f, 60, 117.938f)
222 .cubicTo(45.625f, 142.823f, 31.25f, 167.708f, 16.875f, 192.594f)
223 .close()
224 .detach());
Brian Salomon73c6c9d2019-03-29 15:41:27 -0400225 SkMatrix m;
226 m.setAll(0.1f, 0, -1, 0, 0.115207f, -2.64977f, 0, 0, 1);
227 fPaths.back().transform(m);
228
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000229 // small circle. This is listed last so that it has device coords far
230 // from the origin (small area relative to x,y values).
Mike Reed92f6eb12020-08-25 11:48:41 -0400231 fPaths.push_back(SkPath::Circle(0, 0, 1.2f));
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000232 }
233
Hal Canarybd865e22019-07-18 11:51:19 -0400234 void onDraw(SkCanvas* canvas) override {
reed@google.comd42e3f62012-03-30 20:04:21 +0000235 this->makePaths();
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000236
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500237 SkPaint paint;
238 paint.setAntiAlias(true);
239 SkRandom rand;
Mike Reed15a54032020-08-16 11:15:41 -0400240 canvas->translate(20, 20);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000241
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500242 // As we've added more paths this has gotten pretty big. Scale the whole thing down.
Mike Reed15a54032020-08-16 11:15:41 -0400243 canvas->scale(2.0f/3, 2.0f/3);
commit-bot@chromium.orgfdfbb9d2013-08-15 18:16:27 +0000244
Herb Derbyffacce52022-11-09 10:51:34 -0500245 for (int i = 0; i < fPaths.size(); ++i) {
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500246 canvas->save();
247 // position the path, and make it at off-integer coords.
Mike Reed15a54032020-08-16 11:15:41 -0400248 canvas->translate(200.0f * (i % 5) + 1.0f/10,
249 200.0f * (i / 5) + 9.0f/10);
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500250 SkColor color = rand.nextU();
251 color |= 0xff000000;
252 paint.setColor(color);
253#if 0 // This hitting on 32bit Linux builds for some paths. Temporarily disabling while it is
254 // debugged.
255 SkASSERT(fPaths[i].isConvex());
bsalomon@google.com44d662b2013-08-15 20:34:45 +0000256#endif
Jim Van Verthf9e678d2017-02-15 15:46:52 -0500257 canvas->drawPath(fPaths[i], paint);
258 canvas->restore();
259 }
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000260 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000261
Herb Derbyec96c212023-03-06 10:31:22 -0500262 TArray<SkPath> fPaths;
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000263};
Hal Canarybd865e22019-07-18 11:51:19 -0400264} // namespace
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000265
Hal Canarye964c182019-01-23 10:22:01 -0500266DEF_GM( return new ConvexPathsGM; )