blob: fbfb8c138fcd9e8cf47bac075b5b3a458fc06178 [file] [log] [blame]
caryclark45fa4472015-01-16 07:04:10 -08001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
deanm12670eb2016-04-26 14:09:01 -07007#ifndef SkPathOpsTSect_DEFINED
8#define SkPathOpsTSect_DEFINED
caryclark45fa4472015-01-16 07:04:10 -08009
10#include "SkChunkAlloc.h"
caryclark54359292015-03-26 07:52:43 -070011#include "SkPathOpsBounds.h"
caryclark45fa4472015-01-16 07:04:10 -080012#include "SkPathOpsRect.h"
caryclark45fa4472015-01-16 07:04:10 -080013#include "SkIntersections.h"
caryclark54359292015-03-26 07:52:43 -070014#include "SkTSort.h"
caryclark45fa4472015-01-16 07:04:10 -080015
caryclarked0935a2015-10-22 07:23:52 -070016#ifdef SK_DEBUG
17typedef uint8_t SkOpDebugBool;
18#else
19typedef bool SkOpDebugBool;
20#endif
21
caryclark1049f122015-04-20 08:31:59 -070022/* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */
23template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080024class SkTCoincident {
25public:
caryclark697ac1c2015-04-13 09:36:01 -070026 SkTCoincident() {
caryclarkdf386c52015-04-21 05:27:02 -070027 this->init();
caryclark1049f122015-04-20 08:31:59 -070028 }
29
caryclarked0935a2015-10-22 07:23:52 -070030 void debugInit() {
31#ifdef SK_DEBUG
32 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
33 this->fPerpT = SK_ScalarNaN;
caryclark6c3b9cd2016-09-26 05:36:58 -070034 this->fMatch = 0xFF;
caryclarked0935a2015-10-22 07:23:52 -070035#endif
36 }
37
38 char dumpIsCoincidentStr() const;
caryclark1049f122015-04-20 08:31:59 -070039 void dump() const;
40
caryclark6c3b9cd2016-09-26 05:36:58 -070041 bool isMatch() const {
42 SkASSERT(!!fMatch == fMatch);
43 return SkToBool(fMatch);
caryclark45fa4472015-01-16 07:04:10 -080044 }
45
46 void init() {
caryclarkdf386c52015-04-21 05:27:02 -070047 fPerpT = -1;
caryclark6c3b9cd2016-09-26 05:36:58 -070048 fMatch = false;
caryclarkdf386c52015-04-21 05:27:02 -070049 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
caryclark45fa4472015-01-16 07:04:10 -080050 }
51
52 void markCoincident() {
caryclark6c3b9cd2016-09-26 05:36:58 -070053 if (!fMatch) {
caryclark45fa4472015-01-16 07:04:10 -080054 fPerpT = -1;
55 }
caryclark6c3b9cd2016-09-26 05:36:58 -070056 fMatch = true;
caryclark45fa4472015-01-16 07:04:10 -080057 }
58
59 const SkDPoint& perpPt() const {
60 return fPerpPt;
61 }
62
63 double perpT() const {
64 return fPerpT;
65 }
66
caryclark1049f122015-04-20 08:31:59 -070067 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve& );
caryclark45fa4472015-01-16 07:04:10 -080068
69private:
70 SkDPoint fPerpPt;
71 double fPerpT; // perpendicular intersection on opposite curve
caryclark6c3b9cd2016-09-26 05:36:58 -070072 SkOpDebugBool fMatch;
caryclark45fa4472015-01-16 07:04:10 -080073};
74
caryclark1049f122015-04-20 08:31:59 -070075template<typename TCurve, typename OppCurve> class SkTSect;
76template<typename TCurve, typename OppCurve> class SkTSpan;
caryclark54359292015-03-26 07:52:43 -070077
caryclark1049f122015-04-20 08:31:59 -070078template<typename TCurve, typename OppCurve>
caryclark54359292015-03-26 07:52:43 -070079struct SkTSpanBounded {
caryclark1049f122015-04-20 08:31:59 -070080 SkTSpan<TCurve, OppCurve>* fBounded;
caryclark54359292015-03-26 07:52:43 -070081 SkTSpanBounded* fNext;
82};
caryclark45fa4472015-01-16 07:04:10 -080083
84/* Curve is either TCurve or SkDCubic */
caryclark1049f122015-04-20 08:31:59 -070085template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080086class SkTSpan {
87public:
caryclark1049f122015-04-20 08:31:59 -070088 void addBounded(SkTSpan<OppCurve, TCurve>* , SkChunkAlloc* );
reed0dc4dd62015-03-24 13:55:33 -070089 double closestBoundedT(const SkDPoint& pt) const;
caryclark54359292015-03-26 07:52:43 -070090 bool contains(double t) const;
reed0dc4dd62015-03-24 13:55:33 -070091
caryclark1049f122015-04-20 08:31:59 -070092 void debugInit() {
93 TCurve dummy;
94 dummy.debugInit();
95 init(dummy);
96 initBounds(dummy);
caryclarkdf386c52015-04-21 05:27:02 -070097 fCoinStart.init();
98 fCoinEnd.init();
caryclark1049f122015-04-20 08:31:59 -070099 }
100
101 const SkTSect<OppCurve, TCurve>* debugOpp() const;
caryclark643ede62016-08-08 14:27:45 -0700102
103#ifdef SK_DEBUG
104 void debugSetGlobalState(SkOpGlobalState* state) {
105 fDebugGlobalState = state;
106 }
107#endif
108
caryclark54359292015-03-26 07:52:43 -0700109 const SkTSpan* debugSpan(int ) const;
110 const SkTSpan* debugT(double t) const;
111#ifdef SK_DEBUG
112 bool debugIsBefore(const SkTSpan* span) const;
113#endif
114 void dump() const;
caryclark26ad22a2015-10-16 09:03:38 -0700115 void dumpAll() const;
caryclark1049f122015-04-20 08:31:59 -0700116 void dumpBounded(int id) const;
117 void dumpBounds() const;
118 void dumpCoin() const;
caryclark45fa4472015-01-16 07:04:10 -0800119
120 double endT() const {
121 return fEndT;
122 }
123
caryclark1049f122015-04-20 08:31:59 -0700124 SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp) const;
caryclark54359292015-03-26 07:52:43 -0700125
caryclark1049f122015-04-20 08:31:59 -0700126 SkTSpan<OppCurve, TCurve>* findOppT(double t) const {
127 SkTSpan<OppCurve, TCurve>* result = oppT(t);
caryclark643ede62016-08-08 14:27:45 -0700128 SkOPASSERT(result);
caryclark45fa4472015-01-16 07:04:10 -0800129 return result;
130 }
131
caryclark643ede62016-08-08 14:27:45 -0700132 SkDEBUGCODE(SkOpGlobalState* globalState() const { return fDebugGlobalState; })
133
caryclark54359292015-03-26 07:52:43 -0700134 bool hasOppT(double t) const {
135 return SkToBool(oppT(t));
136 }
137
caryclark1049f122015-04-20 08:31:59 -0700138 int hullsIntersect(SkTSpan<OppCurve, TCurve>* span, bool* start, bool* oppStart);
caryclark54359292015-03-26 07:52:43 -0700139 void init(const TCurve& );
caryclarka35ab3e2016-10-20 08:32:18 -0700140 bool initBounds(const TCurve& );
caryclark54359292015-03-26 07:52:43 -0700141
142 bool isBounded() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700143 return fBounded != nullptr;
caryclark54359292015-03-26 07:52:43 -0700144 }
145
caryclark1049f122015-04-20 08:31:59 -0700146 bool linearsIntersect(SkTSpan<OppCurve, TCurve>* span);
caryclark54359292015-03-26 07:52:43 -0700147 double linearT(const SkDPoint& ) const;
148
149 void markCoincident() {
150 fCoinStart.markCoincident();
151 fCoinEnd.markCoincident();
152 }
caryclark45fa4472015-01-16 07:04:10 -0800153
154 const SkTSpan* next() const {
155 return fNext;
156 }
157
caryclark1049f122015-04-20 08:31:59 -0700158 bool onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp, bool* start,
159 bool* oppStart, bool* ptsInCommon);
caryclark54359292015-03-26 07:52:43 -0700160
caryclark45fa4472015-01-16 07:04:10 -0800161 const TCurve& part() const {
162 return fPart;
163 }
164
caryclark54359292015-03-26 07:52:43 -0700165 bool removeAllBounded();
caryclark1049f122015-04-20 08:31:59 -0700166 bool removeBounded(const SkTSpan<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700167
caryclark45fa4472015-01-16 07:04:10 -0800168 void reset() {
halcanary96fcdcc2015-08-27 07:41:13 -0700169 fBounded = nullptr;
caryclark45fa4472015-01-16 07:04:10 -0800170 }
171
caryclark54359292015-03-26 07:52:43 -0700172 void resetBounds(const TCurve& curve) {
173 fIsLinear = fIsLine = false;
174 initBounds(curve);
caryclark45fa4472015-01-16 07:04:10 -0800175 }
176
caryclark54359292015-03-26 07:52:43 -0700177 bool split(SkTSpan* work, SkChunkAlloc* heap) {
178 return splitAt(work, (work->fStartT + work->fEndT) * 0.5, heap);
179 }
180
181 bool splitAt(SkTSpan* work, double t, SkChunkAlloc* heap);
caryclark45fa4472015-01-16 07:04:10 -0800182
183 double startT() const {
184 return fStartT;
185 }
186
caryclark54359292015-03-26 07:52:43 -0700187private:
caryclark45fa4472015-01-16 07:04:10 -0800188
189 // implementation is for testing only
caryclark54359292015-03-26 07:52:43 -0700190 int debugID() const {
191 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
caryclark45fa4472015-01-16 07:04:10 -0800192 }
193
caryclark54359292015-03-26 07:52:43 -0700194 void dumpID() const;
caryclark45fa4472015-01-16 07:04:10 -0800195
caryclark1049f122015-04-20 08:31:59 -0700196 int hullCheck(const SkTSpan<OppCurve, TCurve>* opp, bool* start, bool* oppStart);
197 int linearIntersects(const OppCurve& ) const;
198 SkTSpan<OppCurve, TCurve>* oppT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800199
caryclark45fa4472015-01-16 07:04:10 -0800200 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700201 void validateBounded() const;
202 void validatePerpT(double oppT) const;
203 void validatePerpPt(double t, const SkDPoint& ) const;
caryclark45fa4472015-01-16 07:04:10 -0800204
205 TCurve fPart;
caryclark1049f122015-04-20 08:31:59 -0700206 SkTCoincident<TCurve, OppCurve> fCoinStart;
207 SkTCoincident<TCurve, OppCurve> fCoinEnd;
208 SkTSpanBounded<OppCurve, TCurve>* fBounded;
caryclark45fa4472015-01-16 07:04:10 -0800209 SkTSpan* fPrev;
210 SkTSpan* fNext;
211 SkDRect fBounds;
212 double fStartT;
213 double fEndT;
214 double fBoundsMax;
caryclarked0935a2015-10-22 07:23:52 -0700215 SkOpDebugBool fCollapsed;
216 SkOpDebugBool fHasPerp;
217 SkOpDebugBool fIsLinear;
218 SkOpDebugBool fIsLine;
219 SkOpDebugBool fDeleted;
caryclark643ede62016-08-08 14:27:45 -0700220 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700221 SkDEBUGCODE(SkTSect<TCurve, OppCurve>* fDebugSect);
caryclark54359292015-03-26 07:52:43 -0700222 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
caryclark1049f122015-04-20 08:31:59 -0700223 friend class SkTSect<TCurve, OppCurve>;
224 friend class SkTSect<OppCurve, TCurve>;
225 friend class SkTSpan<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800226};
227
caryclark1049f122015-04-20 08:31:59 -0700228template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -0800229class SkTSect {
230public:
caryclarke25a4f62016-07-26 09:26:29 -0700231 SkTSect(const TCurve& c SkDEBUGPARAMS(SkOpGlobalState* ) PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
caryclark1049f122015-04-20 08:31:59 -0700232 static void BinarySearch(SkTSect* sect1, SkTSect<OppCurve, TCurve>* sect2,
233 SkIntersections* intersections);
caryclark45fa4472015-01-16 07:04:10 -0800234
caryclarke25a4f62016-07-26 09:26:29 -0700235 SkDEBUGCODE(SkOpGlobalState* globalState() { return fDebugGlobalState; })
caryclark45fa4472015-01-16 07:04:10 -0800236 // for testing only
caryclark1049f122015-04-20 08:31:59 -0700237 bool debugHasBounded(const SkTSpan<OppCurve, TCurve>* ) const;
caryclark54359292015-03-26 07:52:43 -0700238
caryclark1049f122015-04-20 08:31:59 -0700239 const SkTSect<OppCurve, TCurve>* debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700240 return SkDEBUGRELEASE(fOppSect, nullptr);
caryclark54359292015-03-26 07:52:43 -0700241 }
242
caryclark1049f122015-04-20 08:31:59 -0700243 const SkTSpan<TCurve, OppCurve>* debugSpan(int id) const;
244 const SkTSpan<TCurve, OppCurve>* debugT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800245 void dump() const;
caryclark1049f122015-04-20 08:31:59 -0700246 void dumpBoth(SkTSect<OppCurve, TCurve>* ) const;
247 void dumpBounded(int id) const;
248 void dumpBounds() const;
caryclark54359292015-03-26 07:52:43 -0700249 void dumpCoin() const;
250 void dumpCoinCurves() const;
caryclark45fa4472015-01-16 07:04:10 -0800251 void dumpCurves() const;
252
253private:
254 enum {
255 kZeroS1Set = 1,
256 kOneS1Set = 2,
257 kZeroS2Set = 4,
258 kOneS2Set = 8
259 };
260
caryclark1049f122015-04-20 08:31:59 -0700261 SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior);
262 void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t);
263 SkTSpan<TCurve, OppCurve>* addOne();
caryclark55888e42016-07-18 10:01:36 -0700264
caryclark1049f122015-04-20 08:31:59 -0700265 SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, double t) {
266 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700267 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700268 result->splitAt(span, t, &fHeap);
269 result->initBounds(fCurve);
270 span->initBounds(fCurve);
271 return result;
272 }
273
caryclark1049f122015-04-20 08:31:59 -0700274 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
275 double* oppT);
276 SkTSpan<TCurve, OppCurve>* boundsMax() const;
caryclarkef7cee42016-09-06 09:05:54 -0700277 bool coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
caryclark26ad22a2015-10-16 09:03:38 -0700278 void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, double start1e);
caryclark54359292015-03-26 07:52:43 -0700279 bool coincidentHasT(double t);
caryclark1049f122015-04-20 08:31:59 -0700280 int collapsed() const;
281 void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
282 SkTSpan<TCurve, OppCurve>* last);
283 int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
284 SkTSpan<TCurve, OppCurve>** last) const;
caryclarkccec0f92015-03-24 07:28:17 -0700285
caryclark54359292015-03-26 07:52:43 -0700286 int debugID() const {
287 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
288 }
289
caryclarkef7cee42016-09-06 09:05:54 -0700290 bool deleteEmptySpans();
caryclark1049f122015-04-20 08:31:59 -0700291 void dumpCommon(const SkTSpan<TCurve, OppCurve>* ) const;
292 void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const;
293 static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2,
294 SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700295 bool extractCoincident(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
296 SkTSpan<TCurve, OppCurve>* last, SkTSpan<TCurve, OppCurve>** result);
caryclark1049f122015-04-20 08:31:59 -0700297 SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* first,
298 SkTSpan<TCurve, OppCurve>** lastPtr);
299 int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
300 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult);
caryclarked0935a2015-10-22 07:23:52 -0700301 bool isParallel(const SkDLine& thisLine, const SkTSect<OppCurve, TCurve>* opp) const;
caryclark1049f122015-04-20 08:31:59 -0700302 int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
303 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700304 bool markSpanGone(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700305 bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2) const;
306 void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2,
caryclark54359292015-03-26 07:52:43 -0700307 bool* calcMatched, bool* oppMatched) const;
caryclark1049f122015-04-20 08:31:59 -0700308 void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2);
309 SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const;
310 void removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700311 void recoverCollapsed();
caryclark1049f122015-04-20 08:31:59 -0700312 void removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween);
313 void removeAllBut(const SkTSpan<OppCurve, TCurve>* keep, SkTSpan<TCurve, OppCurve>* span,
314 SkTSect<OppCurve, TCurve>* opp);
caryclarkef7cee42016-09-06 09:05:54 -0700315 bool removeSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700316 void removeSpanRange(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last);
317 void removeSpans(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
caryclark34efb702016-10-24 08:19:06 -0700318 void removedEndCheck(SkTSpan<TCurve, OppCurve>* span);
319
320 void resetRemovedEnds() {
321 fRemovedStartT = fRemovedEndT = false;
322 }
323
caryclark1049f122015-04-20 08:31:59 -0700324 SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
325 SkTSpan<TCurve, OppCurve>* tail();
caryclarka35ab3e2016-10-20 08:32:18 -0700326 bool trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
caryclark1049f122015-04-20 08:31:59 -0700327 void unlinkSpan(SkTSpan<TCurve, OppCurve>* span);
328 bool updateBounded(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
329 SkTSpan<OppCurve, TCurve>* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700330 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700331 void validateBounded() const;
332
caryclark45fa4472015-01-16 07:04:10 -0800333 const TCurve& fCurve;
334 SkChunkAlloc fHeap;
caryclark1049f122015-04-20 08:31:59 -0700335 SkTSpan<TCurve, OppCurve>* fHead;
336 SkTSpan<TCurve, OppCurve>* fCoincident;
337 SkTSpan<TCurve, OppCurve>* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800338 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700339 bool fRemovedStartT;
340 bool fRemovedEndT;
caryclarke25a4f62016-07-26 09:26:29 -0700341 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700342 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700343 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
344 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800345#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800346 int fDebugAllocatedCount;
347#endif
caryclark1049f122015-04-20 08:31:59 -0700348 friend class SkTSpan<TCurve, OppCurve>;
349 friend class SkTSpan<OppCurve, TCurve>;
350 friend class SkTSect<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800351};
352
353#define COINCIDENT_SPAN_COUNT 9
354
caryclark1049f122015-04-20 08:31:59 -0700355template<typename TCurve, typename OppCurve>
356void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t,
357 const SkDPoint& cPt, const OppCurve& c2) {
caryclark45fa4472015-01-16 07:04:10 -0800358 SkDVector dxdy = c1.dxdyAtT(t);
359 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
caryclarka35ab3e2016-10-20 08:32:18 -0700360 SkIntersections i SkDEBUGCODE((c1.globalState()));
caryclark45fa4472015-01-16 07:04:10 -0800361 int used = i.intersectRay(c2, perp);
362 // only keep closest
caryclark54359292015-03-26 07:52:43 -0700363 if (used == 0 || used == 3) {
caryclarkdf386c52015-04-21 05:27:02 -0700364 this->init();
caryclark45fa4472015-01-16 07:04:10 -0800365 return;
caryclark55888e42016-07-18 10:01:36 -0700366 }
caryclark45fa4472015-01-16 07:04:10 -0800367 fPerpT = i[0][0];
368 fPerpPt = i.pt(0);
369 SkASSERT(used <= 2);
370 if (used == 2) {
371 double distSq = (fPerpPt - cPt).lengthSquared();
372 double dist2Sq = (i.pt(1) - cPt).lengthSquared();
373 if (dist2Sq < distSq) {
374 fPerpT = i[0][1];
375 fPerpPt = i.pt(1);
376 }
377 }
caryclark54359292015-03-26 07:52:43 -0700378#if DEBUG_T_SECT
caryclark1049f122015-04-20 08:31:59 -0700379 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n",
380 t, cPt.fX, cPt.fY,
381 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY);
caryclark54359292015-03-26 07:52:43 -0700382#endif
caryclark6c3b9cd2016-09-26 05:36:58 -0700383 fMatch = cPt.approximatelyEqual(fPerpPt);
caryclark45fa4472015-01-16 07:04:10 -0800384#if DEBUG_T_SECT
caryclark6c3b9cd2016-09-26 05:36:58 -0700385 if (fMatch) {
caryclark45fa4472015-01-16 07:04:10 -0800386 SkDebugf(""); // allow setting breakpoint
387 }
388#endif
389}
390
caryclark1049f122015-04-20 08:31:59 -0700391template<typename TCurve, typename OppCurve>
392void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkChunkAlloc* heap) {
halcanary385fe4d2015-08-26 13:07:48 -0700393 SkTSpanBounded<OppCurve, TCurve>* bounded = new (heap->allocThrow(
394 sizeof(SkTSpanBounded<OppCurve, TCurve>)))(SkTSpanBounded<OppCurve, TCurve>);
caryclark54359292015-03-26 07:52:43 -0700395 bounded->fBounded = span;
396 bounded->fNext = fBounded;
397 fBounded = bounded;
398}
399
caryclark1049f122015-04-20 08:31:59 -0700400template<typename TCurve, typename OppCurve>
401SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing(
402 SkTSpan<TCurve, OppCurve>* prior) {
403 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700404 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700405 result->fStartT = prior ? prior->fEndT : 0;
caryclark1049f122015-04-20 08:31:59 -0700406 SkTSpan<TCurve, OppCurve>* next = prior ? prior->fNext : fHead;
caryclark54359292015-03-26 07:52:43 -0700407 result->fEndT = next ? next->fStartT : 1;
408 result->fPrev = prior;
409 result->fNext = next;
410 if (prior) {
411 prior->fNext = result;
412 } else {
413 fHead = result;
414 }
415 if (next) {
416 next->fPrev = result;
417 }
418 result->resetBounds(fCurve);
caryclark643ede62016-08-08 14:27:45 -0700419 result->validate();
caryclark54359292015-03-26 07:52:43 -0700420 return result;
421}
422
caryclark1049f122015-04-20 08:31:59 -0700423template<typename TCurve, typename OppCurve>
424void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, double t) {
caryclark54359292015-03-26 07:52:43 -0700425 if (!span->hasOppT(t)) {
caryclark1049f122015-04-20 08:31:59 -0700426 SkTSpan<TCurve, OppCurve>* priorSpan;
427 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan);
caryclark54359292015-03-26 07:52:43 -0700428 if (!opp) {
429 opp = this->addFollowing(priorSpan);
430#if DEBUG_PERP
caryclark26ad22a2015-10-16 09:03:38 -0700431 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ?
432 priorSpan->debugID() : -1, t, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700433#endif
434 }
435#if DEBUG_PERP
436 opp->dump(); SkDebugf("\n");
caryclark26ad22a2015-10-16 09:03:38 -0700437 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ?
438 priorSpan->debugID() : -1, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700439#endif
440 opp->addBounded(span, &fHeap);
441 span->addBounded(opp, &fHeap);
442 }
443 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700444#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700445 span->validatePerpT(t);
caryclark1049f122015-04-20 08:31:59 -0700446#endif
caryclark54359292015-03-26 07:52:43 -0700447}
448
caryclark1049f122015-04-20 08:31:59 -0700449template<typename TCurve, typename OppCurve>
450double SkTSpan<TCurve, OppCurve>::closestBoundedT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700451 double result = -1;
caryclark343382e2016-06-29 08:18:38 -0700452 double closest = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -0700453 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700454 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700455 const SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700456 double startDist = test->fPart[0].distanceSquared(pt);
457 if (closest > startDist) {
458 closest = startDist;
459 result = test->fStartT;
460 }
caryclark1049f122015-04-20 08:31:59 -0700461 double endDist = test->fPart[OppCurve::kPointLast].distanceSquared(pt);
caryclark54359292015-03-26 07:52:43 -0700462 if (closest > endDist) {
463 closest = endDist;
464 result = test->fEndT;
465 }
466 testBounded = testBounded->fNext;
467 }
468 SkASSERT(between(0, result, 1));
469 return result;
470}
471
472#ifdef SK_DEBUG
caryclark1049f122015-04-20 08:31:59 -0700473template<typename TCurve, typename OppCurve>
474bool SkTSpan<TCurve, OppCurve>::debugIsBefore(const SkTSpan* span) const {
caryclark54359292015-03-26 07:52:43 -0700475 const SkTSpan* work = this;
476 do {
477 if (span == work) {
478 return true;
479 }
480 } while ((work = work->fNext));
481 return false;
482}
483#endif
484
caryclark1049f122015-04-20 08:31:59 -0700485template<typename TCurve, typename OppCurve>
486bool SkTSpan<TCurve, OppCurve>::contains(double t) const {
caryclark54359292015-03-26 07:52:43 -0700487 const SkTSpan* work = this;
488 do {
489 if (between(work->fStartT, t, work->fEndT)) {
490 return true;
491 }
492 } while ((work = work->fNext));
493 return false;
494}
495
caryclark1049f122015-04-20 08:31:59 -0700496template<typename TCurve, typename OppCurve>
497const SkTSect<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700498 return SkDEBUGRELEASE(fDebugSect->debugOpp(), nullptr);
caryclark54359292015-03-26 07:52:43 -0700499}
500
caryclark1049f122015-04-20 08:31:59 -0700501template<typename TCurve, typename OppCurve>
502SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::findOppSpan(
503 const SkTSpan<OppCurve, TCurve>* opp) const {
504 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700505 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700506 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700507 if (opp == test) {
508 return test;
509 }
510 bounded = bounded->fNext;
511 }
halcanary96fcdcc2015-08-27 07:41:13 -0700512 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700513}
514
515// returns 0 if no hull intersection
516// 1 if hulls intersect
517// 2 if hulls only share a common endpoint
518// -1 if linear and further checking is required
caryclark1049f122015-04-20 08:31:59 -0700519template<typename TCurve, typename OppCurve>
520int SkTSpan<TCurve, OppCurve>::hullCheck(const SkTSpan<OppCurve, TCurve>* opp,
521 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700522 if (fIsLinear) {
523 return -1;
524 }
525 bool ptsInCommon;
526 if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) {
527 SkASSERT(ptsInCommon);
528 return 2;
529 }
530 bool linear;
531 if (fPart.hullIntersects(opp->fPart, &linear)) {
532 if (!linear) { // check set true if linear
533 return 1;
534 }
535 fIsLinear = true;
536 fIsLine = fPart.controlsInside();
caryclark2bec26a2016-05-26 09:01:47 -0700537 return ptsInCommon ? 1 : -1;
caryclark54359292015-03-26 07:52:43 -0700538 } else { // hull is not linear; check set true if intersected at the end points
539 return ((int) ptsInCommon) << 1; // 0 or 2
540 }
541 return 0;
542}
543
544// OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
545// use line intersection to guess a better split than 0.5
546// OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear
caryclark1049f122015-04-20 08:31:59 -0700547template<typename TCurve, typename OppCurve>
548int SkTSpan<TCurve, OppCurve>::hullsIntersect(SkTSpan<OppCurve, TCurve>* opp,
549 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700550 if (!fBounds.intersects(opp->fBounds)) {
551 return 0;
552 }
553 int hullSect = this->hullCheck(opp, start, oppStart);
554 if (hullSect >= 0) {
555 return hullSect;
556 }
557 hullSect = opp->hullCheck(this, oppStart, start);
558 if (hullSect >= 0) {
559 return hullSect;
560 }
561 return -1;
562}
563
caryclark1049f122015-04-20 08:31:59 -0700564template<typename TCurve, typename OppCurve>
565void SkTSpan<TCurve, OppCurve>::init(const TCurve& c) {
halcanary96fcdcc2015-08-27 07:41:13 -0700566 fPrev = fNext = nullptr;
reed0dc4dd62015-03-24 13:55:33 -0700567 fStartT = 0;
568 fEndT = 1;
halcanary96fcdcc2015-08-27 07:41:13 -0700569 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700570 resetBounds(c);
caryclark45fa4472015-01-16 07:04:10 -0800571}
572
caryclark1049f122015-04-20 08:31:59 -0700573template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -0700574bool SkTSpan<TCurve, OppCurve>::initBounds(const TCurve& c) {
reed0dc4dd62015-03-24 13:55:33 -0700575 fPart = c.subDivide(fStartT, fEndT);
576 fBounds.setBounds(fPart);
577 fCoinStart.init();
578 fCoinEnd.init();
579 fBoundsMax = SkTMax(fBounds.width(), fBounds.height());
580 fCollapsed = fPart.collapsed();
581 fHasPerp = false;
caryclark54359292015-03-26 07:52:43 -0700582 fDeleted = false;
reed0dc4dd62015-03-24 13:55:33 -0700583#if DEBUG_T_SECT
reed0dc4dd62015-03-24 13:55:33 -0700584 if (fCollapsed) {
585 SkDebugf(""); // for convenient breakpoints
caryclark45fa4472015-01-16 07:04:10 -0800586 }
587#endif
caryclarka35ab3e2016-10-20 08:32:18 -0700588 return fBounds.valid();
caryclark45fa4472015-01-16 07:04:10 -0800589}
590
caryclark1049f122015-04-20 08:31:59 -0700591template<typename TCurve, typename OppCurve>
592bool SkTSpan<TCurve, OppCurve>::linearsIntersect(SkTSpan<OppCurve, TCurve>* span) {
caryclark54359292015-03-26 07:52:43 -0700593 int result = this->linearIntersects(span->fPart);
594 if (result <= 1) {
595 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800596 }
caryclark54359292015-03-26 07:52:43 -0700597 SkASSERT(span->fIsLinear);
598 result = span->linearIntersects(this->fPart);
599// SkASSERT(result <= 1);
600 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800601}
602
caryclark1049f122015-04-20 08:31:59 -0700603template<typename TCurve, typename OppCurve>
604double SkTSpan<TCurve, OppCurve>::linearT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700605 SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
606 return fabs(len.fX) > fabs(len.fY)
607 ? (pt.fX - fPart[0].fX) / len.fX
608 : (pt.fY - fPart[0].fY) / len.fY;
caryclark45fa4472015-01-16 07:04:10 -0800609}
610
caryclark1049f122015-04-20 08:31:59 -0700611template<typename TCurve, typename OppCurve>
612int SkTSpan<TCurve, OppCurve>::linearIntersects(const OppCurve& q2) const {
caryclark45fa4472015-01-16 07:04:10 -0800613 // looks like q1 is near-linear
caryclark54359292015-03-26 07:52:43 -0700614 int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
caryclark45fa4472015-01-16 07:04:10 -0800615 if (!fPart.controlsInside()) {
616 double dist = 0; // if there's any question, compute distance to find best outsiders
617 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) {
618 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) {
619 double test = (fPart[outer] - fPart[inner]).lengthSquared();
620 if (dist > test) {
621 continue;
622 }
623 dist = test;
624 start = outer;
625 end = inner;
626 }
627 }
628 }
629 // see if q2 is on one side of the line formed by the extreme points
630 double origX = fPart[start].fX;
631 double origY = fPart[start].fY;
632 double adj = fPart[end].fX - origX;
633 double opp = fPart[end].fY - origY;
caryclark54359292015-03-26 07:52:43 -0700634 double maxPart = SkTMax(fabs(adj), fabs(opp));
635 double sign = 0; // initialization to shut up warning in release build
caryclark1049f122015-04-20 08:31:59 -0700636 for (int n = 0; n < OppCurve::kPointCount; ++n) {
caryclark54359292015-03-26 07:52:43 -0700637 double dx = q2[n].fY - origY;
638 double dy = q2[n].fX - origX;
639 double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
caryclark45fa4472015-01-16 07:04:10 -0800640 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp;
caryclark54359292015-03-26 07:52:43 -0700641 if (precisely_zero_when_compared_to(test, maxVal)) {
642 return 1;
643 }
644 if (approximately_zero_when_compared_to(test, maxVal)) {
645 return 3;
caryclark45fa4472015-01-16 07:04:10 -0800646 }
647 if (n == 0) {
648 sign = test;
649 continue;
650 }
651 if (test * sign < 0) {
caryclark54359292015-03-26 07:52:43 -0700652 return 1;
caryclark45fa4472015-01-16 07:04:10 -0800653 }
654 }
caryclark54359292015-03-26 07:52:43 -0700655 return 0;
656}
657
caryclark1049f122015-04-20 08:31:59 -0700658template<typename TCurve, typename OppCurve>
659bool SkTSpan<TCurve, OppCurve>::onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp,
660 bool* start, bool* oppStart, bool* ptsInCommon) {
caryclark54359292015-03-26 07:52:43 -0700661 if (opp->fPart[0] == fPart[0]) {
662 *start = *oppStart = true;
663 } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
664 *start = false;
665 *oppStart = true;
caryclark1049f122015-04-20 08:31:59 -0700666 } else if (opp->fPart[OppCurve::kPointLast] == fPart[0]) {
caryclark54359292015-03-26 07:52:43 -0700667 *start = true;
668 *oppStart = false;
caryclark1049f122015-04-20 08:31:59 -0700669 } else if (opp->fPart[OppCurve::kPointLast] == fPart[TCurve::kPointLast]) {
caryclark54359292015-03-26 07:52:43 -0700670 *start = *oppStart = false;
671 } else {
672 *ptsInCommon = false;
673 return false;
674 }
675 *ptsInCommon = true;
caryclark1049f122015-04-20 08:31:59 -0700676 const SkDPoint* otherPts[TCurve::kPointCount - 1], * oppOtherPts[OppCurve::kPointCount - 1];
caryclark54359292015-03-26 07:52:43 -0700677 int baseIndex = *start ? 0 : TCurve::kPointLast;
caryclark1049f122015-04-20 08:31:59 -0700678 fPart.otherPts(baseIndex, otherPts);
679 opp->fPart.otherPts(*oppStart ? 0 : OppCurve::kPointLast, oppOtherPts);
caryclark54359292015-03-26 07:52:43 -0700680 const SkDPoint& base = fPart[baseIndex];
caryclark1049f122015-04-20 08:31:59 -0700681 for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(otherPts); ++o1) {
682 SkDVector v1 = *otherPts[o1] - base;
683 for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(oppOtherPts); ++o2) {
684 SkDVector v2 = *oppOtherPts[o2] - base;
caryclark54359292015-03-26 07:52:43 -0700685 if (v2.dot(v1) >= 0) {
686 return false;
687 }
688 }
689 }
690 return true;
691}
692
caryclark1049f122015-04-20 08:31:59 -0700693template<typename TCurve, typename OppCurve>
694SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::oppT(double t) const {
695 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700696 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700697 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700698 if (between(test->fStartT, t, test->fEndT)) {
699 return test;
700 }
701 bounded = bounded->fNext;
702 }
halcanary96fcdcc2015-08-27 07:41:13 -0700703 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700704}
705
caryclark1049f122015-04-20 08:31:59 -0700706template<typename TCurve, typename OppCurve>
707bool SkTSpan<TCurve, OppCurve>::removeAllBounded() {
caryclark54359292015-03-26 07:52:43 -0700708 bool deleteSpan = false;
caryclark1049f122015-04-20 08:31:59 -0700709 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700710 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700711 SkTSpan<OppCurve, TCurve>* opp = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700712 deleteSpan |= opp->removeBounded(this);
713 bounded = bounded->fNext;
714 }
715 return deleteSpan;
716}
717
caryclark1049f122015-04-20 08:31:59 -0700718template<typename TCurve, typename OppCurve>
719bool SkTSpan<TCurve, OppCurve>::removeBounded(const SkTSpan<OppCurve, TCurve>* opp) {
caryclark54359292015-03-26 07:52:43 -0700720 if (fHasPerp) {
721 bool foundStart = false;
722 bool foundEnd = false;
caryclark1049f122015-04-20 08:31:59 -0700723 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700724 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700725 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700726 if (opp != test) {
727 foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT);
728 foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
729 }
730 bounded = bounded->fNext;
731 }
732 if (!foundStart || !foundEnd) {
733 fHasPerp = false;
734 fCoinStart.init();
735 fCoinEnd.init();
736 }
737 }
caryclark1049f122015-04-20 08:31:59 -0700738 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700739 SkTSpanBounded<OppCurve, TCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -0700740 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700741 SkTSpanBounded<OppCurve, TCurve>* boundedNext = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -0700742 if (opp == bounded->fBounded) {
743 if (prev) {
744 prev->fNext = boundedNext;
745 return false;
746 } else {
747 fBounded = boundedNext;
halcanary96fcdcc2015-08-27 07:41:13 -0700748 return fBounded == nullptr;
caryclark54359292015-03-26 07:52:43 -0700749 }
750 }
751 prev = bounded;
752 bounded = boundedNext;
753 }
caryclark643ede62016-08-08 14:27:45 -0700754 SkOPASSERT(0);
caryclark45fa4472015-01-16 07:04:10 -0800755 return false;
756}
757
caryclark1049f122015-04-20 08:31:59 -0700758template<typename TCurve, typename OppCurve>
759bool SkTSpan<TCurve, OppCurve>::splitAt(SkTSpan* work, double t, SkChunkAlloc* heap) {
caryclark45fa4472015-01-16 07:04:10 -0800760 fStartT = t;
761 fEndT = work->fEndT;
762 if (fStartT == fEndT) {
763 fCollapsed = true;
764 return false;
765 }
766 work->fEndT = t;
767 if (work->fStartT == work->fEndT) {
768 work->fCollapsed = true;
769 return false;
770 }
771 fPrev = work;
772 fNext = work->fNext;
773 fIsLinear = work->fIsLinear;
caryclark54359292015-03-26 07:52:43 -0700774 fIsLine = work->fIsLine;
775
caryclark45fa4472015-01-16 07:04:10 -0800776 work->fNext = this;
777 if (fNext) {
778 fNext->fPrev = this;
779 }
caryclark643ede62016-08-08 14:27:45 -0700780 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700781 SkTSpanBounded<OppCurve, TCurve>* bounded = work->fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700782 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700783 while (bounded) {
784 this->addBounded(bounded->fBounded, heap);
785 bounded = bounded->fNext;
786 }
787 bounded = fBounded;
788 while (bounded) {
789 bounded->fBounded->addBounded(this, heap);
790 bounded = bounded->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800791 }
792 return true;
793}
794
caryclark1049f122015-04-20 08:31:59 -0700795template<typename TCurve, typename OppCurve>
796void SkTSpan<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -0700797#if DEBUG_VALIDATE
798 SkASSERT(this != fPrev);
799 SkASSERT(this != fNext);
halcanary96fcdcc2015-08-27 07:41:13 -0700800 SkASSERT(fNext == nullptr || fNext != fPrev);
801 SkASSERT(fNext == nullptr || this == fNext->fPrev);
802 SkASSERT(fPrev == nullptr || this == fPrev->fNext);
caryclark643ede62016-08-08 14:27:45 -0700803 this->validateBounded();
804#endif
805#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700806 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed);
caryclarke839e782016-09-15 07:48:18 -0700807 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollapsed == 0xFF);
caryclark45fa4472015-01-16 07:04:10 -0800808 SkASSERT(0 <= fStartT);
809 SkASSERT(fEndT <= 1);
caryclark54359292015-03-26 07:52:43 -0700810 SkASSERT(fStartT <= fEndT);
caryclarke839e782016-09-15 07:48:18 -0700811 SkASSERT(fBounded || fCollapsed == 0xFF);
caryclark54359292015-03-26 07:52:43 -0700812 if (fHasPerp) {
caryclark6c3b9cd2016-09-26 05:36:58 -0700813 if (fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700814 validatePerpT(fCoinStart.perpT());
815 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt());
816 }
caryclark6c3b9cd2016-09-26 05:36:58 -0700817 if (fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700818 validatePerpT(fCoinEnd.perpT());
819 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt());
820 }
caryclarkccec0f92015-03-24 07:28:17 -0700821 }
reed0dc4dd62015-03-24 13:55:33 -0700822#endif
caryclark54359292015-03-26 07:52:43 -0700823}
caryclarkccec0f92015-03-24 07:28:17 -0700824
caryclark1049f122015-04-20 08:31:59 -0700825template<typename TCurve, typename OppCurve>
826void SkTSpan<TCurve, OppCurve>::validateBounded() const {
caryclark54359292015-03-26 07:52:43 -0700827#if DEBUG_VALIDATE
caryclark1049f122015-04-20 08:31:59 -0700828 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700829 while (testBounded) {
csmartdaltonceeaa782016-08-10 10:07:57 -0700830 SkDEBUGCODE(const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded);
caryclark54359292015-03-26 07:52:43 -0700831 SkASSERT(!overlap->fDeleted);
caryclark643ede62016-08-08 14:27:45 -0700832#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700833 SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
834 SkASSERT(overlap->findOppSpan(this));
caryclark643ede62016-08-08 14:27:45 -0700835#endif
caryclark54359292015-03-26 07:52:43 -0700836 testBounded = testBounded->fNext;
837 }
838#endif
839}
840
caryclark1049f122015-04-20 08:31:59 -0700841template<typename TCurve, typename OppCurve>
842void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const {
843 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700844 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700845 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded;
caryclark26ad22a2015-10-16 09:03:38 -0700846 if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) {
caryclark54359292015-03-26 07:52:43 -0700847 return;
848 }
849 testBounded = testBounded->fNext;
850 }
851 SkASSERT(0);
caryclark54359292015-03-26 07:52:43 -0700852}
853
caryclark1049f122015-04-20 08:31:59 -0700854template<typename TCurve, typename OppCurve>
855void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
856 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt);
caryclark54359292015-03-26 07:52:43 -0700857}
858
859
caryclark1049f122015-04-20 08:31:59 -0700860template<typename TCurve, typename OppCurve>
caryclarke25a4f62016-07-26 09:26:29 -0700861SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
862 SkDEBUGPARAMS(SkOpGlobalState* debugGlobalState)
863 PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
caryclark45fa4472015-01-16 07:04:10 -0800864 : fCurve(c)
caryclark1049f122015-04-20 08:31:59 -0700865 , fHeap(sizeof(SkTSpan<TCurve, OppCurve>) * 4)
halcanary96fcdcc2015-08-27 07:41:13 -0700866 , fCoincident(nullptr)
867 , fDeleted(nullptr)
caryclark45fa4472015-01-16 07:04:10 -0800868 , fActiveCount(0)
caryclarke25a4f62016-07-26 09:26:29 -0700869 SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState))
caryclark54359292015-03-26 07:52:43 -0700870 PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
871 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
872 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
caryclark45fa4472015-01-16 07:04:10 -0800873{
caryclark34efb702016-10-24 08:19:06 -0700874 this->resetRemovedEnds();
875 fHead = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700876 SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState));
caryclark45fa4472015-01-16 07:04:10 -0800877 fHead->init(c);
878}
879
caryclark1049f122015-04-20 08:31:59 -0700880template<typename TCurve, typename OppCurve>
881SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
882 SkTSpan<TCurve, OppCurve>* result;
caryclark45fa4472015-01-16 07:04:10 -0800883 if (fDeleted) {
884 result = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800885 fDeleted = result->fNext;
886 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700887 result = new (fHeap.allocThrow(sizeof(SkTSpan<TCurve, OppCurve>)))(
888 SkTSpan<TCurve, OppCurve>);
caryclark45fa4472015-01-16 07:04:10 -0800889#if DEBUG_T_SECT
890 ++fDebugAllocatedCount;
891#endif
892 }
caryclarked0935a2015-10-22 07:23:52 -0700893 result->reset();
caryclark08b32492015-04-06 11:41:29 -0700894 result->fHasPerp = false;
895 result->fDeleted = false;
caryclark55888e42016-07-18 10:01:36 -0700896 ++fActiveCount;
caryclark54359292015-03-26 07:52:43 -0700897 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
caryclark1049f122015-04-20 08:31:59 -0700898 SkDEBUGCODE(result->fDebugSect = this);
caryclarked0935a2015-10-22 07:23:52 -0700899#ifdef SK_DEBUG
900 result->fPart.debugInit();
901 result->fCoinStart.debugInit();
902 result->fCoinEnd.debugInit();
903 result->fPrev = result->fNext = nullptr;
904 result->fBounds.debugInit();
905 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN;
906 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF;
907#endif
caryclark45fa4472015-01-16 07:04:10 -0800908 return result;
909}
910
caryclark1049f122015-04-20 08:31:59 -0700911template<typename TCurve, typename OppCurve>
912bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
913 double tStep, double* resultT, double* oppT) {
914 SkTSpan<TCurve, OppCurve> work;
caryclark45fa4472015-01-16 07:04:10 -0800915 double result = work.fStartT = work.fEndT = tStart;
caryclark1049f122015-04-20 08:31:59 -0700916 SkDEBUGCODE(work.fDebugSect = this);
caryclark45fa4472015-01-16 07:04:10 -0800917 SkDPoint last = fCurve.ptAtT(tStart);
918 SkDPoint oppPt;
919 bool flip = false;
caryclarkcdeff812016-07-22 03:34:19 -0700920 bool contained = false;
caryclark45fa4472015-01-16 07:04:10 -0800921 SkDEBUGCODE(bool down = tStep < 0);
caryclark1049f122015-04-20 08:31:59 -0700922 const OppCurve& opp = sect2->fCurve;
caryclark45fa4472015-01-16 07:04:10 -0800923 do {
924 tStep *= 0.5;
925 work.fStartT += tStep;
926 if (flip) {
927 tStep = -tStep;
928 flip = false;
929 }
930 work.initBounds(fCurve);
931 if (work.fCollapsed) {
932 return false;
933 }
934 if (last.approximatelyEqual(work.fPart[0])) {
935 break;
936 }
937 last = work.fPart[0];
938 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp);
caryclark6c3b9cd2016-09-26 05:36:58 -0700939 if (work.fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700940#if DEBUG_T_SECT
941 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt());
942#endif
caryclark45fa4472015-01-16 07:04:10 -0800943 double oppTTest = work.fCoinStart.perpT();
caryclark54359292015-03-26 07:52:43 -0700944 if (sect2->fHead->contains(oppTTest)) {
caryclark45fa4472015-01-16 07:04:10 -0800945 *oppT = oppTTest;
946 oppPt = work.fCoinStart.perpPt();
caryclarkcdeff812016-07-22 03:34:19 -0700947 contained = true;
caryclark45fa4472015-01-16 07:04:10 -0800948 SkASSERT(down ? result > work.fStartT : result < work.fStartT);
949 result = work.fStartT;
950 continue;
951 }
952 }
953 tStep = -tStep;
954 flip = true;
955 } while (true);
caryclarkcdeff812016-07-22 03:34:19 -0700956 if (!contained) {
957 return false;
958 }
caryclark45fa4472015-01-16 07:04:10 -0800959 if (last.approximatelyEqual(fCurve[0])) {
960 result = 0;
961 } else if (last.approximatelyEqual(fCurve[TCurve::kPointLast])) {
962 result = 1;
963 }
964 if (oppPt.approximatelyEqual(opp[0])) {
965 *oppT = 0;
caryclark1049f122015-04-20 08:31:59 -0700966 } else if (oppPt.approximatelyEqual(opp[OppCurve::kPointLast])) {
caryclark45fa4472015-01-16 07:04:10 -0800967 *oppT = 1;
968 }
969 *resultT = result;
970 return true;
971}
972
973// OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
974// so that each quad sect has a pointer to the largest, and can update it as spans
975// are split
caryclark1049f122015-04-20 08:31:59 -0700976template<typename TCurve, typename OppCurve>
977SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
978 SkTSpan<TCurve, OppCurve>* test = fHead;
979 SkTSpan<TCurve, OppCurve>* largest = fHead;
caryclark54359292015-03-26 07:52:43 -0700980 bool lCollapsed = largest->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800981 while ((test = test->fNext)) {
caryclark54359292015-03-26 07:52:43 -0700982 bool tCollapsed = test->fCollapsed;
983 if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
984 largest->fBoundsMax < test->fBoundsMax)) {
caryclark45fa4472015-01-16 07:04:10 -0800985 largest = test;
caryclark1049f122015-04-20 08:31:59 -0700986 lCollapsed = test->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800987 }
988 }
caryclark54359292015-03-26 07:52:43 -0700989 return largest;
caryclark45fa4472015-01-16 07:04:10 -0800990}
991
caryclark1049f122015-04-20 08:31:59 -0700992template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -0700993bool SkTSect<TCurve, OppCurve>::coincidentCheck(SkTSect<OppCurve, TCurve>* sect2) {
caryclark1049f122015-04-20 08:31:59 -0700994 SkTSpan<TCurve, OppCurve>* first = fHead;
995 SkTSpan<TCurve, OppCurve>* last, * next;
caryclark45fa4472015-01-16 07:04:10 -0800996 do {
caryclark54359292015-03-26 07:52:43 -0700997 int consecutive = this->countConsecutiveSpans(first, &last);
998 next = last->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800999 if (consecutive < COINCIDENT_SPAN_COUNT) {
1000 continue;
1001 }
caryclark54359292015-03-26 07:52:43 -07001002 this->validate();
1003 sect2->validate();
1004 this->computePerpendiculars(sect2, first, last);
1005 this->validate();
1006 sect2->validate();
caryclark45fa4472015-01-16 07:04:10 -08001007 // check to see if a range of points are on the curve
caryclark1049f122015-04-20 08:31:59 -07001008 SkTSpan<TCurve, OppCurve>* coinStart = first;
caryclark54359292015-03-26 07:52:43 -07001009 do {
caryclarkef7cee42016-09-06 09:05:54 -07001010 bool success = this->extractCoincident(sect2, coinStart, last, &coinStart);
1011 if (!success) {
1012 return false;
1013 }
caryclark54359292015-03-26 07:52:43 -07001014 } while (coinStart && !last->fDeleted);
caryclark55888e42016-07-18 10:01:36 -07001015 if (!fHead || !sect2->fHead) {
1016 break;
1017 }
caryclark643ede62016-08-08 14:27:45 -07001018 if (!next || next->fDeleted) {
1019 break;
1020 }
caryclark45fa4472015-01-16 07:04:10 -08001021 } while ((first = next));
caryclarkef7cee42016-09-06 09:05:54 -07001022 return true;
caryclark45fa4472015-01-16 07:04:10 -08001023}
1024
caryclark1049f122015-04-20 08:31:59 -07001025template<typename TCurve, typename OppCurve>
caryclark26ad22a2015-10-16 09:03:38 -07001026void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2,
1027 double start1s, double start1e) {
1028 SkTSpan<TCurve, OppCurve>* first = fHead;
1029 SkTSpan<TCurve, OppCurve>* last = this->tail();
1030 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead;
1031 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail();
1032 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1033 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
1034 this->removeSpanRange(first, last);
1035 sect2->removeSpanRange(oppFirst, oppLast);
1036 first->fStartT = start1s;
1037 first->fEndT = start1e;
1038 first->resetBounds(fCurve);
1039 first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve);
1040 first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->fCurve);
1041 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
caryclarkef784fb2015-10-30 12:03:06 -07001042 double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : SkTMax(0., first->fCoinStart.perpT());
1043 double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : SkTMin(1., first->fCoinEnd.perpT());
caryclark26ad22a2015-10-16 09:03:38 -07001044 if (!oppMatched) {
1045 SkTSwap(oppStartT, oppEndT);
1046 }
1047 oppFirst->fStartT = oppStartT;
1048 oppFirst->fEndT = oppEndT;
1049 oppFirst->resetBounds(sect2->fCurve);
1050 this->removeCoincident(first, false);
1051 sect2->removeCoincident(oppFirst, true);
1052 if (deleteEmptySpans) {
1053 this->deleteEmptySpans();
1054 sect2->deleteEmptySpans();
1055 }
1056}
1057
1058template<typename TCurve, typename OppCurve>
caryclark1049f122015-04-20 08:31:59 -07001059bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) {
1060 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001061 while (test) {
1062 if (between(test->fStartT, t, test->fEndT)) {
1063 return true;
1064 }
1065 test = test->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001066 }
caryclark54359292015-03-26 07:52:43 -07001067 return false;
caryclark45fa4472015-01-16 07:04:10 -08001068}
1069
caryclark1049f122015-04-20 08:31:59 -07001070template<typename TCurve, typename OppCurve>
1071int SkTSect<TCurve, OppCurve>::collapsed() const {
1072 int result = 0;
1073 const SkTSpan<TCurve, OppCurve>* test = fHead;
1074 while (test) {
1075 if (test->fCollapsed) {
1076 ++result;
1077 }
1078 test = test->next();
1079 }
1080 return result;
1081}
1082
1083template<typename TCurve, typename OppCurve>
1084void SkTSect<TCurve, OppCurve>::computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2,
1085 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
1086 const OppCurve& opp = sect2->fCurve;
1087 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001088 SkTSpan<TCurve, OppCurve>* prior = nullptr;
caryclark45fa4472015-01-16 07:04:10 -08001089 do {
caryclark54359292015-03-26 07:52:43 -07001090 if (!work->fHasPerp && !work->fCollapsed) {
1091 if (prior) {
1092 work->fCoinStart = prior->fCoinEnd;
1093 } else {
1094 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp);
caryclark45fa4472015-01-16 07:04:10 -08001095 }
caryclark6c3b9cd2016-09-26 05:36:58 -07001096 if (work->fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001097 double perpT = work->fCoinStart.perpT();
1098 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001099 work->fCoinStart.init();
caryclark54359292015-03-26 07:52:43 -07001100 } else {
1101 sect2->addForPerp(work, perpT);
1102 }
1103 }
1104 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPointLast], opp);
caryclark6c3b9cd2016-09-26 05:36:58 -07001105 if (work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001106 double perpT = work->fCoinEnd.perpT();
1107 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001108 work->fCoinEnd.init();
caryclark54359292015-03-26 07:52:43 -07001109 } else {
1110 sect2->addForPerp(work, perpT);
1111 }
1112 }
1113 work->fHasPerp = true;
caryclark45fa4472015-01-16 07:04:10 -08001114 }
1115 if (work == last) {
1116 break;
1117 }
caryclark54359292015-03-26 07:52:43 -07001118 prior = work;
caryclark45fa4472015-01-16 07:04:10 -08001119 work = work->fNext;
1120 SkASSERT(work);
1121 } while (true);
caryclark54359292015-03-26 07:52:43 -07001122}
1123
caryclark1049f122015-04-20 08:31:59 -07001124template<typename TCurve, typename OppCurve>
1125int SkTSect<TCurve, OppCurve>::countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
1126 SkTSpan<TCurve, OppCurve>** lastPtr) const {
caryclark54359292015-03-26 07:52:43 -07001127 int consecutive = 1;
caryclark1049f122015-04-20 08:31:59 -07001128 SkTSpan<TCurve, OppCurve>* last = first;
caryclark54359292015-03-26 07:52:43 -07001129 do {
caryclark1049f122015-04-20 08:31:59 -07001130 SkTSpan<TCurve, OppCurve>* next = last->fNext;
caryclark54359292015-03-26 07:52:43 -07001131 if (!next) {
1132 break;
1133 }
1134 if (next->fStartT > last->fEndT) {
1135 break;
1136 }
1137 ++consecutive;
1138 last = next;
1139 } while (true);
1140 *lastPtr = last;
1141 return consecutive;
1142}
1143
caryclark1049f122015-04-20 08:31:59 -07001144template<typename TCurve, typename OppCurve>
1145bool SkTSect<TCurve, OppCurve>::debugHasBounded(const SkTSpan<OppCurve, TCurve>* span) const {
1146 const SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001147 if (!test) {
1148 return false;
1149 }
1150 do {
1151 if (test->findOppSpan(span)) {
1152 return true;
1153 }
1154 } while ((test = test->next()));
1155 return false;
1156}
1157
caryclark1049f122015-04-20 08:31:59 -07001158template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001159bool SkTSect<TCurve, OppCurve>::deleteEmptySpans() {
caryclark1049f122015-04-20 08:31:59 -07001160 SkTSpan<TCurve, OppCurve>* test;
1161 SkTSpan<TCurve, OppCurve>* next = fHead;
caryclark54359292015-03-26 07:52:43 -07001162 while ((test = next)) {
1163 next = test->fNext;
1164 if (!test->fBounded) {
caryclarkef7cee42016-09-06 09:05:54 -07001165 if (!this->removeSpan(test)) {
1166 return false;
1167 }
caryclark54359292015-03-26 07:52:43 -07001168 }
1169 }
caryclarkef7cee42016-09-06 09:05:54 -07001170 return true;
caryclark54359292015-03-26 07:52:43 -07001171}
1172
caryclark1049f122015-04-20 08:31:59 -07001173template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001174bool SkTSect<TCurve, OppCurve>::extractCoincident(
caryclark1049f122015-04-20 08:31:59 -07001175 SkTSect<OppCurve, TCurve>* sect2,
caryclarkef7cee42016-09-06 09:05:54 -07001176 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
1177 SkTSpan<TCurve, OppCurve>** result) {
caryclark1049f122015-04-20 08:31:59 -07001178 first = findCoincidentRun(first, &last);
caryclarka1b42d92016-08-16 10:25:29 -07001179 if (!first || !last) {
caryclarkef7cee42016-09-06 09:05:54 -07001180 *result = nullptr;
1181 return true;
caryclark45fa4472015-01-16 07:04:10 -08001182 }
1183 // march outwards to find limit of coincidence from here to previous and next spans
1184 double startT = first->fStartT;
caryclarkd8bc16b2015-03-26 09:05:12 -07001185 double oppStartT SK_INIT_TO_AVOID_WARNING;
caryclark54359292015-03-26 07:52:43 -07001186 double oppEndT SK_INIT_TO_AVOID_WARNING;
caryclark1049f122015-04-20 08:31:59 -07001187 SkTSpan<TCurve, OppCurve>* prev = first->fPrev;
caryclark6c3b9cd2016-09-26 05:36:58 -07001188 SkASSERT(first->fCoinStart.isMatch());
caryclark1049f122015-04-20 08:31:59 -07001189 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
caryclark6c3b9cd2016-09-26 05:36:58 -07001190 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001191 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
1192 double coinStart;
1193 SkDEBUGCODE(double coinEnd);
caryclark1049f122015-04-20 08:31:59 -07001194 SkTSpan<OppCurve, TCurve>* cutFirst;
caryclark54359292015-03-26 07:52:43 -07001195 if (prev && prev->fEndT == startT
1196 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
1197 &oppStartT)
caryclark1049f122015-04-20 08:31:59 -07001198 && prev->fStartT < coinStart && coinStart < startT
1199 && (cutFirst = prev->oppT(oppStartT))) {
1200 oppFirst = cutFirst;
caryclark54359292015-03-26 07:52:43 -07001201 first = this->addSplitAt(prev, coinStart);
1202 first->markCoincident();
1203 prev->fCoinEnd.markCoincident();
1204 if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
caryclark1049f122015-04-20 08:31:59 -07001205 SkTSpan<OppCurve, TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
caryclark54359292015-03-26 07:52:43 -07001206 if (oppMatched) {
1207 oppFirst->fCoinEnd.markCoincident();
1208 oppHalf->markCoincident();
1209 oppFirst = oppHalf;
1210 } else {
1211 oppFirst->markCoincident();
1212 oppHalf->fCoinStart.markCoincident();
1213 }
1214 }
1215 } else {
1216 SkDEBUGCODE(coinStart = first->fStartT);
caryclarka35ab3e2016-10-20 08:32:18 -07001217 FAIL_IF(!oppFirst);
caryclark54359292015-03-26 07:52:43 -07001218 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
1219 }
caryclark1049f122015-04-20 08:31:59 -07001220 // FIXME: incomplete : if we're not at the end, find end of coin
1221 SkTSpan<OppCurve, TCurve>* oppLast;
caryclark6c3b9cd2016-09-26 05:36:58 -07001222 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001223 oppLast = last->findOppT(last->fCoinEnd.perpT());
1224 SkDEBUGCODE(coinEnd = last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001225#ifdef SK_DEBUG
1226 if (!this->globalState() || !this->globalState()->debugSkipAssert()) {
1227 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT;
1228 }
1229#endif
caryclark54359292015-03-26 07:52:43 -07001230 if (!oppMatched) {
1231 SkTSwap(oppFirst, oppLast);
1232 SkTSwap(oppStartT, oppEndT);
1233 }
caryclarke25a4f62016-07-26 09:26:29 -07001234 SkOPASSERT(oppStartT < oppEndT);
caryclark54359292015-03-26 07:52:43 -07001235 SkASSERT(coinStart == first->fStartT);
1236 SkASSERT(coinEnd == last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001237 SkOPASSERT(oppStartT == oppFirst->fStartT);
1238 SkOPASSERT(oppEndT == oppLast->fEndT);
1239 if (!oppFirst) {
caryclarkef7cee42016-09-06 09:05:54 -07001240 *result = nullptr;
1241 return true;
caryclark643ede62016-08-08 14:27:45 -07001242 }
caryclark42942862016-08-19 07:01:33 -07001243 if (!oppLast) {
caryclarkef7cee42016-09-06 09:05:54 -07001244 *result = nullptr;
1245 return true;
caryclark42942862016-08-19 07:01:33 -07001246 }
caryclark54359292015-03-26 07:52:43 -07001247 // reduce coincident runs to single entries
1248 this->validate();
1249 sect2->validate();
caryclark1049f122015-04-20 08:31:59 -07001250 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1251 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
caryclark54359292015-03-26 07:52:43 -07001252 this->removeSpanRange(first, last);
1253 sect2->removeSpanRange(oppFirst, oppLast);
1254 first->fEndT = last->fEndT;
1255 first->resetBounds(this->fCurve);
1256 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], sect2->fCurve);
1257 first->fCoinEnd.setPerp(fCurve, first->fEndT, first->fPart[TCurve::kPointLast], sect2->fCurve);
1258 oppStartT = first->fCoinStart.perpT();
1259 oppEndT = first->fCoinEnd.perpT();
1260 if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) {
1261 if (!oppMatched) {
1262 SkTSwap(oppStartT, oppEndT);
1263 }
1264 oppFirst->fStartT = oppStartT;
1265 oppFirst->fEndT = oppEndT;
1266 oppFirst->resetBounds(sect2->fCurve);
1267 }
1268 this->validateBounded();
1269 sect2->validateBounded();
1270 last = first->fNext;
1271 this->removeCoincident(first, false);
1272 sect2->removeCoincident(oppFirst, true);
caryclark1049f122015-04-20 08:31:59 -07001273 if (deleteEmptySpans) {
caryclarkef7cee42016-09-06 09:05:54 -07001274 if (!this->deleteEmptySpans() || !sect2->deleteEmptySpans()) {
1275 *result = nullptr;
1276 return false;
1277 }
caryclark54359292015-03-26 07:52:43 -07001278 }
1279 this->validate();
1280 sect2->validate();
caryclarkef7cee42016-09-06 09:05:54 -07001281 *result = last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr;
1282 return true;
caryclark54359292015-03-26 07:52:43 -07001283}
1284
caryclark1049f122015-04-20 08:31:59 -07001285template<typename TCurve, typename OppCurve>
1286SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun(
1287 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) {
1288 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001289 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr;
1290 first = nullptr;
caryclark54359292015-03-26 07:52:43 -07001291 // find the first fully coincident span
1292 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07001293 if (work->fCoinStart.isMatch()) {
caryclark1049f122015-04-20 08:31:59 -07001294#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -07001295 work->validatePerpT(work->fCoinStart.perpT());
1296 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt());
caryclark1049f122015-04-20 08:31:59 -07001297#endif
caryclarka35ab3e2016-10-20 08:32:18 -07001298 SkOPASSERT(work->hasOppT(work->fCoinStart.perpT()));
caryclark6c3b9cd2016-09-26 05:36:58 -07001299 if (!work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001300 break;
1301 }
1302 lastCandidate = work;
1303 if (!first) {
1304 first = work;
1305 }
caryclark1049f122015-04-20 08:31:59 -07001306 } else if (first && work->fCollapsed) {
1307 *lastPtr = lastCandidate;
1308 return first;
caryclark54359292015-03-26 07:52:43 -07001309 } else {
halcanary96fcdcc2015-08-27 07:41:13 -07001310 lastCandidate = nullptr;
caryclark643ede62016-08-08 14:27:45 -07001311 SkOPASSERT(!first);
caryclark54359292015-03-26 07:52:43 -07001312 }
1313 if (work == *lastPtr) {
1314 return first;
1315 }
1316 work = work->fNext;
caryclarke25a4f62016-07-26 09:26:29 -07001317 if (!work) {
1318 return nullptr;
1319 }
caryclark54359292015-03-26 07:52:43 -07001320 } while (true);
1321 if (lastCandidate) {
1322 *lastPtr = lastCandidate;
1323 }
1324 return first;
1325}
1326
caryclark1049f122015-04-20 08:31:59 -07001327template<typename TCurve, typename OppCurve>
1328int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
1329 SkTSect<OppCurve, TCurve>* opp,
1330 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult) {
caryclark54359292015-03-26 07:52:43 -07001331 bool spanStart, oppStart;
1332 int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
1333 if (hullResult >= 0) {
1334 if (hullResult == 2) { // hulls have one point in common
1335 if (!span->fBounded || !span->fBounded->fNext) {
1336 SkASSERT(!span->fBounded || span->fBounded->fBounded == oppSpan);
1337 if (spanStart) {
1338 span->fEndT = span->fStartT;
caryclark45fa4472015-01-16 07:04:10 -08001339 } else {
caryclark54359292015-03-26 07:52:43 -07001340 span->fStartT = span->fEndT;
1341 }
1342 } else {
1343 hullResult = 1;
1344 }
1345 if (!oppSpan->fBounded || !oppSpan->fBounded->fNext) {
1346 SkASSERT(!oppSpan->fBounded || oppSpan->fBounded->fBounded == span);
1347 if (oppStart) {
1348 oppSpan->fEndT = oppSpan->fStartT;
1349 } else {
1350 oppSpan->fStartT = oppSpan->fEndT;
1351 }
1352 *oppResult = 2;
1353 } else {
1354 *oppResult = 1;
1355 }
1356 } else {
1357 *oppResult = 1;
1358 }
1359 return hullResult;
1360 }
1361 if (span->fIsLine && oppSpan->fIsLine) {
1362 SkIntersections i;
1363 int sects = this->linesIntersect(span, opp, oppSpan, &i);
caryclark26ad22a2015-10-16 09:03:38 -07001364 if (sects == 2) {
1365 return *oppResult = 1;
1366 }
caryclark54359292015-03-26 07:52:43 -07001367 if (!sects) {
1368 return -1;
1369 }
caryclark34efb702016-10-24 08:19:06 -07001370 this->removedEndCheck(span);
caryclark54359292015-03-26 07:52:43 -07001371 span->fStartT = span->fEndT = i[0][0];
caryclark34efb702016-10-24 08:19:06 -07001372 opp->removedEndCheck(oppSpan);
caryclark54359292015-03-26 07:52:43 -07001373 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1374 return *oppResult = 2;
1375 }
1376 if (span->fIsLinear || oppSpan->fIsLinear) {
1377 return *oppResult = (int) span->linearsIntersect(oppSpan);
1378 }
1379 return *oppResult = 1;
1380}
1381
caryclarked0935a2015-10-22 07:23:52 -07001382template<typename TCurve>
1383static bool is_parallel(const SkDLine& thisLine, const TCurve& opp) {
1384 if (!opp.IsConic()) {
1385 return false; // FIXME : breaks a lot of stuff now
1386 }
1387 int finds = 0;
1388 SkDLine thisPerp;
1389 thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1390 thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1391 thisPerp.fPts[1] = thisLine.fPts[1];
1392 SkIntersections perpRayI;
1393 perpRayI.intersectRay(opp, thisPerp);
1394 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1395 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]);
1396 }
1397 thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1398 thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1399 thisPerp.fPts[0] = thisLine.fPts[0];
1400 perpRayI.intersectRay(opp, thisPerp);
1401 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1402 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]);
1403 }
1404 return finds >= 2;
1405}
1406
caryclark54359292015-03-26 07:52:43 -07001407// while the intersection points are sufficiently far apart:
1408// construct the tangent lines from the intersections
1409// find the point where the tangent line intersects the opposite curve
caryclark1049f122015-04-20 08:31:59 -07001410template<typename TCurve, typename OppCurve>
1411int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
1412 SkTSect<OppCurve, TCurve>* opp,
1413 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
caryclarka35ab3e2016-10-20 08:32:18 -07001414 SkIntersections thisRayI SkDEBUGCODE((span->fDebugGlobalState));
1415 SkIntersections oppRayI SkDEBUGCODE((span->fDebugGlobalState));
caryclark54359292015-03-26 07:52:43 -07001416 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
caryclark1049f122015-04-20 08:31:59 -07001417 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
caryclark54359292015-03-26 07:52:43 -07001418 int loopCount = 0;
1419 double bestDistSq = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -07001420 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1421 return 0;
1422 }
1423 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1424 return 0;
1425 }
caryclark26ad22a2015-10-16 09:03:38 -07001426 // if the ends of each line intersect the opposite curve, the lines are coincident
1427 if (thisRayI.used() > 1) {
1428 int ptMatches = 0;
1429 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) {
1430 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1431 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPts[lIndex]);
1432 }
1433 }
caryclarked0935a2015-10-22 07:23:52 -07001434 if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001435 return 2;
1436 }
1437 }
1438 if (oppRayI.used() > 1) {
1439 int ptMatches = 0;
1440 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) {
1441 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1442 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[lIndex]);
1443 }
1444 }
caryclarked0935a2015-10-22 07:23:52 -07001445 if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001446 return 2;
1447 }
1448 }
caryclark54359292015-03-26 07:52:43 -07001449 do {
caryclark54359292015-03-26 07:52:43 -07001450 // pick the closest pair of points
1451 double closest = DBL_MAX;
1452 int closeIndex SK_INIT_TO_AVOID_WARNING;
1453 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1454 for (int index = 0; index < oppRayI.used(); ++index) {
1455 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
1456 continue;
1457 }
1458 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) {
1459 if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppSpan->fEndT)) {
1460 continue;
1461 }
1462 double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oIndex));
1463 if (closest > distSq) {
1464 closest = distSq;
1465 closeIndex = index;
1466 oppCloseIndex = oIndex;
caryclarkccec0f92015-03-24 07:28:17 -07001467 }
caryclarkccec0f92015-03-24 07:28:17 -07001468 }
reed0dc4dd62015-03-24 13:55:33 -07001469 }
caryclark54359292015-03-26 07:52:43 -07001470 if (closest == DBL_MAX) {
caryclark1049f122015-04-20 08:31:59 -07001471 break;
reed0dc4dd62015-03-24 13:55:33 -07001472 }
caryclark54359292015-03-26 07:52:43 -07001473 const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
1474 const SkDPoint& iPt = oppRayI.pt(closeIndex);
1475 if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT)
1476 && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan->fEndT)
1477 && oppIPt.approximatelyEqual(iPt)) {
1478 i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex);
1479 return i->used();
1480 }
1481 double distSq = oppIPt.distanceSquared(iPt);
1482 if (bestDistSq < distSq || ++loopCount > 5) {
caryclark1049f122015-04-20 08:31:59 -07001483 return 0;
caryclark54359292015-03-26 07:52:43 -07001484 }
1485 bestDistSq = distSq;
caryclark1049f122015-04-20 08:31:59 -07001486 double oppStart = oppRayI[0][closeIndex];
1487 thisLine[0] = fCurve.ptAtT(oppStart);
1488 thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart);
1489 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1490 break;
1491 }
1492 double start = thisRayI[0][oppCloseIndex];
1493 oppLine[0] = opp->fCurve.ptAtT(start);
1494 oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start);
1495 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1496 break;
1497 }
caryclark54359292015-03-26 07:52:43 -07001498 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001499 // convergence may fail if the curves are nearly coincident
1500 SkTCoincident<OppCurve, TCurve> oCoinS, oCoinE;
1501 oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->fPart[0], fCurve);
1502 oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->fPart[OppCurve::kPointLast], fCurve);
1503 double tStart = oCoinS.perpT();
1504 double tEnd = oCoinE.perpT();
1505 bool swap = tStart > tEnd;
1506 if (swap) {
1507 SkTSwap(tStart, tEnd);
1508 }
1509 tStart = SkTMax(tStart, span->fStartT);
1510 tEnd = SkTMin(tEnd, span->fEndT);
1511 if (tStart > tEnd) {
1512 return 0;
1513 }
1514 SkDVector perpS, perpE;
1515 if (tStart == span->fStartT) {
1516 SkTCoincident<TCurve, OppCurve> coinS;
1517 coinS.setPerp(fCurve, span->fStartT, span->fPart[0], opp->fCurve);
1518 perpS = span->fPart[0] - coinS.perpPt();
1519 } else if (swap) {
1520 perpS = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1521 } else {
1522 perpS = oCoinS.perpPt() - oppSpan->fPart[0];
1523 }
1524 if (tEnd == span->fEndT) {
1525 SkTCoincident<TCurve, OppCurve> coinE;
1526 coinE.setPerp(fCurve, span->fEndT, span->fPart[TCurve::kPointLast], opp->fCurve);
1527 perpE = span->fPart[TCurve::kPointLast] - coinE.perpPt();
1528 } else if (swap) {
1529 perpE = oCoinS.perpPt() - oppSpan->fPart[0];
1530 } else {
1531 perpE = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1532 }
1533 if (perpS.dot(perpE) >= 0) {
1534 return 0;
1535 }
1536 SkTCoincident<TCurve, OppCurve> coinW;
1537 double workT = tStart;
1538 double tStep = tEnd - tStart;
1539 SkDPoint workPt;
1540 do {
1541 tStep *= 0.5;
1542 if (precisely_zero(tStep)) {
1543 return 0;
1544 }
1545 workT += tStep;
1546 workPt = fCurve.ptAtT(workT);
1547 coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
caryclark27c015d2016-09-23 05:47:20 -07001548 double perpT = coinW.perpT();
caryclark6c3b9cd2016-09-26 05:36:58 -07001549 if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) {
caryclarkb6693002015-12-16 12:28:35 -08001550 continue;
1551 }
caryclark1049f122015-04-20 08:31:59 -07001552 SkDVector perpW = workPt - coinW.perpPt();
1553 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
1554 tStep = -tStep;
1555 }
caryclarkb6693002015-12-16 12:28:35 -08001556 if (workPt.approximatelyEqual(coinW.perpPt())) {
1557 break;
1558 }
1559 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001560 double oppTTest = coinW.perpT();
1561 if (!opp->fHead->contains(oppTTest)) {
1562 return 0;
1563 }
1564 i->setMax(1);
1565 i->insert(workT, oppTTest, workPt);
1566 return 1;
caryclark54359292015-03-26 07:52:43 -07001567}
1568
1569
caryclark1049f122015-04-20 08:31:59 -07001570template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001571bool SkTSect<TCurve, OppCurve>::markSpanGone(SkTSpan<TCurve, OppCurve>* span) {
1572 if (--fActiveCount < 0) {
1573 return false;
1574 }
caryclark54359292015-03-26 07:52:43 -07001575 span->fNext = fDeleted;
1576 fDeleted = span;
caryclarke25a4f62016-07-26 09:26:29 -07001577 SkOPASSERT(!span->fDeleted);
caryclark54359292015-03-26 07:52:43 -07001578 span->fDeleted = true;
caryclarkef7cee42016-09-06 09:05:54 -07001579 return true;
caryclark54359292015-03-26 07:52:43 -07001580}
1581
caryclark1049f122015-04-20 08:31:59 -07001582template<typename TCurve, typename OppCurve>
1583bool SkTSect<TCurve, OppCurve>::matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2,
1584 double t2) const {
caryclark54359292015-03-26 07:52:43 -07001585 SkDVector dxdy = this->fCurve.dxdyAtT(t);
1586 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
1587 return dxdy.dot(dxdy2) >= 0;
1588}
1589
caryclark1049f122015-04-20 08:31:59 -07001590template<typename TCurve, typename OppCurve>
1591void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2,
1592 double t2, bool* calcMatched, bool* oppMatched) const {
caryclark54359292015-03-26 07:52:43 -07001593 if (*calcMatched) {
caryclark55888e42016-07-18 10:01:36 -07001594 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
caryclark54359292015-03-26 07:52:43 -07001595 } else {
1596 *oppMatched = this->matchedDirection(t, sect2, t2);
1597 *calcMatched = true;
1598 }
1599}
1600
caryclark1049f122015-04-20 08:31:59 -07001601template<typename TCurve, typename OppCurve>
1602void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2) {
caryclark54359292015-03-26 07:52:43 -07001603 double smallLimit = 0;
1604 do {
1605 // find the smallest unprocessed span
halcanary96fcdcc2015-08-27 07:41:13 -07001606 SkTSpan<TCurve, OppCurve>* smaller = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001607 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001608 do {
caryclark221a4bb2016-10-07 11:15:15 -07001609 if (!test) {
1610 return;
1611 }
caryclark54359292015-03-26 07:52:43 -07001612 if (test->fStartT < smallLimit) {
1613 continue;
1614 }
1615 if (smaller && smaller->fEndT < test->fStartT) {
1616 continue;
1617 }
1618 smaller = test;
1619 } while ((test = test->fNext));
1620 if (!smaller) {
1621 return;
1622 }
1623 smallLimit = smaller->fEndT;
1624 // find next larger span
halcanary96fcdcc2015-08-27 07:41:13 -07001625 SkTSpan<TCurve, OppCurve>* prior = nullptr;
1626 SkTSpan<TCurve, OppCurve>* larger = nullptr;
1627 SkTSpan<TCurve, OppCurve>* largerPrior = nullptr;
caryclark54359292015-03-26 07:52:43 -07001628 test = fCoincident;
1629 do {
1630 if (test->fStartT < smaller->fEndT) {
1631 continue;
1632 }
caryclark221a4bb2016-10-07 11:15:15 -07001633 SkOPASSERT(test->fStartT != smaller->fEndT);
caryclark54359292015-03-26 07:52:43 -07001634 if (larger && larger->fStartT < test->fStartT) {
1635 continue;
1636 }
1637 largerPrior = prior;
1638 larger = test;
1639 } while ((prior = test), (test = test->fNext));
1640 if (!larger) {
1641 continue;
1642 }
1643 // check middle t value to see if it is coincident as well
1644 double midT = (smaller->fEndT + larger->fStartT) / 2;
1645 SkDPoint midPt = fCurve.ptAtT(midT);
caryclark1049f122015-04-20 08:31:59 -07001646 SkTCoincident<TCurve, OppCurve> coin;
caryclark54359292015-03-26 07:52:43 -07001647 coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07001648 if (coin.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001649 smaller->fEndT = larger->fEndT;
1650 smaller->fCoinEnd = larger->fCoinEnd;
1651 if (largerPrior) {
1652 largerPrior->fNext = larger->fNext;
caryclark643ede62016-08-08 14:27:45 -07001653 largerPrior->validate();
caryclark54359292015-03-26 07:52:43 -07001654 } else {
1655 fCoincident = larger->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001656 }
1657 }
caryclark54359292015-03-26 07:52:43 -07001658 } while (true);
1659}
1660
caryclark1049f122015-04-20 08:31:59 -07001661template<typename TCurve, typename OppCurve>
1662SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev(
1663 SkTSpan<TCurve, OppCurve>* span) const {
halcanary96fcdcc2015-08-27 07:41:13 -07001664 SkTSpan<TCurve, OppCurve>* result = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001665 SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001666 while (span != test) {
1667 result = test;
1668 test = test->fNext;
1669 SkASSERT(test);
caryclarkccec0f92015-03-24 07:28:17 -07001670 }
caryclark55888e42016-07-18 10:01:36 -07001671 return result;
caryclarkccec0f92015-03-24 07:28:17 -07001672}
1673
caryclark1049f122015-04-20 08:31:59 -07001674template<typename TCurve, typename OppCurve>
1675void SkTSect<TCurve, OppCurve>::recoverCollapsed() {
1676 SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001677 while (deleted) {
caryclark1049f122015-04-20 08:31:59 -07001678 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001679 if (deleted->fCollapsed) {
caryclark1049f122015-04-20 08:31:59 -07001680 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead;
caryclark45fa4472015-01-16 07:04:10 -08001681 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
1682 spanPtr = &(*spanPtr)->fNext;
1683 }
1684 deleted->fNext = *spanPtr;
1685 *spanPtr = deleted;
1686 }
1687 deleted = delNext;
1688 }
1689}
1690
caryclark1049f122015-04-20 08:31:59 -07001691template<typename TCurve, typename OppCurve>
1692void SkTSect<TCurve, OppCurve>::removeAllBut(const SkTSpan<OppCurve, TCurve>* keep,
1693 SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp) {
1694 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001695 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001696 SkTSpan<OppCurve, TCurve>* bounded = testBounded->fBounded;
1697 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001698 // may have been deleted when opp did 'remove all but'
1699 if (bounded != keep && !bounded->fDeleted) {
1700 SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
1701 if (bounded->removeBounded(span)) {
1702 opp->removeSpan(bounded);
1703 }
caryclarkccec0f92015-03-24 07:28:17 -07001704 }
caryclark54359292015-03-26 07:52:43 -07001705 testBounded = next;
caryclarkccec0f92015-03-24 07:28:17 -07001706 }
caryclark54359292015-03-26 07:52:43 -07001707 SkASSERT(!span->fDeleted);
1708 SkASSERT(span->findOppSpan(keep));
1709 SkASSERT(keep->findOppSpan(span));
caryclarkccec0f92015-03-24 07:28:17 -07001710}
1711
caryclark1049f122015-04-20 08:31:59 -07001712template<typename TCurve, typename OppCurve>
1713void SkTSect<TCurve, OppCurve>::removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp) {
1714 SkTSpan<TCurve, OppCurve>* test = fHead;
1715 SkTSpan<TCurve, OppCurve>* next;
caryclark54359292015-03-26 07:52:43 -07001716 do {
1717 next = test->fNext;
1718 if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
1719 continue;
reed0dc4dd62015-03-24 13:55:33 -07001720 }
caryclark54359292015-03-26 07:52:43 -07001721 SkDVector startV = test->fCoinStart.perpPt() - test->fPart[0];
1722 SkDVector endV = test->fCoinEnd.perpPt() - test->fPart[TCurve::kPointLast];
1723#if DEBUG_T_SECT
1724 SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUNCTION__,
1725 startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV));
1726#endif
1727 if (startV.dot(endV) <= 0) {
1728 continue;
1729 }
1730 this->removeSpans(test, opp);
1731 } while ((test = next));
1732}
1733
caryclark1049f122015-04-20 08:31:59 -07001734template<typename TCurve, typename OppCurve>
1735void SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween) {
caryclark54359292015-03-26 07:52:43 -07001736 this->unlinkSpan(span);
1737 if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
1738 --fActiveCount;
1739 span->fNext = fCoincident;
1740 fCoincident = span;
1741 } else {
1742 this->markSpanGone(span);
reed0dc4dd62015-03-24 13:55:33 -07001743 }
caryclarkccec0f92015-03-24 07:28:17 -07001744}
1745
caryclark1049f122015-04-20 08:31:59 -07001746template<typename TCurve, typename OppCurve>
caryclark34efb702016-10-24 08:19:06 -07001747void SkTSect<TCurve, OppCurve>::removedEndCheck(SkTSpan<TCurve, OppCurve>* span) {
caryclark6c3b9cd2016-09-26 05:36:58 -07001748 if (!span->fStartT) {
1749 fRemovedStartT = true;
1750 }
1751 if (1 == span->fEndT) {
1752 fRemovedEndT = true;
1753 }
caryclark34efb702016-10-24 08:19:06 -07001754}
1755
1756template<typename TCurve, typename OppCurve>
1757bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {\
1758 this->removedEndCheck(span);
caryclark54359292015-03-26 07:52:43 -07001759 this->unlinkSpan(span);
caryclarkef7cee42016-09-06 09:05:54 -07001760 return this->markSpanGone(span);
caryclark54359292015-03-26 07:52:43 -07001761}
1762
caryclark1049f122015-04-20 08:31:59 -07001763template<typename TCurve, typename OppCurve>
1764void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first,
1765 SkTSpan<TCurve, OppCurve>* last) {
caryclark54359292015-03-26 07:52:43 -07001766 if (first == last) {
1767 return;
1768 }
caryclark1049f122015-04-20 08:31:59 -07001769 SkTSpan<TCurve, OppCurve>* span = first;
caryclark54359292015-03-26 07:52:43 -07001770 SkASSERT(span);
caryclark1049f122015-04-20 08:31:59 -07001771 SkTSpan<TCurve, OppCurve>* final = last->fNext;
1772 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001773 while ((span = next) && span != final) {
1774 next = span->fNext;
1775 this->markSpanGone(span);
1776 }
1777 if (final) {
1778 final->fPrev = first;
1779 }
1780 first->fNext = final;
caryclark643ede62016-08-08 14:27:45 -07001781 first->validate();
caryclark54359292015-03-26 07:52:43 -07001782}
1783
caryclark1049f122015-04-20 08:31:59 -07001784template<typename TCurve, typename OppCurve>
1785void SkTSect<TCurve, OppCurve>::removeSpans(SkTSpan<TCurve, OppCurve>* span,
1786 SkTSect<OppCurve, TCurve>* opp) {
1787 SkTSpanBounded<OppCurve, TCurve>* bounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001788 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -07001789 SkTSpan<OppCurve, TCurve>* spanBounded = bounded->fBounded;
1790 SkTSpanBounded<OppCurve, TCurve>* next = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001791 if (span->removeBounded(spanBounded)) { // shuffles last into position 0
1792 this->removeSpan(span);
1793 }
1794 if (spanBounded->removeBounded(span)) {
1795 opp->removeSpan(spanBounded);
1796 }
1797 SkASSERT(!span->fDeleted || !opp->debugHasBounded(span));
1798 bounded = next;
reed0dc4dd62015-03-24 13:55:33 -07001799 }
1800}
caryclarkccec0f92015-03-24 07:28:17 -07001801
caryclark1049f122015-04-20 08:31:59 -07001802template<typename TCurve, typename OppCurve>
1803SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::spanAtT(double t,
1804 SkTSpan<TCurve, OppCurve>** priorSpan) {
1805 SkTSpan<TCurve, OppCurve>* test = fHead;
halcanary96fcdcc2015-08-27 07:41:13 -07001806 SkTSpan<TCurve, OppCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -07001807 while (test && test->fEndT < t) {
1808 prev = test;
1809 test = test->fNext;
reed0dc4dd62015-03-24 13:55:33 -07001810 }
caryclark54359292015-03-26 07:52:43 -07001811 *priorSpan = prev;
halcanary96fcdcc2015-08-27 07:41:13 -07001812 return test && test->fStartT <= t ? test : nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001813}
1814
caryclark1049f122015-04-20 08:31:59 -07001815template<typename TCurve, typename OppCurve>
1816SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::tail() {
1817 SkTSpan<TCurve, OppCurve>* result = fHead;
1818 SkTSpan<TCurve, OppCurve>* next = fHead;
reed0dc4dd62015-03-24 13:55:33 -07001819 while ((next = next->fNext)) {
1820 if (next->fEndT > result->fEndT) {
1821 result = next;
1822 }
1823 }
1824 return result;
1825}
1826
1827/* Each span has a range of opposite spans it intersects. After the span is split in two,
1828 adjust the range to its new size */
caryclark1049f122015-04-20 08:31:59 -07001829template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -07001830bool SkTSect<TCurve, OppCurve>::trim(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001831 SkTSect<OppCurve, TCurve>* opp) {
caryclarka35ab3e2016-10-20 08:32:18 -07001832 FAIL_IF(!span->initBounds(fCurve));
caryclark1049f122015-04-20 08:31:59 -07001833 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001834 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001835 SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
1836 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001837 int oppSects, sects = this->intersects(span, opp, test, &oppSects);
1838 if (sects >= 1) {
1839 if (oppSects == 2) {
1840 test->initBounds(opp->fCurve);
1841 opp->removeAllBut(span, test, this);
1842 }
1843 if (sects == 2) {
1844 span->initBounds(fCurve);
1845 this->removeAllBut(test, span, opp);
caryclarka35ab3e2016-10-20 08:32:18 -07001846 return true;
caryclark54359292015-03-26 07:52:43 -07001847 }
reed0dc4dd62015-03-24 13:55:33 -07001848 } else {
caryclark54359292015-03-26 07:52:43 -07001849 if (span->removeBounded(test)) {
1850 this->removeSpan(span);
1851 }
1852 if (test->removeBounded(span)) {
1853 opp->removeSpan(test);
1854 }
1855 }
1856 testBounded = next;
1857 }
caryclarka35ab3e2016-10-20 08:32:18 -07001858 return true;
caryclark54359292015-03-26 07:52:43 -07001859}
1860
caryclark1049f122015-04-20 08:31:59 -07001861template<typename TCurve, typename OppCurve>
1862void SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) {
1863 SkTSpan<TCurve, OppCurve>* prev = span->fPrev;
1864 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001865 if (prev) {
1866 prev->fNext = next;
1867 if (next) {
1868 next->fPrev = prev;
caryclark643ede62016-08-08 14:27:45 -07001869 next->validate();
caryclark54359292015-03-26 07:52:43 -07001870 }
1871 } else {
1872 fHead = next;
1873 if (next) {
halcanary96fcdcc2015-08-27 07:41:13 -07001874 next->fPrev = nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001875 }
1876 }
1877}
1878
caryclark1049f122015-04-20 08:31:59 -07001879template<typename TCurve, typename OppCurve>
1880bool SkTSect<TCurve, OppCurve>::updateBounded(SkTSpan<TCurve, OppCurve>* first,
1881 SkTSpan<TCurve, OppCurve>* last, SkTSpan<OppCurve, TCurve>* oppFirst) {
1882 SkTSpan<TCurve, OppCurve>* test = first;
1883 const SkTSpan<TCurve, OppCurve>* final = last->next();
caryclark54359292015-03-26 07:52:43 -07001884 bool deleteSpan = false;
1885 do {
1886 deleteSpan |= test->removeAllBounded();
caryclarke25a4f62016-07-26 09:26:29 -07001887 } while ((test = test->fNext) != final && test);
halcanary96fcdcc2015-08-27 07:41:13 -07001888 first->fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -07001889 first->addBounded(oppFirst, &fHeap);
1890 // cannot call validate until remove span range is called
1891 return deleteSpan;
1892}
1893
1894
caryclark1049f122015-04-20 08:31:59 -07001895template<typename TCurve, typename OppCurve>
1896void SkTSect<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -07001897#if DEBUG_VALIDATE
caryclark45fa4472015-01-16 07:04:10 -08001898 int count = 0;
caryclark643ede62016-08-08 14:27:45 -07001899 double last = 0;
caryclark45fa4472015-01-16 07:04:10 -08001900 if (fHead) {
caryclark1049f122015-04-20 08:31:59 -07001901 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark45fa4472015-01-16 07:04:10 -08001902 SkASSERT(!span->fPrev);
caryclark643ede62016-08-08 14:27:45 -07001903 const SkTSpan<TCurve, OppCurve>* next;
caryclark45fa4472015-01-16 07:04:10 -08001904 do {
1905 span->validate();
1906 SkASSERT(span->fStartT >= last);
caryclark643ede62016-08-08 14:27:45 -07001907 last = span->fEndT;
caryclark45fa4472015-01-16 07:04:10 -08001908 ++count;
caryclark643ede62016-08-08 14:27:45 -07001909 next = span->fNext;
1910 SkASSERT(next != span);
1911 } while ((span = next) != nullptr);
caryclark45fa4472015-01-16 07:04:10 -08001912 }
1913 SkASSERT(count == fActiveCount);
caryclark643ede62016-08-08 14:27:45 -07001914#endif
1915#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -08001916 SkASSERT(fActiveCount <= fDebugAllocatedCount);
1917 int deletedCount = 0;
caryclark1049f122015-04-20 08:31:59 -07001918 const SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001919 while (deleted) {
1920 ++deletedCount;
1921 deleted = deleted->fNext;
1922 }
caryclark1049f122015-04-20 08:31:59 -07001923 const SkTSpan<TCurve, OppCurve>* coincident = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001924 while (coincident) {
1925 ++deletedCount;
1926 coincident = coincident->fNext;
1927 }
caryclark45fa4472015-01-16 07:04:10 -08001928 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount);
caryclarkccec0f92015-03-24 07:28:17 -07001929#endif
caryclark54359292015-03-26 07:52:43 -07001930}
1931
caryclark1049f122015-04-20 08:31:59 -07001932template<typename TCurve, typename OppCurve>
1933void SkTSect<TCurve, OppCurve>::validateBounded() const {
caryclark643ede62016-08-08 14:27:45 -07001934#if DEBUG_VALIDATE
caryclark54359292015-03-26 07:52:43 -07001935 if (!fHead) {
1936 return;
1937 }
caryclark1049f122015-04-20 08:31:59 -07001938 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark54359292015-03-26 07:52:43 -07001939 do {
1940 span->validateBounded();
halcanary96fcdcc2015-08-27 07:41:13 -07001941 } while ((span = span->fNext) != nullptr);
caryclark54359292015-03-26 07:52:43 -07001942#endif
1943}
caryclark45fa4472015-01-16 07:04:10 -08001944
caryclark1049f122015-04-20 08:31:59 -07001945template<typename TCurve, typename OppCurve>
1946int SkTSect<TCurve, OppCurve>::EndsEqual(const SkTSect<TCurve, OppCurve>* sect1,
1947 const SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark45fa4472015-01-16 07:04:10 -08001948 int zeroOneSet = 0;
caryclark54359292015-03-26 07:52:43 -07001949 if (sect1->fCurve[0] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001950 zeroOneSet |= kZeroS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001951 intersections->insert(0, 0, sect1->fCurve[0]);
1952 }
caryclark1049f122015-04-20 08:31:59 -07001953 if (sect1->fCurve[0] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001954 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark54359292015-03-26 07:52:43 -07001955 intersections->insert(0, 1, sect1->fCurve[0]);
1956 }
1957 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001958 zeroOneSet |= kOneS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001959 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
1960 }
caryclark1049f122015-04-20 08:31:59 -07001961 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001962 zeroOneSet |= kOneS1Set | kOneS2Set;
reed0dc4dd62015-03-24 13:55:33 -07001963 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07001964 }
1965 // check for zero
1966 if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set))
1967 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) {
1968 zeroOneSet |= kZeroS1Set | kZeroS2Set;
1969 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
1970 }
1971 if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
caryclark1049f122015-04-20 08:31:59 -07001972 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07001973 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark1049f122015-04-20 08:31:59 -07001974 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[OppCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07001975 }
1976 // check for one
1977 if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
1978 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[0])) {
1979 zeroOneSet |= kOneS1Set | kZeroS2Set;
1980 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], sect2->fCurve[0]);
1981 }
1982 if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
1983 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[
caryclark1049f122015-04-20 08:31:59 -07001984 OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07001985 zeroOneSet |= kOneS1Set | kOneS2Set;
1986 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
caryclark1049f122015-04-20 08:31:59 -07001987 sect2->fCurve[OppCurve::kPointLast]);
caryclark45fa4472015-01-16 07:04:10 -08001988 }
1989 return zeroOneSet;
1990}
1991
caryclark1049f122015-04-20 08:31:59 -07001992template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08001993struct SkClosestRecord {
caryclark54359292015-03-26 07:52:43 -07001994 bool operator<(const SkClosestRecord& rh) const {
1995 return fClosest < rh.fClosest;
1996 }
1997
caryclark45fa4472015-01-16 07:04:10 -08001998 void addIntersection(SkIntersections* intersections) const {
1999 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT();
2000 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT();
2001 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
2002 }
2003
caryclark1049f122015-04-20 08:31:59 -07002004 void findEnd(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2,
caryclark45fa4472015-01-16 07:04:10 -08002005 int c1Index, int c2Index) {
2006 const TCurve& c1 = span1->part();
caryclark1049f122015-04-20 08:31:59 -07002007 const OppCurve& c2 = span2->part();
caryclark45fa4472015-01-16 07:04:10 -08002008 if (!c1[c1Index].approximatelyEqual(c2[c2Index])) {
2009 return;
2010 }
2011 double dist = c1[c1Index].distanceSquared(c2[c2Index]);
2012 if (fClosest < dist) {
2013 return;
2014 }
2015 fC1Span = span1;
2016 fC2Span = span2;
2017 fC1StartT = span1->startT();
2018 fC1EndT = span1->endT();
2019 fC2StartT = span2->startT();
2020 fC2EndT = span2->endT();
2021 fC1Index = c1Index;
2022 fC2Index = c2Index;
2023 fClosest = dist;
2024 }
2025
caryclarkcdeff812016-07-22 03:34:19 -07002026 bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const {
caryclark45fa4472015-01-16 07:04:10 -08002027 SkASSERT(fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT()
2028 || mate.fC1Span->endT() <= fC1Span->startT());
caryclarkcdeff812016-07-22 03:34:19 -07002029 SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002030 || mate.fC2Span->endT() <= fC2Span->startT());
2031 return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT()
2032 || fC1Span->startT() == mate.fC1Span->endT()
2033 || fC2Span == mate.fC2Span
2034 || fC2Span->endT() == mate.fC2Span->startT()
2035 || fC2Span->startT() == mate.fC2Span->endT();
2036 }
2037
2038 void merge(const SkClosestRecord& mate) {
2039 fC1Span = mate.fC1Span;
2040 fC2Span = mate.fC2Span;
2041 fClosest = mate.fClosest;
2042 fC1Index = mate.fC1Index;
2043 fC2Index = mate.fC2Index;
2044 }
caryclark55888e42016-07-18 10:01:36 -07002045
caryclark45fa4472015-01-16 07:04:10 -08002046 void reset() {
2047 fClosest = FLT_MAX;
halcanary96fcdcc2015-08-27 07:41:13 -07002048 SkDEBUGCODE(fC1Span = nullptr);
2049 SkDEBUGCODE(fC2Span = nullptr);
caryclark45fa4472015-01-16 07:04:10 -08002050 SkDEBUGCODE(fC1Index = fC2Index = -1);
2051 }
2052
2053 void update(const SkClosestRecord& mate) {
2054 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT);
2055 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT);
2056 fC2StartT = SkTMin(fC2StartT, mate.fC2StartT);
2057 fC2EndT = SkTMax(fC2EndT, mate.fC2EndT);
2058 }
2059
caryclark1049f122015-04-20 08:31:59 -07002060 const SkTSpan<TCurve, OppCurve>* fC1Span;
2061 const SkTSpan<OppCurve, TCurve>* fC2Span;
caryclark45fa4472015-01-16 07:04:10 -08002062 double fC1StartT;
2063 double fC1EndT;
2064 double fC2StartT;
2065 double fC2EndT;
2066 double fClosest;
2067 int fC1Index;
2068 int fC2Index;
2069};
2070
caryclark1049f122015-04-20 08:31:59 -07002071template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002072struct SkClosestSect {
2073 SkClosestSect()
2074 : fUsed(0) {
2075 fClosest.push_back().reset();
2076 }
2077
caryclarkcdeff812016-07-22 03:34:19 -07002078 bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2
2079 SkDEBUGPARAMS(SkIntersections* i)) {
caryclark1049f122015-04-20 08:31:59 -07002080 SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed];
caryclark45fa4472015-01-16 07:04:10 -08002081 record->findEnd(span1, span2, 0, 0);
caryclark1049f122015-04-20 08:31:59 -07002082 record->findEnd(span1, span2, 0, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002083 record->findEnd(span1, span2, TCurve::kPointLast, 0);
caryclark1049f122015-04-20 08:31:59 -07002084 record->findEnd(span1, span2, TCurve::kPointLast, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002085 if (record->fClosest == FLT_MAX) {
caryclark54359292015-03-26 07:52:43 -07002086 return false;
caryclark45fa4472015-01-16 07:04:10 -08002087 }
2088 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002089 SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index];
caryclarkcdeff812016-07-22 03:34:19 -07002090 if (test->matesWith(*record SkDEBUGPARAMS(i))) {
caryclark45fa4472015-01-16 07:04:10 -08002091 if (test->fClosest > record->fClosest) {
2092 test->merge(*record);
2093 }
2094 test->update(*record);
2095 record->reset();
caryclark54359292015-03-26 07:52:43 -07002096 return false;
caryclark45fa4472015-01-16 07:04:10 -08002097 }
2098 }
2099 ++fUsed;
2100 fClosest.push_back().reset();
caryclark54359292015-03-26 07:52:43 -07002101 return true;
caryclark45fa4472015-01-16 07:04:10 -08002102 }
2103
2104 void finish(SkIntersections* intersections) const {
caryclark1049f122015-04-20 08:31:59 -07002105 SkSTArray<TCurve::kMaxIntersections * 3,
2106 const SkClosestRecord<TCurve, OppCurve>*, true> closestPtrs;
caryclark45fa4472015-01-16 07:04:10 -08002107 for (int index = 0; index < fUsed; ++index) {
caryclark54359292015-03-26 07:52:43 -07002108 closestPtrs.push_back(&fClosest[index]);
2109 }
caryclark1049f122015-04-20 08:31:59 -07002110 SkTQSort<const SkClosestRecord<TCurve, OppCurve> >(closestPtrs.begin(), closestPtrs.end()
2111 - 1);
caryclark54359292015-03-26 07:52:43 -07002112 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002113 const SkClosestRecord<TCurve, OppCurve>* test = closestPtrs[index];
caryclark54359292015-03-26 07:52:43 -07002114 test->addIntersection(intersections);
caryclark45fa4472015-01-16 07:04:10 -08002115 }
2116 }
2117
caryclark54359292015-03-26 07:52:43 -07002118 // this is oversized so that an extra records can merge into final one
caryclark1049f122015-04-20 08:31:59 -07002119 SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve, OppCurve>, true> fClosest;
caryclark45fa4472015-01-16 07:04:10 -08002120 int fUsed;
2121};
2122
2123// returns true if the rect is too small to consider
caryclark1049f122015-04-20 08:31:59 -07002124template<typename TCurve, typename OppCurve>
2125void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
2126 SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark54359292015-03-26 07:52:43 -07002127#if DEBUG_T_SECT_DUMP > 1
2128 gDumpTSectNum = 0;
2129#endif
caryclark1049f122015-04-20 08:31:59 -07002130 SkDEBUGCODE(sect1->fOppSect = sect2);
2131 SkDEBUGCODE(sect2->fOppSect = sect1);
caryclark45fa4472015-01-16 07:04:10 -08002132 intersections->reset();
caryclarka35ab3e2016-10-20 08:32:18 -07002133 intersections->setMax(TCurve::kMaxIntersections + 4); // give extra for slop
caryclark1049f122015-04-20 08:31:59 -07002134 SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
2135 SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002136 int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
2137// SkASSERT(between(0, sect, 2));
2138 if (!sect) {
caryclark45fa4472015-01-16 07:04:10 -08002139 return;
2140 }
caryclark54359292015-03-26 07:52:43 -07002141 if (sect == 2 && oppSect == 2) {
caryclark45fa4472015-01-16 07:04:10 -08002142 (void) EndsEqual(sect1, sect2, intersections);
2143 return;
2144 }
caryclark54359292015-03-26 07:52:43 -07002145 span1->addBounded(span2, &sect1->fHeap);
2146 span2->addBounded(span1, &sect2->fHeap);
caryclark26ad22a2015-10-16 09:03:38 -07002147 const int kMaxCoinLoopCount = 8;
2148 int coinLoopCount = kMaxCoinLoopCount;
2149 double start1s SK_INIT_TO_AVOID_WARNING;
2150 double start1e SK_INIT_TO_AVOID_WARNING;
caryclark45fa4472015-01-16 07:04:10 -08002151 do {
2152 // find the largest bounds
caryclark1049f122015-04-20 08:31:59 -07002153 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002154 if (!largest1) {
2155 break;
2156 }
caryclark1049f122015-04-20 08:31:59 -07002157 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002158 // split it
caryclark1049f122015-04-20 08:31:59 -07002159 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
2160 || (!largest1->fCollapsed && largest2->fCollapsed)))) {
2161 if (largest1->fCollapsed) {
2162 break;
2163 }
caryclark34efb702016-10-24 08:19:06 -07002164 sect1->resetRemovedEnds();
2165 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002166 // trim parts that don't intersect the opposite
2167 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
caryclark643ede62016-08-08 14:27:45 -07002168 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002169 if (!half1->split(largest1, &sect1->fHeap)) {
2170 break;
2171 }
caryclarka35ab3e2016-10-20 08:32:18 -07002172 if (!sect1->trim(largest1, sect2)) {
2173 SkOPOBJASSERT(intersections, 0);
2174 return;
2175 }
2176 if (!sect1->trim(half1, sect2)) {
2177 SkOPOBJASSERT(intersections, 0);
2178 return;
2179 }
caryclark1049f122015-04-20 08:31:59 -07002180 } else {
2181 if (largest2->fCollapsed) {
2182 break;
2183 }
caryclark34efb702016-10-24 08:19:06 -07002184 sect1->resetRemovedEnds();
2185 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002186 // trim parts that don't intersect the opposite
2187 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
caryclark643ede62016-08-08 14:27:45 -07002188 SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002189 if (!half2->split(largest2, &sect2->fHeap)) {
2190 break;
2191 }
caryclarka35ab3e2016-10-20 08:32:18 -07002192 if (!sect2->trim(largest2, sect1)) {
2193 SkOPOBJASSERT(intersections, 0);
2194 return;
2195 }
2196 if (!sect2->trim(half2, sect1)) {
2197 SkOPOBJASSERT(intersections, 0);
2198 return;
2199 }
caryclark45fa4472015-01-16 07:04:10 -08002200 }
caryclark54359292015-03-26 07:52:43 -07002201 sect1->validate();
2202 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002203#if DEBUG_T_SECT_LOOP_COUNT
2204 intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop);
2205#endif
caryclark45fa4472015-01-16 07:04:10 -08002206 // if there are 9 or more continuous spans on both sects, suspect coincidence
2207 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2208 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
caryclark26ad22a2015-10-16 09:03:38 -07002209 if (coinLoopCount == kMaxCoinLoopCount) {
2210 start1s = sect1->fHead->fStartT;
2211 start1e = sect1->tail()->fEndT;
2212 }
caryclarkef7cee42016-09-06 09:05:54 -07002213 if (!sect1->coincidentCheck(sect2)) {
2214 return;
2215 }
caryclark54359292015-03-26 07:52:43 -07002216 sect1->validate();
2217 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002218#if DEBUG_T_SECT_LOOP_COUNT
2219 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop);
2220#endif
caryclarkef784fb2015-10-30 12:03:06 -07002221 if (!--coinLoopCount && sect1->fHead && sect2->fHead) {
caryclark26ad22a2015-10-16 09:03:38 -07002222 /* All known working cases resolve in two tries. Sadly, cubicConicTests[0]
2223 gets stuck in a loop. It adds an extension to allow a coincident end
2224 perpendicular to track its intersection in the opposite curve. However,
2225 the bounding box of the extension does not intersect the original curve,
caryclark55888e42016-07-18 10:01:36 -07002226 so the extension is discarded, only to be added again the next time around. */
caryclark26ad22a2015-10-16 09:03:38 -07002227 sect1->coincidentForce(sect2, start1s, start1e);
2228 sect1->validate();
2229 sect2->validate();
2230 }
caryclark45fa4472015-01-16 07:04:10 -08002231 }
caryclark54359292015-03-26 07:52:43 -07002232 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2233 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
2234 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail());
2235 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail());
2236 sect1->removeByPerpendicular(sect2);
2237 sect1->validate();
2238 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002239#if DEBUG_T_SECT_LOOP_COUNT
2240 intersections->debugBumpLoopCount(SkIntersections::kComputePerp_DebugLoop);
2241#endif
caryclark1049f122015-04-20 08:31:59 -07002242 if (sect1->collapsed() > TCurve::kMaxIntersections) {
2243 break;
2244 }
caryclark54359292015-03-26 07:52:43 -07002245 }
2246#if DEBUG_T_SECT_DUMP
2247 sect1->dumpBoth(sect2);
caryclark45fa4472015-01-16 07:04:10 -08002248#endif
2249 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002250 break;
caryclark45fa4472015-01-16 07:04:10 -08002251 }
2252 } while (true);
caryclark1049f122015-04-20 08:31:59 -07002253 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident;
caryclark54359292015-03-26 07:52:43 -07002254 if (coincident) {
2255 // if there is more than one coincident span, check loosely to see if they should be joined
2256 if (coincident->fNext) {
2257 sect1->mergeCoincidence(sect2);
2258 coincident = sect1->fCoincident;
2259 }
2260 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1
caryclark45fa4472015-01-16 07:04:10 -08002261 do {
caryclark221a4bb2016-10-07 11:15:15 -07002262 if (!coincident) {
2263 return;
2264 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002265 if (!coincident->fCoinStart.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002266 continue;
2267 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002268 if (!coincident->fCoinEnd.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002269 continue;
2270 }
caryclark54359292015-03-26 07:52:43 -07002271 int index = intersections->insertCoincident(coincident->fStartT,
2272 coincident->fCoinStart.perpT(), coincident->fPart[0]);
2273 if ((intersections->insertCoincident(coincident->fEndT,
2274 coincident->fCoinEnd.perpT(),
2275 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) {
caryclark45fa4472015-01-16 07:04:10 -08002276 intersections->clearCoincidence(index);
2277 }
caryclark54359292015-03-26 07:52:43 -07002278 } while ((coincident = coincident->fNext));
2279 }
caryclark1049f122015-04-20 08:31:59 -07002280 int zeroOneSet = EndsEqual(sect1, sect2, intersections);
caryclark34efb702016-10-24 08:19:06 -07002281// if (!sect1->fHead || !sect2->fHead) {
caryclark6c3b9cd2016-09-26 05:36:58 -07002282 // if the final iteration contains an end (0 or 1),
2283 if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) {
2284 SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular with opposite curve
caryclarka35ab3e2016-10-20 08:32:18 -07002285 perp.setPerp(sect1->fCurve, 0, sect1->fCurve[0], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002286 if (perp.isMatch()) {
2287 intersections->insert(0, perp.perpT(), perp.perpPt());
2288 }
2289 }
2290 if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) {
2291 SkTCoincident<TCurve, OppCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002292 perp.setPerp(sect1->fCurve, 1, sect1->fCurve[TCurve::kPointLast], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002293 if (perp.isMatch()) {
2294 intersections->insert(1, perp.perpT(), perp.perpPt());
2295 }
2296 }
2297 if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) {
2298 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002299 perp.setPerp(sect2->fCurve, 0, sect2->fCurve[0], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002300 if (perp.isMatch()) {
2301 intersections->insert(perp.perpT(), 0, perp.perpPt());
2302 }
2303 }
2304 if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) {
2305 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002306 perp.setPerp(sect2->fCurve, 1, sect2->fCurve[OppCurve::kPointLast], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002307 if (perp.isMatch()) {
2308 intersections->insert(perp.perpT(), 1, perp.perpPt());
2309 }
2310 }
caryclark34efb702016-10-24 08:19:06 -07002311// }
2312 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002313 return;
caryclark45fa4472015-01-16 07:04:10 -08002314 }
caryclark45fa4472015-01-16 07:04:10 -08002315 sect1->recoverCollapsed();
2316 sect2->recoverCollapsed();
caryclark1049f122015-04-20 08:31:59 -07002317 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002318 // check heads and tails for zero and ones and insert them if we haven't already done so
caryclark1049f122015-04-20 08:31:59 -07002319 const SkTSpan<TCurve, OppCurve>* head1 = result1;
caryclark45fa4472015-01-16 07:04:10 -08002320 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) {
2321 const SkDPoint& start1 = sect1->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002322 if (head1->isBounded()) {
2323 double t = head1->closestBoundedT(start1);
2324 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) {
2325 intersections->insert(0, t, start1);
2326 }
caryclark45fa4472015-01-16 07:04:10 -08002327 }
2328 }
caryclark1049f122015-04-20 08:31:59 -07002329 const SkTSpan<OppCurve, TCurve>* head2 = sect2->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002330 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) {
2331 const SkDPoint& start2 = sect2->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002332 if (head2->isBounded()) {
2333 double t = head2->closestBoundedT(start2);
2334 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) {
2335 intersections->insert(t, 0, start2);
2336 }
caryclark45fa4472015-01-16 07:04:10 -08002337 }
2338 }
caryclark1049f122015-04-20 08:31:59 -07002339 const SkTSpan<TCurve, OppCurve>* tail1 = sect1->tail();
caryclark45fa4472015-01-16 07:04:10 -08002340 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT)) {
2341 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002342 if (tail1->isBounded()) {
2343 double t = tail1->closestBoundedT(end1);
2344 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) {
2345 intersections->insert(1, t, end1);
2346 }
caryclark45fa4472015-01-16 07:04:10 -08002347 }
2348 }
caryclark1049f122015-04-20 08:31:59 -07002349 const SkTSpan<OppCurve, TCurve>* tail2 = sect2->tail();
caryclark45fa4472015-01-16 07:04:10 -08002350 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT)) {
caryclark1049f122015-04-20 08:31:59 -07002351 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002352 if (tail2->isBounded()) {
2353 double t = tail2->closestBoundedT(end2);
2354 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
2355 intersections->insert(t, 1, end2);
2356 }
caryclark45fa4472015-01-16 07:04:10 -08002357 }
2358 }
caryclark1049f122015-04-20 08:31:59 -07002359 SkClosestSect<TCurve, OppCurve> closest;
caryclark45fa4472015-01-16 07:04:10 -08002360 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07002361 while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) {
caryclark45fa4472015-01-16 07:04:10 -08002362 result1 = result1->fNext;
2363 }
2364 if (!result1) {
2365 break;
2366 }
caryclark1049f122015-04-20 08:31:59 -07002367 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002368 bool found = false;
caryclark45fa4472015-01-16 07:04:10 -08002369 while (result2) {
caryclarkcdeff812016-07-22 03:34:19 -07002370 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections));
caryclark45fa4472015-01-16 07:04:10 -08002371 result2 = result2->fNext;
2372 }
caryclark45fa4472015-01-16 07:04:10 -08002373 } while ((result1 = result1->fNext));
2374 closest.finish(intersections);
caryclark54359292015-03-26 07:52:43 -07002375 // if there is more than one intersection and it isn't already coincident, check
2376 int last = intersections->used() - 1;
2377 for (int index = 0; index < last; ) {
2378 if (intersections->isCoincident(index) && intersections->isCoincident(index + 1)) {
2379 ++index;
2380 continue;
2381 }
2382 double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
2383 SkDPoint midPt = sect1->fCurve.ptAtT(midT);
2384 // intersect perpendicular with opposite curve
caryclark1049f122015-04-20 08:31:59 -07002385 SkTCoincident<TCurve, OppCurve> perp;
caryclark54359292015-03-26 07:52:43 -07002386 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002387 if (!perp.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07002388 ++index;
2389 continue;
2390 }
2391 if (intersections->isCoincident(index)) {
2392 intersections->removeOne(index);
2393 --last;
2394 } else if (intersections->isCoincident(index + 1)) {
2395 intersections->removeOne(index + 1);
2396 --last;
2397 } else {
2398 intersections->setCoincident(index++);
2399 }
2400 intersections->setCoincident(index);
2401 }
caryclarka35ab3e2016-10-20 08:32:18 -07002402 SkOPOBJASSERT(intersections, intersections->used() <= TCurve::kMaxIntersections);
caryclark45fa4472015-01-16 07:04:10 -08002403}
deanm12670eb2016-04-26 14:09:01 -07002404
2405#endif