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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 for (int cIndex = 0; cIndex < contourCount; ++cIndex) { | 104 for (int cIndex = 0; cIndex < contourCount; ++cIndex) { |
105 SkOpContour* contour = contourList[cIndex]; | 105 SkOpContour* contour = contourList[cIndex]; |
106 result = contour->undoneSegment(start, end); | 106 result = contour->undoneSegment(start, end); |
107 if (result) { | 107 if (result) { |
108 return result; | 108 return result; |
109 } | 109 } |
110 } | 110 } |
111 return NULL; | 111 return NULL; |
112 } | 112 } |
113 | 113 |
114 SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
{ | 114 SkOpSegment* FindChase(SkTDArray<SkOpSpan*>* chase, int* tIndex, int* endIndex)
{ |
115 while (chase.count()) { | 115 while (chase->count()) { |
116 SkOpSpan* span; | 116 SkOpSpan* span; |
117 chase.pop(&span); | 117 chase->pop(&span); |
118 const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex); | 118 const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex); |
119 SkOpSegment* segment = backPtr.fOther; | 119 SkOpSegment* segment = backPtr.fOther; |
120 tIndex = backPtr.fOtherIndex; | 120 *tIndex = backPtr.fOtherIndex; |
121 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles; | 121 bool sortable = true; |
122 int done = 0; | 122 bool done = true; |
123 if (segment->activeAngle(tIndex, &done, &angles)) { | 123 *endIndex = -1; |
124 SkOpAngle* last = angles.end() - 1; | 124 if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endInd
ex, &done, |
125 tIndex = last->start(); | 125 &sortable)) { |
126 endIndex = last->end(); | 126 *tIndex = last->start(); |
127 #if TRY_ROTATE | 127 *endIndex = last->end(); |
128 *chase.insert(0) = span; | 128 #if TRY_ROTATE |
129 #else | 129 *chase->insert(0) = span; |
130 *chase.append() = span; | 130 #else |
131 #endif | 131 *chase->append() = span; |
| 132 #endif |
132 return last->segment(); | 133 return last->segment(); |
133 } | 134 } |
134 if (done == angles.count()) { | 135 if (done) { |
135 continue; | 136 continue; |
136 } | 137 } |
137 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; | |
138 bool sortable = SkOpSegment::SortAngles(angles, &sorted, | |
139 SkOpSegment::kMayBeUnordered_SortAngleKind); | |
140 int angleCount = sorted.count(); | |
141 #if DEBUG_SORT | |
142 sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0, sorta
ble); | |
143 #endif | |
144 if (!sortable) { | 138 if (!sortable) { |
145 continue; | 139 continue; |
146 } | 140 } |
147 // find first angle, initialize winding to computed fWindSum | 141 // find first angle, initialize winding to computed fWindSum |
148 int firstIndex = -1; | 142 const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); |
149 const SkOpAngle* angle; | 143 const SkOpAngle* firstAngle; |
| 144 SkDEBUGCODE(firstAngle = angle); |
| 145 SkDEBUGCODE(bool loop = false); |
150 int winding; | 146 int winding; |
151 do { | 147 do { |
152 angle = sorted[++firstIndex]; | 148 angle = angle->next(); |
| 149 SkASSERT(angle != firstAngle || !loop); |
| 150 SkDEBUGCODE(loop |= angle == firstAngle); |
153 segment = angle->segment(); | 151 segment = angle->segment(); |
154 winding = segment->windSum(angle); | 152 winding = segment->windSum(angle); |
155 } while (winding == SK_MinS32); | 153 } while (winding == SK_MinS32); |
156 int spanWinding = segment->spanSign(angle->start(), angle->end()); | 154 int spanWinding = segment->spanSign(angle->start(), angle->end()); |
157 #if DEBUG_WINDING | 155 #if DEBUG_WINDING |
158 SkDebugf("%s winding=%d spanWinding=%d\n", | 156 SkDebugf("%s winding=%d spanWinding=%d\n", __FUNCTION__, winding, spanWi
nding); |
159 __FUNCTION__, winding, spanWinding); | |
160 #endif | 157 #endif |
161 // turn span winding into contour winding | 158 // turn span winding into contour winding |
162 if (spanWinding * winding < 0) { | 159 if (spanWinding * winding < 0) { |
163 winding += spanWinding; | 160 winding += spanWinding; |
164 } | 161 } |
165 #if DEBUG_SORT | |
166 segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, 0, sor
table); | |
167 #endif | |
168 // we care about first sign and whether wind sum indicates this | 162 // we care about first sign and whether wind sum indicates this |
169 // edge is inside or outside. Maybe need to pass span winding | 163 // edge is inside or outside. Maybe need to pass span winding |
170 // or first winding or something into this function? | 164 // or first winding or something into this function? |
171 // advance to first undone angle, then return it and winding | 165 // advance to first undone angle, then return it and winding |
172 // (to set whether edges are active or not) | 166 // (to set whether edges are active or not) |
173 int nextIndex = firstIndex + 1; | 167 firstAngle = angle; |
174 int lastIndex = firstIndex != 0 ? firstIndex : angleCount; | 168 winding -= firstAngle->segment()->spanSign(firstAngle); |
175 angle = sorted[firstIndex]; | 169 while ((angle = angle->next()) != firstAngle) { |
176 winding -= angle->segment()->spanSign(angle); | |
177 do { | |
178 SkASSERT(nextIndex != firstIndex); | |
179 if (nextIndex == angleCount) { | |
180 nextIndex = 0; | |
181 } | |
182 angle = sorted[nextIndex]; | |
183 segment = angle->segment(); | 170 segment = angle->segment(); |
184 int maxWinding = winding; | 171 int maxWinding = winding; |
185 winding -= segment->spanSign(angle); | 172 winding -= segment->spanSign(angle); |
186 #if DEBUG_SORT | 173 #if DEBUG_SORT |
187 SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__
, | 174 SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__
, |
188 segment->debugID(), maxWinding, winding, angle->sign()); | 175 segment->debugID(), maxWinding, winding, angle->sign()); |
189 #endif | 176 #endif |
190 tIndex = angle->start(); | 177 *tIndex = angle->start(); |
191 endIndex = angle->end(); | 178 *endIndex = angle->end(); |
192 int lesser = SkMin32(tIndex, endIndex); | 179 int lesser = SkMin32(*tIndex, *endIndex); |
193 const SkOpSpan& nextSpan = segment->span(lesser); | 180 const SkOpSpan& nextSpan = segment->span(lesser); |
194 if (!nextSpan.fDone) { | 181 if (!nextSpan.fDone) { |
195 // FIXME: this be wrong? assign startWinding if edge is in | 182 // FIXME: this be wrong? assign startWinding if edge is in |
196 // same direction. If the direction is opposite, winding to | 183 // same direction. If the direction is opposite, winding to |
197 // assign is flipped sign or +/- 1? | 184 // assign is flipped sign or +/- 1? |
198 if (SkOpSegment::UseInnerWinding(maxWinding, winding)) { | 185 if (SkOpSegment::UseInnerWinding(maxWinding, winding)) { |
199 maxWinding = winding; | 186 maxWinding = winding; |
200 } | 187 } |
201 segment->markAndChaseWinding(angle, maxWinding, 0); | 188 segment->markAndChaseWinding(angle, maxWinding, 0); |
202 break; | 189 break; |
203 } | 190 } |
204 } while (++nextIndex != lastIndex); | 191 } |
205 *chase.insert(0) = span; | 192 *chase->insert(0) = span; |
206 return segment; | 193 return segment; |
207 } | 194 } |
208 return NULL; | 195 return NULL; |
209 } | 196 } |
210 | 197 |
211 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY | 198 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY |
212 void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList) { | 199 void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList) { |
213 int index; | 200 int index; |
214 for (index = 0; index < contourList.count(); ++ index) { | 201 for (index = 0; index < contourList.count(); ++ index) { |
215 contourList[index]->debugShowActiveSpans(); | 202 contourList[index]->debugShowActiveSpans(); |
216 } | 203 } |
217 } | 204 } |
218 #endif | 205 #endif |
219 | 206 |
220 static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourL
ist, | 207 static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourL
ist, |
221 int* index, int* endIndex, SkPoint* topLeft,
bool* unsortable, | 208 int* index, int* endIndex, SkPoint* topLeft,
bool* unsortable, |
222 bool* done, bool onlySortable) { | 209 bool* done, bool onlySortable) { |
223 SkOpSegment* result; | 210 SkOpSegment* result; |
| 211 const SkOpSegment* lastTopStart = NULL; |
| 212 int lastIndex = -1, lastEndIndex = -1; |
224 do { | 213 do { |
225 SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax}; | 214 SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax}; |
226 int contourCount = contourList.count(); | 215 int contourCount = contourList.count(); |
227 SkOpSegment* topStart = NULL; | 216 SkOpSegment* topStart = NULL; |
228 *done = true; | 217 *done = true; |
229 for (int cIndex = 0; cIndex < contourCount; ++cIndex) { | 218 for (int cIndex = 0; cIndex < contourCount; ++cIndex) { |
230 SkOpContour* contour = contourList[cIndex]; | 219 SkOpContour* contour = contourList[cIndex]; |
231 if (contour->done()) { | 220 if (contour->done()) { |
232 continue; | 221 continue; |
233 } | 222 } |
234 const SkPathOpsBounds& bounds = contour->bounds(); | 223 const SkPathOpsBounds& bounds = contour->bounds(); |
235 if (bounds.fBottom < topLeft->fY) { | 224 if (bounds.fBottom < topLeft->fY) { |
236 *done = false; | 225 *done = false; |
237 continue; | 226 continue; |
238 } | 227 } |
239 if (bounds.fBottom == topLeft->fY && bounds.fRight < topLeft->fX) { | 228 if (bounds.fBottom == topLeft->fY && bounds.fRight < topLeft->fX) { |
240 *done = false; | 229 *done = false; |
241 continue; | 230 continue; |
242 } | 231 } |
243 contour->topSortableSegment(*topLeft, &bestXY, &topStart); | 232 contour->topSortableSegment(*topLeft, &bestXY, &topStart); |
244 if (!contour->done()) { | 233 if (!contour->done()) { |
245 *done = false; | 234 *done = false; |
246 } | 235 } |
247 } | 236 } |
248 if (!topStart) { | 237 if (!topStart) { |
249 return NULL; | 238 return NULL; |
250 } | 239 } |
251 *topLeft = bestXY; | 240 *topLeft = bestXY; |
252 result = topStart->findTop(index, endIndex, unsortable, onlySortable); | 241 result = topStart->findTop(index, endIndex, unsortable); |
| 242 if (!result) { |
| 243 if (lastTopStart == topStart && lastIndex == *index && lastEndIndex
== *endIndex) { |
| 244 *done = true; |
| 245 return NULL; |
| 246 } |
| 247 lastTopStart = topStart; |
| 248 lastIndex = *index; |
| 249 lastEndIndex = *endIndex; |
| 250 } |
253 } while (!result); | 251 } while (!result); |
254 if (result) { | 252 if (result) { |
255 *unsortable = false; | 253 *unsortable = false; |
256 } | 254 } |
257 return result; | 255 return result; |
258 } | 256 } |
259 | 257 |
260 static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList, | 258 static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList, |
261 SkOpSegment** current, int* index, int* endIndex, d
ouble* tHit, | 259 SkOpSegment** current, int* index, int* endIndex, d
ouble* tHit, |
262 SkScalar* hitDx, bool* tryAgain, bool opp) { | 260 SkScalar* hitDx, bool* tryAgain, bool opp) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexP
tr, | 294 SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexP
tr, |
297 int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done) { | 295 int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done) { |
298 SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, t
opLeft, unsortable, | 296 SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, t
opLeft, unsortable, |
299 done, true); | 297 done, true); |
300 if (!current) { | 298 if (!current) { |
301 return NULL; | 299 return NULL; |
302 } | 300 } |
303 const int index = *indexPtr; | 301 const int index = *indexPtr; |
304 const int endIndex = *endIndexPtr; | 302 const int endIndex = *endIndexPtr; |
305 if (*firstContour) { | 303 if (*firstContour) { |
306 current->initWinding(index, endIndex); | 304 current->initWinding(index, endIndex, angleIncludeType); |
307 *firstContour = false; | 305 *firstContour = false; |
308 return current; | 306 return current; |
309 } | 307 } |
310 int minIndex = SkMin32(index, endIndex); | 308 int minIndex = SkMin32(index, endIndex); |
311 int sumWinding = current->windSum(minIndex); | 309 int sumWinding = current->windSum(minIndex); |
312 if (sumWinding != SK_MinS32) { | 310 if (sumWinding != SK_MinS32) { |
313 return current; | 311 return current; |
314 } | 312 } |
315 SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32); | 313 SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32); |
316 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles; | 314 const SkOpSpan& span = current->span(endIndex); |
317 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; | 315 if ((index < endIndex ? span.fFromAngleIndex : span.fToAngleIndex) < 0) { |
318 sumWinding = current->computeSum(index, endIndex, angleIncludeType, &angles,
&sorted); | 316 current->addSimpleAngle(endIndex); |
| 317 } |
| 318 sumWinding = current->computeSum(index, endIndex, angleIncludeType); |
319 if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) { | 319 if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) { |
320 return current; | 320 return current; |
321 } | 321 } |
322 int contourWinding; | 322 int contourWinding; |
323 int oppContourWinding = 0; | 323 int oppContourWinding = 0; |
324 // the simple upward projection of the unresolved points hit unsortable angl
es | 324 // the simple upward projection of the unresolved points hit unsortable angl
es |
325 // shoot rays at right angles to the segment to find its winding, ignoring a
ngle cases | 325 // shoot rays at right angles to the segment to find its winding, ignoring a
ngle cases |
326 bool tryAgain; | 326 bool tryAgain; |
327 double tHit; | 327 double tHit; |
328 SkScalar hitDx = 0; | 328 SkScalar hitDx = 0; |
(...skipping 15 matching lines...) Expand all Loading... |
344 break; | 344 break; |
345 } | 345 } |
346 oppContourWinding = rightAngleWinding(contourList, ¤t, indexPtr, e
ndIndexPtr, &tHit, | 346 oppContourWinding = rightAngleWinding(contourList, ¤t, indexPtr, e
ndIndexPtr, &tHit, |
347 &hitOppDx, &tryAgain, true); | 347 &hitOppDx, &tryAgain, true); |
348 } while (tryAgain); | 348 } while (tryAgain); |
349 current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, o
ppContourWinding, | 349 current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, o
ppContourWinding, |
350 hitOppDx); | 350 hitOppDx); |
351 return current; | 351 return current; |
352 } | 352 } |
353 | 353 |
| 354 static bool calcAngles(SkTArray<SkOpContour*, true>* contourList) { |
| 355 int contourCount = (*contourList).count(); |
| 356 for (int cTest = 0; cTest < contourCount; ++cTest) { |
| 357 SkOpContour* contour = (*contourList)[cTest]; |
| 358 if (!contour->calcAngles()) { |
| 359 return false; |
| 360 } |
| 361 } |
| 362 return true; |
| 363 } |
| 364 |
| 365 static void checkDuplicates(SkTArray<SkOpContour*, true>* contourList) { |
| 366 int contourCount = (*contourList).count(); |
| 367 for (int cTest = 0; cTest < contourCount; ++cTest) { |
| 368 SkOpContour* contour = (*contourList)[cTest]; |
| 369 contour->checkDuplicates(); |
| 370 } |
| 371 } |
| 372 |
354 static void checkEnds(SkTArray<SkOpContour*, true>* contourList) { | 373 static void checkEnds(SkTArray<SkOpContour*, true>* contourList) { |
355 // it's hard to determine if the end of a cubic or conic nearly intersects a
nother curve. | 374 // it's hard to determine if the end of a cubic or conic nearly intersects a
nother curve. |
356 // instead, look to see if the connecting curve intersected at that same end
. | 375 // instead, look to see if the connecting curve intersected at that same end
. |
357 int contourCount = (*contourList).count(); | 376 int contourCount = (*contourList).count(); |
358 for (int cTest = 0; cTest < contourCount; ++cTest) { | 377 for (int cTest = 0; cTest < contourCount; ++cTest) { |
359 SkOpContour* contour = (*contourList)[cTest]; | 378 SkOpContour* contour = (*contourList)[cTest]; |
360 contour->checkEnds(); | 379 contour->checkEnds(); |
361 } | 380 } |
362 } | 381 } |
363 | 382 |
| 383 static void checkMultiples(SkTArray<SkOpContour*, true>* contourList) { |
| 384 // it's hard to determine if the end of a cubic or conic nearly intersects a
nother curve. |
| 385 // instead, look to see if the connecting curve intersected at that same end
. |
| 386 int contourCount = (*contourList).count(); |
| 387 for (int cTest = 0; cTest < contourCount; ++cTest) { |
| 388 SkOpContour* contour = (*contourList)[cTest]; |
| 389 contour->checkMultiples(); |
| 390 } |
| 391 } |
| 392 |
| 393 // A small interval of a pair of curves may collapse to lines for each, triggeri
ng coincidence |
| 394 static void checkSmall(SkTArray<SkOpContour*, true>* contourList) { |
| 395 int contourCount = (*contourList).count(); |
| 396 for (int cTest = 0; cTest < contourCount; ++cTest) { |
| 397 SkOpContour* contour = (*contourList)[cTest]; |
| 398 contour->checkSmall(); |
| 399 } |
| 400 } |
| 401 |
364 // A tiny interval may indicate an undiscovered coincidence. Find and fix. | 402 // A tiny interval may indicate an undiscovered coincidence. Find and fix. |
365 static void checkTiny(SkTArray<SkOpContour*, true>* contourList) { | 403 static void checkTiny(SkTArray<SkOpContour*, true>* contourList) { |
366 int contourCount = (*contourList).count(); | 404 int contourCount = (*contourList).count(); |
367 for (int cTest = 0; cTest < contourCount; ++cTest) { | 405 for (int cTest = 0; cTest < contourCount; ++cTest) { |
368 SkOpContour* contour = (*contourList)[cTest]; | 406 SkOpContour* contour = (*contourList)[cTest]; |
369 contour->checkTiny(); | 407 contour->checkTiny(); |
370 } | 408 } |
371 } | 409 } |
372 | 410 |
373 static void fixOtherTIndex(SkTArray<SkOpContour*, true>* contourList) { | 411 static void fixOtherTIndex(SkTArray<SkOpContour*, true>* contourList) { |
374 int contourCount = (*contourList).count(); | 412 int contourCount = (*contourList).count(); |
375 for (int cTest = 0; cTest < contourCount; ++cTest) { | 413 for (int cTest = 0; cTest < contourCount; ++cTest) { |
376 SkOpContour* contour = (*contourList)[cTest]; | 414 SkOpContour* contour = (*contourList)[cTest]; |
377 contour->fixOtherTIndex(); | 415 contour->fixOtherTIndex(); |
378 } | 416 } |
379 } | 417 } |
380 | 418 |
381 static void joinCoincidence(SkTArray<SkOpContour*, true>* contourList) { | 419 static void joinCoincidence(SkTArray<SkOpContour*, true>* contourList) { |
382 int contourCount = (*contourList).count(); | 420 int contourCount = (*contourList).count(); |
383 for (int cTest = 0; cTest < contourCount; ++cTest) { | 421 for (int cTest = 0; cTest < contourCount; ++cTest) { |
384 SkOpContour* contour = (*contourList)[cTest]; | 422 SkOpContour* contour = (*contourList)[cTest]; |
385 contour->joinCoincidence(); | 423 contour->joinCoincidence(); |
386 } | 424 } |
387 } | 425 } |
388 | 426 |
| 427 static void sortAngles(SkTArray<SkOpContour*, true>* contourList) { |
| 428 int contourCount = (*contourList).count(); |
| 429 for (int cTest = 0; cTest < contourCount; ++cTest) { |
| 430 SkOpContour* contour = (*contourList)[cTest]; |
| 431 contour->sortAngles(); |
| 432 } |
| 433 } |
| 434 |
389 static void sortSegments(SkTArray<SkOpContour*, true>* contourList) { | 435 static void sortSegments(SkTArray<SkOpContour*, true>* contourList) { |
390 int contourCount = (*contourList).count(); | 436 int contourCount = (*contourList).count(); |
391 for (int cTest = 0; cTest < contourCount; ++cTest) { | 437 for (int cTest = 0; cTest < contourCount; ++cTest) { |
392 SkOpContour* contour = (*contourList)[cTest]; | 438 SkOpContour* contour = (*contourList)[cTest]; |
393 contour->sortSegments(); | 439 contour->sortSegments(); |
394 } | 440 } |
395 } | 441 } |
396 | 442 |
397 void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, tru
e>& list, | 443 void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, tru
e>& list, |
398 bool evenOdd, bool oppEvenOdd) { | 444 bool evenOdd, bool oppEvenOdd) { |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 } | 652 } |
607 } while (rIndex < count); | 653 } while (rIndex < count); |
608 #if DEBUG_ASSEMBLE | 654 #if DEBUG_ASSEMBLE |
609 for (rIndex = 0; rIndex < count; ++rIndex) { | 655 for (rIndex = 0; rIndex < count; ++rIndex) { |
610 SkASSERT(sLink[rIndex] == SK_MaxS32); | 656 SkASSERT(sLink[rIndex] == SK_MaxS32); |
611 SkASSERT(eLink[rIndex] == SK_MaxS32); | 657 SkASSERT(eLink[rIndex] == SK_MaxS32); |
612 } | 658 } |
613 #endif | 659 #endif |
614 } | 660 } |
615 | 661 |
616 void HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) { | 662 bool HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) { |
617 #if DEBUG_SHOW_WINDING | 663 #if DEBUG_SHOW_WINDING |
618 SkOpContour::debugShowWindingValues(contourList); | 664 SkOpContour::debugShowWindingValues(contourList); |
619 #endif | 665 #endif |
620 CoincidenceCheck(contourList, total); | 666 CoincidenceCheck(contourList, total); |
621 #if DEBUG_SHOW_WINDING | 667 #if DEBUG_SHOW_WINDING |
622 SkOpContour::debugShowWindingValues(contourList); | 668 SkOpContour::debugShowWindingValues(contourList); |
623 #endif | 669 #endif |
624 fixOtherTIndex(contourList); | 670 fixOtherTIndex(contourList); |
625 checkEnds(contourList); | 671 checkEnds(contourList); |
| 672 checkMultiples(contourList); |
| 673 checkDuplicates(contourList); |
626 checkTiny(contourList); | 674 checkTiny(contourList); |
| 675 checkSmall(contourList); |
627 joinCoincidence(contourList); | 676 joinCoincidence(contourList); |
628 sortSegments(contourList); | 677 sortSegments(contourList); |
| 678 if (!calcAngles(contourList)) { |
| 679 return false; |
| 680 } |
| 681 sortAngles(contourList); |
629 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY | 682 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY |
630 DebugShowActiveSpans(*contourList); | 683 DebugShowActiveSpans(*contourList); |
631 #endif | 684 #endif |
| 685 return true; |
632 } | 686 } |
OLD | NEW |