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 "SkIntersections.h" | 7 #include "SkIntersections.h" |
| 8 #include "SkOpContour.h" |
8 #include "SkOpSegment.h" | 9 #include "SkOpSegment.h" |
9 #include "SkPathWriter.h" | 10 #include "SkPathWriter.h" |
10 #include "SkTSort.h" | 11 #include "SkTSort.h" |
11 | 12 |
12 #define F (false) // discard the edge | 13 #define F (false) // discard the edge |
13 #define T (true) // keep the edge | 14 #define T (true) // keep the edge |
14 | 15 |
15 static const bool gUnaryActiveEdge[2][2] = { | 16 static const bool gUnaryActiveEdge[2][2] = { |
16 // from=0 from=1 | 17 // from=0 from=1 |
17 // to=0,1 to=0,1 | 18 // to=0,1 to=0,1 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 suFrom = (maxWinding & xorSuMask) != 0; | 181 suFrom = (maxWinding & xorSuMask) != 0; |
181 suTo = (sumWinding & xorSuMask) != 0; | 182 suTo = (sumWinding & xorSuMask) != 0; |
182 } else { | 183 } else { |
183 miFrom = (maxWinding & xorMiMask) != 0; | 184 miFrom = (maxWinding & xorMiMask) != 0; |
184 miTo = (sumWinding & xorMiMask) != 0; | 185 miTo = (sumWinding & xorMiMask) != 0; |
185 suFrom = (oppMaxWinding & xorSuMask) != 0; | 186 suFrom = (oppMaxWinding & xorSuMask) != 0; |
186 suTo = (oppSumWinding & xorSuMask) != 0; | 187 suTo = (oppSumWinding & xorSuMask) != 0; |
187 } | 188 } |
188 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; | 189 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; |
189 #if DEBUG_ACTIVE_OP | 190 #if DEBUG_ACTIVE_OP |
190 SkDebugf("%s op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", __FUNCT
ION__, | 191 SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo
=%d result=%d\n", |
| 192 __FUNCTION__, debugID(), span(index).fT, span(endIndex).fT, |
191 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); | 193 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); |
192 #endif | 194 #endif |
193 return result; | 195 return result; |
194 } | 196 } |
195 | 197 |
196 bool SkOpSegment::activeWinding(int index, int endIndex) { | 198 bool SkOpSegment::activeWinding(int index, int endIndex) { |
197 int sumWinding = updateWinding(endIndex, index); | 199 int sumWinding = updateWinding(endIndex, index); |
198 return activeWinding(index, endIndex, &sumWinding); | 200 return activeWinding(index, endIndex, &sumWinding); |
199 } | 201 } |
200 | 202 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 default: | 399 default: |
398 SkASSERT(0); | 400 SkASSERT(0); |
399 } | 401 } |
400 } | 402 } |
401 } | 403 } |
402 // return ePtr[SkPathOpsVerbToPoints(fVerb)]; | 404 // return ePtr[SkPathOpsVerbToPoints(fVerb)]; |
403 } | 405 } |
404 | 406 |
405 void SkOpSegment::addEndSpan(int endIndex) { | 407 void SkOpSegment::addEndSpan(int endIndex) { |
406 int spanCount = fTs.count(); | 408 int spanCount = fTs.count(); |
407 int angleIndex = fAngles.count(); | |
408 int startIndex = endIndex - 1; | 409 int startIndex = endIndex - 1; |
409 while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) { | 410 while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) { |
410 ++startIndex; | 411 ++startIndex; |
411 SkASSERT(startIndex < spanCount - 1); | 412 SkASSERT(startIndex < spanCount - 1); |
412 ++endIndex; | 413 ++endIndex; |
413 } | 414 } |
414 fAngles.push_back().set(this, spanCount - 1, startIndex); | 415 SkOpAngle& angle = fAngles.push_back(); |
| 416 angle.set(this, spanCount - 1, startIndex); |
415 #if DEBUG_ANGLE | 417 #if DEBUG_ANGLE |
416 fAngles.back().setID(angleIndex); | |
417 debugCheckPointsEqualish(endIndex, spanCount); | 418 debugCheckPointsEqualish(endIndex, spanCount); |
418 #endif | 419 #endif |
419 setFromAngleIndex(endIndex, angleIndex); | 420 setFromAngle(endIndex, &angle); |
420 } | 421 } |
421 | 422 |
422 void SkOpSegment::setFromAngleIndex(int endIndex, int angleIndex) { | 423 void SkOpSegment::setFromAngle(int endIndex, SkOpAngle* angle) { |
423 int spanCount = fTs.count(); | 424 int spanCount = fTs.count(); |
424 do { | 425 do { |
425 fTs[endIndex].fFromAngleIndex = angleIndex; | 426 fTs[endIndex].fFromAngle = angle; |
426 } while (++endIndex < spanCount); | 427 } while (++endIndex < spanCount); |
427 } | 428 } |
428 | 429 |
429 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) { | 430 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) { |
430 init(pts, SkPath::kLine_Verb, operand, evenOdd); | 431 init(pts, SkPath::kLine_Verb, operand, evenOdd); |
431 fBounds.set(pts, 2); | 432 fBounds.set(pts, 2); |
432 } | 433 } |
433 | 434 |
434 // add 2 to edge or out of range values to get T extremes | 435 // add 2 to edge or out of range values to get T extremes |
435 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) { | 436 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) { |
436 SkOpSpan& span = fTs[index]; | 437 SkOpSpan& span = fTs[index]; |
437 if (precisely_zero(otherT)) { | 438 if (precisely_zero(otherT)) { |
438 otherT = 0; | 439 otherT = 0; |
439 } else if (precisely_equal(otherT, 1)) { | 440 } else if (precisely_equal(otherT, 1)) { |
440 otherT = 1; | 441 otherT = 1; |
441 } | 442 } |
442 span.fOtherT = otherT; | 443 span.fOtherT = otherT; |
443 span.fOtherIndex = otherIndex; | 444 span.fOtherIndex = otherIndex; |
444 } | 445 } |
445 | 446 |
446 void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) { | 447 void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) { |
447 init(pts, SkPath::kQuad_Verb, operand, evenOdd); | 448 init(pts, SkPath::kQuad_Verb, operand, evenOdd); |
448 fBounds.setQuadBounds(pts); | 449 fBounds.setQuadBounds(pts); |
449 } | 450 } |
450 | 451 |
451 int SkOpSegment::addSingletonAngleDown(int endIndex, SkOpSegment** otherPtr) { | 452 SkOpAngle* SkOpSegment::addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle*
* anglePtr) { |
452 int startIndex = findEndSpan(endIndex); | 453 int spanIndex = count() - 1; |
453 SkASSERT(startIndex > 0); | 454 int startIndex = nextExactSpan(spanIndex, -1); |
454 int spanIndex = endIndex - 1; | 455 SkASSERT(startIndex >= 0); |
455 fSingletonAngles.push_back().set(this, spanIndex, startIndex - 1); | 456 SkOpAngle& angle = fAngles.push_back(); |
456 setFromAngleIndex(startIndex, fAngles.count() + fSingletonAngles.count() - 1
); | 457 *anglePtr = ∠ |
| 458 angle.set(this, spanIndex, startIndex); |
| 459 setFromAngle(spanIndex, &angle); |
457 SkOpSegment* other; | 460 SkOpSegment* other; |
| 461 int oStartIndex, oEndIndex; |
458 do { | 462 do { |
459 other = fTs[spanIndex].fOther; | 463 const SkOpSpan& span = fTs[spanIndex]; |
460 if (other->fTs[0].fWindValue) { | 464 SkASSERT(span.fT > 0); |
| 465 other = span.fOther; |
| 466 oStartIndex = span.fOtherIndex; |
| 467 oEndIndex = other->nextExactSpan(oStartIndex, 1); |
| 468 if (oEndIndex > 0 && other->span(oStartIndex).fWindValue) { |
461 break; | 469 break; |
462 } | 470 } |
| 471 oEndIndex = oStartIndex; |
| 472 oStartIndex = other->nextExactSpan(oEndIndex, -1); |
463 --spanIndex; | 473 --spanIndex; |
464 SkASSERT(fTs[spanIndex].fT == 1); | 474 } while (oStartIndex < 0 || !other->span(oStartIndex).fWindSum); |
465 } while (true); | 475 SkOpAngle& oAngle = other->fAngles.push_back(); |
466 int oEndIndex = other->findStartSpan(0); | 476 oAngle.set(other, oStartIndex, oEndIndex); |
467 SkASSERT(oEndIndex > 0); | 477 other->setToAngle(oEndIndex, &oAngle); |
468 int otherIndex = other->fSingletonAngles.count(); | |
469 other->fSingletonAngles.push_back().set(other, 0, oEndIndex); | |
470 other->setToAngleIndex(oEndIndex, other->fAngles.count() + otherIndex); | |
471 *otherPtr = other; | 478 *otherPtr = other; |
472 return otherIndex; | 479 return &oAngle; |
473 } | 480 } |
474 | 481 |
475 int SkOpSegment::addSingletonAngleUp(int start, SkOpSegment** otherPtr) { | 482 SkOpAngle* SkOpSegment::addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle**
anglePtr) { |
476 int endIndex = findStartSpan(start); | 483 int endIndex = nextExactSpan(0, 1); |
477 SkASSERT(endIndex > 0); | 484 SkASSERT(endIndex > 0); |
478 int thisIndex = fSingletonAngles.count(); | 485 SkOpAngle& angle = fAngles.push_back(); |
479 fSingletonAngles.push_back().set(this, start, endIndex); | 486 *anglePtr = ∠ |
480 setToAngleIndex(endIndex, fAngles.count() + thisIndex); | 487 angle.set(this, 0, endIndex); |
481 int spanIndex = start; | 488 setToAngle(endIndex, &angle); |
| 489 int spanIndex = 0; |
482 SkOpSegment* other; | 490 SkOpSegment* other; |
483 int oCount, oStartIndex; | 491 int oStartIndex, oEndIndex; |
484 do { | 492 do { |
485 other = fTs[spanIndex].fOther; | 493 const SkOpSpan& span = fTs[spanIndex]; |
486 oCount = other->count(); | 494 SkASSERT(span.fT < 1); |
487 oStartIndex = other->findEndSpan(oCount); | 495 other = span.fOther; |
488 SkASSERT(oStartIndex > 0); | 496 oEndIndex = span.fOtherIndex; |
489 if (other->fTs[oStartIndex - 1].fWindValue) { | 497 oStartIndex = other->nextExactSpan(oEndIndex, -1); |
| 498 if (oStartIndex >= 0 && other->span(oStartIndex).fWindValue) { |
490 break; | 499 break; |
491 } | 500 } |
| 501 oStartIndex = oEndIndex; |
| 502 oEndIndex = other->nextExactSpan(oStartIndex, 1); |
492 ++spanIndex; | 503 ++spanIndex; |
493 SkASSERT(fTs[spanIndex].fT == 0); | 504 } while (oEndIndex < 0 || !other->span(oStartIndex).fWindValue); |
494 } while (true); | 505 SkOpAngle& oAngle = other->fAngles.push_back(); |
495 int otherIndex = other->fSingletonAngles.count(); | 506 oAngle.set(other, oEndIndex, oStartIndex); |
496 other->fSingletonAngles.push_back().set(other, oCount - 1, oStartIndex - 1); | 507 other->setFromAngle(oEndIndex, &oAngle); |
497 other->setFromAngleIndex(oStartIndex, other->fAngles.count() + otherIndex); | |
498 *otherPtr = other; | 508 *otherPtr = other; |
499 return otherIndex; | 509 return &oAngle; |
500 } | 510 } |
501 | 511 |
502 SkOpAngle* SkOpSegment::addSingletonAngles(int start, int step) { | 512 SkOpAngle* SkOpSegment::addSingletonAngles(int step) { |
503 int thisIndex = fSingletonAngles.count(); | |
504 SkOpSegment* other; | 513 SkOpSegment* other; |
505 int otherIndex; | 514 SkOpAngle* angle, * otherAngle; |
506 if (step > 0) { | 515 if (step > 0) { |
507 otherIndex = addSingletonAngleUp(start, &other); | 516 otherAngle = addSingletonAngleUp(&other, &angle); |
508 } else { | 517 } else { |
509 otherIndex = addSingletonAngleDown(start + 1, &other); | 518 otherAngle = addSingletonAngleDown(&other, &angle); |
510 } | 519 } |
511 fSingletonAngles[thisIndex].insert(&other->fSingletonAngles[otherIndex]); | 520 angle->insert(otherAngle); |
512 #if DEBUG_ANGLE | 521 return angle; |
513 fSingletonAngles[thisIndex].setID(fAngles.count() + thisIndex); | |
514 other->fSingletonAngles[otherIndex].setID(other->fAngles.count() + otherInde
x); | |
515 #endif | |
516 return &fSingletonAngles[thisIndex]; | |
517 } | 522 } |
518 | 523 |
519 void SkOpSegment::addStartSpan(int endIndex) { | 524 void SkOpSegment::addStartSpan(int endIndex) { |
520 int angleIndex = fAngles.count(); | |
521 int index = 0; | 525 int index = 0; |
522 fAngles.push_back().set(this, index, endIndex); | 526 SkOpAngle& angle = fAngles.push_back(); |
| 527 angle.set(this, index, endIndex); |
523 #if DEBUG_ANGLE | 528 #if DEBUG_ANGLE |
524 fAngles.back().setID(angleIndex); | |
525 debugCheckPointsEqualish(index, endIndex); | 529 debugCheckPointsEqualish(index, endIndex); |
526 #endif | 530 #endif |
527 setToAngleIndex(endIndex, angleIndex); | 531 setToAngle(endIndex, &angle); |
528 } | 532 } |
529 | 533 |
530 void SkOpSegment::setToAngleIndex(int endIndex, int angleIndex) { | 534 void SkOpSegment::setToAngle(int endIndex, SkOpAngle* angle) { |
531 int index = 0; | 535 int index = 0; |
532 do { | 536 do { |
533 fTs[index].fToAngleIndex = angleIndex; | 537 fTs[index].fToAngle = angle; |
534 } while (++index < endIndex); | 538 } while (++index < endIndex); |
535 } | 539 } |
536 | 540 |
537 // Defer all coincident edge processing until | 541 // Defer all coincident edge processing until |
538 // after normal intersections have been computed | 542 // after normal intersections have been computed |
539 | 543 |
540 // no need to be tricky; insert in normal T order | 544 // no need to be tricky; insert in normal T order |
541 // resolve overlapping ts when considering coincidence later | 545 // resolve overlapping ts when considering coincidence later |
542 | 546 |
543 // add non-coincident intersection. Resulting edges are sorted in T. | 547 // add non-coincident intersection. Resulting edges are sorted in T. |
544 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { | 548 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { |
545 SkASSERT(this != other || fVerb == SkPath::kCubic_Verb); | 549 SkASSERT(this != other || fVerb == SkPath::kCubic_Verb); |
546 #if 0 // this needs an even rougher association to be useful | 550 #if 0 // this needs an even rougher association to be useful |
547 SkASSERT(SkDPoint::RoughlyEqual(ptAtT(newT), pt)); | 551 SkASSERT(SkDPoint::RoughlyEqual(ptAtT(newT), pt)); |
548 #endif | 552 #endif |
549 if (precisely_zero(newT)) { | 553 const SkPoint& firstPt = fPts[0]; |
550 newT = 0; | 554 const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)]; |
551 } else if (precisely_equal(newT, 1)) { | 555 SkASSERT(newT == 0 || !precisely_zero(newT)); |
552 newT = 1; | 556 SkASSERT(newT == 1 || !precisely_equal(newT, 1)); |
553 } | |
554 // FIXME: in the pathological case where there is a ton of intercepts, | 557 // FIXME: in the pathological case where there is a ton of intercepts, |
555 // binary search? | 558 // binary search? |
556 int insertedAt = -1; | 559 int insertedAt = -1; |
557 int tCount = fTs.count(); | 560 int tCount = fTs.count(); |
558 const SkPoint& firstPt = fPts[0]; | |
559 const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)]; | |
560 for (int index = 0; index < tCount; ++index) { | 561 for (int index = 0; index < tCount; ++index) { |
561 // OPTIMIZATION: if there are three or more identical Ts, then | 562 // OPTIMIZATION: if there are three or more identical Ts, then |
562 // the fourth and following could be further insertion-sorted so | 563 // the fourth and following could be further insertion-sorted so |
563 // that all the edges are clockwise or counterclockwise. | 564 // that all the edges are clockwise or counterclockwise. |
564 // This could later limit segment tests to the two adjacent | 565 // This could later limit segment tests to the two adjacent |
565 // neighbors, although it doesn't help with determining which | 566 // neighbors, although it doesn't help with determining which |
566 // circular direction to go in. | 567 // circular direction to go in. |
567 const SkOpSpan& span = fTs[index]; | 568 const SkOpSpan& span = fTs[index]; |
568 if (newT < span.fT) { | 569 if (newT < span.fT) { |
569 insertedAt = index; | 570 insertedAt = index; |
(...skipping 11 matching lines...) Expand all Loading... |
581 } | 582 } |
582 } | 583 } |
583 SkOpSpan* span; | 584 SkOpSpan* span; |
584 if (insertedAt >= 0) { | 585 if (insertedAt >= 0) { |
585 span = fTs.insert(insertedAt); | 586 span = fTs.insert(insertedAt); |
586 } else { | 587 } else { |
587 insertedAt = tCount; | 588 insertedAt = tCount; |
588 span = fTs.append(); | 589 span = fTs.append(); |
589 } | 590 } |
590 span->fT = newT; | 591 span->fT = newT; |
| 592 #if SK_DEBUG |
| 593 span->fOtherT = -1; |
| 594 #endif |
591 span->fOther = other; | 595 span->fOther = other; |
592 span->fPt = pt; | 596 span->fPt = pt; |
593 #if 0 | 597 #if 0 |
594 // cubics, for instance, may not be exact enough to satisfy this check (e.g.
, cubicOp69d) | 598 // cubics, for instance, may not be exact enough to satisfy this check (e.g.
, cubicOp69d) |
595 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) | 599 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) |
596 && approximately_equal(xyAtT(newT).fY, pt.fY)); | 600 && approximately_equal(xyAtT(newT).fY, pt.fY)); |
597 #endif | 601 #endif |
598 span->fFromAngleIndex = -1; | 602 span->fFromAngle = NULL; |
599 span->fToAngleIndex = -1; | 603 span->fToAngle = NULL; |
600 span->fWindSum = SK_MinS32; | 604 span->fWindSum = SK_MinS32; |
601 span->fOppSum = SK_MinS32; | 605 span->fOppSum = SK_MinS32; |
602 span->fWindValue = 1; | 606 span->fWindValue = 1; |
603 span->fOppValue = 0; | 607 span->fOppValue = 0; |
604 span->fChased = false; | 608 span->fChased = false; |
| 609 span->fCoincident = false; |
| 610 span->fLoop = false; |
| 611 span->fNear = false; |
| 612 span->fMultiple = false; |
| 613 span->fSmall = false; |
| 614 span->fTiny = false; |
605 if ((span->fDone = newT == 1)) { | 615 if ((span->fDone = newT == 1)) { |
606 ++fDoneSpans; | 616 ++fDoneSpans; |
607 } | 617 } |
608 span->fLoop = false; | |
609 span->fSmall = false; | |
610 span->fTiny = false; | |
611 int less = -1; | 618 int less = -1; |
| 619 // FIXME: note that this relies on spans being a continguous array |
612 // find range of spans with nearly the same point as this one | 620 // find range of spans with nearly the same point as this one |
613 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt,
pt)) { | 621 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt,
pt)) { |
614 if (fVerb == SkPath::kCubic_Verb) { | 622 if (fVerb == SkPath::kCubic_Verb) { |
615 double tInterval = newT - span[less].fT; | 623 double tInterval = newT - span[less].fT; |
616 double tMid = newT - tInterval / 2; | 624 double tMid = newT - tInterval / 2; |
617 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); | 625 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); |
618 if (!midPt.approximatelyEqual(xyAtT(span))) { | 626 if (!midPt.approximatelyEqual(xyAtT(span))) { |
619 break; | 627 break; |
620 } | 628 } |
621 } | 629 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS
egment* other) { | 688 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS
egment* other) { |
681 bool binary = fOperand != other->fOperand; | 689 bool binary = fOperand != other->fOperand; |
682 int index = 0; | 690 int index = 0; |
683 while (startPt != fTs[index].fPt) { | 691 while (startPt != fTs[index].fPt) { |
684 SkASSERT(index < fTs.count()); | 692 SkASSERT(index < fTs.count()); |
685 ++index; | 693 ++index; |
686 } | 694 } |
687 while (index > 0 && precisely_equal(fTs[index].fT, fTs[index - 1].fT)) { | 695 while (index > 0 && precisely_equal(fTs[index].fT, fTs[index - 1].fT)) { |
688 --index; | 696 --index; |
689 } | 697 } |
| 698 bool oFoundEnd = false; |
690 int oIndex = other->fTs.count(); | 699 int oIndex = other->fTs.count(); |
691 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match | 700 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match |
692 SkASSERT(oIndex > 0); | 701 SkASSERT(oIndex > 0); |
693 } | 702 } |
694 double oStartT = other->fTs[oIndex].fT; | 703 double oStartT = other->fTs[oIndex].fT; |
695 // look for first point beyond match | 704 // look for first point beyond match |
696 while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other
->fTs[oIndex].fT)) { | 705 while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other
->fTs[oIndex].fT)) { |
697 SkASSERT(oIndex > 0); | 706 SkASSERT(oIndex > 0); |
698 } | 707 } |
699 SkOpSpan* test = &fTs[index]; | 708 SkOpSpan* test = &fTs[index]; |
700 SkOpSpan* oTest = &other->fTs[oIndex]; | 709 SkOpSpan* oTest = &other->fTs[oIndex]; |
701 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; | 710 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; |
702 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; | 711 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; |
| 712 bool decrement, track, bigger; |
| 713 int originalWindValue; |
| 714 const SkPoint* testPt; |
| 715 const SkPoint* oTestPt; |
703 do { | 716 do { |
704 SkASSERT(test->fT < 1); | 717 SkASSERT(test->fT < 1); |
705 SkASSERT(oTest->fT < 1); | 718 SkASSERT(oTest->fT < 1); |
706 bool decrement = test->fWindValue && oTest->fWindValue; | 719 decrement = test->fWindValue && oTest->fWindValue; |
707 bool track = test->fWindValue || oTest->fWindValue; | 720 track = test->fWindValue || oTest->fWindValue; |
708 bool bigger = test->fWindValue >= oTest->fWindValue; | 721 bigger = test->fWindValue >= oTest->fWindValue; |
709 const SkPoint& testPt = test->fPt; | 722 testPt = &test->fPt; |
710 double testT = test->fT; | 723 double testT = test->fT; |
711 const SkPoint& oTestPt = oTest->fPt; | 724 oTestPt = &oTest->fPt; |
712 double oTestT = oTest->fT; | 725 double oTestT = oTest->fT; |
713 do { | 726 do { |
714 if (decrement) { | 727 if (decrement) { |
715 if (binary && bigger) { | 728 if (binary && bigger) { |
716 test->fOppValue--; | 729 test->fOppValue--; |
717 } else { | 730 } else { |
718 decrementSpan(test); | 731 decrementSpan(test); |
719 } | 732 } |
720 } else if (track) { | 733 } else if (track) { |
721 TrackOutsidePair(&outsidePts, testPt, oTestPt); | 734 TrackOutsidePair(&outsidePts, *testPt, *oTestPt); |
722 } | 735 } |
723 SkASSERT(index < fTs.count() - 1); | 736 SkASSERT(index < fTs.count() - 1); |
724 test = &fTs[++index]; | 737 test = &fTs[++index]; |
725 } while (testPt == test->fPt || precisely_equal(testT, test->fT)); | 738 } while (*testPt == test->fPt || precisely_equal(testT, test->fT)); |
726 SkDEBUGCODE(int originalWindValue = oTest->fWindValue); | 739 originalWindValue = oTest->fWindValue; |
727 do { | 740 do { |
728 SkASSERT(oTest->fT < 1); | 741 SkASSERT(oTest->fT < 1); |
729 SkASSERT(originalWindValue == oTest->fWindValue); | 742 SkASSERT(originalWindValue == oTest->fWindValue); |
730 if (decrement) { | 743 if (decrement) { |
731 if (binary && !bigger) { | 744 if (binary && !bigger) { |
732 oTest->fOppValue--; | 745 oTest->fOppValue--; |
733 } else { | 746 } else { |
734 other->decrementSpan(oTest); | 747 other->decrementSpan(oTest); |
735 } | 748 } |
736 } else if (track) { | 749 } else if (track) { |
737 TrackOutsidePair(&oOutsidePts, oTestPt, testPt); | 750 TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt); |
| 751 } |
| 752 if (!oIndex) { |
| 753 break; |
| 754 } |
| 755 oFoundEnd |= endPt == oTest->fPt; |
| 756 oTest = &other->fTs[--oIndex]; |
| 757 } while (*oTestPt == oTest->fPt || precisely_equal(oTestT, oTest->fT)); |
| 758 } while (endPt != test->fPt && test->fT < 1); |
| 759 // FIXME: determine if canceled edges need outside ts added |
| 760 if (!oFoundEnd) { |
| 761 for (int oIdx2 = oIndex; oIdx2 >= 0; --oIdx2) { |
| 762 SkOpSpan* oTst2 = &other->fTs[oIdx2]; |
| 763 if (originalWindValue != oTst2->fWindValue) { |
| 764 goto skipAdvanceOtherCancel; |
| 765 } |
| 766 if (!oTst2->fWindValue) { |
| 767 goto skipAdvanceOtherCancel; |
| 768 } |
| 769 if (endPt == other->fTs[oIdx2].fPt) { |
| 770 break; |
| 771 } |
| 772 } |
| 773 do { |
| 774 SkASSERT(originalWindValue == oTest->fWindValue); |
| 775 if (decrement) { |
| 776 if (binary && !bigger) { |
| 777 oTest->fOppValue--; |
| 778 } else { |
| 779 other->decrementSpan(oTest); |
| 780 } |
| 781 } else if (track) { |
| 782 TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt); |
738 } | 783 } |
739 if (!oIndex) { | 784 if (!oIndex) { |
740 break; | 785 break; |
741 } | 786 } |
742 oTest = &other->fTs[--oIndex]; | 787 oTest = &other->fTs[--oIndex]; |
743 } while (oTestPt == oTest->fPt || precisely_equal(oTestT, oTest->fT)); | 788 oFoundEnd |= endPt == oTest->fPt; |
744 } while (endPt != test->fPt && test->fT < 1); | 789 } while (!oFoundEnd || endPt == oTest->fPt); |
745 // FIXME: determine if canceled edges need outside ts added | 790 } |
| 791 skipAdvanceOtherCancel: |
746 int outCount = outsidePts.count(); | 792 int outCount = outsidePts.count(); |
747 if (!done() && outCount) { | 793 if (!done() && outCount) { |
748 addCancelOutsides(outsidePts[0], outsidePts[1], other); | 794 addCancelOutsides(outsidePts[0], outsidePts[1], other); |
749 if (outCount > 2) { | 795 if (outCount > 2) { |
750 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1]
, other); | 796 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1]
, other); |
751 } | 797 } |
752 } | 798 } |
753 if (!other->done() && oOutsidePts.count()) { | 799 if (!other->done() && oOutsidePts.count()) { |
754 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this); | 800 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this); |
755 } | 801 } |
| 802 setCoincidentRange(startPt, endPt, other); |
| 803 other->setCoincidentRange(startPt, endPt, this); |
756 } | 804 } |
757 | 805 |
758 int SkOpSegment::addSelfT(const SkPoint& pt, double newT) { | 806 int SkOpSegment::addSelfT(const SkPoint& pt, double newT) { |
759 // if the tail nearly intersects itself but not quite, the caller records th
is separately | 807 // if the tail nearly intersects itself but not quite, the caller records th
is separately |
760 int result = addT(this, pt, newT); | 808 int result = addT(this, pt, newT); |
761 SkOpSpan* span = &fTs[result]; | 809 SkOpSpan* span = &fTs[result]; |
762 fLoop = span->fLoop = true; | 810 fLoop = span->fLoop = true; |
763 return result; | 811 return result; |
764 } | 812 } |
765 | 813 |
| 814 // find the starting or ending span with an existing loop of angles |
| 815 // FIXME? replicate for all identical starting/ending spans? |
| 816 // OPTIMIZE? remove the spans pointing to windValue==0 here or earlier? |
| 817 // FIXME? assert that only one other span has a valid windValue or oppValue |
766 void SkOpSegment::addSimpleAngle(int index) { | 818 void SkOpSegment::addSimpleAngle(int index) { |
| 819 SkOpSpan* span = &fTs[index]; |
767 if (index == 0) { | 820 if (index == 0) { |
768 SkASSERT(!fTs[index].fTiny && fTs[index + 1].fT > 0); | 821 do { |
| 822 if (span->fToAngle) { |
| 823 SkASSERT(span->fToAngle->loopCount() == 2); |
| 824 SkASSERT(!span->fFromAngle); |
| 825 span->fFromAngle = span->fToAngle->next(); |
| 826 return; |
| 827 } |
| 828 span = &fTs[++index]; |
| 829 } while (span->fT == 0); |
| 830 SkASSERT(index == 1); |
| 831 index = 0; |
| 832 SkASSERT(!fTs[0].fTiny && fTs[1].fT > 0); |
769 addStartSpan(1); | 833 addStartSpan(1); |
770 } else { | 834 } else { |
| 835 do { |
| 836 if (span->fFromAngle) { |
| 837 SkASSERT(span->fFromAngle->loopCount() == 2); |
| 838 SkASSERT(!span->fToAngle); |
| 839 span->fToAngle = span->fFromAngle->next(); |
| 840 return; |
| 841 } |
| 842 span = &fTs[--index]; |
| 843 } while (span->fT == 1); |
| 844 SkASSERT(index == count() - 2); |
| 845 index = count() - 1; |
771 SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1); | 846 SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1); |
772 addEndSpan(index); | 847 addEndSpan(index); |
773 } | 848 } |
774 SkOpSpan& span = fTs[index]; | 849 span = &fTs[index]; |
775 SkOpSegment* other = span.fOther; | 850 SkOpSegment* other = span->fOther; |
776 SkOpSpan& oSpan = other->fTs[span.fOtherIndex]; | 851 SkOpSpan& oSpan = other->fTs[span->fOtherIndex]; |
777 SkOpAngle* angle, * oAngle; | 852 SkOpAngle* angle, * oAngle; |
778 if (index == 0) { | 853 if (index == 0) { |
779 SkASSERT(span.fOtherIndex - 1 >= 0); | 854 SkASSERT(span->fOtherIndex - 1 >= 0); |
780 SkASSERT(span.fOtherT == 1); | 855 SkASSERT(span->fOtherT == 1); |
781 SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span.fOtherIndex - 1]); | 856 SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span->fOtherIndex - 1]); |
782 SkASSERT(!oPrior.fTiny && oPrior.fT < 1); | 857 SkASSERT(!oPrior.fTiny && oPrior.fT < 1); |
783 other->addEndSpan(span.fOtherIndex); | 858 other->addEndSpan(span->fOtherIndex); |
784 angle = &this->angle(span.fToAngleIndex); | 859 angle = span->fToAngle; |
785 oAngle = &other->angle(oSpan.fFromAngleIndex); | 860 oAngle = oSpan.fFromAngle; |
786 } else { | 861 } else { |
787 SkASSERT(span.fOtherIndex + 1 < other->count()); | 862 SkASSERT(span->fOtherIndex + 1 < other->count()); |
788 SkASSERT(span.fOtherT == 0); | 863 SkASSERT(span->fOtherT == 0); |
789 SkASSERT(!oSpan.fTiny && (other->fTs[span.fOtherIndex + 1].fT > 0 | 864 SkASSERT(!oSpan.fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0 |
790 || (other->fTs[span.fOtherIndex + 1].fFromAngleIndex < 0 | 865 || (other->fTs[span->fOtherIndex + 1].fFromAngle == NULL |
791 && other->fTs[span.fOtherIndex + 1].fToAngleIndex < 0))); | 866 && other->fTs[span->fOtherIndex + 1].fToAngle == NULL))); |
792 int oIndex = 1; | 867 int oIndex = 1; |
793 do { | 868 do { |
794 const SkOpSpan& osSpan = other->span(oIndex); | 869 const SkOpSpan& osSpan = other->span(oIndex); |
795 if (osSpan.fFromAngleIndex >= 0 || osSpan.fT > 0) { | 870 if (osSpan.fFromAngle || osSpan.fT > 0) { |
796 break; | 871 break; |
797 } | 872 } |
798 ++oIndex; | 873 ++oIndex; |
799 SkASSERT(oIndex < other->count()); | 874 SkASSERT(oIndex < other->count()); |
800 } while (true); | 875 } while (true); |
801 other->addStartSpan(oIndex); | 876 other->addStartSpan(oIndex); |
802 angle = &this->angle(span.fFromAngleIndex); | 877 angle = span->fFromAngle; |
803 oAngle = &other->angle(oSpan.fToAngleIndex); | 878 oAngle = oSpan.fToAngle; |
804 } | 879 } |
805 angle->insert(oAngle); | 880 angle->insert(oAngle); |
806 } | 881 } |
807 | 882 |
| 883 void SkOpSegment::alignMultiples(SkTDArray<AlignedSpan>* alignedArray) { |
| 884 debugValidate(); |
| 885 int count = this->count(); |
| 886 for (int index = 0; index < count; ++index) { |
| 887 SkOpSpan& span = fTs[index]; |
| 888 if (!span.fMultiple) { |
| 889 continue; |
| 890 } |
| 891 int end = nextExactSpan(index, 1); |
| 892 SkASSERT(end > index + 1); |
| 893 const SkPoint& thisPt = span.fPt; |
| 894 while (index < end - 1) { |
| 895 SkOpSegment* other1 = span.fOther; |
| 896 int oCnt = other1->count(); |
| 897 for (int idx2 = index + 1; idx2 < end; ++idx2) { |
| 898 SkOpSpan& span2 = fTs[idx2]; |
| 899 SkOpSegment* other2 = span2.fOther; |
| 900 for (int oIdx = 0; oIdx < oCnt; ++oIdx) { |
| 901 SkOpSpan& oSpan = other1->fTs[oIdx]; |
| 902 if (oSpan.fOther != other2) { |
| 903 continue; |
| 904 } |
| 905 if (oSpan.fPt == thisPt) { |
| 906 goto skipExactMatches; |
| 907 } |
| 908 } |
| 909 for (int oIdx = 0; oIdx < oCnt; ++oIdx) { |
| 910 SkOpSpan& oSpan = other1->fTs[oIdx]; |
| 911 if (oSpan.fOther != other2) { |
| 912 continue; |
| 913 } |
| 914 if (SkDPoint::RoughlyEqual(oSpan.fPt, thisPt)) { |
| 915 SkOpSpan& oSpan2 = other2->fTs[oSpan.fOtherIndex]; |
| 916 if (zero_or_one(span.fOtherT) || zero_or_one(oSpan.fT) |
| 917 || zero_or_one(span2.fOtherT) || zero_or_one(oSp
an2.fT)) { |
| 918 return; |
| 919 } |
| 920 if (!way_roughly_equal(span.fOtherT, oSpan.fT) |
| 921 || !way_roughly_equal(span2.fOtherT, oSpan2.fT) |
| 922 || !way_roughly_equal(span2.fOtherT, oSpan.fOthe
rT) |
| 923 || !way_roughly_equal(span.fOtherT, oSpan2.fOthe
rT)) { |
| 924 return; |
| 925 } |
| 926 alignSpan(thisPt, span.fOtherT, other1, span2.fOtherT, |
| 927 other2, &oSpan, alignedArray); |
| 928 alignSpan(thisPt, span2.fOtherT, other2, span.fOtherT, |
| 929 other1, &oSpan2, alignedArray); |
| 930 break; |
| 931 } |
| 932 } |
| 933 skipExactMatches: |
| 934 ; |
| 935 } |
| 936 ++index; |
| 937 } |
| 938 } |
| 939 debugValidate(); |
| 940 } |
| 941 |
| 942 void SkOpSegment::alignSpan(const SkPoint& newPt, double newT, const SkOpSegment
* other, |
| 943 double otherT, const SkOpSegment* other2, SkOpSpan* oSpan, |
| 944 SkTDArray<AlignedSpan>* alignedArray) { |
| 945 AlignedSpan* aligned = alignedArray->append(); |
| 946 aligned->fOldPt = oSpan->fPt; |
| 947 aligned->fPt = newPt; |
| 948 aligned->fOldT = oSpan->fT; |
| 949 aligned->fT = newT; |
| 950 aligned->fSegment = this; // OPTIMIZE: may be unused, can remove |
| 951 aligned->fOther1 = other; |
| 952 aligned->fOther2 = other2; |
| 953 SkASSERT(SkDPoint::RoughlyEqual(oSpan->fPt, newPt)); |
| 954 oSpan->fPt = newPt; |
| 955 // SkASSERT(way_roughly_equal(oSpan->fT, newT)); |
| 956 oSpan->fT = newT; |
| 957 // SkASSERT(way_roughly_equal(oSpan->fOtherT, otherT)); |
| 958 oSpan->fOtherT = otherT; |
| 959 } |
| 960 |
808 bool SkOpSegment::alignSpan(int index, double thisT, const SkPoint& thisPt) { | 961 bool SkOpSegment::alignSpan(int index, double thisT, const SkPoint& thisPt) { |
809 bool aligned = false; | 962 bool aligned = false; |
810 SkOpSpan* span = &fTs[index]; | 963 SkOpSpan* span = &fTs[index]; |
811 SkOpSegment* other = span->fOther; | 964 SkOpSegment* other = span->fOther; |
812 int oIndex = span->fOtherIndex; | 965 int oIndex = span->fOtherIndex; |
813 SkOpSpan* oSpan = &other->fTs[oIndex]; | 966 SkOpSpan* oSpan = &other->fTs[oIndex]; |
814 if (span->fT != thisT) { | 967 if (span->fT != thisT) { |
815 span->fT = thisT; | 968 span->fT = thisT; |
816 oSpan->fOtherT = thisT; | 969 oSpan->fOtherT = thisT; |
817 aligned = true; | 970 aligned = true; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 if (span->fDone != allDone) { | 1023 if (span->fDone != allDone) { |
871 span->fDone = allDone; | 1024 span->fDone = allDone; |
872 fDoneSpans += allDone ? 1 : -1; | 1025 fDoneSpans += allDone ? 1 : -1; |
873 } | 1026 } |
874 SkASSERT(span->fWindValue == winding); | 1027 SkASSERT(span->fWindValue == winding); |
875 SkASSERT(span->fOppValue == oppWinding); | 1028 SkASSERT(span->fOppValue == oppWinding); |
876 ++index; | 1029 ++index; |
877 } | 1030 } |
878 } | 1031 } |
879 | 1032 |
| 1033 void SkOpSegment::blindCancel(const SkCoincidence& coincidence, SkOpSegment* oth
er) { |
| 1034 bool binary = fOperand != other->fOperand; |
| 1035 int index = 0; |
| 1036 int last = this->count(); |
| 1037 do { |
| 1038 SkOpSpan& span = this->fTs[--last]; |
| 1039 if (span.fT != 1 && !span.fSmall) { |
| 1040 break; |
| 1041 } |
| 1042 span.fCoincident = true; |
| 1043 } while (true); |
| 1044 int oIndex = other->count(); |
| 1045 do { |
| 1046 SkOpSpan& oSpan = other->fTs[--oIndex]; |
| 1047 if (oSpan.fT != 1 && !oSpan.fSmall) { |
| 1048 break; |
| 1049 } |
| 1050 oSpan.fCoincident = true; |
| 1051 } while (true); |
| 1052 do { |
| 1053 SkOpSpan* test = &this->fTs[index]; |
| 1054 int baseWind = test->fWindValue; |
| 1055 int baseOpp = test->fOppValue; |
| 1056 int endIndex = index; |
| 1057 while (++endIndex <= last) { |
| 1058 SkOpSpan* endSpan = &this->fTs[endIndex]; |
| 1059 SkASSERT(endSpan->fT < 1); |
| 1060 if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp
) { |
| 1061 break; |
| 1062 } |
| 1063 endSpan->fCoincident = true; |
| 1064 } |
| 1065 SkOpSpan* oTest = &other->fTs[oIndex]; |
| 1066 int oBaseWind = oTest->fWindValue; |
| 1067 int oBaseOpp = oTest->fOppValue; |
| 1068 int oStartIndex = oIndex; |
| 1069 while (--oStartIndex >= 0) { |
| 1070 SkOpSpan* oStartSpan = &other->fTs[oStartIndex]; |
| 1071 if (oStartSpan->fWindValue != oBaseWind || oStartSpan->fOppValue !=
oBaseOpp) { |
| 1072 break; |
| 1073 } |
| 1074 oStartSpan->fCoincident = true; |
| 1075 } |
| 1076 bool decrement = baseWind && oBaseWind; |
| 1077 bool bigger = baseWind >= oBaseWind; |
| 1078 do { |
| 1079 SkASSERT(test->fT < 1); |
| 1080 if (decrement) { |
| 1081 if (binary && bigger) { |
| 1082 test->fOppValue--; |
| 1083 } else { |
| 1084 decrementSpan(test); |
| 1085 } |
| 1086 } |
| 1087 test->fCoincident = true; |
| 1088 test = &fTs[++index]; |
| 1089 } while (index < endIndex); |
| 1090 do { |
| 1091 SkASSERT(oTest->fT < 1); |
| 1092 if (decrement) { |
| 1093 if (binary && !bigger) { |
| 1094 oTest->fOppValue--; |
| 1095 } else { |
| 1096 other->decrementSpan(oTest); |
| 1097 } |
| 1098 } |
| 1099 oTest->fCoincident = true; |
| 1100 oTest = &other->fTs[--oIndex]; |
| 1101 } while (oIndex > oStartIndex); |
| 1102 } while (index <= last && oIndex >= 0); |
| 1103 SkASSERT(index > last); |
| 1104 SkASSERT(oIndex < 0); |
| 1105 } |
| 1106 |
| 1107 void SkOpSegment::blindCoincident(const SkCoincidence& coincidence, SkOpSegment*
other) { |
| 1108 bool binary = fOperand != other->fOperand; |
| 1109 int index = 0; |
| 1110 int last = this->count(); |
| 1111 do { |
| 1112 SkOpSpan& span = this->fTs[--last]; |
| 1113 if (span.fT != 1 && !span.fSmall) { |
| 1114 break; |
| 1115 } |
| 1116 span.fCoincident = true; |
| 1117 } while (true); |
| 1118 int oIndex = 0; |
| 1119 int oLast = other->count(); |
| 1120 do { |
| 1121 SkOpSpan& oSpan = other->fTs[--oLast]; |
| 1122 if (oSpan.fT != 1 && !oSpan.fSmall) { |
| 1123 break; |
| 1124 } |
| 1125 oSpan.fCoincident = true; |
| 1126 } while (true); |
| 1127 do { |
| 1128 SkOpSpan* test = &this->fTs[index]; |
| 1129 int baseWind = test->fWindValue; |
| 1130 int baseOpp = test->fOppValue; |
| 1131 int endIndex = index; |
| 1132 SkOpSpan* endSpan; |
| 1133 while (++endIndex <= last) { |
| 1134 endSpan = &this->fTs[endIndex]; |
| 1135 SkASSERT(endSpan->fT < 1); |
| 1136 if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp
) { |
| 1137 break; |
| 1138 } |
| 1139 endSpan->fCoincident = true; |
| 1140 } |
| 1141 SkOpSpan* oTest = &other->fTs[oIndex]; |
| 1142 int oBaseWind = oTest->fWindValue; |
| 1143 int oBaseOpp = oTest->fOppValue; |
| 1144 int oEndIndex = oIndex; |
| 1145 SkOpSpan* oEndSpan; |
| 1146 while (++oEndIndex <= oLast) { |
| 1147 oEndSpan = &this->fTs[oEndIndex]; |
| 1148 SkASSERT(oEndSpan->fT < 1); |
| 1149 if (oEndSpan->fWindValue != oBaseWind || oEndSpan->fOppValue != oBas
eOpp) { |
| 1150 break; |
| 1151 } |
| 1152 oEndSpan->fCoincident = true; |
| 1153 } |
| 1154 // consolidate the winding count even if done |
| 1155 if ((test->fWindValue || test->fOppValue) && (oTest->fWindValue || oTest
->fOppValue)) { |
| 1156 if (!binary || test->fWindValue + oTest->fOppValue >= 0) { |
| 1157 bumpCoincidentBlind(binary, index, endIndex); |
| 1158 other->bumpCoincidentOBlind(oIndex, oEndIndex); |
| 1159 } else { |
| 1160 other->bumpCoincidentBlind(binary, oIndex, oEndIndex); |
| 1161 bumpCoincidentOBlind(index, endIndex); |
| 1162 } |
| 1163 } |
| 1164 index = endIndex; |
| 1165 oIndex = oEndIndex; |
| 1166 } while (index <= last && oIndex <= oLast); |
| 1167 SkASSERT(index > last); |
| 1168 SkASSERT(oIndex > oLast); |
| 1169 } |
| 1170 |
| 1171 void SkOpSegment::bumpCoincidentBlind(bool binary, int index, int endIndex) { |
| 1172 const SkOpSpan& oTest = fTs[index]; |
| 1173 int oWindValue = oTest.fWindValue; |
| 1174 int oOppValue = oTest.fOppValue; |
| 1175 if (binary) { |
| 1176 SkTSwap<int>(oWindValue, oOppValue); |
| 1177 } |
| 1178 do { |
| 1179 (void) bumpSpan(&fTs[index], oWindValue, oOppValue); |
| 1180 } while (++index < endIndex); |
| 1181 } |
| 1182 |
880 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in
dexPtr, | 1183 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in
dexPtr, |
881 SkTArray<SkPoint, true>* outsideTs) { | 1184 SkTArray<SkPoint, true>* outsideTs) { |
882 int index = *indexPtr; | 1185 int index = *indexPtr; |
883 int oWindValue = oTest.fWindValue; | 1186 int oWindValue = oTest.fWindValue; |
884 int oOppValue = oTest.fOppValue; | 1187 int oOppValue = oTest.fOppValue; |
885 if (binary) { | 1188 if (binary) { |
886 SkTSwap<int>(oWindValue, oOppValue); | 1189 SkTSwap<int>(oWindValue, oOppValue); |
887 } | 1190 } |
888 SkOpSpan* const test = &fTs[index]; | 1191 SkOpSpan* const test = &fTs[index]; |
889 SkOpSpan* end = test; | 1192 SkOpSpan* end = test; |
890 const SkPoint& oStartPt = oTest.fPt; | 1193 const SkPoint& oStartPt = oTest.fPt; |
891 do { | 1194 do { |
892 if (bumpSpan(end, oWindValue, oOppValue)) { | 1195 if (bumpSpan(end, oWindValue, oOppValue)) { |
893 TrackOutside(outsideTs, oStartPt); | 1196 TrackOutside(outsideTs, oStartPt); |
894 } | 1197 } |
895 end = &fTs[++index]; | 1198 end = &fTs[++index]; |
896 } while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && en
d->fT < 1); | 1199 } while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && en
d->fT < 1); |
897 *indexPtr = index; | 1200 *indexPtr = index; |
898 } | 1201 } |
899 | 1202 |
| 1203 void SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) { |
| 1204 do { |
| 1205 zeroSpan(&fTs[index]); |
| 1206 } while (++index < endIndex); |
| 1207 } |
| 1208 |
900 // because of the order in which coincidences are resolved, this and other | 1209 // because of the order in which coincidences are resolved, this and other |
901 // may not have the same intermediate points. Compute the corresponding | 1210 // may not have the same intermediate points. Compute the corresponding |
902 // intermediate T values (using this as the master, other as the follower) | 1211 // intermediate T values (using this as the master, other as the follower) |
903 // and walk other conditionally -- hoping that it catches up in the end | 1212 // and walk other conditionally -- hoping that it catches up in the end |
904 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, | 1213 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, |
905 SkTArray<SkPoint, true>* oOutsidePts) { | 1214 SkTArray<SkPoint, true>* oOutsidePts) { |
906 int oIndex = *oIndexPtr; | 1215 int oIndex = *oIndexPtr; |
907 SkOpSpan* const oTest = &fTs[oIndex]; | 1216 SkOpSpan* const oTest = &fTs[oIndex]; |
908 SkOpSpan* oEnd = oTest; | 1217 SkOpSpan* oEnd = oTest; |
909 const SkPoint& oStartPt = oTest->fPt; | 1218 const SkPoint& oStartPt = oTest->fPt; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 } | 1327 } |
1019 test = &fTs[++index]; | 1328 test = &fTs[++index]; |
1020 testPt = &test->fPt; | 1329 testPt = &test->fPt; |
1021 } while (endPt != *testPt); | 1330 } while (endPt != *testPt); |
1022 } | 1331 } |
1023 if (endPt != *oTestPt) { | 1332 if (endPt != *oTestPt) { |
1024 // look ahead to see if zeroing more spans will allows us to catch up | 1333 // look ahead to see if zeroing more spans will allows us to catch up |
1025 int oPeekIndex = oIndex; | 1334 int oPeekIndex = oIndex; |
1026 bool success = true; | 1335 bool success = true; |
1027 SkOpSpan* oPeek; | 1336 SkOpSpan* oPeek; |
| 1337 int oCount = other->count(); |
1028 do { | 1338 do { |
1029 oPeek = &other->fTs[oPeekIndex]; | 1339 oPeek = &other->fTs[oPeekIndex]; |
1030 if (oPeek->fT == 1) { | 1340 if (++oPeekIndex == oCount) { |
1031 success = false; | 1341 success = false; |
1032 break; | 1342 break; |
1033 } | 1343 } |
1034 ++oPeekIndex; | |
1035 } while (endPt != oPeek->fPt); | 1344 } while (endPt != oPeek->fPt); |
1036 if (success) { | 1345 if (success) { |
1037 // make sure the matching point completes the coincidence span | 1346 // make sure the matching point completes the coincidence span |
1038 success = false; | 1347 success = false; |
1039 do { | 1348 do { |
1040 if (oPeek->fOther == this) { | 1349 if (oPeek->fOther == this) { |
1041 success = true; | 1350 success = true; |
1042 break; | 1351 break; |
1043 } | 1352 } |
1044 oPeek = &other->fTs[++oPeekIndex]; | 1353 oPeek = &other->fTs[++oPeekIndex]; |
(...skipping 11 matching lines...) Expand all Loading... |
1056 } while (endPt != *oTestPt); | 1365 } while (endPt != *oTestPt); |
1057 } | 1366 } |
1058 } | 1367 } |
1059 int outCount = outsidePts.count(); | 1368 int outCount = outsidePts.count(); |
1060 if (!done() && outCount) { | 1369 if (!done() && outCount) { |
1061 addCoinOutsides(outsidePts[0], endPt, other); | 1370 addCoinOutsides(outsidePts[0], endPt, other); |
1062 } | 1371 } |
1063 if (!other->done() && oOutsidePts.count()) { | 1372 if (!other->done() && oOutsidePts.count()) { |
1064 other->addCoinOutsides(oOutsidePts[0], endPt, this); | 1373 other->addCoinOutsides(oOutsidePts[0], endPt, this); |
1065 } | 1374 } |
| 1375 setCoincidentRange(startPt, endPt, other); |
| 1376 other->setCoincidentRange(startPt, endPt, this); |
1066 } | 1377 } |
1067 | 1378 |
1068 // FIXME: this doesn't prevent the same span from being added twice | 1379 // FIXME: this doesn't prevent the same span from being added twice |
1069 // fix in caller, SkASSERT here? | 1380 // fix in caller, SkASSERT here? |
1070 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other
T, bool borrowWind, | 1381 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other
T, bool borrowWind, |
1071 const SkPoint& pt) { | 1382 const SkPoint& pt, const SkPoint& pt2) { |
1072 int tCount = fTs.count(); | 1383 int tCount = fTs.count(); |
1073 for (int tIndex = 0; tIndex < tCount; ++tIndex) { | 1384 for (int tIndex = 0; tIndex < tCount; ++tIndex) { |
1074 const SkOpSpan& span = fTs[tIndex]; | 1385 const SkOpSpan& span = fTs[tIndex]; |
1075 if (!approximately_negative(span.fT - t)) { | 1386 if (!approximately_negative(span.fT - t)) { |
1076 break; | 1387 break; |
1077 } | 1388 } |
1078 if (approximately_negative(span.fT - t) && span.fOther == other | 1389 if (approximately_negative(span.fT - t) && span.fOther == other |
1079 && approximately_equal(span.fOtherT, otherT)) { | 1390 && approximately_equal(span.fOtherT, otherT)) { |
1080 #if DEBUG_ADD_T_PAIR | 1391 #if DEBUG_ADD_T_PAIR |
1081 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", | 1392 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", |
1082 __FUNCTION__, fID, t, other->fID, otherT); | 1393 __FUNCTION__, fID, t, other->fID, otherT); |
1083 #endif | 1394 #endif |
1084 return NULL; | 1395 return NULL; |
1085 } | 1396 } |
1086 } | 1397 } |
1087 #if DEBUG_ADD_T_PAIR | 1398 #if DEBUG_ADD_T_PAIR |
1088 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", | 1399 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", |
1089 __FUNCTION__, fID, t, other->fID, otherT); | 1400 __FUNCTION__, fID, t, other->fID, otherT); |
1090 #endif | 1401 #endif |
1091 int insertedAt = addT(other, pt, t); | 1402 int insertedAt = addT(other, pt, t); |
1092 int otherInsertedAt = other->addT(this, pt, otherT); | 1403 int otherInsertedAt = other->addT(this, pt2, otherT); |
1093 addOtherT(insertedAt, otherT, otherInsertedAt); | 1404 addOtherT(insertedAt, otherT, otherInsertedAt); |
1094 other->addOtherT(otherInsertedAt, t, insertedAt); | 1405 other->addOtherT(otherInsertedAt, t, insertedAt); |
1095 matchWindingValue(insertedAt, t, borrowWind); | 1406 matchWindingValue(insertedAt, t, borrowWind); |
1096 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); | 1407 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); |
1097 return &span(insertedAt); | 1408 SkOpSpan& span = this->fTs[insertedAt]; |
| 1409 if (pt != pt2) { |
| 1410 span.fNear = true; |
| 1411 SkOpSpan& oSpan = other->fTs[otherInsertedAt]; |
| 1412 oSpan.fNear = true; |
| 1413 } |
| 1414 return &span; |
1098 } | 1415 } |
1099 | 1416 |
1100 const SkOpAngle& SkOpSegment::angle(int index) const { | 1417 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other
T, bool borrowWind, |
1101 SkASSERT(index >= 0); | 1418 const SkPoint& pt) { |
1102 int count = fAngles.count(); | 1419 return addTPair(t, other, otherT, borrowWind, pt, pt); |
1103 if (index < count) { | |
1104 return fAngles[index]; | |
1105 } | |
1106 index -= count; | |
1107 count = fSingletonAngles.count(); | |
1108 SkASSERT(index < count); | |
1109 return fSingletonAngles[index]; | |
1110 } | 1420 } |
1111 | 1421 |
1112 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint&
pt2) const { | 1422 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint&
pt2) const { |
1113 const SkPoint midPt = ptAtT(midT); | 1423 const SkPoint midPt = ptAtT(midT); |
1114 SkPathOpsBounds bounds; | 1424 SkPathOpsBounds bounds; |
1115 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY); | 1425 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY); |
1116 bounds.sort(); | 1426 bounds.sort(); |
1117 return bounds.almostContains(midPt); | 1427 return bounds.almostContains(midPt); |
1118 } | 1428 } |
1119 | 1429 |
(...skipping 11 matching lines...) Expand all Loading... |
1131 int spanCount = fTs.count(); | 1441 int spanCount = fTs.count(); |
1132 if (spanCount <= 2) { | 1442 if (spanCount <= 2) { |
1133 return spanCount == 2; | 1443 return spanCount == 2; |
1134 } | 1444 } |
1135 int index = 1; | 1445 int index = 1; |
1136 const SkOpSpan* firstSpan = &fTs[index]; | 1446 const SkOpSpan* firstSpan = &fTs[index]; |
1137 int activePrior = checkSetAngle(0); | 1447 int activePrior = checkSetAngle(0); |
1138 const SkOpSpan* span = &fTs[0]; | 1448 const SkOpSpan* span = &fTs[0]; |
1139 if (firstSpan->fT == 0 || span->fTiny || span->fOtherT != 1 || span->fOther-
>multipleEnds()) { | 1449 if (firstSpan->fT == 0 || span->fTiny || span->fOtherT != 1 || span->fOther-
>multipleEnds()) { |
1140 index = findStartSpan(0); // curve start intersects | 1450 index = findStartSpan(0); // curve start intersects |
1141 if (index < 0) { | 1451 SkASSERT(index > 0); |
1142 return false; | |
1143 } | |
1144 if (activePrior >= 0) { | 1452 if (activePrior >= 0) { |
1145 addStartSpan(index); | 1453 addStartSpan(index); |
1146 } | 1454 } |
1147 } | 1455 } |
1148 bool addEnd; | 1456 bool addEnd; |
1149 int endIndex = spanCount - 1; | 1457 int endIndex = spanCount - 1; |
1150 span = &fTs[endIndex - 1]; | 1458 span = &fTs[endIndex - 1]; |
1151 if ((addEnd = span->fT == 1 || span->fTiny)) { // if curve end intersects | 1459 if ((addEnd = span->fT == 1 || span->fTiny)) { // if curve end intersects |
1152 endIndex = findEndSpan(endIndex); | 1460 endIndex = findEndSpan(endIndex); |
1153 if (endIndex < 0) { | 1461 SkASSERT(endIndex > 0); |
1154 return false; | |
1155 } | |
1156 } else { | 1462 } else { |
1157 addEnd = fTs[endIndex].fOtherT != 0 || fTs[endIndex].fOther->multipleSta
rts(); | 1463 addEnd = fTs[endIndex].fOtherT != 0 || fTs[endIndex].fOther->multipleSta
rts(); |
1158 } | 1464 } |
1159 SkASSERT(endIndex >= index); | 1465 SkASSERT(endIndex >= index); |
1160 int prior = 0; | 1466 int prior = 0; |
1161 while (index < endIndex) { | 1467 while (index < endIndex) { |
1162 const SkOpSpan& fromSpan = fTs[index]; // for each intermediate interse
ction | 1468 const SkOpSpan& fromSpan = fTs[index]; // for each intermediate interse
ction |
1163 const SkOpSpan* lastSpan; | 1469 const SkOpSpan* lastSpan; |
1164 span = &fromSpan; | 1470 span = &fromSpan; |
1165 int start = index; | 1471 int start = index; |
1166 do { | 1472 do { |
1167 lastSpan = span; | 1473 lastSpan = span; |
1168 span = &fTs[++index]; | 1474 span = &fTs[++index]; |
1169 SkASSERT(index < spanCount); | 1475 SkASSERT(index < spanCount); |
1170 if (!precisely_negative(span->fT - lastSpan->fT) && !lastSpan->fTiny
) { | 1476 if (!precisely_negative(span->fT - lastSpan->fT) && !lastSpan->fTiny
) { |
1171 break; | 1477 break; |
1172 } | 1478 } |
1173 if (!SkDPoint::ApproximatelyEqual(lastSpan->fPt, span->fPt)) { | 1479 if (!SkDPoint::ApproximatelyEqual(lastSpan->fPt, span->fPt)) { |
1174 return false; | 1480 return false; |
1175 } | 1481 } |
1176 } while (true); | 1482 } while (true); |
1177 int angleIndex = fAngles.count(); | 1483 SkOpAngle* angle = NULL; |
1178 int priorAngleIndex; | 1484 SkOpAngle* priorAngle; |
1179 if (activePrior >= 0) { | 1485 if (activePrior >= 0) { |
1180 int pActive = firstActive(prior); | 1486 int pActive = firstActive(prior); |
1181 SkASSERT(pActive < start); | 1487 SkASSERT(pActive < start); |
1182 fAngles.push_back().set(this, start, pActive); | 1488 priorAngle = &fAngles.push_back(); |
1183 priorAngleIndex = angleIndex++; | 1489 priorAngle->set(this, start, pActive); |
1184 #if DEBUG_ANGLE | |
1185 fAngles.back().setID(priorAngleIndex); | |
1186 #endif | |
1187 } | 1490 } |
1188 int active = checkSetAngle(start); | 1491 int active = checkSetAngle(start); |
1189 if (active >= 0) { | 1492 if (active >= 0) { |
1190 SkASSERT(active < index); | 1493 SkASSERT(active < index); |
1191 fAngles.push_back().set(this, active, index); | 1494 angle = &fAngles.push_back(); |
1192 #if DEBUG_ANGLE | 1495 angle->set(this, active, index); |
1193 fAngles.back().setID(angleIndex); | |
1194 #endif | |
1195 } | 1496 } |
1196 #if DEBUG_ANGLE | 1497 #if DEBUG_ANGLE |
1197 debugCheckPointsEqualish(start, index); | 1498 debugCheckPointsEqualish(start, index); |
1198 #endif | 1499 #endif |
1199 prior = start; | 1500 prior = start; |
1200 do { | 1501 do { |
1201 const SkOpSpan* startSpan = &fTs[start - 1]; | 1502 const SkOpSpan* startSpan = &fTs[start - 1]; |
1202 if (!startSpan->fSmall || startSpan->fFromAngleIndex >= 0 | 1503 if (!startSpan->fSmall || isCanceled(start - 1) || startSpan->fFromA
ngle |
1203 || startSpan->fToAngleIndex >= 0) { | 1504 || startSpan->fToAngle) { |
1204 break; | 1505 break; |
1205 } | 1506 } |
1206 --start; | 1507 --start; |
1207 } while (start > 0); | 1508 } while (start > 0); |
1208 do { | 1509 do { |
1209 if (activePrior >= 0) { | 1510 if (activePrior >= 0) { |
1210 SkASSERT(fTs[start].fFromAngleIndex == -1); | 1511 SkASSERT(fTs[start].fFromAngle == NULL); |
1211 fTs[start].fFromAngleIndex = priorAngleIndex; | 1512 fTs[start].fFromAngle = priorAngle; |
1212 } | 1513 } |
1213 if (active >= 0) { | 1514 if (active >= 0) { |
1214 SkASSERT(fTs[start].fToAngleIndex == -1); | 1515 SkASSERT(fTs[start].fToAngle == NULL); |
1215 fTs[start].fToAngleIndex = angleIndex; | 1516 fTs[start].fToAngle = angle; |
1216 } | 1517 } |
1217 } while (++start < index); | 1518 } while (++start < index); |
1218 activePrior = active; | 1519 activePrior = active; |
1219 } | 1520 } |
1220 if (addEnd && activePrior >= 0) { | 1521 if (addEnd && activePrior >= 0) { |
1221 addEndSpan(endIndex); | 1522 addEndSpan(endIndex); |
1222 } | 1523 } |
1223 return true; | 1524 return true; |
1224 } | 1525 } |
1225 | 1526 |
1226 int SkOpSegment::checkSetAngle(int tIndex) const { | 1527 int SkOpSegment::checkSetAngle(int tIndex) const { |
1227 const SkOpSpan* span = &fTs[tIndex]; | 1528 const SkOpSpan* span = &fTs[tIndex]; |
1228 while (span->fTiny /* || span->fSmall */) { | 1529 while (span->fTiny /* || span->fSmall */) { |
1229 span = &fTs[++tIndex]; | 1530 span = &fTs[++tIndex]; |
1230 } | 1531 } |
1231 return isCanceled(tIndex) ? -1 : tIndex; | 1532 return isCanceled(tIndex) ? -1 : tIndex; |
1232 } | 1533 } |
1233 | 1534 |
1234 // at this point, the span is already ordered, or unorderable, or unsortable | 1535 // at this point, the span is already ordered, or unorderable |
1235 int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType
includeType) { | 1536 int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType
includeType) { |
1236 SkASSERT(includeType != SkOpAngle::kUnaryXor); | 1537 SkASSERT(includeType != SkOpAngle::kUnaryXor); |
1237 SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex); | 1538 SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex); |
1238 if (NULL == firstAngle) { | 1539 if (NULL == firstAngle) { |
1239 return SK_NaN32; | 1540 return SK_NaN32; |
1240 } | 1541 } |
1241 // if all angles have a computed winding, | 1542 // if all angles have a computed winding, |
1242 // or if no adjacent angles are orderable, | 1543 // or if no adjacent angles are orderable, |
1243 // or if adjacent orderable angles have no computed winding, | 1544 // or if adjacent orderable angles have no computed winding, |
1244 // there's nothing to do | 1545 // there's nothing to do |
1245 // if two orderable angles are adjacent, and one has winding computed, trans
fer to the other | 1546 // if two orderable angles are adjacent, and both are next to orderable angl
es, |
| 1547 // and one has winding computed, transfer to the other |
1246 SkOpAngle* baseAngle = NULL; | 1548 SkOpAngle* baseAngle = NULL; |
1247 bool tryReverse = false; | 1549 bool tryReverse = false; |
1248 // look for counterclockwise transfers | 1550 // look for counterclockwise transfers |
1249 SkOpAngle* angle = firstAngle; | 1551 SkOpAngle* angle = firstAngle->previous(); |
| 1552 SkOpAngle* next = angle->next(); |
| 1553 firstAngle = next; |
1250 do { | 1554 do { |
1251 int testWinding = angle->segment()->windSum(angle); | 1555 SkOpAngle* prior = angle; |
1252 if (SK_MinS32 != testWinding && !angle->unorderable()) { | 1556 angle = next; |
1253 baseAngle = angle; | 1557 next = angle->next(); |
| 1558 SkASSERT(prior->next() == angle); |
| 1559 SkASSERT(angle->next() == next); |
| 1560 if (prior->unorderable() || angle->unorderable() || next->unorderable())
{ |
| 1561 baseAngle = NULL; |
1254 continue; | 1562 continue; |
1255 } | 1563 } |
1256 if (angle->unorderable()) { | 1564 int testWinding = angle->segment()->windSum(angle); |
1257 baseAngle = NULL; | 1565 if (SK_MinS32 != testWinding) { |
| 1566 baseAngle = angle; |
1258 tryReverse = true; | 1567 tryReverse = true; |
1259 continue; | 1568 continue; |
1260 } | 1569 } |
1261 if (baseAngle) { | 1570 if (baseAngle) { |
1262 ComputeOneSum(baseAngle, angle, includeType); | 1571 ComputeOneSum(baseAngle, angle, includeType); |
1263 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle :
NULL; | 1572 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle :
NULL; |
1264 tryReverse |= !baseAngle; | |
1265 } | 1573 } |
1266 } while ((angle = angle->next()) != firstAngle); | 1574 } while (next != firstAngle); |
1267 if (baseAngle && SK_MinS32 == firstAngle->segment()->windSum(angle)) { | 1575 if (baseAngle && SK_MinS32 == firstAngle->segment()->windSum(firstAngle)) { |
1268 firstAngle = baseAngle; | 1576 firstAngle = baseAngle; |
1269 tryReverse = true; | 1577 tryReverse = true; |
1270 } | 1578 } |
1271 if (tryReverse) { | 1579 if (tryReverse) { |
1272 baseAngle = NULL; | 1580 baseAngle = NULL; |
1273 angle = firstAngle; | 1581 SkOpAngle* prior = firstAngle; |
1274 do { | 1582 do { |
| 1583 angle = prior; |
| 1584 prior = angle->previous(); |
| 1585 SkASSERT(prior->next() == angle); |
| 1586 next = angle->next(); |
| 1587 if (prior->unorderable() || angle->unorderable() || next->unorderabl
e()) { |
| 1588 baseAngle = NULL; |
| 1589 continue; |
| 1590 } |
1275 int testWinding = angle->segment()->windSum(angle); | 1591 int testWinding = angle->segment()->windSum(angle); |
1276 if (SK_MinS32 != testWinding) { | 1592 if (SK_MinS32 != testWinding) { |
1277 baseAngle = angle; | 1593 baseAngle = angle; |
1278 continue; | 1594 continue; |
1279 } | 1595 } |
1280 if (angle->unorderable()) { | |
1281 baseAngle = NULL; | |
1282 continue; | |
1283 } | |
1284 if (baseAngle) { | 1596 if (baseAngle) { |
1285 ComputeOneSumReverse(baseAngle, angle, includeType); | 1597 ComputeOneSumReverse(baseAngle, angle, includeType); |
1286 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angl
e : NULL; | 1598 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angl
e : NULL; |
1287 } | 1599 } |
1288 } while ((angle = angle->previous()) != firstAngle); | 1600 } while (prior != firstAngle); |
1289 } | 1601 } |
1290 int minIndex = SkMin32(startIndex, endIndex); | 1602 int minIndex = SkMin32(startIndex, endIndex); |
1291 return windSum(minIndex); | 1603 return windSum(minIndex); |
1292 } | 1604 } |
1293 | 1605 |
1294 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle
, | 1606 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle
, |
1295 SkOpAngle::IncludeType includeType) { | 1607 SkOpAngle::IncludeType includeType) { |
1296 const SkOpSegment* baseSegment = baseAngle->segment(); | 1608 const SkOpSegment* baseSegment = baseAngle->segment(); |
1297 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); | 1609 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); |
1298 int sumSuWinding; | 1610 int sumSuWinding; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 const SkOpSpan& span = this->span(index); | 1667 const SkOpSpan& span = this->span(index); |
1356 if (span.fPt == pt) { | 1668 if (span.fPt == pt) { |
1357 const SkOpSpan& endSpan = this->span(endIndex); | 1669 const SkOpSpan& endSpan = this->span(endIndex); |
1358 return span.fT == endSpan.fT && pt != endSpan.fPt; | 1670 return span.fT == endSpan.fT && pt != endSpan.fPt; |
1359 } | 1671 } |
1360 index += step; | 1672 index += step; |
1361 } while (index != endIndex); | 1673 } while (index != endIndex); |
1362 return false; | 1674 return false; |
1363 } | 1675 } |
1364 | 1676 |
| 1677 bool SkOpSegment::containsT(double t, const SkOpSegment* other, double otherT) c
onst { |
| 1678 int count = this->count(); |
| 1679 for (int index = 0; index < count; ++index) { |
| 1680 const SkOpSpan& span = fTs[index]; |
| 1681 if (t < span.fT) { |
| 1682 return false; |
| 1683 } |
| 1684 if (t == span.fT) { |
| 1685 if (other != span.fOther) { |
| 1686 continue; |
| 1687 } |
| 1688 if (other->fVerb != SkPath::kCubic_Verb) { |
| 1689 return true; |
| 1690 } |
| 1691 if (!other->fLoop) { |
| 1692 return true; |
| 1693 } |
| 1694 double otherMidT = (otherT + span.fOtherT) / 2; |
| 1695 SkPoint otherPt = other->ptAtT(otherMidT); |
| 1696 return SkDPoint::ApproximatelyEqual(span.fPt, otherPt); |
| 1697 } |
| 1698 } |
| 1699 return false; |
| 1700 } |
| 1701 |
1365 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi
tT, | 1702 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi
tT, |
1366 bool* hitSomething, double mid, bool opp, bool cur
rent) const { | 1703 bool* hitSomething, double mid, bool opp, bool cur
rent) const { |
1367 SkScalar bottom = fBounds.fBottom; | 1704 SkScalar bottom = fBounds.fBottom; |
1368 int bestTIndex = -1; | 1705 int bestTIndex = -1; |
1369 if (bottom <= *bestY) { | 1706 if (bottom <= *bestY) { |
1370 return bestTIndex; | 1707 return bestTIndex; |
1371 } | 1708 } |
1372 SkScalar top = fBounds.fTop; | 1709 SkScalar top = fBounds.fTop; |
1373 if (top >= basePt.fY) { | 1710 if (top >= basePt.fY) { |
1374 return bestTIndex; | 1711 return bestTIndex; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1535 testSpan = &firstSpan - 1; | 1872 testSpan = &firstSpan - 1; |
1536 smallCounts[0] = smallCounts[1] = 0; | 1873 smallCounts[0] = smallCounts[1] = 0; |
1537 while (++testSpan <= &lastSpan) { | 1874 while (++testSpan <= &lastSpan) { |
1538 SkASSERT(approximately_equal(testSpan->fT, firstLoopT) + | 1875 SkASSERT(approximately_equal(testSpan->fT, firstLoopT) + |
1539 approximately_equal(testSpan->fT, lastLoopT) == 1); | 1876 approximately_equal(testSpan->fT, lastLoopT) == 1); |
1540 smallCounts[approximately_equal(testSpan->fT, lastLoopT)]++; | 1877 smallCounts[approximately_equal(testSpan->fT, lastLoopT)]++; |
1541 } | 1878 } |
1542 return true; | 1879 return true; |
1543 } | 1880 } |
1544 | 1881 |
| 1882 double SkOpSegment::calcMissingTEnd(const SkOpSegment* ref, double loEnd, double
min, double max, |
| 1883 double hiEnd, const SkOpSegment* other, int thisStart) { |
| 1884 if (max >= hiEnd) { |
| 1885 return -1; |
| 1886 } |
| 1887 int end = findOtherT(hiEnd, ref); |
| 1888 if (end < 0) { |
| 1889 return -1; |
| 1890 } |
| 1891 double tHi = span(end).fT; |
| 1892 double tLo, refLo; |
| 1893 if (thisStart >= 0) { |
| 1894 tLo = span(thisStart).fT; |
| 1895 refLo = min; |
| 1896 } else { |
| 1897 int start1 = findOtherT(loEnd, ref); |
| 1898 SkASSERT(start1 >= 0); |
| 1899 tLo = span(start1).fT; |
| 1900 refLo = loEnd; |
| 1901 } |
| 1902 double missingT = (max - refLo) / (hiEnd - refLo); |
| 1903 missingT = tLo + missingT * (tHi - tLo); |
| 1904 return missingT; |
| 1905 } |
| 1906 |
| 1907 double SkOpSegment::calcMissingTStart(const SkOpSegment* ref, double loEnd, doub
le min, double max, |
| 1908 double hiEnd, const SkOpSegment* other, int thisEnd) { |
| 1909 if (min <= loEnd) { |
| 1910 return -1; |
| 1911 } |
| 1912 int start = findOtherT(loEnd, ref); |
| 1913 if (start < 0) { |
| 1914 return -1; |
| 1915 } |
| 1916 double tLo = span(start).fT; |
| 1917 double tHi, refHi; |
| 1918 if (thisEnd >= 0) { |
| 1919 tHi = span(thisEnd).fT; |
| 1920 refHi = max; |
| 1921 } else { |
| 1922 int end1 = findOtherT(hiEnd, ref); |
| 1923 if (end1 < 0) { |
| 1924 return -1; |
| 1925 } |
| 1926 tHi = span(end1).fT; |
| 1927 refHi = hiEnd; |
| 1928 } |
| 1929 double missingT = (min - loEnd) / (refHi - loEnd); |
| 1930 missingT = tLo + missingT * (tHi - tLo); |
| 1931 return missingT; |
| 1932 } |
| 1933 |
1545 // see if spans with two or more intersections have the same number on the other
end | 1934 // see if spans with two or more intersections have the same number on the other
end |
1546 void SkOpSegment::checkDuplicates() { | 1935 void SkOpSegment::checkDuplicates() { |
1547 debugValidate(); | 1936 debugValidate(); |
1548 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; | 1937 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; |
1549 int index; | 1938 int index; |
1550 int endIndex = 0; | 1939 int endIndex = 0; |
1551 bool endFound; | 1940 bool endFound; |
1552 do { | 1941 do { |
1553 index = endIndex; | 1942 index = endIndex; |
1554 endIndex = nextExactSpan(index, 1); | 1943 endIndex = nextExactSpan(index, 1); |
1555 if ((endFound = endIndex < 0)) { | 1944 if ((endFound = endIndex < 0)) { |
1556 endIndex = count(); | 1945 endIndex = count(); |
1557 } | 1946 } |
1558 int dupCount = endIndex - index; | 1947 int dupCount = endIndex - index; |
1559 if (dupCount < 2) { | 1948 if (dupCount < 2) { |
1560 continue; | 1949 continue; |
1561 } | 1950 } |
1562 do { | 1951 do { |
1563 const SkOpSpan* thisSpan = &fTs[index]; | 1952 const SkOpSpan* thisSpan = &fTs[index]; |
| 1953 if (thisSpan->fNear) { |
| 1954 continue; |
| 1955 } |
1564 SkOpSegment* other = thisSpan->fOther; | 1956 SkOpSegment* other = thisSpan->fOther; |
1565 int oIndex = thisSpan->fOtherIndex; | 1957 int oIndex = thisSpan->fOtherIndex; |
1566 int oStart = other->nextExactSpan(oIndex, -1) + 1; | 1958 int oStart = other->nextExactSpan(oIndex, -1) + 1; |
1567 int oEnd = other->nextExactSpan(oIndex, 1); | 1959 int oEnd = other->nextExactSpan(oIndex, 1); |
1568 if (oEnd < 0) { | 1960 if (oEnd < 0) { |
1569 oEnd = other->count(); | 1961 oEnd = other->count(); |
1570 } | 1962 } |
1571 int oCount = oEnd - oStart; | 1963 int oCount = oEnd - oStart; |
1572 // force the other to match its t and this pt if not on an end point | 1964 // force the other to match its t and this pt if not on an end point |
1573 if (oCount != dupCount) { | 1965 if (oCount != dupCount) { |
(...skipping 21 matching lines...) Expand all Loading... |
1595 if (missingCount == 0) { | 1987 if (missingCount == 0) { |
1596 return; | 1988 return; |
1597 } | 1989 } |
1598 SkSTArray<kMissingSpanCount, MissingSpan, true> missingCoincidence; | 1990 SkSTArray<kMissingSpanCount, MissingSpan, true> missingCoincidence; |
1599 for (index = 0; index < missingCount; ++index) { | 1991 for (index = 0; index < missingCount; ++index) { |
1600 MissingSpan& missing = missingSpans[index]; | 1992 MissingSpan& missing = missingSpans[index]; |
1601 SkOpSegment* missingOther = missing.fOther; | 1993 SkOpSegment* missingOther = missing.fOther; |
1602 if (missing.fSegment == missing.fOther) { | 1994 if (missing.fSegment == missing.fOther) { |
1603 continue; | 1995 continue; |
1604 } | 1996 } |
| 1997 #if 0 // FIXME: this eliminates spurious data from skpwww_argus_presse_fr_41 bu
t breaks |
| 1998 // skpwww_fashionscandal_com_94 -- calcAngles complains, but I don't unde
rstand why |
| 1999 if (missing.fSegment->containsT(missing.fT, missing.fOther, missing.fOth
erT)) { |
| 2000 #if DEBUG_DUPLICATES |
| 2001 SkDebugf("skip 1 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fSe
gment->fID, |
| 2002 missing.fT, missing.fOther->fID, missing.fOtherT); |
| 2003 #endif |
| 2004 continue; |
| 2005 } |
| 2006 if (missing.fOther->containsT(missing.fOtherT, missing.fSegment, missing
.fT)) { |
| 2007 #if DEBUG_DUPLICATES |
| 2008 SkDebugf("skip 2 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fOt
her->fID, |
| 2009 missing.fOtherT, missing.fSegment->fID, missing.fT); |
| 2010 #endif |
| 2011 continue; |
| 2012 } |
| 2013 #endif |
| 2014 // skip if adding would insert point into an existing coincindent span |
| 2015 if (missing.fSegment->inCoincidentSpan(missing.fT, missingOther) |
| 2016 && missingOther->inCoincidentSpan(missing.fOtherT, this)) { |
| 2017 continue; |
| 2018 } |
| 2019 // skip if the created coincident spans are small |
| 2020 if (missing.fSegment->coincidentSmall(missing.fPt, missing.fT, missingOt
her) |
| 2021 && missingOther->coincidentSmall(missing.fPt, missing.fOtherT, m
issing.fSegment)) { |
| 2022 continue; |
| 2023 } |
1605 const SkOpSpan* added = missing.fSegment->addTPair(missing.fT, missingOt
her, | 2024 const SkOpSpan* added = missing.fSegment->addTPair(missing.fT, missingOt
her, |
1606 missing.fOtherT, false, missing.fPt); | 2025 missing.fOtherT, false, missing.fPt); |
1607 if (added && added->fSmall) { | 2026 if (added && added->fSmall) { |
1608 missing.fSegment->checkSmallCoincidence(*added, &missingCoincidence)
; | 2027 missing.fSegment->checkSmallCoincidence(*added, &missingCoincidence)
; |
1609 } | 2028 } |
1610 } | 2029 } |
1611 for (index = 0; index < missingCount; ++index) { | 2030 for (index = 0; index < missingCount; ++index) { |
1612 MissingSpan& missing = missingSpans[index]; | 2031 MissingSpan& missing = missingSpans[index]; |
1613 missing.fSegment->fixOtherTIndex(); | 2032 missing.fSegment->fixOtherTIndex(); |
1614 missing.fOther->fixOtherTIndex(); | 2033 missing.fOther->fixOtherTIndex(); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1770 while (fTs[end].fT < 1) { | 2189 while (fTs[end].fT < 1) { |
1771 int start = index = end; | 2190 int start = index = end; |
1772 end = nextExactSpan(index, 1); | 2191 end = nextExactSpan(index, 1); |
1773 if (end <= index) { | 2192 if (end <= index) { |
1774 return; // buffer overflow example triggers this | 2193 return; // buffer overflow example triggers this |
1775 } | 2194 } |
1776 if (index + 1 == end) { | 2195 if (index + 1 == end) { |
1777 continue; | 2196 continue; |
1778 } | 2197 } |
1779 // force the duplicates to agree on t and pt if not on the end | 2198 // force the duplicates to agree on t and pt if not on the end |
1780 double thisT = fTs[index].fT; | 2199 SkOpSpan& span = fTs[index]; |
1781 const SkPoint& thisPt = fTs[index].fPt; | 2200 double thisT = span.fT; |
| 2201 const SkPoint& thisPt = span.fPt; |
| 2202 span.fMultiple = true; |
1782 bool aligned = false; | 2203 bool aligned = false; |
1783 while (++index < end) { | 2204 while (++index < end) { |
1784 aligned |= alignSpan(index, thisT, thisPt); | 2205 aligned |= alignSpan(index, thisT, thisPt); |
1785 } | 2206 } |
1786 if (aligned) { | 2207 if (aligned) { |
1787 alignSpanState(start, end); | 2208 alignSpanState(start, end); |
1788 } | 2209 } |
| 2210 fMultiples = true; |
1789 } | 2211 } |
1790 debugValidate(); | 2212 debugValidate(); |
1791 } | 2213 } |
1792 | 2214 |
1793 void SkOpSegment::CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan, | 2215 void SkOpSegment::CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan, |
1794 const SkOpSpan* oFirst, const SkOpSpan* oLast, const SkOpSpan** missingP
tr, | 2216 const SkOpSpan* oFirst, const SkOpSpan* oLast, const SkOpSpan** missingP
tr, |
1795 SkTArray<MissingSpan, true>* missingSpans) { | 2217 SkTArray<MissingSpan, true>* missingSpans) { |
1796 SkASSERT(oSpan->fPt == test->fPt); | 2218 SkASSERT(oSpan->fPt == test->fPt); |
1797 const SkOpSpan* oTest = oSpan; | 2219 const SkOpSpan* oTest = oSpan; |
1798 while (oTest > oFirst && (--oTest)->fPt == test->fPt) { | 2220 while (oTest > oFirst && (--oTest)->fPt == test->fPt) { |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2139 } | 2561 } |
2140 } | 2562 } |
2141 // OPTIMIZE: consolidate to avoid multiple calls to fix index | 2563 // OPTIMIZE: consolidate to avoid multiple calls to fix index |
2142 for (int index = 0; index < missingCount; ++index) { | 2564 for (int index = 0; index < missingCount; ++index) { |
2143 MissingSpan& missing = missingSpans[index]; | 2565 MissingSpan& missing = missingSpans[index]; |
2144 missing.fSegment->fixOtherTIndex(); | 2566 missing.fSegment->fixOtherTIndex(); |
2145 missing.fOther->fixOtherTIndex(); | 2567 missing.fOther->fixOtherTIndex(); |
2146 } | 2568 } |
2147 } | 2569 } |
2148 | 2570 |
| 2571 bool SkOpSegment::coincidentSmall(const SkPoint& pt, double t, const SkOpSegment
* other) const { |
| 2572 int count = this->count(); |
| 2573 for (int index = 0; index < count; ++index) { |
| 2574 const SkOpSpan& span = this->span(index); |
| 2575 if (span.fOther != other) { |
| 2576 continue; |
| 2577 } |
| 2578 if (span.fPt == pt) { |
| 2579 continue; |
| 2580 } |
| 2581 if (!AlmostEqualUlps(span.fPt, pt)) { |
| 2582 continue; |
| 2583 } |
| 2584 if (fVerb != SkPath::kCubic_Verb) { |
| 2585 return true; |
| 2586 } |
| 2587 double tInterval = t - span.fT; |
| 2588 double tMid = t - tInterval / 2; |
| 2589 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); |
| 2590 return midPt.approximatelyEqual(xyAtT(t)); |
| 2591 } |
| 2592 return false; |
| 2593 } |
| 2594 |
2149 bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* o
ther, int oStart, | 2595 bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* o
ther, int oStart, |
2150 int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) cons
t { | 2596 int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) cons
t { |
2151 SkASSERT(span->fT == 0 || span->fT == 1); | 2597 SkASSERT(span->fT == 0 || span->fT == 1); |
2152 SkASSERT(span->fOtherT == 0 || span->fOtherT == 1); | 2598 SkASSERT(span->fOtherT == 0 || span->fOtherT == 1); |
2153 const SkOpSpan* otherSpan = &other->span(oEnd); | 2599 const SkOpSpan* otherSpan = &other->span(oEnd); |
2154 double refT = otherSpan->fT; | 2600 double refT = otherSpan->fT; |
2155 const SkPoint& refPt = otherSpan->fPt; | 2601 const SkPoint& refPt = otherSpan->fPt; |
2156 const SkOpSpan* lastSpan = &other->span(step > 0 ? other->count() - 1 : 0); | 2602 const SkOpSpan* lastSpan = &other->span(step > 0 ? other->count() - 1 : 0); |
2157 do { | 2603 do { |
2158 const SkOpSegment* match = span->fOther; | 2604 const SkOpSegment* match = span->fOther; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2228 Opposite values result from combining coincident spans. | 2674 Opposite values result from combining coincident spans. |
2229 */ | 2675 */ |
2230 SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
, int* nextEnd, | 2676 SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
, int* nextEnd, |
2231 bool* unsortable, SkPathOp op, const int xo
rMiMask, | 2677 bool* unsortable, SkPathOp op, const int xo
rMiMask, |
2232 const int xorSuMask) { | 2678 const int xorSuMask) { |
2233 const int startIndex = *nextStart; | 2679 const int startIndex = *nextStart; |
2234 const int endIndex = *nextEnd; | 2680 const int endIndex = *nextEnd; |
2235 SkASSERT(startIndex != endIndex); | 2681 SkASSERT(startIndex != endIndex); |
2236 SkDEBUGCODE(const int count = fTs.count()); | 2682 SkDEBUGCODE(const int count = fTs.count()); |
2237 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); | 2683 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); |
2238 const int step = SkSign32(endIndex - startIndex); | 2684 int step = SkSign32(endIndex - startIndex); |
2239 const int end = nextExactSpan(startIndex, step); | 2685 *nextStart = startIndex; |
2240 SkASSERT(end >= 0); | 2686 SkOpSegment* other = isSimple(nextStart, &step); |
2241 SkOpSpan* endSpan = &fTs[end]; | 2687 if (other) |
2242 SkOpSegment* other; | 2688 { |
2243 if (isSimple(end)) { | |
2244 // mark the smaller of startIndex, endIndex done, and all adjacent | 2689 // mark the smaller of startIndex, endIndex done, and all adjacent |
2245 // spans with the same T value (but not 'other' spans) | 2690 // spans with the same T value (but not 'other' spans) |
2246 #if DEBUG_WINDING | 2691 #if DEBUG_WINDING |
2247 SkDebugf("%s simple\n", __FUNCTION__); | 2692 SkDebugf("%s simple\n", __FUNCTION__); |
2248 #endif | 2693 #endif |
2249 int min = SkMin32(startIndex, endIndex); | 2694 int min = SkMin32(startIndex, endIndex); |
2250 if (fTs[min].fDone) { | 2695 if (fTs[min].fDone) { |
2251 return NULL; | 2696 return NULL; |
2252 } | 2697 } |
2253 markDoneBinary(min); | 2698 markDoneBinary(min); |
2254 other = endSpan->fOther; | |
2255 *nextStart = endSpan->fOtherIndex; | |
2256 double startT = other->fTs[*nextStart].fT; | 2699 double startT = other->fTs[*nextStart].fT; |
2257 *nextEnd = *nextStart; | 2700 *nextEnd = *nextStart; |
2258 do { | 2701 do { |
2259 *nextEnd += step; | 2702 *nextEnd += step; |
2260 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); | 2703 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); |
2261 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); | 2704 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); |
2262 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { | 2705 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { |
2263 *unsortable = true; | 2706 *unsortable = true; |
2264 return NULL; | 2707 return NULL; |
2265 } | 2708 } |
2266 return other; | 2709 return other; |
2267 } | 2710 } |
| 2711 const int end = nextExactSpan(startIndex, step); |
| 2712 SkASSERT(end >= 0); |
2268 SkASSERT(startIndex - endIndex != 0); | 2713 SkASSERT(startIndex - endIndex != 0); |
2269 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); | 2714 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); |
2270 // more than one viable candidate -- measure angles to find best | 2715 // more than one viable candidate -- measure angles to find best |
2271 | 2716 |
2272 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp); | 2717 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp); |
2273 bool sortable = calcWinding != SK_NaN32; | 2718 bool sortable = calcWinding != SK_NaN32; |
2274 if (!sortable) { | 2719 if (!sortable) { |
2275 *unsortable = true; | 2720 *unsortable = true; |
2276 markDoneBinary(SkMin32(startIndex, endIndex)); | 2721 markDoneBinary(SkMin32(startIndex, endIndex)); |
2277 return NULL; | 2722 return NULL; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2318 foundDone = nextSegment->done(nextAngle); | 2763 foundDone = nextSegment->done(nextAngle); |
2319 } | 2764 } |
2320 } | 2765 } |
2321 if (nextSegment->done()) { | 2766 if (nextSegment->done()) { |
2322 continue; | 2767 continue; |
2323 } | 2768 } |
2324 if (nextSegment->isTiny(nextAngle)) { | 2769 if (nextSegment->isTiny(nextAngle)) { |
2325 continue; | 2770 continue; |
2326 } | 2771 } |
2327 if (!activeAngle) { | 2772 if (!activeAngle) { |
2328 nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextAngle->e
nd()); | 2773 (void) nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextA
ngle->end()); |
2329 } | 2774 } |
2330 SkOpSpan* last = nextAngle->lastMarked(); | 2775 SkOpSpan* last = nextAngle->lastMarked(); |
2331 if (last) { | 2776 if (last) { |
2332 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); | 2777 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); |
2333 *chase->append() = last; | 2778 *chase->append() = last; |
2334 #if DEBUG_WINDING | 2779 #if DEBUG_WINDING |
2335 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__
, | 2780 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__
, |
2336 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last
->fWindSum, | 2781 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last
->fWindSum, |
2337 last->fSmall); | 2782 last->fSmall); |
2338 #endif | 2783 #endif |
(...skipping 19 matching lines...) Expand all Loading... |
2358 return nextSegment; | 2803 return nextSegment; |
2359 } | 2804 } |
2360 | 2805 |
2361 SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
Start, | 2806 SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
Start, |
2362 int* nextEnd, bool* unsortable) { | 2807 int* nextEnd, bool* unsortable) { |
2363 const int startIndex = *nextStart; | 2808 const int startIndex = *nextStart; |
2364 const int endIndex = *nextEnd; | 2809 const int endIndex = *nextEnd; |
2365 SkASSERT(startIndex != endIndex); | 2810 SkASSERT(startIndex != endIndex); |
2366 SkDEBUGCODE(const int count = fTs.count()); | 2811 SkDEBUGCODE(const int count = fTs.count()); |
2367 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); | 2812 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); |
2368 const int step = SkSign32(endIndex - startIndex); | 2813 int step = SkSign32(endIndex - startIndex); |
2369 const int end = nextExactSpan(startIndex, step); | 2814 *nextStart = startIndex; |
2370 SkASSERT(end >= 0); | 2815 SkOpSegment* other = isSimple(nextStart, &step); |
2371 SkOpSpan* endSpan = &fTs[end]; | 2816 if (other) |
2372 SkOpSegment* other; | 2817 { |
2373 if (isSimple(end)) { | |
2374 // mark the smaller of startIndex, endIndex done, and all adjacent | 2818 // mark the smaller of startIndex, endIndex done, and all adjacent |
2375 // spans with the same T value (but not 'other' spans) | 2819 // spans with the same T value (but not 'other' spans) |
2376 #if DEBUG_WINDING | 2820 #if DEBUG_WINDING |
2377 SkDebugf("%s simple\n", __FUNCTION__); | 2821 SkDebugf("%s simple\n", __FUNCTION__); |
2378 #endif | 2822 #endif |
2379 int min = SkMin32(startIndex, endIndex); | 2823 int min = SkMin32(startIndex, endIndex); |
2380 if (fTs[min].fDone) { | 2824 if (fTs[min].fDone) { |
2381 return NULL; | 2825 return NULL; |
2382 } | 2826 } |
2383 markDoneUnary(min); | 2827 markDoneUnary(min); |
2384 other = endSpan->fOther; | |
2385 *nextStart = endSpan->fOtherIndex; | |
2386 double startT = other->fTs[*nextStart].fT; | 2828 double startT = other->fTs[*nextStart].fT; |
2387 *nextEnd = *nextStart; | 2829 *nextEnd = *nextStart; |
2388 do { | 2830 do { |
2389 *nextEnd += step; | 2831 *nextEnd += step; |
2390 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); | 2832 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); |
2391 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); | 2833 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); |
2392 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { | 2834 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { |
2393 *unsortable = true; | 2835 *unsortable = true; |
2394 return NULL; | 2836 return NULL; |
2395 } | 2837 } |
2396 return other; | 2838 return other; |
2397 } | 2839 } |
| 2840 const int end = nextExactSpan(startIndex, step); |
| 2841 SkASSERT(end >= 0); |
2398 SkASSERT(startIndex - endIndex != 0); | 2842 SkASSERT(startIndex - endIndex != 0); |
2399 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); | 2843 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); |
2400 // more than one viable candidate -- measure angles to find best | 2844 // more than one viable candidate -- measure angles to find best |
2401 | 2845 |
2402 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding); | 2846 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding); |
2403 bool sortable = calcWinding != SK_NaN32; | 2847 bool sortable = calcWinding != SK_NaN32; |
2404 if (!sortable) { | 2848 if (!sortable) { |
2405 *unsortable = true; | 2849 *unsortable = true; |
2406 markDoneUnary(SkMin32(startIndex, endIndex)); | 2850 markDoneUnary(SkMin32(startIndex, endIndex)); |
2407 return NULL; | 2851 return NULL; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2467 return nextSegment; | 2911 return nextSegment; |
2468 } | 2912 } |
2469 | 2913 |
2470 SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
able) { | 2914 SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
able) { |
2471 const int startIndex = *nextStart; | 2915 const int startIndex = *nextStart; |
2472 const int endIndex = *nextEnd; | 2916 const int endIndex = *nextEnd; |
2473 SkASSERT(startIndex != endIndex); | 2917 SkASSERT(startIndex != endIndex); |
2474 SkDEBUGCODE(int count = fTs.count()); | 2918 SkDEBUGCODE(int count = fTs.count()); |
2475 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); | 2919 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); |
2476 int step = SkSign32(endIndex - startIndex); | 2920 int step = SkSign32(endIndex - startIndex); |
2477 int end = nextExactSpan(startIndex, step); | |
2478 SkASSERT(end >= 0); | |
2479 SkOpSpan* endSpan = &fTs[end]; | |
2480 SkOpSegment* other; | |
2481 // Detect cases where all the ends canceled out (e.g., | 2921 // Detect cases where all the ends canceled out (e.g., |
2482 // there is no angle) and therefore there's only one valid connection | 2922 // there is no angle) and therefore there's only one valid connection |
2483 if (isSimple(end) || !spanToAngle(end, startIndex)) { | 2923 *nextStart = startIndex; |
| 2924 SkOpSegment* other = isSimple(nextStart, &step); |
| 2925 if (other) |
| 2926 { |
2484 #if DEBUG_WINDING | 2927 #if DEBUG_WINDING |
2485 SkDebugf("%s simple\n", __FUNCTION__); | 2928 SkDebugf("%s simple\n", __FUNCTION__); |
2486 #endif | 2929 #endif |
2487 int min = SkMin32(startIndex, endIndex); | 2930 int min = SkMin32(startIndex, endIndex); |
2488 if (fTs[min].fDone) { | 2931 if (fTs[min].fDone) { |
2489 return NULL; | 2932 return NULL; |
2490 } | 2933 } |
2491 markDone(min, 1); | 2934 markDone(min, 1); |
2492 other = endSpan->fOther; | |
2493 *nextStart = endSpan->fOtherIndex; | |
2494 double startT = other->fTs[*nextStart].fT; | 2935 double startT = other->fTs[*nextStart].fT; |
2495 // FIXME: I don't know why the logic here is difference from the winding
case | 2936 // FIXME: I don't know why the logic here is difference from the winding
case |
2496 SkDEBUGCODE(bool firstLoop = true;) | 2937 SkDEBUGCODE(bool firstLoop = true;) |
2497 if ((approximately_less_than_zero(startT) && step < 0) | 2938 if ((approximately_less_than_zero(startT) && step < 0) |
2498 || (approximately_greater_than_one(startT) && step > 0)) { | 2939 || (approximately_greater_than_one(startT) && step > 0)) { |
2499 step = -step; | 2940 step = -step; |
2500 SkDEBUGCODE(firstLoop = false;) | 2941 SkDEBUGCODE(firstLoop = false;) |
2501 } | 2942 } |
2502 do { | 2943 do { |
2503 *nextEnd = *nextStart; | 2944 *nextEnd = *nextStart; |
2504 do { | 2945 do { |
2505 *nextEnd += step; | 2946 *nextEnd += step; |
2506 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); | 2947 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); |
2507 if (other->fTs[SkMin32(*nextStart, *nextEnd)].fWindValue) { | 2948 if (other->fTs[SkMin32(*nextStart, *nextEnd)].fWindValue) { |
2508 break; | 2949 break; |
2509 } | 2950 } |
2510 SkASSERT(firstLoop); | 2951 SkASSERT(firstLoop); |
2511 SkDEBUGCODE(firstLoop = false;) | 2952 SkDEBUGCODE(firstLoop = false;) |
2512 step = -step; | 2953 step = -step; |
2513 } while (true); | 2954 } while (true); |
2514 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); | 2955 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); |
2515 return other; | 2956 return other; |
2516 } | 2957 } |
2517 SkASSERT(startIndex - endIndex != 0); | 2958 SkASSERT(startIndex - endIndex != 0); |
2518 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); | 2959 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); |
2519 // parallel block above with presorted version | 2960 // parallel block above with presorted version |
| 2961 int end = nextExactSpan(startIndex, step); |
| 2962 SkASSERT(end >= 0); |
2520 SkOpAngle* angle = spanToAngle(end, startIndex); | 2963 SkOpAngle* angle = spanToAngle(end, startIndex); |
2521 SkASSERT(angle); | 2964 SkASSERT(angle); |
2522 #if DEBUG_SORT | 2965 #if DEBUG_SORT |
2523 SkDebugf("%s\n", __FUNCTION__); | 2966 SkDebugf("%s\n", __FUNCTION__); |
2524 angle->debugLoop(); | 2967 angle->debugLoop(); |
2525 #endif | 2968 #endif |
2526 SkOpAngle* nextAngle = angle->next(); | 2969 SkOpAngle* nextAngle = angle->next(); |
2527 const SkOpAngle* foundAngle = NULL; | 2970 const SkOpAngle* foundAngle = NULL; |
2528 bool foundDone = false; | 2971 bool foundDone = false; |
2529 SkOpSegment* nextSegment; | 2972 SkOpSegment* nextSegment; |
(...skipping 25 matching lines...) Expand all Loading... |
2555 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn
d); | 2998 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn
d); |
2556 #endif | 2999 #endif |
2557 return nextSegment; | 3000 return nextSegment; |
2558 } | 3001 } |
2559 | 3002 |
2560 int SkOpSegment::findStartSpan(int startIndex) const { | 3003 int SkOpSegment::findStartSpan(int startIndex) const { |
2561 int index = startIndex; | 3004 int index = startIndex; |
2562 const SkOpSpan* span = &fTs[index]; | 3005 const SkOpSpan* span = &fTs[index]; |
2563 const SkPoint& firstPt = span->fPt; | 3006 const SkPoint& firstPt = span->fPt; |
2564 double firstT = span->fT; | 3007 double firstT = span->fT; |
| 3008 const SkOpSpan* prior; |
2565 do { | 3009 do { |
2566 if (index > 0) { | 3010 prior = span; |
2567 if (span->fT != firstT) { | 3011 span = &fTs[++index]; |
2568 break; | 3012 } while (SkDPoint::ApproximatelyEqual(span->fPt, firstPt) |
2569 } | 3013 && (span->fT == firstT || prior->fTiny)); |
2570 if (!SkDPoint::ApproximatelyEqual(firstPt, fTs[index].fPt)) { | |
2571 return -1; | |
2572 } | |
2573 } | |
2574 ++index; | |
2575 if (span->fTiny) { | |
2576 if (!SkDPoint::ApproximatelyEqual(firstPt, fTs[index].fPt)) { | |
2577 return -1; | |
2578 } | |
2579 firstT = fTs[index++].fT; | |
2580 } | |
2581 span = &fTs[index]; | |
2582 } while (true); | |
2583 return index; | 3014 return index; |
2584 } | 3015 } |
2585 | 3016 |
2586 int SkOpSegment::findExactT(double t, const SkOpSegment* match) const { | 3017 int SkOpSegment::findExactT(double t, const SkOpSegment* match) const { |
2587 int count = this->count(); | 3018 int count = this->count(); |
2588 for (int index = 0; index < count; ++index) { | 3019 for (int index = 0; index < count; ++index) { |
2589 const SkOpSpan& span = fTs[index]; | 3020 const SkOpSpan& span = fTs[index]; |
2590 if (span.fT == t && span.fOther == match) { | 3021 if (span.fT == t && span.fOther == match) { |
2591 return index; | 3022 return index; |
2592 } | 3023 } |
2593 } | 3024 } |
2594 SkASSERT(0); | 3025 SkASSERT(0); |
2595 return -1; | 3026 return -1; |
2596 } | 3027 } |
2597 | 3028 |
| 3029 int SkOpSegment::findOtherT(double t, const SkOpSegment* match) const { |
| 3030 int count = this->count(); |
| 3031 for (int index = 0; index < count; ++index) { |
| 3032 const SkOpSpan& span = fTs[index]; |
| 3033 if (span.fOtherT == t && span.fOther == match) { |
| 3034 return index; |
| 3035 } |
| 3036 } |
| 3037 return -1; |
| 3038 } |
| 3039 |
2598 int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) co
nst { | 3040 int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) co
nst { |
2599 int count = this->count(); | 3041 int count = this->count(); |
2600 for (int index = 0; index < count; ++index) { | 3042 for (int index = 0; index < count; ++index) { |
2601 const SkOpSpan& span = fTs[index]; | 3043 const SkOpSpan& span = fTs[index]; |
2602 if (approximately_equal_orderable(span.fT, t) && span.fOther == match) { | 3044 if (approximately_equal_orderable(span.fT, t) && span.fOther == match) { |
2603 return index; | 3045 return index; |
2604 } | 3046 } |
2605 } | 3047 } |
2606 // Usually, the pair of ts are an exact match. It's possible that the t valu
es have | 3048 // Usually, the pair of ts are an exact match. It's possible that the t valu
es have |
2607 // been adjusted to make multiple intersections align. In this rare case, lo
ok for a | 3049 // been adjusted to make multiple intersections align. In this rare case, lo
ok for a |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2640 if (span(firstT).fDone || (end = nextSpan(firstT, step)) == -1) { | 3082 if (span(firstT).fDone || (end = nextSpan(firstT, step)) == -1) { |
2641 step = -1; | 3083 step = -1; |
2642 end = nextSpan(firstT, step); | 3084 end = nextSpan(firstT, step); |
2643 SkASSERT(end != -1); | 3085 SkASSERT(end != -1); |
2644 } | 3086 } |
2645 // if the topmost T is not on end, or is three-way or more, find left | 3087 // if the topmost T is not on end, or is three-way or more, find left |
2646 // look for left-ness from tLeft to firstT (matching y of other) | 3088 // look for left-ness from tLeft to firstT (matching y of other) |
2647 SkASSERT(firstT - end != 0); | 3089 SkASSERT(firstT - end != 0); |
2648 SkOpAngle* markAngle = spanToAngle(firstT, end); | 3090 SkOpAngle* markAngle = spanToAngle(firstT, end); |
2649 if (!markAngle) { | 3091 if (!markAngle) { |
2650 markAngle = addSingletonAngles(firstT, step); | 3092 markAngle = addSingletonAngles(step); |
2651 } | 3093 } |
2652 markAngle->markStops(); | 3094 markAngle->markStops(); |
2653 const SkOpAngle* baseAngle = markAngle->findFirst(); | 3095 const SkOpAngle* baseAngle = markAngle->findFirst(); |
2654 if (!baseAngle) { | 3096 if (!baseAngle) { |
2655 return NULL; // nothing to do | 3097 return NULL; // nothing to do |
2656 } | 3098 } |
2657 SkScalar top = SK_ScalarMax; | 3099 SkScalar top = SK_ScalarMax; |
2658 const SkOpAngle* firstAngle = NULL; | 3100 const SkOpAngle* firstAngle = NULL; |
2659 const SkOpAngle* angle = baseAngle; | 3101 const SkOpAngle* angle = baseAngle; |
2660 do { | 3102 do { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2747 if (oT == oSpan.fT && this == oSpan.fOther && oSpan.fOtherT == iSpan
.fT) { | 3189 if (oT == oSpan.fT && this == oSpan.fOther && oSpan.fOtherT == iSpan
.fT) { |
2748 iSpan.fOtherIndex = o; | 3190 iSpan.fOtherIndex = o; |
2749 oSpan.fOtherIndex = i; | 3191 oSpan.fOtherIndex = i; |
2750 break; | 3192 break; |
2751 } | 3193 } |
2752 } | 3194 } |
2753 SkASSERT(iSpan.fOtherIndex >= 0); | 3195 SkASSERT(iSpan.fOtherIndex >= 0); |
2754 } | 3196 } |
2755 } | 3197 } |
2756 | 3198 |
| 3199 bool SkOpSegment::inCoincidentSpan(double t, const SkOpSegment* other) const { |
| 3200 int foundEnds = 0; |
| 3201 int count = this->count(); |
| 3202 for (int index = 0; index < count; ++index) { |
| 3203 const SkOpSpan& span = this->span(index); |
| 3204 if (span.fCoincident) { |
| 3205 foundEnds |= (span.fOther == other) << ((t > span.fT) + (t >= span.f
T)); |
| 3206 } |
| 3207 } |
| 3208 SkASSERT(foundEnds != 7); |
| 3209 return foundEnds == 0x3 || foundEnds == 0x5 || foundEnds == 0x6; // two bit
s set |
| 3210 } |
| 3211 |
2757 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo
l evenOdd) { | 3212 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo
l evenOdd) { |
2758 fDoneSpans = 0; | 3213 fDoneSpans = 0; |
2759 fOperand = operand; | 3214 fOperand = operand; |
2760 fXor = evenOdd; | 3215 fXor = evenOdd; |
2761 fPts = pts; | 3216 fPts = pts; |
2762 fVerb = verb; | 3217 fVerb = verb; |
2763 fLoop = fSmall = fTiny = false; | 3218 fLoop = fMultiples = fSmall = fTiny = false; |
2764 } | 3219 } |
2765 | 3220 |
2766 void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIn
cludeType) { | 3221 void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIn
cludeType) { |
2767 int local = spanSign(start, end); | 3222 int local = spanSign(start, end); |
2768 if (angleIncludeType == SkOpAngle::kBinarySingle) { | 3223 if (angleIncludeType == SkOpAngle::kBinarySingle) { |
2769 int oppLocal = oppSign(start, end); | 3224 int oppLocal = oppSign(start, end); |
2770 (void) markAndChaseWinding(start, end, local, oppLocal); | 3225 (void) markAndChaseWinding(start, end, local, oppLocal); |
2771 // OPTIMIZATION: the reverse mark and chase could skip the first marking | 3226 // OPTIMIZATION: the reverse mark and chase could skip the first marking |
2772 (void) markAndChaseWinding(end, start, local, oppLocal); | 3227 (void) markAndChaseWinding(end, start, local, oppLocal); |
2773 } else { | 3228 } else { |
(...skipping 12 matching lines...) Expand all Loading... |
2786 from has the same x direction as this span, the winding should change. If the dx
is opposite, then | 3241 from has the same x direction as this span, the winding should change. If the dx
is opposite, then |
2787 the same winding is shared by both. | 3242 the same winding is shared by both. |
2788 */ | 3243 */ |
2789 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc
alar hitDx, | 3244 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc
alar hitDx, |
2790 int oppWind, SkScalar hitOppDx) { | 3245 int oppWind, SkScalar hitOppDx) { |
2791 SkASSERT(hitDx || !winding); | 3246 SkASSERT(hitDx || !winding); |
2792 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; | 3247 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; |
2793 SkASSERT(dx); | 3248 SkASSERT(dx); |
2794 int windVal = windValue(SkMin32(start, end)); | 3249 int windVal = windValue(SkMin32(start, end)); |
2795 #if DEBUG_WINDING_AT_T | 3250 #if DEBUG_WINDING_AT_T |
2796 SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding
, | 3251 SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, d
ebugID(), winding, |
2797 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); | 3252 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); |
2798 #endif | 3253 #endif |
2799 int sideWind = winding + (dx < 0 ? windVal : -windVal); | 3254 int sideWind = winding + (dx < 0 ? windVal : -windVal); |
2800 if (abs(winding) < abs(sideWind)) { | 3255 if (abs(winding) < abs(sideWind)) { |
2801 winding = sideWind; | 3256 winding = sideWind; |
2802 } | 3257 } |
2803 #if DEBUG_WINDING_AT_T | |
2804 SkDebugf(" winding=%d\n", winding); | |
2805 #endif | |
2806 SkDEBUGCODE(int oppLocal = oppSign(start, end)); | 3258 SkDEBUGCODE(int oppLocal = oppSign(start, end)); |
2807 SkASSERT(hitOppDx || !oppWind || !oppLocal); | 3259 SkASSERT(hitOppDx || !oppWind || !oppLocal); |
2808 int oppWindVal = oppValue(SkMin32(start, end)); | 3260 int oppWindVal = oppValue(SkMin32(start, end)); |
2809 if (!oppWind) { | 3261 if (!oppWind) { |
2810 oppWind = dx < 0 ? oppWindVal : -oppWindVal; | 3262 oppWind = dx < 0 ? oppWindVal : -oppWindVal; |
2811 } else if (hitOppDx * dx >= 0) { | 3263 } else if (hitOppDx * dx >= 0) { |
2812 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); | 3264 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); |
2813 if (abs(oppWind) < abs(oppSideWind)) { | 3265 if (abs(oppWind) < abs(oppSideWind)) { |
2814 oppWind = oppSideWind; | 3266 oppWind = oppSideWind; |
2815 } | 3267 } |
2816 } | 3268 } |
| 3269 #if DEBUG_WINDING_AT_T |
| 3270 SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind); |
| 3271 #endif |
2817 (void) markAndChaseWinding(start, end, winding, oppWind); | 3272 (void) markAndChaseWinding(start, end, winding, oppWind); |
2818 // OPTIMIZATION: the reverse mark and chase could skip the first marking | 3273 // OPTIMIZATION: the reverse mark and chase could skip the first marking |
2819 (void) markAndChaseWinding(end, start, winding, oppWind); | 3274 (void) markAndChaseWinding(end, start, winding, oppWind); |
2820 } | 3275 } |
2821 | 3276 |
2822 bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPt
r) const { | 3277 bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPt
r) const { |
2823 if (!baseAngle->inLoop()) { | 3278 if (!baseAngle->inLoop()) { |
2824 return false; | 3279 return false; |
2825 } | 3280 } |
2826 int index = *indexPtr; | 3281 int index = *indexPtr; |
2827 int froIndex = fTs[index].fFromAngleIndex; | 3282 SkOpAngle* from = fTs[index].fFromAngle; |
2828 int toIndex = fTs[index].fToAngleIndex; | 3283 SkOpAngle* to = fTs[index].fToAngle; |
2829 while (++index < spanCount) { | 3284 while (++index < spanCount) { |
2830 int nextFro = fTs[index].fFromAngleIndex; | 3285 SkOpAngle* nextFrom = fTs[index].fFromAngle; |
2831 int nextTo = fTs[index].fToAngleIndex; | 3286 SkOpAngle* nextTo = fTs[index].fToAngle; |
2832 if (froIndex != nextFro || toIndex != nextTo) { | 3287 if (from != nextFrom || to != nextTo) { |
2833 break; | 3288 break; |
2834 } | 3289 } |
2835 } | 3290 } |
2836 *indexPtr = index; | 3291 *indexPtr = index; |
2837 return true; | 3292 return true; |
2838 } | 3293 } |
2839 | 3294 |
2840 // OPTIMIZE: successive calls could start were the last leaves off | 3295 // OPTIMIZE: successive calls could start were the last leaves off |
2841 // or calls could specialize to walk forwards or backwards | 3296 // or calls could specialize to walk forwards or backwards |
2842 bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const { | 3297 bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const { |
2843 int tCount = fTs.count(); | 3298 int tCount = fTs.count(); |
2844 for (int index = 0; index < tCount; ++index) { | 3299 for (int index = 0; index < tCount; ++index) { |
2845 const SkOpSpan& span = fTs[index]; | 3300 const SkOpSpan& span = fTs[index]; |
2846 if (approximately_zero(startT - span.fT) && pt == span.fPt) { | 3301 if (approximately_zero(startT - span.fT) && pt == span.fPt) { |
2847 return false; | 3302 return false; |
2848 } | 3303 } |
2849 } | 3304 } |
2850 return true; | 3305 return true; |
2851 } | 3306 } |
2852 | 3307 |
2853 bool SkOpSegment::isSimple(int end) const { | 3308 |
2854 #if 1 | 3309 SkOpSegment* SkOpSegment::isSimple(int* end, int* step) { |
2855 int count = fTs.count(); | 3310 return nextChase(end, step, NULL, NULL); |
2856 if (count == 2) { | |
2857 return true; | |
2858 } | |
2859 double t = fTs[end].fT; | |
2860 if (approximately_less_than_zero(t)) { | |
2861 return !approximately_less_than_zero(fTs[1].fT); | |
2862 } | |
2863 if (approximately_greater_than_one(t)) { | |
2864 return !approximately_greater_than_one(fTs[count - 2].fT); | |
2865 } | |
2866 return false; | |
2867 #else | |
2868 // OPTIMIZE: code could be rejiggered to use this simpler test. To make this
work, a little | |
2869 // more logic is required to ignore the dangling canceled out spans | |
2870 const SkOpSpan& span = fTs[end]; | |
2871 return span.fFromAngleIndex < 0 && span.fToAngleIndex < 0; | |
2872 #endif | |
2873 } | 3311 } |
2874 | 3312 |
2875 bool SkOpSegment::isTiny(const SkOpAngle* angle) const { | 3313 bool SkOpSegment::isTiny(const SkOpAngle* angle) const { |
2876 int start = angle->start(); | 3314 int start = angle->start(); |
2877 int end = angle->end(); | 3315 int end = angle->end(); |
2878 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; | 3316 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; |
2879 return mSpan.fTiny; | 3317 return mSpan.fTiny; |
2880 } | 3318 } |
2881 | 3319 |
2882 bool SkOpSegment::isTiny(int index) const { | 3320 bool SkOpSegment::isTiny(int index) const { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2921 } | 3359 } |
2922 | 3360 |
2923 // this span is excluded by the winding rule -- chase the ends | 3361 // this span is excluded by the winding rule -- chase the ends |
2924 // as long as they are unambiguous to mark connections as done | 3362 // as long as they are unambiguous to mark connections as done |
2925 // and give them the same winding value | 3363 // and give them the same winding value |
2926 | 3364 |
2927 SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) { | 3365 SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) { |
2928 int step = SkSign32(endIndex - index); | 3366 int step = SkSign32(endIndex - index); |
2929 int min = SkMin32(index, endIndex); | 3367 int min = SkMin32(index, endIndex); |
2930 markDoneBinary(min); | 3368 markDoneBinary(min); |
2931 SkOpSpan* last; | 3369 SkOpSpan* last = NULL; |
2932 SkOpSegment* other = this; | 3370 SkOpSegment* other = this; |
2933 while ((other = other->nextChase(&index, step, &min, &last))) { | 3371 while ((other = other->nextChase(&index, &step, &min, &last))) { |
2934 if (other->done()) { | 3372 if (other->done()) { |
2935 return NULL; | 3373 SkASSERT(!last); |
| 3374 break; |
2936 } | 3375 } |
2937 other->markDoneBinary(min); | 3376 other->markDoneBinary(min); |
2938 } | 3377 } |
2939 return last; | 3378 return last; |
2940 } | 3379 } |
2941 | 3380 |
2942 SkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) { | 3381 SkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) { |
2943 int step = SkSign32(endIndex - index); | 3382 int step = SkSign32(endIndex - index); |
2944 int min = SkMin32(index, endIndex); | 3383 int min = SkMin32(index, endIndex); |
2945 markDoneUnary(min); | 3384 markDoneUnary(min); |
2946 SkOpSpan* last; | 3385 SkOpSpan* last = NULL; |
2947 SkOpSegment* other = this; | 3386 SkOpSegment* other = this; |
2948 while ((other = other->nextChase(&index, step, &min, &last))) { | 3387 while ((other = other->nextChase(&index, &step, &min, &last))) { |
2949 if (other->done()) { | 3388 if (other->done()) { |
2950 return NULL; | 3389 SkASSERT(!last); |
| 3390 break; |
2951 } | 3391 } |
2952 other->markDoneUnary(min); | 3392 other->markDoneUnary(min); |
2953 } | 3393 } |
2954 return last; | 3394 return last; |
2955 } | 3395 } |
2956 | 3396 |
2957 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding)
{ | 3397 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding)
{ |
2958 int index = angle->start(); | 3398 int index = angle->start(); |
2959 int endIndex = angle->end(); | 3399 int endIndex = angle->end(); |
2960 int step = SkSign32(endIndex - index); | 3400 int step = SkSign32(endIndex - index); |
2961 int min = SkMin32(index, endIndex); | 3401 int min = SkMin32(index, endIndex); |
2962 markWinding(min, winding); | 3402 markWinding(min, winding); |
2963 SkOpSpan* last; | 3403 SkOpSpan* last = NULL; |
2964 SkOpSegment* other = this; | 3404 SkOpSegment* other = this; |
2965 while ((other = other->nextChase(&index, step, &min, &last))) { | 3405 while ((other = other->nextChase(&index, &step, &min, &last))) { |
2966 if (other->fTs[min].fWindSum != SK_MinS32) { | 3406 if (other->fTs[min].fWindSum != SK_MinS32) { |
2967 SkASSERT(other->fTs[min].fWindSum == winding); | 3407 SkASSERT(other->fTs[min].fWindSum == winding); |
2968 return NULL; | 3408 SkASSERT(!last); |
| 3409 break; |
2969 } | 3410 } |
2970 other->markWinding(min, winding); | 3411 other->markWinding(min, winding); |
2971 } | 3412 } |
2972 return last; | 3413 return last; |
2973 } | 3414 } |
2974 | 3415 |
2975 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding)
{ | 3416 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding)
{ |
2976 int min = SkMin32(index, endIndex); | 3417 int min = SkMin32(index, endIndex); |
2977 int step = SkSign32(endIndex - index); | 3418 int step = SkSign32(endIndex - index); |
2978 markWinding(min, winding); | 3419 markWinding(min, winding); |
2979 SkOpSpan* last; | 3420 SkOpSpan* last = NULL; |
2980 SkOpSegment* other = this; | 3421 SkOpSegment* other = this; |
2981 while ((other = other->nextChase(&index, step, &min, &last))) { | 3422 while ((other = other->nextChase(&index, &step, &min, &last))) { |
2982 if (other->fTs[min].fWindSum != SK_MinS32) { | 3423 if (other->fTs[min].fWindSum != SK_MinS32) { |
2983 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo
p); | 3424 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo
p); |
2984 return NULL; | 3425 SkASSERT(!last); |
| 3426 break; |
2985 } | 3427 } |
2986 other->markWinding(min, winding); | 3428 other->markWinding(min, winding); |
2987 } | 3429 } |
2988 return last; | 3430 return last; |
2989 } | 3431 } |
2990 | 3432 |
2991 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding,
int oppWinding) { | 3433 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding,
int oppWinding) { |
2992 int min = SkMin32(index, endIndex); | 3434 int min = SkMin32(index, endIndex); |
2993 int step = SkSign32(endIndex - index); | 3435 int step = SkSign32(endIndex - index); |
2994 markWinding(min, winding, oppWinding); | 3436 markWinding(min, winding, oppWinding); |
2995 SkOpSpan* last; | 3437 SkOpSpan* last = NULL; |
2996 SkOpSegment* other = this; | 3438 SkOpSegment* other = this; |
2997 while ((other = other->nextChase(&index, step, &min, &last))) { | 3439 while ((other = other->nextChase(&index, &step, &min, &last))) { |
2998 if (other->fTs[min].fWindSum != SK_MinS32) { | 3440 if (other->fTs[min].fWindSum != SK_MinS32) { |
2999 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo
p); | 3441 #if SK_DEBUG |
3000 return NULL; | 3442 if (!other->fTs[min].fLoop) { |
| 3443 if (fOperand == other->fOperand) { |
| 3444 // FIXME: this is probably a bug -- rects4 asserts here |
| 3445 // SkASSERT(other->fTs[min].fWindSum == winding); |
| 3446 // FIXME: this is probably a bug -- rects3 asserts here |
| 3447 // SkASSERT(other->fTs[min].fOppSum == oppWinding); |
| 3448 } else { |
| 3449 SkASSERT(other->fTs[min].fWindSum == oppWinding); |
| 3450 // FIXME: this is probably a bug -- skpwww_joomla_org_23 asserts here |
| 3451 // SkASSERT(other->fTs[min].fOppSum == winding); |
| 3452 } |
| 3453 } |
| 3454 SkASSERT(!last); |
| 3455 #endif |
| 3456 break; |
3001 } | 3457 } |
3002 other->markWinding(min, winding, oppWinding); | 3458 if (fOperand == other->fOperand) { |
| 3459 other->markWinding(min, winding, oppWinding); |
| 3460 } else { |
| 3461 other->markWinding(min, oppWinding, winding); |
| 3462 } |
3003 } | 3463 } |
3004 return last; | 3464 return last; |
3005 } | 3465 } |
3006 | 3466 |
3007 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding,
int oppWinding) { | 3467 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding,
int oppWinding) { |
3008 int start = angle->start(); | 3468 int start = angle->start(); |
3009 int end = angle->end(); | 3469 int end = angle->end(); |
3010 return markAndChaseWinding(start, end, winding, oppWinding); | 3470 return markAndChaseWinding(start, end, winding, oppWinding); |
3011 } | 3471 } |
3012 | 3472 |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3309 SkOpSpan& newSpan = fTs[tIndex]; | 3769 SkOpSpan& newSpan = fTs[tIndex]; |
3310 newSpan.fWindValue = nextDoorWind; | 3770 newSpan.fWindValue = nextDoorWind; |
3311 newSpan.fOppValue = nextOppWind; | 3771 newSpan.fOppValue = nextOppWind; |
3312 if (!nextDoorWind && !nextOppWind && !newSpan.fDone) { | 3772 if (!nextDoorWind && !nextOppWind && !newSpan.fDone) { |
3313 newSpan.fDone = true; | 3773 newSpan.fDone = true; |
3314 ++fDoneSpans; | 3774 ++fDoneSpans; |
3315 } | 3775 } |
3316 } | 3776 } |
3317 } | 3777 } |
3318 | 3778 |
3319 // return span if when chasing, two or more radiating spans are not done | |
3320 // OPTIMIZATION: ? multiple spans is detected when there is only one valid | |
3321 // candidate and the remaining spans have windValue == 0 (canceled by | |
3322 // coincidence). The coincident edges could either be removed altogether, | |
3323 // or this code could be more complicated in detecting this case. Worth it? | |
3324 bool SkOpSegment::multipleSpans(int end) const { | |
3325 return end > 0 && end < fTs.count() - 1; | |
3326 } | |
3327 | |
3328 bool SkOpSegment::nextCandidate(int* start, int* end) const { | 3779 bool SkOpSegment::nextCandidate(int* start, int* end) const { |
3329 while (fTs[*end].fDone) { | 3780 while (fTs[*end].fDone) { |
3330 if (fTs[*end].fT == 1) { | 3781 if (fTs[*end].fT == 1) { |
3331 return false; | 3782 return false; |
3332 } | 3783 } |
3333 ++(*end); | 3784 ++(*end); |
3334 } | 3785 } |
3335 *start = *end; | 3786 *start = *end; |
3336 *end = nextExactSpan(*start, 1); | 3787 *end = nextExactSpan(*start, 1); |
3337 return true; | 3788 return true; |
3338 } | 3789 } |
3339 | 3790 |
3340 SkOpSegment* SkOpSegment::nextChase(int* index, const int step, int* min, SkOpSp
an** last) { | 3791 static SkOpSegment* set_last(SkOpSpan** last, SkOpSpan* endSpan) { |
3341 int end = nextExactSpan(*index, step); | 3792 if (last && !endSpan->fSmall) { |
| 3793 *last = endSpan; |
| 3794 } |
| 3795 return NULL; |
| 3796 } |
| 3797 |
| 3798 SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, Sk
OpSpan** last) { |
| 3799 int origIndex = *indexPtr; |
| 3800 int step = *stepPtr; |
| 3801 int end = nextExactSpan(origIndex, step); |
3342 SkASSERT(end >= 0); | 3802 SkASSERT(end >= 0); |
3343 if (fTs[end].fSmall) { | 3803 SkOpSpan& endSpan = fTs[end]; |
3344 *last = NULL; | 3804 SkOpAngle* angle = step > 0 ? endSpan.fFromAngle : endSpan.fToAngle; |
3345 return NULL; | 3805 int foundIndex; |
| 3806 int otherEnd; |
| 3807 SkOpSegment* other; |
| 3808 if (angle == NULL) { |
| 3809 if (endSpan.fT != 0 && endSpan.fT != 1) { |
| 3810 return NULL; |
| 3811 } |
| 3812 other = endSpan.fOther; |
| 3813 foundIndex = endSpan.fOtherIndex; |
| 3814 otherEnd = other->nextExactSpan(foundIndex, step); |
| 3815 } else { |
| 3816 int loopCount = angle->loopCount(); |
| 3817 if (loopCount > 2) { |
| 3818 return set_last(last, &endSpan); |
| 3819 } |
| 3820 const SkOpAngle* next = angle->next(); |
| 3821 if (angle->sign() != next->sign()) { |
| 3822 #if DEBUG_WINDING |
| 3823 SkDebugf("%s mismatched signs\n", __FUNCTION__); |
| 3824 #endif |
| 3825 // return set_last(last, &endSpan); |
| 3826 } |
| 3827 other = next->segment(); |
| 3828 foundIndex = end = next->start(); |
| 3829 otherEnd = next->end(); |
3346 } | 3830 } |
3347 if (multipleSpans(end)) { | 3831 int foundStep = foundIndex < otherEnd ? 1 : -1; |
3348 *last = &fTs[end]; | 3832 if (*stepPtr != foundStep) { |
3349 return NULL; | 3833 return set_last(last, &endSpan); |
3350 } | 3834 } |
3351 const SkOpSpan& endSpan = fTs[end]; | 3835 SkASSERT(*indexPtr >= 0); |
3352 SkOpSegment* other = endSpan.fOther; | |
3353 *index = endSpan.fOtherIndex; | |
3354 SkASSERT(*index >= 0); | |
3355 int otherEnd = other->nextExactSpan(*index, step); | |
3356 SkASSERT(otherEnd >= 0); | 3836 SkASSERT(otherEnd >= 0); |
3357 *min = SkMin32(*index, otherEnd); | 3837 #if 1 |
3358 if (other->fTs[*min].fSmall) { | 3838 int origMin = origIndex + (step < 0 ? step : 0); |
3359 *last = NULL; | 3839 const SkOpSpan& orig = this->span(origMin); |
3360 return NULL; | 3840 #endif |
| 3841 int foundMin = SkMin32(foundIndex, otherEnd); |
| 3842 #if 1 |
| 3843 const SkOpSpan& found = other->span(foundMin); |
| 3844 if (found.fWindValue != orig.fWindValue || found.fOppValue != orig.fOppValue
) { |
| 3845 return set_last(last, &endSpan); |
| 3846 } |
| 3847 #endif |
| 3848 *indexPtr = foundIndex; |
| 3849 *stepPtr = foundStep; |
| 3850 if (minPtr) { |
| 3851 *minPtr = foundMin; |
3361 } | 3852 } |
3362 return other; | 3853 return other; |
3363 } | 3854 } |
3364 | 3855 |
3365 // This has callers for two different situations: one establishes the end | 3856 // This has callers for two different situations: one establishes the end |
3366 // of the current span, and one establishes the beginning of the next span | 3857 // of the current span, and one establishes the beginning of the next span |
3367 // (thus the name). When this is looking for the end of the current span, | 3858 // (thus the name). When this is looking for the end of the current span, |
3368 // coincidence is found when the beginning Ts contain -step and the end | 3859 // coincidence is found when the beginning Ts contain -step and the end |
3369 // contains step. When it is looking for the beginning of the next, the | 3860 // contains step. When it is looking for the beginning of the next, the |
3370 // first Ts found can be ignored and the last Ts should contain -step. | 3861 // first Ts found can be ignored and the last Ts should contain -step. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3407 const SkOpSpan& span = fTs[to]; | 3898 const SkOpSpan& span = fTs[to]; |
3408 if (precisely_negative(span.fT - fromSpan.fT)) { | 3899 if (precisely_negative(span.fT - fromSpan.fT)) { |
3409 continue; | 3900 continue; |
3410 } | 3901 } |
3411 return to; | 3902 return to; |
3412 } | 3903 } |
3413 } | 3904 } |
3414 return -1; | 3905 return -1; |
3415 } | 3906 } |
3416 | 3907 |
| 3908 void SkOpSegment::pinT(const SkPoint& pt, double* t) { |
| 3909 if (pt == fPts[0]) { |
| 3910 *t = 0; |
| 3911 } |
| 3912 int count = SkPathOpsVerbToPoints(fVerb); |
| 3913 if (pt == fPts[count]) { |
| 3914 *t = 1; |
| 3915 } |
| 3916 } |
| 3917 |
| 3918 void SkOpSegment::setCoincidentRange(const SkPoint& startPt, const SkPoint& endP
t, |
| 3919 SkOpSegment* other) { |
| 3920 int count = this->count(); |
| 3921 for (int index = 0; index < count; ++index) { |
| 3922 SkOpSpan &span = fTs[index]; |
| 3923 if ((startPt == span.fPt || endPt == span.fPt) && other == span.fOther)
{ |
| 3924 span.fCoincident = true; |
| 3925 } |
| 3926 } |
| 3927 } |
| 3928 |
3417 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int*
sumSuWinding, | 3929 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int*
sumSuWinding, |
3418 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding
) { | 3930 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding
) { |
3419 int deltaSum = spanSign(index, endIndex); | 3931 int deltaSum = spanSign(index, endIndex); |
3420 int oppDeltaSum = oppSign(index, endIndex); | 3932 int oppDeltaSum = oppSign(index, endIndex); |
3421 if (operand()) { | 3933 if (operand()) { |
3422 *maxWinding = *sumSuWinding; | 3934 *maxWinding = *sumSuWinding; |
3423 *sumWinding = *sumSuWinding -= deltaSum; | 3935 *sumWinding = *sumSuWinding -= deltaSum; |
3424 *oppMaxWinding = *sumMiWinding; | 3936 *oppMaxWinding = *sumMiWinding; |
3425 *oppSumWinding = *sumMiWinding -= oppDeltaSum; | 3937 *oppSumWinding = *sumMiWinding -= oppDeltaSum; |
3426 } else { | 3938 } else { |
(...skipping 18 matching lines...) Expand all Loading... |
3445 #endif | 3957 #endif |
3446 } | 3958 } |
3447 | 3959 |
3448 void SkOpSegment::sortAngles() { | 3960 void SkOpSegment::sortAngles() { |
3449 int spanCount = fTs.count(); | 3961 int spanCount = fTs.count(); |
3450 if (spanCount <= 2) { | 3962 if (spanCount <= 2) { |
3451 return; | 3963 return; |
3452 } | 3964 } |
3453 int index = 0; | 3965 int index = 0; |
3454 do { | 3966 do { |
3455 int fromIndex = fTs[index].fFromAngleIndex; | 3967 SkOpAngle* fromAngle = fTs[index].fFromAngle; |
3456 int toIndex = fTs[index].fToAngleIndex; | 3968 SkOpAngle* toAngle = fTs[index].fToAngle; |
3457 if (fromIndex < 0 && toIndex < 0) { | 3969 if (!fromAngle && !toAngle) { |
3458 index += 1; | 3970 index += 1; |
3459 continue; | 3971 continue; |
3460 } | 3972 } |
3461 SkOpAngle* baseAngle = NULL; | 3973 SkOpAngle* baseAngle = NULL; |
3462 if (fromIndex >= 0) { | 3974 if (fromAngle) { |
3463 baseAngle = &this->angle(fromIndex); | 3975 baseAngle = fromAngle; |
3464 if (inLoop(baseAngle, spanCount, &index)) { | 3976 if (inLoop(baseAngle, spanCount, &index)) { |
3465 continue; | 3977 continue; |
3466 } | 3978 } |
3467 } | 3979 } |
3468 #if DEBUG_ANGLE | 3980 #if DEBUG_ANGLE |
3469 bool wroteAfterHeader = false; | 3981 bool wroteAfterHeader = false; |
3470 #endif | 3982 #endif |
3471 if (toIndex >= 0) { | 3983 if (toAngle) { |
3472 SkOpAngle* toAngle = &this->angle(toIndex); | |
3473 if (!baseAngle) { | 3984 if (!baseAngle) { |
3474 baseAngle = toAngle; | 3985 baseAngle = toAngle; |
3475 if (inLoop(baseAngle, spanCount, &index)) { | 3986 if (inLoop(baseAngle, spanCount, &index)) { |
3476 continue; | 3987 continue; |
3477 } | 3988 } |
3478 } else { | 3989 } else { |
3479 SkDEBUGCODE(int newIndex = index); | 3990 SkDEBUGCODE(int newIndex = index); |
3480 SkASSERT(!inLoop(baseAngle, spanCount, &newIndex) && newIndex ==
index); | 3991 SkASSERT(!inLoop(baseAngle, spanCount, &newIndex) && newIndex ==
index); |
3481 #if DEBUG_ANGLE | 3992 #if DEBUG_ANGLE |
3482 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
fTs[index].fT, | 3993 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
fTs[index].fT, |
3483 index); | 3994 index); |
3484 wroteAfterHeader = true; | 3995 wroteAfterHeader = true; |
3485 #endif | 3996 #endif |
3486 baseAngle->insert(toAngle); | 3997 baseAngle->insert(toAngle); |
3487 } | 3998 } |
3488 } | 3999 } |
3489 int nextFrom, nextTo; | 4000 SkOpAngle* nextFrom, * nextTo; |
3490 int firstIndex = index; | 4001 int firstIndex = index; |
3491 do { | 4002 do { |
3492 SkOpSpan& span = fTs[index]; | 4003 SkOpSpan& span = fTs[index]; |
3493 SkOpSegment* other = span.fOther; | 4004 SkOpSegment* other = span.fOther; |
3494 SkOpSpan& oSpan = other->fTs[span.fOtherIndex]; | 4005 SkOpSpan& oSpan = other->fTs[span.fOtherIndex]; |
3495 int otherAngleIndex = oSpan.fFromAngleIndex; | 4006 SkOpAngle* oAngle = oSpan.fFromAngle; |
3496 if (otherAngleIndex >= 0) { | 4007 if (oAngle) { |
3497 #if DEBUG_ANGLE | 4008 #if DEBUG_ANGLE |
3498 if (!wroteAfterHeader) { | 4009 if (!wroteAfterHeader) { |
3499 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI
D(), fTs[index].fT, | 4010 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI
D(), fTs[index].fT, |
3500 index); | 4011 index); |
3501 wroteAfterHeader = true; | 4012 wroteAfterHeader = true; |
3502 } | 4013 } |
3503 #endif | 4014 #endif |
3504 SkOpAngle* oAngle = &other->angle(otherAngleIndex); | |
3505 if (!oAngle->loopContains(*baseAngle)) { | 4015 if (!oAngle->loopContains(*baseAngle)) { |
3506 baseAngle->insert(oAngle); | 4016 baseAngle->insert(oAngle); |
3507 } | 4017 } |
3508 } | 4018 } |
3509 otherAngleIndex = oSpan.fToAngleIndex; | 4019 oAngle = oSpan.fToAngle; |
3510 if (otherAngleIndex >= 0) { | 4020 if (oAngle) { |
3511 #if DEBUG_ANGLE | 4021 #if DEBUG_ANGLE |
3512 if (!wroteAfterHeader) { | 4022 if (!wroteAfterHeader) { |
3513 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI
D(), fTs[index].fT, | 4023 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI
D(), fTs[index].fT, |
3514 index); | 4024 index); |
3515 wroteAfterHeader = true; | 4025 wroteAfterHeader = true; |
3516 } | 4026 } |
3517 #endif | 4027 #endif |
3518 SkOpAngle* oAngle = &other->angle(otherAngleIndex); | |
3519 if (!oAngle->loopContains(*baseAngle)) { | 4028 if (!oAngle->loopContains(*baseAngle)) { |
3520 baseAngle->insert(oAngle); | 4029 baseAngle->insert(oAngle); |
3521 } | 4030 } |
3522 } | 4031 } |
3523 if (++index == spanCount) { | 4032 if (++index == spanCount) { |
3524 break; | 4033 break; |
3525 } | 4034 } |
3526 nextFrom = fTs[index].fFromAngleIndex; | 4035 nextFrom = fTs[index].fFromAngle; |
3527 nextTo = fTs[index].fToAngleIndex; | 4036 nextTo = fTs[index].fToAngle; |
3528 } while (fromIndex == nextFrom && toIndex == nextTo); | 4037 } while (fromAngle == nextFrom && toAngle == nextTo); |
3529 if (baseAngle && baseAngle->loopCount() == 1) { | 4038 if (baseAngle && baseAngle->loopCount() == 1) { |
3530 index = firstIndex; | 4039 index = firstIndex; |
3531 do { | 4040 do { |
3532 SkOpSpan& span = fTs[index]; | 4041 SkOpSpan& span = fTs[index]; |
3533 span.fFromAngleIndex = span.fToAngleIndex = -1; | 4042 span.fFromAngle = span.fToAngle = NULL; |
3534 if (++index == spanCount) { | 4043 if (++index == spanCount) { |
3535 break; | 4044 break; |
3536 } | 4045 } |
3537 nextFrom = fTs[index].fFromAngleIndex; | 4046 nextFrom = fTs[index].fFromAngle; |
3538 nextTo = fTs[index].fToAngleIndex; | 4047 nextTo = fTs[index].fToAngle; |
3539 } while (fromIndex == nextFrom && toIndex == nextTo); | 4048 } while (fromAngle == nextFrom && toAngle == nextTo); |
3540 baseAngle = NULL; | 4049 baseAngle = NULL; |
3541 } | 4050 } |
3542 #if DEBUG_SORT | 4051 #if DEBUG_SORT |
3543 SkASSERT(!baseAngle || baseAngle->loopCount() > 1); | 4052 SkASSERT(!baseAngle || baseAngle->loopCount() > 1); |
3544 #endif | 4053 #endif |
3545 } while (index < spanCount); | 4054 } while (index < spanCount); |
3546 } | 4055 } |
3547 | 4056 |
3548 // return true if midpoints were computed | 4057 // return true if midpoints were computed |
3549 bool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { | 4058 bool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3742 } | 4251 } |
3743 | 4252 |
3744 int SkOpSegment::windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx
) const { | 4253 int SkOpSegment::windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx
) const { |
3745 if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span,
disregard | 4254 if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span,
disregard |
3746 return SK_MinS32; | 4255 return SK_MinS32; |
3747 } | 4256 } |
3748 int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex); | 4257 int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex); |
3749 SkASSERT(winding != SK_MinS32); | 4258 SkASSERT(winding != SK_MinS32); |
3750 int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex); | 4259 int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex); |
3751 #if DEBUG_WINDING_AT_T | 4260 #if DEBUG_WINDING_AT_T |
3752 SkDebugf("%s oldWinding=%d windValue=%d", __FUNCTION__, winding, windVal); | 4261 SkDebugf("%s id=%d opp=%d tHit=%1.9g t=%1.9g oldWinding=%d windValue=%d", __
FUNCTION__, |
| 4262 debugID(), crossOpp, tHit, t(tIndex), winding, windVal); |
3753 #endif | 4263 #endif |
3754 // see if a + change in T results in a +/- change in X (compute x'(T)) | 4264 // see if a + change in T results in a +/- change in X (compute x'(T)) |
3755 *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; | 4265 *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; |
3756 if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { | 4266 if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { |
3757 *dx = fPts[2].fX - fPts[1].fX - *dx; | 4267 *dx = fPts[2].fX - fPts[1].fX - *dx; |
3758 } | 4268 } |
3759 if (*dx == 0) { | 4269 if (*dx == 0) { |
3760 #if DEBUG_WINDING_AT_T | 4270 #if DEBUG_WINDING_AT_T |
3761 SkDebugf(" dx=0 winding=SK_MinS32\n"); | 4271 SkDebugf(" dx=0 winding=SK_MinS32\n"); |
3762 #endif | 4272 #endif |
(...skipping 22 matching lines...) Expand all Loading... |
3785 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); | 4295 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); |
3786 span->fWindValue = 0; | 4296 span->fWindValue = 0; |
3787 span->fOppValue = 0; | 4297 span->fOppValue = 0; |
3788 if (span->fTiny || span->fSmall) { | 4298 if (span->fTiny || span->fSmall) { |
3789 return; | 4299 return; |
3790 } | 4300 } |
3791 SkASSERT(!span->fDone); | 4301 SkASSERT(!span->fDone); |
3792 span->fDone = true; | 4302 span->fDone = true; |
3793 ++fDoneSpans; | 4303 ++fDoneSpans; |
3794 } | 4304 } |
OLD | NEW |