blob: 5af843f0166006444bcaf3188eebbe5c4a472d88 [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();
bsalomon@google.com278dc692012-02-15 16:52:51 +000051 // CW
52 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
57 // CCW
58 fPaths.push_back().moveTo(0, 0);
59 fPaths.back().lineTo(0, 100 * SK_Scalar1);
60 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
61 0, 0);
62
63 // CW
64 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
65 fPaths.back().quadTo(50 * SK_Scalar1, 0,
66 100 * SK_Scalar1, 50 * SK_Scalar1);
67 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
68 0, 50 * SK_Scalar1);
69
70 // CCW
71 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
72 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
73 100 * SK_Scalar1, 50 * SK_Scalar1);
74 fPaths.back().quadTo(50 * SK_Scalar1, 0,
75 0, 50 * SK_Scalar1);
76
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000077 fPaths.push_back().addRect(0, 0,
78 100 * SK_Scalar1, 100 * SK_Scalar1,
79 SkPath::kCW_Direction);
80
81 fPaths.push_back().addRect(0, 0,
82 100 * SK_Scalar1, 100 * SK_Scalar1,
83 SkPath::kCCW_Direction);
84
85 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
86 50 * SK_Scalar1, SkPath::kCW_Direction);
87
88 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
89 40 * SK_Scalar1, SkPath::kCCW_Direction);
90
91 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
92 50 * SK_Scalar1,
93 100 * SK_Scalar1),
94 SkPath::kCW_Direction);
95
96 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
97 100 * SK_Scalar1,
98 50 * SK_Scalar1),
99 SkPath::kCCW_Direction);
100
101 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
102 100 * SK_Scalar1,
103 5 * SK_Scalar1),
104 SkPath::kCCW_Direction);
105
106 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
107 SK_Scalar1,
108 100 * SK_Scalar1),
109 SkPath::kCCW_Direction);
110
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000111 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
112 SK_Scalar1 * 100,
113 SK_Scalar1 * 100),
114 40 * SK_Scalar1, 20 * SK_Scalar1,
115 SkPath::kCW_Direction);
116
117 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
118 SK_Scalar1 * 100,
119 SK_Scalar1 * 100),
120 20 * SK_Scalar1, 40 * SK_Scalar1,
121 SkPath::kCCW_Direction);
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000122
123 // shallow diagonals
124 fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1);
125 fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1);
126 fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1);
bsalomon@google.com9732f622012-01-31 15:19:21 +0000127
rmistry@google.comd6176b02012-08-23 18:14:13 +0000128
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000129 //It turns out arcTos are not automatically marked as convex and they
130 //may in fact be ever so slightly concave.
131 //fPaths.push_back().arcTo(SkRect::MakeXYWH(0, 0,
132 // 50 * SK_Scalar1,
133 // 100 * SK_Scalar1),
134 // 25 * SK_Scalar1, 130 * SK_Scalar1, false);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000135
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000136 // cubics
137 fPaths.push_back().cubicTo( 1 * SK_Scalar1, 1 * SK_Scalar1,
138 10 * SK_Scalar1, 90 * SK_Scalar1,
139 0 * SK_Scalar1, 100 * SK_Scalar1);
140 fPaths.push_back().cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
141 20 * SK_Scalar1, 100 * SK_Scalar1,
142 0 * SK_Scalar1, 0 * SK_Scalar1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000143
bsalomon@google.coma51ab842012-07-10 19:53:34 +0000144 // path that has a cubic with a repeated first control point and
145 // a repeated last control point.
146 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
147 fPaths.back().cubicTo(10 * SK_Scalar1, 10 * SK_Scalar1,
148 10 * SK_Scalar1, 0,
149 20 * SK_Scalar1, 0);
150 fPaths.back().lineTo(40 * SK_Scalar1, 0);
151 fPaths.back().cubicTo(40 * SK_Scalar1, 0,
152 50 * SK_Scalar1, 0,
153 50 * SK_Scalar1, 10 * SK_Scalar1);
154
155 // path that has two cubics with repeated middle control points.
156 fPaths.push_back().moveTo(SK_Scalar1 * 10, SK_Scalar1 * 10);
157 fPaths.back().cubicTo(10 * SK_Scalar1, 0,
158 10 * SK_Scalar1, 0,
159 20 * SK_Scalar1, 0);
160 fPaths.back().lineTo(40 * SK_Scalar1, 0);
161 fPaths.back().cubicTo(50 * SK_Scalar1, 0,
162 50 * SK_Scalar1, 0,
163 50 * SK_Scalar1, 10 * SK_Scalar1);
164
bsalomon@google.com54ad8512012-08-02 14:55:45 +0000165 // cubic where last three points are almost a line
166 fPaths.push_back().moveTo(0, 228 * SK_Scalar1 / 8);
167 fPaths.back().cubicTo(628 * SK_Scalar1 / 8, 82 * SK_Scalar1 / 8,
168 1255 * SK_Scalar1 / 8, 141 * SK_Scalar1 / 8,
169 1883 * SK_Scalar1 / 8, 202 * SK_Scalar1 / 8);
170
171 // flat cubic where the at end point tangents both point outward.
172 fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
173 fPaths.back().cubicTo(0, SK_Scalar1,
174 30 * SK_Scalar1, SK_Scalar1,
175 20 * SK_Scalar1, 0);
176
177 // flat cubic where initial tangent is in, end tangent out
178 fPaths.push_back().moveTo(0, 0 * SK_Scalar1);
179 fPaths.back().cubicTo(10 * SK_Scalar1, SK_Scalar1,
180 30 * SK_Scalar1, SK_Scalar1,
181 20 * SK_Scalar1, 0);
182
183 // flat cubic where initial tangent is out, end tangent in
184 fPaths.push_back().moveTo(10 * SK_Scalar1, 0);
185 fPaths.back().cubicTo(0, SK_Scalar1,
186 20 * SK_Scalar1, SK_Scalar1,
187 30 * SK_Scalar1, 0);
188
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000189 // triangle where one edge is a degenerate quad
190 fPaths.push_back().moveTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1);
191 fPaths.back().quadTo(SkFloatToScalar(16.9921875f), 45 * SK_Scalar1,
192 SkFloatToScalar(31.25f), 45 * SK_Scalar1);
193 fPaths.back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
194 fPaths.back().lineTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1);
195
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000196 // point degenerate
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000197 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
198 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000199
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000200 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
201 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
202 50 * SK_Scalar1, 50 * SK_Scalar1);
203 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
204 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
205 50 * SK_Scalar1, 50 * SK_Scalar1,
206 50 * SK_Scalar1, 50 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000207
bsalomon@google.com9732f622012-01-31 15:19:21 +0000208 // moveTo only paths
209 fPaths.push_back().moveTo(0, 0);
210 fPaths.back().moveTo(0, 0);
211 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
212 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
213 fPaths.back().moveTo(10 * SK_Scalar1, 10 * SK_Scalar1);
214
215 fPaths.push_back().moveTo(0, 0);
216 fPaths.back().moveTo(0, 0);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000217
218 // line degenerate
219 fPaths.push_back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
220 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 0, 0);
221 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1,
222 50 * SK_Scalar1, 50 * SK_Scalar1);
223 fPaths.push_back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
224 100 * SK_Scalar1, 100 * SK_Scalar1);
225 fPaths.push_back().cubicTo(0, 0,
226 0, 0,
227 100 * SK_Scalar1, 100 * SK_Scalar1);
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000228
229 // small circle. This is listed last so that it has device coords far
230 // from the origin (small area relative to x,y values).
231 fPaths.push_back().addCircle(0, 0, SkFloatToScalar(0.8f));
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000232 }
233
234 virtual void onDraw(SkCanvas* canvas) {
reed@google.comd42e3f62012-03-30 20:04:21 +0000235 this->makePaths();
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000236
237 SkPaint paint;
238 paint.setAntiAlias(true);
239 SkRandom rand;
240 canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000241 for (int i = 0; i < fPaths.count(); ++i) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000242 canvas->save();
243 // position the path, and make it at off-integer coords.
244 canvas->translate(SK_Scalar1 * 200 * (i % 5) + SK_Scalar1 / 4,
245 SK_Scalar1 * 200 * (i / 5) + 3 * SK_Scalar1 / 4);
246 SkColor color = rand.nextU();
247 color |= 0xff000000;
248 paint.setColor(color);
249 SkASSERT(fPaths[i].isConvex());
250 canvas->drawPath(fPaths[i], paint);
251 canvas->restore();
252 }
253 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000254
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000255private:
256 typedef GM INHERITED;
257 SkTArray<SkPath> fPaths;
258};
259
260//////////////////////////////////////////////////////////////////////////////
261
262static GM* MyFactory(void*) { return new ConvexPathsGM; }
263static GMRegistry reg(MyFactory);
264
265}
266