OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include "SkIntersections.h" | 7 #include "SkIntersections.h" |
8 #include "SkOpContour.h" | 8 #include "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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |