| 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) { | 48 static void showPathContours(SkPath::Iter& iter, const char* suffix) { |
| 49 uint8_t verb; | 49 uint8_t verb; |
| 50 SkPoint pts[4]; | 50 SkPoint pts[4]; |
| 51 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { | 51 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| 52 switch (verb) { | 52 switch (verb) { |
| 53 case SkPath::kMove_Verb: | 53 case SkPath::kMove_Verb: |
| 54 SkDebugf("path.moveTo(%1.9g,%1.9g);\n", pts[0].fX, pts[0].fY); | 54 SkDebugf(" path%s.moveTo(%1.9g,%1.9g);\n", suffix, pts[0].fX,
pts[0].fY); |
| 55 continue; | 55 continue; |
| 56 case SkPath::kLine_Verb: | 56 case SkPath::kLine_Verb: |
| 57 SkDebugf("path.lineTo(%1.9g,%1.9g);\n", pts[1].fX, pts[1].fY); | 57 SkDebugf(" path%s.lineTo(%1.9g,%1.9g);\n", suffix, pts[1].fX,
pts[1].fY); |
| 58 break; | 58 break; |
| 59 case SkPath::kQuad_Verb: | 59 case SkPath::kQuad_Verb: |
| 60 SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n", | 60 SkDebugf(" path%s.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n", suffi
x, |
| 61 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); | 61 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); |
| 62 break; | 62 break; |
| 63 case SkPath::kCubic_Verb: | 63 case SkPath::kCubic_Verb: |
| 64 SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n
", | 64 SkDebugf(" path%s.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.
9g);\n", suffix, |
| 65 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3
].fY); | 65 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3
].fY); |
| 66 break; | 66 break; |
| 67 case SkPath::kClose_Verb: | 67 case SkPath::kClose_Verb: |
| 68 SkDebugf("path.close();\n"); | 68 SkDebugf(" path%s.close();\n", suffix); |
| 69 break; | 69 break; |
| 70 default: | 70 default: |
| 71 SkDEBUGFAIL("bad verb"); | 71 SkDEBUGFAIL("bad verb"); |
| 72 return; | 72 return; |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 } | 75 } |
| 76 | 76 |
| 77 void showPath(const SkPath& path, const char* str) { | |
| 78 SkDebugf("%s\n", !str ? "original:" : str); | |
| 79 showPath(path); | |
| 80 } | |
| 81 | |
| 82 static const char* fillTypeStr[] = { | 77 static const char* fillTypeStr[] = { |
| 83 "kWinding_FillType", | 78 "kWinding_FillType", |
| 84 "kEvenOdd_FillType", | 79 "kEvenOdd_FillType", |
| 85 "kInverseWinding_FillType", | 80 "kInverseWinding_FillType", |
| 86 "kInverseEvenOdd_FillType" | 81 "kInverseEvenOdd_FillType" |
| 87 }; | 82 }; |
| 88 | 83 |
| 89 void showPath(const SkPath& path) { | 84 static void showPath(const SkPath& path, const char* suffix) { |
| 90 SkPath::Iter iter(path, true); | 85 SkPath::Iter iter(path, true); |
| 91 #define SUPPORT_RECT_CONTOUR_DETECTION 0 | 86 #define SUPPORT_RECT_CONTOUR_DETECTION 0 |
| 92 #if SUPPORT_RECT_CONTOUR_DETECTION | 87 #if SUPPORT_RECT_CONTOUR_DETECTION |
| 93 int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0; | 88 int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0; |
| 94 if (rectCount > 0) { | 89 if (rectCount > 0) { |
| 95 SkTDArray<SkRect> rects; | 90 SkTDArray<SkRect> rects; |
| 96 SkTDArray<SkPath::Direction> directions; | 91 SkTDArray<SkPath::Direction> directions; |
| 97 rects.setCount(rectCount); | 92 rects.setCount(rectCount); |
| 98 directions.setCount(rectCount); | 93 directions.setCount(rectCount); |
| 99 path.rectContours(rects.begin(), directions.begin()); | 94 path.rectContours(rects.begin(), directions.begin()); |
| 100 for (int contour = 0; contour < rectCount; ++contour) { | 95 for (int contour = 0; contour < rectCount; ++contour) { |
| 101 const SkRect& rect = rects[contour]; | 96 const SkRect& rect = rects[contour]; |
| 102 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, |
| 103 rect.fRight, rect.fBottom, directions[contour] == SkPath::kC
CW_Direction | 98 rect.fRight, rect.fBottom, directions[contour] == SkPath::kC
CW_Direction |
| 104 ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); | 99 ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); |
| 105 } | 100 } |
| 106 return; | 101 return; |
| 107 } | 102 } |
| 108 #endif | 103 #endif |
| 109 SkPath::FillType fillType = path.getFillType(); | 104 SkPath::FillType fillType = path.getFillType(); |
| 110 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); | 105 SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInver
seEvenOdd_FillType); |
| 111 SkDebugf("path.setFillType(%s);\n", fillTypeStr[fillType]); | 106 SkDebugf(" path%s.setFillType(SkPath::%s);\n", suffix, fillTypeStr[fillTy
pe]); |
| 112 iter.setPath(path, true); | 107 iter.setPath(path, true); |
| 113 showPathContours(iter); | 108 showPathContours(iter, suffix); |
| 114 } | 109 } |
| 115 | 110 |
| 116 void showPathData(const SkPath& path) { | 111 #if DEBUG_SHOW_TEST_NAME |
| 112 static void showPathData(const SkPath& path) { |
| 117 SkPath::Iter iter(path, true); | 113 SkPath::Iter iter(path, true); |
| 118 uint8_t verb; | 114 uint8_t verb; |
| 119 SkPoint pts[4]; | 115 SkPoint pts[4]; |
| 120 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { | 116 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| 121 switch (verb) { | 117 switch (verb) { |
| 122 case SkPath::kMove_Verb: | 118 case SkPath::kMove_Verb: |
| 123 continue; | 119 continue; |
| 124 case SkPath::kLine_Verb: | 120 case SkPath::kLine_Verb: |
| 125 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", pts[0].fX, pts[0].
fY, | 121 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", pts[0].fX, pts[0].
fY, |
| 126 pts[1].fX, pts[1].fY); | 122 pts[1].fX, pts[1].fY); |
| 127 break; | 123 break; |
| 128 case SkPath::kQuad_Verb: | 124 case SkPath::kQuad_Verb: |
| 129 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", | 125 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", |
| 130 pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, p
ts[2].fY); | 126 pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, p
ts[2].fY); |
| 131 break; | 127 break; |
| 132 case SkPath::kCubic_Verb: | 128 case SkPath::kCubic_Verb: |
| 133 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%
1.9g}},\n", | 129 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%
1.9g}},\n", |
| 134 pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, p
ts[2].fY, | 130 pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, p
ts[2].fY, |
| 135 pts[3].fX, pts[3].fY); | 131 pts[3].fX, pts[3].fY); |
| 136 break; | 132 break; |
| 137 case SkPath::kClose_Verb: | 133 case SkPath::kClose_Verb: |
| 138 break; | 134 break; |
| 139 default: | 135 default: |
| 140 SkDEBUGFAIL("bad verb"); | 136 SkDEBUGFAIL("bad verb"); |
| 141 return; | 137 return; |
| 142 } | 138 } |
| 143 } | 139 } |
| 144 } | 140 } |
| 141 #endif |
| 145 | 142 |
| 146 void showOp(const SkPathOp op) { | 143 void showOp(const SkPathOp op) { |
| 147 switch (op) { | 144 switch (op) { |
| 148 case kDifference_PathOp: | 145 case kDifference_PathOp: |
| 149 SkDebugf("op difference\n"); | 146 SkDebugf("op difference\n"); |
| 150 break; | 147 break; |
| 151 case kIntersect_PathOp: | 148 case kIntersect_PathOp: |
| 152 SkDebugf("op intersect\n"); | 149 SkDebugf("op intersect\n"); |
| 153 break; | 150 break; |
| 154 case kUnion_PathOp: | 151 case kUnion_PathOp: |
| 155 SkDebugf("op union\n"); | 152 SkDebugf("op union\n"); |
| 156 break; | 153 break; |
| 157 case kXOR_PathOp: | 154 case kXOR_PathOp: |
| 158 SkDebugf("op xor\n"); | 155 SkDebugf("op xor\n"); |
| 159 break; | 156 break; |
| 160 case kReverseDifference_PathOp: | 157 case kReverseDifference_PathOp: |
| 161 SkDebugf("op reverse difference\n"); | 158 SkDebugf("op reverse difference\n"); |
| 162 break; | 159 break; |
| 163 default: | 160 default: |
| 164 SkASSERT(0); | 161 SkASSERT(0); |
| 165 } | 162 } |
| 166 } | 163 } |
| 167 | 164 |
| 165 #if 0 |
| 168 static void showPath(const SkPath& path, const char* str, const SkMatrix& scale)
{ | 166 static void showPath(const SkPath& path, const char* str, const SkMatrix& scale)
{ |
| 169 SkPath scaled; | 167 SkPath scaled; |
| 170 SkMatrix inverse; | 168 SkMatrix inverse; |
| 171 bool success = scale.invert(&inverse); | 169 bool success = scale.invert(&inverse); |
| 172 if (!success) { | 170 if (!success) { |
| 173 SkASSERT(0); | 171 SkASSERT(0); |
| 174 } | 172 } |
| 175 path.transform(inverse, &scaled); | 173 path.transform(inverse, &scaled); |
| 176 showPath(scaled, str); | 174 showPath(scaled, str); |
| 177 } | 175 } |
| 176 #endif |
| 178 | 177 |
| 179 #if DEBUG_SHOW_TEST_NAME | 178 #if DEBUG_SHOW_TEST_NAME |
| 180 static char hexorator(int x) { | 179 static char hexorator(int x) { |
| 181 if (x < 10) { | 180 if (x < 10) { |
| 182 return x + '0'; | 181 return x + '0'; |
| 183 } | 182 } |
| 184 x -= 10; | 183 x -= 10; |
| 185 SkASSERT(x < 26); | 184 SkASSERT(x < 26); |
| 186 return x + 'A'; | 185 return x + 'A'; |
| 187 } | 186 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; | 318 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; |
| 320 } | 319 } |
| 321 *outPtr++ = '\0'; | 320 *outPtr++ = '\0'; |
| 322 SkDebugf("%s\n", out); | 321 SkDebugf("%s\n", out); |
| 323 } | 322 } |
| 324 return true; | 323 return true; |
| 325 } | 324 } |
| 326 | 325 |
| 327 static void showSimplifiedPath(const SkPath& one, const SkPath& two, | 326 static void showSimplifiedPath(const SkPath& one, const SkPath& two, |
| 328 const SkPath& scaledOne, const SkPath& scaledTwo) { | 327 const SkPath& scaledOne, const SkPath& scaledTwo) { |
| 329 showPath(one, "original:"); | 328 showPath(one, ""); |
| 330 showPath(two, "simplified:"); | 329 // showPath(two, "simplified:"); |
| 331 drawAsciiPaths(scaledOne, scaledTwo, true); | 330 drawAsciiPaths(scaledOne, scaledTwo, true); |
| 332 } | 331 } |
| 333 | 332 |
| 334 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& two, | 333 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& two, |
| 335 SkBitmap& bitmap) { | 334 SkBitmap& bitmap) { |
| 336 int errors2x2; | 335 int errors2x2; |
| 337 SkPath scaledOne, scaledTwo; | 336 SkPath scaledOne, scaledTwo; |
| 338 int errors = pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors
2x2); | 337 int errors = pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors
2x2); |
| 339 if (errors2x2 == 0) { | 338 if (errors2x2 == 0) { |
| 340 return 0; | 339 return 0; |
| 341 } | 340 } |
| 342 const int MAX_ERRORS = 9; | 341 const int MAX_ERRORS = 9; |
| 343 if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) { | 342 if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) { |
| 344 showSimplifiedPath(one, two, scaledOne, scaledTwo); | 343 showSimplifiedPath(one, two, scaledOne, scaledTwo); |
| 345 } | 344 } |
| 346 if (errors2x2 > MAX_ERRORS && gComparePathsAssert) { | 345 if (errors2x2 > MAX_ERRORS && gComparePathsAssert) { |
| 347 SkDebugf("%s errors=%d\n", __FUNCTION__, errors); | 346 SkDebugf("%s errors=%d\n", __FUNCTION__, errors); |
| 348 showSimplifiedPath(one, two, scaledOne, scaledTwo); | 347 showSimplifiedPath(one, two, scaledOne, scaledTwo); |
| 349 REPORTER_ASSERT(reporter, 0); | 348 REPORTER_ASSERT(reporter, 0); |
| 350 } | 349 } |
| 351 return errors2x2 > MAX_ERRORS ? errors2x2 : 0; | 350 return errors2x2 > MAX_ERRORS ? errors2x2 : 0; |
| 352 } | 351 } |
| 353 | 352 |
| 354 static void showPathOpPath(const SkPath& one, const SkPath& two, const SkPath& a
, const SkPath& b, | 353 static void showPathOpPath(const SkPath& one, const SkPath& two, const SkPath& a
, const SkPath& b, |
| 355 const SkPath& scaledOne, const SkPath& scaledTwo, const SkPathOp shapeOp
, | 354 const SkPath& scaledOne, const SkPath& scaledTwo, const SkPathOp shapeOp
, |
| 356 const SkMatrix& scale) { | 355 const SkMatrix& scale) { |
| 357 SkASSERT((unsigned) shapeOp < SK_ARRAY_COUNT(opStrs)); | 356 SkASSERT((unsigned) shapeOp < SK_ARRAY_COUNT(opStrs)); |
| 358 showPath(a, "minuend:"); | 357 SkDebugf("static void xOp#%s(skiatest::Reporter* reporter) {\n", opSuffixes[
shapeOp]); |
| 359 SkDebugf("op: %s\n", opStrs[shapeOp]); | 358 SkDebugf(" SkPath path, pathB;\n"); |
| 360 showPath(b, "subtrahend:"); | 359 showPath(a, ""); |
| 360 showPath(b, "B"); |
| 361 SkDebugf(" testPathOp(reporter, path, pathB, %s);\n", opStrs[shapeOp]); |
| 362 SkDebugf("}\n"); |
| 361 // the region often isn't very helpful since it approximates curves with a l
ot of line-tos | 363 // the region often isn't very helpful since it approximates curves with a l
ot of line-tos |
| 362 if (0) showPath(scaledOne, "region:", scale); | 364 // if (0) showPath(scaledOne, "region:", scale); |
| 363 showPath(two, "op result:"); | 365 // showPath(two, "op result:"); |
| 364 drawAsciiPaths(scaledOne, scaledTwo, true); | 366 drawAsciiPaths(scaledOne, scaledTwo, true); |
| 365 } | 367 } |
| 366 | 368 |
| 367 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& scaledOne, | 369 static int comparePaths(skiatest::Reporter* reporter, const SkPath& one, const S
kPath& scaledOne, |
| 368 const SkPath& two, const SkPath& scaledTwo, SkBitmap& bi
tmap, | 370 const SkPath& two, const SkPath& scaledTwo, SkBitmap& bi
tmap, |
| 369 const SkPath& a, const SkPath& b, const SkPathOp shapeOp
, | 371 const SkPath& a, const SkPath& b, const SkPathOp shapeOp
, |
| 370 const SkMatrix& scale) { | 372 const SkMatrix& scale) { |
| 371 int errors2x2; | 373 int errors2x2; |
| 372 int errors = pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2); | 374 int errors = pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2); |
| 373 if (errors2x2 == 0) { | 375 if (errors2x2 == 0) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 writeTestName(nameSuffix, outFile); | 443 writeTestName(nameSuffix, outFile); |
| 442 outFile.writeText("),\n"); | 444 outFile.writeText("),\n"); |
| 443 outFile.flush(); | 445 outFile.flush(); |
| 444 } | 446 } |
| 445 | 447 |
| 446 bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st
ate, | 448 bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st
ate, |
| 447 const char* pathStr) { | 449 const char* pathStr) { |
| 448 SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWi
nding_FillType; | 450 SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWi
nding_FillType; |
| 449 path.setFillType(fillType); | 451 path.setFillType(fillType); |
| 450 if (gShowPath) { | 452 if (gShowPath) { |
| 451 showPath(path); | 453 showPath(path, ""); |
| 452 } | 454 } |
| 453 if (!Simplify(path, &out)) { | 455 if (!Simplify(path, &out)) { |
| 454 SkDebugf("%s did not expect failure\n", __FUNCTION__); | 456 SkDebugf("%s did not expect failure\n", __FUNCTION__); |
| 455 REPORTER_ASSERT(state.fReporter, 0); | 457 REPORTER_ASSERT(state.fReporter, 0); |
| 456 return false; | 458 return false; |
| 457 } | 459 } |
| 458 if (!gComparePaths) { | 460 if (!gComparePaths) { |
| 459 return true; | 461 return true; |
| 460 } | 462 } |
| 461 int result = comparePaths(state.fReporter, path, out, *state.fBitmap); | 463 int result = comparePaths(state.fReporter, path, out, *state.fBitmap); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 } | 616 } |
| 615 if (tests[index].fun == stopTest) { | 617 if (tests[index].fun == stopTest) { |
| 616 SkDebugf("lastTest\n"); | 618 SkDebugf("lastTest\n"); |
| 617 } | 619 } |
| 618 if (index == last) { | 620 if (index == last) { |
| 619 break; | 621 break; |
| 620 } | 622 } |
| 621 index += reverse ? -1 : 1; | 623 index += reverse ? -1 : 1; |
| 622 } while (true); | 624 } while (true); |
| 623 } | 625 } |
| OLD | NEW |