| 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 |