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 #ifndef SkPathOpsTSect_DEFINED | 7 #ifndef SkPathOpsTSect_DEFINED |
8 #define SkPathOpsTSect_DEFINED | 8 #define SkPathOpsTSect_DEFINED |
9 | 9 |
10 #include "SkChunkAlloc.h" | 10 #include "SkChunkAlloc.h" |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 enum { | 243 enum { |
244 kZeroS1Set = 1, | 244 kZeroS1Set = 1, |
245 kOneS1Set = 2, | 245 kOneS1Set = 2, |
246 kZeroS2Set = 4, | 246 kZeroS2Set = 4, |
247 kOneS2Set = 8 | 247 kOneS2Set = 8 |
248 }; | 248 }; |
249 | 249 |
250 SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior); | 250 SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior); |
251 void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t); | 251 void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t); |
252 SkTSpan<TCurve, OppCurve>* addOne(); | 252 SkTSpan<TCurve, OppCurve>* addOne(); |
253 | 253 |
254 SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, doubl
e t) { | 254 SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, doubl
e t) { |
255 SkTSpan<TCurve, OppCurve>* result = this->addOne(); | 255 SkTSpan<TCurve, OppCurve>* result = this->addOne(); |
256 result->splitAt(span, t, &fHeap); | 256 result->splitAt(span, t, &fHeap); |
257 result->initBounds(fCurve); | 257 result->initBounds(fCurve); |
258 span->initBounds(fCurve); | 258 span->initBounds(fCurve); |
259 return result; | 259 return result; |
260 } | 260 } |
261 | 261 |
262 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tSt
ep, double* t, | 262 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tSt
ep, double* t, |
263 double* oppT); | 263 double* oppT); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t, | 336 void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t, |
337 const SkDPoint& cPt, const OppCurve& c2) { | 337 const SkDPoint& cPt, const OppCurve& c2) { |
338 SkDVector dxdy = c1.dxdyAtT(t); | 338 SkDVector dxdy = c1.dxdyAtT(t); |
339 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }}; | 339 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }}; |
340 SkIntersections i; | 340 SkIntersections i; |
341 int used = i.intersectRay(c2, perp); | 341 int used = i.intersectRay(c2, perp); |
342 // only keep closest | 342 // only keep closest |
343 if (used == 0 || used == 3) { | 343 if (used == 0 || used == 3) { |
344 this->init(); | 344 this->init(); |
345 return; | 345 return; |
346 } | 346 } |
347 fPerpT = i[0][0]; | 347 fPerpT = i[0][0]; |
348 fPerpPt = i.pt(0); | 348 fPerpPt = i.pt(0); |
349 SkASSERT(used <= 2); | 349 SkASSERT(used <= 2); |
350 if (used == 2) { | 350 if (used == 2) { |
351 double distSq = (fPerpPt - cPt).lengthSquared(); | 351 double distSq = (fPerpPt - cPt).lengthSquared(); |
352 double dist2Sq = (i.pt(1) - cPt).lengthSquared(); | 352 double dist2Sq = (i.pt(1) - cPt).lengthSquared(); |
353 if (dist2Sq < distSq) { | 353 if (dist2Sq < distSq) { |
354 fPerpT = i[0][1]; | 354 fPerpT = i[0][1]; |
355 fPerpPt = i.pt(1); | 355 fPerpPt = i.pt(1); |
356 } | 356 } |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 } else { | 851 } else { |
852 result = new (fHeap.allocThrow(sizeof(SkTSpan<TCurve, OppCurve>)))( | 852 result = new (fHeap.allocThrow(sizeof(SkTSpan<TCurve, OppCurve>)))( |
853 SkTSpan<TCurve, OppCurve>); | 853 SkTSpan<TCurve, OppCurve>); |
854 #if DEBUG_T_SECT | 854 #if DEBUG_T_SECT |
855 ++fDebugAllocatedCount; | 855 ++fDebugAllocatedCount; |
856 #endif | 856 #endif |
857 } | 857 } |
858 result->reset(); | 858 result->reset(); |
859 result->fHasPerp = false; | 859 result->fHasPerp = false; |
860 result->fDeleted = false; | 860 result->fDeleted = false; |
861 ++fActiveCount; | 861 ++fActiveCount; |
862 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID); | 862 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID); |
863 SkDEBUGCODE(result->fDebugSect = this); | 863 SkDEBUGCODE(result->fDebugSect = this); |
864 #ifdef SK_DEBUG | 864 #ifdef SK_DEBUG |
865 result->fPart.debugInit(); | 865 result->fPart.debugInit(); |
866 result->fCoinStart.debugInit(); | 866 result->fCoinStart.debugInit(); |
867 result->fCoinEnd.debugInit(); | 867 result->fCoinEnd.debugInit(); |
868 result->fPrev = result->fNext = nullptr; | 868 result->fPrev = result->fNext = nullptr; |
869 result->fBounds.debugInit(); | 869 result->fBounds.debugInit(); |
870 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN; | 870 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN; |
871 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF; | 871 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 this->validate(); | 962 this->validate(); |
963 sect2->validate(); | 963 sect2->validate(); |
964 this->computePerpendiculars(sect2, first, last); | 964 this->computePerpendiculars(sect2, first, last); |
965 this->validate(); | 965 this->validate(); |
966 sect2->validate(); | 966 sect2->validate(); |
967 // check to see if a range of points are on the curve | 967 // check to see if a range of points are on the curve |
968 SkTSpan<TCurve, OppCurve>* coinStart = first; | 968 SkTSpan<TCurve, OppCurve>* coinStart = first; |
969 do { | 969 do { |
970 coinStart = this->extractCoincident(sect2, coinStart, last); | 970 coinStart = this->extractCoincident(sect2, coinStart, last); |
971 } while (coinStart && !last->fDeleted); | 971 } while (coinStart && !last->fDeleted); |
| 972 if (!fHead || !sect2->fHead) { |
| 973 break; |
| 974 } |
972 } while ((first = next)); | 975 } while ((first = next)); |
973 } | 976 } |
974 | 977 |
975 template<typename TCurve, typename OppCurve> | 978 template<typename TCurve, typename OppCurve> |
976 void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2
, | 979 void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2
, |
977 double start1s, double start1e) { | 980 double start1s, double start1e) { |
978 SkTSpan<TCurve, OppCurve>* first = fHead; | 981 SkTSpan<TCurve, OppCurve>* first = fHead; |
979 SkTSpan<TCurve, OppCurve>* last = this->tail(); | 982 SkTSpan<TCurve, OppCurve>* last = this->tail(); |
980 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead; | 983 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead; |
981 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail(); | 984 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail(); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 sect2->validateBounded(); | 1204 sect2->validateBounded(); |
1202 last = first->fNext; | 1205 last = first->fNext; |
1203 this->removeCoincident(first, false); | 1206 this->removeCoincident(first, false); |
1204 sect2->removeCoincident(oppFirst, true); | 1207 sect2->removeCoincident(oppFirst, true); |
1205 if (deleteEmptySpans) { | 1208 if (deleteEmptySpans) { |
1206 this->deleteEmptySpans(); | 1209 this->deleteEmptySpans(); |
1207 sect2->deleteEmptySpans(); | 1210 sect2->deleteEmptySpans(); |
1208 } | 1211 } |
1209 this->validate(); | 1212 this->validate(); |
1210 sect2->validate(); | 1213 sect2->validate(); |
1211 return last && !last->fDeleted ? last : nullptr; | 1214 return last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr; |
1212 } | 1215 } |
1213 | 1216 |
1214 template<typename TCurve, typename OppCurve> | 1217 template<typename TCurve, typename OppCurve> |
1215 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun( | 1218 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun( |
1216 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) { | 1219 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) { |
1217 SkTSpan<TCurve, OppCurve>* work = first; | 1220 SkTSpan<TCurve, OppCurve>* work = first; |
1218 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr; | 1221 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr; |
1219 first = nullptr; | 1222 first = nullptr; |
1220 // find the first fully coincident span | 1223 // find the first fully coincident span |
1221 do { | 1224 do { |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 double t2) const { | 1507 double t2) const { |
1505 SkDVector dxdy = this->fCurve.dxdyAtT(t); | 1508 SkDVector dxdy = this->fCurve.dxdyAtT(t); |
1506 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2); | 1509 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2); |
1507 return dxdy.dot(dxdy2) >= 0; | 1510 return dxdy.dot(dxdy2) >= 0; |
1508 } | 1511 } |
1509 | 1512 |
1510 template<typename TCurve, typename OppCurve> | 1513 template<typename TCurve, typename OppCurve> |
1511 void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve
, TCurve>* sect2, | 1514 void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve
, TCurve>* sect2, |
1512 double t2, bool* calcMatched, bool* oppMatched) const { | 1515 double t2, bool* calcMatched, bool* oppMatched) const { |
1513 if (*calcMatched) { | 1516 if (*calcMatched) { |
1514 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2)); | 1517 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2)); |
1515 } else { | 1518 } else { |
1516 *oppMatched = this->matchedDirection(t, sect2, t2); | 1519 *oppMatched = this->matchedDirection(t, sect2, t2); |
1517 *calcMatched = true; | 1520 *calcMatched = true; |
1518 } | 1521 } |
1519 } | 1522 } |
1520 | 1523 |
1521 template<typename TCurve, typename OppCurve> | 1524 template<typename TCurve, typename OppCurve> |
1522 void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect
2) { | 1525 void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect
2) { |
1523 double smallLimit = 0; | 1526 double smallLimit = 0; |
1524 do { | 1527 do { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1577 template<typename TCurve, typename OppCurve> | 1580 template<typename TCurve, typename OppCurve> |
1578 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev( | 1581 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev( |
1579 SkTSpan<TCurve, OppCurve>* span) const { | 1582 SkTSpan<TCurve, OppCurve>* span) const { |
1580 SkTSpan<TCurve, OppCurve>* result = nullptr; | 1583 SkTSpan<TCurve, OppCurve>* result = nullptr; |
1581 SkTSpan<TCurve, OppCurve>* test = fHead; | 1584 SkTSpan<TCurve, OppCurve>* test = fHead; |
1582 while (span != test) { | 1585 while (span != test) { |
1583 result = test; | 1586 result = test; |
1584 test = test->fNext; | 1587 test = test->fNext; |
1585 SkASSERT(test); | 1588 SkASSERT(test); |
1586 } | 1589 } |
1587 return result; | 1590 return result; |
1588 } | 1591 } |
1589 | 1592 |
1590 template<typename TCurve, typename OppCurve> | 1593 template<typename TCurve, typename OppCurve> |
1591 void SkTSect<TCurve, OppCurve>::recoverCollapsed() { | 1594 void SkTSect<TCurve, OppCurve>::recoverCollapsed() { |
1592 SkTSpan<TCurve, OppCurve>* deleted = fDeleted; | 1595 SkTSpan<TCurve, OppCurve>* deleted = fDeleted; |
1593 while (deleted) { | 1596 while (deleted) { |
1594 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext; | 1597 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext; |
1595 if (deleted->fCollapsed) { | 1598 if (deleted->fCollapsed) { |
1596 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead; | 1599 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead; |
1597 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) { | 1600 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) { |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1932 || fC2Span->startT() == mate.fC2Span->endT(); | 1935 || fC2Span->startT() == mate.fC2Span->endT(); |
1933 } | 1936 } |
1934 | 1937 |
1935 void merge(const SkClosestRecord& mate) { | 1938 void merge(const SkClosestRecord& mate) { |
1936 fC1Span = mate.fC1Span; | 1939 fC1Span = mate.fC1Span; |
1937 fC2Span = mate.fC2Span; | 1940 fC2Span = mate.fC2Span; |
1938 fClosest = mate.fClosest; | 1941 fClosest = mate.fClosest; |
1939 fC1Index = mate.fC1Index; | 1942 fC1Index = mate.fC1Index; |
1940 fC2Index = mate.fC2Index; | 1943 fC2Index = mate.fC2Index; |
1941 } | 1944 } |
1942 | 1945 |
1943 void reset() { | 1946 void reset() { |
1944 fClosest = FLT_MAX; | 1947 fClosest = FLT_MAX; |
1945 SkDEBUGCODE(fC1Span = nullptr); | 1948 SkDEBUGCODE(fC1Span = nullptr); |
1946 SkDEBUGCODE(fC2Span = nullptr); | 1949 SkDEBUGCODE(fC2Span = nullptr); |
1947 SkDEBUGCODE(fC1Index = fC2Index = -1); | 1950 SkDEBUGCODE(fC1Index = fC2Index = -1); |
1948 } | 1951 } |
1949 | 1952 |
1950 void update(const SkClosestRecord& mate) { | 1953 void update(const SkClosestRecord& mate) { |
1951 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT); | 1954 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT); |
1952 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT); | 1955 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2092 sect1->validate(); | 2095 sect1->validate(); |
2093 sect2->validate(); | 2096 sect2->validate(); |
2094 #if DEBUG_T_SECT_LOOP_COUNT | 2097 #if DEBUG_T_SECT_LOOP_COUNT |
2095 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugL
oop); | 2098 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugL
oop); |
2096 #endif | 2099 #endif |
2097 if (!--coinLoopCount && sect1->fHead && sect2->fHead) { | 2100 if (!--coinLoopCount && sect1->fHead && sect2->fHead) { |
2098 /* All known working cases resolve in two tries. Sadly, cubicCon
icTests[0] | 2101 /* All known working cases resolve in two tries. Sadly, cubicCon
icTests[0] |
2099 gets stuck in a loop. It adds an extension to allow a coincid
ent end | 2102 gets stuck in a loop. It adds an extension to allow a coincid
ent end |
2100 perpendicular to track its intersection in the opposite curve
. However, | 2103 perpendicular to track its intersection in the opposite curve
. However, |
2101 the bounding box of the extension does not intersect the orig
inal curve, | 2104 the bounding box of the extension does not intersect the orig
inal curve, |
2102 so the extension is discarded, only to be added again the nex
t time around. */ | 2105 so the extension is discarded, only to be added again the nex
t time around. */ |
2103 sect1->coincidentForce(sect2, start1s, start1e); | 2106 sect1->coincidentForce(sect2, start1s, start1e); |
2104 sect1->validate(); | 2107 sect1->validate(); |
2105 sect2->validate(); | 2108 sect2->validate(); |
2106 } | 2109 } |
2107 } | 2110 } |
2108 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT | 2111 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT |
2109 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { | 2112 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { |
2110 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail()); | 2113 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail()); |
2111 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail()); | 2114 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail()); |
2112 sect1->removeByPerpendicular(sect2); | 2115 sect1->removeByPerpendicular(sect2); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2238 --last; | 2241 --last; |
2239 } else { | 2242 } else { |
2240 intersections->setCoincident(index++); | 2243 intersections->setCoincident(index++); |
2241 } | 2244 } |
2242 intersections->setCoincident(index); | 2245 intersections->setCoincident(index); |
2243 } | 2246 } |
2244 SkASSERT(intersections->used() <= TCurve::kMaxIntersections); | 2247 SkASSERT(intersections->used() <= TCurve::kMaxIntersections); |
2245 } | 2248 } |
2246 | 2249 |
2247 #endif | 2250 #endif |
OLD | NEW |