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 bool loop = false; | 48 SkDEBUGCODE(bool loop = false); |
49 int winding; | 49 int winding; |
50 do { | 50 do { |
51 angle = angle->next(); | 51 angle = angle->next(); |
52 if (angle == firstAngle && loop) { | 52 SkASSERT(angle != firstAngle || !loop); |
53 break; // if we get here, there's no winding, loop is unorder
able | 53 SkDEBUGCODE(loop |= angle == firstAngle); |
54 } | |
55 loop |= angle == firstAngle; | |
56 segment = angle->segment(); | 54 segment = angle->segment(); |
57 winding = segment->windSum(angle); | 55 winding = segment->windSum(angle); |
58 } while (winding == SK_MinS32); | 56 } while (winding == SK_MinS32); |
59 if (winding == SK_MinS32) { | |
60 continue; | |
61 } | |
62 int sumMiWinding = segment->updateWindingReverse(angle); | 57 int sumMiWinding = segment->updateWindingReverse(angle); |
63 int sumSuWinding = segment->updateOppWindingReverse(angle); | 58 int sumSuWinding = segment->updateOppWindingReverse(angle); |
64 if (segment->operand()) { | 59 if (segment->operand()) { |
65 SkTSwap<int>(sumMiWinding, sumSuWinding); | 60 SkTSwap<int>(sumMiWinding, sumSuWinding); |
66 } | 61 } |
67 SkOpSegment* first = NULL; | 62 SkOpSegment* first = NULL; |
68 bool badData = false; | 63 while ((angle = angle->next()) != firstAngle) { |
69 while ((angle = angle->next()) != firstAngle && !badData) { | |
70 segment = angle->segment(); | 64 segment = angle->segment(); |
71 int start = angle->start(); | 65 int start = angle->start(); |
72 int end = angle->end(); | 66 int end = angle->end(); |
73 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; | 67 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; |
74 segment->setUpWindings(start, end, &sumMiWinding, &sumSuWinding, | 68 segment->setUpWindings(start, end, &sumMiWinding, &sumSuWinding, |
75 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); | 69 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); |
76 if (!segment->done(angle)) { | 70 if (!segment->done(angle)) { |
77 if (!first) { | 71 if (!first) { |
78 first = segment; | 72 first = segment; |
79 *tIndex = start; | 73 *tIndex = start; |
80 *endIndex = end; | 74 *endIndex = end; |
81 } | 75 } |
82 if (segment->inconsistentAngle(maxWinding, sumWinding, oppMaxWin
ding, | |
83 oppSumWinding, angle)) { | |
84 badData = true; | |
85 break; | |
86 } | |
87 // OPTIMIZATION: should this also add to the chase? | 76 // OPTIMIZATION: should this also add to the chase? |
88 (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, | 77 (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, |
89 oppSumWinding, angle); | 78 oppSumWinding, angle); |
90 } | 79 } |
91 } | 80 } |
92 if (badData) { | |
93 continue; | |
94 } | |
95 if (first) { | 81 if (first) { |
96 #if TRY_ROTATE | 82 #if TRY_ROTATE |
97 *chase.insert(0) = span; | 83 *chase.insert(0) = span; |
98 #else | 84 #else |
99 *chase.append() = span; | 85 *chase.append() = span; |
100 #endif | 86 #endif |
101 return first; | 87 return first; |
102 } | 88 } |
103 } | 89 } |
104 return NULL; | 90 return NULL; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 }; | 238 }; |
253 | 239 |
254 static const bool gOutInverse[kReverseDifference_PathOp + 1][2][2] = { | 240 static const bool gOutInverse[kReverseDifference_PathOp + 1][2][2] = { |
255 {{ false, false }, { true, false }}, // diff | 241 {{ false, false }, { true, false }}, // diff |
256 {{ false, false }, { false, true }}, // sect | 242 {{ false, false }, { false, true }}, // sect |
257 {{ false, true }, { true, true }}, // union | 243 {{ false, true }, { true, true }}, // union |
258 {{ false, true }, { true, false }}, // xor | 244 {{ false, true }, { true, false }}, // xor |
259 {{ false, true }, { false, false }}, // rev diff | 245 {{ false, true }, { false, false }}, // rev diff |
260 }; | 246 }; |
261 | 247 |
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 FILE* file = fopen("/usr/local/google/home/caryclark/Documents/svgop.txt", "
w"); | |
278 fprintf(file, "\nstatic void test_%d(skiatest::Reporter* reporter, const cha
r* filename) {\n", | |
279 ++dumpID); | |
280 fprintf(file, " SkPath path;\n"); | |
281 fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillT
ype()); | |
282 dump_path(file, one, false, true); | |
283 fprintf(file, " SkPath path1(path);\n"); | |
284 fprintf(file, " path.reset();\n"); | |
285 fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillT
ype()); | |
286 dump_path(file, two, false, true); | |
287 fprintf(file, " SkPath path2(path);\n"); | |
288 fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filenam
e);\n", op); | |
289 fprintf(file, "}\n"); | |
290 fclose(file); | |
291 } | |
292 #endif | |
293 | |
294 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { | 248 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { |
295 #if DEBUGGING_PATHOPS_FROM_HOST | |
296 dump_op(one, two, op); | |
297 #endif | |
298 #if DEBUG_SHOW_TEST_NAME | 249 #if DEBUG_SHOW_TEST_NAME |
299 char* debugName = DEBUG_FILENAME_STRING; | 250 char* debugName = DEBUG_FILENAME_STRING; |
300 if (debugName && debugName[0]) { | 251 if (debugName && debugName[0]) { |
301 SkPathOpsDebug::BumpTestName(debugName); | 252 SkPathOpsDebug::BumpTestName(debugName); |
302 SkPathOpsDebug::ShowPath(one, two, op, debugName); | 253 SkPathOpsDebug::ShowPath(one, two, op, debugName); |
303 } | 254 } |
304 #endif | 255 #endif |
305 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; | 256 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; |
306 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI
nverseFillType()] | 257 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI
nverseFillType()] |
307 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; | 258 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 { // if some edges could not be resolved, assemble remaining fragments | 317 { // if some edges could not be resolved, assemble remaining fragments |
367 SkPath temp; | 318 SkPath temp; |
368 temp.setFillType(fillType); | 319 temp.setFillType(fillType); |
369 SkPathWriter assembled(temp); | 320 SkPathWriter assembled(temp); |
370 Assemble(wrapper, &assembled); | 321 Assemble(wrapper, &assembled); |
371 *result = *assembled.nativePath(); | 322 *result = *assembled.nativePath(); |
372 result->setFillType(fillType); | 323 result->setFillType(fillType); |
373 } | 324 } |
374 return true; | 325 return true; |
375 } | 326 } |
OLD | NEW |