blob: e2ecdcb4b7b51043a286eda83f4519b83174654f [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +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 */
reed@android.com3abec1d2009-03-02 05:36:20 +00008#include "Test.h"
reed@google.com55b5f4b2011-09-07 12:23:41 +00009#include "SkPaint.h"
reed@android.com3abec1d2009-03-02 05:36:20 +000010#include "SkPath.h"
reed@google.com04863fa2011-05-15 04:08:24 +000011#include "SkParse.h"
reed@google.com53effc52011-09-21 19:05:12 +000012#include "SkReader32.h"
reed@android.com60bc6d52010-02-11 11:09:39 +000013#include "SkSize.h"
reed@google.com53effc52011-09-21 19:05:12 +000014#include "SkWriter32.h"
reed@android.com3abec1d2009-03-02 05:36:20 +000015
reed@google.com55b5f4b2011-09-07 12:23:41 +000016static void stroke_cubic(const SkPoint pts[4]) {
17 SkPath path;
18 path.moveTo(pts[0]);
19 path.cubicTo(pts[1], pts[2], pts[3]);
20
21 SkPaint paint;
22 paint.setStyle(SkPaint::kStroke_Style);
23 paint.setStrokeWidth(SK_Scalar1 * 2);
24
25 SkPath fill;
26 paint.getFillPath(path, &fill);
27}
28
29// just ensure this can run w/o any SkASSERTS firing in the debug build
30// we used to assert due to differences in how we determine a degenerate vector
31// but that was fixed with the introduction of SkPoint::CanNormalize
32static void stroke_tiny_cubic() {
33 SkPoint p0[] = {
34 { 372.0f, 92.0f },
35 { 372.0f, 92.0f },
36 { 372.0f, 92.0f },
37 { 372.0f, 92.0f },
38 };
39
40 stroke_cubic(p0);
41
42 SkPoint p1[] = {
43 { 372.0f, 92.0f },
44 { 372.0007f, 92.000755f },
45 { 371.99927f, 92.003922f },
46 { 371.99826f, 92.003899f },
47 };
48
49 stroke_cubic(p1);
50}
51
bsalomon@google.comb3b8dfa2011-07-13 17:44:36 +000052static void check_close(skiatest::Reporter* reporter, const SkPath& path) {
53 for (int i = 0; i < 2; ++i) {
54 SkPath::Iter iter(path, (bool)i);
55 SkPoint mv;
56 SkPoint pts[4];
57 SkPath::Verb v;
58 int nMT = 0;
59 int nCL = 0;
tomhudson@google.com221db3c2011-07-28 21:10:29 +000060 mv.set(0, 0);
bsalomon@google.comb3b8dfa2011-07-13 17:44:36 +000061 while (SkPath::kDone_Verb != (v = iter.next(pts))) {
62 switch (v) {
63 case SkPath::kMove_Verb:
64 mv = pts[0];
65 ++nMT;
66 break;
67 case SkPath::kClose_Verb:
68 REPORTER_ASSERT(reporter, mv == pts[0]);
69 ++nCL;
70 break;
71 default:
72 break;
73 }
74 }
75 // if we force a close on the interator we should have a close
76 // for every moveTo
77 REPORTER_ASSERT(reporter, !i || nMT == nCL);
78 }
79}
80
81static void test_close(skiatest::Reporter* reporter) {
82 SkPath closePt;
83 closePt.moveTo(0, 0);
84 closePt.close();
85 check_close(reporter, closePt);
86
87 SkPath openPt;
88 openPt.moveTo(0, 0);
89 check_close(reporter, openPt);
90
91 SkPath empty;
92 check_close(reporter, empty);
93 empty.close();
94 check_close(reporter, empty);
95
96 SkPath rect;
97 rect.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
98 check_close(reporter, rect);
99 rect.close();
100 check_close(reporter, rect);
101
102 SkPath quad;
103 quad.quadTo(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
104 check_close(reporter, quad);
105 quad.close();
106 check_close(reporter, quad);
107
108 SkPath cubic;
109 quad.cubicTo(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1,
110 10*SK_Scalar1, 20 * SK_Scalar1, 20*SK_Scalar1);
111 check_close(reporter, cubic);
112 cubic.close();
113 check_close(reporter, cubic);
114
115 SkPath line;
116 line.moveTo(SK_Scalar1, SK_Scalar1);
117 line.lineTo(10 * SK_Scalar1, 10*SK_Scalar1);
118 check_close(reporter, line);
119 line.close();
120 check_close(reporter, line);
121
122 SkPath rect2;
123 rect2.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
124 rect2.close();
125 rect2.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
126 check_close(reporter, rect2);
127 rect2.close();
128 check_close(reporter, rect2);
129
130 SkPath oval3;
131 oval3.addOval(SkRect::MakeWH(SK_Scalar1*100,SK_Scalar1*100));
132 oval3.close();
133 oval3.addOval(SkRect::MakeWH(SK_Scalar1*200,SK_Scalar1*200));
134 check_close(reporter, oval3);
135 oval3.close();
136 check_close(reporter, oval3);
137
138 SkPath moves;
139 moves.moveTo(SK_Scalar1, SK_Scalar1);
140 moves.moveTo(5 * SK_Scalar1, SK_Scalar1);
141 moves.moveTo(SK_Scalar1, 10 * SK_Scalar1);
142 moves.moveTo(10 *SK_Scalar1, SK_Scalar1);
143 check_close(reporter, moves);
reed@google.com55b5f4b2011-09-07 12:23:41 +0000144
145 stroke_tiny_cubic();
bsalomon@google.comb3b8dfa2011-07-13 17:44:36 +0000146}
147
reed@google.com7c424812011-05-15 04:38:34 +0000148static void check_convexity(skiatest::Reporter* reporter, const SkPath& path,
149 SkPath::Convexity expected) {
150 SkPath::Convexity c = SkPath::ComputeConvexity(path);
151 REPORTER_ASSERT(reporter, c == expected);
152}
153
154static void test_convexity2(skiatest::Reporter* reporter) {
155 SkPath pt;
156 pt.moveTo(0, 0);
157 pt.close();
reed@google.comb54455e2011-05-16 14:16:04 +0000158 check_convexity(reporter, pt, SkPath::kConvex_Convexity);
reed@google.com7c424812011-05-15 04:38:34 +0000159
160 SkPath line;
161 line.moveTo(12, 20);
162 line.lineTo(-12, -20);
163 line.close();
reed@google.comb54455e2011-05-16 14:16:04 +0000164 check_convexity(reporter, pt, SkPath::kConvex_Convexity);
reed@google.com7c424812011-05-15 04:38:34 +0000165
166 SkPath triLeft;
167 triLeft.moveTo(0, 0);
168 triLeft.lineTo(1, 0);
169 triLeft.lineTo(1, 1);
170 triLeft.close();
171 check_convexity(reporter, triLeft, SkPath::kConvex_Convexity);
172
173 SkPath triRight;
174 triRight.moveTo(0, 0);
175 triRight.lineTo(-1, 0);
176 triRight.lineTo(1, 1);
177 triRight.close();
178 check_convexity(reporter, triRight, SkPath::kConvex_Convexity);
179
180 SkPath square;
181 square.moveTo(0, 0);
182 square.lineTo(1, 0);
183 square.lineTo(1, 1);
184 square.lineTo(0, 1);
185 square.close();
186 check_convexity(reporter, square, SkPath::kConvex_Convexity);
187
188 SkPath redundantSquare;
189 redundantSquare.moveTo(0, 0);
190 redundantSquare.lineTo(0, 0);
191 redundantSquare.lineTo(0, 0);
192 redundantSquare.lineTo(1, 0);
193 redundantSquare.lineTo(1, 0);
194 redundantSquare.lineTo(1, 0);
195 redundantSquare.lineTo(1, 1);
196 redundantSquare.lineTo(1, 1);
197 redundantSquare.lineTo(1, 1);
198 redundantSquare.lineTo(0, 1);
199 redundantSquare.lineTo(0, 1);
200 redundantSquare.lineTo(0, 1);
201 redundantSquare.close();
202 check_convexity(reporter, redundantSquare, SkPath::kConvex_Convexity);
203
204 SkPath bowTie;
205 bowTie.moveTo(0, 0);
206 bowTie.lineTo(0, 0);
207 bowTie.lineTo(0, 0);
208 bowTie.lineTo(1, 1);
209 bowTie.lineTo(1, 1);
210 bowTie.lineTo(1, 1);
211 bowTie.lineTo(1, 0);
212 bowTie.lineTo(1, 0);
213 bowTie.lineTo(1, 0);
214 bowTie.lineTo(0, 1);
215 bowTie.lineTo(0, 1);
216 bowTie.lineTo(0, 1);
217 bowTie.close();
218 check_convexity(reporter, bowTie, SkPath::kConcave_Convexity);
219
220 SkPath spiral;
221 spiral.moveTo(0, 0);
epoger@google.com2047f002011-05-17 17:36:59 +0000222 spiral.lineTo(100, 0);
223 spiral.lineTo(100, 100);
224 spiral.lineTo(0, 100);
225 spiral.lineTo(0, 50);
226 spiral.lineTo(50, 50);
227 spiral.lineTo(50, 75);
reed@google.com7c424812011-05-15 04:38:34 +0000228 spiral.close();
reed@google.com85b6e392011-05-15 20:25:17 +0000229 check_convexity(reporter, spiral, SkPath::kConcave_Convexity);
reed@google.com7c424812011-05-15 04:38:34 +0000230
231 SkPath dent;
epoger@google.com1f753992011-05-18 20:23:30 +0000232 dent.moveTo(SkIntToScalar(0), SkIntToScalar(0));
233 dent.lineTo(SkIntToScalar(100), SkIntToScalar(100));
234 dent.lineTo(SkIntToScalar(0), SkIntToScalar(100));
235 dent.lineTo(SkIntToScalar(-50), SkIntToScalar(200));
236 dent.lineTo(SkIntToScalar(-200), SkIntToScalar(100));
reed@google.com7c424812011-05-15 04:38:34 +0000237 dent.close();
238 check_convexity(reporter, dent, SkPath::kConcave_Convexity);
239}
240
reed@android.com6b82d1a2009-06-03 02:35:01 +0000241static void check_convex_bounds(skiatest::Reporter* reporter, const SkPath& p,
242 const SkRect& bounds) {
243 REPORTER_ASSERT(reporter, p.isConvex());
244 REPORTER_ASSERT(reporter, p.getBounds() == bounds);
reed@google.com62047cf2011-02-07 19:39:09 +0000245
reed@android.com6b82d1a2009-06-03 02:35:01 +0000246 SkPath p2(p);
247 REPORTER_ASSERT(reporter, p2.isConvex());
248 REPORTER_ASSERT(reporter, p2.getBounds() == bounds);
249
250 SkPath other;
251 other.swap(p2);
252 REPORTER_ASSERT(reporter, other.isConvex());
253 REPORTER_ASSERT(reporter, other.getBounds() == bounds);
254}
255
reed@google.com04863fa2011-05-15 04:08:24 +0000256static void setFromString(SkPath* path, const char str[]) {
257 bool first = true;
258 while (str) {
259 SkScalar x, y;
260 str = SkParse::FindScalar(str, &x);
261 if (NULL == str) {
262 break;
263 }
264 str = SkParse::FindScalar(str, &y);
265 SkASSERT(str);
266 if (first) {
267 path->moveTo(x, y);
268 first = false;
269 } else {
270 path->lineTo(x, y);
271 }
272 }
273}
274
275static void test_convexity(skiatest::Reporter* reporter) {
reed@google.com04863fa2011-05-15 04:08:24 +0000276 static const SkPath::Convexity C = SkPath::kConcave_Convexity;
277 static const SkPath::Convexity V = SkPath::kConvex_Convexity;
278
279 SkPath path;
280
reed@google.comb54455e2011-05-16 14:16:04 +0000281 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
reed@google.com04863fa2011-05-15 04:08:24 +0000282 path.addCircle(0, 0, 10);
283 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
284 path.addCircle(0, 0, 10); // 2nd circle
285 REPORTER_ASSERT(reporter, C == SkPath::ComputeConvexity(path));
286 path.reset();
287 path.addRect(0, 0, 10, 10, SkPath::kCCW_Direction);
288 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
289 path.reset();
290 path.addRect(0, 0, 10, 10, SkPath::kCW_Direction);
291 REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path));
292
293 static const struct {
294 const char* fPathStr;
295 SkPath::Convexity fExpectedConvexity;
296 } gRec[] = {
reed@google.comb54455e2011-05-16 14:16:04 +0000297 { "", SkPath::kConvex_Convexity },
298 { "0 0", SkPath::kConvex_Convexity },
299 { "0 0 10 10", SkPath::kConvex_Convexity },
reed@google.com85b6e392011-05-15 20:25:17 +0000300 { "0 0 10 10 20 20 0 0 10 10", SkPath::kConcave_Convexity },
reed@google.com04863fa2011-05-15 04:08:24 +0000301 { "0 0 10 10 10 20", SkPath::kConvex_Convexity },
302 { "0 0 10 10 10 0", SkPath::kConvex_Convexity },
303 { "0 0 10 10 10 0 0 10", SkPath::kConcave_Convexity },
304 { "0 0 10 0 0 10 -10 -10", SkPath::kConcave_Convexity },
305 };
306
307 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
308 SkPath path;
309 setFromString(&path, gRec[i].fPathStr);
310 SkPath::Convexity c = SkPath::ComputeConvexity(path);
311 REPORTER_ASSERT(reporter, c == gRec[i].fExpectedConvexity);
312 }
313}
314
caryclark@google.comf1316942011-07-26 19:54:45 +0000315// Simple isRect test is inline TestPath, below.
316// test_isRect provides more extensive testing.
317static void test_isRect(skiatest::Reporter* reporter) {
318 // passing tests (all moveTo / lineTo...
319 SkPoint r1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
320 SkPoint r2[] = {{1, 0}, {1, 1}, {0, 1}, {0, 0}};
321 SkPoint r3[] = {{1, 1}, {0, 1}, {0, 0}, {1, 0}};
322 SkPoint r4[] = {{0, 1}, {0, 0}, {1, 0}, {1, 1}};
323 SkPoint r5[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
324 SkPoint r6[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
325 SkPoint r7[] = {{1, 1}, {1, 0}, {0, 0}, {0, 1}};
326 SkPoint r8[] = {{1, 0}, {0, 0}, {0, 1}, {1, 1}};
327 SkPoint r9[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
328 SkPoint ra[] = {{0, 0}, {0, .5f}, {0, 1}, {.5f, 1}, {1, 1}, {1, .5f},
329 {1, 0}, {.5f, 0}};
330 SkPoint rb[] = {{0, 0}, {.5f, 0}, {1, 0}, {1, .5f}, {1, 1}, {.5f, 1},
331 {0, 1}, {0, .5f}};
332 SkPoint rc[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}};
333 SkPoint rd[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}};
334 SkPoint re[] = {{0, 0}, {1, 0}, {1, 0}, {1, 1}, {0, 1}};
335
336 // failing tests
337 SkPoint f1[] = {{0, 0}, {1, 0}, {1, 1}}; // too few points
338 SkPoint f2[] = {{0, 0}, {1, 1}, {0, 1}, {1, 0}}; // diagonal
339 SkPoint f3[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}}; // wraps
340 SkPoint f4[] = {{0, 0}, {1, 0}, {0, 0}, {1, 0}, {1, 1}, {0, 1}}; // backs up
341 SkPoint f5[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}}; // end overshoots
342 SkPoint f6[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 2}}; // end overshoots
343 SkPoint f7[] = {{0, 0}, {1, 0}, {1, 1}, {0, 2}}; // end overshoots
344 SkPoint f8[] = {{0, 0}, {1, 0}, {1, 1}, {1, 0}}; // 'L'
345
346 // failing, no close
347 SkPoint c1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; // close doesn't match
348 SkPoint c2[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}}; // ditto
349
350 size_t testLen[] = {
351 sizeof(r1), sizeof(r2), sizeof(r3), sizeof(r4), sizeof(r5), sizeof(r6),
352 sizeof(r7), sizeof(r8), sizeof(r9), sizeof(ra), sizeof(rb), sizeof(rc),
353 sizeof(rd), sizeof(re),
354 sizeof(f1), sizeof(f2), sizeof(f3), sizeof(f4), sizeof(f5), sizeof(f6),
355 sizeof(f7), sizeof(f8),
356 sizeof(c1), sizeof(c2)
357 };
358 SkPoint* tests[] = {
359 r1, r2, r3, r4, r5, r6, r7, r8, r9, ra, rb, rc, rd, re,
360 f1, f2, f3, f4, f5, f6, f7, f8,
361 c1, c2
362 };
363 SkPoint* lastPass = re;
364 SkPoint* lastClose = f8;
365 bool fail = false;
366 bool close = true;
367 const size_t testCount = sizeof(tests) / sizeof(tests[0]);
368 size_t index;
369 for (size_t testIndex = 0; testIndex < testCount; ++testIndex) {
370 SkPath path;
371 path.moveTo(tests[testIndex][0].fX, tests[testIndex][0].fY);
372 for (index = 1; index < testLen[testIndex] / sizeof(SkPoint); ++index) {
373 path.lineTo(tests[testIndex][index].fX, tests[testIndex][index].fY);
374 }
375 if (close) {
376 path.close();
377 }
378 REPORTER_ASSERT(reporter, fail ^ path.isRect(0));
379 if (tests[testIndex] == lastPass) {
380 fail = true;
381 }
382 if (tests[testIndex] == lastClose) {
383 close = false;
384 }
385 }
386
387 // fail, close then line
388 SkPath path1;
389 path1.moveTo(r1[0].fX, r1[0].fY);
390 for (index = 1; index < testLen[0] / sizeof(SkPoint); ++index) {
391 path1.lineTo(r1[index].fX, r1[index].fY);
392 }
393 path1.close();
394 path1.lineTo(1, 0);
395 REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
396
397 // fail, move in the middle
398 path1.reset();
399 path1.moveTo(r1[0].fX, r1[0].fY);
400 for (index = 1; index < testLen[0] / sizeof(SkPoint); ++index) {
401 if (index == 2) {
402 path1.moveTo(1, .5f);
403 }
404 path1.lineTo(r1[index].fX, r1[index].fY);
405 }
406 path1.close();
407 REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
408
409 // fail, move on the edge
410 path1.reset();
411 for (index = 1; index < testLen[0] / sizeof(SkPoint); ++index) {
412 path1.moveTo(r1[index - 1].fX, r1[index - 1].fY);
413 path1.lineTo(r1[index].fX, r1[index].fY);
414 }
415 path1.close();
416 REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
417
418 // fail, quad
419 path1.reset();
420 path1.moveTo(r1[0].fX, r1[0].fY);
421 for (index = 1; index < testLen[0] / sizeof(SkPoint); ++index) {
422 if (index == 2) {
423 path1.quadTo(1, .5f, 1, .5f);
424 }
425 path1.lineTo(r1[index].fX, r1[index].fY);
426 }
427 path1.close();
428 REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
429
430 // fail, cubic
431 path1.reset();
432 path1.moveTo(r1[0].fX, r1[0].fY);
433 for (index = 1; index < testLen[0] / sizeof(SkPoint); ++index) {
434 if (index == 2) {
435 path1.cubicTo(1, .5f, 1, .5f, 1, .5f);
436 }
437 path1.lineTo(r1[index].fX, r1[index].fY);
438 }
439 path1.close();
440 REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
441}
442
reed@google.com53effc52011-09-21 19:05:12 +0000443static void test_flattening(skiatest::Reporter* reporter) {
444 SkPath p;
445
446 static const SkPoint pts[] = {
447 { 0, 0 },
448 { SkIntToScalar(10), SkIntToScalar(10) },
449 { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 },
450 { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) }
451 };
452 p.moveTo(pts[0]);
453 p.lineTo(pts[1]);
454 p.quadTo(pts[2], pts[3]);
455 p.cubicTo(pts[4], pts[5], pts[6]);
456
457 SkWriter32 writer(100);
458 p.flatten(writer);
459 size_t size = writer.size();
460 SkAutoMalloc storage(size);
461 writer.flatten(storage.get());
462 SkReader32 reader(storage.get(), size);
463
464 SkPath p1;
465 REPORTER_ASSERT(reporter, p1 != p);
466 p1.unflatten(reader);
467 REPORTER_ASSERT(reporter, p1 == p);
468}
469
470static void test_transform(skiatest::Reporter* reporter) {
471 SkPath p, p1;
472
473 static const SkPoint pts[] = {
474 { 0, 0 },
475 { SkIntToScalar(10), SkIntToScalar(10) },
476 { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 },
477 { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) }
478 };
479 p.moveTo(pts[0]);
480 p.lineTo(pts[1]);
481 p.quadTo(pts[2], pts[3]);
482 p.cubicTo(pts[4], pts[5], pts[6]);
483
484 SkMatrix matrix;
485 matrix.reset();
486 p.transform(matrix, &p1);
487 REPORTER_ASSERT(reporter, p == p1);
488
489 matrix.setScale(SK_Scalar1 * 2, SK_Scalar1 * 3);
490 p.transform(matrix, &p1);
491 SkPoint pts1[7];
492 int count = p1.getPoints(pts1, 7);
493 REPORTER_ASSERT(reporter, 7 == count);
494 for (int i = 0; i < count; ++i) {
495 SkPoint newPt = SkPoint::Make(pts[i].fX * 2, pts[i].fY * 3);
496 REPORTER_ASSERT(reporter, newPt == pts1[i]);
497 }
498}
499
reed@google.com10296cc2011-09-21 12:29:05 +0000500#define kCurveSegmentMask (SkPath::kQuad_SegmentMask | SkPath::kCubic_SegmentMask)
501
reed@google.com04863fa2011-05-15 04:08:24 +0000502void TestPath(skiatest::Reporter* reporter);
503void TestPath(skiatest::Reporter* reporter) {
reed@android.com60bc6d52010-02-11 11:09:39 +0000504 {
505 SkSize size;
506 size.fWidth = 3.4f;
507 size.width();
508 size = SkSize::Make(3,4);
509 SkISize isize = SkISize::Make(3,4);
510 }
511
512 SkTSize<SkScalar>::Make(3,4);
513
reed@android.com3abec1d2009-03-02 05:36:20 +0000514 SkPath p, p2;
515 SkRect bounds, bounds2;
reed@android.com80e39a72009-04-02 16:59:40 +0000516
reed@android.com3abec1d2009-03-02 05:36:20 +0000517 REPORTER_ASSERT(reporter, p.isEmpty());
reed@google.com10296cc2011-09-21 12:29:05 +0000518 REPORTER_ASSERT(reporter, 0 == p.getSegmentMasks());
reed@google.comb54455e2011-05-16 14:16:04 +0000519 REPORTER_ASSERT(reporter, p.isConvex());
reed@android.com3abec1d2009-03-02 05:36:20 +0000520 REPORTER_ASSERT(reporter, p.getFillType() == SkPath::kWinding_FillType);
521 REPORTER_ASSERT(reporter, !p.isInverseFillType());
522 REPORTER_ASSERT(reporter, p == p2);
523 REPORTER_ASSERT(reporter, !(p != p2));
524
reed@android.comd252db02009-04-01 18:31:44 +0000525 REPORTER_ASSERT(reporter, p.getBounds().isEmpty());
reed@android.com80e39a72009-04-02 16:59:40 +0000526
reed@android.com3abec1d2009-03-02 05:36:20 +0000527 bounds.set(0, 0, SK_Scalar1, SK_Scalar1);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000528
reed@android.com6b82d1a2009-06-03 02:35:01 +0000529 p.addRoundRect(bounds, SK_Scalar1, SK_Scalar1);
530 check_convex_bounds(reporter, p, bounds);
reed@google.com10296cc2011-09-21 12:29:05 +0000531 // we have quads or cubics
532 REPORTER_ASSERT(reporter, p.getSegmentMasks() & kCurveSegmentMask);
reed@google.com62047cf2011-02-07 19:39:09 +0000533
reed@android.com6b82d1a2009-06-03 02:35:01 +0000534 p.reset();
reed@google.com10296cc2011-09-21 12:29:05 +0000535 REPORTER_ASSERT(reporter, 0 == p.getSegmentMasks());
536
reed@android.com6b82d1a2009-06-03 02:35:01 +0000537 p.addOval(bounds);
538 check_convex_bounds(reporter, p, bounds);
reed@google.com62047cf2011-02-07 19:39:09 +0000539
reed@android.com6b82d1a2009-06-03 02:35:01 +0000540 p.reset();
reed@android.com3abec1d2009-03-02 05:36:20 +0000541 p.addRect(bounds);
reed@android.com6b82d1a2009-06-03 02:35:01 +0000542 check_convex_bounds(reporter, p, bounds);
reed@google.com10296cc2011-09-21 12:29:05 +0000543 // we have only lines
544 REPORTER_ASSERT(reporter, SkPath::kLine_SegmentMask == p.getSegmentMasks());
reed@android.com3abec1d2009-03-02 05:36:20 +0000545
546 REPORTER_ASSERT(reporter, p != p2);
547 REPORTER_ASSERT(reporter, !(p == p2));
548
549 // does getPoints return the right result
550 REPORTER_ASSERT(reporter, p.getPoints(NULL, 5) == 4);
551 SkPoint pts[4];
552 int count = p.getPoints(pts, 4);
553 REPORTER_ASSERT(reporter, count == 4);
554 bounds2.set(pts, 4);
555 REPORTER_ASSERT(reporter, bounds == bounds2);
reed@android.com80e39a72009-04-02 16:59:40 +0000556
reed@android.com3abec1d2009-03-02 05:36:20 +0000557 bounds.offset(SK_Scalar1*3, SK_Scalar1*4);
558 p.offset(SK_Scalar1*3, SK_Scalar1*4);
reed@android.comd252db02009-04-01 18:31:44 +0000559 REPORTER_ASSERT(reporter, bounds == p.getBounds());
reed@android.com3abec1d2009-03-02 05:36:20 +0000560
reed@android.com3abec1d2009-03-02 05:36:20 +0000561 REPORTER_ASSERT(reporter, p.isRect(NULL));
caryclark@google.comf1316942011-07-26 19:54:45 +0000562 bounds2.setEmpty();
reed@android.com3abec1d2009-03-02 05:36:20 +0000563 REPORTER_ASSERT(reporter, p.isRect(&bounds2));
564 REPORTER_ASSERT(reporter, bounds == bounds2);
reed@android.com80e39a72009-04-02 16:59:40 +0000565
reed@android.com3abec1d2009-03-02 05:36:20 +0000566 // now force p to not be a rect
567 bounds.set(0, 0, SK_Scalar1/2, SK_Scalar1/2);
568 p.addRect(bounds);
569 REPORTER_ASSERT(reporter, !p.isRect(NULL));
caryclark@google.comf1316942011-07-26 19:54:45 +0000570 test_isRect(reporter);
reed@android.com3abec1d2009-03-02 05:36:20 +0000571
572 SkPoint pt;
573
574 p.moveTo(SK_Scalar1, 0);
575 p.getLastPt(&pt);
576 REPORTER_ASSERT(reporter, pt.fX == SK_Scalar1);
reed@google.com62047cf2011-02-07 19:39:09 +0000577
reed@google.com04863fa2011-05-15 04:08:24 +0000578 test_convexity(reporter);
reed@google.com7c424812011-05-15 04:38:34 +0000579 test_convexity2(reporter);
bsalomon@google.comb3b8dfa2011-07-13 17:44:36 +0000580 test_close(reporter);
reed@google.com10296cc2011-09-21 12:29:05 +0000581
582 p.reset();
583 p.moveTo(0, 0);
584 p.quadTo(100, 100, 200, 200);
585 REPORTER_ASSERT(reporter, SkPath::kQuad_SegmentMask == p.getSegmentMasks());
586 p.cubicTo(100, 100, 200, 200, 300, 300);
587 REPORTER_ASSERT(reporter, kCurveSegmentMask == p.getSegmentMasks());
588 p.reset();
589 p.moveTo(0, 0);
590 p.cubicTo(100, 100, 200, 200, 300, 300);
591 REPORTER_ASSERT(reporter, SkPath::kCubic_SegmentMask == p.getSegmentMasks());
reed@google.com53effc52011-09-21 19:05:12 +0000592
593 test_flattening(reporter);
594 test_transform(reporter);
reed@android.com3abec1d2009-03-02 05:36:20 +0000595}
596
597#include "TestClassDef.h"
598DEFINE_TESTCLASS("Path", PathTestClass, TestPath)