Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(468)

Side by Side Diff: src/pathops/SkOpSegment.cpp

Issue 23542056: path ops work in progress (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: verbose + mutex around file number access Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkOpSegment.h" 8 #include "SkOpSegment.h"
9 #include "SkPathWriter.h" 9 #include "SkPathWriter.h"
10 #include "SkTSort.h" 10 #include "SkTSort.h"
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT, bool i sNear) { 410 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT, bool i sNear) {
411 if (precisely_zero(newT)) { 411 if (precisely_zero(newT)) {
412 newT = 0; 412 newT = 0;
413 } else if (precisely_equal(newT, 1)) { 413 } else if (precisely_equal(newT, 1)) {
414 newT = 1; 414 newT = 1;
415 } 415 }
416 // FIXME: in the pathological case where there is a ton of intercepts, 416 // FIXME: in the pathological case where there is a ton of intercepts,
417 // binary search? 417 // binary search?
418 int insertedAt = -1; 418 int insertedAt = -1;
419 size_t tCount = fTs.count(); 419 size_t tCount = fTs.count();
420 const SkPoint& firstPt = fPts[0];
421 const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)];
420 for (size_t index = 0; index < tCount; ++index) { 422 for (size_t index = 0; index < tCount; ++index) {
421 // OPTIMIZATION: if there are three or more identical Ts, then 423 // OPTIMIZATION: if there are three or more identical Ts, then
422 // the fourth and following could be further insertion-sorted so 424 // the fourth and following could be further insertion-sorted so
423 // that all the edges are clockwise or counterclockwise. 425 // that all the edges are clockwise or counterclockwise.
424 // This could later limit segment tests to the two adjacent 426 // This could later limit segment tests to the two adjacent
425 // neighbors, although it doesn't help with determining which 427 // neighbors, although it doesn't help with determining which
426 // circular direction to go in. 428 // circular direction to go in.
427 if (newT < fTs[index].fT) { 429 const SkOpSpan& span = fTs[index];
430 if (newT < span.fT) {
428 insertedAt = index; 431 insertedAt = index;
429 break; 432 break;
430 } 433 }
434 if (newT == span.fT) {
435 if (pt == span.fPt) {
436 insertedAt = index;
437 break;
438 }
439 if ((pt == firstPt && newT == 0) || (span.fPt == lastPt && newT == 1 )) {
440 insertedAt = index;
441 break;
442 }
443 }
431 } 444 }
432 SkOpSpan* span; 445 SkOpSpan* span;
433 if (insertedAt >= 0) { 446 if (insertedAt >= 0) {
434 span = fTs.insert(insertedAt); 447 span = fTs.insert(insertedAt);
435 } else { 448 } else {
436 insertedAt = tCount; 449 insertedAt = tCount;
437 span = fTs.append(); 450 span = fTs.append();
438 } 451 }
439 span->fT = newT; 452 span->fT = newT;
440 span->fOther = other; 453 span->fOther = other;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 ++fDoneSpans; 508 ++fDoneSpans;
496 --less; 509 --less;
497 } 510 }
498 int more = 1; 511 int more = 1;
499 while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, sp an->fPt)) { 512 while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, sp an->fPt)) {
500 if (span[more - 1].fDone) { 513 if (span[more - 1].fDone) {
501 break; 514 break;
502 } 515 }
503 double tEndInterval = span[more].fT - newT; 516 double tEndInterval = span[more].fT - newT;
504 if (precisely_negative(tEndInterval)) { 517 if (precisely_negative(tEndInterval)) {
518 if ((span->fTiny = span[more].fTiny)) {
519 span->fDone = true;
520 ++fDoneSpans;
521 }
505 break; 522 break;
506 } 523 }
507 if (fVerb == SkPath::kCubic_Verb) { 524 if (fVerb == SkPath::kCubic_Verb) {
508 double tMid = newT - tEndInterval / 2; 525 double tMid = newT - tEndInterval / 2;
509 SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid); 526 SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid);
510 if (!midEndPt.approximatelyEqual(xyAtT(span))) { 527 if (!midEndPt.approximatelyEqual(xyAtT(span))) {
511 break; 528 break;
512 } 529 }
513 } 530 }
514 span[more - 1].fSmall = true; 531 span[more - 1].fSmall = true;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 ^ ^ <--| <--| 566 ^ ^ <--| <--|
550 startPt endPt test/oTest first pos test/oTest final po s 567 startPt endPt test/oTest first pos test/oTest final po s
551 */ 568 */
552 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS egment* other) { 569 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS egment* other) {
553 bool binary = fOperand != other->fOperand; 570 bool binary = fOperand != other->fOperand;
554 int index = 0; 571 int index = 0;
555 while (startPt != fTs[index].fPt) { 572 while (startPt != fTs[index].fPt) {
556 SkASSERT(index < fTs.count()); 573 SkASSERT(index < fTs.count());
557 ++index; 574 ++index;
558 } 575 }
576 while (index > 0 && fTs[index].fT == fTs[index - 1].fT) {
577 --index;
578 }
559 int oIndex = other->fTs.count(); 579 int oIndex = other->fTs.count();
560 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match 580 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match
561 SkASSERT(oIndex > 0); 581 SkASSERT(oIndex > 0);
562 } 582 }
563 while (startPt == other->fTs[--oIndex].fPt) { // look for first point beyon d match 583 double oStartT = other->fTs[oIndex].fT;
584 // look for first point beyond match
585 while (startPt == other->fTs[--oIndex].fPt || oStartT == other->fTs[oIndex]. fT) {
564 SkASSERT(oIndex > 0); 586 SkASSERT(oIndex > 0);
565 } 587 }
566 SkOpSpan* test = &fTs[index]; 588 SkOpSpan* test = &fTs[index];
567 SkOpSpan* oTest = &other->fTs[oIndex]; 589 SkOpSpan* oTest = &other->fTs[oIndex];
568 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; 590 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts;
569 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 591 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts;
570 do { 592 do {
571 SkASSERT(test->fT < 1); 593 SkASSERT(test->fT < 1);
572 SkASSERT(oTest->fT < 1); 594 SkASSERT(oTest->fT < 1);
573 bool decrement = test->fWindValue && oTest->fWindValue; 595 bool decrement = test->fWindValue && oTest->fWindValue;
574 bool track = test->fWindValue || oTest->fWindValue; 596 bool track = test->fWindValue || oTest->fWindValue;
575 bool bigger = test->fWindValue >= oTest->fWindValue; 597 bool bigger = test->fWindValue >= oTest->fWindValue;
576 const SkPoint& testPt = test->fPt; 598 const SkPoint& testPt = test->fPt;
599 double testT = test->fT;
577 const SkPoint& oTestPt = oTest->fPt; 600 const SkPoint& oTestPt = oTest->fPt;
601 double oTestT = oTest->fT;
578 do { 602 do {
579 if (decrement) { 603 if (decrement) {
580 if (binary && bigger) { 604 if (binary && bigger) {
581 test->fOppValue--; 605 test->fOppValue--;
582 } else { 606 } else {
583 decrementSpan(test); 607 decrementSpan(test);
584 } 608 }
585 } else if (track) { 609 } else if (track) {
586 TrackOutsidePair(&outsidePts, testPt, oTestPt); 610 TrackOutsidePair(&outsidePts, testPt, oTestPt);
587 } 611 }
588 SkASSERT(index < fTs.count() - 1); 612 SkASSERT(index < fTs.count() - 1);
589 test = &fTs[++index]; 613 test = &fTs[++index];
590 } while (testPt == test->fPt); 614 } while (testPt == test->fPt || testT == test->fT);
591 SkDEBUGCODE(int originalWindValue = oTest->fWindValue); 615 SkDEBUGCODE(int originalWindValue = oTest->fWindValue);
592 do { 616 do {
593 SkASSERT(oTest->fT < 1); 617 SkASSERT(oTest->fT < 1);
594 SkASSERT(originalWindValue == oTest->fWindValue); 618 SkASSERT(originalWindValue == oTest->fWindValue);
595 if (decrement) { 619 if (decrement) {
596 if (binary && !bigger) { 620 if (binary && !bigger) {
597 oTest->fOppValue--; 621 oTest->fOppValue--;
598 } else { 622 } else {
599 other->decrementSpan(oTest); 623 other->decrementSpan(oTest);
600 } 624 }
601 } else if (track) { 625 } else if (track) {
602 TrackOutsidePair(&oOutsidePts, oTestPt, testPt); 626 TrackOutsidePair(&oOutsidePts, oTestPt, testPt);
603 } 627 }
604 if (!oIndex) { 628 if (!oIndex) {
605 break; 629 break;
606 } 630 }
607 oTest = &other->fTs[--oIndex]; 631 oTest = &other->fTs[--oIndex];
608 } while (oTestPt == oTest->fPt); 632 } while (oTestPt == oTest->fPt || oTestT == oTest->fT);
609 SkASSERT(endPt != test->fPt || oTestPt == endPt); 633 } while (endPt != test->fPt && test->fT < 1);
610 } while (endPt != test->fPt);
611 // FIXME: determine if canceled edges need outside ts added 634 // FIXME: determine if canceled edges need outside ts added
612 int outCount = outsidePts.count(); 635 int outCount = outsidePts.count();
613 if (!done() && outCount) { 636 if (!done() && outCount) {
614 addCancelOutsides(outsidePts[0], outsidePts[1], other); 637 addCancelOutsides(outsidePts[0], outsidePts[1], other);
615 if (outCount > 2) { 638 if (outCount > 2) {
616 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other); 639 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other);
617 } 640 }
618 } 641 }
619 if (!other->done() && oOutsidePts.count()) { 642 if (!other->done() && oOutsidePts.count()) {
620 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this); 643 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this);
(...skipping 17 matching lines...) Expand all
638 SkTSwap<int>(oWindValue, oOppValue); 661 SkTSwap<int>(oWindValue, oOppValue);
639 } 662 }
640 SkOpSpan* const test = &fTs[index]; 663 SkOpSpan* const test = &fTs[index];
641 SkOpSpan* end = test; 664 SkOpSpan* end = test;
642 const SkPoint& oStartPt = oTest.fPt; 665 const SkPoint& oStartPt = oTest.fPt;
643 do { 666 do {
644 if (bumpSpan(end, oWindValue, oOppValue)) { 667 if (bumpSpan(end, oWindValue, oOppValue)) {
645 TrackOutside(outsideTs, oStartPt); 668 TrackOutside(outsideTs, oStartPt);
646 } 669 }
647 end = &fTs[++index]; 670 end = &fTs[++index];
648 } while (end->fPt == test->fPt); 671 } while ((end->fPt == test->fPt || end->fT == test->fT) && end->fT < 1);
649 *indexPtr = index; 672 *indexPtr = index;
650 } 673 }
651 674
652 bool SkOpSegment::bumpCoincident(SkOpSpan* test, bool bigger, bool binary) { 675 bool SkOpSegment::bumpCoincident(SkOpSpan* test, bool bigger, bool binary) {
653 if (bigger) { 676 if (bigger) {
654 if (binary) { 677 if (binary) {
655 if (fOppXor) { 678 if (fOppXor) {
656 test->fOppValue ^= 1; 679 test->fOppValue ^= 1;
657 } else { 680 } else {
658 test->fOppValue++; 681 test->fOppValue++;
(...skipping 19 matching lines...) Expand all
678 // may not have the same intermediate points. Compute the corresponding 701 // may not have the same intermediate points. Compute the corresponding
679 // intermediate T values (using this as the master, other as the follower) 702 // intermediate T values (using this as the master, other as the follower)
680 // and walk other conditionally -- hoping that it catches up in the end 703 // and walk other conditionally -- hoping that it catches up in the end
681 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, 704 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr,
682 SkTArray<SkPoint, true>* oOutsidePts) { 705 SkTArray<SkPoint, true>* oOutsidePts) {
683 int oIndex = *oIndexPtr; 706 int oIndex = *oIndexPtr;
684 SkOpSpan* const oTest = &fTs[oIndex]; 707 SkOpSpan* const oTest = &fTs[oIndex];
685 SkOpSpan* oEnd = oTest; 708 SkOpSpan* oEnd = oTest;
686 const SkPoint& startPt = test.fPt; 709 const SkPoint& startPt = test.fPt;
687 const SkPoint& oStartPt = oTest->fPt; 710 const SkPoint& oStartPt = oTest->fPt;
688 if (oStartPt == oEnd->fPt) { 711 double oStartT = oTest->fT;
712 if (oStartPt == oEnd->fPt || oStartT == oEnd->fT) {
689 TrackOutside(oOutsidePts, startPt); 713 TrackOutside(oOutsidePts, startPt);
690 } 714 }
691 while (oStartPt == oEnd->fPt) { 715 while (oStartPt == oEnd->fPt || oStartT == oEnd->fT) {
692 zeroSpan(oEnd); 716 zeroSpan(oEnd);
693 oEnd = &fTs[++oIndex]; 717 oEnd = &fTs[++oIndex];
694 } 718 }
695 *oIndexPtr = oIndex; 719 *oIndexPtr = oIndex;
696 } 720 }
697 721
698 // FIXME: need to test this case: 722 // FIXME: need to test this case:
699 // contourA has two segments that are coincident 723 // contourA has two segments that are coincident
700 // contourB has two segments that are coincident in the same place 724 // contourB has two segments that are coincident in the same place
701 // each ends up with +2/0 pairs for winding count 725 // each ends up with +2/0 pairs for winding count
702 // since logic below doesn't transfer count (only increments/decrements) can thi s be 726 // since logic below doesn't transfer count (only increments/decrements) can thi s be
703 // resolved to +4/0 ? 727 // resolved to +4/0 ?
704 728
705 // set spans from start to end to increment the greater by one and decrement 729 // set spans from start to end to increment the greater by one and decrement
706 // the lesser 730 // the lesser
707 void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, 731 void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d ouble endT,
708 SkOpSegment* other) { 732 SkOpSegment* other) {
709 bool binary = fOperand != other->fOperand; 733 bool binary = fOperand != other->fOperand;
710 int index = 0; 734 int index = 0;
711 while (startPt != fTs[index].fPt) { 735 while (startPt != fTs[index].fPt) {
712 SkASSERT(index < fTs.count()); 736 SkASSERT(index < fTs.count());
713 ++index; 737 ++index;
714 } 738 }
739 double startT = fTs[index].fT;
740 while (index > 0 && fTs[index - 1].fT == startT) {
741 --index;
742 }
715 int oIndex = 0; 743 int oIndex = 0;
716 while (startPt != other->fTs[oIndex].fPt) { 744 while (startPt != other->fTs[oIndex].fPt) {
717 SkASSERT(oIndex < other->fTs.count()); 745 SkASSERT(oIndex < other->fTs.count());
718 ++oIndex; 746 ++oIndex;
719 } 747 }
748 double oStartT = other->fTs[oIndex].fT;
749 while (oIndex > 0 && other->fTs[oIndex - 1].fT == oStartT) {
750 --oIndex;
751 }
720 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; 752 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts;
721 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 753 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts;
722 SkOpSpan* test = &fTs[index]; 754 SkOpSpan* test = &fTs[index];
723 const SkPoint* testPt = &test->fPt; 755 const SkPoint* testPt = &test->fPt;
756 double testT = test->fT;
724 SkOpSpan* oTest = &other->fTs[oIndex]; 757 SkOpSpan* oTest = &other->fTs[oIndex];
725 const SkPoint* oTestPt = &oTest->fPt; 758 const SkPoint* oTestPt = &oTest->fPt;
726 SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 759 SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
727 do { 760 do {
728 SkASSERT(test->fT < 1); 761 SkASSERT(test->fT < 1);
729 SkASSERT(oTest->fT < 1); 762 SkASSERT(oTest->fT < 1);
730 #if 0 763 #if 0
731 if (test->fDone || oTest->fDone) { 764 if (test->fDone || oTest->fDone) {
732 #else // consolidate the winding count even if done 765 #else // consolidate the winding count even if done
733 if ((test->fWindValue == 0 && test->fOppValue == 0) 766 if ((test->fWindValue == 0 && test->fOppValue == 0)
(...skipping 19 matching lines...) Expand all
753 if (!binary || test->fWindValue + oTest->fOppValue >= 0) { 786 if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
754 bumpCoincidentThis(*oTest, binary, &index, &outsidePts); 787 bumpCoincidentThis(*oTest, binary, &index, &outsidePts);
755 other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); 788 other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts);
756 } else { 789 } else {
757 other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts); 790 other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts);
758 bumpCoincidentOther(*oTest, &index, &outsidePts); 791 bumpCoincidentOther(*oTest, &index, &outsidePts);
759 } 792 }
760 } 793 }
761 test = &fTs[index]; 794 test = &fTs[index];
762 testPt = &test->fPt; 795 testPt = &test->fPt;
763 if (endPt == *testPt) { 796 testT = test->fT;
797 if (endPt == *testPt || endT == testT) {
764 break; 798 break;
765 } 799 }
766 oTest = &other->fTs[oIndex]; 800 oTest = &other->fTs[oIndex];
767 oTestPt = &oTest->fPt; 801 oTestPt = &oTest->fPt;
768 SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 802 SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
769 } while (endPt != *oTestPt); 803 } while (endPt != *oTestPt);
804 if (endPt != *testPt && endT != testT) { // in rare cases, one may have end ed before the other
805 int lastWind = test[-1].fWindValue;
806 int lastOpp = test[-1].fOppValue;
807 bool zero = lastWind == 0 && lastOpp == 0;
808 do {
809 if (test->fWindValue || test->fOppValue) {
810 test->fWindValue = lastWind;
811 test->fOppValue = lastOpp;
812 if (zero) {
813 test->fDone = true;
814 ++fDoneSpans;
815 }
816 }
817 test = &fTs[++index];
818 testPt = &test->fPt;
819 } while (endPt != *testPt);
820 }
770 int outCount = outsidePts.count(); 821 int outCount = outsidePts.count();
771 if (!done() && outCount) { 822 if (!done() && outCount) {
772 addCoinOutsides(outsidePts[0], endPt, other); 823 addCoinOutsides(outsidePts[0], endPt, other);
773 } 824 }
774 if (!other->done() && oOutsidePts.count()) { 825 if (!other->done() && oOutsidePts.count()) {
775 other->addCoinOutsides(oOutsidePts[0], endPt, this); 826 other->addCoinOutsides(oOutsidePts[0], endPt, this);
776 } 827 }
777 } 828 }
778 829
779 // FIXME: this doesn't prevent the same span from being added twice 830 // FIXME: this doesn't prevent the same span from being added twice
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 if (!span->fOppValue && !span->fDone) { 1369 if (!span->fOppValue && !span->fDone) {
1319 span->fDone = true; 1370 span->fDone = true;
1320 ++fDoneSpans; 1371 ++fDoneSpans;
1321 return true; 1372 return true;
1322 } 1373 }
1323 } 1374 }
1324 return false; 1375 return false;
1325 } 1376 }
1326 1377
1327 bool SkOpSegment::bumpSpan(SkOpSpan* span, int windDelta, int oppDelta) { 1378 bool SkOpSegment::bumpSpan(SkOpSpan* span, int windDelta, int oppDelta) {
1328 SkASSERT(!span->fDone || span->fTiny); 1379 SkASSERT(!span->fDone || span->fTiny || span->fSmall);
1329 span->fWindValue += windDelta; 1380 span->fWindValue += windDelta;
1330 SkASSERT(span->fWindValue >= 0); 1381 SkASSERT(span->fWindValue >= 0);
1331 span->fOppValue += oppDelta; 1382 span->fOppValue += oppDelta;
1332 SkASSERT(span->fOppValue >= 0); 1383 SkASSERT(span->fOppValue >= 0);
1333 if (fXor) { 1384 if (fXor) {
1334 span->fWindValue &= 1; 1385 span->fWindValue &= 1;
1335 } 1386 }
1336 if (fOppXor) { 1387 if (fOppXor) {
1337 span->fOppValue &= 1; 1388 span->fOppValue &= 1;
1338 } 1389 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 ++tLast; 1428 ++tLast;
1378 } 1429 }
1379 while (++tLast < count && t == fTs[tLast].fT) 1430 while (++tLast < count && t == fTs[tLast].fT)
1380 ; 1431 ;
1381 for (int peekIndex = peekStart; peekIndex <= peekLast; ++peekIndex) { 1432 for (int peekIndex = peekStart; peekIndex <= peekLast; ++peekIndex) {
1382 if (peekIndex == span.fOtherIndex) { // skip the other span pointed to by this span 1433 if (peekIndex == span.fOtherIndex) { // skip the other span pointed to by this span
1383 continue; 1434 continue;
1384 } 1435 }
1385 const SkOpSpan& peekSpan = other->fTs[peekIndex]; 1436 const SkOpSpan& peekSpan = other->fTs[peekIndex];
1386 SkOpSegment* match = peekSpan.fOther; 1437 SkOpSegment* match = peekSpan.fOther;
1438 if (match->done()) {
1439 continue; // if the edge has already been eaten (likely coincid ence), ignore it
1440 }
1387 const double matchT = peekSpan.fOtherT; 1441 const double matchT = peekSpan.fOtherT;
1388 // see if any of the spans match the other spans 1442 // see if any of the spans match the other spans
1389 for (int tIndex = tStart + 1; tIndex < tLast; ++tIndex) { 1443 for (int tIndex = tStart + 1; tIndex < tLast; ++tIndex) {
1390 const SkOpSpan& tSpan = fTs[tIndex]; 1444 const SkOpSpan& tSpan = fTs[tIndex];
1391 if (tSpan.fOther == match) { 1445 if (tSpan.fOther == match) {
1392 if (tSpan.fOtherT == matchT) { 1446 if (tSpan.fOtherT == matchT) {
1393 goto nextPeeker; 1447 goto nextPeekIndex;
1394 } 1448 }
1395 double midT = (tSpan.fOtherT + matchT) / 2; 1449 double midT = (tSpan.fOtherT + matchT) / 2;
1396 if (match->betweenPoints(midT, tSpan.fPt, peekSpan.fPt)) { 1450 if (match->betweenPoints(midT, tSpan.fPt, peekSpan.fPt)) {
1397 goto nextPeeker; 1451 goto nextPeekIndex;
1398 } 1452 }
1399 } 1453 }
1400 } 1454 }
1401 if (missingSpans.count() > 0) { 1455 if (missingSpans.count() > 0) {
1402 const MissingSpan& lastMissing = missingSpans.back(); 1456 const MissingSpan& lastMissing = missingSpans.back();
1403 if (lastMissing.fCommand == MissingSpan::kAddMissing 1457 if (lastMissing.fCommand == MissingSpan::kAddMissing
1404 && lastMissing.fT == t 1458 && lastMissing.fT == t
1405 && lastMissing.fOther == match 1459 && lastMissing.fOther == match
1406 && lastMissing.fOtherT == matchT) { 1460 && lastMissing.fOtherT == matchT) {
1407 SkASSERT(lastMissing.fPt == peekSpan.fPt); 1461 SkASSERT(lastMissing.fPt == peekSpan.fPt);
1408 continue; 1462 continue;
1409 } 1463 }
1410 } 1464 }
1411 #if DEBUG_CHECK_ENDS 1465 #if DEBUG_CHECK_ENDS
1412 SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,% 1.9g)\n", 1466 SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,% 1.9g)\n",
1413 __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, p eekSpan.fPt.fY); 1467 __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, p eekSpan.fPt.fY);
1414 #endif 1468 #endif
1415 // this segment is missing a entry that the other contains 1469 // this segment is missing a entry that the other contains
1416 // remember so we can add the missing one and recompute the indices 1470 // remember so we can add the missing one and recompute the indices
1417 MissingSpan& missing = missingSpans.push_back(); 1471 {
1418 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 1472 MissingSpan& missing = missingSpans.push_back();
1419 missing.fCommand = MissingSpan::kAddMissing; 1473 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
1420 missing.fT = t; 1474 missing.fCommand = MissingSpan::kAddMissing;
1421 missing.fOther = match; 1475 missing.fT = t;
1422 missing.fOtherT = matchT; 1476 missing.fOther = match;
1423 missing.fPt = peekSpan.fPt; 1477 missing.fOtherT = matchT;
1478 missing.fPt = peekSpan.fPt;
1479 }
1480 break;
1481 nextPeekIndex:
1482 ;
1424 } 1483 }
1425 nextPeeker:
1426 ;
1427 } 1484 }
1428 if (missingSpans.count() == 0) { 1485 if (missingSpans.count() == 0) {
1486 debugValidate();
1429 return; 1487 return;
1430 } 1488 }
1431 // if one end is near the other point, look for a coincident span 1489 // if one end is near the other point, look for a coincident span
1432 for (int index = 0; index < count; ++index) { 1490 for (int index = 0; index < count; ++index) {
1433 const SkOpSpan& span = fTs[index]; 1491 const SkOpSpan& span = fTs[index];
1434 if (span.fT > 0) { 1492 if (span.fT > 0) {
1435 break; 1493 break;
1436 } 1494 }
1437 const SkOpSpan& otherSpan = span.fOther->span(span.fOtherIndex); 1495 const SkOpSpan& otherSpan = span.fOther->span(span.fOtherIndex);
1438 if (span.fNear) { 1496 if (span.fNear) {
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1683 } 1741 }
1684 return other; 1742 return other;
1685 } 1743 }
1686 // more than one viable candidate -- measure angles to find best 1744 // more than one viable candidate -- measure angles to find best
1687 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles; 1745 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
1688 SkASSERT(startIndex - endIndex != 0); 1746 SkASSERT(startIndex - endIndex != 0);
1689 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 1747 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
1690 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; 1748 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
1691 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp, &angles , &sorted); 1749 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp, &angles , &sorted);
1692 bool sortable = calcWinding != SK_NaN32; 1750 bool sortable = calcWinding != SK_NaN32;
1751 if (sortable && sorted.count() == 0) {
1752 // if no edge has a computed winding sum, we can go no further
1753 *unsortable = true;
1754 return NULL;
1755 }
1693 int angleCount = angles.count(); 1756 int angleCount = angles.count();
1694 int firstIndex = findStartingEdge(sorted, startIndex, end); 1757 int firstIndex = findStartingEdge(sorted, startIndex, end);
1695 SkASSERT(!sortable || firstIndex >= 0); 1758 SkASSERT(!sortable || firstIndex >= 0);
1696 #if DEBUG_SORT 1759 #if DEBUG_SORT
1697 debugShowSort(__FUNCTION__, sorted, firstIndex, sortable); 1760 debugShowSort(__FUNCTION__, sorted, firstIndex, sortable);
1698 #endif 1761 #endif
1699 if (!sortable) { 1762 if (!sortable) {
1700 *unsortable = true; 1763 *unsortable = true;
1701 return NULL; 1764 return NULL;
1702 } 1765 }
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
2197 int oppWindVal = oppValue(SkMin32(start, end)); 2260 int oppWindVal = oppValue(SkMin32(start, end));
2198 if (!oppWind) { 2261 if (!oppWind) {
2199 oppWind = dx < 0 ? oppWindVal : -oppWindVal; 2262 oppWind = dx < 0 ? oppWindVal : -oppWindVal;
2200 } else if (hitOppDx * dx >= 0) { 2263 } else if (hitOppDx * dx >= 0) {
2201 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); 2264 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal);
2202 if (abs(oppWind) < abs(oppSideWind)) { 2265 if (abs(oppWind) < abs(oppSideWind)) {
2203 oppWind = oppSideWind; 2266 oppWind = oppSideWind;
2204 } 2267 }
2205 } 2268 }
2206 (void) markAndChaseWinding(start, end, winding, oppWind); 2269 (void) markAndChaseWinding(start, end, winding, oppWind);
2270 // OPTIMIZATION: the reverse mark and chase could skip the first marking
2271 (void) markAndChaseWinding(end, start, winding, oppWind);
2207 } 2272 }
2208 2273
2209 // OPTIMIZE: successive calls could start were the last leaves off 2274 // OPTIMIZE: successive calls could start were the last leaves off
2210 // or calls could specialize to walk forwards or backwards 2275 // or calls could specialize to walk forwards or backwards
2211 bool SkOpSegment::isMissing(double startT) const { 2276 bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const {
2212 size_t tCount = fTs.count(); 2277 size_t tCount = fTs.count();
2213 for (size_t index = 0; index < tCount; ++index) { 2278 for (size_t index = 0; index < tCount; ++index) {
2214 if (approximately_zero(startT - fTs[index].fT)) { 2279 const SkOpSpan& span = fTs[index];
2280 if (approximately_zero(startT - span.fT) && pt == span.fPt) {
2215 return false; 2281 return false;
2216 } 2282 }
2217 } 2283 }
2218 return true; 2284 return true;
2219 } 2285 }
2220 2286
2221 bool SkOpSegment::isSimple(int end) const { 2287 bool SkOpSegment::isSimple(int end) const {
2222 int count = fTs.count(); 2288 int count = fTs.count();
2223 if (count == 2) { 2289 if (count == 2) {
2224 return true; 2290 return true;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2345 maxWinding = sumWinding; 2411 maxWinding = sumWinding;
2346 } 2412 }
2347 SkOpSpan* last; 2413 SkOpSpan* last;
2348 if (activeAngle) { 2414 if (activeAngle) {
2349 last = markAndChaseWinding(angle, maxWinding); 2415 last = markAndChaseWinding(angle, maxWinding);
2350 } else { 2416 } else {
2351 last = markAndChaseDoneUnary(angle, maxWinding); 2417 last = markAndChaseDoneUnary(angle, maxWinding);
2352 } 2418 }
2353 #if DEBUG_WINDING 2419 #if DEBUG_WINDING
2354 if (last) { 2420 if (last) {
2355 SkDebugf("%s last id=%d windSum=%d small=%d\n", __FUNCTION__, 2421 SkDebugf("%s last id=%d windSum=", __FUNCTION__,
2356 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last->fW indSum, 2422 last->fOther->fTs[last->fOtherIndex].fOther->debugID());
2357 last->fSmall); 2423 SkPathOpsDebug::WindingPrintf(last->fWindSum);
2424 SkDebugf(" small=%d\n", last->fSmall);
2358 } 2425 }
2359 #endif 2426 #endif
2360 return last; 2427 return last;
2361 } 2428 }
2362 2429
2363 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi ng, 2430 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi ng,
2364 int oppSumWinding, bool activeAngle, const SkOp Angle* angle) { 2431 int oppSumWinding, bool activeAngle, const SkOp Angle* angle) {
2365 SkASSERT(angle->segment() == this); 2432 SkASSERT(angle->segment() == this);
2366 if (UseInnerWinding(maxWinding, sumWinding)) { 2433 if (UseInnerWinding(maxWinding, sumWinding)) {
2367 maxWinding = sumWinding; 2434 maxWinding = sumWinding;
2368 } 2435 }
2369 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumW inding)) { 2436 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumW inding)) {
2370 oppMaxWinding = oppSumWinding; 2437 oppMaxWinding = oppSumWinding;
2371 } 2438 }
2372 SkOpSpan* last; 2439 SkOpSpan* last;
2373 if (activeAngle) { 2440 if (activeAngle) {
2374 last = markAndChaseWinding(angle, maxWinding, oppMaxWinding); 2441 last = markAndChaseWinding(angle, maxWinding, oppMaxWinding);
2375 } else { 2442 } else {
2376 last = markAndChaseDoneBinary(angle, maxWinding, oppMaxWinding); 2443 last = markAndChaseDoneBinary(angle, maxWinding, oppMaxWinding);
2377 } 2444 }
2378 #if DEBUG_WINDING 2445 #if DEBUG_WINDING
2379 if (last) { 2446 if (last) {
2380 SkDebugf("%s last id=%d windSum=%d small=%d\n", __FUNCTION__, 2447 SkDebugf("%s last id=%d windSum=", __FUNCTION__,
2381 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last->fW indSum, 2448 last->fOther->fTs[last->fOtherIndex].fOther->debugID());
2382 last->fSmall); 2449 SkPathOpsDebug::WindingPrintf(last->fWindSum);
2450 SkDebugf(" small=%d\n", last->fSmall);
2383 } 2451 }
2384 #endif 2452 #endif
2385 return last; 2453 return last;
2386 } 2454 }
2387 2455
2388 // FIXME: this should also mark spans with equal (x,y) 2456 // FIXME: this should also mark spans with equal (x,y)
2389 // This may be called when the segment is already marked done. While this 2457 // This may be called when the segment is already marked done. While this
2390 // wastes time, it shouldn't do any more than spin through the T spans. 2458 // wastes time, it shouldn't do any more than spin through the T spans.
2391 // OPTIMIZATION: abort on first done found (assuming that this code is 2459 // OPTIMIZATION: abort on first done found (assuming that this code is
2392 // always called to mark segments done). 2460 // always called to mark segments done).
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2484 #endif 2552 #endif
2485 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 2553 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
2486 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum); 2554 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum);
2487 span.fWindSum = winding; 2555 span.fWindSum = winding;
2488 return &span; 2556 return &span;
2489 } 2557 }
2490 2558
2491 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng, 2559 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng,
2492 int oppWinding) { 2560 int oppWinding) {
2493 SkOpSpan& span = fTs[tIndex]; 2561 SkOpSpan& span = fTs[tIndex];
2494 if (span.fDone) { 2562 if (span.fDone && !span.fSmall) {
2495 return NULL; 2563 return NULL;
2496 } 2564 }
2497 #if DEBUG_MARK_DONE 2565 #if DEBUG_MARK_DONE
2498 debugShowNewWinding(funName, span, winding, oppWinding); 2566 debugShowNewWinding(funName, span, winding, oppWinding);
2499 #endif 2567 #endif
2500 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 2568 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
2501 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum); 2569 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum);
2502 span.fWindSum = winding; 2570 span.fWindSum = winding;
2503 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding); 2571 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding);
2504 SkASSERT(abs(oppWinding) <= SkPathOpsDebug::gMaxWindSum); 2572 SkASSERT(abs(oppWinding) <= SkPathOpsDebug::gMaxWindSum);
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
3127 } 3195 }
3128 } 3196 }
3129 SkASSERT(0); 3197 SkASSERT(0);
3130 return 0; 3198 return 0;
3131 } 3199 }
3132 3200
3133 void SkOpSegment::zeroSpan(SkOpSpan* span) { 3201 void SkOpSegment::zeroSpan(SkOpSpan* span) {
3134 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 3202 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
3135 span->fWindValue = 0; 3203 span->fWindValue = 0;
3136 span->fOppValue = 0; 3204 span->fOppValue = 0;
3205 if (span->fTiny || span->fSmall) {
3206 return;
3207 }
3137 SkASSERT(!span->fDone); 3208 SkASSERT(!span->fDone);
3138 span->fDone = true; 3209 span->fDone = true;
3139 ++fDoneSpans; 3210 ++fDoneSpans;
3140 } 3211 }
3141 3212
3142 #if DEBUG_SWAP_TOP 3213 #if DEBUG_SWAP_TOP
3143 bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const { 3214 bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const {
3144 if (fVerb != SkPath::kCubic_Verb) { 3215 if (fVerb != SkPath::kCubic_Verb) {
3145 return false; 3216 return false;
3146 } 3217 }
3147 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT); 3218 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
3148 return dst.controlsContainedByEnds(); 3219 return dst.controlsContainedByEnds();
3149 } 3220 }
3150 #endif 3221 #endif
3151 3222
3152 #if DEBUG_CONCIDENT 3223 #if DEBUG_CONCIDENT
3153 // SkASSERT if pair has not already been added 3224 // SkASSERT if pair has not already been added
3154 void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double other T) const { 3225 void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double other T) const {
3155 for (int i = 0; i < fTs.count(); ++i) { 3226 for (int i = 0; i < fTs.count(); ++i) {
3156 if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == other T) { 3227 if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == other T) {
3157 return; 3228 return;
3158 } 3229 }
3159 } 3230 }
3160 SkASSERT(0); 3231 SkASSERT(0);
3161 } 3232 }
3162 #endif 3233 #endif
3163 3234
3164 #if DEBUG_CONCIDENT 3235 #if DEBUG_CONCIDENT
3165 void SkOpSegment::debugShowTs() const { 3236 void SkOpSegment::debugShowTs(const char* prefix) const {
3166 SkDebugf("%s id=%d", __FUNCTION__, fID); 3237 SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID);
3167 int lastWind = -1; 3238 int lastWind = -1;
3168 int lastOpp = -1; 3239 int lastOpp = -1;
3169 double lastT = -1; 3240 double lastT = -1;
3170 int i; 3241 int i;
3171 for (i = 0; i < fTs.count(); ++i) { 3242 for (i = 0; i < fTs.count(); ++i) {
3172 bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue 3243 bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
3173 || lastOpp != fTs[i].fOppValue; 3244 || lastOpp != fTs[i].fOppValue;
3174 if (change && lastWind >= 0) { 3245 if (change && lastWind >= 0) {
3175 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]", 3246 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
3176 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp); 3247 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
3510 3581
3511 void SkOpSegment::dumpSpans() const { 3582 void SkOpSegment::dumpSpans() const {
3512 int count = this->count(); 3583 int count = this->count();
3513 for (int index = 0; index < count; ++index) { 3584 for (int index = 0; index < count; ++index) {
3514 const SkOpSpan& span = this->span(index); 3585 const SkOpSpan& span = this->span(index);
3515 SkDebugf("[%d] ", index); 3586 SkDebugf("[%d] ", index);
3516 span.dump(); 3587 span.dump();
3517 } 3588 }
3518 } 3589 }
3519 #endif 3590 #endif
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698