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

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

Issue 633393002: harden pathops for pathological test (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: exclude new test that asserts in debug Created 6 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
« 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 "SkOpContour.h" 8 #include "SkOpContour.h"
9 #include "SkOpSegment.h" 9 #include "SkOpSegment.h"
10 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 } 153 }
154 next: 154 next:
155 lastDone = span.fDone; 155 lastDone = span.fDone;
156 } 156 }
157 return topPt; 157 return topPt;
158 } 158 }
159 159
160 bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask , SkPathOp op) { 160 bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask , SkPathOp op) {
161 int sumMiWinding = updateWinding(endIndex, index); 161 int sumMiWinding = updateWinding(endIndex, index);
162 int sumSuWinding = updateOppWinding(endIndex, index); 162 int sumSuWinding = updateOppWinding(endIndex, index);
163 #if DEBUG_LIMIT_WIND_SUM
164 SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM);
165 SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM);
166 #endif
163 if (fOperand) { 167 if (fOperand) {
164 SkTSwap<int>(sumMiWinding, sumSuWinding); 168 SkTSwap<int>(sumMiWinding, sumSuWinding);
165 } 169 }
166 return activeOp(xorMiMask, xorSuMask, index, endIndex, op, &sumMiWinding, &s umSuWinding); 170 return activeOp(xorMiMask, xorSuMask, index, endIndex, op, &sumMiWinding, &s umSuWinding);
167 } 171 }
168 172
169 bool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, int index, int endIndex , SkPathOp op, 173 bool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, int index, int endIndex , SkPathOp op,
170 int* sumMiWinding, int* sumSuWinding) { 174 int* sumMiWinding, int* sumSuWinding) {
171 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; 175 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
172 setUpWindings(index, endIndex, sumMiWinding, sumSuWinding, 176 setUpWindings(index, endIndex, sumMiWinding, sumSuWinding,
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 span->fChased = false; 614 span->fChased = false;
611 span->fCoincident = false; 615 span->fCoincident = false;
612 span->fLoop = false; 616 span->fLoop = false;
613 span->fNear = false; 617 span->fNear = false;
614 span->fMultiple = false; 618 span->fMultiple = false;
615 span->fSmall = false; 619 span->fSmall = false;
616 span->fTiny = false; 620 span->fTiny = false;
617 if ((span->fDone = newT == 1)) { 621 if ((span->fDone = newT == 1)) {
618 ++fDoneSpans; 622 ++fDoneSpans;
619 } 623 }
624 setSpanFlags(pt, newT, span);
625 return insertedAt;
626 }
627
628 void SkOpSegment::setSpanFlags(const SkPoint& pt, double newT, SkOpSpan* span) {
620 int less = -1; 629 int less = -1;
621 // FIXME: note that this relies on spans being a continguous array 630 // FIXME: note that this relies on spans being a continguous array
622 // find range of spans with nearly the same point as this one 631 // find range of spans with nearly the same point as this one
623 // FIXME: SkDPoint::ApproximatelyEqual is better but breaks tests at the mom ent 632 // FIXME: SkDPoint::ApproximatelyEqual is better but breaks tests at the mom ent
624 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) { 633 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) {
625 if (fVerb == SkPath::kCubic_Verb) { 634 if (fVerb == SkPath::kCubic_Verb) {
626 double tInterval = newT - span[less].fT; 635 double tInterval = newT - span[less].fT;
627 double tMid = newT - tInterval / 2; 636 double tMid = newT - tInterval / 2;
628 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); 637 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid);
629 if (!midPt.approximatelyEqual(xyAtT(span))) { 638 if (!midPt.approximatelyEqual(xyAtT(span))) {
(...skipping 15 matching lines...) Expand all
645 } 654 }
646 ++more; 655 ++more;
647 } 656 }
648 ++less; 657 ++less;
649 --more; 658 --more;
650 while (more - 1 > less && span[more].fPt == span[more - 1].fPt 659 while (more - 1 > less && span[more].fPt == span[more - 1].fPt
651 && span[more].fT == span[more - 1].fT) { 660 && span[more].fT == span[more - 1].fT) {
652 --more; 661 --more;
653 } 662 }
654 if (less == more) { 663 if (less == more) {
655 return insertedAt; 664 return;
656 } 665 }
657 if (precisely_negative(span[more].fT - span[less].fT)) { 666 if (precisely_negative(span[more].fT - span[less].fT)) {
658 return insertedAt; 667 return;
659 } 668 }
660 // if the total range of t values is big enough, mark all tiny 669 // if the total range of t values is big enough, mark all tiny
661 bool tiny = span[less].fPt == span[more].fPt; 670 bool tiny = span[less].fPt == span[more].fPt;
662 int index = less; 671 int index = less;
663 do { 672 do {
664 fSmall = span[index].fSmall = true; 673 fSmall = span[index].fSmall = true;
665 fTiny |= span[index].fTiny = tiny; 674 fTiny |= span[index].fTiny = tiny;
666 if (!span[index].fDone) { 675 if (!span[index].fDone) {
667 span[index].fDone = true; 676 span[index].fDone = true;
668 ++fDoneSpans; 677 ++fDoneSpans;
669 } 678 }
670 } while (++index < more); 679 } while (++index < more);
671 return insertedAt; 680 return;
681 }
682
683 void SkOpSegment::resetSpanFlags() {
684 fSmall = fTiny = false;
685 fDoneSpans = 0;
686 int start = 0;
687 int last = this->count() - 1;
688 do {
689 SkOpSpan* startSpan = &this->fTs[start];
690 double startT = startSpan->fT;
691 startSpan->fSmall = startSpan->fTiny = false; // sets range initial
692 bool terminus = startT == 1;
693 if ((startSpan->fDone = !startSpan->fWindValue | terminus)) {
694 ++fDoneSpans;
695 }
696 ++start; // range initial + 1
697 if (terminus) {
698 continue;
699 }
700 const SkPoint& pt = startSpan->fPt;
701 int end = start; // range initial + 1
702 while (end <= last) {
703 const SkOpSpan& endSpan = this->span(end);
704 if (!AlmostEqualUlps(endSpan.fPt, pt)) {
705 break;
706 }
707 if (fVerb == SkPath::kCubic_Verb) {
708 double tMid = (startSpan->fT + endSpan.fT) / 2;
709 SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid);
710 if (!midEndPt.approximatelyEqual(xyAtT(startSpan))) {
711 break;
712 }
713 }
714 ++end;
715 }
716 if (start == end) { // end == range final + 1
717 continue;
718 }
719 while (--end >= start) { // end == range final
720 const SkOpSpan& endSpan = this->span(end);
721 const SkOpSpan& priorSpan = this->span(end - 1);
722 if (endSpan.fPt != priorSpan.fPt || endSpan.fT != priorSpan.fT) {
723 break; // end == range final + 1
724 }
725 }
726 if (end < start) { // end == range final + 1
727 continue;
728 }
729 int index = start - 1; // index == range initial
730 start = end; // start = range final + 1
731 const SkOpSpan& nextSpan = this->span(end);
732 if (precisely_negative(nextSpan.fT - startSpan->fT)) {
733 while (++index < end) {
734 startSpan = &this->fTs[index];
735 startSpan->fSmall = startSpan->fTiny = false; // sets range ini tial + 1
736 if ((startSpan->fDone = !startSpan->fWindValue)) {
737 ++fDoneSpans;
738 }
739 }
740 continue;
741 }
742 if (!startSpan->fWindValue) {
743 --fDoneSpans; // added back below
744 }
745 bool tiny = nextSpan.fPt == startSpan->fPt;
746 do {
747 fSmall = startSpan->fSmall = true; // sets range initial
748 fTiny |= startSpan->fTiny = tiny;
749 startSpan->fDone = true;
750 ++fDoneSpans;
751 startSpan = &this->fTs[++index];
752 } while (index < end); // loop through tiny small range end (last)
753 } while (start <= last);
672 } 754 }
673 755
674 // set spans from start to end to decrement by one 756 // set spans from start to end to decrement by one
675 // note this walks other backwards 757 // note this walks other backwards
676 // FIXME: there's probably an edge case that can be constructed where 758 // FIXME: there's probably an edge case that can be constructed where
677 // two span in one segment are separated by float epsilon on one span but 759 // two span in one segment are separated by float epsilon on one span but
678 // not the other, if one segment is very small. For this 760 // not the other, if one segment is very small. For this
679 // case the counts asserted below may or may not be enough to separate the 761 // case the counts asserted below may or may not be enough to separate the
680 // spans. Even if the counts work out, what if the spans aren't correctly 762 // spans. Even if the counts work out, what if the spans aren't correctly
681 // sorted? It feels better in such a case to match the span's other span 763 // sorted? It feels better in such a case to match the span's other span
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 if (originalWindValue != oTst2->fWindValue) { 851 if (originalWindValue != oTst2->fWindValue) {
770 goto skipAdvanceOtherCancel; 852 goto skipAdvanceOtherCancel;
771 } 853 }
772 if (!oTst2->fWindValue) { 854 if (!oTst2->fWindValue) {
773 goto skipAdvanceOtherCancel; 855 goto skipAdvanceOtherCancel;
774 } 856 }
775 if (endPt == other->fTs[oIdx2].fPt) { 857 if (endPt == other->fTs[oIdx2].fPt) {
776 break; 858 break;
777 } 859 }
778 } 860 }
861 oFoundEnd = endPt == oTest->fPt;
779 do { 862 do {
780 SkASSERT(originalWindValue == oTest->fWindValue); 863 SkASSERT(originalWindValue == oTest->fWindValue);
781 if (decrement) { 864 if (decrement) {
782 if (binary && !bigger) { 865 if (binary && !bigger) {
783 oTest->fOppValue--; 866 oTest->fOppValue--;
784 } else { 867 } else {
785 other->decrementSpan(oTest); 868 other->decrementSpan(oTest);
786 } 869 }
787 } else if (track) { 870 } else if (track) {
788 TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt); 871 TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 } 1046 }
964 skipExactMatches: 1047 skipExactMatches:
965 ; 1048 ;
966 } 1049 }
967 ++index; 1050 ++index;
968 } 1051 }
969 } 1052 }
970 debugValidate(); 1053 debugValidate();
971 } 1054 }
972 1055
1056 void SkOpSegment::alignRange(int lower, int upper,
1057 const SkOpSegment* other, int oLower, int oUpper) {
1058 for (int oIndex = oLower; oIndex <= oUpper; ++oIndex) {
1059 const SkOpSpan& oSpan = other->span(oIndex);
1060 const SkOpSegment* oOther = oSpan.fOther;
1061 if (oOther == this) {
1062 continue;
1063 }
1064 SkOpSpan* matchSpan;
1065 int matchIndex;
1066 const SkOpSpan* refSpan;
1067 for (int iIndex = lower; iIndex <= upper; ++iIndex) {
1068 const SkOpSpan& iSpan = this->span(iIndex);
1069 const SkOpSegment* iOther = iSpan.fOther;
1070 if (iOther == other) {
1071 continue;
1072 }
1073 if (iOther == oOther) {
1074 goto nextI;
1075 }
1076 }
1077 {
1078 // oSpan does not have a match in this
1079 int iCount = this->count();
1080 const SkOpSpan* iMatch = NULL;
1081 double iMatchTDiff;
1082 matchIndex = -1;
1083 for (int iIndex = 0; iIndex < iCount; ++iIndex) {
1084 const SkOpSpan& iSpan = this->span(iIndex);
1085 const SkOpSegment* iOther = iSpan.fOther;
1086 if (iOther != oOther) {
1087 continue;
1088 }
1089 double testTDiff = fabs(iSpan.fOtherT - oSpan.fOtherT);
1090 if (!iMatch || testTDiff < iMatchTDiff) {
1091 matchIndex = iIndex;
1092 iMatch = &iSpan;
1093 iMatchTDiff = testTDiff;
1094 }
1095 }
1096 if (matchIndex < 0) {
1097 continue; // the entry is missing, & will be picked up later (F IXME: fix it here?)
1098 }
1099 matchSpan = &this->fTs[matchIndex];
1100 refSpan = &this->span(lower);
1101 if (!SkDPoint::ApproximatelyEqual(matchSpan->fPt, refSpan->fPt)) {
1102 goto nextI;
1103 }
1104 if (matchIndex != lower - 1 && matchIndex != upper + 1) {
1105 // the consecutive spans need to be rearranged to get the missin g one close
1106 continue; // FIXME: more work to do
1107 }
1108 }
1109 {
1110 this->fixOtherTIndex();
1111 SkScalar newT;
1112 if (matchSpan->fT != 0 && matchSpan->fT != 1) {
1113 newT = matchSpan->fT = refSpan->fT;
1114 matchSpan->fOther->fTs[matchSpan->fOtherIndex].fOtherT = refSpan ->fT;
1115 } else { // leave span at the start or end there and adjust the nei ghbors
1116 newT = matchSpan->fT;
1117 for (int iIndex = lower; iIndex <= upper; ++iIndex) {
1118 matchSpan = &this->fTs[iIndex];
1119 matchSpan->fT = newT;
1120 matchSpan->fOther->fTs[matchSpan->fOtherIndex].fOtherT = new T;
1121 }
1122 }
1123 this->resetSpanFlags(); // fix up small / tiny / done
1124 // align ts of other ranges with adjacent spans that match the align ed points
1125 lower = SkTMin(lower, matchIndex);
1126 while (lower > 0) {
1127 const SkOpSpan& span = this->span(lower - 1);
1128 if (span.fT != newT) {
1129 break;
1130 }
1131 --lower;
1132 }
1133 upper = SkTMax(upper, matchIndex);
1134 int last = this->count() - 1;
1135 while (upper < last) {
1136 const SkOpSpan& span = this->span(upper + 1);
1137 if (span.fT != newT) {
1138 break;
1139 }
1140 ++upper;
1141 }
1142 for (int iIndex = lower; iIndex <= upper; ++iIndex) {
1143 const SkOpSpan& span = this->span(iIndex);
1144 SkOpSegment* aOther = span.fOther;
1145 int aLower = span.fOtherIndex;
1146 SkScalar aT = span.fOtherT;
1147 bool aResetFlags = false;
1148 while (aLower > 0) {
1149 SkOpSpan* aSpan = &aOther->fTs[aLower - 1];
1150 for (int iIndex = lower; iIndex <= upper; ++iIndex) {
1151 if (aSpan->fPt == this->fTs[iIndex].fPt) {
1152 goto matchFound;
1153 }
1154 }
1155 break;
1156 matchFound:
1157 --aLower;
1158 }
1159 int aUpper = span.fOtherIndex;
1160 int aLast = aOther->count() - 1;
1161 while (aUpper < aLast) {
1162 SkOpSpan* aSpan = &aOther->fTs[aUpper + 1];
1163 for (int iIndex = lower; iIndex <= upper; ++iIndex) {
1164 if (aSpan->fPt == this->fTs[iIndex].fPt) {
1165 goto matchFound2;
1166 }
1167 }
1168 break;
1169 matchFound2:
1170 ++aUpper;
1171 }
1172 if (aOther->fTs[aLower].fT == 0) {
1173 aT = 0;
1174 } else if (aOther->fTs[aUpper].fT == 1) {
1175 aT = 1;
1176 }
1177 bool aFixed = false;
1178 for (int aIndex = aLower; aIndex <= aUpper; ++aIndex) {
1179 SkOpSpan* aSpan = &aOther->fTs[aIndex];
1180 if (aSpan->fT == aT) {
1181 continue;
1182 }
1183 SkASSERT(way_roughly_equal(aSpan->fT, aT));
1184 if (!aFixed) {
1185 aOther->fixOtherTIndex();
1186 aFixed = true;
1187 }
1188 aSpan->fT = aT;
1189 aSpan->fOther->fTs[aSpan->fOtherIndex].fOtherT = aT;
1190 aResetFlags = true;
1191 }
1192 if (aResetFlags) {
1193 aOther->resetSpanFlags();
1194 }
1195 }
1196 }
1197 nextI: ;
1198 }
1199 }
1200
973 void SkOpSegment::alignSpan(const SkPoint& newPt, double newT, const SkOpSegment * other, 1201 void SkOpSegment::alignSpan(const SkPoint& newPt, double newT, const SkOpSegment * other,
974 double otherT, const SkOpSegment* other2, SkOpSpan* oSpan, 1202 double otherT, const SkOpSegment* other2, SkOpSpan* oSpan,
975 SkTDArray<AlignedSpan>* alignedArray) { 1203 SkTDArray<AlignedSpan>* alignedArray) {
976 AlignedSpan* aligned = alignedArray->append(); 1204 AlignedSpan* aligned = alignedArray->append();
977 aligned->fOldPt = oSpan->fPt; 1205 aligned->fOldPt = oSpan->fPt;
978 aligned->fPt = newPt; 1206 aligned->fPt = newPt;
979 aligned->fOldT = oSpan->fT; 1207 aligned->fOldT = oSpan->fT;
980 aligned->fT = newT; 1208 aligned->fT = newT;
981 aligned->fSegment = this; // OPTIMIZE: may be unused, can remove 1209 aligned->fSegment = this; // OPTIMIZE: may be unused, can remove
982 aligned->fOther1 = other; 1210 aligned->fOther1 = other;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 void SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) { 1466 void SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) {
1239 do { 1467 do {
1240 zeroSpan(&fTs[index]); 1468 zeroSpan(&fTs[index]);
1241 } while (++index < endIndex); 1469 } while (++index < endIndex);
1242 } 1470 }
1243 1471
1244 // because of the order in which coincidences are resolved, this and other 1472 // because of the order in which coincidences are resolved, this and other
1245 // may not have the same intermediate points. Compute the corresponding 1473 // may not have the same intermediate points. Compute the corresponding
1246 // intermediate T values (using this as the master, other as the follower) 1474 // intermediate T values (using this as the master, other as the follower)
1247 // and walk other conditionally -- hoping that it catches up in the end 1475 // and walk other conditionally -- hoping that it catches up in the end
1248 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, 1476 bool SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr,
1249 SkTArray<SkPoint, true>* oOutsidePts) { 1477 SkTArray<SkPoint, true>* oOutsidePts, const SkPoint& oEndPt) {
1250 int oIndex = *oIndexPtr; 1478 int oIndex = *oIndexPtr;
1251 SkOpSpan* const oTest = &fTs[oIndex]; 1479 SkOpSpan* const oTest = &fTs[oIndex];
1252 SkOpSpan* oEnd = oTest; 1480 SkOpSpan* oEnd = oTest;
1253 const SkPoint& oStartPt = oTest->fPt; 1481 const SkPoint& oStartPt = oTest->fPt;
1254 double oStartT = oTest->fT; 1482 double oStartT = oTest->fT;
1255 #if 0 // FIXME : figure out what disabling this breaks 1483 #if 0 // FIXME : figure out what disabling this breaks
1256 const SkPoint& startPt = test.fPt; 1484 const SkPoint& startPt = test.fPt;
1257 // this is always true since oEnd == oTest && oStartPt == oTest->fPt -- find proper condition 1485 // this is always true since oEnd == oTest && oStartPt == oTest->fPt -- find proper condition
1258 if (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) { 1486 if (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) {
1259 TrackOutside(oOutsidePts, startPt); 1487 TrackOutside(oOutsidePts, startPt);
1260 } 1488 }
1261 #endif 1489 #endif
1490 bool foundEnd = false;
1262 while (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) { 1491 while (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) {
1492 foundEnd |= oEndPt == oEnd->fPt;
1263 zeroSpan(oEnd); 1493 zeroSpan(oEnd);
1264 oEnd = &fTs[++oIndex]; 1494 oEnd = &fTs[++oIndex];
1265 } 1495 }
1266 *oIndexPtr = oIndex; 1496 *oIndexPtr = oIndex;
1497 return foundEnd;
1267 } 1498 }
1268 1499
1269 // FIXME: need to test this case: 1500 // FIXME: need to test this case:
1270 // contourA has two segments that are coincident 1501 // contourA has two segments that are coincident
1271 // contourB has two segments that are coincident in the same place 1502 // contourB has two segments that are coincident in the same place
1272 // each ends up with +2/0 pairs for winding count 1503 // each ends up with +2/0 pairs for winding count
1273 // since logic below doesn't transfer count (only increments/decrements) can thi s be 1504 // since logic below doesn't transfer count (only increments/decrements) can thi s be
1274 // resolved to +4/0 ? 1505 // resolved to +4/0 ?
1275 1506
1276 // set spans from start to end to increment the greater by one and decrement 1507 // set spans from start to end to increment the greater by one and decrement
(...skipping 29 matching lines...) Expand all
1306 // paths with extreme data will fail this test and eject out of pathops alto gether later on 1537 // paths with extreme data will fail this test and eject out of pathops alto gether later on
1307 // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 1538 // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
1308 do { 1539 do {
1309 SkASSERT(test->fT < 1); 1540 SkASSERT(test->fT < 1);
1310 if (oTest->fT == 1) { 1541 if (oTest->fT == 1) {
1311 // paths with extreme data may be so mismatched that we fail here 1542 // paths with extreme data may be so mismatched that we fail here
1312 return false; 1543 return false;
1313 } 1544 }
1314 1545
1315 // consolidate the winding count even if done 1546 // consolidate the winding count even if done
1547 bool foundEnd = false;
1316 if ((test->fWindValue == 0 && test->fOppValue == 0) 1548 if ((test->fWindValue == 0 && test->fOppValue == 0)
1317 || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) { 1549 || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) {
1318 SkDEBUGCODE(int firstWind = test->fWindValue); 1550 SkDEBUGCODE(int firstWind = test->fWindValue);
1319 SkDEBUGCODE(int firstOpp = test->fOppValue); 1551 SkDEBUGCODE(int firstOpp = test->fOppValue);
1320 do { 1552 do {
1321 SkASSERT(firstWind == fTs[index].fWindValue); 1553 SkASSERT(firstWind == fTs[index].fWindValue);
1322 SkASSERT(firstOpp == fTs[index].fOppValue); 1554 SkASSERT(firstOpp == fTs[index].fOppValue);
1323 ++index; 1555 ++index;
1324 SkASSERT(index < fTs.count()); 1556 SkASSERT(index < fTs.count());
1325 } while (*testPt == fTs[index].fPt); 1557 } while (*testPt == fTs[index].fPt);
1326 SkDEBUGCODE(firstWind = oTest->fWindValue); 1558 SkDEBUGCODE(firstWind = oTest->fWindValue);
1327 SkDEBUGCODE(firstOpp = oTest->fOppValue); 1559 SkDEBUGCODE(firstOpp = oTest->fOppValue);
1328 do { 1560 do {
1329 SkASSERT(firstWind == other->fTs[oIndex].fWindValue); 1561 SkASSERT(firstWind == other->fTs[oIndex].fWindValue);
1330 SkASSERT(firstOpp == other->fTs[oIndex].fOppValue); 1562 SkASSERT(firstOpp == other->fTs[oIndex].fOppValue);
1331 ++oIndex; 1563 ++oIndex;
1332 SkASSERT(oIndex < other->fTs.count()); 1564 SkASSERT(oIndex < other->fTs.count());
1333 } while (*oTestPt == other->fTs[oIndex].fPt); 1565 } while (*oTestPt == other->fTs[oIndex].fPt);
1334 } else { 1566 } else {
1335 if (!binary || test->fWindValue + oTest->fOppValue >= 0) { 1567 if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
1336 if (!bumpCoincidentThis(*oTest, binary, &index, &outsidePts)) { 1568 if (!bumpCoincidentThis(*oTest, binary, &index, &outsidePts)) {
1337 return false; 1569 return false;
1338 } 1570 }
1339 other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); 1571 foundEnd = other->bumpCoincidentOther(*test, &oIndex, &oOutsideP ts, endPt);
1340 } else { 1572 } else {
1341 if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOutside Pts)) { 1573 if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOutside Pts)) {
1342 return false; 1574 return false;
1343 } 1575 }
1344 bumpCoincidentOther(*oTest, &index, &outsidePts); 1576 foundEnd = bumpCoincidentOther(*oTest, &index, &outsidePts, endP t);
1345 } 1577 }
1346 } 1578 }
1347 test = &fTs[index]; 1579 test = &fTs[index];
1348 testPt = &test->fPt; 1580 testPt = &test->fPt;
1349 testT = test->fT; 1581 testT = test->fT;
1350 oTest = &other->fTs[oIndex]; 1582 oTest = &other->fTs[oIndex];
1351 oTestPt = &oTest->fPt; 1583 oTestPt = &oTest->fPt;
1352 if (endPt == *testPt || precisely_equal(endT, testT)) { 1584 if (endPt == *testPt || precisely_equal(endT, testT)) {
1353 break; 1585 break;
1354 } 1586 }
1587 if (0 && foundEnd) { // FIXME: this is likely needed but wait until a t est case triggers it
1588 break;
1589 }
1355 // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 1590 // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
1356 } while (endPt != *oTestPt); 1591 } while (endPt != *oTestPt);
1357 // in rare cases, one may have ended before the other 1592 // in rare cases, one may have ended before the other
1358 if (endPt != *testPt && !precisely_equal(endT, testT)) { 1593 if (endPt != *testPt && !precisely_equal(endT, testT)) {
1359 int lastWind = test[-1].fWindValue; 1594 int lastWind = test[-1].fWindValue;
1360 int lastOpp = test[-1].fOppValue; 1595 int lastOpp = test[-1].fOppValue;
1361 bool zero = lastWind == 0 && lastOpp == 0; 1596 bool zero = lastWind == 0 && lastOpp == 0;
1362 do { 1597 do {
1363 if (test->fWindValue || test->fOppValue) { 1598 if (test->fWindValue || test->fOppValue) {
1364 test->fWindValue = lastWind; 1599 test->fWindValue = lastWind;
1365 test->fOppValue = lastOpp; 1600 test->fOppValue = lastOpp;
1366 if (zero) { 1601 if (zero) {
1602 SkASSERT(!test->fDone);
1367 test->fDone = true; 1603 test->fDone = true;
1368 ++fDoneSpans; 1604 ++fDoneSpans;
1369 } 1605 }
1370 } 1606 }
1371 test = &fTs[++index]; 1607 test = &fTs[++index];
1372 testPt = &test->fPt; 1608 testPt = &test->fPt;
1373 } while (endPt != *testPt); 1609 } while (endPt != *testPt);
1374 } 1610 }
1375 if (endPt != *oTestPt) { 1611 if (endPt != *oTestPt) {
1376 // look ahead to see if zeroing more spans will allows us to catch up 1612 // look ahead to see if zeroing more spans will allows us to catch up
(...skipping 18 matching lines...) Expand all
1395 } 1631 }
1396 if (++oPeekIndex == oCount) { 1632 if (++oPeekIndex == oCount) {
1397 break; 1633 break;
1398 } 1634 }
1399 oPeek = &other->fTs[oPeekIndex]; 1635 oPeek = &other->fTs[oPeekIndex];
1400 } while (endPt == oPeek->fPt); 1636 } while (endPt == oPeek->fPt);
1401 } 1637 }
1402 if (success) { 1638 if (success) {
1403 do { 1639 do {
1404 if (!binary || test->fWindValue + oTest->fOppValue >= 0) { 1640 if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
1405 other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); 1641 if (other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts, endPt)) {
1642 break;
1643 }
1406 } else { 1644 } else {
1407 if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOut sidePts)) { 1645 if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOut sidePts)) {
1408 return false; 1646 return false;
1409 } 1647 }
1410 } 1648 }
1411 oTest = &other->fTs[oIndex]; 1649 oTest = &other->fTs[oIndex];
1412 oTestPt = &oTest->fPt; 1650 oTestPt = &oTest->fPt;
1413 } while (endPt != *oTestPt); 1651 } while (endPt != *oTestPt);
1414 } 1652 }
1415 } 1653 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 } 1707 }
1470 } 1708 }
1471 } 1709 }
1472 #if DEBUG_ADD_T_PAIR 1710 #if DEBUG_ADD_T_PAIR
1473 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", 1711 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
1474 __FUNCTION__, fID, t, other->fID, otherT); 1712 __FUNCTION__, fID, t, other->fID, otherT);
1475 #endif 1713 #endif
1476 SkASSERT(other != this); 1714 SkASSERT(other != this);
1477 int insertedAt = addT(other, pt, t); 1715 int insertedAt = addT(other, pt, t);
1478 int otherInsertedAt = other->addT(this, pt2, otherT); 1716 int otherInsertedAt = other->addT(this, pt2, otherT);
1479 addOtherT(insertedAt, otherT, otherInsertedAt); 1717 this->addOtherT(insertedAt, otherT, otherInsertedAt);
1480 other->addOtherT(otherInsertedAt, t, insertedAt); 1718 other->addOtherT(otherInsertedAt, t, insertedAt);
1481 matchWindingValue(insertedAt, t, borrowWind); 1719 this->matchWindingValue(insertedAt, t, borrowWind);
1482 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); 1720 other->matchWindingValue(otherInsertedAt, otherT, borrowWind);
1483 SkOpSpan& span = this->fTs[insertedAt]; 1721 SkOpSpan& span = this->fTs[insertedAt];
1484 if (pt != pt2) { 1722 if (pt != pt2) {
1485 span.fNear = true; 1723 span.fNear = true;
1486 SkOpSpan& oSpan = other->fTs[otherInsertedAt]; 1724 SkOpSpan& oSpan = other->fTs[otherInsertedAt];
1487 oSpan.fNear = true; 1725 oSpan.fNear = true;
1488 } 1726 }
1727 // if the newly inserted spans match a neighbor on one but not the other, ma ke them agree
1728 int lower = this->nextExactSpan(insertedAt, -1) + 1;
1729 int upper = this->nextExactSpan(insertedAt, 1) - 1;
1730 if (upper < 0) {
1731 upper = this->count() - 1;
1732 }
1733 int oLower = other->nextExactSpan(otherInsertedAt, -1) + 1;
1734 int oUpper = other->nextExactSpan(otherInsertedAt, 1) - 1;
1735 if (oUpper < 0) {
1736 oUpper = other->count() - 1;
1737 }
1738 if (lower == upper && oLower == oUpper) {
1739 return &span;
1740 }
1741 #if DEBUG_CONCIDENT
1742 SkDebugf("%s id=%d lower=%d upper=%d other=%d oLower=%d oUpper=%d\n", __FUNC TION__,
1743 debugID(), lower, upper, other->debugID(), oLower, oUpper);
1744 #endif
1745 // find the nearby spans in one range missing in the other
1746 this->alignRange(lower, upper, other, oLower, oUpper);
1747 other->alignRange(oLower, oUpper, this, lower, upper);
1489 return &span; 1748 return &span;
1490 } 1749 }
1491 1750
1492 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind, 1751 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind,
1493 const SkPoint& pt) { 1752 const SkPoint& pt) {
1494 return addTPair(t, other, otherT, borrowWind, pt, pt); 1753 return addTPair(t, other, otherT, borrowWind, pt, pt);
1495 } 1754 }
1496 1755
1497 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const { 1756 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const {
1498 const SkPoint midPt = ptAtT(midT); 1757 const SkPoint midPt = ptAtT(midT);
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 SkASSERT(span->fWindValue >= 0); 2145 SkASSERT(span->fWindValue >= 0);
1887 span->fOppValue += oppDelta; 2146 span->fOppValue += oppDelta;
1888 SkASSERT(span->fOppValue >= 0); 2147 SkASSERT(span->fOppValue >= 0);
1889 if (fXor) { 2148 if (fXor) {
1890 span->fWindValue &= 1; 2149 span->fWindValue &= 1;
1891 } 2150 }
1892 if (fOppXor) { 2151 if (fOppXor) {
1893 span->fOppValue &= 1; 2152 span->fOppValue &= 1;
1894 } 2153 }
1895 if (!span->fWindValue && !span->fOppValue) { 2154 if (!span->fWindValue && !span->fOppValue) {
1896 span->fDone = true; 2155 if (!span->fDone) {
1897 ++fDoneSpans; 2156 span->fDone = true;
2157 ++fDoneSpans;
2158 }
1898 return true; 2159 return true;
1899 } 2160 }
1900 return false; 2161 return false;
1901 } 2162 }
1902 2163
1903 const SkOpSpan& SkOpSegment::firstSpan(const SkOpSpan& thisSpan) const { 2164 const SkOpSpan& SkOpSegment::firstSpan(const SkOpSpan& thisSpan) const {
1904 const SkOpSpan* firstSpan = &thisSpan; // rewind to the start 2165 const SkOpSpan* firstSpan = &thisSpan; // rewind to the start
1905 const SkOpSpan* beginSpan = fTs.begin(); 2166 const SkOpSpan* beginSpan = fTs.begin();
1906 const SkPoint& testPt = thisSpan.fPt; 2167 const SkPoint& testPt = thisSpan.fPt;
1907 while (firstSpan > beginSpan && firstSpan[-1].fPt == testPt) { 2168 while (firstSpan > beginSpan && firstSpan[-1].fPt == testPt) {
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
2111 missing.fOther->fixOtherTIndex(); 2372 missing.fOther->fixOtherTIndex();
2112 } 2373 }
2113 for (index = 0; index < missingCoincidence.count(); ++index) { 2374 for (index = 0; index < missingCoincidence.count(); ++index) {
2114 MissingSpan& missing = missingCoincidence[index]; 2375 MissingSpan& missing = missingCoincidence[index];
2115 missing.fSegment->fixOtherTIndex(); 2376 missing.fSegment->fixOtherTIndex();
2116 } 2377 }
2117 debugValidate(); 2378 debugValidate();
2118 } 2379 }
2119 2380
2120 // look to see if the curve end intersects an intermediary that intersects the o ther 2381 // look to see if the curve end intersects an intermediary that intersects the o ther
2121 void SkOpSegment::checkEnds() { 2382 bool SkOpSegment::checkEnds() {
2122 debugValidate(); 2383 debugValidate();
2123 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 2384 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
2124 int count = fTs.count(); 2385 int count = fTs.count();
2125 for (int index = 0; index < count; ++index) { 2386 for (int index = 0; index < count; ++index) {
2126 const SkOpSpan& span = fTs[index]; 2387 const SkOpSpan& span = fTs[index];
2127 double otherT = span.fOtherT; 2388 double otherT = span.fOtherT;
2128 if (otherT != 0 && otherT != 1) { // only check ends 2389 if (otherT != 0 && otherT != 1) { // only check ends
2129 continue; 2390 continue;
2130 } 2391 }
2131 const SkOpSegment* other = span.fOther; 2392 const SkOpSegment* other = span.fOther;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2186 if (match->betweenPoints(midT, tSpan.fPt, peekSpan.fPt)) { 2447 if (match->betweenPoints(midT, tSpan.fPt, peekSpan.fPt)) {
2187 goto nextPeekIndex; 2448 goto nextPeekIndex;
2188 } 2449 }
2189 } 2450 }
2190 } 2451 }
2191 if (missingSpans.count() > 0) { 2452 if (missingSpans.count() > 0) {
2192 const MissingSpan& lastMissing = missingSpans.back(); 2453 const MissingSpan& lastMissing = missingSpans.back();
2193 if (lastMissing.fT == t 2454 if (lastMissing.fT == t
2194 && lastMissing.fOther == match 2455 && lastMissing.fOther == match
2195 && lastMissing.fOtherT == matchT) { 2456 && lastMissing.fOtherT == matchT) {
2196 SkASSERT(lastMissing.fPt == peekSpan.fPt); 2457 SkASSERT(SkDPoint::ApproximatelyEqual(lastMissing.fPt, peekS pan.fPt));
2197 continue; 2458 continue;
2198 } 2459 }
2199 } 2460 }
2200 #if DEBUG_CHECK_ENDS 2461 if (this == match) {
2462 return false; // extremely large paths can trigger this
2463 }
2464 #if DEBUG_CHECK_ALIGN
2201 SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,% 1.9g)\n", 2465 SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,% 1.9g)\n",
2202 __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, p eekSpan.fPt.fY); 2466 __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, p eekSpan.fPt.fY);
2203 #endif 2467 #endif
2204 // this segment is missing a entry that the other contains 2468 // this segment is missing a entry that the other contains
2205 // remember so we can add the missing one and recompute the indices 2469 // remember so we can add the missing one and recompute the indices
2206 { 2470 {
2207 MissingSpan& missing = missingSpans.push_back(); 2471 MissingSpan& missing = missingSpans.push_back();
2208 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 2472 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
2209 missing.fT = t; 2473 missing.fT = t;
2210 SkASSERT(this != match); 2474 SkASSERT(this != match);
2211 missing.fOther = match; 2475 missing.fOther = match;
2212 missing.fOtherT = matchT; 2476 missing.fOtherT = matchT;
2213 missing.fPt = peekSpan.fPt; 2477 missing.fPt = peekSpan.fPt;
2214 } 2478 }
2215 break; 2479 break;
2216 nextPeekIndex: 2480 nextPeekIndex:
2217 ; 2481 ;
2218 } 2482 }
2219 } 2483 }
2220 if (missingSpans.count() == 0) { 2484 if (missingSpans.count() == 0) {
2221 debugValidate(); 2485 debugValidate();
2222 return; 2486 return true;
2223 } 2487 }
2224 debugValidate(); 2488 debugValidate();
2225 int missingCount = missingSpans.count(); 2489 int missingCount = missingSpans.count();
2226 for (int index = 0; index < missingCount; ++index) { 2490 for (int index = 0; index < missingCount; ++index) {
2227 MissingSpan& missing = missingSpans[index]; 2491 MissingSpan& missing = missingSpans[index];
2228 if (this != missing.fOther) { 2492 if (this != missing.fOther) {
2229 addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing .fPt); 2493 addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing .fPt);
2230 } 2494 }
2231 } 2495 }
2232 fixOtherTIndex(); 2496 fixOtherTIndex();
2233 // OPTIMIZATION: this may fix indices more than once. Build an array of uniq ue segments to 2497 // OPTIMIZATION: this may fix indices more than once. Build an array of uniq ue segments to
2234 // avoid this 2498 // avoid this
2235 for (int index = 0; index < missingCount; ++index) { 2499 for (int index = 0; index < missingCount; ++index) {
2236 missingSpans[index].fOther->fixOtherTIndex(); 2500 missingSpans[index].fOther->fixOtherTIndex();
2237 } 2501 }
2238 debugValidate(); 2502 debugValidate();
2503 return true;
2239 } 2504 }
2240 2505
2241 void SkOpSegment::checkLinks(const SkOpSpan* base, 2506 void SkOpSegment::checkLinks(const SkOpSpan* base,
2242 SkTArray<MissingSpan, true>* missingSpans) const { 2507 SkTArray<MissingSpan, true>* missingSpans) const {
2243 const SkOpSpan* first = fTs.begin(); 2508 const SkOpSpan* first = fTs.begin();
2244 const SkOpSpan* last = fTs.end() - 1; 2509 const SkOpSpan* last = fTs.end() - 1;
2245 SkASSERT(base >= first && last >= base); 2510 SkASSERT(base >= first && last >= base);
2246 const SkOpSegment* other = base->fOther; 2511 const SkOpSegment* other = base->fOther;
2247 const SkOpSpan* oFirst = other->fTs.begin(); 2512 const SkOpSpan* oFirst = other->fTs.begin();
2248 const SkOpSpan* oLast = other->fTs.end() - 1; 2513 const SkOpSpan* oLast = other->fTs.end() - 1;
2249 const SkOpSpan* oSpan = &other->fTs[base->fOtherIndex]; 2514 const SkOpSpan* oSpan = &other->fTs[base->fOtherIndex];
2250 const SkOpSpan* test = base; 2515 const SkOpSpan* test = base;
2251 const SkOpSpan* missing = NULL; 2516 const SkOpSpan* missing = NULL;
2252 while (test > first && (--test)->fPt == base->fPt) { 2517 while (test > first && (--test)->fPt == base->fPt) {
2253 if (this == test->fOther) { 2518 if (this == test->fOther) {
2254 continue; 2519 continue;
2255 } 2520 }
2256 CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans); 2521 CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans);
2257 } 2522 }
2258 test = base; 2523 test = base;
2259 while (test < last && (++test)->fPt == base->fPt) { 2524 while (test < last && (++test)->fPt == base->fPt) {
2260 SkASSERT(this != test->fOther); 2525 SkASSERT(this != test->fOther || test->fLoop);
2261 CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans); 2526 CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans);
2262 } 2527 }
2263 } 2528 }
2264 2529
2265 // see if spans with two or more intersections all agree on common t and point v alues 2530 // see if spans with two or more intersections all agree on common t and point v alues
2266 void SkOpSegment::checkMultiples() { 2531 void SkOpSegment::checkMultiples() {
2267 debugValidate(); 2532 debugValidate();
2268 int index; 2533 int index;
2269 int end = 0; 2534 int end = 0;
2270 while (fTs[++end].fT == 0) 2535 while (fTs[++end].fT == 0)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 SkOpSegment* missingOther = missing.fOther; 2691 SkOpSegment* missingOther = missing.fOther;
2427 // note that add t pair may edit span arrays, so prior pointers to spans are no longer valid 2692 // note that add t pair may edit span arrays, so prior pointers to spans are no longer valid
2428 if (!missing.fSegment->addTPair(missing.fT, missingOther, missing.fOther T, false, 2693 if (!missing.fSegment->addTPair(missing.fT, missingOther, missing.fOther T, false,
2429 missing.fPt)) { 2694 missing.fPt)) {
2430 continue; 2695 continue;
2431 } 2696 }
2432 int otherTIndex = missingOther->findT(missing.fOtherT, missing.fPt, miss ing.fSegment); 2697 int otherTIndex = missingOther->findT(missing.fOtherT, missing.fPt, miss ing.fSegment);
2433 const SkOpSpan& otherSpan = missingOther->span(otherTIndex); 2698 const SkOpSpan& otherSpan = missingOther->span(otherTIndex);
2434 if (otherSpan.fSmall) { 2699 if (otherSpan.fSmall) {
2435 const SkOpSpan* nextSpan = &otherSpan; 2700 const SkOpSpan* nextSpan = &otherSpan;
2701 if (nextSpan->fPt == missing.fPt) {
2702 continue;
2703 }
2436 do { 2704 do {
2437 ++nextSpan; 2705 ++nextSpan;
2438 } while (nextSpan->fSmall); 2706 } while (nextSpan->fSmall);
2707 if (nextSpan->fT == 1) {
2708 continue;
2709 }
2439 SkAssertResult(missing.fSegment->addTCoincident(missing.fPt, nextSpa n->fPt, 2710 SkAssertResult(missing.fSegment->addTCoincident(missing.fPt, nextSpa n->fPt,
2440 nextSpan->fT, missingOther)); 2711 nextSpan->fT, missingOther));
2441 } else if (otherSpan.fT > 0) { 2712 } else if (otherSpan.fT > 0) {
2442 const SkOpSpan* priorSpan = &otherSpan; 2713 const SkOpSpan* priorSpan = &otherSpan;
2443 do { 2714 do {
2444 --priorSpan; 2715 --priorSpan;
2445 } while (priorSpan->fT == otherSpan.fT); 2716 } while (priorSpan->fT == otherSpan.fT);
2446 if (priorSpan->fSmall) { 2717 if (priorSpan->fSmall) {
2447 missing.fSegment->addTCancel(missing.fPt, priorSpan->fPt, missin gOther); 2718 missing.fSegment->addTCancel(missing.fPt, priorSpan->fPt, missin gOther);
2448 } 2719 }
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after
3104 for (int index = 0; index < count; ++index) { 3375 for (int index = 0; index < count; ++index) {
3105 const SkOpSpan& span = fTs[index]; 3376 const SkOpSpan& span = fTs[index];
3106 if (span.fT == t && span.fOther == match) { 3377 if (span.fT == t && span.fOther == match) {
3107 return index; 3378 return index;
3108 } 3379 }
3109 } 3380 }
3110 SkASSERT(0); 3381 SkASSERT(0);
3111 return -1; 3382 return -1;
3112 } 3383 }
3113 3384
3385
3386
3114 int SkOpSegment::findOtherT(double t, const SkOpSegment* match) const { 3387 int SkOpSegment::findOtherT(double t, const SkOpSegment* match) const {
3115 int count = this->count(); 3388 int count = this->count();
3116 for (int index = 0; index < count; ++index) { 3389 for (int index = 0; index < count; ++index) {
3117 const SkOpSpan& span = fTs[index]; 3390 const SkOpSpan& span = fTs[index];
3118 if (span.fOtherT == t && span.fOther == match) { 3391 if (span.fOtherT == t && span.fOther == match) {
3119 return index; 3392 return index;
3120 } 3393 }
3121 } 3394 }
3122 return -1; 3395 return -1;
3123 } 3396 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3190 return NULL; // nothing to do 3463 return NULL; // nothing to do
3191 } 3464 }
3192 SkScalar top = SK_ScalarMax; 3465 SkScalar top = SK_ScalarMax;
3193 const SkOpAngle* firstAngle = NULL; 3466 const SkOpAngle* firstAngle = NULL;
3194 const SkOpAngle* angle = baseAngle; 3467 const SkOpAngle* angle = baseAngle;
3195 do { 3468 do {
3196 if (!angle->unorderable()) { 3469 if (!angle->unorderable()) {
3197 SkOpSegment* next = angle->segment(); 3470 SkOpSegment* next = angle->segment();
3198 SkPathOpsBounds bounds; 3471 SkPathOpsBounds bounds;
3199 next->subDivideBounds(angle->end(), angle->start(), &bounds); 3472 next->subDivideBounds(angle->end(), angle->start(), &bounds);
3200 if (approximately_greater(top, bounds.fTop)) { 3473 bool nearSame = AlmostEqualUlps(top, bounds.top());
3474 bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->s ectorStart();
3475 bool lesserSector = top > bounds.fTop;
3476 if (lesserSector && (!nearSame || lowerSector)) {
3201 top = bounds.fTop; 3477 top = bounds.fTop;
3202 firstAngle = angle; 3478 firstAngle = angle;
3203 } 3479 }
3204 } 3480 }
3205 angle = angle->next(); 3481 angle = angle->next();
3206 } while (angle != baseAngle); 3482 } while (angle != baseAngle);
3207 SkASSERT(firstAngle); 3483 if (!firstAngle) {
3484 return NULL; // if all are unorderable, give up
3485 }
3208 #if DEBUG_SORT 3486 #if DEBUG_SORT
3209 SkDebugf("%s\n", __FUNCTION__); 3487 SkDebugf("%s\n", __FUNCTION__);
3210 firstAngle->debugLoop(); 3488 firstAngle->debugLoop();
3211 #endif 3489 #endif
3212 // skip edges that have already been processed 3490 // skip edges that have already been processed
3213 angle = firstAngle; 3491 angle = firstAngle;
3214 SkOpSegment* leftSegment = NULL; 3492 SkOpSegment* leftSegment = NULL;
3215 bool looped = false; 3493 bool looped = false;
3216 do { 3494 do {
3217 *unsortable = angle->unorderable(); 3495 *unsortable = angle->unorderable();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3294 for (int index = 0; index < count; ++index) { 3572 for (int index = 0; index < count; ++index) {
3295 const SkOpSpan& span = this->span(index); 3573 const SkOpSpan& span = this->span(index);
3296 if (span.fCoincident) { 3574 if (span.fCoincident) {
3297 foundEnds |= (span.fOther == other) << ((t > span.fT) + (t >= span.f T)); 3575 foundEnds |= (span.fOther == other) << ((t > span.fT) + (t >= span.f T));
3298 } 3576 }
3299 } 3577 }
3300 SkASSERT(foundEnds != 7); 3578 SkASSERT(foundEnds != 7);
3301 return foundEnds == 0x3 || foundEnds == 0x5 || foundEnds == 0x6; // two bit s set 3579 return foundEnds == 0x3 || foundEnds == 0x5 || foundEnds == 0x6; // two bit s set
3302 } 3580 }
3303 3581
3582 bool SkOpSegment::inconsistentAngle(int maxWinding, int sumWinding, int oppMaxWi nding,
3583 int oppSumWinding, const SkOpAngle* angle) const {
3584 SkASSERT(angle->segment() == this);
3585 if (UseInnerWinding(maxWinding, sumWinding)) {
3586 maxWinding = sumWinding;
3587 }
3588 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumW inding)) {
3589 oppMaxWinding = oppSumWinding;
3590 }
3591 return inconsistentWinding(angle, maxWinding, oppMaxWinding);
3592 }
3593
3594 bool SkOpSegment::inconsistentWinding(const SkOpAngle* angle, int winding,
3595 int oppWinding) const {
3596 int index = angle->start();
3597 int endIndex = angle->end();
3598 int min = SkMin32(index, endIndex);
3599 int step = SkSign32(endIndex - index);
3600 if (inconsistentWinding(min, winding, oppWinding)) {
3601 return true;
3602 }
3603 const SkOpSegment* other = this;
3604 while ((other = other->nextChase(&index, &step, &min, NULL))) {
3605 if (other->fTs[min].fWindSum != SK_MinS32) {
3606 break;
3607 }
3608 if (fOperand == other->fOperand) {
3609 if (other->inconsistentWinding(min, winding, oppWinding)) {
3610 return true;
3611 }
3612 } else {
3613 if (other->inconsistentWinding(min, oppWinding, winding)) {
3614 return true;
3615 }
3616 }
3617 }
3618 return false;
3619 }
3620
3621 bool SkOpSegment::inconsistentWinding(int index, int winding, int oppWinding) co nst {
3622 SkASSERT(winding || oppWinding);
3623 double referenceT = this->span(index).fT;
3624 int lesser = index;
3625 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3626 if (inconsistentWinding(__FUNCTION__, lesser, winding, oppWinding)) {
3627 return true;
3628 }
3629 }
3630 do {
3631 if (inconsistentWinding(__FUNCTION__, index, winding, oppWinding)) {
3632 return true;
3633 }
3634 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT));
3635 return false;
3636 }
3637
3638 bool SkOpSegment::inconsistentWinding(const char* funName, int tIndex, int windi ng,
3639 int oppWinding) const {
3640 const SkOpSpan& span = this->span(tIndex);
3641 if (span.fDone && !span.fSmall) {
3642 return false;
3643 }
3644 return (span.fWindSum != SK_MinS32 && span.fWindSum != winding)
3645 || (span.fOppSum != SK_MinS32 && span.fOppSum != oppWinding);
3646 }
3647
3304 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo l evenOdd) { 3648 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo l evenOdd) {
3305 fDoneSpans = 0; 3649 fDoneSpans = 0;
3306 fOperand = operand; 3650 fOperand = operand;
3307 fXor = evenOdd; 3651 fXor = evenOdd;
3308 fPts = pts; 3652 fPts = pts;
3309 fVerb = verb; 3653 fVerb = verb;
3310 fLoop = fMultiples = fSmall = fTiny = false; 3654 fLoop = fMultiples = fSmall = fTiny = false;
3311 } 3655 }
3312 3656
3313 void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIn cludeType) { 3657 void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIn cludeType) {
3314 int local = spanSign(start, end); 3658 int local = spanSign(start, end);
3659 SkDEBUGCODE(bool success);
3315 if (angleIncludeType == SkOpAngle::kBinarySingle) { 3660 if (angleIncludeType == SkOpAngle::kBinarySingle) {
3316 int oppLocal = oppSign(start, end); 3661 int oppLocal = oppSign(start, end);
3317 (void) markAndChaseWinding(start, end, local, oppLocal); 3662 SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, oppLocal, NULL);
3318 // OPTIMIZATION: the reverse mark and chase could skip the first marking 3663 // OPTIMIZATION: the reverse mark and chase could skip the first marking
3319 (void) markAndChaseWinding(end, start, local, oppLocal); 3664 SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, oppLocal, NULL);
3320 } else { 3665 } else {
3321 (void) markAndChaseWinding(start, end, local); 3666 SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, NULL);
3322 // OPTIMIZATION: the reverse mark and chase could skip the first marking 3667 // OPTIMIZATION: the reverse mark and chase could skip the first marking
3323 (void) markAndChaseWinding(end, start, local); 3668 SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, NULL);
3324 } 3669 }
3670 SkASSERT(success);
3325 } 3671 }
3326 3672
3327 /* 3673 /*
3328 when we start with a vertical intersect, we try to use the dx to determine if th e edge is to 3674 when we start with a vertical intersect, we try to use the dx to determine if th e edge is to
3329 the left or the right of vertical. This determines if we need to add the span's 3675 the left or the right of vertical. This determines if we need to add the span's
3330 sign or not. However, this isn't enough. 3676 sign or not. However, this isn't enough.
3331 If the supplied sign (winding) is zero, then we didn't hit another vertical span , so dx is needed. 3677 If the supplied sign (winding) is zero, then we didn't hit another vertical span , so dx is needed.
3332 If there was a winding, then it may or may not need adjusting. If the span the w inding was borrowed 3678 If there was a winding, then it may or may not need adjusting. If the span the w inding was borrowed
3333 from has the same x direction as this span, the winding should change. If the dx is opposite, then 3679 from has the same x direction as this span, the winding should change. If the dx is opposite, then
3334 the same winding is shared by both. 3680 the same winding is shared by both.
3335 */ 3681 */
3336 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc alar hitDx, 3682 bool SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc alar hitDx,
3337 int oppWind, SkScalar hitOppDx) { 3683 int oppWind, SkScalar hitOppDx) {
3338 SkASSERT(hitDx || !winding); 3684 SkASSERT(hitDx || !winding);
3339 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 3685 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX;
3340 SkASSERT(dx); 3686 SkASSERT(dx);
3341 int windVal = windValue(SkMin32(start, end)); 3687 int windVal = windValue(SkMin32(start, end));
3342 #if DEBUG_WINDING_AT_T 3688 #if DEBUG_WINDING_AT_T
3343 SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, d ebugID(), winding, 3689 SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, d ebugID(), winding,
3344 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); 3690 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal);
3345 #endif 3691 #endif
3346 int sideWind = winding + (dx < 0 ? windVal : -windVal); 3692 int sideWind = winding + (dx < 0 ? windVal : -windVal);
3347 if (abs(winding) < abs(sideWind)) { 3693 if (abs(winding) < abs(sideWind)) {
3348 winding = sideWind; 3694 winding = sideWind;
3349 } 3695 }
3350 SkDEBUGCODE(int oppLocal = oppSign(start, end)); 3696 SkDEBUGCODE(int oppLocal = oppSign(start, end));
3351 SkASSERT(hitOppDx || !oppWind || !oppLocal); 3697 SkASSERT(hitOppDx || !oppWind || !oppLocal);
3352 int oppWindVal = oppValue(SkMin32(start, end)); 3698 int oppWindVal = oppValue(SkMin32(start, end));
3353 if (!oppWind) { 3699 if (!oppWind) {
3354 oppWind = dx < 0 ? oppWindVal : -oppWindVal; 3700 oppWind = dx < 0 ? oppWindVal : -oppWindVal;
3355 } else if (hitOppDx * dx >= 0) { 3701 } else if (hitOppDx * dx >= 0) {
3356 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); 3702 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal);
3357 if (abs(oppWind) < abs(oppSideWind)) { 3703 if (abs(oppWind) < abs(oppSideWind)) {
3358 oppWind = oppSideWind; 3704 oppWind = oppSideWind;
3359 } 3705 }
3360 } 3706 }
3361 #if DEBUG_WINDING_AT_T 3707 #if DEBUG_WINDING_AT_T
3362 SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind); 3708 SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind);
3363 #endif 3709 #endif
3364 (void) markAndChaseWinding(start, end, winding, oppWind); 3710 // if this fails to mark (because the edges are too small) inform caller to try again
3711 bool success = markAndChaseWinding(start, end, winding, oppWind, NULL);
3365 // OPTIMIZATION: the reverse mark and chase could skip the first marking 3712 // OPTIMIZATION: the reverse mark and chase could skip the first marking
3366 (void) markAndChaseWinding(end, start, winding, oppWind); 3713 success |= markAndChaseWinding(end, start, winding, oppWind, NULL);
3714 return success;
3367 } 3715 }
3368 3716
3369 bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPt r) const { 3717 bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPt r) const {
3370 if (!baseAngle->inLoop()) { 3718 if (!baseAngle->inLoop()) {
3371 return false; 3719 return false;
3372 } 3720 }
3373 int index = *indexPtr; 3721 int index = *indexPtr;
3374 SkOpAngle* from = fTs[index].fFromAngle; 3722 SkOpAngle* from = fTs[index].fFromAngle;
3375 SkOpAngle* to = fTs[index].fToAngle; 3723 SkOpAngle* to = fTs[index].fToAngle;
3376 while (++index < spanCount) { 3724 while (++index < spanCount) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3420 // if neither is a line, test for coincidence 3768 // if neither is a line, test for coincidence
3421 bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, const SkPoi nt& otherPt, 3769 bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, const SkPoi nt& otherPt,
3422 int step, bool cancel) { 3770 int step, bool cancel) {
3423 int otherTIndex = other->findT(otherT, otherPt, this); 3771 int otherTIndex = other->findT(otherT, otherPt, this);
3424 int next = other->nextExactSpan(otherTIndex, step); 3772 int next = other->nextExactSpan(otherTIndex, step);
3425 int otherMin = SkMin32(otherTIndex, next); 3773 int otherMin = SkMin32(otherTIndex, next);
3426 int otherWind = other->span(otherMin).fWindValue; 3774 int otherWind = other->span(otherMin).fWindValue;
3427 if (otherWind == 0) { 3775 if (otherWind == 0) {
3428 return false; 3776 return false;
3429 } 3777 }
3430 SkASSERT(next >= 0); 3778 if (next < 0) {
3779 return false; // can happen if t values were adjusted but coincident ts were not
3780 }
3431 int tIndex = 0; 3781 int tIndex = 0;
3432 do { 3782 do {
3433 SkOpSpan* test = &fTs[tIndex]; 3783 SkOpSpan* test = &fTs[tIndex];
3434 SkASSERT(test->fT == 0); 3784 SkASSERT(test->fT == 0);
3435 if (test->fOther == other || test->fOtherT != 1) { 3785 if (test->fOther == other || test->fOtherT != 1) {
3436 continue; 3786 continue;
3437 } 3787 }
3438 SkPoint startPt, endPt; 3788 SkPoint startPt, endPt;
3439 double endT; 3789 double endT;
3440 if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) { 3790 if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) {
3441 SkOpSegment* match = test->fOther; 3791 SkOpSegment* match = test->fOther;
3442 if (cancel) { 3792 if (cancel) {
3443 match->addTCancel(startPt, endPt, other); 3793 match->addTCancel(startPt, endPt, other);
3444 } else { 3794 } else {
3445 SkAssertResult(match->addTCoincident(startPt, endPt, endT, other )); 3795 if (!match->addTCoincident(startPt, endPt, endT, other)) {
3796 return false;
3797 }
3446 } 3798 }
3447 return true; 3799 return true;
3448 } 3800 }
3449 } while (fTs[++tIndex].fT == 0); 3801 } while (fTs[++tIndex].fT == 0);
3450 return false; 3802 return false;
3451 } 3803 }
3452 3804
3453 // this span is excluded by the winding rule -- chase the ends 3805 // this span is excluded by the winding rule -- chase the ends
3454 // as long as they are unambiguous to mark connections as done 3806 // as long as they are unambiguous to mark connections as done
3455 // and give them the same winding value 3807 // and give them the same winding value
(...skipping 23 matching lines...) Expand all
3479 while ((other = other->nextChase(&index, &step, &min, &last))) { 3831 while ((other = other->nextChase(&index, &step, &min, &last))) {
3480 if (other->done()) { 3832 if (other->done()) {
3481 SkASSERT(!last); 3833 SkASSERT(!last);
3482 break; 3834 break;
3483 } 3835 }
3484 other->markDoneUnary(min); 3836 other->markDoneUnary(min);
3485 } 3837 }
3486 return last; 3838 return last;
3487 } 3839 }
3488 3840
3489 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) { 3841 bool SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, SkOpS pan** lastPtr) {
3490 int index = angle->start(); 3842 int index = angle->start();
3491 int endIndex = angle->end(); 3843 int endIndex = angle->end();
3844 return markAndChaseWinding(index, endIndex, winding, lastPtr);
3845 }
3846
3847 bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, SkOp Span** lastPtr) {
3848 int min = SkMin32(index, endIndex);
3492 int step = SkSign32(endIndex - index); 3849 int step = SkSign32(endIndex - index);
3493 int min = SkMin32(index, endIndex); 3850 bool success = markWinding(min, winding);
3494 markWinding(min, winding);
3495 SkOpSpan* last = NULL; 3851 SkOpSpan* last = NULL;
3496 SkOpSegment* other = this; 3852 SkOpSegment* other = this;
3497 while ((other = other->nextChase(&index, &step, &min, &last))) { 3853 while ((other = other->nextChase(&index, &step, &min, &last))) {
3498 if (other->fTs[min].fWindSum != SK_MinS32) {
3499 // SkASSERT(other->fTs[min].fWindSum == winding);
3500 SkASSERT(!last);
3501 break;
3502 }
3503 other->markWinding(min, winding);
3504 }
3505 return last;
3506 }
3507
3508 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding) {
3509 int min = SkMin32(index, endIndex);
3510 int step = SkSign32(endIndex - index);
3511 markWinding(min, winding);
3512 SkOpSpan* last = NULL;
3513 SkOpSegment* other = this;
3514 while ((other = other->nextChase(&index, &step, &min, &last))) {
3515 if (other->fTs[min].fWindSum != SK_MinS32) { 3854 if (other->fTs[min].fWindSum != SK_MinS32) {
3516 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p); 3855 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p);
3517 SkASSERT(!last); 3856 SkASSERT(!last);
3518 break; 3857 break;
3519 } 3858 }
3520 other->markWinding(min, winding); 3859 (void) other->markWinding(min, winding);
3521 } 3860 }
3522 return last; 3861 if (lastPtr) {
3862 *lastPtr = last;
3863 }
3864 return success;
3523 } 3865 }
3524 3866
3525 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) { 3867 bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding,
3868 SkOpSpan** lastPtr) {
3526 int min = SkMin32(index, endIndex); 3869 int min = SkMin32(index, endIndex);
3527 int step = SkSign32(endIndex - index); 3870 int step = SkSign32(endIndex - index);
3528 markWinding(min, winding, oppWinding); 3871 bool success = markWinding(min, winding, oppWinding);
3529 SkOpSpan* last = NULL; 3872 SkOpSpan* last = NULL;
3530 SkOpSegment* other = this; 3873 SkOpSegment* other = this;
3531 while ((other = other->nextChase(&index, &step, &min, &last))) { 3874 while ((other = other->nextChase(&index, &step, &min, &last))) {
3532 if (other->fTs[min].fWindSum != SK_MinS32) { 3875 if (other->fTs[min].fWindSum != SK_MinS32) {
3533 #ifdef SK_DEBUG 3876 #ifdef SK_DEBUG
3534 if (!other->fTs[min].fLoop) { 3877 if (!other->fTs[min].fLoop) {
3535 if (fOperand == other->fOperand) { 3878 if (fOperand == other->fOperand) {
3536 // FIXME: this is probably a bug -- rects4 asserts here 3879 // FIXME: this is probably a bug -- rects4 asserts here
3537 // SkASSERT(other->fTs[min].fWindSum == winding); 3880 // SkASSERT(other->fTs[min].fWindSum == winding);
3538 // FIXME: this is probably a bug -- rects3 asserts here 3881 // FIXME: this is probably a bug -- rects3 asserts here
3539 // SkASSERT(other->fTs[min].fOppSum == oppWinding); 3882 // SkASSERT(other->fTs[min].fOppSum == oppWinding);
3540 } else { 3883 } else {
3541 // FIXME: this is probably a bug -- issue414409b asserts here 3884 // FIXME: this is probably a bug -- issue414409b asserts here
3542 // SkASSERT(other->fTs[min].fWindSum == oppWinding); 3885 // SkASSERT(other->fTs[min].fWindSum == oppWinding);
3543 // FIXME: this is probably a bug -- skpwww_joomla_org_23 asserts here 3886 // FIXME: this is probably a bug -- skpwww_joomla_org_23 asserts here
3544 // SkASSERT(other->fTs[min].fOppSum == winding); 3887 // SkASSERT(other->fTs[min].fOppSum == winding);
3545 } 3888 }
3546 } 3889 }
3547 SkASSERT(!last); 3890 SkASSERT(!last);
3548 #endif 3891 #endif
3549 break; 3892 break;
3550 } 3893 }
3551 if (fOperand == other->fOperand) { 3894 if (fOperand == other->fOperand) {
3552 other->markWinding(min, winding, oppWinding); 3895 (void) other->markWinding(min, winding, oppWinding);
3553 } else { 3896 } else {
3554 other->markWinding(min, oppWinding, winding); 3897 (void) other->markWinding(min, oppWinding, winding);
3555 } 3898 }
3556 } 3899 }
3557 return last; 3900 if (lastPtr) {
3901 *lastPtr = last;
3902 }
3903 return success;
3558 } 3904 }
3559 3905
3560 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding) { 3906 bool SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int o ppWinding,
3907 SkOpSpan** lastPtr) {
3561 int start = angle->start(); 3908 int start = angle->start();
3562 int end = angle->end(); 3909 int end = angle->end();
3563 return markAndChaseWinding(start, end, winding, oppWinding); 3910 return markAndChaseWinding(start, end, winding, oppWinding, lastPtr);
3564 } 3911 }
3565 3912
3566 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle * angle) { 3913 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle * angle) {
3567 SkASSERT(angle->segment() == this); 3914 SkASSERT(angle->segment() == this);
3568 if (UseInnerWinding(maxWinding, sumWinding)) { 3915 if (UseInnerWinding(maxWinding, sumWinding)) {
3569 maxWinding = sumWinding; 3916 maxWinding = sumWinding;
3570 } 3917 }
3571 SkOpSpan* last = markAndChaseWinding(angle, maxWinding); 3918 SkOpSpan* last;
3919 SkAssertResult(markAndChaseWinding(angle, maxWinding, &last));
3572 #if DEBUG_WINDING 3920 #if DEBUG_WINDING
3573 if (last) { 3921 if (last) {
3574 SkDebugf("%s last id=%d windSum=", __FUNCTION__, 3922 SkDebugf("%s last id=%d windSum=", __FUNCTION__,
3575 last->fOther->fTs[last->fOtherIndex].fOther->debugID()); 3923 last->fOther->fTs[last->fOtherIndex].fOther->debugID());
3576 SkPathOpsDebug::WindingPrintf(last->fWindSum); 3924 SkPathOpsDebug::WindingPrintf(last->fWindSum);
3577 SkDebugf(" small=%d\n", last->fSmall); 3925 SkDebugf(" small=%d\n", last->fSmall);
3578 } 3926 }
3579 #endif 3927 #endif
3580 return last; 3928 return last;
3581 } 3929 }
3582 3930
3583 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi ng, 3931 SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi ng,
3584 int oppSumWinding, const SkOpAngle* angle) { 3932 int oppSumWinding, const SkOpAngle* angle) {
3585 SkASSERT(angle->segment() == this); 3933 SkASSERT(angle->segment() == this);
3586 if (UseInnerWinding(maxWinding, sumWinding)) { 3934 if (UseInnerWinding(maxWinding, sumWinding)) {
3587 maxWinding = sumWinding; 3935 maxWinding = sumWinding;
3588 } 3936 }
3589 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumW inding)) { 3937 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumW inding)) {
3590 oppMaxWinding = oppSumWinding; 3938 oppMaxWinding = oppSumWinding;
3591 } 3939 }
3592 SkOpSpan* last = markAndChaseWinding(angle, maxWinding, oppMaxWinding); 3940 SkOpSpan* last;
3941 // caller doesn't require that this marks anything
3942 (void) markAndChaseWinding(angle, maxWinding, oppMaxWinding, &last);
3593 #if DEBUG_WINDING 3943 #if DEBUG_WINDING
3594 if (last) { 3944 if (last) {
3595 SkDebugf("%s last id=%d windSum=", __FUNCTION__, 3945 SkDebugf("%s last id=%d windSum=", __FUNCTION__,
3596 last->fOther->fTs[last->fOtherIndex].fOther->debugID()); 3946 last->fOther->fTs[last->fOtherIndex].fOther->debugID());
3597 SkPathOpsDebug::WindingPrintf(last->fWindSum); 3947 SkPathOpsDebug::WindingPrintf(last->fWindSum);
3598 SkDebugf(" small=%d\n", last->fSmall); 3948 SkDebugf(" small=%d\n", last->fSmall);
3599 } 3949 }
3600 #endif 3950 #endif
3601 return last; 3951 return last;
3602 } 3952 }
(...skipping 22 matching lines...) Expand all
3625 int lesser = index; 3975 int lesser = index;
3626 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 3976 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3627 markOneDoneBinary(__FUNCTION__, lesser); 3977 markOneDoneBinary(__FUNCTION__, lesser);
3628 } 3978 }
3629 do { 3979 do {
3630 markOneDoneBinary(__FUNCTION__, index); 3980 markOneDoneBinary(__FUNCTION__, index);
3631 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT)); 3981 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
3632 debugValidate(); 3982 debugValidate();
3633 } 3983 }
3634 3984
3985 void SkOpSegment::markDoneFinal(int index) {
3986 double referenceT = fTs[index].fT;
3987 int lesser = index;
3988 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3989 markOneDoneFinal(__FUNCTION__, lesser);
3990 }
3991 do {
3992 markOneDoneFinal(__FUNCTION__, index);
3993 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
3994 debugValidate();
3995 }
3996
3635 void SkOpSegment::markDoneUnary(int index) { 3997 void SkOpSegment::markDoneUnary(int index) {
3636 double referenceT = fTs[index].fT; 3998 double referenceT = fTs[index].fT;
3637 int lesser = index; 3999 int lesser = index;
3638 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 4000 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3639 markOneDoneUnary(__FUNCTION__, lesser); 4001 markOneDoneUnary(__FUNCTION__, lesser);
3640 } 4002 }
3641 do { 4003 do {
3642 markOneDoneUnary(__FUNCTION__, index); 4004 markOneDoneUnary(__FUNCTION__, index);
3643 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT)); 4005 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
3644 debugValidate(); 4006 debugValidate();
3645 } 4007 }
3646 4008
3647 void SkOpSegment::markOneDone(const char* funName, int tIndex, int winding) { 4009 void SkOpSegment::markOneDone(const char* funName, int tIndex, int winding) {
3648 SkOpSpan* span = markOneWinding(funName, tIndex, winding); 4010 SkOpSpan* span;
3649 if (!span || span->fDone) { 4011 (void) markOneWinding(funName, tIndex, winding, &span); // allowed to do no thing
4012 if (span->fDone) {
3650 return; 4013 return;
3651 } 4014 }
3652 span->fDone = true; 4015 span->fDone = true;
3653 fDoneSpans++; 4016 ++fDoneSpans;
4017 }
4018
4019 void SkOpSegment::markOneDoneFinal(const char* funName, int tIndex) {
4020 SkOpSpan* span = &fTs[tIndex];
4021 if (span->fDone) {
4022 return;
4023 }
4024 span->fDone = true;
4025 ++fDoneSpans;
3654 } 4026 }
3655 4027
3656 void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) { 4028 void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) {
3657 SkOpSpan* span = verifyOneWinding(funName, tIndex); 4029 SkOpSpan* span = verifyOneWinding(funName, tIndex);
3658 if (!span) { 4030 if (!span) {
3659 return; 4031 return;
3660 } 4032 }
3661 SkASSERT(!span->fDone); 4033 SkASSERT(!span->fDone);
3662 span->fDone = true; 4034 span->fDone = true;
3663 fDoneSpans++; 4035 ++fDoneSpans;
3664 } 4036 }
3665 4037
3666 void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) { 4038 void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) {
3667 SkOpSpan* span = verifyOneWindingU(funName, tIndex); 4039 SkOpSpan* span = verifyOneWindingU(funName, tIndex);
3668 if (!span) { 4040 if (!span) {
3669 return; 4041 return;
3670 } 4042 }
3671 if (span->fWindSum == SK_MinS32) { 4043 if (span->fWindSum == SK_MinS32) {
3672 SkDebugf("%s uncomputed\n", __FUNCTION__); 4044 SkDebugf("%s uncomputed\n", __FUNCTION__);
3673 } 4045 }
3674 SkASSERT(!span->fDone); 4046 SkASSERT(!span->fDone);
3675 span->fDone = true; 4047 span->fDone = true;
3676 fDoneSpans++; 4048 ++fDoneSpans;
3677 } 4049 }
3678 4050
3679 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng) { 4051 bool SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding, S kOpSpan** lastPtr) {
3680 SkOpSpan& span = fTs[tIndex]; 4052 SkOpSpan* span = &fTs[tIndex];
3681 if (span.fDone && !span.fSmall) { 4053 if (lastPtr) {
3682 return NULL; 4054 *lastPtr = span;
4055 }
4056 if (span->fDone && !span->fSmall) {
4057 return false;
3683 } 4058 }
3684 #if DEBUG_MARK_DONE 4059 #if DEBUG_MARK_DONE
3685 debugShowNewWinding(funName, span, winding); 4060 debugShowNewWinding(funName, *span, winding);
3686 #endif 4061 #endif
3687 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 4062 SkASSERT(span->fWindSum == SK_MinS32 || span->fWindSum == winding);
3688 #if DEBUG_LIMIT_WIND_SUM 4063 #if DEBUG_LIMIT_WIND_SUM
3689 SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM); 4064 SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM);
3690 #endif 4065 #endif
3691 span.fWindSum = winding; 4066 span->fWindSum = winding;
3692 return &span; 4067 return true;
3693 } 4068 }
3694 4069
3695 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng, 4070 bool SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding,
3696 int oppWinding) { 4071 int oppWinding, SkOpSpan** lastPtr) {
3697 SkOpSpan& span = fTs[tIndex]; 4072 SkOpSpan* span = &fTs[tIndex];
3698 if (span.fDone && !span.fSmall) { 4073 if (span->fDone && !span->fSmall) {
3699 return NULL; 4074 return false;
3700 } 4075 }
3701 #if DEBUG_MARK_DONE 4076 #if DEBUG_MARK_DONE
3702 debugShowNewWinding(funName, span, winding, oppWinding); 4077 debugShowNewWinding(funName, *span, winding, oppWinding);
3703 #endif 4078 #endif
3704 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 4079 SkASSERT(span->fWindSum == SK_MinS32 || span->fWindSum == winding);
3705 #if DEBUG_LIMIT_WIND_SUM 4080 #if DEBUG_LIMIT_WIND_SUM
3706 SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM); 4081 SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM);
3707 #endif 4082 #endif
3708 span.fWindSum = winding; 4083 span->fWindSum = winding;
3709 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding); 4084 SkASSERT(span->fOppSum == SK_MinS32 || span->fOppSum == oppWinding);
3710 #if DEBUG_LIMIT_WIND_SUM 4085 #if DEBUG_LIMIT_WIND_SUM
3711 SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM); 4086 SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM);
3712 #endif 4087 #endif
3713 span.fOppSum = oppWinding; 4088 span->fOppSum = oppWinding;
3714 debugValidate(); 4089 debugValidate();
3715 return &span; 4090 if (lastPtr) {
4091 *lastPtr = span;
4092 }
4093 return true;
3716 } 4094 }
3717 4095
3718 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order 4096 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order
3719 bool SkOpSegment::clockwise(int tStart, int tEnd, bool* swap) const { 4097 bool SkOpSegment::clockwise(int tStart, int tEnd, bool* swap) const {
3720 SkASSERT(fVerb != SkPath::kLine_Verb); 4098 SkASSERT(fVerb != SkPath::kLine_Verb);
3721 SkPoint edge[4]; 4099 SkPoint edge[4];
3722 subDivide(tStart, tEnd, edge); 4100 subDivide(tStart, tEnd, edge);
3723 int points = SkPathOpsVerbToPoints(fVerb); 4101 int points = SkPathOpsVerbToPoints(fVerb);
3724 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY) ; 4102 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY) ;
3725 bool sumSet = false; 4103 bool sumSet = false;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
3829 debugShowNewWinding(funName, span, span.fWindSum); 4207 debugShowNewWinding(funName, span, span.fWindSum);
3830 #endif 4208 #endif
3831 // If the prior angle in the sort is unorderable, the winding sum may not be com putable. 4209 // If the prior angle in the sort is unorderable, the winding sum may not be com putable.
3832 // To enable the assert, the 'prior is unorderable' state could be 4210 // To enable the assert, the 'prior is unorderable' state could be
3833 // piped down to this test, but not sure it's worth it. 4211 // piped down to this test, but not sure it's worth it.
3834 // (Once the sort order is stored in the span, this test may be feasible.) 4212 // (Once the sort order is stored in the span, this test may be feasible.)
3835 // SkASSERT(span.fWindSum != SK_MinS32); 4213 // SkASSERT(span.fWindSum != SK_MinS32);
3836 return &span; 4214 return &span;
3837 } 4215 }
3838 4216
3839 void SkOpSegment::markWinding(int index, int winding) { 4217 bool SkOpSegment::markWinding(int index, int winding) {
3840 // SkASSERT(!done()); 4218 // SkASSERT(!done());
3841 SkASSERT(winding); 4219 SkASSERT(winding);
3842 double referenceT = fTs[index].fT; 4220 double referenceT = fTs[index].fT;
3843 int lesser = index; 4221 int lesser = index;
4222 bool success = false;
3844 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 4223 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3845 markOneWinding(__FUNCTION__, lesser, winding); 4224 success |= markOneWinding(__FUNCTION__, lesser, winding, NULL);
3846 } 4225 }
3847 do { 4226 do {
3848 markOneWinding(__FUNCTION__, index, winding); 4227 success |= markOneWinding(__FUNCTION__, index, winding, NULL);
3849 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT)); 4228 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT));
3850 debugValidate(); 4229 debugValidate();
4230 return success;
3851 } 4231 }
3852 4232
3853 void SkOpSegment::markWinding(int index, int winding, int oppWinding) { 4233 bool SkOpSegment::markWinding(int index, int winding, int oppWinding) {
3854 // SkASSERT(!done()); 4234 // SkASSERT(!done());
3855 SkASSERT(winding || oppWinding); 4235 SkASSERT(winding || oppWinding);
3856 double referenceT = fTs[index].fT; 4236 double referenceT = fTs[index].fT;
3857 int lesser = index; 4237 int lesser = index;
4238 bool success = false;
3858 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 4239 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3859 markOneWinding(__FUNCTION__, lesser, winding, oppWinding); 4240 success |= markOneWinding(__FUNCTION__, lesser, winding, oppWinding, NUL L);
3860 } 4241 }
3861 do { 4242 do {
3862 markOneWinding(__FUNCTION__, index, winding, oppWinding); 4243 success |= markOneWinding(__FUNCTION__, index, winding, oppWinding, NULL );
3863 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT)); 4244 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT));
3864 debugValidate(); 4245 debugValidate();
4246 return success;
3865 } 4247 }
3866 4248
3867 void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) { 4249 void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) {
3868 int nextDoorWind = SK_MaxS32; 4250 int nextDoorWind = SK_MaxS32;
3869 int nextOppWind = SK_MaxS32; 4251 int nextOppWind = SK_MaxS32;
3870 // prefer exact matches 4252 // prefer exact matches
3871 if (tIndex > 0) { 4253 if (tIndex > 0) {
3872 const SkOpSpan& below = fTs[tIndex - 1]; 4254 const SkOpSpan& below = fTs[tIndex - 1];
3873 if (below.fT == t) { 4255 if (below.fT == t) {
3874 nextDoorWind = below.fWindValue; 4256 nextDoorWind = below.fWindValue;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3917 if (fTs[*end].fT == 1) { 4299 if (fTs[*end].fT == 1) {
3918 return false; 4300 return false;
3919 } 4301 }
3920 ++(*end); 4302 ++(*end);
3921 } 4303 }
3922 *start = *end; 4304 *start = *end;
3923 *end = nextExactSpan(*start, 1); 4305 *end = nextExactSpan(*start, 1);
3924 return true; 4306 return true;
3925 } 4307 }
3926 4308
3927 static SkOpSegment* set_last(SkOpSpan** last, SkOpSpan* endSpan) { 4309 static SkOpSegment* set_last(SkOpSpan** last, const SkOpSpan* endSpan) {
3928 if (last && !endSpan->fSmall) { 4310 if (last && !endSpan->fSmall) {
3929 *last = endSpan; 4311 *last = const_cast<SkOpSpan*>(endSpan); // FIXME: get rid of cast
3930 } 4312 }
3931 return NULL; 4313 return NULL;
3932 } 4314 }
3933 4315
3934 SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, Sk OpSpan** last) { 4316 SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr,
4317 SkOpSpan** last) const {
3935 int origIndex = *indexPtr; 4318 int origIndex = *indexPtr;
3936 int step = *stepPtr; 4319 int step = *stepPtr;
3937 int end = nextExactSpan(origIndex, step); 4320 int end = nextExactSpan(origIndex, step);
3938 SkASSERT(end >= 0); 4321 SkASSERT(end >= 0);
3939 SkOpSpan& endSpan = fTs[end]; 4322 const SkOpSpan& endSpan = this->span(end);
3940 SkOpAngle* angle = step > 0 ? endSpan.fFromAngle : endSpan.fToAngle; 4323 SkOpAngle* angle = step > 0 ? endSpan.fFromAngle : endSpan.fToAngle;
3941 int foundIndex; 4324 int foundIndex;
3942 int otherEnd; 4325 int otherEnd;
3943 SkOpSegment* other; 4326 SkOpSegment* other;
3944 if (angle == NULL) { 4327 if (angle == NULL) {
3945 if (endSpan.fT != 0 && endSpan.fT != 1) { 4328 if (endSpan.fT != 0 && endSpan.fT != 1) {
3946 return NULL; 4329 return NULL;
3947 } 4330 }
3948 other = endSpan.fOther; 4331 other = endSpan.fOther;
3949 foundIndex = endSpan.fOtherIndex; 4332 foundIndex = endSpan.fOtherIndex;
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
4455 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 4838 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
4456 span->fWindValue = 0; 4839 span->fWindValue = 0;
4457 span->fOppValue = 0; 4840 span->fOppValue = 0;
4458 if (span->fTiny || span->fSmall) { 4841 if (span->fTiny || span->fSmall) {
4459 return; 4842 return;
4460 } 4843 }
4461 SkASSERT(!span->fDone); 4844 SkASSERT(!span->fDone);
4462 span->fDone = true; 4845 span->fDone = true;
4463 ++fDoneSpans; 4846 ++fDoneSpans;
4464 } 4847 }
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