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