| 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 |