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 "SkOpCoincidence.h" | 8 #include "SkOpCoincidence.h" |
9 #include "SkOpEdgeBuilder.h" | 9 #include "SkOpEdgeBuilder.h" |
10 #include "SkPathOpsCommon.h" | 10 #include "SkPathOpsCommon.h" |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 } while (!simple->isClosed() && (!unsortable || !start->starter(
end)->done())); | 145 } while (!simple->isClosed() && (!unsortable || !start->starter(
end)->done())); |
146 if (current->activeWinding(start, end) && !simple->isClosed()) { | 146 if (current->activeWinding(start, end) && !simple->isClosed()) { |
147 SkOpSpan* spanStart = start->starter(end); | 147 SkOpSpan* spanStart = start->starter(end); |
148 if (!spanStart->done()) { | 148 if (!spanStart->done()) { |
149 if (!current->addCurveTo(start, end, simple)) { | 149 if (!current->addCurveTo(start, end, simple)) { |
150 return false; | 150 return false; |
151 } | 151 } |
152 current->markDone(spanStart); | 152 current->markDone(spanStart); |
153 } | 153 } |
154 } | 154 } |
155 simple->close(); | 155 simple->finishContour(); |
156 } else { | 156 } else { |
157 SkOpSpanBase* last = current->markAndChaseDone(start, end); | 157 SkOpSpanBase* last = current->markAndChaseDone(start, end); |
158 if (last && !last->chased()) { | 158 if (last && !last->chased()) { |
159 last->setChased(true); | 159 last->setChased(true); |
160 SkASSERT(!SkPathOpsDebug::ChaseContains(chase, last)); | 160 SkASSERT(!SkPathOpsDebug::ChaseContains(chase, last)); |
161 *chase.append() = last; | 161 *chase.append() = last; |
162 #if DEBUG_WINDING | 162 #if DEBUG_WINDING |
163 SkDebugf("%s chase.append id=%d", __FUNCTION__, last->segmen
t()->debugID()); | 163 SkDebugf("%s chase.append id=%d", __FUNCTION__, last->segmen
t()->debugID()); |
164 if (!last->final()) { | 164 if (!last->final()) { |
165 SkDebugf(" windSum=%d", last->upCast()->windSum()); | 165 SkDebugf(" windSum=%d", last->upCast()->windSum()); |
166 } | 166 } |
167 SkDebugf("\n"); | 167 SkDebugf("\n"); |
168 #endif | 168 #endif |
169 } | 169 } |
170 } | 170 } |
171 current = findChaseOp(chase, &start, &end); | 171 current = findChaseOp(chase, &start, &end); |
172 SkPathOpsDebug::ShowActiveSpans(contourList); | 172 SkPathOpsDebug::ShowActiveSpans(contourList); |
173 if (!current) { | 173 if (!current) { |
174 break; | 174 break; |
175 } | 175 } |
176 } while (true); | 176 } while (true); |
177 } while (true); | 177 } while (true); |
178 return simple->someAssemblyRequired(); | 178 return true; |
179 } | 179 } |
180 | 180 |
181 // pretty picture: | 181 // pretty picture: |
182 // https://docs.google.com/a/google.com/drawings/d/1sPV8rPfpEFXymBp3iSbDRWAycp1b
-7vD9JP2V-kn9Ss/edit?usp=sharing | 182 // https://docs.google.com/a/google.com/drawings/d/1sPV8rPfpEFXymBp3iSbDRWAycp1b
-7vD9JP2V-kn9Ss/edit?usp=sharing |
183 static const SkPathOp gOpInverse[kReverseDifference_SkPathOp + 1][2][2] = { | 183 static const SkPathOp gOpInverse[kReverseDifference_SkPathOp + 1][2][2] = { |
184 // inside minuend outside minuend | 184 // inside minuend outside minuend |
185 // inside subtrahend outside subtrahend inside subtrahend outsi
de subtrahend | 185 // inside subtrahend outside subtrahend inside subtrahend outsi
de subtrahend |
186 {{ kDifference_SkPathOp, kIntersect_SkPathOp }, { kUnion_SkPathOp, kReverseDif
ference_SkPathOp }}, | 186 {{ kDifference_SkPathOp, kIntersect_SkPathOp }, { kUnion_SkPathOp, kReverseDif
ference_SkPathOp }}, |
187 {{ kIntersect_SkPathOp, kDifference_SkPathOp }, { kReverseDifference_SkPathOp,
kUnion_SkPathOp }}, | 187 {{ kIntersect_SkPathOp, kDifference_SkPathOp }, { kReverseDifference_SkPathOp,
kUnion_SkPathOp }}, |
188 {{ kUnion_SkPathOp, kReverseDifference_SkPathOp }, { kDifference_SkPathOp, kIn
tersect_SkPathOp }}, | 188 {{ kUnion_SkPathOp, kReverseDifference_SkPathOp }, { kDifference_SkPathOp, kIn
tersect_SkPathOp }}, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 subtrahend = &two; | 279 subtrahend = &two; |
280 } | 280 } |
281 if (op == kReverseDifference_SkPathOp) { | 281 if (op == kReverseDifference_SkPathOp) { |
282 SkTSwap(minuend, subtrahend); | 282 SkTSwap(minuend, subtrahend); |
283 op = kDifference_SkPathOp; | 283 op = kDifference_SkPathOp; |
284 } | 284 } |
285 #if DEBUG_SORT | 285 #if DEBUG_SORT |
286 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault; | 286 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault; |
287 #endif | 287 #endif |
288 // turn path into list of segments | 288 // turn path into list of segments |
289 SkOpEdgeBuilder builder(*minuend, &contour, &globalState); | 289 SkOpEdgeBuilder builder(*minuend, contourList, &globalState); |
290 if (builder.unparseable()) { | 290 if (builder.unparseable()) { |
291 return false; | 291 return false; |
292 } | 292 } |
293 const int xorMask = builder.xorMask(); | 293 const int xorMask = builder.xorMask(); |
294 builder.addOperand(*subtrahend); | 294 builder.addOperand(*subtrahend); |
295 if (!builder.finish()) { | 295 if (!builder.finish()) { |
296 return false; | 296 return false; |
297 } | 297 } |
298 #if DEBUG_DUMP_SEGMENTS | 298 #if DEBUG_DUMP_SEGMENTS |
299 contourList->dumpSegments("seg", op); | 299 contourList->dumpSegments("seg", op); |
(...skipping 20 matching lines...) Expand all Loading... |
320 if (!HandleCoincidence(contourList, &coincidence)) { | 320 if (!HandleCoincidence(contourList, &coincidence)) { |
321 return false; | 321 return false; |
322 } | 322 } |
323 #if DEBUG_ALIGNMENT | 323 #if DEBUG_ALIGNMENT |
324 contourList->dumpSegments("aligned"); | 324 contourList->dumpSegments("aligned"); |
325 #endif | 325 #endif |
326 // construct closed contours | 326 // construct closed contours |
327 result->reset(); | 327 result->reset(); |
328 result->setFillType(fillType); | 328 result->setFillType(fillType); |
329 SkPathWriter wrapper(*result); | 329 SkPathWriter wrapper(*result); |
330 bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper); | 330 if (!bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper)) { |
331 { // if some edges could not be resolved, assemble remaining fragments | 331 return false; |
332 SkPath temp; | |
333 temp.setFillType(fillType); | |
334 SkPathWriter assembled(temp); | |
335 Assemble(wrapper, &assembled); | |
336 *result = *assembled.nativePath(); | |
337 result->setFillType(fillType); | |
338 } | 332 } |
| 333 wrapper.assemble(); // if some edges could not be resolved, assemble remain
ing |
339 #if DEBUG_T_SECT_LOOP_COUNT | 334 #if DEBUG_T_SECT_LOOP_COUNT |
340 { | 335 { |
341 SkAutoMutexAcquire autoM(debugWorstLoop); | 336 SkAutoMutexAcquire autoM(debugWorstLoop); |
342 if (!gVerboseFinalize) { | 337 if (!gVerboseFinalize) { |
343 gVerboseFinalize = &ReportPathOpsDebugging; | 338 gVerboseFinalize = &ReportPathOpsDebugging; |
344 } | 339 } |
345 debugWorstState.debugDoYourWorst(&globalState); | 340 debugWorstState.debugDoYourWorst(&globalState); |
346 } | 341 } |
347 #endif | 342 #endif |
348 if (scaleFactor > 1) { | 343 if (scaleFactor > 1) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 one.dumpHex(); | 458 one.dumpHex(); |
464 SkDebugf("two: fill=%d\n", two.getFillType()); | 459 SkDebugf("two: fill=%d\n", two.getFillType()); |
465 two.dumpHex(); | 460 two.dumpHex(); |
466 SkASSERT(0); | 461 SkASSERT(0); |
467 } | 462 } |
468 return true; | 463 return true; |
469 #else | 464 #else |
470 return OpDebug(one, two, op, result SkDEBUGPARAMS(true) SkDEBUGPARAMS(nullp
tr)); | 465 return OpDebug(one, two, op, result SkDEBUGPARAMS(true) SkDEBUGPARAMS(nullp
tr)); |
471 #endif | 466 #endif |
472 } | 467 } |
OLD | NEW |