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 #include "SkAddIntersections.h" | 7 #include "SkAddIntersections.h" |
8 #include "SkOpEdgeBuilder.h" | 8 #include "SkOpEdgeBuilder.h" |
9 #include "SkPathOpsCommon.h" | 9 #include "SkPathOpsCommon.h" |
10 #include "SkPathWriter.h" | 10 #include "SkPathWriter.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 } | 38 } |
39 if (!sortable) { | 39 if (!sortable) { |
40 continue; | 40 continue; |
41 } | 41 } |
42 // find first angle, initialize winding to computed fWindSum | 42 // find first angle, initialize winding to computed fWindSum |
43 const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); | 43 const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); |
44 if (!angle) { | 44 if (!angle) { |
45 continue; | 45 continue; |
46 } | 46 } |
47 const SkOpAngle* firstAngle = angle; | 47 const SkOpAngle* firstAngle = angle; |
48 SkDEBUGCODE(bool loop = false); | 48 bool loop = false; |
49 int winding; | 49 int winding = SK_MinS32; |
50 do { | 50 do { |
51 angle = angle->next(); | 51 angle = angle->next(); |
52 SkASSERT(angle != firstAngle || !loop); | 52 if (angle == firstAngle && loop) { |
53 SkDEBUGCODE(loop |= angle == firstAngle); | 53 break; // if we get here, there's no winding, loop is unorder
able |
| 54 } |
| 55 loop |= angle == firstAngle; |
54 segment = angle->segment(); | 56 segment = angle->segment(); |
55 winding = segment->windSum(angle); | 57 winding = segment->windSum(angle); |
56 } while (winding == SK_MinS32); | 58 } while (winding == SK_MinS32); |
| 59 if (winding == SK_MinS32) { |
| 60 continue; |
| 61 } |
57 int sumMiWinding = segment->updateWindingReverse(angle); | 62 int sumMiWinding = segment->updateWindingReverse(angle); |
58 int sumSuWinding = segment->updateOppWindingReverse(angle); | 63 int sumSuWinding = segment->updateOppWindingReverse(angle); |
59 if (segment->operand()) { | 64 if (segment->operand()) { |
60 SkTSwap<int>(sumMiWinding, sumSuWinding); | 65 SkTSwap<int>(sumMiWinding, sumSuWinding); |
61 } | 66 } |
62 SkOpSegment* first = NULL; | 67 SkOpSegment* first = NULL; |
63 while ((angle = angle->next()) != firstAngle) { | 68 bool badData = false; |
| 69 while ((angle = angle->next()) != firstAngle && !badData) { |
64 segment = angle->segment(); | 70 segment = angle->segment(); |
65 int start = angle->start(); | 71 int start = angle->start(); |
66 int end = angle->end(); | 72 int end = angle->end(); |
67 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; | 73 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; |
68 segment->setUpWindings(start, end, &sumMiWinding, &sumSuWinding, | 74 segment->setUpWindings(start, end, &sumMiWinding, &sumSuWinding, |
69 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); | 75 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); |
70 if (!segment->done(angle)) { | 76 if (!segment->done(angle)) { |
71 if (!first) { | 77 if (!first) { |
72 first = segment; | 78 first = segment; |
73 *tIndex = start; | 79 *tIndex = start; |
74 *endIndex = end; | 80 *endIndex = end; |
75 } | 81 } |
| 82 if (segment->inconsistentAngle(maxWinding, sumWinding, oppMaxWin
ding, |
| 83 oppSumWinding, angle)) { |
| 84 badData = true; |
| 85 break; |
| 86 } |
76 // OPTIMIZATION: should this also add to the chase? | 87 // OPTIMIZATION: should this also add to the chase? |
77 (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, | 88 (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, |
78 oppSumWinding, angle); | 89 oppSumWinding, angle); |
79 } | 90 } |
80 } | 91 } |
| 92 if (badData) { |
| 93 continue; |
| 94 } |
81 if (first) { | 95 if (first) { |
82 #if TRY_ROTATE | 96 #if TRY_ROTATE |
83 *chase.insert(0) = span; | 97 *chase.insert(0) = span; |
84 #else | 98 #else |
85 *chase.append() = span; | 99 *chase.append() = span; |
86 #endif | 100 #endif |
87 return first; | 101 return first; |
88 } | 102 } |
89 } | 103 } |
90 return NULL; | 104 return NULL; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 }; | 252 }; |
239 | 253 |
240 static const bool gOutInverse[kReverseDifference_PathOp + 1][2][2] = { | 254 static const bool gOutInverse[kReverseDifference_PathOp + 1][2][2] = { |
241 {{ false, false }, { true, false }}, // diff | 255 {{ false, false }, { true, false }}, // diff |
242 {{ false, false }, { false, true }}, // sect | 256 {{ false, false }, { false, true }}, // sect |
243 {{ false, true }, { true, true }}, // union | 257 {{ false, true }, { true, true }}, // union |
244 {{ false, true }, { true, false }}, // xor | 258 {{ false, true }, { true, false }}, // xor |
245 {{ false, true }, { false, false }}, // rev diff | 259 {{ false, true }, { false, false }}, // rev diff |
246 }; | 260 }; |
247 | 261 |
| 262 #define DEBUGGING_PATHOPS_FROM_HOST 0 // enable to debug svg in chrome -- note
path hardcoded below |
| 263 #if DEBUGGING_PATHOPS_FROM_HOST |
| 264 #include "SkData.h" |
| 265 #include "SkStream.h" |
| 266 |
| 267 static void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex
) { |
| 268 SkDynamicMemoryWStream wStream; |
| 269 path.dump(&wStream, force, dumpAsHex); |
| 270 SkAutoDataUnref data(wStream.copyToData()); |
| 271 fprintf(file, "%.*s\n", (int) data->size(), data->data()); |
| 272 } |
| 273 |
| 274 static int dumpID = 0; |
| 275 |
| 276 static void dump_op(const SkPath& one, const SkPath& two, SkPathOp op) { |
| 277 #if SK_BUILD_FOR_MAC |
| 278 FILE* file = fopen("/Users/caryclark/Documents/svgop.txt", "w"); |
| 279 #else |
| 280 FILE* file = fopen("/usr/local/google/home/caryclark/Documents/svgop.txt", "
w"); |
| 281 #endif |
| 282 fprintf(file, |
| 283 "\nstatic void fuzz763_%d(skiatest::Reporter* reporter, const char*
filename) {\n", |
| 284 ++dumpID); |
| 285 fprintf(file, " SkPath path;\n"); |
| 286 fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillT
ype()); |
| 287 dump_path(file, one, false, true); |
| 288 fprintf(file, " SkPath path1(path);\n"); |
| 289 fprintf(file, " path.reset();\n"); |
| 290 fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillT
ype()); |
| 291 dump_path(file, two, false, true); |
| 292 fprintf(file, " SkPath path2(path);\n"); |
| 293 fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filenam
e);\n", op); |
| 294 fprintf(file, "}\n"); |
| 295 fclose(file); |
| 296 } |
| 297 #endif |
| 298 |
248 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { | 299 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { |
| 300 #if DEBUGGING_PATHOPS_FROM_HOST |
| 301 dump_op(one, two, op); |
| 302 #endif |
249 #if DEBUG_SHOW_TEST_NAME | 303 #if DEBUG_SHOW_TEST_NAME |
250 char* debugName = DEBUG_FILENAME_STRING; | 304 char* debugName = DEBUG_FILENAME_STRING; |
251 if (debugName && debugName[0]) { | 305 if (debugName && debugName[0]) { |
252 SkPathOpsDebug::BumpTestName(debugName); | 306 SkPathOpsDebug::BumpTestName(debugName); |
253 SkPathOpsDebug::ShowPath(one, two, op, debugName); | 307 SkPathOpsDebug::ShowPath(one, two, op, debugName); |
254 } | 308 } |
255 #endif | 309 #endif |
256 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; | 310 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; |
257 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI
nverseFillType()] | 311 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI
nverseFillType()] |
258 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; | 312 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 { // if some edges could not be resolved, assemble remaining fragments | 371 { // if some edges could not be resolved, assemble remaining fragments |
318 SkPath temp; | 372 SkPath temp; |
319 temp.setFillType(fillType); | 373 temp.setFillType(fillType); |
320 SkPathWriter assembled(temp); | 374 SkPathWriter assembled(temp); |
321 Assemble(wrapper, &assembled); | 375 Assemble(wrapper, &assembled); |
322 *result = *assembled.nativePath(); | 376 *result = *assembled.nativePath(); |
323 result->setFillType(fillType); | 377 result->setFillType(fillType); |
324 } | 378 } |
325 return true; | 379 return true; |
326 } | 380 } |
OLD | NEW |