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 13 matching lines...) Expand all Loading... |
24 class SkTCoincident { | 24 class SkTCoincident { |
25 public: | 25 public: |
26 SkTCoincident() { | 26 SkTCoincident() { |
27 this->init(); | 27 this->init(); |
28 } | 28 } |
29 | 29 |
30 void debugInit() { | 30 void debugInit() { |
31 #ifdef SK_DEBUG | 31 #ifdef SK_DEBUG |
32 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN; | 32 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN; |
33 this->fPerpT = SK_ScalarNaN; | 33 this->fPerpT = SK_ScalarNaN; |
34 this->fCoincident = 0xFF; | 34 this->fMatch = 0xFF; |
35 #endif | 35 #endif |
36 } | 36 } |
37 | 37 |
38 char dumpIsCoincidentStr() const; | 38 char dumpIsCoincidentStr() const; |
39 void dump() const; | 39 void dump() const; |
40 | 40 |
41 bool isCoincident() const { | 41 bool isMatch() const { |
42 SkASSERT(!!fCoincident == fCoincident); | 42 SkASSERT(!!fMatch == fMatch); |
43 return SkToBool(fCoincident); | 43 return SkToBool(fMatch); |
44 } | 44 } |
45 | 45 |
46 void init() { | 46 void init() { |
47 fPerpT = -1; | 47 fPerpT = -1; |
48 fCoincident = false; | 48 fMatch = false; |
49 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN; | 49 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN; |
50 } | 50 } |
51 | 51 |
52 void markCoincident() { | 52 void markCoincident() { |
53 if (!fCoincident) { | 53 if (!fMatch) { |
54 fPerpT = -1; | 54 fPerpT = -1; |
55 } | 55 } |
56 fCoincident = true; | 56 fMatch = true; |
57 } | 57 } |
58 | 58 |
59 const SkDPoint& perpPt() const { | 59 const SkDPoint& perpPt() const { |
60 return fPerpPt; | 60 return fPerpPt; |
61 } | 61 } |
62 | 62 |
63 double perpT() const { | 63 double perpT() const { |
64 return fPerpT; | 64 return fPerpT; |
65 } | 65 } |
66 | 66 |
67 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve
& ); | 67 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve
& ); |
68 | 68 |
69 private: | 69 private: |
70 SkDPoint fPerpPt; | 70 SkDPoint fPerpPt; |
71 double fPerpT; // perpendicular intersection on opposite curve | 71 double fPerpT; // perpendicular intersection on opposite curve |
72 SkOpDebugBool fCoincident; | 72 SkOpDebugBool fMatch; |
73 }; | 73 }; |
74 | 74 |
75 template<typename TCurve, typename OppCurve> class SkTSect; | 75 template<typename TCurve, typename OppCurve> class SkTSect; |
76 template<typename TCurve, typename OppCurve> class SkTSpan; | 76 template<typename TCurve, typename OppCurve> class SkTSpan; |
77 | 77 |
78 template<typename TCurve, typename OppCurve> | 78 template<typename TCurve, typename OppCurve> |
79 struct SkTSpanBounded { | 79 struct SkTSpanBounded { |
80 SkTSpan<TCurve, OppCurve>* fBounded; | 80 SkTSpan<TCurve, OppCurve>* fBounded; |
81 SkTSpanBounded* fNext; | 81 SkTSpanBounded* fNext; |
82 }; | 82 }; |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 SkTSpan<OppCurve, TCurve>* oppFirst); | 323 SkTSpan<OppCurve, TCurve>* oppFirst); |
324 void validate() const; | 324 void validate() const; |
325 void validateBounded() const; | 325 void validateBounded() const; |
326 | 326 |
327 const TCurve& fCurve; | 327 const TCurve& fCurve; |
328 SkChunkAlloc fHeap; | 328 SkChunkAlloc fHeap; |
329 SkTSpan<TCurve, OppCurve>* fHead; | 329 SkTSpan<TCurve, OppCurve>* fHead; |
330 SkTSpan<TCurve, OppCurve>* fCoincident; | 330 SkTSpan<TCurve, OppCurve>* fCoincident; |
331 SkTSpan<TCurve, OppCurve>* fDeleted; | 331 SkTSpan<TCurve, OppCurve>* fDeleted; |
332 int fActiveCount; | 332 int fActiveCount; |
| 333 bool fRemovedStartT; |
| 334 bool fRemovedEndT; |
333 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState); | 335 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState); |
334 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect); | 336 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect); |
335 PATH_OPS_DEBUG_T_SECT_CODE(int fID); | 337 PATH_OPS_DEBUG_T_SECT_CODE(int fID); |
336 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount); | 338 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount); |
337 #if DEBUG_T_SECT | 339 #if DEBUG_T_SECT |
338 int fDebugAllocatedCount; | 340 int fDebugAllocatedCount; |
339 #endif | 341 #endif |
340 friend class SkTSpan<TCurve, OppCurve>; | 342 friend class SkTSpan<TCurve, OppCurve>; |
341 friend class SkTSpan<OppCurve, TCurve>; | 343 friend class SkTSpan<OppCurve, TCurve>; |
342 friend class SkTSect<OppCurve, TCurve>; | 344 friend class SkTSect<OppCurve, TCurve>; |
(...skipping 22 matching lines...) Expand all Loading... |
365 if (dist2Sq < distSq) { | 367 if (dist2Sq < distSq) { |
366 fPerpT = i[0][1]; | 368 fPerpT = i[0][1]; |
367 fPerpPt = i.pt(1); | 369 fPerpPt = i.pt(1); |
368 } | 370 } |
369 } | 371 } |
370 #if DEBUG_T_SECT | 372 #if DEBUG_T_SECT |
371 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.
9g)\n", | 373 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.
9g)\n", |
372 t, cPt.fX, cPt.fY, | 374 t, cPt.fX, cPt.fY, |
373 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, f
PerpPt.fY); | 375 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, f
PerpPt.fY); |
374 #endif | 376 #endif |
375 fCoincident = cPt.approximatelyEqual(fPerpPt); | 377 fMatch = cPt.approximatelyEqual(fPerpPt); |
376 #if DEBUG_T_SECT | 378 #if DEBUG_T_SECT |
377 if (fCoincident) { | 379 if (fMatch) { |
378 SkDebugf(""); // allow setting breakpoint | 380 SkDebugf(""); // allow setting breakpoint |
379 } | 381 } |
380 #endif | 382 #endif |
381 } | 383 } |
382 | 384 |
383 template<typename TCurve, typename OppCurve> | 385 template<typename TCurve, typename OppCurve> |
384 void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkCh
unkAlloc* heap) { | 386 void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkCh
unkAlloc* heap) { |
385 SkTSpanBounded<OppCurve, TCurve>* bounded = new (heap->allocThrow( | 387 SkTSpanBounded<OppCurve, TCurve>* bounded = new (heap->allocThrow( |
386 sizeof(SkTSpanBounded<OppCurve, TCurve>)))(SkTSpanBounded<OppCurve,
TCurve>); | 388 sizeof(SkTSpanBounded<OppCurve, TCurve>)))(SkTSpanBounded<OppCurve,
TCurve>); |
387 bounded->fBounded = span; | 389 bounded->fBounded = span; |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 this->validateBounded(); | 796 this->validateBounded(); |
795 #endif | 797 #endif |
796 #if DEBUG_T_SECT | 798 #if DEBUG_T_SECT |
797 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed); | 799 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed); |
798 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollaps
ed == 0xFF); | 800 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollaps
ed == 0xFF); |
799 SkASSERT(0 <= fStartT); | 801 SkASSERT(0 <= fStartT); |
800 SkASSERT(fEndT <= 1); | 802 SkASSERT(fEndT <= 1); |
801 SkASSERT(fStartT <= fEndT); | 803 SkASSERT(fStartT <= fEndT); |
802 SkASSERT(fBounded || fCollapsed == 0xFF); | 804 SkASSERT(fBounded || fCollapsed == 0xFF); |
803 if (fHasPerp) { | 805 if (fHasPerp) { |
804 if (fCoinStart.isCoincident()) { | 806 if (fCoinStart.isMatch()) { |
805 validatePerpT(fCoinStart.perpT()); | 807 validatePerpT(fCoinStart.perpT()); |
806 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt()); | 808 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt()); |
807 } | 809 } |
808 if (fCoinEnd.isCoincident()) { | 810 if (fCoinEnd.isMatch()) { |
809 validatePerpT(fCoinEnd.perpT()); | 811 validatePerpT(fCoinEnd.perpT()); |
810 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt()); | 812 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt()); |
811 } | 813 } |
812 } | 814 } |
813 #endif | 815 #endif |
814 } | 816 } |
815 | 817 |
816 template<typename TCurve, typename OppCurve> | 818 template<typename TCurve, typename OppCurve> |
817 void SkTSpan<TCurve, OppCurve>::validateBounded() const { | 819 void SkTSpan<TCurve, OppCurve>::validateBounded() const { |
818 #if DEBUG_VALIDATE | 820 #if DEBUG_VALIDATE |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 } | 921 } |
920 work.initBounds(fCurve); | 922 work.initBounds(fCurve); |
921 if (work.fCollapsed) { | 923 if (work.fCollapsed) { |
922 return false; | 924 return false; |
923 } | 925 } |
924 if (last.approximatelyEqual(work.fPart[0])) { | 926 if (last.approximatelyEqual(work.fPart[0])) { |
925 break; | 927 break; |
926 } | 928 } |
927 last = work.fPart[0]; | 929 last = work.fPart[0]; |
928 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp); | 930 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp); |
929 if (work.fCoinStart.isCoincident()) { | 931 if (work.fCoinStart.isMatch()) { |
930 #if DEBUG_T_SECT | 932 #if DEBUG_T_SECT |
931 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt(
)); | 933 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt(
)); |
932 #endif | 934 #endif |
933 double oppTTest = work.fCoinStart.perpT(); | 935 double oppTTest = work.fCoinStart.perpT(); |
934 if (sect2->fHead->contains(oppTTest)) { | 936 if (sect2->fHead->contains(oppTTest)) { |
935 *oppT = oppTTest; | 937 *oppT = oppTTest; |
936 oppPt = work.fCoinStart.perpPt(); | 938 oppPt = work.fCoinStart.perpPt(); |
937 contained = true; | 939 contained = true; |
938 SkASSERT(down ? result > work.fStartT : result < work.fStartT); | 940 SkASSERT(down ? result > work.fStartT : result < work.fStartT); |
939 result = work.fStartT; | 941 result = work.fStartT; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 const OppCurve& opp = sect2->fCurve; | 1078 const OppCurve& opp = sect2->fCurve; |
1077 SkTSpan<TCurve, OppCurve>* work = first; | 1079 SkTSpan<TCurve, OppCurve>* work = first; |
1078 SkTSpan<TCurve, OppCurve>* prior = nullptr; | 1080 SkTSpan<TCurve, OppCurve>* prior = nullptr; |
1079 do { | 1081 do { |
1080 if (!work->fHasPerp && !work->fCollapsed) { | 1082 if (!work->fHasPerp && !work->fCollapsed) { |
1081 if (prior) { | 1083 if (prior) { |
1082 work->fCoinStart = prior->fCoinEnd; | 1084 work->fCoinStart = prior->fCoinEnd; |
1083 } else { | 1085 } else { |
1084 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0],
opp); | 1086 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0],
opp); |
1085 } | 1087 } |
1086 if (work->fCoinStart.isCoincident()) { | 1088 if (work->fCoinStart.isMatch()) { |
1087 double perpT = work->fCoinStart.perpT(); | 1089 double perpT = work->fCoinStart.perpT(); |
1088 if (sect2->coincidentHasT(perpT)) { | 1090 if (sect2->coincidentHasT(perpT)) { |
1089 work->fCoinStart.init(); | 1091 work->fCoinStart.init(); |
1090 } else { | 1092 } else { |
1091 sect2->addForPerp(work, perpT); | 1093 sect2->addForPerp(work, perpT); |
1092 } | 1094 } |
1093 } | 1095 } |
1094 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPoi
ntLast], opp); | 1096 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPoi
ntLast], opp); |
1095 if (work->fCoinEnd.isCoincident()) { | 1097 if (work->fCoinEnd.isMatch()) { |
1096 double perpT = work->fCoinEnd.perpT(); | 1098 double perpT = work->fCoinEnd.perpT(); |
1097 if (sect2->coincidentHasT(perpT)) { | 1099 if (sect2->coincidentHasT(perpT)) { |
1098 work->fCoinEnd.init(); | 1100 work->fCoinEnd.init(); |
1099 } else { | 1101 } else { |
1100 sect2->addForPerp(work, perpT); | 1102 sect2->addForPerp(work, perpT); |
1101 } | 1103 } |
1102 } | 1104 } |
1103 work->fHasPerp = true; | 1105 work->fHasPerp = true; |
1104 } | 1106 } |
1105 if (work == last) { | 1107 if (work == last) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 first = findCoincidentRun(first, &last); | 1170 first = findCoincidentRun(first, &last); |
1169 if (!first || !last) { | 1171 if (!first || !last) { |
1170 *result = nullptr; | 1172 *result = nullptr; |
1171 return true; | 1173 return true; |
1172 } | 1174 } |
1173 // march outwards to find limit of coincidence from here to previous and nex
t spans | 1175 // march outwards to find limit of coincidence from here to previous and nex
t spans |
1174 double startT = first->fStartT; | 1176 double startT = first->fStartT; |
1175 double oppStartT SK_INIT_TO_AVOID_WARNING; | 1177 double oppStartT SK_INIT_TO_AVOID_WARNING; |
1176 double oppEndT SK_INIT_TO_AVOID_WARNING; | 1178 double oppEndT SK_INIT_TO_AVOID_WARNING; |
1177 SkTSpan<TCurve, OppCurve>* prev = first->fPrev; | 1179 SkTSpan<TCurve, OppCurve>* prev = first->fPrev; |
1178 SkASSERT(first->fCoinStart.isCoincident()); | 1180 SkASSERT(first->fCoinStart.isMatch()); |
1179 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perp
T()); | 1181 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perp
T()); |
1180 SkOPASSERT(last->fCoinEnd.isCoincident()); | 1182 SkOPASSERT(last->fCoinEnd.isMatch()); |
1181 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT(); | 1183 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT(); |
1182 double coinStart; | 1184 double coinStart; |
1183 SkDEBUGCODE(double coinEnd); | 1185 SkDEBUGCODE(double coinEnd); |
1184 SkTSpan<OppCurve, TCurve>* cutFirst; | 1186 SkTSpan<OppCurve, TCurve>* cutFirst; |
1185 if (prev && prev->fEndT == startT | 1187 if (prev && prev->fEndT == startT |
1186 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &co
inStart, | 1188 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &co
inStart, |
1187 &oppStartT) | 1189 &oppStartT) |
1188 && prev->fStartT < coinStart && coinStart < startT | 1190 && prev->fStartT < coinStart && coinStart < startT |
1189 && (cutFirst = prev->oppT(oppStartT))) { | 1191 && (cutFirst = prev->oppT(oppStartT))) { |
1190 oppFirst = cutFirst; | 1192 oppFirst = cutFirst; |
(...skipping 10 matching lines...) Expand all Loading... |
1201 oppFirst->markCoincident(); | 1203 oppFirst->markCoincident(); |
1202 oppHalf->fCoinStart.markCoincident(); | 1204 oppHalf->fCoinStart.markCoincident(); |
1203 } | 1205 } |
1204 } | 1206 } |
1205 } else { | 1207 } else { |
1206 SkDEBUGCODE(coinStart = first->fStartT); | 1208 SkDEBUGCODE(coinStart = first->fStartT); |
1207 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT
); | 1209 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT
); |
1208 } | 1210 } |
1209 // FIXME: incomplete : if we're not at the end, find end of coin | 1211 // FIXME: incomplete : if we're not at the end, find end of coin |
1210 SkTSpan<OppCurve, TCurve>* oppLast; | 1212 SkTSpan<OppCurve, TCurve>* oppLast; |
1211 SkOPASSERT(last->fCoinEnd.isCoincident()); | 1213 SkOPASSERT(last->fCoinEnd.isMatch()); |
1212 oppLast = last->findOppT(last->fCoinEnd.perpT()); | 1214 oppLast = last->findOppT(last->fCoinEnd.perpT()); |
1213 SkDEBUGCODE(coinEnd = last->fEndT); | 1215 SkDEBUGCODE(coinEnd = last->fEndT); |
1214 #ifdef SK_DEBUG | 1216 #ifdef SK_DEBUG |
1215 if (!this->globalState() || !this->globalState()->debugSkipAssert()) { | 1217 if (!this->globalState() || !this->globalState()->debugSkipAssert()) { |
1216 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT; | 1218 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT; |
1217 } | 1219 } |
1218 #endif | 1220 #endif |
1219 if (!oppMatched) { | 1221 if (!oppMatched) { |
1220 SkTSwap(oppFirst, oppLast); | 1222 SkTSwap(oppFirst, oppLast); |
1221 SkTSwap(oppStartT, oppEndT); | 1223 SkTSwap(oppStartT, oppEndT); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 } | 1274 } |
1273 | 1275 |
1274 template<typename TCurve, typename OppCurve> | 1276 template<typename TCurve, typename OppCurve> |
1275 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun( | 1277 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun( |
1276 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) { | 1278 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) { |
1277 SkTSpan<TCurve, OppCurve>* work = first; | 1279 SkTSpan<TCurve, OppCurve>* work = first; |
1278 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr; | 1280 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr; |
1279 first = nullptr; | 1281 first = nullptr; |
1280 // find the first fully coincident span | 1282 // find the first fully coincident span |
1281 do { | 1283 do { |
1282 if (work->fCoinStart.isCoincident()) { | 1284 if (work->fCoinStart.isMatch()) { |
1283 #if DEBUG_T_SECT | 1285 #if DEBUG_T_SECT |
1284 work->validatePerpT(work->fCoinStart.perpT()); | 1286 work->validatePerpT(work->fCoinStart.perpT()); |
1285 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perp
Pt()); | 1287 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perp
Pt()); |
1286 #endif | 1288 #endif |
1287 SkASSERT(work->hasOppT(work->fCoinStart.perpT())); | 1289 SkASSERT(work->hasOppT(work->fCoinStart.perpT())); |
1288 if (!work->fCoinEnd.isCoincident()) { | 1290 if (!work->fCoinEnd.isMatch()) { |
1289 break; | 1291 break; |
1290 } | 1292 } |
1291 lastCandidate = work; | 1293 lastCandidate = work; |
1292 if (!first) { | 1294 if (!first) { |
1293 first = work; | 1295 first = work; |
1294 } | 1296 } |
1295 } else if (first && work->fCollapsed) { | 1297 } else if (first && work->fCollapsed) { |
1296 *lastPtr = lastCandidate; | 1298 *lastPtr = lastCandidate; |
1297 return first; | 1299 return first; |
1298 } else { | 1300 } else { |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 SkDPoint workPt; | 1527 SkDPoint workPt; |
1526 do { | 1528 do { |
1527 tStep *= 0.5; | 1529 tStep *= 0.5; |
1528 if (precisely_zero(tStep)) { | 1530 if (precisely_zero(tStep)) { |
1529 return 0; | 1531 return 0; |
1530 } | 1532 } |
1531 workT += tStep; | 1533 workT += tStep; |
1532 workPt = fCurve.ptAtT(workT); | 1534 workPt = fCurve.ptAtT(workT); |
1533 coinW.setPerp(fCurve, workT, workPt, opp->fCurve); | 1535 coinW.setPerp(fCurve, workT, workPt, opp->fCurve); |
1534 double perpT = coinW.perpT(); | 1536 double perpT = coinW.perpT(); |
1535 if (coinW.isCoincident() ? !between(oppSpan->fStartT, perpT, oppSpan->fE
ndT) : perpT < 0) { | 1537 if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT)
: perpT < 0) { |
1536 continue; | 1538 continue; |
1537 } | 1539 } |
1538 SkDVector perpW = workPt - coinW.perpPt(); | 1540 SkDVector perpW = workPt - coinW.perpPt(); |
1539 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) { | 1541 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) { |
1540 tStep = -tStep; | 1542 tStep = -tStep; |
1541 } | 1543 } |
1542 if (workPt.approximatelyEqual(coinW.perpPt())) { | 1544 if (workPt.approximatelyEqual(coinW.perpPt())) { |
1543 break; | 1545 break; |
1544 } | 1546 } |
1545 } while (true); | 1547 } while (true); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1621 larger = test; | 1623 larger = test; |
1622 } while ((prior = test), (test = test->fNext)); | 1624 } while ((prior = test), (test = test->fNext)); |
1623 if (!larger) { | 1625 if (!larger) { |
1624 continue; | 1626 continue; |
1625 } | 1627 } |
1626 // check middle t value to see if it is coincident as well | 1628 // check middle t value to see if it is coincident as well |
1627 double midT = (smaller->fEndT + larger->fStartT) / 2; | 1629 double midT = (smaller->fEndT + larger->fStartT) / 2; |
1628 SkDPoint midPt = fCurve.ptAtT(midT); | 1630 SkDPoint midPt = fCurve.ptAtT(midT); |
1629 SkTCoincident<TCurve, OppCurve> coin; | 1631 SkTCoincident<TCurve, OppCurve> coin; |
1630 coin.setPerp(fCurve, midT, midPt, sect2->fCurve); | 1632 coin.setPerp(fCurve, midT, midPt, sect2->fCurve); |
1631 if (coin.isCoincident()) { | 1633 if (coin.isMatch()) { |
1632 smaller->fEndT = larger->fEndT; | 1634 smaller->fEndT = larger->fEndT; |
1633 smaller->fCoinEnd = larger->fCoinEnd; | 1635 smaller->fCoinEnd = larger->fCoinEnd; |
1634 if (largerPrior) { | 1636 if (largerPrior) { |
1635 largerPrior->fNext = larger->fNext; | 1637 largerPrior->fNext = larger->fNext; |
1636 largerPrior->validate(); | 1638 largerPrior->validate(); |
1637 } else { | 1639 } else { |
1638 fCoincident = larger->fNext; | 1640 fCoincident = larger->fNext; |
1639 } | 1641 } |
1640 } | 1642 } |
1641 } while (true); | 1643 } while (true); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1721 --fActiveCount; | 1723 --fActiveCount; |
1722 span->fNext = fCoincident; | 1724 span->fNext = fCoincident; |
1723 fCoincident = span; | 1725 fCoincident = span; |
1724 } else { | 1726 } else { |
1725 this->markSpanGone(span); | 1727 this->markSpanGone(span); |
1726 } | 1728 } |
1727 } | 1729 } |
1728 | 1730 |
1729 template<typename TCurve, typename OppCurve> | 1731 template<typename TCurve, typename OppCurve> |
1730 bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) { | 1732 bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) { |
| 1733 if (!span->fStartT) { |
| 1734 fRemovedStartT = true; |
| 1735 } |
| 1736 if (1 == span->fEndT) { |
| 1737 fRemovedEndT = true; |
| 1738 } |
1731 this->unlinkSpan(span); | 1739 this->unlinkSpan(span); |
1732 return this->markSpanGone(span); | 1740 return this->markSpanGone(span); |
1733 } | 1741 } |
1734 | 1742 |
1735 template<typename TCurve, typename OppCurve> | 1743 template<typename TCurve, typename OppCurve> |
1736 void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first
, | 1744 void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first
, |
1737 SkTSpan<TCurve, OppCurve>* last) { | 1745 SkTSpan<TCurve, OppCurve>* last) { |
1738 if (first == last) { | 1746 if (first == last) { |
1739 return; | 1747 return; |
1740 } | 1748 } |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2119 int coinLoopCount = kMaxCoinLoopCount; | 2127 int coinLoopCount = kMaxCoinLoopCount; |
2120 double start1s SK_INIT_TO_AVOID_WARNING; | 2128 double start1s SK_INIT_TO_AVOID_WARNING; |
2121 double start1e SK_INIT_TO_AVOID_WARNING; | 2129 double start1e SK_INIT_TO_AVOID_WARNING; |
2122 do { | 2130 do { |
2123 // find the largest bounds | 2131 // find the largest bounds |
2124 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax(); | 2132 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax(); |
2125 if (!largest1) { | 2133 if (!largest1) { |
2126 break; | 2134 break; |
2127 } | 2135 } |
2128 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax(); | 2136 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax(); |
| 2137 sect1->fRemovedStartT = sect1->fRemovedEndT = false; |
| 2138 sect2->fRemovedStartT = sect2->fRemovedEndT = false; |
2129 // split it | 2139 // split it |
2130 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsM
ax | 2140 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsM
ax |
2131 || (!largest1->fCollapsed && largest2->fCollapsed)))) { | 2141 || (!largest1->fCollapsed && largest2->fCollapsed)))) { |
2132 if (largest1->fCollapsed) { | 2142 if (largest1->fCollapsed) { |
2133 break; | 2143 break; |
2134 } | 2144 } |
2135 // trim parts that don't intersect the opposite | 2145 // trim parts that don't intersect the opposite |
2136 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne(); | 2146 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne(); |
2137 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState())); | 2147 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState())); |
2138 if (!half1->split(largest1, §1->fHeap)) { | 2148 if (!half1->split(largest1, §1->fHeap)) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2207 } while (true); | 2217 } while (true); |
2208 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident; | 2218 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident; |
2209 if (coincident) { | 2219 if (coincident) { |
2210 // if there is more than one coincident span, check loosely to see if th
ey should be joined | 2220 // if there is more than one coincident span, check loosely to see if th
ey should be joined |
2211 if (coincident->fNext) { | 2221 if (coincident->fNext) { |
2212 sect1->mergeCoincidence(sect2); | 2222 sect1->mergeCoincidence(sect2); |
2213 coincident = sect1->fCoincident; | 2223 coincident = sect1->fCoincident; |
2214 } | 2224 } |
2215 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only look
s at sect 1 | 2225 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only look
s at sect 1 |
2216 do { | 2226 do { |
2217 if (!coincident->fCoinStart.isCoincident()) { | 2227 if (!coincident->fCoinStart.isMatch()) { |
2218 continue; | 2228 continue; |
2219 } | 2229 } |
2220 if (!coincident->fCoinEnd.isCoincident()) { | 2230 if (!coincident->fCoinEnd.isMatch()) { |
2221 continue; | 2231 continue; |
2222 } | 2232 } |
2223 int index = intersections->insertCoincident(coincident->fStartT, | 2233 int index = intersections->insertCoincident(coincident->fStartT, |
2224 coincident->fCoinStart.perpT(), coincident->fPart[0]); | 2234 coincident->fCoinStart.perpT(), coincident->fPart[0]); |
2225 if ((intersections->insertCoincident(coincident->fEndT, | 2235 if ((intersections->insertCoincident(coincident->fEndT, |
2226 coincident->fCoinEnd.perpT(), | 2236 coincident->fCoinEnd.perpT(), |
2227 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) { | 2237 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) { |
2228 intersections->clearCoincidence(index); | 2238 intersections->clearCoincidence(index); |
2229 } | 2239 } |
2230 } while ((coincident = coincident->fNext)); | 2240 } while ((coincident = coincident->fNext)); |
2231 } | 2241 } |
2232 int zeroOneSet = EndsEqual(sect1, sect2, intersections); | 2242 int zeroOneSet = EndsEqual(sect1, sect2, intersections); |
2233 if (!sect1->fHead || !sect2->fHead) { | 2243 if (!sect1->fHead || !sect2->fHead) { |
| 2244 // if the final iteration contains an end (0 or 1), |
| 2245 if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) { |
| 2246 SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular w
ith opposite curve |
| 2247 perp.setPerp(sect1->fCurve, 0, sect1->fCurve.fPts[0], sect2->fCurve)
; |
| 2248 if (perp.isMatch()) { |
| 2249 intersections->insert(0, perp.perpT(), perp.perpPt()); |
| 2250 } |
| 2251 } |
| 2252 if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) { |
| 2253 SkTCoincident<TCurve, OppCurve> perp; |
| 2254 perp.setPerp(sect1->fCurve, 1, sect1->fCurve.fPts[TCurve::kPointLast
], sect2->fCurve); |
| 2255 if (perp.isMatch()) { |
| 2256 intersections->insert(1, perp.perpT(), perp.perpPt()); |
| 2257 } |
| 2258 } |
| 2259 if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) { |
| 2260 SkTCoincident<OppCurve, TCurve> perp; |
| 2261 perp.setPerp(sect2->fCurve, 0, sect2->fCurve.fPts[0], sect1->fCurve)
; |
| 2262 if (perp.isMatch()) { |
| 2263 intersections->insert(perp.perpT(), 0, perp.perpPt()); |
| 2264 } |
| 2265 } |
| 2266 if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) { |
| 2267 SkTCoincident<OppCurve, TCurve> perp; |
| 2268 perp.setPerp(sect2->fCurve, 1, sect2->fCurve.fPts[OppCurve::kPointLa
st], sect1->fCurve); |
| 2269 if (perp.isMatch()) { |
| 2270 intersections->insert(perp.perpT(), 1, perp.perpPt()); |
| 2271 } |
| 2272 } |
2234 return; | 2273 return; |
2235 } | 2274 } |
2236 sect1->recoverCollapsed(); | 2275 sect1->recoverCollapsed(); |
2237 sect2->recoverCollapsed(); | 2276 sect2->recoverCollapsed(); |
2238 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead; | 2277 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead; |
2239 // check heads and tails for zero and ones and insert them if we haven't alr
eady done so | 2278 // check heads and tails for zero and ones and insert them if we haven't alr
eady done so |
2240 const SkTSpan<TCurve, OppCurve>* head1 = result1; | 2279 const SkTSpan<TCurve, OppCurve>* head1 = result1; |
2241 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStart
T)) { | 2280 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStart
T)) { |
2242 const SkDPoint& start1 = sect1->fCurve[0]; | 2281 const SkDPoint& start1 = sect1->fCurve[0]; |
2243 if (head1->isBounded()) { | 2282 if (head1->isBounded()) { |
(...skipping 28 matching lines...) Expand all Loading... |
2272 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast]; | 2311 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast]; |
2273 if (tail2->isBounded()) { | 2312 if (tail2->isBounded()) { |
2274 double t = tail2->closestBoundedT(end2); | 2313 double t = tail2->closestBoundedT(end2); |
2275 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) { | 2314 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) { |
2276 intersections->insert(t, 1, end2); | 2315 intersections->insert(t, 1, end2); |
2277 } | 2316 } |
2278 } | 2317 } |
2279 } | 2318 } |
2280 SkClosestSect<TCurve, OppCurve> closest; | 2319 SkClosestSect<TCurve, OppCurve> closest; |
2281 do { | 2320 do { |
2282 while (result1 && result1->fCoinStart.isCoincident() && result1->fCoinEn
d.isCoincident()) { | 2321 while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isM
atch()) { |
2283 result1 = result1->fNext; | 2322 result1 = result1->fNext; |
2284 } | 2323 } |
2285 if (!result1) { | 2324 if (!result1) { |
2286 break; | 2325 break; |
2287 } | 2326 } |
2288 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead; | 2327 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead; |
2289 bool found = false; | 2328 bool found = false; |
2290 while (result2) { | 2329 while (result2) { |
2291 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections)
); | 2330 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections)
); |
2292 result2 = result2->fNext; | 2331 result2 = result2->fNext; |
2293 } | 2332 } |
2294 } while ((result1 = result1->fNext)); | 2333 } while ((result1 = result1->fNext)); |
2295 closest.finish(intersections); | 2334 closest.finish(intersections); |
2296 // if there is more than one intersection and it isn't already coincident, c
heck | 2335 // if there is more than one intersection and it isn't already coincident, c
heck |
2297 int last = intersections->used() - 1; | 2336 int last = intersections->used() - 1; |
2298 for (int index = 0; index < last; ) { | 2337 for (int index = 0; index < last; ) { |
2299 if (intersections->isCoincident(index) && intersections->isCoincident(in
dex + 1)) { | 2338 if (intersections->isCoincident(index) && intersections->isCoincident(in
dex + 1)) { |
2300 ++index; | 2339 ++index; |
2301 continue; | 2340 continue; |
2302 } | 2341 } |
2303 double midT = ((*intersections)[0][index] + (*intersections)[0][index +
1]) / 2; | 2342 double midT = ((*intersections)[0][index] + (*intersections)[0][index +
1]) / 2; |
2304 SkDPoint midPt = sect1->fCurve.ptAtT(midT); | 2343 SkDPoint midPt = sect1->fCurve.ptAtT(midT); |
2305 // intersect perpendicular with opposite curve | 2344 // intersect perpendicular with opposite curve |
2306 SkTCoincident<TCurve, OppCurve> perp; | 2345 SkTCoincident<TCurve, OppCurve> perp; |
2307 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve); | 2346 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve); |
2308 if (!perp.isCoincident()) { | 2347 if (!perp.isMatch()) { |
2309 ++index; | 2348 ++index; |
2310 continue; | 2349 continue; |
2311 } | 2350 } |
2312 if (intersections->isCoincident(index)) { | 2351 if (intersections->isCoincident(index)) { |
2313 intersections->removeOne(index); | 2352 intersections->removeOne(index); |
2314 --last; | 2353 --last; |
2315 } else if (intersections->isCoincident(index + 1)) { | 2354 } else if (intersections->isCoincident(index + 1)) { |
2316 intersections->removeOne(index + 1); | 2355 intersections->removeOne(index + 1); |
2317 --last; | 2356 --last; |
2318 } else { | 2357 } else { |
2319 intersections->setCoincident(index++); | 2358 intersections->setCoincident(index++); |
2320 } | 2359 } |
2321 intersections->setCoincident(index); | 2360 intersections->setCoincident(index); |
2322 } | 2361 } |
2323 SkASSERT(intersections->used() <= TCurve::kMaxIntersections); | 2362 SkASSERT(intersections->used() <= TCurve::kMaxIntersections); |
2324 } | 2363 } |
2325 | 2364 |
2326 #endif | 2365 #endif |
OLD | NEW |