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

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

Issue 75453003: optimize pathops coverage (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: remove unused code now that testing is complete Created 7 years, 1 month 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
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 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 fBounds.setQuadBounds(pts); 400 fBounds.setQuadBounds(pts);
401 } 401 }
402 402
403 // Defer all coincident edge processing until 403 // Defer all coincident edge processing until
404 // after normal intersections have been computed 404 // after normal intersections have been computed
405 405
406 // no need to be tricky; insert in normal T order 406 // no need to be tricky; insert in normal T order
407 // resolve overlapping ts when considering coincidence later 407 // resolve overlapping ts when considering coincidence later
408 408
409 // add non-coincident intersection. Resulting edges are sorted in T. 409 // add non-coincident intersection. Resulting edges are sorted in T.
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) {
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]; 420 const SkPoint& firstPt = fPts[0];
(...skipping 24 matching lines...) Expand all
445 SkOpSpan* span; 445 SkOpSpan* span;
446 if (insertedAt >= 0) { 446 if (insertedAt >= 0) {
447 span = fTs.insert(insertedAt); 447 span = fTs.insert(insertedAt);
448 } else { 448 } else {
449 insertedAt = tCount; 449 insertedAt = tCount;
450 span = fTs.append(); 450 span = fTs.append();
451 } 451 }
452 span->fT = newT; 452 span->fT = newT;
453 span->fOther = other; 453 span->fOther = other;
454 span->fPt = pt; 454 span->fPt = pt;
455 span->fNear = isNear;
456 #if 0 455 #if 0
457 // cubics, for instance, may not be exact enough to satisfy this check (e.g. , cubicOp69d) 456 // cubics, for instance, may not be exact enough to satisfy this check (e.g. , cubicOp69d)
458 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) 457 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX)
459 && approximately_equal(xyAtT(newT).fY, pt.fY)); 458 && approximately_equal(xyAtT(newT).fY, pt.fY));
460 #endif 459 #endif
461 span->fWindSum = SK_MinS32; 460 span->fWindSum = SK_MinS32;
462 span->fOppSum = SK_MinS32; 461 span->fOppSum = SK_MinS32;
463 span->fWindValue = 1; 462 span->fWindValue = 1;
464 span->fOppValue = 0; 463 span->fOppValue = 0;
465 span->fSmall = false; 464 span->fSmall = false;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other); 638 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other);
640 } 639 }
641 } 640 }
642 if (!other->done() && oOutsidePts.count()) { 641 if (!other->done() && oOutsidePts.count()) {
643 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this); 642 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this);
644 } 643 }
645 } 644 }
646 645
647 int SkOpSegment::addSelfT(SkOpSegment* other, const SkPoint& pt, double newT) { 646 int SkOpSegment::addSelfT(SkOpSegment* other, const SkPoint& pt, double newT) {
648 // if the tail nearly intersects itself but not quite, the caller records th is separately 647 // if the tail nearly intersects itself but not quite, the caller records th is separately
649 int result = addT(other, pt, newT, SkOpSpan::kPointIsExact); 648 int result = addT(other, pt, newT);
650 SkOpSpan* span = &fTs[result]; 649 SkOpSpan* span = &fTs[result];
651 span->fLoop = true; 650 span->fLoop = true;
652 return result; 651 return result;
653 } 652 }
654 653
655 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in dexPtr, 654 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in dexPtr,
656 SkTArray<SkPoint, true>* outsideTs) { 655 SkTArray<SkPoint, true>* outsideTs) {
657 int index = *indexPtr; 656 int index = *indexPtr;
658 int oWindValue = oTest.fWindValue; 657 int oWindValue = oTest.fWindValue;
659 int oOppValue = oTest.fOppValue; 658 int oOppValue = oTest.fOppValue;
660 if (binary) { 659 if (binary) {
661 SkTSwap<int>(oWindValue, oOppValue); 660 SkTSwap<int>(oWindValue, oOppValue);
662 } 661 }
663 SkOpSpan* const test = &fTs[index]; 662 SkOpSpan* const test = &fTs[index];
664 SkOpSpan* end = test; 663 SkOpSpan* end = test;
665 const SkPoint& oStartPt = oTest.fPt; 664 const SkPoint& oStartPt = oTest.fPt;
666 do { 665 do {
667 if (bumpSpan(end, oWindValue, oOppValue)) { 666 if (bumpSpan(end, oWindValue, oOppValue)) {
668 TrackOutside(outsideTs, oStartPt); 667 TrackOutside(outsideTs, oStartPt);
669 } 668 }
670 end = &fTs[++index]; 669 end = &fTs[++index];
671 } while ((end->fPt == test->fPt || end->fT == test->fT) && end->fT < 1); 670 } while ((end->fPt == test->fPt || end->fT == test->fT) && end->fT < 1);
672 *indexPtr = index; 671 *indexPtr = index;
673 } 672 }
674 673
675 bool SkOpSegment::bumpCoincident(SkOpSpan* test, bool bigger, bool binary) {
676 if (bigger) {
677 if (binary) {
678 if (fOppXor) {
679 test->fOppValue ^= 1;
680 } else {
681 test->fOppValue++;
682 }
683 } else {
684 if (fXor) {
685 test->fWindValue ^= 1;
686 } else {
687 test->fWindValue++;
688 }
689 }
690 if (!test->fWindValue && !test->fOppValue) {
691 test->fDone = true;
692 ++fDoneSpans;
693 return true;
694 }
695 return false;
696 }
697 return decrementSpan(test);
698 }
699
700 // because of the order in which coincidences are resolved, this and other 674 // because of the order in which coincidences are resolved, this and other
701 // may not have the same intermediate points. Compute the corresponding 675 // may not have the same intermediate points. Compute the corresponding
702 // intermediate T values (using this as the master, other as the follower) 676 // intermediate T values (using this as the master, other as the follower)
703 // and walk other conditionally -- hoping that it catches up in the end 677 // and walk other conditionally -- hoping that it catches up in the end
704 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, 678 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr,
705 SkTArray<SkPoint, true>* oOutsidePts) { 679 SkTArray<SkPoint, true>* oOutsidePts) {
706 int oIndex = *oIndexPtr; 680 int oIndex = *oIndexPtr;
707 SkOpSpan* const oTest = &fTs[oIndex]; 681 SkOpSpan* const oTest = &fTs[oIndex];
708 SkOpSpan* oEnd = oTest; 682 SkOpSpan* oEnd = oTest;
709 const SkPoint& startPt = test.fPt; 683 const SkPoint& startPt = test.fPt;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", 817 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n",
844 __FUNCTION__, fID, t, other->fID, otherT); 818 __FUNCTION__, fID, t, other->fID, otherT);
845 #endif 819 #endif
846 return; 820 return;
847 } 821 }
848 } 822 }
849 #if DEBUG_ADD_T_PAIR 823 #if DEBUG_ADD_T_PAIR
850 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", 824 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
851 __FUNCTION__, fID, t, other->fID, otherT); 825 __FUNCTION__, fID, t, other->fID, otherT);
852 #endif 826 #endif
853 int insertedAt = addT(other, pt, t, SkOpSpan::kPointIsExact); 827 int insertedAt = addT(other, pt, t);
854 int otherInsertedAt = other->addT(this, pt, otherT, SkOpSpan::kPointIsExact) ; 828 int otherInsertedAt = other->addT(this, pt, otherT);
855 addOtherT(insertedAt, otherT, otherInsertedAt); 829 addOtherT(insertedAt, otherT, otherInsertedAt);
856 other->addOtherT(otherInsertedAt, t, insertedAt); 830 other->addOtherT(otherInsertedAt, t, insertedAt);
857 matchWindingValue(insertedAt, t, borrowWind); 831 matchWindingValue(insertedAt, t, borrowWind);
858 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); 832 other->matchWindingValue(otherInsertedAt, otherT, borrowWind);
859 } 833 }
860 834
861 void SkOpSegment::addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* an gles) const { 835 void SkOpSegment::addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* an gles) const {
862 // add edge leading into junction 836 // add edge leading into junction
863 int min = SkMin32(end, start); 837 int min = SkMin32(end, start);
864 if (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0) { 838 if (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0) {
865 addAngle(angles, end, start); 839 addAngle(angles, end, start);
866 } 840 }
867 // add edge leading away from junction 841 // add edge leading away from junction
868 int step = SkSign32(end - start); 842 int step = SkSign32(end - start);
869 int tIndex = nextExactSpan(end, step); 843 int tIndex = nextExactSpan(end, step);
870 min = SkMin32(end, tIndex); 844 min = SkMin32(end, tIndex);
871 if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0)) { 845 if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0)) {
872 addAngle(angles, end, tIndex); 846 addAngle(angles, end, tIndex);
873 } 847 }
874 } 848 }
875 849
876 SkOpSegment::MissingSpan::Command SkOpSegment::adjustThisNear(double startT, con st SkPoint& startPt,
877 const SkPoint& endPt, SkTArray<MissingSpan, true>* missingSpans) {
878 // see if endPt exists on this curve, and if it has the same t or a differen t T than the startT
879 int count = this->count();
880 SkASSERT(count > 0);
881 int startIndex, endIndex, step;
882 if (startT == 0) {
883 startIndex = 0;
884 endIndex = count;
885 step = 1;
886 } else {
887 SkASSERT(startT == 1);
888 startIndex = count - 1;
889 endIndex = -1;
890 step = -1;
891 }
892 int index = startIndex;
893 do {
894 const SkOpSpan& span = fTs[index];
895 if (span.fPt != endPt) {
896 continue;
897 }
898 if (span.fT == startT) {
899 // check to see if otherT matches some other mid curve intersection
900 int inner = startIndex;
901 do {
902 if (inner == index) {
903 continue;
904 }
905 const SkOpSpan& matchSpan = fTs[inner];
906 double matchT = span.fOther->missingNear(span.fOtherT, matchSpan .fOther, startPt,
907 endPt);
908 if (matchT >= 0) {
909 SkASSERT(missingSpans);
910 MissingSpan& missingSpan = missingSpans->push_back();
911 SkDEBUGCODE(sk_bzero(&missingSpan, sizeof(missingSpan)));
912 missingSpan.fCommand = MissingSpan::kRemoveNear;
913 missingSpan.fT = startT;
914 missingSpan.fSegment = this;
915 missingSpan.fOther = span.fOther;
916 missingSpan.fOtherT = matchT;
917 return missingSpan.fCommand;
918 }
919 } while ((inner += step) != endIndex);
920 break;
921 }
922 double midT = (startT + span.fT) / 2;
923 if (betweenPoints(midT, startPt, endPt)) {
924 if (!missingSpans) {
925 return MissingSpan::kZeroSpan;
926 }
927 MissingSpan& missingSpan = missingSpans->push_back();
928 SkDEBUGCODE(sk_bzero(&missingSpan, sizeof(missingSpan)));
929 missingSpan.fCommand = MissingSpan::kZeroSpan;
930 missingSpan.fT = SkTMin(startT, span.fT);
931 missingSpan.fEndT = SkTMax(startT, span.fT);
932 missingSpan.fSegment = this;
933 return missingSpan.fCommand;
934 }
935 } while ((index += step) != endIndex);
936 return MissingSpan::kNoAction;
937 }
938
939 void SkOpSegment::adjustOtherNear(double startT, const SkPoint& startPt, const S kPoint& endPt,
940 SkTArray<MissingSpan, true>* missingSpans) {
941 int count = this->count();
942 SkASSERT(count > 0);
943 int startIndex, endIndex, step;
944 if (startT == 0) {
945 startIndex = 0;
946 endIndex = count;
947 step = 1;
948 } else {
949 SkASSERT(startT == 1);
950 startIndex = count - 1;
951 endIndex = -1;
952 step = -1;
953 }
954 int index = startIndex;
955 do {
956 const SkOpSpan& span = fTs[index];
957 if (span.fT != startT) {
958 return;
959 }
960 SkOpSegment* other = span.fOther;
961 if (other->fPts[0] == endPt) {
962 other->adjustThisNear(0, endPt, startPt, missingSpans);
963 } else if (other->fPts[0] == startPt) {
964 other->adjustThisNear(0, startPt, endPt, missingSpans);
965 }
966 if (other->ptAtT(1) == endPt) {
967 other->adjustThisNear(1, endPt, startPt, missingSpans);
968 } else if (other->ptAtT(1) == startPt) {
969 other->adjustThisNear(1, startPt, endPt, missingSpans);
970 }
971 } while ((index += step) != endIndex);
972 }
973
974 void SkOpSegment::adjustMissingNear(const SkPoint& startPt, const SkPoint& endPt ,
975 SkTArray<MissingSpan, true>* missingSpans) {
976 int count = missingSpans->count();
977 for (int index = 0; index < count; ) {
978 MissingSpan& missing = (*missingSpans)[index];
979 SkOpSegment* other = missing.fOther;
980 MissingSpan::Command command = MissingSpan::kNoAction;
981 if (missing.fPt == startPt) {
982 if (missingNear(missing.fT, other, startPt, endPt) >= 0) {
983 command = MissingSpan::kZeroSpan;
984 } else if (other->ptAtT(0) == endPt) {
985 command = other->adjustThisNear(0, endPt, startPt, NULL);
986 } else if (other->ptAtT(1) == endPt) {
987 command = other->adjustThisNear(1, endPt, startPt, NULL);
988 }
989 } else if (missing.fPt == endPt) {
990 if (missingNear(missing.fT, other, endPt, startPt) >= 0) {
991 command = MissingSpan::kZeroSpan;
992 } else if (other->ptAtT(0) == startPt) {
993 command = other->adjustThisNear(0, startPt, endPt, NULL);
994 } else if (other->ptAtT(1) == startPt) {
995 command = other->adjustThisNear(1, startPt, endPt, NULL);
996 }
997 }
998 if (command == MissingSpan::kZeroSpan) {
999 #if 1
1000 missing = missingSpans->back();
1001 missingSpans->pop_back();
1002 #else // if this is supported in the future ...
1003 missingSpans->removeShuffle(index);
1004 #endif
1005 --count;
1006 continue;
1007 }
1008 ++index;
1009 }
1010 }
1011
1012 void SkOpSegment::adjustNear(double startT, const SkPoint& endPt,
1013 SkTArray<MissingSpan, true>* missingSpans) {
1014 const SkPoint startPt = ptAtT(startT);
1015 adjustMissingNear(startPt, endPt, missingSpans);
1016 adjustThisNear(startT, startPt, endPt, missingSpans);
1017 adjustOtherNear(startT, startPt, endPt, missingSpans);
1018 }
1019
1020 int SkOpSegment::advanceCoincidentThis(int index) {
1021 SkOpSpan* const test = &fTs[index];
1022 SkOpSpan* end;
1023 do {
1024 end = &fTs[++index];
1025 } while (approximately_negative(end->fT - test->fT));
1026 return index;
1027 }
1028
1029 int SkOpSegment::advanceCoincidentOther(double oEndT, int oIndex) {
1030 SkOpSpan* const oTest = &fTs[oIndex];
1031 SkOpSpan* oEnd = oTest;
1032 const double oStartT = oTest->fT;
1033 while (!approximately_negative(oEndT - oEnd->fT)
1034 && approximately_negative(oEnd->fT - oStartT)) {
1035 oEnd = &fTs[++oIndex];
1036 }
1037 return oIndex;
1038 }
1039
1040 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const { 850 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const {
1041 const SkPoint midPt = ptAtT(midT); 851 const SkPoint midPt = ptAtT(midT);
1042 SkPathOpsBounds bounds; 852 SkPathOpsBounds bounds;
1043 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY); 853 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY);
1044 bounds.sort(); 854 bounds.sort();
1045 return bounds.almostContains(midPt); 855 return bounds.almostContains(midPt);
1046 } 856 }
1047 857
1048 bool SkOpSegment::betweenTs(int lesser, double testT, int greater) const { 858 bool SkOpSegment::betweenTs(int lesser, double testT, int greater) const {
1049 if (lesser > greater) { 859 if (lesser > greater) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 } 1038 }
1229 } 1039 }
1230 SkOpSegment* nextSegment = nextAngle->segment(); 1040 SkOpSegment* nextSegment = nextAngle->segment();
1231 int maxWinding, sumWinding; 1041 int maxWinding, sumWinding;
1232 SkOpSpan* last; 1042 SkOpSpan* last;
1233 if (binary) { 1043 if (binary) {
1234 int oppMaxWinding, oppSumWinding; 1044 int oppMaxWinding, oppSumWinding;
1235 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiW inding, 1045 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiW inding,
1236 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSum Winding); 1046 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSum Winding);
1237 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding, 1047 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding,
1238 true, nextAngle); 1048 nextAngle);
1239 } else { 1049 } else {
1240 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiW inding, 1050 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiW inding,
1241 &maxWinding, &sumWinding); 1051 &maxWinding, &sumWinding);
1242 last = nextSegment->markAngle(maxWinding, sumWinding, true, nextAngle); 1052 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
1243 } 1053 }
1244 nextAngle->setLastMarked(last); 1054 nextAngle->setLastMarked(last);
1245 } 1055 }
1246 1056
1247 void SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* ne xtAngle, 1057 void SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* ne xtAngle,
1248 SkOpAngle::IncludeType includeType) { 1058 SkOpAngle::IncludeType includeType) {
1249 const SkOpSegment* baseSegment = baseAngle->segment(); 1059 const SkOpSegment* baseSegment = baseAngle->segment();
1250 int sumMiWinding = baseSegment->updateWinding(baseAngle); 1060 int sumMiWinding = baseSegment->updateWinding(baseAngle);
1251 int sumSuWinding; 1061 int sumSuWinding;
1252 bool binary = includeType >= SkOpAngle::kBinarySingle; 1062 bool binary = includeType >= SkOpAngle::kBinarySingle;
1253 if (binary) { 1063 if (binary) {
1254 sumSuWinding = baseSegment->updateOppWinding(baseAngle); 1064 sumSuWinding = baseSegment->updateOppWinding(baseAngle);
1255 if (baseSegment->operand()) { 1065 if (baseSegment->operand()) {
1256 SkTSwap<int>(sumMiWinding, sumSuWinding); 1066 SkTSwap<int>(sumMiWinding, sumSuWinding);
1257 } 1067 }
1258 } 1068 }
1259 SkOpSegment* nextSegment = nextAngle->segment(); 1069 SkOpSegment* nextSegment = nextAngle->segment();
1260 int maxWinding, sumWinding; 1070 int maxWinding, sumWinding;
1261 SkOpSpan* last; 1071 SkOpSpan* last;
1262 if (binary) { 1072 if (binary) {
1263 int oppMaxWinding, oppSumWinding; 1073 int oppMaxWinding, oppSumWinding;
1264 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding, 1074 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding,
1265 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSum Winding); 1075 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSum Winding);
1266 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding, 1076 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding,
1267 true, nextAngle); 1077 nextAngle);
1268 } else { 1078 } else {
1269 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding, 1079 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding,
1270 &maxWinding, &sumWinding); 1080 &maxWinding, &sumWinding);
1271 last = nextSegment->markAngle(maxWinding, sumWinding, true, nextAngle); 1081 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
1272 } 1082 }
1273 nextAngle->setLastMarked(last); 1083 nextAngle->setLastMarked(last);
1274 } 1084 }
1275 1085
1276 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT, 1086 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT,
1277 bool* hitSomething, double mid, bool opp, bool cur rent) const { 1087 bool* hitSomething, double mid, bool opp, bool cur rent) const {
1278 SkScalar bottom = fBounds.fBottom; 1088 SkScalar bottom = fBounds.fBottom;
1279 int bestTIndex = -1; 1089 int bestTIndex = -1;
1280 if (bottom <= *bestY) { 1090 if (bottom <= *bestY) {
1281 return bestTIndex; 1091 return bestTIndex;
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 goto nextPeekIndex; 1272 goto nextPeekIndex;
1463 } 1273 }
1464 double midT = (tSpan.fOtherT + matchT) / 2; 1274 double midT = (tSpan.fOtherT + matchT) / 2;
1465 if (match->betweenPoints(midT, tSpan.fPt, peekSpan.fPt)) { 1275 if (match->betweenPoints(midT, tSpan.fPt, peekSpan.fPt)) {
1466 goto nextPeekIndex; 1276 goto nextPeekIndex;
1467 } 1277 }
1468 } 1278 }
1469 } 1279 }
1470 if (missingSpans.count() > 0) { 1280 if (missingSpans.count() > 0) {
1471 const MissingSpan& lastMissing = missingSpans.back(); 1281 const MissingSpan& lastMissing = missingSpans.back();
1472 if (lastMissing.fCommand == MissingSpan::kAddMissing 1282 if (lastMissing.fT == t
1473 && lastMissing.fT == t
1474 && lastMissing.fOther == match 1283 && lastMissing.fOther == match
1475 && lastMissing.fOtherT == matchT) { 1284 && lastMissing.fOtherT == matchT) {
1476 SkASSERT(lastMissing.fPt == peekSpan.fPt); 1285 SkASSERT(lastMissing.fPt == peekSpan.fPt);
1477 continue; 1286 continue;
1478 } 1287 }
1479 } 1288 }
1480 #if DEBUG_CHECK_ENDS 1289 #if DEBUG_CHECK_ENDS
1481 SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,% 1.9g)\n", 1290 SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,% 1.9g)\n",
1482 __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, p eekSpan.fPt.fY); 1291 __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, p eekSpan.fPt.fY);
1483 #endif 1292 #endif
1484 // this segment is missing a entry that the other contains 1293 // this segment is missing a entry that the other contains
1485 // remember so we can add the missing one and recompute the indices 1294 // remember so we can add the missing one and recompute the indices
1486 { 1295 {
1487 MissingSpan& missing = missingSpans.push_back(); 1296 MissingSpan& missing = missingSpans.push_back();
1488 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 1297 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
1489 missing.fCommand = MissingSpan::kAddMissing;
1490 missing.fT = t; 1298 missing.fT = t;
1491 missing.fOther = match; 1299 missing.fOther = match;
1492 missing.fOtherT = matchT; 1300 missing.fOtherT = matchT;
1493 missing.fPt = peekSpan.fPt; 1301 missing.fPt = peekSpan.fPt;
1494 } 1302 }
1495 break; 1303 break;
1496 nextPeekIndex: 1304 nextPeekIndex:
1497 ; 1305 ;
1498 } 1306 }
1499 } 1307 }
1500 if (missingSpans.count() == 0) { 1308 if (missingSpans.count() == 0) {
1501 debugValidate(); 1309 debugValidate();
1502 return; 1310 return;
1503 } 1311 }
1504 // if one end is near the other point, look for a coincident span
1505 for (int index = 0; index < count; ++index) {
1506 const SkOpSpan& span = fTs[index];
1507 if (span.fT > 0) {
1508 break;
1509 }
1510 const SkOpSpan& otherSpan = span.fOther->span(span.fOtherIndex);
1511 if (span.fNear) {
1512 SkASSERT(otherSpan.fPt == fPts[0]);
1513 adjustNear(0, span.fPt, &missingSpans);
1514 continue;
1515 }
1516 if (otherSpan.fNear) {
1517 SkASSERT(span.fPt == fPts[0]);
1518 adjustNear(0, otherSpan.fPt, &missingSpans);
1519 }
1520 }
1521 for (int index = count; --index >= 0; ) {
1522 const SkOpSpan& span = fTs[index];
1523 if (span.fT < 1) {
1524 break;
1525 }
1526 const SkOpSegment* other = span.fOther;
1527 if (span.fNear) {
1528 SkASSERT(other->ptAtT(span.fOtherT) == ptAtT(1));
1529 const SkPoint& otherPt = other->xyAtT(span.fOtherIndex);
1530 SkASSERT(otherPt != ptAtT(1));
1531 adjustNear(1, otherPt, &missingSpans);
1532 continue;
1533 }
1534 const SkOpSpan& otherSpan = other->span(span.fOtherIndex);
1535 if (otherSpan.fNear) {
1536 SkASSERT(otherSpan.fPt == ptAtT(1));
1537 SkPoint otherPt = other->ptAtT(span.fOtherT);
1538 SkASSERT(otherPt != ptAtT(1));
1539 adjustNear(1, otherPt, &missingSpans);
1540 }
1541 }
1542 debugValidate(); 1312 debugValidate();
1543 int missingCount = missingSpans.count(); 1313 int missingCount = missingSpans.count();
1544 for (int index = 0; index < missingCount; ++index) { 1314 for (int index = 0; index < missingCount; ++index) {
1545 MissingSpan& missing = missingSpans[index]; 1315 MissingSpan& missing = missingSpans[index];
1546 switch (missing.fCommand) { 1316 addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt );
1547 case MissingSpan::kNoAction:
1548 break;
1549 case MissingSpan::kAddMissing:
1550 addTPair(missing.fT, missing.fOther, missing.fOtherT, false, mis sing.fPt);
1551 break;
1552 case MissingSpan::kRemoveNear: {
1553 SkOpSegment* segment = missing.fSegment;
1554 int count = segment->count();
1555 for (int inner = 0; inner < count; ++inner) {
1556 const SkOpSpan& span = segment->span(inner);
1557 if (span.fT != missing.fT && span.fOther != missing.fOther) {
1558 continue;
1559 }
1560 SkASSERT(span.fNear);
1561 SkOpSegment* other = span.fOther;
1562 int otherCount = other->count();
1563 for (int otherIndex = 0; otherIndex < otherCount; ++otherInd ex) {
1564 const SkOpSpan& otherSpan = other->span(otherIndex);
1565 if (otherSpan.fT == span.fOtherT && otherSpan.fOther == segment
1566 && otherSpan.fOtherT == span.fT) {
1567 if (otherSpan.fDone) {
1568 other->fDoneSpans--;
1569 }
1570 other->fTs.remove(otherIndex);
1571 // FIXME: remove may leave a tiny dangling -- recomp ute tiny w/index
1572 break;
1573 }
1574 }
1575 if (span.fDone) {
1576 segment->fDoneSpans--;
1577 }
1578 segment->fTs.remove(inner);
1579 // FIXME: remove may leave a tiny dangling -- recompute tiny w/index
1580 break;
1581 }
1582 break;
1583 }
1584 case MissingSpan::kZeroSpan: {
1585 SkOpSegment* segment = missing.fSegment;
1586 int count = segment->count();
1587 for (int inner = 0; inner < count; ++inner) {
1588 SkOpSpan& span = segment->fTs[inner];
1589 if (span.fT < missing.fT) {
1590 continue;
1591 }
1592 if (span.fT >= missing.fEndT) {
1593 break;
1594 }
1595 span.fWindValue = span.fOppValue = 0;
1596 if (!span.fDone) {
1597 span.fDone = true;
1598 ++segment->fDoneSpans;
1599 }
1600 }
1601 break;
1602 }
1603 }
1604 } 1317 }
1605 fixOtherTIndex(); 1318 fixOtherTIndex();
1606 // OPTIMIZATION: this may fix indices more than once. Build an array of uniq ue segments to 1319 // OPTIMIZATION: this may fix indices more than once. Build an array of uniq ue segments to
1607 // avoid this 1320 // avoid this
1608 for (int index = 0; index < missingCount; ++index) { 1321 for (int index = 0; index < missingCount; ++index) {
1609 const MissingSpan& missing = missingSpans[index]; 1322 missingSpans[index].fOther->fixOtherTIndex();
1610 switch (missing.fCommand) {
1611 case MissingSpan::kNoAction:
1612 break;
1613 case MissingSpan::kAddMissing:
1614 missing.fOther->fixOtherTIndex();
1615 break;
1616 case MissingSpan::kRemoveNear:
1617 missing.fSegment->fixOtherTIndex();
1618 missing.fOther->fixOtherTIndex();
1619 break;
1620 case MissingSpan::kZeroSpan:
1621 break;
1622 }
1623 } 1323 }
1624 debugValidate(); 1324 debugValidate();
1625 } 1325 }
1626 1326
1627 bool SkOpSegment::checkSmall(int index) const { 1327 bool SkOpSegment::checkSmall(int index) const {
1628 if (fTs[index].fSmall) { 1328 if (fTs[index].fSmall) {
1629 return true; 1329 return true;
1630 } 1330 }
1631 double tBase = fTs[index].fT; 1331 double tBase = fTs[index].fT;
1632 while (index > 0 && precisely_negative(tBase - fTs[--index].fT)) 1332 while (index > 0 && precisely_negative(tBase - fTs[--index].fT))
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1680 continue; 1380 continue;
1681 } 1381 }
1682 #if DEBUG_CHECK_TINY 1382 #if DEBUG_CHECK_TINY
1683 SkDebugf("%s [%d] add coincidence [%d] [%d]\n", __FUNCTION__, fI D, 1383 SkDebugf("%s [%d] add coincidence [%d] [%d]\n", __FUNCTION__, fI D,
1684 thisOther->fID, nextOther->fID); 1384 thisOther->fID, nextOther->fID);
1685 #endif 1385 #endif
1686 // this segment is missing a entry that the other contains 1386 // this segment is missing a entry that the other contains
1687 // remember so we can add the missing one and recompute the indi ces 1387 // remember so we can add the missing one and recompute the indi ces
1688 MissingSpan& missing = missingSpans.push_back(); 1388 MissingSpan& missing = missingSpans.push_back();
1689 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 1389 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
1690 missing.fCommand = MissingSpan::kAddMissing;
1691 missing.fSegment = thisOther; 1390 missing.fSegment = thisOther;
1692 missing.fT = thisSpan->fOtherT; 1391 missing.fT = thisSpan->fOtherT;
1693 missing.fOther = nextOther; 1392 missing.fOther = nextOther;
1694 missing.fOtherT = nextSpan->fOtherT; 1393 missing.fOtherT = nextSpan->fOtherT;
1695 missing.fPt = thisSpan->fPt; 1394 missing.fPt = thisSpan->fPt;
1696 } 1395 }
1697 } 1396 }
1698 } 1397 }
1699 int missingCount = missingSpans.count(); 1398 int missingCount = missingSpans.count();
1700 if (!missingCount) { 1399 if (!missingCount) {
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after
2399 2098
2400 bool SkOpSegment::isTiny(int index) const { 2099 bool SkOpSegment::isTiny(int index) const {
2401 return fTs[index].fTiny; 2100 return fTs[index].fTiny;
2402 } 2101 }
2403 2102
2404 // look pair of active edges going away from coincident edge 2103 // look pair of active edges going away from coincident edge
2405 // one of them should be the continuation of other 2104 // one of them should be the continuation of other
2406 // if both are active, look to see if they both the connect to another coinciden t pair 2105 // if both are active, look to see if they both the connect to another coinciden t pair
2407 // if one at least one is a line, then make the pair coincident 2106 // if one at least one is a line, then make the pair coincident
2408 // if neither is a line, test for coincidence 2107 // if neither is a line, test for coincidence
2409 bool SkOpSegment::joinCoincidence(bool end, SkOpSegment* other, double otherT, i nt step, 2108 bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, int step,
2410 bool cancel) { 2109 bool cancel) {
2411 int otherTIndex = other->findT(otherT, this); 2110 int otherTIndex = other->findT(otherT, this);
2412 int next = other->nextExactSpan(otherTIndex, step); 2111 int next = other->nextExactSpan(otherTIndex, step);
2413 int otherMin = SkTMin(otherTIndex, next); 2112 int otherMin = SkTMin(otherTIndex, next);
2414 int otherWind = other->span(otherMin).fWindValue; 2113 int otherWind = other->span(otherMin).fWindValue;
2415 if (otherWind == 0) { 2114 if (otherWind == 0) {
2416 return false; 2115 return false;
2417 } 2116 }
2418 SkASSERT(next >= 0); 2117 SkASSERT(next >= 0);
2419 if (end) { 2118 int tIndex = 0;
2420 int tIndex = count() - 1; 2119 do {
2421 do { 2120 SkOpSpan* test = &fTs[tIndex];
2422 SkOpSpan* test = &fTs[tIndex]; 2121 SkASSERT(test->fT == 0);
2423 SkASSERT(test->fT == 1); 2122 if (test->fOther == other || test->fOtherT != 1) {
2424 if (test->fOther == other || test->fOtherT != 0) { 2123 continue;
2425 continue; 2124 }
2125 SkPoint startPt, endPt;
2126 double endT;
2127 if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) {
2128 SkOpSegment* match = test->fOther;
2129 if (cancel) {
2130 match->addTCancel(startPt, endPt, other);
2131 } else {
2132 match->addTCoincident(startPt, endPt, endT, other);
2426 } 2133 }
2427 SkPoint startPt, endPt; 2134 return true;
2428 double endT; 2135 }
2429 if (findCoincidentMatch(test, other, otherTIndex, next, step, &start Pt, &endPt, &endT)) { 2136 } while (fTs[++tIndex].fT == 0);
2430 SkOpSegment* match = test->fOther;
2431 if (cancel) {
2432 match->addTCancel(startPt, endPt, other);
2433 } else {
2434 match->addTCoincident(startPt, endPt, endT, other);
2435 }
2436 return true;
2437 }
2438 } while (fTs[--tIndex].fT == 1);
2439 } else {
2440 int tIndex = 0;
2441 do {
2442 SkOpSpan* test = &fTs[tIndex];
2443 SkASSERT(test->fT == 0);
2444 if (test->fOther == other || test->fOtherT != 1) {
2445 continue;
2446 }
2447 SkPoint startPt, endPt;
2448 double endT;
2449 if (findCoincidentMatch(test, other, otherTIndex, next, step, &start Pt, &endPt, &endT)) {
2450 SkOpSegment* match = test->fOther;
2451 if (cancel) {
2452 match->addTCancel(startPt, endPt, other);
2453 } else {
2454 match->addTCoincident(startPt, endPt, endT, other);
2455 }
2456 return true;
2457 }
2458 } while (fTs[++tIndex].fT == 0);
2459 }
2460 return false; 2137 return false;
2461 } 2138 }
2462 2139
2463 // this span is excluded by the winding rule -- chase the ends 2140 // this span is excluded by the winding rule -- chase the ends
2464 // as long as they are unambiguous to mark connections as done 2141 // as long as they are unambiguous to mark connections as done
2465 // and give them the same winding value 2142 // and give them the same winding value
2466 SkOpSpan* SkOpSegment::markAndChaseDone(int index, int endIndex, int winding) {
2467 int step = SkSign32(endIndex - index);
2468 int min = SkMin32(index, endIndex);
2469 markDone(min, winding);
2470 SkOpSpan* last;
2471 SkOpSegment* other = this;
2472 while ((other = other->nextChase(&index, step, &min, &last))) {
2473 other->markDone(min, winding);
2474 }
2475 return last;
2476 }
2477
2478 SkOpSpan* SkOpSegment::markAndChaseDoneBinary(const SkOpAngle* angle, int windin g, int oppWinding) {
2479 int index = angle->start();
2480 int endIndex = angle->end();
2481 int step = SkSign32(endIndex - index);
2482 int min = SkMin32(index, endIndex);
2483 markDoneBinary(min, winding, oppWinding);
2484 SkOpSpan* last;
2485 SkOpSegment* other = this;
2486 while ((other = other->nextChase(&index, step, &min, &last))) {
2487 other->markDoneBinary(min, winding, oppWinding);
2488 }
2489 return last;
2490 }
2491 2143
2492 SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) { 2144 SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) {
2493 int step = SkSign32(endIndex - index); 2145 int step = SkSign32(endIndex - index);
2494 int min = SkMin32(index, endIndex); 2146 int min = SkMin32(index, endIndex);
2495 markDoneBinary(min); 2147 markDoneBinary(min);
2496 SkOpSpan* last; 2148 SkOpSpan* last;
2497 SkOpSegment* other = this; 2149 SkOpSegment* other = this;
2498 while ((other = other->nextChase(&index, step, &min, &last))) { 2150 while ((other = other->nextChase(&index, step, &min, &last))) {
2499 if (other->done()) { 2151 if (other->done()) {
2500 return NULL; 2152 return NULL;
(...skipping 11 matching lines...) Expand all
2512 SkOpSegment* other = this; 2164 SkOpSegment* other = this;
2513 while ((other = other->nextChase(&index, step, &min, &last))) { 2165 while ((other = other->nextChase(&index, step, &min, &last))) {
2514 if (other->done()) { 2166 if (other->done()) {
2515 return NULL; 2167 return NULL;
2516 } 2168 }
2517 other->markDoneUnary(min); 2169 other->markDoneUnary(min);
2518 } 2170 }
2519 return last; 2171 return last;
2520 } 2172 }
2521 2173
2522 SkOpSpan* SkOpSegment::markAndChaseDoneUnary(const SkOpAngle* angle, int winding ) {
2523 int index = angle->start();
2524 int endIndex = angle->end();
2525 return markAndChaseDone(index, endIndex, winding);
2526 }
2527
2528 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, const int win ding) { 2174 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, const int win ding) {
2529 int index = angle->start(); 2175 int index = angle->start();
2530 int endIndex = angle->end(); 2176 int endIndex = angle->end();
2531 int step = SkSign32(endIndex - index); 2177 int step = SkSign32(endIndex - index);
2532 int min = SkMin32(index, endIndex); 2178 int min = SkMin32(index, endIndex);
2533 markWinding(min, winding); 2179 markWinding(min, winding);
2534 SkOpSpan* last; 2180 SkOpSpan* last;
2535 SkOpSegment* other = this; 2181 SkOpSegment* other = this;
2536 while ((other = other->nextChase(&index, step, &min, &last))) { 2182 while ((other = other->nextChase(&index, step, &min, &last))) {
2537 if (other->fTs[min].fWindSum != SK_MinS32) { 2183 if (other->fTs[min].fWindSum != SK_MinS32) {
(...skipping 20 matching lines...) Expand all
2558 } 2204 }
2559 return last; 2205 return last;
2560 } 2206 }
2561 2207
2562 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding) { 2208 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding) {
2563 int start = angle->start(); 2209 int start = angle->start();
2564 int end = angle->end(); 2210 int end = angle->end();
2565 return markAndChaseWinding(start, end, winding, oppWinding); 2211 return markAndChaseWinding(start, end, winding, oppWinding);
2566 } 2212 }
2567 2213
2568 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, bool activeAngl e, 2214 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle * angle) {
2569 const SkOpAngle* angle) {
2570 SkASSERT(angle->segment() == this); 2215 SkASSERT(angle->segment() == this);
2571 if (UseInnerWinding(maxWinding, sumWinding)) { 2216 if (UseInnerWinding(maxWinding, sumWinding)) {
2572 maxWinding = sumWinding; 2217 maxWinding = sumWinding;
2573 } 2218 }
2574 SkOpSpan* last; 2219 SkOpSpan* last = markAndChaseWinding(angle, maxWinding);
2575 if (activeAngle) {
2576 last = markAndChaseWinding(angle, maxWinding);
2577 } else {
2578 last = markAndChaseDoneUnary(angle, maxWinding);
2579 }
2580 #if DEBUG_WINDING 2220 #if DEBUG_WINDING
2581 if (last) { 2221 if (last) {
2582 SkDebugf("%s last id=%d windSum=", __FUNCTION__, 2222 SkDebugf("%s last id=%d windSum=", __FUNCTION__,
2583 last->fOther->fTs[last->fOtherIndex].fOther->debugID()); 2223 last->fOther->fTs[last->fOtherIndex].fOther->debugID());
2584 SkPathOpsDebug::WindingPrintf(last->fWindSum); 2224 SkPathOpsDebug::WindingPrintf(last->fWindSum);
2585 SkDebugf(" small=%d\n", last->fSmall); 2225 SkDebugf(" small=%d\n", last->fSmall);
2586 } 2226 }
2587 #endif 2227 #endif
2588 return last; 2228 return last;
2589 } 2229 }
2590 2230
2591 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi ng, 2231 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi ng,
2592 int oppSumWinding, bool activeAngle, const SkOp Angle* angle) { 2232 int oppSumWinding, const SkOpAngle* angle) {
2593 SkASSERT(angle->segment() == this); 2233 SkASSERT(angle->segment() == this);
2594 if (UseInnerWinding(maxWinding, sumWinding)) { 2234 if (UseInnerWinding(maxWinding, sumWinding)) {
2595 maxWinding = sumWinding; 2235 maxWinding = sumWinding;
2596 } 2236 }
2597 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumW inding)) { 2237 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumW inding)) {
2598 oppMaxWinding = oppSumWinding; 2238 oppMaxWinding = oppSumWinding;
2599 } 2239 }
2600 SkOpSpan* last; 2240 SkOpSpan* last = markAndChaseWinding(angle, maxWinding, oppMaxWinding);
2601 if (activeAngle) {
2602 last = markAndChaseWinding(angle, maxWinding, oppMaxWinding);
2603 } else {
2604 last = markAndChaseDoneBinary(angle, maxWinding, oppMaxWinding);
2605 }
2606 #if DEBUG_WINDING 2241 #if DEBUG_WINDING
2607 if (last) { 2242 if (last) {
2608 SkDebugf("%s last id=%d windSum=", __FUNCTION__, 2243 SkDebugf("%s last id=%d windSum=", __FUNCTION__,
2609 last->fOther->fTs[last->fOtherIndex].fOther->debugID()); 2244 last->fOther->fTs[last->fOtherIndex].fOther->debugID());
2610 SkPathOpsDebug::WindingPrintf(last->fWindSum); 2245 SkPathOpsDebug::WindingPrintf(last->fWindSum);
2611 SkDebugf(" small=%d\n", last->fSmall); 2246 SkDebugf(" small=%d\n", last->fSmall);
2612 } 2247 }
2613 #endif 2248 #endif
2614 return last; 2249 return last;
2615 } 2250 }
2616 2251
2617 // FIXME: this should also mark spans with equal (x,y) 2252 // FIXME: this should also mark spans with equal (x,y)
2618 // This may be called when the segment is already marked done. While this 2253 // This may be called when the segment is already marked done. While this
2619 // wastes time, it shouldn't do any more than spin through the T spans. 2254 // wastes time, it shouldn't do any more than spin through the T spans.
2620 // OPTIMIZATION: abort on first done found (assuming that this code is 2255 // OPTIMIZATION: abort on first done found (assuming that this code is
2621 // always called to mark segments done). 2256 // always called to mark segments done).
2622 void SkOpSegment::markDone(int index, int winding) { 2257 void SkOpSegment::markDone(int index, int winding) {
2623 // SkASSERT(!done()); 2258 // SkASSERT(!done());
2624 SkASSERT(winding); 2259 SkASSERT(winding);
2625 double referenceT = fTs[index].fT; 2260 double referenceT = fTs[index].fT;
2626 int lesser = index; 2261 int lesser = index;
2627 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 2262 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2628 markOneDone(__FUNCTION__, lesser, winding); 2263 markOneDone(__FUNCTION__, lesser, winding);
2629 } 2264 }
2630 do { 2265 do {
2631 markOneDone(__FUNCTION__, index, winding); 2266 markOneDone(__FUNCTION__, index, winding);
2632 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT)); 2267 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
2633 } 2268 }
2634 2269
2635 void SkOpSegment::markDoneBinary(int index, int winding, int oppWinding) {
2636 // SkASSERT(!done());
2637 SkASSERT(winding || oppWinding);
2638 double referenceT = fTs[index].fT;
2639 int lesser = index;
2640 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2641 markOneDoneBinary(__FUNCTION__, lesser, winding, oppWinding);
2642 }
2643 do {
2644 markOneDoneBinary(__FUNCTION__, index, winding, oppWinding);
2645 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
2646 }
2647
2648 void SkOpSegment::markDoneBinary(int index) { 2270 void SkOpSegment::markDoneBinary(int index) {
2649 double referenceT = fTs[index].fT; 2271 double referenceT = fTs[index].fT;
2650 int lesser = index; 2272 int lesser = index;
2651 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 2273 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2652 markOneDoneBinary(__FUNCTION__, lesser); 2274 markOneDoneBinary(__FUNCTION__, lesser);
2653 } 2275 }
2654 do { 2276 do {
2655 markOneDoneBinary(__FUNCTION__, index); 2277 markOneDoneBinary(__FUNCTION__, index);
2656 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT)); 2278 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
2657 } 2279 }
(...skipping 20 matching lines...) Expand all
2678 2300
2679 void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) { 2301 void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) {
2680 SkOpSpan* span = verifyOneWinding(funName, tIndex); 2302 SkOpSpan* span = verifyOneWinding(funName, tIndex);
2681 if (!span) { 2303 if (!span) {
2682 return; 2304 return;
2683 } 2305 }
2684 span->fDone = true; 2306 span->fDone = true;
2685 fDoneSpans++; 2307 fDoneSpans++;
2686 } 2308 }
2687 2309
2688 void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex, int winding , int oppWinding) {
2689 SkOpSpan* span = markOneWinding(funName, tIndex, winding, oppWinding);
2690 if (!span) {
2691 return;
2692 }
2693 span->fDone = true;
2694 fDoneSpans++;
2695 }
2696
2697 void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) { 2310 void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) {
2698 SkOpSpan* span = verifyOneWindingU(funName, tIndex); 2311 SkOpSpan* span = verifyOneWindingU(funName, tIndex);
2699 if (!span) { 2312 if (!span) {
2700 return; 2313 return;
2701 } 2314 }
2702 span->fDone = true; 2315 span->fDone = true;
2703 fDoneSpans++; 2316 fDoneSpans++;
2704 } 2317 }
2705 2318
2706 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng) { 2319 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2783 } 2396 }
2784 2397
2785 SkOpSpan* SkOpSegment::verifyOneWinding(const char* funName, int tIndex) { 2398 SkOpSpan* SkOpSegment::verifyOneWinding(const char* funName, int tIndex) {
2786 SkOpSpan& span = fTs[tIndex]; 2399 SkOpSpan& span = fTs[tIndex];
2787 if (span.fDone) { 2400 if (span.fDone) {
2788 return NULL; 2401 return NULL;
2789 } 2402 }
2790 #if DEBUG_MARK_DONE 2403 #if DEBUG_MARK_DONE
2791 debugShowNewWinding(funName, span, span.fWindSum, span.fOppSum); 2404 debugShowNewWinding(funName, span, span.fWindSum, span.fOppSum);
2792 #endif 2405 #endif
2793 SkASSERT(span.fWindSum != SK_MinS32); 2406 // If the prior angle in the sort is unorderable, the winding sum may not be com putable.
2794 SkASSERT(span.fOppSum != SK_MinS32); 2407 // To enable the assert, the 'prior is unorderable' state could be
2408 // piped down to this test, but not sure it's worth it.
2409 // (Once the sort order is stored in the span, this test may be feasible.)
2410 // SkASSERT(span.fWindSum != SK_MinS32);
2411 // SkASSERT(span.fOppSum != SK_MinS32);
2795 return &span; 2412 return &span;
2796 } 2413 }
2797 2414
2798 SkOpSpan* SkOpSegment::verifyOneWindingU(const char* funName, int tIndex) { 2415 SkOpSpan* SkOpSegment::verifyOneWindingU(const char* funName, int tIndex) {
2799 SkOpSpan& span = fTs[tIndex]; 2416 SkOpSpan& span = fTs[tIndex];
2800 if (span.fDone) { 2417 if (span.fDone) {
2801 return NULL; 2418 return NULL;
2802 } 2419 }
2803 #if DEBUG_MARK_DONE 2420 #if DEBUG_MARK_DONE
2804 debugShowNewWinding(funName, span, span.fWindSum); 2421 debugShowNewWinding(funName, span, span.fWindSum);
2805 #endif 2422 #endif
2806 SkASSERT(span.fWindSum != SK_MinS32); 2423 // If the prior angle in the sort is unorderable, the winding sum may not be com putable.
2424 // To enable the assert, the 'prior is unorderable' state could be
2425 // piped down to this test, but not sure it's worth it.
2426 // (Once the sort order is stored in the span, this test may be feasible.)
2427 // SkASSERT(span.fWindSum != SK_MinS32);
2807 return &span; 2428 return &span;
2808 } 2429 }
2809 2430
2810 // note that just because a span has one end that is unsortable, that's 2431 // note that just because a span has one end that is unsortable, that's
2811 // not enough to mark it done. The other end may be sortable, allowing the 2432 // not enough to mark it done. The other end may be sortable, allowing the
2812 // span to be added. 2433 // span to be added.
2813 // FIXME: if abs(start - end) > 1, mark intermediates as unsortable on both ends 2434 // FIXME: if abs(start - end) > 1, mark intermediates as unsortable on both ends
2814 void SkOpSegment::markUnsortable(int start, int end) { 2435 void SkOpSegment::markUnsortable(int start, int end) {
2815 SkOpSpan* span = &fTs[start]; 2436 SkOpSpan* span = &fTs[start];
2816 if (start < end) { 2437 if (start < end) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2884 SkOpSpan& newSpan = fTs[tIndex]; 2505 SkOpSpan& newSpan = fTs[tIndex];
2885 newSpan.fWindValue = nextDoorWind; 2506 newSpan.fWindValue = nextDoorWind;
2886 newSpan.fOppValue = nextOppWind; 2507 newSpan.fOppValue = nextOppWind;
2887 if (!nextDoorWind && !nextOppWind && !newSpan.fDone) { 2508 if (!nextDoorWind && !nextOppWind && !newSpan.fDone) {
2888 newSpan.fDone = true; 2509 newSpan.fDone = true;
2889 ++fDoneSpans; 2510 ++fDoneSpans;
2890 } 2511 }
2891 } 2512 }
2892 } 2513 }
2893 2514
2894 double SkOpSegment::missingNear(double t, const SkOpSegment* other, const SkPoin t& startPt,
2895 const SkPoint& endPt) const {
2896 int count = this->count();
2897 for (int index = 0; index < count; ++index) {
2898 const SkOpSpan& span = this->span(index);
2899 if (span.fOther == other && span.fPt == startPt) {
2900 double midT = (t + span.fT) / 2;
2901 if (betweenPoints(midT, startPt, endPt)) {
2902 return span.fT;
2903 }
2904 }
2905 }
2906 return -1;
2907 }
2908
2909 // return span if when chasing, two or more radiating spans are not done 2515 // return span if when chasing, two or more radiating spans are not done
2910 // OPTIMIZATION: ? multiple spans is detected when there is only one valid 2516 // OPTIMIZATION: ? multiple spans is detected when there is only one valid
2911 // candidate and the remaining spans have windValue == 0 (canceled by 2517 // candidate and the remaining spans have windValue == 0 (canceled by
2912 // coincidence). The coincident edges could either be removed altogether, 2518 // coincidence). The coincident edges could either be removed altogether,
2913 // or this code could be more complicated in detecting this case. Worth it? 2519 // or this code could be more complicated in detecting this case. Worth it?
2914 bool SkOpSegment::multipleSpans(int end) const { 2520 bool SkOpSegment::multipleSpans(int end) const {
2915 return end > 0 && end < fTs.count() - 1; 2521 return end > 0 && end < fTs.count() - 1;
2916 } 2522 }
2917 2523
2918 bool SkOpSegment::nextCandidate(int* start, int* end) const { 2524 bool SkOpSegment::nextCandidate(int* start, int* end) const {
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
3323 return winding; 2929 return winding;
3324 } 2930 }
3325 2931
3326 int SkOpSegment::windSum(const SkOpAngle* angle) const { 2932 int SkOpSegment::windSum(const SkOpAngle* angle) const {
3327 int start = angle->start(); 2933 int start = angle->start();
3328 int end = angle->end(); 2934 int end = angle->end();
3329 int index = SkMin32(start, end); 2935 int index = SkMin32(start, end);
3330 return windSum(index); 2936 return windSum(index);
3331 } 2937 }
3332 2938
3333 int SkOpSegment::windValue(const SkOpAngle* angle) const {
3334 int start = angle->start();
3335 int end = angle->end();
3336 int index = SkMin32(start, end);
3337 return windValue(index);
3338 }
3339
3340 int SkOpSegment::windValueAt(double t) const {
3341 int count = fTs.count();
3342 for (int index = 0; index < count; ++index) {
3343 if (fTs[index].fT == t) {
3344 return fTs[index].fWindValue;
3345 }
3346 }
3347 SkASSERT(0);
3348 return 0;
3349 }
3350
3351 void SkOpSegment::zeroSpan(SkOpSpan* span) { 2939 void SkOpSegment::zeroSpan(SkOpSpan* span) {
3352 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 2940 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
3353 span->fWindValue = 0; 2941 span->fWindValue = 0;
3354 span->fOppValue = 0; 2942 span->fOppValue = 0;
3355 if (span->fTiny || span->fSmall) { 2943 if (span->fTiny || span->fSmall) {
3356 return; 2944 return;
3357 } 2945 }
3358 SkASSERT(!span->fDone); 2946 SkASSERT(!span->fDone);
3359 span->fDone = true; 2947 span->fDone = true;
3360 ++fDoneSpans; 2948 ++fDoneSpans;
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
3731 3319
3732 void SkOpSegment::dumpSpans() const { 3320 void SkOpSegment::dumpSpans() const {
3733 int count = this->count(); 3321 int count = this->count();
3734 for (int index = 0; index < count; ++index) { 3322 for (int index = 0; index < count; ++index) {
3735 const SkOpSpan& span = this->span(index); 3323 const SkOpSpan& span = this->span(index);
3736 SkDebugf("[%d] ", index); 3324 SkDebugf("[%d] ", index);
3737 span.dump(); 3325 span.dump();
3738 } 3326 }
3739 } 3327 }
3740 #endif 3328 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698