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 "SkOpEdgeBuilder.h" | 7 #include "SkOpEdgeBuilder.h" |
8 #include "SkPathOpsCommon.h" | 8 #include "SkPathOpsCommon.h" |
9 #include "SkPathWriter.h" | 9 #include "SkPathWriter.h" |
10 #include "SkTSort.h" | 10 #include "SkTSort.h" |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 if (!contour->done()) { | 243 if (!contour->done()) { |
244 *done = false; | 244 *done = false; |
245 } | 245 } |
246 } | 246 } |
247 if (!topStart) { | 247 if (!topStart) { |
248 return NULL; | 248 return NULL; |
249 } | 249 } |
250 *topLeft = bestXY; | 250 *topLeft = bestXY; |
251 result = topStart->findTop(index, endIndex, unsortable, onlySortable); | 251 result = topStart->findTop(index, endIndex, unsortable, onlySortable); |
252 } while (!result); | 252 } while (!result); |
| 253 if (result) { |
| 254 *unsortable = false; |
| 255 } |
253 return result; | 256 return result; |
254 } | 257 } |
255 | 258 |
256 static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList, | 259 static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList, |
257 SkOpSegment** current, int* index, int* endIndex, d
ouble* tHit, | 260 SkOpSegment** current, int* index, int* endIndex, d
ouble* tHit, |
258 SkScalar* hitDx, bool* tryAgain, bool opp) { | 261 SkScalar* hitDx, bool* tryAgain, bool opp) { |
259 double test = 0.9; | 262 double test = 0.9; |
260 int contourWinding; | 263 int contourWinding; |
261 do { | 264 do { |
262 contourWinding = contourRangeCheckY(contourList, current, index, endInde
x, tHit, hitDx, | 265 contourWinding = contourRangeCheckY(contourList, current, index, endInde
x, tHit, hitDx, |
(...skipping 18 matching lines...) Expand all Loading... |
281 if (contour->done()) { | 284 if (contour->done()) { |
282 continue; | 285 continue; |
283 } | 286 } |
284 *current = contour->nonVerticalSegment(index, endIndex); | 287 *current = contour->nonVerticalSegment(index, endIndex); |
285 if (*current) { | 288 if (*current) { |
286 return; | 289 return; |
287 } | 290 } |
288 } | 291 } |
289 } | 292 } |
290 | 293 |
291 SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, bo
ol* firstContour, | 294 SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, |
292 int* indexPtr, int* endIndexPtr, SkPoint* topLeft,
bool* unsortable, | 295 SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexP
tr, |
293 bool* done, bool binary) { | 296 int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done) { |
294 SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, t
opLeft, unsortable, | 297 SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, t
opLeft, unsortable, |
295 done, true); | 298 done, true); |
296 if (!current) { | 299 if (!current) { |
297 return NULL; | 300 return NULL; |
298 } | 301 } |
299 const int index = *indexPtr; | 302 const int index = *indexPtr; |
300 const int endIndex = *endIndexPtr; | 303 const int endIndex = *endIndexPtr; |
301 if (*firstContour) { | 304 if (*firstContour) { |
302 current->initWinding(index, endIndex); | 305 current->initWinding(index, endIndex); |
303 *firstContour = false; | 306 *firstContour = false; |
304 return current; | 307 return current; |
305 } | 308 } |
306 int minIndex = SkMin32(index, endIndex); | 309 int minIndex = SkMin32(index, endIndex); |
307 int sumWinding = current->windSum(minIndex); | 310 int sumWinding = current->windSum(minIndex); |
308 if (sumWinding != SK_MinS32) { | 311 if (sumWinding != SK_MinS32) { |
309 return current; | 312 return current; |
310 } | 313 } |
311 sumWinding = current->computeSum(index, endIndex, binary); | 314 SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32); |
312 if (sumWinding != SK_MinS32) { | 315 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles; |
| 316 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; |
| 317 sumWinding = current->computeSum(index, endIndex, angleIncludeType, &angles,
&sorted); |
| 318 if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) { |
313 return current; | 319 return current; |
314 } | 320 } |
315 int contourWinding; | 321 int contourWinding; |
316 int oppContourWinding = 0; | 322 int oppContourWinding = 0; |
317 // the simple upward projection of the unresolved points hit unsortable angl
es | 323 // the simple upward projection of the unresolved points hit unsortable angl
es |
318 // shoot rays at right angles to the segment to find its winding, ignoring a
ngle cases | 324 // shoot rays at right angles to the segment to find its winding, ignoring a
ngle cases |
319 bool tryAgain; | 325 bool tryAgain; |
320 double tHit; | 326 double tHit; |
321 SkScalar hitDx = 0; | 327 SkScalar hitDx = 0; |
322 SkScalar hitOppDx = 0; | 328 SkScalar hitOppDx = 0; |
323 do { | 329 do { |
324 // if current is vertical, find another candidate which is not | 330 // if current is vertical, find another candidate which is not |
325 // if only remaining candidates are vertical, then they can be marked do
ne | 331 // if only remaining candidates are vertical, then they can be marked do
ne |
326 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >=
0); | 332 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >=
0); |
327 skipVertical(contourList, ¤t, indexPtr, endIndexPtr); | 333 skipVertical(contourList, ¤t, indexPtr, endIndexPtr); |
328 | 334 |
329 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >=
0); | 335 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >=
0); |
330 tryAgain = false; | 336 tryAgain = false; |
331 contourWinding = rightAngleWinding(contourList, ¤t, indexPtr, endI
ndexPtr, &tHit, | 337 contourWinding = rightAngleWinding(contourList, ¤t, indexPtr, endI
ndexPtr, &tHit, |
332 &hitDx, &tryAgain, false); | 338 &hitDx, &tryAgain, false); |
333 if (tryAgain) { | 339 if (tryAgain) { |
334 continue; | 340 continue; |
335 } | 341 } |
336 if (!binary) { | 342 if (angleIncludeType < SkOpAngle::kBinarySingle) { |
337 break; | 343 break; |
338 } | 344 } |
339 oppContourWinding = rightAngleWinding(contourList, ¤t, indexPtr, e
ndIndexPtr, &tHit, | 345 oppContourWinding = rightAngleWinding(contourList, ¤t, indexPtr, e
ndIndexPtr, &tHit, |
340 &hitOppDx, &tryAgain, true); | 346 &hitOppDx, &tryAgain, true); |
341 } while (tryAgain); | 347 } while (tryAgain); |
342 current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, o
ppContourWinding, | 348 current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, o
ppContourWinding, |
343 hitOppDx); | 349 hitOppDx); |
344 return current; | 350 return current; |
345 } | 351 } |
346 | 352 |
347 void CheckEnds(SkTArray<SkOpContour*, true>* contourList) { | 353 void CheckEnds(SkTArray<SkOpContour*, true>* contourList) { |
348 // it's hard to determine if the end of a cubic or conic nearly intersects a
nother curve. | 354 // it's hard to determine if the end of a cubic or conic nearly intersects a
nother curve. |
349 // instead, look to see if the connecting curve intersected at that same end
. | 355 // instead, look to see if the connecting curve intersected at that same end
. |
350 int contourCount = (*contourList).count(); | 356 int contourCount = (*contourList).count(); |
351 for (int cTest = 0; cTest < contourCount; ++cTest) { | 357 for (int cTest = 0; cTest < contourCount; ++cTest) { |
352 SkOpContour* contour = (*contourList)[cTest]; | 358 SkOpContour* contour = (*contourList)[cTest]; |
353 contour->checkEnds(); | 359 contour->checkEnds(); |
354 } | 360 } |
355 } | 361 } |
356 | 362 |
| 363 // A tiny interval may indicate an undiscovered coincidence. Find and fix. |
| 364 void CheckTiny(SkTArray<SkOpContour*, true>* contourList) { |
| 365 int contourCount = (*contourList).count(); |
| 366 for (int cTest = 0; cTest < contourCount; ++cTest) { |
| 367 SkOpContour* contour = (*contourList)[cTest]; |
| 368 contour->checkTiny(); |
| 369 } |
| 370 } |
| 371 |
357 void FixOtherTIndex(SkTArray<SkOpContour*, true>* contourList) { | 372 void FixOtherTIndex(SkTArray<SkOpContour*, true>* contourList) { |
358 int contourCount = (*contourList).count(); | 373 int contourCount = (*contourList).count(); |
359 for (int cTest = 0; cTest < contourCount; ++cTest) { | 374 for (int cTest = 0; cTest < contourCount; ++cTest) { |
360 SkOpContour* contour = (*contourList)[cTest]; | 375 SkOpContour* contour = (*contourList)[cTest]; |
361 contour->fixOtherTIndex(); | 376 contour->fixOtherTIndex(); |
362 } | 377 } |
363 } | 378 } |
364 | 379 |
365 void SortSegments(SkTArray<SkOpContour*, true>* contourList) { | 380 void SortSegments(SkTArray<SkOpContour*, true>* contourList) { |
366 int contourCount = (*contourList).count(); | 381 int contourCount = (*contourList).count(); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 } | 600 } |
586 } | 601 } |
587 } while (rIndex < count); | 602 } while (rIndex < count); |
588 #if DEBUG_ASSEMBLE | 603 #if DEBUG_ASSEMBLE |
589 for (rIndex = 0; rIndex < count; ++rIndex) { | 604 for (rIndex = 0; rIndex < count; ++rIndex) { |
590 SkASSERT(sLink[rIndex] == SK_MaxS32); | 605 SkASSERT(sLink[rIndex] == SK_MaxS32); |
591 SkASSERT(eLink[rIndex] == SK_MaxS32); | 606 SkASSERT(eLink[rIndex] == SK_MaxS32); |
592 } | 607 } |
593 #endif | 608 #endif |
594 } | 609 } |
OLD | NEW |