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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 int angleCount = sorted.count(); | 42 int angleCount = sorted.count(); |
43 #if DEBUG_SORT | 43 #if DEBUG_SORT |
44 sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, sortable); | 44 sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, sortable); |
45 #endif | 45 #endif |
46 if (!sortable) { | 46 if (!sortable) { |
47 continue; | 47 continue; |
48 } | 48 } |
49 // find first angle, initialize winding to computed fWindSum | 49 // find first angle, initialize winding to computed fWindSum |
50 int firstIndex = -1; | 50 int firstIndex = -1; |
51 const SkOpAngle* angle; | 51 const SkOpAngle* angle; |
| 52 bool foundAngle = true; |
52 do { | 53 do { |
53 angle = sorted[++firstIndex]; | 54 ++firstIndex; |
| 55 if (firstIndex >= angleCount) { |
| 56 foundAngle = false; |
| 57 break; |
| 58 } |
| 59 angle = sorted[firstIndex]; |
54 segment = angle->segment(); | 60 segment = angle->segment(); |
55 } while (segment->windSum(angle) == SK_MinS32); | 61 } while (segment->windSum(angle) == SK_MinS32); |
| 62 if (!foundAngle) { |
| 63 continue; |
| 64 } |
56 #if DEBUG_SORT | 65 #if DEBUG_SORT |
57 segment->debugShowSort(__FUNCTION__, sorted, firstIndex, sortable); | 66 segment->debugShowSort(__FUNCTION__, sorted, firstIndex, sortable); |
58 #endif | 67 #endif |
59 int sumMiWinding = segment->updateWindingReverse(angle); | 68 int sumMiWinding = segment->updateWindingReverse(angle); |
60 int sumSuWinding = segment->updateOppWindingReverse(angle); | 69 int sumSuWinding = segment->updateOppWindingReverse(angle); |
61 if (segment->operand()) { | 70 if (segment->operand()) { |
62 SkTSwap<int>(sumMiWinding, sumSuWinding); | 71 SkTSwap<int>(sumMiWinding, sumSuWinding); |
63 } | 72 } |
64 int nextIndex = firstIndex + 1; | 73 int nextIndex = firstIndex + 1; |
65 int lastIndex = firstIndex != 0 ? firstIndex : angleCount; | 74 int lastIndex = firstIndex != 0 ? firstIndex : angleCount; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 | 137 |
129 static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o
p, | 138 static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o
p, |
130 const int xorMask, const int xorOpMask, SkPathWriter* simple) { | 139 const int xorMask, const int xorOpMask, SkPathWriter* simple) { |
131 bool firstContour = true; | 140 bool firstContour = true; |
132 bool unsortable = false; | 141 bool unsortable = false; |
133 bool topUnsortable = false; | 142 bool topUnsortable = false; |
134 SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; | 143 SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; |
135 do { | 144 do { |
136 int index, endIndex; | 145 int index, endIndex; |
137 bool done; | 146 bool done; |
138 SkOpSegment* current = FindSortableTop(contourList, &firstContour, &inde
x, &endIndex, | 147 SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySi
ngle, &firstContour, |
139 &topLeft, &topUnsortable, &done, true); | 148 &index, &endIndex, &topLeft, &topUnsortable, &done); |
140 if (!current) { | 149 if (!current) { |
141 if (topUnsortable || !done) { | 150 if (topUnsortable || !done) { |
142 topUnsortable = false; | 151 topUnsortable = false; |
143 SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMi
n); | 152 SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMi
n); |
144 topLeft.fX = topLeft.fY = SK_ScalarMin; | 153 topLeft.fX = topLeft.fY = SK_ScalarMin; |
145 continue; | 154 continue; |
146 } | 155 } |
147 break; | 156 break; |
148 } | 157 } |
149 SkTDArray<SkOpSpan*> chaseArray; | 158 SkTDArray<SkOpSpan*> chaseArray; |
(...skipping 28 matching lines...) Expand all Loading... |
178 current->debugID(), current->xyAtT(index).fX, current->xyAtT
(index).fY, | 187 current->debugID(), current->xyAtT(index).fX, current->xyAtT
(index).fY, |
179 current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY); | 188 current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY); |
180 #endif | 189 #endif |
181 current->addCurveTo(index, endIndex, simple, true); | 190 current->addCurveTo(index, endIndex, simple, true); |
182 current = next; | 191 current = next; |
183 index = nextStart; | 192 index = nextStart; |
184 endIndex = nextEnd; | 193 endIndex = nextEnd; |
185 } while (!simple->isClosed() && (!unsortable | 194 } while (!simple->isClosed() && (!unsortable |
186 || !current->done(SkMin32(index, endIndex)))); | 195 || !current->done(SkMin32(index, endIndex)))); |
187 if (current->activeWinding(index, endIndex) && !simple->isClosed
()) { | 196 if (current->activeWinding(index, endIndex) && !simple->isClosed
()) { |
| 197 // FIXME : add to simplify, xor cpaths |
| 198 int min = SkMin32(index, endIndex); |
| 199 if (!unsortable && !simple->isEmpty()) { |
| 200 unsortable = current->checkSmall(min); |
| 201 } |
188 SkASSERT(unsortable || simple->isEmpty()); | 202 SkASSERT(unsortable || simple->isEmpty()); |
189 int min = SkMin32(index, endIndex); | |
190 if (!current->done(min)) { | 203 if (!current->done(min)) { |
191 current->addCurveTo(index, endIndex, simple, true); | 204 current->addCurveTo(index, endIndex, simple, true); |
192 current->markDoneBinary(min); | 205 current->markDoneBinary(min); |
193 } | 206 } |
194 } | 207 } |
195 simple->close(); | 208 simple->close(); |
196 } else { | 209 } else { |
197 SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex
); | 210 SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex
); |
198 if (last && !last->fLoop) { | 211 if (last && !last->fLoop) { |
199 *chaseArray.append() = last; | 212 *chaseArray.append() = last; |
(...skipping 28 matching lines...) Expand all Loading... |
228 {{ false, false }, { false, true }}, // sect | 241 {{ false, false }, { false, true }}, // sect |
229 {{ false, true }, { true, true }}, // union | 242 {{ false, true }, { true, true }}, // union |
230 {{ false, true }, { true, false }}, // xor | 243 {{ false, true }, { true, false }}, // xor |
231 {{ false, true }, { false, false }}, // rev diff | 244 {{ false, true }, { false, false }}, // rev diff |
232 }; | 245 }; |
233 | 246 |
234 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { | 247 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { |
235 #if DEBUG_SHOW_TEST_NAME | 248 #if DEBUG_SHOW_TEST_NAME |
236 char* debugName = DEBUG_FILENAME_STRING; | 249 char* debugName = DEBUG_FILENAME_STRING; |
237 if (debugName && debugName[0]) { | 250 if (debugName && debugName[0]) { |
238 DebugBumpTestName(debugName); | 251 SkPathOpsDebug::BumpTestName(debugName); |
239 DebugShowPath(one, two, op, debugName); | 252 SkPathOpsDebug::ShowPath(one, two, op, debugName); |
240 } | 253 } |
241 #endif | 254 #endif |
242 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; | 255 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; |
243 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI
nverseFillType()] | 256 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI
nverseFillType()] |
244 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; | 257 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; |
245 const SkPath* minuend = &one; | 258 const SkPath* minuend = &one; |
246 const SkPath* subtrahend = &two; | 259 const SkPath* subtrahend = &two; |
247 if (op == kReverseDifference_PathOp) { | 260 if (op == kReverseDifference_PathOp) { |
248 minuend = &two; | 261 minuend = &two; |
249 subtrahend = &one; | 262 subtrahend = &one; |
250 op = kDifference_PathOp; | 263 op = kDifference_PathOp; |
251 } | 264 } |
252 #if DEBUG_SORT || DEBUG_SWAP_TOP | 265 #if DEBUG_SORT || DEBUG_SWAP_TOP |
253 gDebugSortCount = gDebugSortCountDefault; | 266 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault; |
254 #endif | 267 #endif |
255 // turn path into list of segments | 268 // turn path into list of segments |
256 SkTArray<SkOpContour> contours; | 269 SkTArray<SkOpContour> contours; |
257 // FIXME: add self-intersecting cubics' T values to segment | 270 // FIXME: add self-intersecting cubics' T values to segment |
258 SkOpEdgeBuilder builder(*minuend, contours); | 271 SkOpEdgeBuilder builder(*minuend, contours); |
259 const int xorMask = builder.xorMask(); | 272 const int xorMask = builder.xorMask(); |
260 builder.addOperand(*subtrahend); | 273 builder.addOperand(*subtrahend); |
261 if (!builder.finish()) { | 274 if (!builder.finish()) { |
262 return false; | 275 return false; |
263 } | 276 } |
(...skipping 29 matching lines...) Expand all Loading... |
293 } | 306 } |
294 #if DEBUG_SHOW_WINDING | 307 #if DEBUG_SHOW_WINDING |
295 SkOpContour::debugShowWindingValues(contourList); | 308 SkOpContour::debugShowWindingValues(contourList); |
296 #endif | 309 #endif |
297 CoincidenceCheck(&contourList, total); | 310 CoincidenceCheck(&contourList, total); |
298 #if DEBUG_SHOW_WINDING | 311 #if DEBUG_SHOW_WINDING |
299 SkOpContour::debugShowWindingValues(contourList); | 312 SkOpContour::debugShowWindingValues(contourList); |
300 #endif | 313 #endif |
301 FixOtherTIndex(&contourList); | 314 FixOtherTIndex(&contourList); |
302 CheckEnds(&contourList); | 315 CheckEnds(&contourList); |
| 316 CheckTiny(&contourList); |
303 SortSegments(&contourList); | 317 SortSegments(&contourList); |
304 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY | 318 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY |
305 DebugShowActiveSpans(contourList); | 319 DebugShowActiveSpans(contourList); |
306 #endif | 320 #endif |
307 // construct closed contours | 321 // construct closed contours |
308 SkPathWriter wrapper(*result); | 322 SkPathWriter wrapper(*result); |
309 bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper); | 323 bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper); |
310 { // if some edges could not be resolved, assemble remaining fragments | 324 { // if some edges could not be resolved, assemble remaining fragments |
311 SkPath temp; | 325 SkPath temp; |
312 temp.setFillType(fillType); | 326 temp.setFillType(fillType); |
313 SkPathWriter assembled(temp); | 327 SkPathWriter assembled(temp); |
314 Assemble(wrapper, &assembled); | 328 Assemble(wrapper, &assembled); |
315 *result = *assembled.nativePath(); | 329 *result = *assembled.nativePath(); |
316 result->setFillType(fillType); | 330 result->setFillType(fillType); |
317 } | 331 } |
318 return true; | 332 return true; |
319 } | 333 } |
OLD | NEW |