blob: c793266b17ebef674fa80977f0beaa9d99959d5e [file] [log] [blame]
reed@android.com3abec1d2009-03-02 05:36:20 +00001#include "Test.h"
2#include "SkPath.h"
reed@google.com04863fa2011-05-15 04:08:24 +00003#include "SkParse.h"
reed@android.com60bc6d52010-02-11 11:09:39 +00004#include "SkSize.h"
reed@android.com3abec1d2009-03-02 05:36:20 +00005
bsalomon@google.comb3b8dfa2011-07-13 17:44:36 +00006static void check_close(skiatest::Reporter* reporter, const SkPath& path) {
7 for (int i = 0; i < 2; ++i) {
8 SkPath::Iter iter(path, (bool)i);
9 SkPoint mv;
10 SkPoint pts[4];
11 SkPath::Verb v;
12 int nMT = 0;
13 int nCL = 0;
14 while (SkPath::kDone_Verb != (v = iter.next(pts))) {
15 switch (v) {
16 case SkPath::kMove_Verb:
17 mv = pts[0];
18 ++nMT;
19 break;
20 case SkPath::kClose_Verb:
21 REPORTER_ASSERT(reporter, mv == pts[0]);
22 ++nCL;
23 break;
24 default:
25 break;
26 }
27 }
28 // if we force a close on the interator we should have a close
29 // for every moveTo
30 REPORTER_ASSERT(reporter, !i || nMT == nCL);
31 }
32}
33
34static void test_close(skiatest::Reporter* reporter) {
35 SkPath closePt;
36 closePt.moveTo(0, 0);
37 closePt.close();
38 check_close(reporter, closePt);
39
40 SkPath openPt;
41 openPt.moveTo(0, 0);
42 check_close(reporter, openPt);
43
44 SkPath empty;
45 check_close(reporter, empty);
46 empty.close();
47 check_close(reporter, empty);
48
49 SkPath rect;
50 rect.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
51 check_close(reporter, rect);
52 rect.close();
53 check_close(reporter, rect);
54
55 SkPath quad;
56 quad.quadTo(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
57 check_close(reporter, quad);
58 quad.close();
59 check_close(reporter, quad);
60
61 SkPath cubic;
62 quad.cubicTo(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1,
63 10*SK_Scalar1, 20 * SK_Scalar1, 20*SK_Scalar1);
64 check_close(reporter, cubic);
65 cubic.close();
66 check_close(reporter, cubic);
67
68 SkPath line;
69 line.moveTo(SK_Scalar1, SK_Scalar1);
70 line.lineTo(10 * SK_Scalar1, 10*SK_Scalar1);
71 check_close(reporter, line);
72 line.close();
73 check_close(reporter, line);
74
75 SkPath rect2;
76 rect2.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
77 rect2.close();
78 rect2.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
79 check_close(reporter, rect2);
80 rect2.close();
81 check_close(reporter, rect2);
82
83 SkPath oval3;
84 oval3.addOval(SkRect::MakeWH(SK_Scalar1*100,SK_Scalar1*100));
85 oval3.close();
86 oval3.addOval(SkRect::MakeWH(SK_Scalar1*200,SK_Scalar1*200));
87 check_close(reporter, oval3);
88 oval3.close();
89 check_close(reporter, oval3);
90
91 SkPath moves;
92 moves.moveTo(SK_Scalar1, SK_Scalar1);
93 moves.moveTo(5 * SK_Scalar1, SK_Scalar1);
94 moves.moveTo(SK_Scalar1, 10 * SK_Scalar1);
95 moves.moveTo(10 *SK_Scalar1, SK_Scalar1);
96 check_close(reporter, moves);
97}
98
reed@google.com7c424812011-05-15 04:38:34 +000099static void check_convexity(skiatest::Reporter* reporter, const SkPath& path,
100 SkPath::Convexity expected) {
101 SkPath::Convexity c = SkPath::ComputeConvexity(path);
102 REPORTER_ASSERT(reporter, c == expected);
103}
104
105static void test_convexity2(skiatest::Reporter* reporter) {
106 SkPath pt;
107 pt.moveTo(0, 0);
108 pt.close();
reed@google.comb54455e2011-05-16 14:16:04 +0000109 check_convexity(reporter, pt, SkPath::kConvex_Convexity);
reed@google.com7c424812011-05-15 04:38:34 +0000110
111 SkPath line;
112 line.moveTo(12, 20);
113 line.lineTo(-12, -20);
114 line.close();
reed@google.comb54455e2011-05-16 14:16:04 +0000115 check_convexity(reporter, pt, SkPath::kConvex_Convexity);
reed@google.com7c424812011-05-15 04:38:34 +0000116
117 SkPath triLeft;
118 triLeft.moveTo(0, 0);
119 triLeft.lineTo(1, 0);
120 triLeft.lineTo(1, 1);
121 triLeft.close();
122 check_convexity(reporter, triLeft, SkPath::kConvex_Convexity);
123
124 SkPath triRight;
125 triRight.moveTo(0, 0);
126 triRight.lineTo(-1, 0);
127 triRight.lineTo(1, 1);
128 triRight.close();
129 check_convexity(reporter, triRight, SkPath::kConvex_Convexity);
130
131 SkPath square;
132 square.moveTo(0, 0);
133 square.lineTo(1, 0);
134 square.lineTo(1, 1);
135 square.lineTo(0, 1);
136 square.close();
137 check_convexity(reporter, square, SkPath::kConvex_Convexity);
138
139 SkPath redundantSquare;
140 redundantSquare.moveTo(0, 0);
141 redundantSquare.lineTo(0, 0);
142 redundantSquare.lineTo(0, 0);
143 redundantSquare.lineTo(1, 0);
144 redundantSquare.lineTo(1, 0);
145 redundantSquare.lineTo(1, 0);
146 redundantSquare.lineTo(1, 1);
147 redundantSquare.lineTo(1, 1);
148 redundantSquare.lineTo(1, 1);
149 redundantSquare.lineTo(0, 1);
150 redundantSquare.lineTo(0, 1);
151 redundantSquare.lineTo(0, 1);
152 redundantSquare.close();
153 check_convexity(reporter, redundantSquare, SkPath::kConvex_Convexity);
154
155 SkPath bowTie;
156 bowTie.moveTo(0, 0);
157 bowTie.lineTo(0, 0);
158 bowTie.lineTo(0, 0);
159 bowTie.lineTo(1, 1);
160 bowTie.lineTo(1, 1);
161 bowTie.lineTo(1, 1);
162 bowTie.lineTo(1, 0);
163 bowTie.lineTo(1, 0);
164 bowTie.lineTo(1, 0);
165 bowTie.lineTo(0, 1);
166 bowTie.lineTo(0, 1);
167 bowTie.lineTo(0, 1);
168 bowTie.close();
169 check_convexity(reporter, bowTie, SkPath::kConcave_Convexity);
170
171 SkPath spiral;
172 spiral.moveTo(0, 0);
epoger@google.com2047f002011-05-17 17:36:59 +0000173 spiral.lineTo(100, 0);
174 spiral.lineTo(100, 100);
175 spiral.lineTo(0, 100);
176 spiral.lineTo(0, 50);
177 spiral.lineTo(50, 50);
178 spiral.lineTo(50, 75);
reed@google.com7c424812011-05-15 04:38:34 +0000179 spiral.close();
reed@google.com85b6e392011-05-15 20:25:17 +0000180 check_convexity(reporter, spiral, SkPath::kConcave_Convexity);
reed@google.com7c424812011-05-15 04:38:34 +0000181
182 SkPath dent;
epoger@google.com1f753992011-05-18 20:23:30 +0000183 dent.moveTo(SkIntToScalar(0), SkIntToScalar(0));
184 dent.lineTo(SkIntToScalar(100), SkIntToScalar(100));
185 dent.lineTo(SkIntToScalar(0), SkIntToScalar(100));
186 dent.lineTo(SkIntToScalar(-50), SkIntToScalar(200));
187 dent.lineTo(SkIntToScalar(-200), SkIntToScalar(100));
reed@google.com7c424812011-05-15 04:38:34 +0000188 dent.close();
189 check_convexity(reporter, dent, SkPath::kConcave_Convexity);
190}
191
reed@android.com6b82d1a2009-06-03 02:35:01 +0000192static void check_convex_bounds(skiatest::Reporter* reporter, const SkPath& p,
193 const SkRect& bounds) {
194 REPORTER_ASSERT(reporter, p.isConvex());
195 REPORTER_ASSERT(reporter, p.getBounds() == bounds);
reed@google.com62047cf2011-02-07 19:39:09 +0000196
reed@android.com6b82d1a2009-06-03 02:35:01 +0000197 SkPath p2(p);
198 REPORTER_ASSERT(reporter, p2.isConvex());
199 REPORTER_ASSERT(reporter, p2.getBounds() == bounds);
200
201 SkPath other;
202 other.swap(p2);
203 REPORTER_ASSERT(reporter, other.isConvex());
204 REPORTER_ASSERT(reporter, other.getBounds() == bounds);
205}
206
reed@google.com04863fa2011-05-15 04:08:24 +0000207static void setFromString(SkPath* path, const char str[]) {
208 bool first = true;
209 while (str) {
210 SkScalar x, y;
211 str = SkParse::FindScalar(str, &x);
212 if (NULL == str) {
213 break;
214 }
215 str = SkParse::FindScalar(str, &y);
216 SkASSERT(str);
217 if (first) {
218 path->moveTo(x, y);
219 first = false;
220 } else {
221 path->lineTo(x, y);
222 }
223 }
224}
225
226static void test_convexity(skiatest::Reporter* reporter) {
reed@google.com04863fa2011-05-15 04:08:24 +0000227 static const SkPath::Convexity C = SkPath::kConcave_Convexity;
228 static const SkPath::Convexity V = SkPath::kConvex_Convexity;
229
230 SkPath path;
231
reed@google.comb54455e2011-05-16 14:16:04 +0000232 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
reed@google.com04863fa2011-05-15 04:08:24 +0000233 path.addCircle(0, 0, 10);
234 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
235 path.addCircle(0, 0, 10); // 2nd circle
236 REPORTER_ASSERT(reporter, C == SkPath::ComputeConvexity(path));
237 path.reset();
238 path.addRect(0, 0, 10, 10, SkPath::kCCW_Direction);
239 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
240 path.reset();
241 path.addRect(0, 0, 10, 10, SkPath::kCW_Direction);
242 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
243
244 static const struct {
245 const char* fPathStr;
246 SkPath::Convexity fExpectedConvexity;
247 } gRec[] = {
reed@google.comb54455e2011-05-16 14:16:04 +0000248 { "", SkPath::kConvex_Convexity },
249 { "0 0", SkPath::kConvex_Convexity },
250 { "0 0 10 10", SkPath::kConvex_Convexity },
reed@google.com85b6e392011-05-15 20:25:17 +0000251 { "0 0 10 10 20 20 0 0 10 10", SkPath::kConcave_Convexity },
reed@google.com04863fa2011-05-15 04:08:24 +0000252 { "0 0 10 10 10 20", SkPath::kConvex_Convexity },
253 { "0 0 10 10 10 0", SkPath::kConvex_Convexity },
254 { "0 0 10 10 10 0 0 10", SkPath::kConcave_Convexity },
255 { "0 0 10 0 0 10 -10 -10", SkPath::kConcave_Convexity },
256 };
257
258 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
259 SkPath path;
260 setFromString(&path, gRec[i].fPathStr);
261 SkPath::Convexity c = SkPath::ComputeConvexity(path);
262 REPORTER_ASSERT(reporter, c == gRec[i].fExpectedConvexity);
263 }
264}
265
266void TestPath(skiatest::Reporter* reporter);
267void TestPath(skiatest::Reporter* reporter) {
reed@android.com60bc6d52010-02-11 11:09:39 +0000268 {
269 SkSize size;
270 size.fWidth = 3.4f;
271 size.width();
272 size = SkSize::Make(3,4);
273 SkISize isize = SkISize::Make(3,4);
274 }
275
276 SkTSize<SkScalar>::Make(3,4);
277
reed@android.com3abec1d2009-03-02 05:36:20 +0000278 SkPath p, p2;
279 SkRect bounds, bounds2;
reed@android.com80e39a72009-04-02 16:59:40 +0000280
reed@android.com3abec1d2009-03-02 05:36:20 +0000281 REPORTER_ASSERT(reporter, p.isEmpty());
reed@google.comb54455e2011-05-16 14:16:04 +0000282 REPORTER_ASSERT(reporter, p.isConvex());
reed@android.com3abec1d2009-03-02 05:36:20 +0000283 REPORTER_ASSERT(reporter, p.getFillType() == SkPath::kWinding_FillType);
284 REPORTER_ASSERT(reporter, !p.isInverseFillType());
285 REPORTER_ASSERT(reporter, p == p2);
286 REPORTER_ASSERT(reporter, !(p != p2));
287
reed@android.comd252db02009-04-01 18:31:44 +0000288 REPORTER_ASSERT(reporter, p.getBounds().isEmpty());
reed@android.com80e39a72009-04-02 16:59:40 +0000289
reed@android.com3abec1d2009-03-02 05:36:20 +0000290 bounds.set(0, 0, SK_Scalar1, SK_Scalar1);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000291
reed@android.com6b82d1a2009-06-03 02:35:01 +0000292 p.addRoundRect(bounds, SK_Scalar1, SK_Scalar1);
293 check_convex_bounds(reporter, p, bounds);
reed@google.com62047cf2011-02-07 19:39:09 +0000294
reed@android.com6b82d1a2009-06-03 02:35:01 +0000295 p.reset();
reed@android.com6b82d1a2009-06-03 02:35:01 +0000296 p.addOval(bounds);
297 check_convex_bounds(reporter, p, bounds);
reed@google.com62047cf2011-02-07 19:39:09 +0000298
reed@android.com6b82d1a2009-06-03 02:35:01 +0000299 p.reset();
reed@android.com3abec1d2009-03-02 05:36:20 +0000300 p.addRect(bounds);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000301 check_convex_bounds(reporter, p, bounds);
reed@android.com3abec1d2009-03-02 05:36:20 +0000302
303 REPORTER_ASSERT(reporter, p != p2);
304 REPORTER_ASSERT(reporter, !(p == p2));
305
306 // does getPoints return the right result
307 REPORTER_ASSERT(reporter, p.getPoints(NULL, 5) == 4);
308 SkPoint pts[4];
309 int count = p.getPoints(pts, 4);
310 REPORTER_ASSERT(reporter, count == 4);
311 bounds2.set(pts, 4);
312 REPORTER_ASSERT(reporter, bounds == bounds2);
reed@android.com80e39a72009-04-02 16:59:40 +0000313
reed@android.com3abec1d2009-03-02 05:36:20 +0000314 bounds.offset(SK_Scalar1*3, SK_Scalar1*4);
315 p.offset(SK_Scalar1*3, SK_Scalar1*4);
reed@android.comd252db02009-04-01 18:31:44 +0000316 REPORTER_ASSERT(reporter, bounds == p.getBounds());
reed@android.com3abec1d2009-03-02 05:36:20 +0000317
318#if 0 // isRect needs to be implemented
319 REPORTER_ASSERT(reporter, p.isRect(NULL));
320 bounds.setEmpty();
321 REPORTER_ASSERT(reporter, p.isRect(&bounds2));
322 REPORTER_ASSERT(reporter, bounds == bounds2);
reed@android.com80e39a72009-04-02 16:59:40 +0000323
reed@android.com3abec1d2009-03-02 05:36:20 +0000324 // now force p to not be a rect
325 bounds.set(0, 0, SK_Scalar1/2, SK_Scalar1/2);
326 p.addRect(bounds);
327 REPORTER_ASSERT(reporter, !p.isRect(NULL));
328#endif
329
330 SkPoint pt;
331
332 p.moveTo(SK_Scalar1, 0);
333 p.getLastPt(&pt);
334 REPORTER_ASSERT(reporter, pt.fX == SK_Scalar1);
reed@google.com62047cf2011-02-07 19:39:09 +0000335
reed@google.com04863fa2011-05-15 04:08:24 +0000336 test_convexity(reporter);
reed@google.com7c424812011-05-15 04:38:34 +0000337 test_convexity2(reporter);
bsalomon@google.comb3b8dfa2011-07-13 17:44:36 +0000338 test_close(reporter);
reed@android.com3abec1d2009-03-02 05:36:20 +0000339}
340
341#include "TestClassDef.h"
342DEFINE_TESTCLASS("Path", PathTestClass, TestPath)