OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 | 7 |
8 #include "SkChunkAlloc.h" | 8 #include "SkChunkAlloc.h" |
9 #include "SkPathOpsBounds.h" | 9 #include "SkPathOpsBounds.h" |
10 #include "SkPathOpsRect.h" | 10 #include "SkPathOpsRect.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 fCoinEnd.init(); | 80 fCoinEnd.init(); |
81 } | 81 } |
82 | 82 |
83 const SkTSect<OppCurve, TCurve>* debugOpp() const; | 83 const SkTSect<OppCurve, TCurve>* debugOpp() const; |
84 const SkTSpan* debugSpan(int ) const; | 84 const SkTSpan* debugSpan(int ) const; |
85 const SkTSpan* debugT(double t) const; | 85 const SkTSpan* debugT(double t) const; |
86 #ifdef SK_DEBUG | 86 #ifdef SK_DEBUG |
87 bool debugIsBefore(const SkTSpan* span) const; | 87 bool debugIsBefore(const SkTSpan* span) const; |
88 #endif | 88 #endif |
89 void dump() const; | 89 void dump() const; |
| 90 void dumpAll() const; |
90 void dumpBounded(int id) const; | 91 void dumpBounded(int id) const; |
91 void dumpBounds() const; | 92 void dumpBounds() const; |
92 void dumpCoin() const; | 93 void dumpCoin() const; |
93 | 94 |
94 double endT() const { | 95 double endT() const { |
95 return fEndT; | 96 return fEndT; |
96 } | 97 } |
97 | 98 |
98 SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp)
const; | 99 SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp)
const; |
99 | 100 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 result->splitAt(span, t, &fHeap); | 238 result->splitAt(span, t, &fHeap); |
238 result->initBounds(fCurve); | 239 result->initBounds(fCurve); |
239 span->initBounds(fCurve); | 240 span->initBounds(fCurve); |
240 return result; | 241 return result; |
241 } | 242 } |
242 | 243 |
243 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tSt
ep, double* t, | 244 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tSt
ep, double* t, |
244 double* oppT); | 245 double* oppT); |
245 SkTSpan<TCurve, OppCurve>* boundsMax() const; | 246 SkTSpan<TCurve, OppCurve>* boundsMax() const; |
246 void coincidentCheck(SkTSect<OppCurve, TCurve>* sect2); | 247 void coincidentCheck(SkTSect<OppCurve, TCurve>* sect2); |
| 248 void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, doubl
e start1e); |
247 bool coincidentHasT(double t); | 249 bool coincidentHasT(double t); |
248 int collapsed() const; | 250 int collapsed() const; |
249 void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve,
OppCurve>* first, | 251 void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve,
OppCurve>* first, |
250 SkTSpan<TCurve, OppCurve>* last); | 252 SkTSpan<TCurve, OppCurve>* last); |
251 int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first, | 253 int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first, |
252 SkTSpan<TCurve, OppCurve>** last) const; | 254 SkTSpan<TCurve, OppCurve>** last) const; |
253 | 255 |
254 int debugID() const { | 256 int debugID() const { |
255 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1); | 257 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1); |
256 } | 258 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 } | 380 } |
379 | 381 |
380 template<typename TCurve, typename OppCurve> | 382 template<typename TCurve, typename OppCurve> |
381 void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, doub
le t) { | 383 void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, doub
le t) { |
382 if (!span->hasOppT(t)) { | 384 if (!span->hasOppT(t)) { |
383 SkTSpan<TCurve, OppCurve>* priorSpan; | 385 SkTSpan<TCurve, OppCurve>* priorSpan; |
384 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan); | 386 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan); |
385 if (!opp) { | 387 if (!opp) { |
386 opp = this->addFollowing(priorSpan); | 388 opp = this->addFollowing(priorSpan); |
387 #if DEBUG_PERP | 389 #if DEBUG_PERP |
388 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan
->debugID(), t, | 390 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan
? |
389 opp->debugID()); | 391 priorSpan->debugID() : -1, t, opp->debugID()); |
390 #endif | 392 #endif |
391 } | 393 } |
392 #if DEBUG_PERP | 394 #if DEBUG_PERP |
393 opp->dump(); SkDebugf("\n"); | 395 opp->dump(); SkDebugf("\n"); |
394 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan->debu
gID(), | 396 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ? |
395 opp->debugID()); | 397 priorSpan->debugID() : -1, opp->debugID()); |
396 #endif | 398 #endif |
397 opp->addBounded(span, &fHeap); | 399 opp->addBounded(span, &fHeap); |
398 span->addBounded(opp, &fHeap); | 400 span->addBounded(opp, &fHeap); |
399 } | 401 } |
400 this->validate(); | 402 this->validate(); |
401 #if DEBUG_T_SECT | 403 #if DEBUG_T_SECT |
402 span->validatePerpT(t); | 404 span->validatePerpT(t); |
403 #endif | 405 #endif |
404 } | 406 } |
405 | 407 |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 testBounded = testBounded->fNext; | 787 testBounded = testBounded->fNext; |
786 } | 788 } |
787 #endif | 789 #endif |
788 } | 790 } |
789 | 791 |
790 template<typename TCurve, typename OppCurve> | 792 template<typename TCurve, typename OppCurve> |
791 void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const { | 793 void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const { |
792 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded; | 794 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded; |
793 while (testBounded) { | 795 while (testBounded) { |
794 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded; | 796 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded; |
795 if (between(overlap->fStartT, oppT, overlap->fEndT)) { | 797 if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) { |
796 return; | 798 return; |
797 } | 799 } |
798 testBounded = testBounded->fNext; | 800 testBounded = testBounded->fNext; |
799 } | 801 } |
800 SkASSERT(0); | 802 SkASSERT(0); |
801 } | 803 } |
802 | 804 |
803 template<typename TCurve, typename OppCurve> | 805 template<typename TCurve, typename OppCurve> |
804 void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) con
st { | 806 void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) con
st { |
805 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt); | 807 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 sect2->validate(); | 939 sect2->validate(); |
938 // check to see if a range of points are on the curve | 940 // check to see if a range of points are on the curve |
939 SkTSpan<TCurve, OppCurve>* coinStart = first; | 941 SkTSpan<TCurve, OppCurve>* coinStart = first; |
940 do { | 942 do { |
941 coinStart = this->extractCoincident(sect2, coinStart, last); | 943 coinStart = this->extractCoincident(sect2, coinStart, last); |
942 } while (coinStart && !last->fDeleted); | 944 } while (coinStart && !last->fDeleted); |
943 } while ((first = next)); | 945 } while ((first = next)); |
944 } | 946 } |
945 | 947 |
946 template<typename TCurve, typename OppCurve> | 948 template<typename TCurve, typename OppCurve> |
| 949 void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2
, |
| 950 double start1s, double start1e) { |
| 951 SkTSpan<TCurve, OppCurve>* first = fHead; |
| 952 SkTSpan<TCurve, OppCurve>* last = this->tail(); |
| 953 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead; |
| 954 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail(); |
| 955 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst); |
| 956 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first); |
| 957 this->removeSpanRange(first, last); |
| 958 sect2->removeSpanRange(oppFirst, oppLast); |
| 959 first->fStartT = start1s; |
| 960 first->fEndT = start1e; |
| 961 first->resetBounds(fCurve); |
| 962 first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve); |
| 963 first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->
fCurve); |
| 964 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT(); |
| 965 double oppStartT = SkTMax(0., first->fCoinStart.perpT()); |
| 966 double oppEndT = SkTMin(1., first->fCoinEnd.perpT()); |
| 967 if (!oppMatched) { |
| 968 SkTSwap(oppStartT, oppEndT); |
| 969 } |
| 970 oppFirst->fStartT = oppStartT; |
| 971 oppFirst->fEndT = oppEndT; |
| 972 oppFirst->resetBounds(sect2->fCurve); |
| 973 this->removeCoincident(first, false); |
| 974 sect2->removeCoincident(oppFirst, true); |
| 975 if (deleteEmptySpans) { |
| 976 this->deleteEmptySpans(); |
| 977 sect2->deleteEmptySpans(); |
| 978 } |
| 979 } |
| 980 |
| 981 template<typename TCurve, typename OppCurve> |
947 bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) { | 982 bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) { |
948 SkTSpan<TCurve, OppCurve>* test = fCoincident; | 983 SkTSpan<TCurve, OppCurve>* test = fCoincident; |
949 while (test) { | 984 while (test) { |
950 if (between(test->fStartT, t, test->fEndT)) { | 985 if (between(test->fStartT, t, test->fEndT)) { |
951 return true; | 986 return true; |
952 } | 987 } |
953 test = test->fNext; | 988 test = test->fNext; |
954 } | 989 } |
955 return false; | 990 return false; |
956 } | 991 } |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 *oppResult = 1; | 1254 *oppResult = 1; |
1220 } | 1255 } |
1221 } else { | 1256 } else { |
1222 *oppResult = 1; | 1257 *oppResult = 1; |
1223 } | 1258 } |
1224 return hullResult; | 1259 return hullResult; |
1225 } | 1260 } |
1226 if (span->fIsLine && oppSpan->fIsLine) { | 1261 if (span->fIsLine && oppSpan->fIsLine) { |
1227 SkIntersections i; | 1262 SkIntersections i; |
1228 int sects = this->linesIntersect(span, opp, oppSpan, &i); | 1263 int sects = this->linesIntersect(span, opp, oppSpan, &i); |
| 1264 if (sects == 2) { |
| 1265 return *oppResult = 1; |
| 1266 } |
1229 if (!sects) { | 1267 if (!sects) { |
1230 return -1; | 1268 return -1; |
1231 } | 1269 } |
1232 span->fStartT = span->fEndT = i[0][0]; | 1270 span->fStartT = span->fEndT = i[0][0]; |
1233 oppSpan->fStartT = oppSpan->fEndT = i[1][0]; | 1271 oppSpan->fStartT = oppSpan->fEndT = i[1][0]; |
1234 return *oppResult = 2; | 1272 return *oppResult = 2; |
1235 } | 1273 } |
1236 if (span->fIsLinear || oppSpan->fIsLinear) { | 1274 if (span->fIsLinear || oppSpan->fIsLinear) { |
1237 return *oppResult = (int) span->linearsIntersect(oppSpan); | 1275 return *oppResult = (int) span->linearsIntersect(oppSpan); |
1238 } | 1276 } |
(...skipping 11 matching lines...) Expand all Loading... |
1250 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }}; | 1288 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }}; |
1251 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast]
}}; | 1289 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast]
}}; |
1252 int loopCount = 0; | 1290 int loopCount = 0; |
1253 double bestDistSq = DBL_MAX; | 1291 double bestDistSq = DBL_MAX; |
1254 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) { | 1292 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) { |
1255 return 0; | 1293 return 0; |
1256 } | 1294 } |
1257 if (!oppRayI.intersectRay(this->fCurve, oppLine)) { | 1295 if (!oppRayI.intersectRay(this->fCurve, oppLine)) { |
1258 return 0; | 1296 return 0; |
1259 } | 1297 } |
| 1298 // if the ends of each line intersect the opposite curve, the lines are coin
cident |
| 1299 if (thisRayI.used() > 1) { |
| 1300 int ptMatches = 0; |
| 1301 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) { |
| 1302 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); +
+lIndex) { |
| 1303 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPt
s[lIndex]); |
| 1304 } |
| 1305 } |
| 1306 if (ptMatches == 2) { |
| 1307 return 2; |
| 1308 } |
| 1309 } |
| 1310 if (oppRayI.used() > 1) { |
| 1311 int ptMatches = 0; |
| 1312 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) { |
| 1313 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); +
+lIndex) { |
| 1314 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[
lIndex]); |
| 1315 } |
| 1316 } |
| 1317 if (ptMatches == 2) { |
| 1318 return 2; |
| 1319 } |
| 1320 } |
1260 do { | 1321 do { |
1261 // pick the closest pair of points | 1322 // pick the closest pair of points |
1262 double closest = DBL_MAX; | 1323 double closest = DBL_MAX; |
1263 int closeIndex SK_INIT_TO_AVOID_WARNING; | 1324 int closeIndex SK_INIT_TO_AVOID_WARNING; |
1264 int oppCloseIndex SK_INIT_TO_AVOID_WARNING; | 1325 int oppCloseIndex SK_INIT_TO_AVOID_WARNING; |
1265 for (int index = 0; index < oppRayI.used(); ++index) { | 1326 for (int index = 0; index < oppRayI.used(); ++index) { |
1266 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT))
{ | 1327 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT))
{ |
1267 continue; | 1328 continue; |
1268 } | 1329 } |
1269 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) { | 1330 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) { |
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1914 // SkASSERT(between(0, sect, 2)); | 1975 // SkASSERT(between(0, sect, 2)); |
1915 if (!sect) { | 1976 if (!sect) { |
1916 return; | 1977 return; |
1917 } | 1978 } |
1918 if (sect == 2 && oppSect == 2) { | 1979 if (sect == 2 && oppSect == 2) { |
1919 (void) EndsEqual(sect1, sect2, intersections); | 1980 (void) EndsEqual(sect1, sect2, intersections); |
1920 return; | 1981 return; |
1921 } | 1982 } |
1922 span1->addBounded(span2, §1->fHeap); | 1983 span1->addBounded(span2, §1->fHeap); |
1923 span2->addBounded(span1, §2->fHeap); | 1984 span2->addBounded(span1, §2->fHeap); |
| 1985 const int kMaxCoinLoopCount = 8; |
| 1986 int coinLoopCount = kMaxCoinLoopCount; |
| 1987 double start1s SK_INIT_TO_AVOID_WARNING; |
| 1988 double start1e SK_INIT_TO_AVOID_WARNING; |
1924 do { | 1989 do { |
1925 // find the largest bounds | 1990 // find the largest bounds |
1926 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax(); | 1991 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax(); |
1927 if (!largest1) { | 1992 if (!largest1) { |
1928 break; | 1993 break; |
1929 } | 1994 } |
1930 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax(); | 1995 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax(); |
1931 // split it | 1996 // split it |
1932 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsM
ax | 1997 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsM
ax |
1933 || (!largest1->fCollapsed && largest2->fCollapsed)))) { | 1998 || (!largest1->fCollapsed && largest2->fCollapsed)))) { |
(...skipping 14 matching lines...) Expand all Loading... |
1948 // trim parts that don't intersect the opposite | 2013 // trim parts that don't intersect the opposite |
1949 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne(); | 2014 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne(); |
1950 if (!half2->split(largest2, §2->fHeap)) { | 2015 if (!half2->split(largest2, §2->fHeap)) { |
1951 break; | 2016 break; |
1952 } | 2017 } |
1953 sect2->trim(largest2, sect1); | 2018 sect2->trim(largest2, sect1); |
1954 sect2->trim(half2, sect1); | 2019 sect2->trim(half2, sect1); |
1955 } | 2020 } |
1956 sect1->validate(); | 2021 sect1->validate(); |
1957 sect2->validate(); | 2022 sect2->validate(); |
| 2023 #if DEBUG_T_SECT_LOOP_COUNT |
| 2024 intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop
); |
| 2025 #endif |
1958 // if there are 9 or more continuous spans on both sects, suspect coinci
dence | 2026 // if there are 9 or more continuous spans on both sects, suspect coinci
dence |
1959 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT | 2027 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT |
1960 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { | 2028 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { |
| 2029 if (coinLoopCount == kMaxCoinLoopCount) { |
| 2030 start1s = sect1->fHead->fStartT; |
| 2031 start1e = sect1->tail()->fEndT; |
| 2032 } |
1961 sect1->coincidentCheck(sect2); | 2033 sect1->coincidentCheck(sect2); |
1962 sect1->validate(); | 2034 sect1->validate(); |
1963 sect2->validate(); | 2035 sect2->validate(); |
| 2036 #if DEBUG_T_SECT_LOOP_COUNT |
| 2037 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugL
oop); |
| 2038 #endif |
| 2039 if (!--coinLoopCount) { |
| 2040 /* All known working cases resolve in two tries. Sadly, cubicCon
icTests[0] |
| 2041 gets stuck in a loop. It adds an extension to allow a coincid
ent end |
| 2042 perpendicular to track its intersection in the opposite curve
. However, |
| 2043 the bounding box of the extension does not intersect the orig
inal curve, |
| 2044 so the extension is discarded, only to be added again the nex
t time around. */ |
| 2045 sect1->coincidentForce(sect2, start1s, start1e); |
| 2046 sect1->validate(); |
| 2047 sect2->validate(); |
| 2048 } |
1964 } | 2049 } |
1965 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT | 2050 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT |
1966 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { | 2051 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { |
1967 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail()); | 2052 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail()); |
1968 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail()); | 2053 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail()); |
1969 sect1->removeByPerpendicular(sect2); | 2054 sect1->removeByPerpendicular(sect2); |
1970 sect1->validate(); | 2055 sect1->validate(); |
1971 sect2->validate(); | 2056 sect2->validate(); |
| 2057 #if DEBUG_T_SECT_LOOP_COUNT |
| 2058 intersections->debugBumpLoopCount(SkIntersections::kComputePerp_Debu
gLoop); |
| 2059 #endif |
1972 if (sect1->collapsed() > TCurve::kMaxIntersections) { | 2060 if (sect1->collapsed() > TCurve::kMaxIntersections) { |
1973 break; | 2061 break; |
1974 } | 2062 } |
1975 } | 2063 } |
1976 #if DEBUG_T_SECT_DUMP | 2064 #if DEBUG_T_SECT_DUMP |
1977 sect1->dumpBoth(sect2); | 2065 sect1->dumpBoth(sect2); |
1978 #endif | 2066 #endif |
1979 if (!sect1->fHead || !sect2->fHead) { | 2067 if (!sect1->fHead || !sect2->fHead) { |
1980 break; | 2068 break; |
1981 } | 2069 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2086 } else if (intersections->isCoincident(index + 1)) { | 2174 } else if (intersections->isCoincident(index + 1)) { |
2087 intersections->removeOne(index + 1); | 2175 intersections->removeOne(index + 1); |
2088 --last; | 2176 --last; |
2089 } else { | 2177 } else { |
2090 intersections->setCoincident(index++); | 2178 intersections->setCoincident(index++); |
2091 } | 2179 } |
2092 intersections->setCoincident(index); | 2180 intersections->setCoincident(index); |
2093 } | 2181 } |
2094 SkASSERT(intersections->used() <= TCurve::kMaxIntersections); | 2182 SkASSERT(intersections->used() <= TCurve::kMaxIntersections); |
2095 } | 2183 } |
OLD | NEW |