OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "PathOpsExtendedTest.h" | 8 #include "PathOpsExtendedTest.h" |
9 #include "PathOpsThreadedCommon.h" | 9 #include "PathOpsThreadedCommon.h" |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 "i", | 38 "i", |
39 "u", | 39 "u", |
40 "o", | 40 "o", |
41 }; | 41 }; |
42 | 42 |
43 static bool gShowPath = false; | 43 static bool gShowPath = false; |
44 static bool gComparePaths = true; | 44 static bool gComparePaths = true; |
45 static bool gComparePathsAssert = true; | 45 static bool gComparePathsAssert = true; |
46 static bool gPathStrAssert = true; | 46 static bool gPathStrAssert = true; |
47 | 47 |
48 static void showPathContours(SkPath::Iter& iter, const char* suffix) { | 48 static const char* gFillTypeStr[] = { |
| 49 "kWinding_FillType", |
| 50 "kEvenOdd_FillType", |
| 51 "kInverseWinding_FillType", |
| 52 "kInverseEvenOdd_FillType" |
| 53 }; |
| 54 |
| 55 static void showPathContours(SkPath::RawIter& iter, const char* pathName) { |
49 uint8_t verb; | 56 uint8_t verb; |
50 SkPoint pts[4]; | 57 SkPoint pts[4]; |
51 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { | 58 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
52 switch (verb) { | 59 switch (verb) { |
53 case SkPath::kMove_Verb: | 60 case SkPath::kMove_Verb: |
54 SkDebugf(" path%s.moveTo(%1.9g,%1.9g);\n", suffix, pts[0].fX,
pts[0].fY); | 61 SkDebugf(" %s.moveTo(%#1.9gf, %#1.9gf);\n", pathName, pts[0].
fX, pts[0].fY); |
55 continue; | 62 continue; |
56 case SkPath::kLine_Verb: | 63 case SkPath::kLine_Verb: |
57 SkDebugf(" path%s.lineTo(%1.9g,%1.9g);\n", suffix, pts[1].fX,
pts[1].fY); | 64 SkDebugf(" %s.lineTo(%#1.9gf, %#1.9gf);\n", pathName, pts[1].
fX, pts[1].fY); |
58 break; | 65 break; |
59 case SkPath::kQuad_Verb: | 66 case SkPath::kQuad_Verb: |
60 SkDebugf(" path%s.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n", suffi
x, | 67 SkDebugf(" %s.quadTo(%#1.9gf, %#1.9gf, %#1.9gf, %#1.9gf);\n",
pathName, |
61 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); | 68 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); |
62 break; | 69 break; |
63 case SkPath::kCubic_Verb: | 70 case SkPath::kCubic_Verb: |
64 SkDebugf(" path%s.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.
9g);\n", suffix, | 71 SkDebugf(" %s.cubicTo(%#1.9gf, %#1.9gf, %#1.9gf, %#1.9gf, %#1
.9gf, %#1.9gf);\n", |
65 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3
].fY); | 72 pathName, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3]
.fX, pts[3].fY); |
66 break; | 73 break; |
67 case SkPath::kClose_Verb: | 74 case SkPath::kClose_Verb: |
68 SkDebugf(" path%s.close();\n", suffix); | 75 SkDebugf(" %s.close();\n", pathName); |
69 break; | 76 break; |
70 default: | 77 default: |
71 SkDEBUGFAIL("bad verb"); | 78 SkDEBUGFAIL("bad verb"); |
72 return; | 79 return; |
73 } | 80 } |
74 } | 81 } |
75 } | 82 } |
76 | 83 |
77 static const char* fillTypeStr[] = { | 84 static void showPath(const SkPath& path, const char* pathName, bool includeDecla
ration) { |
78 "kWinding_FillType", | 85 SkPath::RawIter iter(path); |
79 "kEvenOdd_FillType", | |
80 "kInverseWinding_FillType", | |
81 "kInverseEvenOdd_FillType" | |
82 }; | |
83 | |
84 static void showPath(const SkPath& path, const char* suffix) { | |
85 SkPath::Iter iter(path, true); | |
86 #define SUPPORT_RECT_CONTOUR_DETECTION 0 | 86 #define SUPPORT_RECT_CONTOUR_DETECTION 0 |
87 #if SUPPORT_RECT_CONTOUR_DETECTION | 87 #if SUPPORT_RECT_CONTOUR_DETECTION |
88 int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0; | 88 int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0; |
89 if (rectCount > 0) { | 89 if (rectCount > 0) { |
90 SkTDArray<SkRect> rects; | 90 SkTDArray<SkRect> rects; |
91 SkTDArray<SkPath::Direction> directions; | 91 SkTDArray<SkPath::Direction> directions; |
92 rects.setCount(rectCount); | 92 rects.setCount(rectCount); |
93 directions.setCount(rectCount); | 93 directions.setCount(rectCount); |
94 path.rectContours(rects.begin(), directions.begin()); | 94 path.rectContours(rects.begin(), directions.begin()); |
95 for (int contour = 0; contour < rectCount; ++contour) { | 95 for (int contour = 0; contour < rectCount; ++contour) { |
96 const SkRect& rect = rects[contour]; | 96 const SkRect& rect = rects[contour]; |
97 SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLe
ft, rect.fTop, | 97 SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLe
ft, rect.fTop, |
98 rect.fRight, rect.fBottom, directions[contour] == SkPath::kC
CW_Direction | 98 rect.fRight, rect.fBottom, directions[contour] == SkPath::kC
CW_Direction |
99 ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); | 99 ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); |
100 } | 100 } |
101 return; | 101 return; |
102 } | 102 } |
103 #endif | 103 #endif |
104 SkPath::FillType fillType = path.getFillType(); | 104 SkPath::FillType fillType = path.getFillType(); |
105 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); | 105 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); |
106 SkDebugf(" path%s.setFillType(SkPath::%s);\n", suffix, fillTypeStr[fillTy
pe]); | 106 if (includeDeclaration) { |
107 iter.setPath(path, true); | 107 SkDebugf(" SkPath %s;\n", pathName); |
108 showPathContours(iter, suffix); | 108 } |
| 109 SkDebugf(" %s.setFillType(SkPath::%s);\n", pathName, gFillTypeStr[fillTyp
e]); |
| 110 iter.setPath(path); |
| 111 showPathContours(iter, pathName); |
109 } | 112 } |
110 | 113 |
111 #if DEBUG_SHOW_TEST_NAME | 114 #if DEBUG_SHOW_TEST_NAME |
112 static void showPathData(const SkPath& path) { | 115 static void showPathData(const SkPath& path) { |
113 SkPath::Iter iter(path, true); | 116 SkPath::RawIter iter(path); |
114 uint8_t verb; | 117 uint8_t verb; |
115 SkPoint pts[4]; | 118 SkPoint pts[4]; |
116 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { | 119 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
117 switch (verb) { | 120 switch (verb) { |
118 case SkPath::kMove_Verb: | 121 case SkPath::kMove_Verb: |
119 continue; | 122 continue; |
120 case SkPath::kLine_Verb: | 123 case SkPath::kLine_Verb: |
121 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", pts[0].fX, pts[0].
fY, | 124 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", pts[0].fX, pts[0].
fY, |
122 pts[1].fX, pts[1].fY); | 125 pts[1].fX, pts[1].fY); |
123 break; | 126 break; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 SkDebugf("op xor\n"); | 158 SkDebugf("op xor\n"); |
156 break; | 159 break; |
157 case kReverseDifference_PathOp: | 160 case kReverseDifference_PathOp: |
158 SkDebugf("op reverse difference\n"); | 161 SkDebugf("op reverse difference\n"); |
159 break; | 162 break; |
160 default: | 163 default: |
161 SkASSERT(0); | 164 SkASSERT(0); |
162 } | 165 } |
163 } | 166 } |
164 | 167 |
165 #if 0 | 168 #if DEBUG_SHOW_TEST_NAME |
166 static void showPath(const SkPath& path, const char* str, const SkMatrix& scale)
{ | 169 |
167 SkPath scaled; | 170 void ShowFunctionHeader(const char* functionName) { |
168 SkMatrix inverse; | 171 SkDebugf("\nstatic void %s(skiatest::Reporter* reporter) {\n", functionName)
; |
169 bool success = scale.invert(&inverse); | 172 if (strcmp("skphealth_com76", functionName) == 0) { |
170 if (!success) { | 173 SkDebugf("found it\n"); |
171 SkASSERT(0); | |
172 } | 174 } |
173 path.transform(inverse, &scaled); | 175 } |
174 showPath(scaled, str); | 176 |
| 177 static const char* gOpStrs[] = { |
| 178 "kDifference_PathOp", |
| 179 "kIntersect_PathOp", |
| 180 "kUnion_PathOp", |
| 181 "kXor_PathOp", |
| 182 "kReverseDifference_PathOp", |
| 183 }; |
| 184 |
| 185 void ShowOp(SkPathOp op, const char* pathOne, const char* pathTwo) { |
| 186 SkDebugf(" testPathOp(reporter, %s, %s, %s);\n", pathOne, pathTwo, gOpStr
s[op]); |
| 187 SkDebugf("}\n"); |
175 } | 188 } |
176 #endif | 189 #endif |
177 | 190 |
178 #if DEBUG_SHOW_TEST_NAME | 191 #if DEBUG_SHOW_TEST_NAME |
179 static char hexorator(int x) { | 192 static char hexorator(int x) { |
180 if (x < 10) { | 193 if (x < 10) { |
181 return x + '0'; | 194 return x + '0'; |
182 } | 195 } |
183 x -= 10; | 196 x -= 10; |
184 SkASSERT(x < 26); | 197 SkASSERT(x < 26); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; | 331 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; |
319 } | 332 } |
320 *outPtr++ = '\0'; | 333 *outPtr++ = '\0'; |
321 SkDebugf("%s\n", out); | 334 SkDebugf("%s\n", out); |
322 } | 335 } |
323 return true; | 336 return true; |
324 } | 337 } |
325 | 338 |
326 static void showSimplifiedPath(const SkPath& one, const SkPath& two, | 339 static void showSimplifiedPath(const SkPath& one, const SkPath& two, |
327 const SkPath& scaledOne, const SkPath& scaledTwo) { | 340 const SkPath& scaledOne, const SkPath& scaledTwo) { |
328 showPath(one, ""); | 341 showPath(one, "path", false); |
329 // showPath(two, "simplified:"); | |
330 drawAsciiPaths(scaledOne, scaledTwo, true); | 342 drawAsciiPaths(scaledOne, scaledTwo, true); |
331 } | 343 } |
332 | 344 |
333 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& two, | 345 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& two, |
334 SkBitmap& bitmap) { | 346 SkBitmap& bitmap) { |
335 int errors2x2; | 347 int errors2x2; |
336 SkPath scaledOne, scaledTwo; | 348 SkPath scaledOne, scaledTwo; |
337 int errors = pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors
2x2); | 349 int errors = pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors
2x2); |
338 if (errors2x2 == 0) { | 350 if (errors2x2 == 0) { |
339 return 0; | 351 return 0; |
340 } | 352 } |
341 const int MAX_ERRORS = 9; | 353 const int MAX_ERRORS = 9; |
342 if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) { | 354 if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) { |
343 showSimplifiedPath(one, two, scaledOne, scaledTwo); | 355 showSimplifiedPath(one, two, scaledOne, scaledTwo); |
344 } | 356 } |
345 if (errors2x2 > MAX_ERRORS && gComparePathsAssert) { | 357 if (errors2x2 > MAX_ERRORS && gComparePathsAssert) { |
346 SkDebugf("%s errors=%d\n", __FUNCTION__, errors); | 358 SkDebugf("%s errors=%d\n", __FUNCTION__, errors); |
347 showSimplifiedPath(one, two, scaledOne, scaledTwo); | 359 showSimplifiedPath(one, two, scaledOne, scaledTwo); |
348 REPORTER_ASSERT(reporter, 0); | 360 REPORTER_ASSERT(reporter, 0); |
349 } | 361 } |
350 return errors2x2 > MAX_ERRORS ? errors2x2 : 0; | 362 return errors2x2 > MAX_ERRORS ? errors2x2 : 0; |
351 } | 363 } |
352 | 364 |
353 static void showPathOpPath(const SkPath& one, const SkPath& two, const SkPath& a
, const SkPath& b, | 365 static void showPathOpPath(const SkPath& one, const SkPath& two, const SkPath& a
, const SkPath& b, |
354 const SkPath& scaledOne, const SkPath& scaledTwo, const SkPathOp shapeOp
, | 366 const SkPath& scaledOne, const SkPath& scaledTwo, const SkPathOp shapeOp
, |
355 const SkMatrix& scale) { | 367 const SkMatrix& scale) { |
356 SkASSERT((unsigned) shapeOp < SK_ARRAY_COUNT(opStrs)); | 368 SkASSERT((unsigned) shapeOp < SK_ARRAY_COUNT(opStrs)); |
357 SkDebugf("static void xOp#%s(skiatest::Reporter* reporter) {\n", opSuffixes[
shapeOp]); | 369 SkDebugf("static void xOp#%s(skiatest::Reporter* reporter) {\n", opSuffixes[
shapeOp]); |
358 SkDebugf(" SkPath path, pathB;\n"); | 370 SkDebugf(" SkPath path, pathB;\n"); |
359 showPath(a, ""); | 371 showPath(a, "path", false); |
360 showPath(b, "B"); | 372 showPath(b, "pathB", false); |
361 SkDebugf(" testPathOp(reporter, path, pathB, %s);\n", opStrs[shapeOp]); | 373 SkDebugf(" testPathOp(reporter, path, pathB, %s);\n", opStrs[shapeOp]); |
362 SkDebugf("}\n"); | 374 SkDebugf("}\n"); |
363 // the region often isn't very helpful since it approximates curves with a l
ot of line-tos | |
364 // if (0) showPath(scaledOne, "region:", scale); | |
365 // showPath(two, "op result:"); | |
366 drawAsciiPaths(scaledOne, scaledTwo, true); | 375 drawAsciiPaths(scaledOne, scaledTwo, true); |
367 } | 376 } |
368 | 377 |
369 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& scaledOne, | 378 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& scaledOne, |
370 const SkPath& two, const SkPath& scaledTwo, SkBitmap& bi
tmap, | 379 const SkPath& two, const SkPath& scaledTwo, SkBitmap& bi
tmap, |
371 const SkPath& a, const SkPath& b, const SkPathOp shapeOp
, | 380 const SkPath& a, const SkPath& b, const SkPathOp shapeOp
, |
372 const SkMatrix& scale) { | 381 const SkMatrix& scale) { |
373 int errors2x2; | 382 int errors2x2; |
374 int errors = pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2); | 383 int errors = pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2); |
375 if (errors2x2 == 0) { | 384 if (errors2x2 == 0) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 writeTestName(nameSuffix, outFile); | 452 writeTestName(nameSuffix, outFile); |
444 outFile.writeText("),\n"); | 453 outFile.writeText("),\n"); |
445 outFile.flush(); | 454 outFile.flush(); |
446 } | 455 } |
447 | 456 |
448 bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st
ate, | 457 bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st
ate, |
449 const char* pathStr) { | 458 const char* pathStr) { |
450 SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWi
nding_FillType; | 459 SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWi
nding_FillType; |
451 path.setFillType(fillType); | 460 path.setFillType(fillType); |
452 if (gShowPath) { | 461 if (gShowPath) { |
453 showPath(path, ""); | 462 showPath(path, "path", false); |
454 } | 463 } |
455 if (!Simplify(path, &out)) { | 464 if (!Simplify(path, &out)) { |
456 SkDebugf("%s did not expect failure\n", __FUNCTION__); | 465 SkDebugf("%s did not expect failure\n", __FUNCTION__); |
457 REPORTER_ASSERT(state.fReporter, 0); | 466 REPORTER_ASSERT(state.fReporter, 0); |
458 return false; | 467 return false; |
459 } | 468 } |
460 if (!gComparePaths) { | 469 if (!gComparePaths) { |
461 return true; | 470 return true; |
462 } | 471 } |
463 int result = comparePaths(state.fReporter, path, out, *state.fBitmap); | 472 int result = comparePaths(state.fReporter, path, out, *state.fBitmap); |
(...skipping 28 matching lines...) Expand all Loading... |
492 } | 501 } |
493 SkBitmap bitmap; | 502 SkBitmap bitmap; |
494 int result = comparePaths(reporter, path, out, bitmap); | 503 int result = comparePaths(reporter, path, out, bitmap); |
495 if (result && gPathStrAssert) { | 504 if (result && gPathStrAssert) { |
496 REPORTER_ASSERT(reporter, 0); | 505 REPORTER_ASSERT(reporter, 0); |
497 } | 506 } |
498 reporter->bumpTestCount(); | 507 reporter->bumpTestCount(); |
499 return result == 0; | 508 return result == 0; |
500 } | 509 } |
501 | 510 |
| 511 #if DEBUG_SHOW_TEST_NAME |
| 512 void DebugShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, const cha
r* testName) { |
| 513 ShowFunctionHeader(testName); |
| 514 showPath(a, "path", true); |
| 515 showPath(b, "pathB", true); |
| 516 ShowOp(shapeOp, "path", "pathB"); |
| 517 } |
| 518 #endif |
| 519 |
502 bool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, | 520 bool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, |
503 const SkPathOp shapeOp) { | 521 const SkPathOp shapeOp, const char* testName) { |
504 #if DEBUG_SHOW_TEST_NAME | 522 #if DEBUG_SHOW_TEST_NAME |
505 showPathData(a); | 523 if (testName == NULL) { |
506 showOp(shapeOp); | 524 showPathData(a); |
507 showPathData(b); | 525 showOp(shapeOp); |
| 526 showPathData(b); |
| 527 } else { |
| 528 DebugShowPath(a, b, shapeOp, testName); |
| 529 } |
508 #endif | 530 #endif |
509 SkPath out; | 531 SkPath out; |
510 if (!Op(a, b, shapeOp, &out) ) { | 532 if (!Op(a, b, shapeOp, &out) ) { |
511 SkDebugf("%s did not expect failure\n", __FUNCTION__); | 533 SkDebugf("%s did not expect failure\n", __FUNCTION__); |
512 REPORTER_ASSERT(reporter, 0); | 534 REPORTER_ASSERT(reporter, 0); |
513 return false; | 535 return false; |
514 } | 536 } |
515 SkPath pathOut, scaledPathOut; | 537 SkPath pathOut, scaledPathOut; |
516 SkRegion rgnA, rgnB, openClip, rgnOut; | 538 SkRegion rgnA, rgnB, openClip, rgnOut; |
517 openClip.setRect(-16000, -16000, 16000, 16000); | 539 openClip.setRect(-16000, -16000, 16000, 16000); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 } | 638 } |
617 if (tests[index].fun == stopTest) { | 639 if (tests[index].fun == stopTest) { |
618 SkDebugf("lastTest\n"); | 640 SkDebugf("lastTest\n"); |
619 } | 641 } |
620 if (index == last) { | 642 if (index == last) { |
621 break; | 643 break; |
622 } | 644 } |
623 index += reverse ? -1 : 1; | 645 index += reverse ? -1 : 1; |
624 } while (true); | 646 } while (true); |
625 } | 647 } |
OLD | NEW |