blob: 51ea44a26c273302a622f3e6398563df50f75ab5 [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);
318 SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
319 SkTSpan<TCurve, OppCurve>* tail();
caryclarka35ab3e2016-10-20 08:32:18 -0700320 bool trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
caryclark1049f122015-04-20 08:31:59 -0700321 void unlinkSpan(SkTSpan<TCurve, OppCurve>* span);
322 bool updateBounded(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
323 SkTSpan<OppCurve, TCurve>* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700324 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700325 void validateBounded() const;
326
caryclark45fa4472015-01-16 07:04:10 -0800327 const TCurve& fCurve;
328 SkChunkAlloc fHeap;
caryclark1049f122015-04-20 08:31:59 -0700329 SkTSpan<TCurve, OppCurve>* fHead;
330 SkTSpan<TCurve, OppCurve>* fCoincident;
331 SkTSpan<TCurve, OppCurve>* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800332 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700333 bool fRemovedStartT;
334 bool fRemovedEndT;
caryclarke25a4f62016-07-26 09:26:29 -0700335 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700336 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700337 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
338 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800339#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800340 int fDebugAllocatedCount;
341#endif
caryclark1049f122015-04-20 08:31:59 -0700342 friend class SkTSpan<TCurve, OppCurve>;
343 friend class SkTSpan<OppCurve, TCurve>;
344 friend class SkTSect<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800345};
346
347#define COINCIDENT_SPAN_COUNT 9
348
caryclark1049f122015-04-20 08:31:59 -0700349template<typename TCurve, typename OppCurve>
350void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t,
351 const SkDPoint& cPt, const OppCurve& c2) {
caryclark45fa4472015-01-16 07:04:10 -0800352 SkDVector dxdy = c1.dxdyAtT(t);
353 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
caryclarka35ab3e2016-10-20 08:32:18 -0700354 SkIntersections i SkDEBUGCODE((c1.globalState()));
caryclark45fa4472015-01-16 07:04:10 -0800355 int used = i.intersectRay(c2, perp);
356 // only keep closest
caryclark54359292015-03-26 07:52:43 -0700357 if (used == 0 || used == 3) {
caryclarkdf386c52015-04-21 05:27:02 -0700358 this->init();
caryclark45fa4472015-01-16 07:04:10 -0800359 return;
caryclark55888e42016-07-18 10:01:36 -0700360 }
caryclark45fa4472015-01-16 07:04:10 -0800361 fPerpT = i[0][0];
362 fPerpPt = i.pt(0);
363 SkASSERT(used <= 2);
364 if (used == 2) {
365 double distSq = (fPerpPt - cPt).lengthSquared();
366 double dist2Sq = (i.pt(1) - cPt).lengthSquared();
367 if (dist2Sq < distSq) {
368 fPerpT = i[0][1];
369 fPerpPt = i.pt(1);
370 }
371 }
caryclark54359292015-03-26 07:52:43 -0700372#if DEBUG_T_SECT
caryclark1049f122015-04-20 08:31:59 -0700373 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n",
374 t, cPt.fX, cPt.fY,
375 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY);
caryclark54359292015-03-26 07:52:43 -0700376#endif
caryclark6c3b9cd2016-09-26 05:36:58 -0700377 fMatch = cPt.approximatelyEqual(fPerpPt);
caryclark45fa4472015-01-16 07:04:10 -0800378#if DEBUG_T_SECT
caryclark6c3b9cd2016-09-26 05:36:58 -0700379 if (fMatch) {
caryclark45fa4472015-01-16 07:04:10 -0800380 SkDebugf(""); // allow setting breakpoint
381 }
382#endif
383}
384
caryclark1049f122015-04-20 08:31:59 -0700385template<typename TCurve, typename OppCurve>
386void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkChunkAlloc* heap) {
halcanary385fe4d2015-08-26 13:07:48 -0700387 SkTSpanBounded<OppCurve, TCurve>* bounded = new (heap->allocThrow(
388 sizeof(SkTSpanBounded<OppCurve, TCurve>)))(SkTSpanBounded<OppCurve, TCurve>);
caryclark54359292015-03-26 07:52:43 -0700389 bounded->fBounded = span;
390 bounded->fNext = fBounded;
391 fBounded = bounded;
392}
393
caryclark1049f122015-04-20 08:31:59 -0700394template<typename TCurve, typename OppCurve>
395SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing(
396 SkTSpan<TCurve, OppCurve>* prior) {
397 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700398 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700399 result->fStartT = prior ? prior->fEndT : 0;
caryclark1049f122015-04-20 08:31:59 -0700400 SkTSpan<TCurve, OppCurve>* next = prior ? prior->fNext : fHead;
caryclark54359292015-03-26 07:52:43 -0700401 result->fEndT = next ? next->fStartT : 1;
402 result->fPrev = prior;
403 result->fNext = next;
404 if (prior) {
405 prior->fNext = result;
406 } else {
407 fHead = result;
408 }
409 if (next) {
410 next->fPrev = result;
411 }
412 result->resetBounds(fCurve);
caryclark643ede62016-08-08 14:27:45 -0700413 result->validate();
caryclark54359292015-03-26 07:52:43 -0700414 return result;
415}
416
caryclark1049f122015-04-20 08:31:59 -0700417template<typename TCurve, typename OppCurve>
418void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, double t) {
caryclark54359292015-03-26 07:52:43 -0700419 if (!span->hasOppT(t)) {
caryclark1049f122015-04-20 08:31:59 -0700420 SkTSpan<TCurve, OppCurve>* priorSpan;
421 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan);
caryclark54359292015-03-26 07:52:43 -0700422 if (!opp) {
423 opp = this->addFollowing(priorSpan);
424#if DEBUG_PERP
caryclark26ad22a2015-10-16 09:03:38 -0700425 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ?
426 priorSpan->debugID() : -1, t, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700427#endif
428 }
429#if DEBUG_PERP
430 opp->dump(); SkDebugf("\n");
caryclark26ad22a2015-10-16 09:03:38 -0700431 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ?
432 priorSpan->debugID() : -1, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700433#endif
434 opp->addBounded(span, &fHeap);
435 span->addBounded(opp, &fHeap);
436 }
437 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700438#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700439 span->validatePerpT(t);
caryclark1049f122015-04-20 08:31:59 -0700440#endif
caryclark54359292015-03-26 07:52:43 -0700441}
442
caryclark1049f122015-04-20 08:31:59 -0700443template<typename TCurve, typename OppCurve>
444double SkTSpan<TCurve, OppCurve>::closestBoundedT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700445 double result = -1;
caryclark343382e2016-06-29 08:18:38 -0700446 double closest = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -0700447 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700448 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700449 const SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700450 double startDist = test->fPart[0].distanceSquared(pt);
451 if (closest > startDist) {
452 closest = startDist;
453 result = test->fStartT;
454 }
caryclark1049f122015-04-20 08:31:59 -0700455 double endDist = test->fPart[OppCurve::kPointLast].distanceSquared(pt);
caryclark54359292015-03-26 07:52:43 -0700456 if (closest > endDist) {
457 closest = endDist;
458 result = test->fEndT;
459 }
460 testBounded = testBounded->fNext;
461 }
462 SkASSERT(between(0, result, 1));
463 return result;
464}
465
466#ifdef SK_DEBUG
caryclark1049f122015-04-20 08:31:59 -0700467template<typename TCurve, typename OppCurve>
468bool SkTSpan<TCurve, OppCurve>::debugIsBefore(const SkTSpan* span) const {
caryclark54359292015-03-26 07:52:43 -0700469 const SkTSpan* work = this;
470 do {
471 if (span == work) {
472 return true;
473 }
474 } while ((work = work->fNext));
475 return false;
476}
477#endif
478
caryclark1049f122015-04-20 08:31:59 -0700479template<typename TCurve, typename OppCurve>
480bool SkTSpan<TCurve, OppCurve>::contains(double t) const {
caryclark54359292015-03-26 07:52:43 -0700481 const SkTSpan* work = this;
482 do {
483 if (between(work->fStartT, t, work->fEndT)) {
484 return true;
485 }
486 } while ((work = work->fNext));
487 return false;
488}
489
caryclark1049f122015-04-20 08:31:59 -0700490template<typename TCurve, typename OppCurve>
491const SkTSect<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700492 return SkDEBUGRELEASE(fDebugSect->debugOpp(), nullptr);
caryclark54359292015-03-26 07:52:43 -0700493}
494
caryclark1049f122015-04-20 08:31:59 -0700495template<typename TCurve, typename OppCurve>
496SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::findOppSpan(
497 const SkTSpan<OppCurve, TCurve>* opp) const {
498 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700499 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700500 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700501 if (opp == test) {
502 return test;
503 }
504 bounded = bounded->fNext;
505 }
halcanary96fcdcc2015-08-27 07:41:13 -0700506 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700507}
508
509// returns 0 if no hull intersection
510// 1 if hulls intersect
511// 2 if hulls only share a common endpoint
512// -1 if linear and further checking is required
caryclark1049f122015-04-20 08:31:59 -0700513template<typename TCurve, typename OppCurve>
514int SkTSpan<TCurve, OppCurve>::hullCheck(const SkTSpan<OppCurve, TCurve>* opp,
515 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700516 if (fIsLinear) {
517 return -1;
518 }
519 bool ptsInCommon;
520 if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) {
521 SkASSERT(ptsInCommon);
522 return 2;
523 }
524 bool linear;
525 if (fPart.hullIntersects(opp->fPart, &linear)) {
526 if (!linear) { // check set true if linear
527 return 1;
528 }
529 fIsLinear = true;
530 fIsLine = fPart.controlsInside();
caryclark2bec26a2016-05-26 09:01:47 -0700531 return ptsInCommon ? 1 : -1;
caryclark54359292015-03-26 07:52:43 -0700532 } else { // hull is not linear; check set true if intersected at the end points
533 return ((int) ptsInCommon) << 1; // 0 or 2
534 }
535 return 0;
536}
537
538// OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
539// use line intersection to guess a better split than 0.5
540// OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear
caryclark1049f122015-04-20 08:31:59 -0700541template<typename TCurve, typename OppCurve>
542int SkTSpan<TCurve, OppCurve>::hullsIntersect(SkTSpan<OppCurve, TCurve>* opp,
543 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700544 if (!fBounds.intersects(opp->fBounds)) {
545 return 0;
546 }
547 int hullSect = this->hullCheck(opp, start, oppStart);
548 if (hullSect >= 0) {
549 return hullSect;
550 }
551 hullSect = opp->hullCheck(this, oppStart, start);
552 if (hullSect >= 0) {
553 return hullSect;
554 }
555 return -1;
556}
557
caryclark1049f122015-04-20 08:31:59 -0700558template<typename TCurve, typename OppCurve>
559void SkTSpan<TCurve, OppCurve>::init(const TCurve& c) {
halcanary96fcdcc2015-08-27 07:41:13 -0700560 fPrev = fNext = nullptr;
reed0dc4dd62015-03-24 13:55:33 -0700561 fStartT = 0;
562 fEndT = 1;
halcanary96fcdcc2015-08-27 07:41:13 -0700563 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700564 resetBounds(c);
caryclark45fa4472015-01-16 07:04:10 -0800565}
566
caryclark1049f122015-04-20 08:31:59 -0700567template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -0700568bool SkTSpan<TCurve, OppCurve>::initBounds(const TCurve& c) {
reed0dc4dd62015-03-24 13:55:33 -0700569 fPart = c.subDivide(fStartT, fEndT);
570 fBounds.setBounds(fPart);
571 fCoinStart.init();
572 fCoinEnd.init();
573 fBoundsMax = SkTMax(fBounds.width(), fBounds.height());
574 fCollapsed = fPart.collapsed();
575 fHasPerp = false;
caryclark54359292015-03-26 07:52:43 -0700576 fDeleted = false;
reed0dc4dd62015-03-24 13:55:33 -0700577#if DEBUG_T_SECT
reed0dc4dd62015-03-24 13:55:33 -0700578 if (fCollapsed) {
579 SkDebugf(""); // for convenient breakpoints
caryclark45fa4472015-01-16 07:04:10 -0800580 }
581#endif
caryclarka35ab3e2016-10-20 08:32:18 -0700582 return fBounds.valid();
caryclark45fa4472015-01-16 07:04:10 -0800583}
584
caryclark1049f122015-04-20 08:31:59 -0700585template<typename TCurve, typename OppCurve>
586bool SkTSpan<TCurve, OppCurve>::linearsIntersect(SkTSpan<OppCurve, TCurve>* span) {
caryclark54359292015-03-26 07:52:43 -0700587 int result = this->linearIntersects(span->fPart);
588 if (result <= 1) {
589 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800590 }
caryclark54359292015-03-26 07:52:43 -0700591 SkASSERT(span->fIsLinear);
592 result = span->linearIntersects(this->fPart);
593// SkASSERT(result <= 1);
594 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800595}
596
caryclark1049f122015-04-20 08:31:59 -0700597template<typename TCurve, typename OppCurve>
598double SkTSpan<TCurve, OppCurve>::linearT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700599 SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
600 return fabs(len.fX) > fabs(len.fY)
601 ? (pt.fX - fPart[0].fX) / len.fX
602 : (pt.fY - fPart[0].fY) / len.fY;
caryclark45fa4472015-01-16 07:04:10 -0800603}
604
caryclark1049f122015-04-20 08:31:59 -0700605template<typename TCurve, typename OppCurve>
606int SkTSpan<TCurve, OppCurve>::linearIntersects(const OppCurve& q2) const {
caryclark45fa4472015-01-16 07:04:10 -0800607 // looks like q1 is near-linear
caryclark54359292015-03-26 07:52:43 -0700608 int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
caryclark45fa4472015-01-16 07:04:10 -0800609 if (!fPart.controlsInside()) {
610 double dist = 0; // if there's any question, compute distance to find best outsiders
611 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) {
612 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) {
613 double test = (fPart[outer] - fPart[inner]).lengthSquared();
614 if (dist > test) {
615 continue;
616 }
617 dist = test;
618 start = outer;
619 end = inner;
620 }
621 }
622 }
623 // see if q2 is on one side of the line formed by the extreme points
624 double origX = fPart[start].fX;
625 double origY = fPart[start].fY;
626 double adj = fPart[end].fX - origX;
627 double opp = fPart[end].fY - origY;
caryclark54359292015-03-26 07:52:43 -0700628 double maxPart = SkTMax(fabs(adj), fabs(opp));
629 double sign = 0; // initialization to shut up warning in release build
caryclark1049f122015-04-20 08:31:59 -0700630 for (int n = 0; n < OppCurve::kPointCount; ++n) {
caryclark54359292015-03-26 07:52:43 -0700631 double dx = q2[n].fY - origY;
632 double dy = q2[n].fX - origX;
633 double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
caryclark45fa4472015-01-16 07:04:10 -0800634 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp;
caryclark54359292015-03-26 07:52:43 -0700635 if (precisely_zero_when_compared_to(test, maxVal)) {
636 return 1;
637 }
638 if (approximately_zero_when_compared_to(test, maxVal)) {
639 return 3;
caryclark45fa4472015-01-16 07:04:10 -0800640 }
641 if (n == 0) {
642 sign = test;
643 continue;
644 }
645 if (test * sign < 0) {
caryclark54359292015-03-26 07:52:43 -0700646 return 1;
caryclark45fa4472015-01-16 07:04:10 -0800647 }
648 }
caryclark54359292015-03-26 07:52:43 -0700649 return 0;
650}
651
caryclark1049f122015-04-20 08:31:59 -0700652template<typename TCurve, typename OppCurve>
653bool SkTSpan<TCurve, OppCurve>::onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp,
654 bool* start, bool* oppStart, bool* ptsInCommon) {
caryclark54359292015-03-26 07:52:43 -0700655 if (opp->fPart[0] == fPart[0]) {
656 *start = *oppStart = true;
657 } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
658 *start = false;
659 *oppStart = true;
caryclark1049f122015-04-20 08:31:59 -0700660 } else if (opp->fPart[OppCurve::kPointLast] == fPart[0]) {
caryclark54359292015-03-26 07:52:43 -0700661 *start = true;
662 *oppStart = false;
caryclark1049f122015-04-20 08:31:59 -0700663 } else if (opp->fPart[OppCurve::kPointLast] == fPart[TCurve::kPointLast]) {
caryclark54359292015-03-26 07:52:43 -0700664 *start = *oppStart = false;
665 } else {
666 *ptsInCommon = false;
667 return false;
668 }
669 *ptsInCommon = true;
caryclark1049f122015-04-20 08:31:59 -0700670 const SkDPoint* otherPts[TCurve::kPointCount - 1], * oppOtherPts[OppCurve::kPointCount - 1];
caryclark54359292015-03-26 07:52:43 -0700671 int baseIndex = *start ? 0 : TCurve::kPointLast;
caryclark1049f122015-04-20 08:31:59 -0700672 fPart.otherPts(baseIndex, otherPts);
673 opp->fPart.otherPts(*oppStart ? 0 : OppCurve::kPointLast, oppOtherPts);
caryclark54359292015-03-26 07:52:43 -0700674 const SkDPoint& base = fPart[baseIndex];
caryclark1049f122015-04-20 08:31:59 -0700675 for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(otherPts); ++o1) {
676 SkDVector v1 = *otherPts[o1] - base;
677 for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(oppOtherPts); ++o2) {
678 SkDVector v2 = *oppOtherPts[o2] - base;
caryclark54359292015-03-26 07:52:43 -0700679 if (v2.dot(v1) >= 0) {
680 return false;
681 }
682 }
683 }
684 return true;
685}
686
caryclark1049f122015-04-20 08:31:59 -0700687template<typename TCurve, typename OppCurve>
688SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::oppT(double t) const {
689 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700690 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700691 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700692 if (between(test->fStartT, t, test->fEndT)) {
693 return test;
694 }
695 bounded = bounded->fNext;
696 }
halcanary96fcdcc2015-08-27 07:41:13 -0700697 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700698}
699
caryclark1049f122015-04-20 08:31:59 -0700700template<typename TCurve, typename OppCurve>
701bool SkTSpan<TCurve, OppCurve>::removeAllBounded() {
caryclark54359292015-03-26 07:52:43 -0700702 bool deleteSpan = false;
caryclark1049f122015-04-20 08:31:59 -0700703 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700704 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700705 SkTSpan<OppCurve, TCurve>* opp = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700706 deleteSpan |= opp->removeBounded(this);
707 bounded = bounded->fNext;
708 }
709 return deleteSpan;
710}
711
caryclark1049f122015-04-20 08:31:59 -0700712template<typename TCurve, typename OppCurve>
713bool SkTSpan<TCurve, OppCurve>::removeBounded(const SkTSpan<OppCurve, TCurve>* opp) {
caryclark54359292015-03-26 07:52:43 -0700714 if (fHasPerp) {
715 bool foundStart = false;
716 bool foundEnd = false;
caryclark1049f122015-04-20 08:31:59 -0700717 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700718 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700719 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700720 if (opp != test) {
721 foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT);
722 foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
723 }
724 bounded = bounded->fNext;
725 }
726 if (!foundStart || !foundEnd) {
727 fHasPerp = false;
728 fCoinStart.init();
729 fCoinEnd.init();
730 }
731 }
caryclark1049f122015-04-20 08:31:59 -0700732 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700733 SkTSpanBounded<OppCurve, TCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -0700734 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700735 SkTSpanBounded<OppCurve, TCurve>* boundedNext = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -0700736 if (opp == bounded->fBounded) {
737 if (prev) {
738 prev->fNext = boundedNext;
739 return false;
740 } else {
741 fBounded = boundedNext;
halcanary96fcdcc2015-08-27 07:41:13 -0700742 return fBounded == nullptr;
caryclark54359292015-03-26 07:52:43 -0700743 }
744 }
745 prev = bounded;
746 bounded = boundedNext;
747 }
caryclark643ede62016-08-08 14:27:45 -0700748 SkOPASSERT(0);
caryclark45fa4472015-01-16 07:04:10 -0800749 return false;
750}
751
caryclark1049f122015-04-20 08:31:59 -0700752template<typename TCurve, typename OppCurve>
753bool SkTSpan<TCurve, OppCurve>::splitAt(SkTSpan* work, double t, SkChunkAlloc* heap) {
caryclark45fa4472015-01-16 07:04:10 -0800754 fStartT = t;
755 fEndT = work->fEndT;
756 if (fStartT == fEndT) {
757 fCollapsed = true;
758 return false;
759 }
760 work->fEndT = t;
761 if (work->fStartT == work->fEndT) {
762 work->fCollapsed = true;
763 return false;
764 }
765 fPrev = work;
766 fNext = work->fNext;
767 fIsLinear = work->fIsLinear;
caryclark54359292015-03-26 07:52:43 -0700768 fIsLine = work->fIsLine;
769
caryclark45fa4472015-01-16 07:04:10 -0800770 work->fNext = this;
771 if (fNext) {
772 fNext->fPrev = this;
773 }
caryclark643ede62016-08-08 14:27:45 -0700774 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700775 SkTSpanBounded<OppCurve, TCurve>* bounded = work->fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700776 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700777 while (bounded) {
778 this->addBounded(bounded->fBounded, heap);
779 bounded = bounded->fNext;
780 }
781 bounded = fBounded;
782 while (bounded) {
783 bounded->fBounded->addBounded(this, heap);
784 bounded = bounded->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800785 }
786 return true;
787}
788
caryclark1049f122015-04-20 08:31:59 -0700789template<typename TCurve, typename OppCurve>
790void SkTSpan<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -0700791#if DEBUG_VALIDATE
792 SkASSERT(this != fPrev);
793 SkASSERT(this != fNext);
halcanary96fcdcc2015-08-27 07:41:13 -0700794 SkASSERT(fNext == nullptr || fNext != fPrev);
795 SkASSERT(fNext == nullptr || this == fNext->fPrev);
796 SkASSERT(fPrev == nullptr || this == fPrev->fNext);
caryclark643ede62016-08-08 14:27:45 -0700797 this->validateBounded();
798#endif
799#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700800 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed);
caryclarke839e782016-09-15 07:48:18 -0700801 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollapsed == 0xFF);
caryclark45fa4472015-01-16 07:04:10 -0800802 SkASSERT(0 <= fStartT);
803 SkASSERT(fEndT <= 1);
caryclark54359292015-03-26 07:52:43 -0700804 SkASSERT(fStartT <= fEndT);
caryclarke839e782016-09-15 07:48:18 -0700805 SkASSERT(fBounded || fCollapsed == 0xFF);
caryclark54359292015-03-26 07:52:43 -0700806 if (fHasPerp) {
caryclark6c3b9cd2016-09-26 05:36:58 -0700807 if (fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700808 validatePerpT(fCoinStart.perpT());
809 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt());
810 }
caryclark6c3b9cd2016-09-26 05:36:58 -0700811 if (fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700812 validatePerpT(fCoinEnd.perpT());
813 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt());
814 }
caryclarkccec0f92015-03-24 07:28:17 -0700815 }
reed0dc4dd62015-03-24 13:55:33 -0700816#endif
caryclark54359292015-03-26 07:52:43 -0700817}
caryclarkccec0f92015-03-24 07:28:17 -0700818
caryclark1049f122015-04-20 08:31:59 -0700819template<typename TCurve, typename OppCurve>
820void SkTSpan<TCurve, OppCurve>::validateBounded() const {
caryclark54359292015-03-26 07:52:43 -0700821#if DEBUG_VALIDATE
caryclark1049f122015-04-20 08:31:59 -0700822 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700823 while (testBounded) {
csmartdaltonceeaa782016-08-10 10:07:57 -0700824 SkDEBUGCODE(const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded);
caryclark54359292015-03-26 07:52:43 -0700825 SkASSERT(!overlap->fDeleted);
caryclark643ede62016-08-08 14:27:45 -0700826#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700827 SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
828 SkASSERT(overlap->findOppSpan(this));
caryclark643ede62016-08-08 14:27:45 -0700829#endif
caryclark54359292015-03-26 07:52:43 -0700830 testBounded = testBounded->fNext;
831 }
832#endif
833}
834
caryclark1049f122015-04-20 08:31:59 -0700835template<typename TCurve, typename OppCurve>
836void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const {
837 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700838 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700839 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded;
caryclark26ad22a2015-10-16 09:03:38 -0700840 if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) {
caryclark54359292015-03-26 07:52:43 -0700841 return;
842 }
843 testBounded = testBounded->fNext;
844 }
845 SkASSERT(0);
caryclark54359292015-03-26 07:52:43 -0700846}
847
caryclark1049f122015-04-20 08:31:59 -0700848template<typename TCurve, typename OppCurve>
849void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
850 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt);
caryclark54359292015-03-26 07:52:43 -0700851}
852
853
caryclark1049f122015-04-20 08:31:59 -0700854template<typename TCurve, typename OppCurve>
caryclarke25a4f62016-07-26 09:26:29 -0700855SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
856 SkDEBUGPARAMS(SkOpGlobalState* debugGlobalState)
857 PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
caryclark45fa4472015-01-16 07:04:10 -0800858 : fCurve(c)
caryclark1049f122015-04-20 08:31:59 -0700859 , fHeap(sizeof(SkTSpan<TCurve, OppCurve>) * 4)
halcanary96fcdcc2015-08-27 07:41:13 -0700860 , fCoincident(nullptr)
861 , fDeleted(nullptr)
caryclark45fa4472015-01-16 07:04:10 -0800862 , fActiveCount(0)
caryclarke25a4f62016-07-26 09:26:29 -0700863 SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState))
caryclark54359292015-03-26 07:52:43 -0700864 PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
865 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
866 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
caryclark45fa4472015-01-16 07:04:10 -0800867{
868 fHead = addOne();
caryclark643ede62016-08-08 14:27:45 -0700869 SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState));
caryclark45fa4472015-01-16 07:04:10 -0800870 fHead->init(c);
871}
872
caryclark1049f122015-04-20 08:31:59 -0700873template<typename TCurve, typename OppCurve>
874SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
875 SkTSpan<TCurve, OppCurve>* result;
caryclark45fa4472015-01-16 07:04:10 -0800876 if (fDeleted) {
877 result = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800878 fDeleted = result->fNext;
879 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700880 result = new (fHeap.allocThrow(sizeof(SkTSpan<TCurve, OppCurve>)))(
881 SkTSpan<TCurve, OppCurve>);
caryclark45fa4472015-01-16 07:04:10 -0800882#if DEBUG_T_SECT
883 ++fDebugAllocatedCount;
884#endif
885 }
caryclarked0935a2015-10-22 07:23:52 -0700886 result->reset();
caryclark08b32492015-04-06 11:41:29 -0700887 result->fHasPerp = false;
888 result->fDeleted = false;
caryclark55888e42016-07-18 10:01:36 -0700889 ++fActiveCount;
caryclark54359292015-03-26 07:52:43 -0700890 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
caryclark1049f122015-04-20 08:31:59 -0700891 SkDEBUGCODE(result->fDebugSect = this);
caryclarked0935a2015-10-22 07:23:52 -0700892#ifdef SK_DEBUG
893 result->fPart.debugInit();
894 result->fCoinStart.debugInit();
895 result->fCoinEnd.debugInit();
896 result->fPrev = result->fNext = nullptr;
897 result->fBounds.debugInit();
898 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN;
899 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF;
900#endif
caryclark45fa4472015-01-16 07:04:10 -0800901 return result;
902}
903
caryclark1049f122015-04-20 08:31:59 -0700904template<typename TCurve, typename OppCurve>
905bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
906 double tStep, double* resultT, double* oppT) {
907 SkTSpan<TCurve, OppCurve> work;
caryclark45fa4472015-01-16 07:04:10 -0800908 double result = work.fStartT = work.fEndT = tStart;
caryclark1049f122015-04-20 08:31:59 -0700909 SkDEBUGCODE(work.fDebugSect = this);
caryclark45fa4472015-01-16 07:04:10 -0800910 SkDPoint last = fCurve.ptAtT(tStart);
911 SkDPoint oppPt;
912 bool flip = false;
caryclarkcdeff812016-07-22 03:34:19 -0700913 bool contained = false;
caryclark45fa4472015-01-16 07:04:10 -0800914 SkDEBUGCODE(bool down = tStep < 0);
caryclark1049f122015-04-20 08:31:59 -0700915 const OppCurve& opp = sect2->fCurve;
caryclark45fa4472015-01-16 07:04:10 -0800916 do {
917 tStep *= 0.5;
918 work.fStartT += tStep;
919 if (flip) {
920 tStep = -tStep;
921 flip = false;
922 }
923 work.initBounds(fCurve);
924 if (work.fCollapsed) {
925 return false;
926 }
927 if (last.approximatelyEqual(work.fPart[0])) {
928 break;
929 }
930 last = work.fPart[0];
931 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp);
caryclark6c3b9cd2016-09-26 05:36:58 -0700932 if (work.fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700933#if DEBUG_T_SECT
934 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt());
935#endif
caryclark45fa4472015-01-16 07:04:10 -0800936 double oppTTest = work.fCoinStart.perpT();
caryclark54359292015-03-26 07:52:43 -0700937 if (sect2->fHead->contains(oppTTest)) {
caryclark45fa4472015-01-16 07:04:10 -0800938 *oppT = oppTTest;
939 oppPt = work.fCoinStart.perpPt();
caryclarkcdeff812016-07-22 03:34:19 -0700940 contained = true;
caryclark45fa4472015-01-16 07:04:10 -0800941 SkASSERT(down ? result > work.fStartT : result < work.fStartT);
942 result = work.fStartT;
943 continue;
944 }
945 }
946 tStep = -tStep;
947 flip = true;
948 } while (true);
caryclarkcdeff812016-07-22 03:34:19 -0700949 if (!contained) {
950 return false;
951 }
caryclark45fa4472015-01-16 07:04:10 -0800952 if (last.approximatelyEqual(fCurve[0])) {
953 result = 0;
954 } else if (last.approximatelyEqual(fCurve[TCurve::kPointLast])) {
955 result = 1;
956 }
957 if (oppPt.approximatelyEqual(opp[0])) {
958 *oppT = 0;
caryclark1049f122015-04-20 08:31:59 -0700959 } else if (oppPt.approximatelyEqual(opp[OppCurve::kPointLast])) {
caryclark45fa4472015-01-16 07:04:10 -0800960 *oppT = 1;
961 }
962 *resultT = result;
963 return true;
964}
965
966// OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
967// so that each quad sect has a pointer to the largest, and can update it as spans
968// are split
caryclark1049f122015-04-20 08:31:59 -0700969template<typename TCurve, typename OppCurve>
970SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
971 SkTSpan<TCurve, OppCurve>* test = fHead;
972 SkTSpan<TCurve, OppCurve>* largest = fHead;
caryclark54359292015-03-26 07:52:43 -0700973 bool lCollapsed = largest->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800974 while ((test = test->fNext)) {
caryclark54359292015-03-26 07:52:43 -0700975 bool tCollapsed = test->fCollapsed;
976 if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
977 largest->fBoundsMax < test->fBoundsMax)) {
caryclark45fa4472015-01-16 07:04:10 -0800978 largest = test;
caryclark1049f122015-04-20 08:31:59 -0700979 lCollapsed = test->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800980 }
981 }
caryclark54359292015-03-26 07:52:43 -0700982 return largest;
caryclark45fa4472015-01-16 07:04:10 -0800983}
984
caryclark1049f122015-04-20 08:31:59 -0700985template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -0700986bool SkTSect<TCurve, OppCurve>::coincidentCheck(SkTSect<OppCurve, TCurve>* sect2) {
caryclark1049f122015-04-20 08:31:59 -0700987 SkTSpan<TCurve, OppCurve>* first = fHead;
988 SkTSpan<TCurve, OppCurve>* last, * next;
caryclark45fa4472015-01-16 07:04:10 -0800989 do {
caryclark54359292015-03-26 07:52:43 -0700990 int consecutive = this->countConsecutiveSpans(first, &last);
991 next = last->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800992 if (consecutive < COINCIDENT_SPAN_COUNT) {
993 continue;
994 }
caryclark54359292015-03-26 07:52:43 -0700995 this->validate();
996 sect2->validate();
997 this->computePerpendiculars(sect2, first, last);
998 this->validate();
999 sect2->validate();
caryclark45fa4472015-01-16 07:04:10 -08001000 // check to see if a range of points are on the curve
caryclark1049f122015-04-20 08:31:59 -07001001 SkTSpan<TCurve, OppCurve>* coinStart = first;
caryclark54359292015-03-26 07:52:43 -07001002 do {
caryclarkef7cee42016-09-06 09:05:54 -07001003 bool success = this->extractCoincident(sect2, coinStart, last, &coinStart);
1004 if (!success) {
1005 return false;
1006 }
caryclark54359292015-03-26 07:52:43 -07001007 } while (coinStart && !last->fDeleted);
caryclark55888e42016-07-18 10:01:36 -07001008 if (!fHead || !sect2->fHead) {
1009 break;
1010 }
caryclark643ede62016-08-08 14:27:45 -07001011 if (!next || next->fDeleted) {
1012 break;
1013 }
caryclark45fa4472015-01-16 07:04:10 -08001014 } while ((first = next));
caryclarkef7cee42016-09-06 09:05:54 -07001015 return true;
caryclark45fa4472015-01-16 07:04:10 -08001016}
1017
caryclark1049f122015-04-20 08:31:59 -07001018template<typename TCurve, typename OppCurve>
caryclark26ad22a2015-10-16 09:03:38 -07001019void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2,
1020 double start1s, double start1e) {
1021 SkTSpan<TCurve, OppCurve>* first = fHead;
1022 SkTSpan<TCurve, OppCurve>* last = this->tail();
1023 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead;
1024 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail();
1025 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1026 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
1027 this->removeSpanRange(first, last);
1028 sect2->removeSpanRange(oppFirst, oppLast);
1029 first->fStartT = start1s;
1030 first->fEndT = start1e;
1031 first->resetBounds(fCurve);
1032 first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve);
1033 first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->fCurve);
1034 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
caryclarkef784fb2015-10-30 12:03:06 -07001035 double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : SkTMax(0., first->fCoinStart.perpT());
1036 double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : SkTMin(1., first->fCoinEnd.perpT());
caryclark26ad22a2015-10-16 09:03:38 -07001037 if (!oppMatched) {
1038 SkTSwap(oppStartT, oppEndT);
1039 }
1040 oppFirst->fStartT = oppStartT;
1041 oppFirst->fEndT = oppEndT;
1042 oppFirst->resetBounds(sect2->fCurve);
1043 this->removeCoincident(first, false);
1044 sect2->removeCoincident(oppFirst, true);
1045 if (deleteEmptySpans) {
1046 this->deleteEmptySpans();
1047 sect2->deleteEmptySpans();
1048 }
1049}
1050
1051template<typename TCurve, typename OppCurve>
caryclark1049f122015-04-20 08:31:59 -07001052bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) {
1053 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001054 while (test) {
1055 if (between(test->fStartT, t, test->fEndT)) {
1056 return true;
1057 }
1058 test = test->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001059 }
caryclark54359292015-03-26 07:52:43 -07001060 return false;
caryclark45fa4472015-01-16 07:04:10 -08001061}
1062
caryclark1049f122015-04-20 08:31:59 -07001063template<typename TCurve, typename OppCurve>
1064int SkTSect<TCurve, OppCurve>::collapsed() const {
1065 int result = 0;
1066 const SkTSpan<TCurve, OppCurve>* test = fHead;
1067 while (test) {
1068 if (test->fCollapsed) {
1069 ++result;
1070 }
1071 test = test->next();
1072 }
1073 return result;
1074}
1075
1076template<typename TCurve, typename OppCurve>
1077void SkTSect<TCurve, OppCurve>::computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2,
1078 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
1079 const OppCurve& opp = sect2->fCurve;
1080 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001081 SkTSpan<TCurve, OppCurve>* prior = nullptr;
caryclark45fa4472015-01-16 07:04:10 -08001082 do {
caryclark54359292015-03-26 07:52:43 -07001083 if (!work->fHasPerp && !work->fCollapsed) {
1084 if (prior) {
1085 work->fCoinStart = prior->fCoinEnd;
1086 } else {
1087 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp);
caryclark45fa4472015-01-16 07:04:10 -08001088 }
caryclark6c3b9cd2016-09-26 05:36:58 -07001089 if (work->fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001090 double perpT = work->fCoinStart.perpT();
1091 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001092 work->fCoinStart.init();
caryclark54359292015-03-26 07:52:43 -07001093 } else {
1094 sect2->addForPerp(work, perpT);
1095 }
1096 }
1097 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPointLast], opp);
caryclark6c3b9cd2016-09-26 05:36:58 -07001098 if (work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001099 double perpT = work->fCoinEnd.perpT();
1100 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001101 work->fCoinEnd.init();
caryclark54359292015-03-26 07:52:43 -07001102 } else {
1103 sect2->addForPerp(work, perpT);
1104 }
1105 }
1106 work->fHasPerp = true;
caryclark45fa4472015-01-16 07:04:10 -08001107 }
1108 if (work == last) {
1109 break;
1110 }
caryclark54359292015-03-26 07:52:43 -07001111 prior = work;
caryclark45fa4472015-01-16 07:04:10 -08001112 work = work->fNext;
1113 SkASSERT(work);
1114 } while (true);
caryclark54359292015-03-26 07:52:43 -07001115}
1116
caryclark1049f122015-04-20 08:31:59 -07001117template<typename TCurve, typename OppCurve>
1118int SkTSect<TCurve, OppCurve>::countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
1119 SkTSpan<TCurve, OppCurve>** lastPtr) const {
caryclark54359292015-03-26 07:52:43 -07001120 int consecutive = 1;
caryclark1049f122015-04-20 08:31:59 -07001121 SkTSpan<TCurve, OppCurve>* last = first;
caryclark54359292015-03-26 07:52:43 -07001122 do {
caryclark1049f122015-04-20 08:31:59 -07001123 SkTSpan<TCurve, OppCurve>* next = last->fNext;
caryclark54359292015-03-26 07:52:43 -07001124 if (!next) {
1125 break;
1126 }
1127 if (next->fStartT > last->fEndT) {
1128 break;
1129 }
1130 ++consecutive;
1131 last = next;
1132 } while (true);
1133 *lastPtr = last;
1134 return consecutive;
1135}
1136
caryclark1049f122015-04-20 08:31:59 -07001137template<typename TCurve, typename OppCurve>
1138bool SkTSect<TCurve, OppCurve>::debugHasBounded(const SkTSpan<OppCurve, TCurve>* span) const {
1139 const SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001140 if (!test) {
1141 return false;
1142 }
1143 do {
1144 if (test->findOppSpan(span)) {
1145 return true;
1146 }
1147 } while ((test = test->next()));
1148 return false;
1149}
1150
caryclark1049f122015-04-20 08:31:59 -07001151template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001152bool SkTSect<TCurve, OppCurve>::deleteEmptySpans() {
caryclark1049f122015-04-20 08:31:59 -07001153 SkTSpan<TCurve, OppCurve>* test;
1154 SkTSpan<TCurve, OppCurve>* next = fHead;
caryclark54359292015-03-26 07:52:43 -07001155 while ((test = next)) {
1156 next = test->fNext;
1157 if (!test->fBounded) {
caryclarkef7cee42016-09-06 09:05:54 -07001158 if (!this->removeSpan(test)) {
1159 return false;
1160 }
caryclark54359292015-03-26 07:52:43 -07001161 }
1162 }
caryclarkef7cee42016-09-06 09:05:54 -07001163 return true;
caryclark54359292015-03-26 07:52:43 -07001164}
1165
caryclark1049f122015-04-20 08:31:59 -07001166template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001167bool SkTSect<TCurve, OppCurve>::extractCoincident(
caryclark1049f122015-04-20 08:31:59 -07001168 SkTSect<OppCurve, TCurve>* sect2,
caryclarkef7cee42016-09-06 09:05:54 -07001169 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
1170 SkTSpan<TCurve, OppCurve>** result) {
caryclark1049f122015-04-20 08:31:59 -07001171 first = findCoincidentRun(first, &last);
caryclarka1b42d92016-08-16 10:25:29 -07001172 if (!first || !last) {
caryclarkef7cee42016-09-06 09:05:54 -07001173 *result = nullptr;
1174 return true;
caryclark45fa4472015-01-16 07:04:10 -08001175 }
1176 // march outwards to find limit of coincidence from here to previous and next spans
1177 double startT = first->fStartT;
caryclarkd8bc16b2015-03-26 09:05:12 -07001178 double oppStartT SK_INIT_TO_AVOID_WARNING;
caryclark54359292015-03-26 07:52:43 -07001179 double oppEndT SK_INIT_TO_AVOID_WARNING;
caryclark1049f122015-04-20 08:31:59 -07001180 SkTSpan<TCurve, OppCurve>* prev = first->fPrev;
caryclark6c3b9cd2016-09-26 05:36:58 -07001181 SkASSERT(first->fCoinStart.isMatch());
caryclark1049f122015-04-20 08:31:59 -07001182 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
caryclark6c3b9cd2016-09-26 05:36:58 -07001183 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001184 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
1185 double coinStart;
1186 SkDEBUGCODE(double coinEnd);
caryclark1049f122015-04-20 08:31:59 -07001187 SkTSpan<OppCurve, TCurve>* cutFirst;
caryclark54359292015-03-26 07:52:43 -07001188 if (prev && prev->fEndT == startT
1189 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
1190 &oppStartT)
caryclark1049f122015-04-20 08:31:59 -07001191 && prev->fStartT < coinStart && coinStart < startT
1192 && (cutFirst = prev->oppT(oppStartT))) {
1193 oppFirst = cutFirst;
caryclark54359292015-03-26 07:52:43 -07001194 first = this->addSplitAt(prev, coinStart);
1195 first->markCoincident();
1196 prev->fCoinEnd.markCoincident();
1197 if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
caryclark1049f122015-04-20 08:31:59 -07001198 SkTSpan<OppCurve, TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
caryclark54359292015-03-26 07:52:43 -07001199 if (oppMatched) {
1200 oppFirst->fCoinEnd.markCoincident();
1201 oppHalf->markCoincident();
1202 oppFirst = oppHalf;
1203 } else {
1204 oppFirst->markCoincident();
1205 oppHalf->fCoinStart.markCoincident();
1206 }
1207 }
1208 } else {
1209 SkDEBUGCODE(coinStart = first->fStartT);
caryclarka35ab3e2016-10-20 08:32:18 -07001210 FAIL_IF(!oppFirst);
caryclark54359292015-03-26 07:52:43 -07001211 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
1212 }
caryclark1049f122015-04-20 08:31:59 -07001213 // FIXME: incomplete : if we're not at the end, find end of coin
1214 SkTSpan<OppCurve, TCurve>* oppLast;
caryclark6c3b9cd2016-09-26 05:36:58 -07001215 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001216 oppLast = last->findOppT(last->fCoinEnd.perpT());
1217 SkDEBUGCODE(coinEnd = last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001218#ifdef SK_DEBUG
1219 if (!this->globalState() || !this->globalState()->debugSkipAssert()) {
1220 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT;
1221 }
1222#endif
caryclark54359292015-03-26 07:52:43 -07001223 if (!oppMatched) {
1224 SkTSwap(oppFirst, oppLast);
1225 SkTSwap(oppStartT, oppEndT);
1226 }
caryclarke25a4f62016-07-26 09:26:29 -07001227 SkOPASSERT(oppStartT < oppEndT);
caryclark54359292015-03-26 07:52:43 -07001228 SkASSERT(coinStart == first->fStartT);
1229 SkASSERT(coinEnd == last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001230 SkOPASSERT(oppStartT == oppFirst->fStartT);
1231 SkOPASSERT(oppEndT == oppLast->fEndT);
1232 if (!oppFirst) {
caryclarkef7cee42016-09-06 09:05:54 -07001233 *result = nullptr;
1234 return true;
caryclark643ede62016-08-08 14:27:45 -07001235 }
caryclark42942862016-08-19 07:01:33 -07001236 if (!oppLast) {
caryclarkef7cee42016-09-06 09:05:54 -07001237 *result = nullptr;
1238 return true;
caryclark42942862016-08-19 07:01:33 -07001239 }
caryclark54359292015-03-26 07:52:43 -07001240 // reduce coincident runs to single entries
1241 this->validate();
1242 sect2->validate();
caryclark1049f122015-04-20 08:31:59 -07001243 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1244 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
caryclark54359292015-03-26 07:52:43 -07001245 this->removeSpanRange(first, last);
1246 sect2->removeSpanRange(oppFirst, oppLast);
1247 first->fEndT = last->fEndT;
1248 first->resetBounds(this->fCurve);
1249 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], sect2->fCurve);
1250 first->fCoinEnd.setPerp(fCurve, first->fEndT, first->fPart[TCurve::kPointLast], sect2->fCurve);
1251 oppStartT = first->fCoinStart.perpT();
1252 oppEndT = first->fCoinEnd.perpT();
1253 if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) {
1254 if (!oppMatched) {
1255 SkTSwap(oppStartT, oppEndT);
1256 }
1257 oppFirst->fStartT = oppStartT;
1258 oppFirst->fEndT = oppEndT;
1259 oppFirst->resetBounds(sect2->fCurve);
1260 }
1261 this->validateBounded();
1262 sect2->validateBounded();
1263 last = first->fNext;
1264 this->removeCoincident(first, false);
1265 sect2->removeCoincident(oppFirst, true);
caryclark1049f122015-04-20 08:31:59 -07001266 if (deleteEmptySpans) {
caryclarkef7cee42016-09-06 09:05:54 -07001267 if (!this->deleteEmptySpans() || !sect2->deleteEmptySpans()) {
1268 *result = nullptr;
1269 return false;
1270 }
caryclark54359292015-03-26 07:52:43 -07001271 }
1272 this->validate();
1273 sect2->validate();
caryclarkef7cee42016-09-06 09:05:54 -07001274 *result = last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr;
1275 return true;
caryclark54359292015-03-26 07:52:43 -07001276}
1277
caryclark1049f122015-04-20 08:31:59 -07001278template<typename TCurve, typename OppCurve>
1279SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun(
1280 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) {
1281 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001282 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr;
1283 first = nullptr;
caryclark54359292015-03-26 07:52:43 -07001284 // find the first fully coincident span
1285 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07001286 if (work->fCoinStart.isMatch()) {
caryclark1049f122015-04-20 08:31:59 -07001287#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -07001288 work->validatePerpT(work->fCoinStart.perpT());
1289 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt());
caryclark1049f122015-04-20 08:31:59 -07001290#endif
caryclarka35ab3e2016-10-20 08:32:18 -07001291 SkOPASSERT(work->hasOppT(work->fCoinStart.perpT()));
caryclark6c3b9cd2016-09-26 05:36:58 -07001292 if (!work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001293 break;
1294 }
1295 lastCandidate = work;
1296 if (!first) {
1297 first = work;
1298 }
caryclark1049f122015-04-20 08:31:59 -07001299 } else if (first && work->fCollapsed) {
1300 *lastPtr = lastCandidate;
1301 return first;
caryclark54359292015-03-26 07:52:43 -07001302 } else {
halcanary96fcdcc2015-08-27 07:41:13 -07001303 lastCandidate = nullptr;
caryclark643ede62016-08-08 14:27:45 -07001304 SkOPASSERT(!first);
caryclark54359292015-03-26 07:52:43 -07001305 }
1306 if (work == *lastPtr) {
1307 return first;
1308 }
1309 work = work->fNext;
caryclarke25a4f62016-07-26 09:26:29 -07001310 if (!work) {
1311 return nullptr;
1312 }
caryclark54359292015-03-26 07:52:43 -07001313 } while (true);
1314 if (lastCandidate) {
1315 *lastPtr = lastCandidate;
1316 }
1317 return first;
1318}
1319
caryclark1049f122015-04-20 08:31:59 -07001320template<typename TCurve, typename OppCurve>
1321int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
1322 SkTSect<OppCurve, TCurve>* opp,
1323 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult) {
caryclark54359292015-03-26 07:52:43 -07001324 bool spanStart, oppStart;
1325 int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
1326 if (hullResult >= 0) {
1327 if (hullResult == 2) { // hulls have one point in common
1328 if (!span->fBounded || !span->fBounded->fNext) {
1329 SkASSERT(!span->fBounded || span->fBounded->fBounded == oppSpan);
1330 if (spanStart) {
1331 span->fEndT = span->fStartT;
caryclark45fa4472015-01-16 07:04:10 -08001332 } else {
caryclark54359292015-03-26 07:52:43 -07001333 span->fStartT = span->fEndT;
1334 }
1335 } else {
1336 hullResult = 1;
1337 }
1338 if (!oppSpan->fBounded || !oppSpan->fBounded->fNext) {
1339 SkASSERT(!oppSpan->fBounded || oppSpan->fBounded->fBounded == span);
1340 if (oppStart) {
1341 oppSpan->fEndT = oppSpan->fStartT;
1342 } else {
1343 oppSpan->fStartT = oppSpan->fEndT;
1344 }
1345 *oppResult = 2;
1346 } else {
1347 *oppResult = 1;
1348 }
1349 } else {
1350 *oppResult = 1;
1351 }
1352 return hullResult;
1353 }
1354 if (span->fIsLine && oppSpan->fIsLine) {
1355 SkIntersections i;
1356 int sects = this->linesIntersect(span, opp, oppSpan, &i);
caryclark26ad22a2015-10-16 09:03:38 -07001357 if (sects == 2) {
1358 return *oppResult = 1;
1359 }
caryclark54359292015-03-26 07:52:43 -07001360 if (!sects) {
1361 return -1;
1362 }
1363 span->fStartT = span->fEndT = i[0][0];
1364 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1365 return *oppResult = 2;
1366 }
1367 if (span->fIsLinear || oppSpan->fIsLinear) {
1368 return *oppResult = (int) span->linearsIntersect(oppSpan);
1369 }
1370 return *oppResult = 1;
1371}
1372
caryclarked0935a2015-10-22 07:23:52 -07001373template<typename TCurve>
1374static bool is_parallel(const SkDLine& thisLine, const TCurve& opp) {
1375 if (!opp.IsConic()) {
1376 return false; // FIXME : breaks a lot of stuff now
1377 }
1378 int finds = 0;
1379 SkDLine thisPerp;
1380 thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1381 thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1382 thisPerp.fPts[1] = thisLine.fPts[1];
1383 SkIntersections perpRayI;
1384 perpRayI.intersectRay(opp, thisPerp);
1385 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1386 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]);
1387 }
1388 thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1389 thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1390 thisPerp.fPts[0] = thisLine.fPts[0];
1391 perpRayI.intersectRay(opp, thisPerp);
1392 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1393 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]);
1394 }
1395 return finds >= 2;
1396}
1397
caryclark54359292015-03-26 07:52:43 -07001398// while the intersection points are sufficiently far apart:
1399// construct the tangent lines from the intersections
1400// find the point where the tangent line intersects the opposite curve
caryclark1049f122015-04-20 08:31:59 -07001401template<typename TCurve, typename OppCurve>
1402int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
1403 SkTSect<OppCurve, TCurve>* opp,
1404 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
caryclarka35ab3e2016-10-20 08:32:18 -07001405 SkIntersections thisRayI SkDEBUGCODE((span->fDebugGlobalState));
1406 SkIntersections oppRayI SkDEBUGCODE((span->fDebugGlobalState));
caryclark54359292015-03-26 07:52:43 -07001407 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
caryclark1049f122015-04-20 08:31:59 -07001408 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
caryclark54359292015-03-26 07:52:43 -07001409 int loopCount = 0;
1410 double bestDistSq = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -07001411 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1412 return 0;
1413 }
1414 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1415 return 0;
1416 }
caryclark26ad22a2015-10-16 09:03:38 -07001417 // if the ends of each line intersect the opposite curve, the lines are coincident
1418 if (thisRayI.used() > 1) {
1419 int ptMatches = 0;
1420 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) {
1421 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1422 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPts[lIndex]);
1423 }
1424 }
caryclarked0935a2015-10-22 07:23:52 -07001425 if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001426 return 2;
1427 }
1428 }
1429 if (oppRayI.used() > 1) {
1430 int ptMatches = 0;
1431 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) {
1432 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1433 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[lIndex]);
1434 }
1435 }
caryclarked0935a2015-10-22 07:23:52 -07001436 if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001437 return 2;
1438 }
1439 }
caryclark54359292015-03-26 07:52:43 -07001440 do {
caryclark54359292015-03-26 07:52:43 -07001441 // pick the closest pair of points
1442 double closest = DBL_MAX;
1443 int closeIndex SK_INIT_TO_AVOID_WARNING;
1444 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1445 for (int index = 0; index < oppRayI.used(); ++index) {
1446 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
1447 continue;
1448 }
1449 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) {
1450 if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppSpan->fEndT)) {
1451 continue;
1452 }
1453 double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oIndex));
1454 if (closest > distSq) {
1455 closest = distSq;
1456 closeIndex = index;
1457 oppCloseIndex = oIndex;
caryclarkccec0f92015-03-24 07:28:17 -07001458 }
caryclarkccec0f92015-03-24 07:28:17 -07001459 }
reed0dc4dd62015-03-24 13:55:33 -07001460 }
caryclark54359292015-03-26 07:52:43 -07001461 if (closest == DBL_MAX) {
caryclark1049f122015-04-20 08:31:59 -07001462 break;
reed0dc4dd62015-03-24 13:55:33 -07001463 }
caryclark54359292015-03-26 07:52:43 -07001464 const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
1465 const SkDPoint& iPt = oppRayI.pt(closeIndex);
1466 if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT)
1467 && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan->fEndT)
1468 && oppIPt.approximatelyEqual(iPt)) {
1469 i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex);
1470 return i->used();
1471 }
1472 double distSq = oppIPt.distanceSquared(iPt);
1473 if (bestDistSq < distSq || ++loopCount > 5) {
caryclark1049f122015-04-20 08:31:59 -07001474 return 0;
caryclark54359292015-03-26 07:52:43 -07001475 }
1476 bestDistSq = distSq;
caryclark1049f122015-04-20 08:31:59 -07001477 double oppStart = oppRayI[0][closeIndex];
1478 thisLine[0] = fCurve.ptAtT(oppStart);
1479 thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart);
1480 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1481 break;
1482 }
1483 double start = thisRayI[0][oppCloseIndex];
1484 oppLine[0] = opp->fCurve.ptAtT(start);
1485 oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start);
1486 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1487 break;
1488 }
caryclark54359292015-03-26 07:52:43 -07001489 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001490 // convergence may fail if the curves are nearly coincident
1491 SkTCoincident<OppCurve, TCurve> oCoinS, oCoinE;
1492 oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->fPart[0], fCurve);
1493 oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->fPart[OppCurve::kPointLast], fCurve);
1494 double tStart = oCoinS.perpT();
1495 double tEnd = oCoinE.perpT();
1496 bool swap = tStart > tEnd;
1497 if (swap) {
1498 SkTSwap(tStart, tEnd);
1499 }
1500 tStart = SkTMax(tStart, span->fStartT);
1501 tEnd = SkTMin(tEnd, span->fEndT);
1502 if (tStart > tEnd) {
1503 return 0;
1504 }
1505 SkDVector perpS, perpE;
1506 if (tStart == span->fStartT) {
1507 SkTCoincident<TCurve, OppCurve> coinS;
1508 coinS.setPerp(fCurve, span->fStartT, span->fPart[0], opp->fCurve);
1509 perpS = span->fPart[0] - coinS.perpPt();
1510 } else if (swap) {
1511 perpS = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1512 } else {
1513 perpS = oCoinS.perpPt() - oppSpan->fPart[0];
1514 }
1515 if (tEnd == span->fEndT) {
1516 SkTCoincident<TCurve, OppCurve> coinE;
1517 coinE.setPerp(fCurve, span->fEndT, span->fPart[TCurve::kPointLast], opp->fCurve);
1518 perpE = span->fPart[TCurve::kPointLast] - coinE.perpPt();
1519 } else if (swap) {
1520 perpE = oCoinS.perpPt() - oppSpan->fPart[0];
1521 } else {
1522 perpE = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1523 }
1524 if (perpS.dot(perpE) >= 0) {
1525 return 0;
1526 }
1527 SkTCoincident<TCurve, OppCurve> coinW;
1528 double workT = tStart;
1529 double tStep = tEnd - tStart;
1530 SkDPoint workPt;
1531 do {
1532 tStep *= 0.5;
1533 if (precisely_zero(tStep)) {
1534 return 0;
1535 }
1536 workT += tStep;
1537 workPt = fCurve.ptAtT(workT);
1538 coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
caryclark27c015d2016-09-23 05:47:20 -07001539 double perpT = coinW.perpT();
caryclark6c3b9cd2016-09-26 05:36:58 -07001540 if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) {
caryclarkb6693002015-12-16 12:28:35 -08001541 continue;
1542 }
caryclark1049f122015-04-20 08:31:59 -07001543 SkDVector perpW = workPt - coinW.perpPt();
1544 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
1545 tStep = -tStep;
1546 }
caryclarkb6693002015-12-16 12:28:35 -08001547 if (workPt.approximatelyEqual(coinW.perpPt())) {
1548 break;
1549 }
1550 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001551 double oppTTest = coinW.perpT();
1552 if (!opp->fHead->contains(oppTTest)) {
1553 return 0;
1554 }
1555 i->setMax(1);
1556 i->insert(workT, oppTTest, workPt);
1557 return 1;
caryclark54359292015-03-26 07:52:43 -07001558}
1559
1560
caryclark1049f122015-04-20 08:31:59 -07001561template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001562bool SkTSect<TCurve, OppCurve>::markSpanGone(SkTSpan<TCurve, OppCurve>* span) {
1563 if (--fActiveCount < 0) {
1564 return false;
1565 }
caryclark54359292015-03-26 07:52:43 -07001566 span->fNext = fDeleted;
1567 fDeleted = span;
caryclarke25a4f62016-07-26 09:26:29 -07001568 SkOPASSERT(!span->fDeleted);
caryclark54359292015-03-26 07:52:43 -07001569 span->fDeleted = true;
caryclarkef7cee42016-09-06 09:05:54 -07001570 return true;
caryclark54359292015-03-26 07:52:43 -07001571}
1572
caryclark1049f122015-04-20 08:31:59 -07001573template<typename TCurve, typename OppCurve>
1574bool SkTSect<TCurve, OppCurve>::matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2,
1575 double t2) const {
caryclark54359292015-03-26 07:52:43 -07001576 SkDVector dxdy = this->fCurve.dxdyAtT(t);
1577 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
1578 return dxdy.dot(dxdy2) >= 0;
1579}
1580
caryclark1049f122015-04-20 08:31:59 -07001581template<typename TCurve, typename OppCurve>
1582void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2,
1583 double t2, bool* calcMatched, bool* oppMatched) const {
caryclark54359292015-03-26 07:52:43 -07001584 if (*calcMatched) {
caryclark55888e42016-07-18 10:01:36 -07001585 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
caryclark54359292015-03-26 07:52:43 -07001586 } else {
1587 *oppMatched = this->matchedDirection(t, sect2, t2);
1588 *calcMatched = true;
1589 }
1590}
1591
caryclark1049f122015-04-20 08:31:59 -07001592template<typename TCurve, typename OppCurve>
1593void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2) {
caryclark54359292015-03-26 07:52:43 -07001594 double smallLimit = 0;
1595 do {
1596 // find the smallest unprocessed span
halcanary96fcdcc2015-08-27 07:41:13 -07001597 SkTSpan<TCurve, OppCurve>* smaller = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001598 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001599 do {
caryclark221a4bb2016-10-07 11:15:15 -07001600 if (!test) {
1601 return;
1602 }
caryclark54359292015-03-26 07:52:43 -07001603 if (test->fStartT < smallLimit) {
1604 continue;
1605 }
1606 if (smaller && smaller->fEndT < test->fStartT) {
1607 continue;
1608 }
1609 smaller = test;
1610 } while ((test = test->fNext));
1611 if (!smaller) {
1612 return;
1613 }
1614 smallLimit = smaller->fEndT;
1615 // find next larger span
halcanary96fcdcc2015-08-27 07:41:13 -07001616 SkTSpan<TCurve, OppCurve>* prior = nullptr;
1617 SkTSpan<TCurve, OppCurve>* larger = nullptr;
1618 SkTSpan<TCurve, OppCurve>* largerPrior = nullptr;
caryclark54359292015-03-26 07:52:43 -07001619 test = fCoincident;
1620 do {
1621 if (test->fStartT < smaller->fEndT) {
1622 continue;
1623 }
caryclark221a4bb2016-10-07 11:15:15 -07001624 SkOPASSERT(test->fStartT != smaller->fEndT);
caryclark54359292015-03-26 07:52:43 -07001625 if (larger && larger->fStartT < test->fStartT) {
1626 continue;
1627 }
1628 largerPrior = prior;
1629 larger = test;
1630 } while ((prior = test), (test = test->fNext));
1631 if (!larger) {
1632 continue;
1633 }
1634 // check middle t value to see if it is coincident as well
1635 double midT = (smaller->fEndT + larger->fStartT) / 2;
1636 SkDPoint midPt = fCurve.ptAtT(midT);
caryclark1049f122015-04-20 08:31:59 -07001637 SkTCoincident<TCurve, OppCurve> coin;
caryclark54359292015-03-26 07:52:43 -07001638 coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07001639 if (coin.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001640 smaller->fEndT = larger->fEndT;
1641 smaller->fCoinEnd = larger->fCoinEnd;
1642 if (largerPrior) {
1643 largerPrior->fNext = larger->fNext;
caryclark643ede62016-08-08 14:27:45 -07001644 largerPrior->validate();
caryclark54359292015-03-26 07:52:43 -07001645 } else {
1646 fCoincident = larger->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001647 }
1648 }
caryclark54359292015-03-26 07:52:43 -07001649 } while (true);
1650}
1651
caryclark1049f122015-04-20 08:31:59 -07001652template<typename TCurve, typename OppCurve>
1653SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev(
1654 SkTSpan<TCurve, OppCurve>* span) const {
halcanary96fcdcc2015-08-27 07:41:13 -07001655 SkTSpan<TCurve, OppCurve>* result = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001656 SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001657 while (span != test) {
1658 result = test;
1659 test = test->fNext;
1660 SkASSERT(test);
caryclarkccec0f92015-03-24 07:28:17 -07001661 }
caryclark55888e42016-07-18 10:01:36 -07001662 return result;
caryclarkccec0f92015-03-24 07:28:17 -07001663}
1664
caryclark1049f122015-04-20 08:31:59 -07001665template<typename TCurve, typename OppCurve>
1666void SkTSect<TCurve, OppCurve>::recoverCollapsed() {
1667 SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001668 while (deleted) {
caryclark1049f122015-04-20 08:31:59 -07001669 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001670 if (deleted->fCollapsed) {
caryclark1049f122015-04-20 08:31:59 -07001671 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead;
caryclark45fa4472015-01-16 07:04:10 -08001672 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
1673 spanPtr = &(*spanPtr)->fNext;
1674 }
1675 deleted->fNext = *spanPtr;
1676 *spanPtr = deleted;
1677 }
1678 deleted = delNext;
1679 }
1680}
1681
caryclark1049f122015-04-20 08:31:59 -07001682template<typename TCurve, typename OppCurve>
1683void SkTSect<TCurve, OppCurve>::removeAllBut(const SkTSpan<OppCurve, TCurve>* keep,
1684 SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp) {
1685 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001686 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001687 SkTSpan<OppCurve, TCurve>* bounded = testBounded->fBounded;
1688 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001689 // may have been deleted when opp did 'remove all but'
1690 if (bounded != keep && !bounded->fDeleted) {
1691 SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
1692 if (bounded->removeBounded(span)) {
1693 opp->removeSpan(bounded);
1694 }
caryclarkccec0f92015-03-24 07:28:17 -07001695 }
caryclark54359292015-03-26 07:52:43 -07001696 testBounded = next;
caryclarkccec0f92015-03-24 07:28:17 -07001697 }
caryclark54359292015-03-26 07:52:43 -07001698 SkASSERT(!span->fDeleted);
1699 SkASSERT(span->findOppSpan(keep));
1700 SkASSERT(keep->findOppSpan(span));
caryclarkccec0f92015-03-24 07:28:17 -07001701}
1702
caryclark1049f122015-04-20 08:31:59 -07001703template<typename TCurve, typename OppCurve>
1704void SkTSect<TCurve, OppCurve>::removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp) {
1705 SkTSpan<TCurve, OppCurve>* test = fHead;
1706 SkTSpan<TCurve, OppCurve>* next;
caryclark54359292015-03-26 07:52:43 -07001707 do {
1708 next = test->fNext;
1709 if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
1710 continue;
reed0dc4dd62015-03-24 13:55:33 -07001711 }
caryclark54359292015-03-26 07:52:43 -07001712 SkDVector startV = test->fCoinStart.perpPt() - test->fPart[0];
1713 SkDVector endV = test->fCoinEnd.perpPt() - test->fPart[TCurve::kPointLast];
1714#if DEBUG_T_SECT
1715 SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUNCTION__,
1716 startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV));
1717#endif
1718 if (startV.dot(endV) <= 0) {
1719 continue;
1720 }
1721 this->removeSpans(test, opp);
1722 } while ((test = next));
1723}
1724
caryclark1049f122015-04-20 08:31:59 -07001725template<typename TCurve, typename OppCurve>
1726void SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween) {
caryclark54359292015-03-26 07:52:43 -07001727 this->unlinkSpan(span);
1728 if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
1729 --fActiveCount;
1730 span->fNext = fCoincident;
1731 fCoincident = span;
1732 } else {
1733 this->markSpanGone(span);
reed0dc4dd62015-03-24 13:55:33 -07001734 }
caryclarkccec0f92015-03-24 07:28:17 -07001735}
1736
caryclark1049f122015-04-20 08:31:59 -07001737template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001738bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {
caryclark6c3b9cd2016-09-26 05:36:58 -07001739 if (!span->fStartT) {
1740 fRemovedStartT = true;
1741 }
1742 if (1 == span->fEndT) {
1743 fRemovedEndT = true;
1744 }
caryclark54359292015-03-26 07:52:43 -07001745 this->unlinkSpan(span);
caryclarkef7cee42016-09-06 09:05:54 -07001746 return this->markSpanGone(span);
caryclark54359292015-03-26 07:52:43 -07001747}
1748
caryclark1049f122015-04-20 08:31:59 -07001749template<typename TCurve, typename OppCurve>
1750void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first,
1751 SkTSpan<TCurve, OppCurve>* last) {
caryclark54359292015-03-26 07:52:43 -07001752 if (first == last) {
1753 return;
1754 }
caryclark1049f122015-04-20 08:31:59 -07001755 SkTSpan<TCurve, OppCurve>* span = first;
caryclark54359292015-03-26 07:52:43 -07001756 SkASSERT(span);
caryclark1049f122015-04-20 08:31:59 -07001757 SkTSpan<TCurve, OppCurve>* final = last->fNext;
1758 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001759 while ((span = next) && span != final) {
1760 next = span->fNext;
1761 this->markSpanGone(span);
1762 }
1763 if (final) {
1764 final->fPrev = first;
1765 }
1766 first->fNext = final;
caryclark643ede62016-08-08 14:27:45 -07001767 first->validate();
caryclark54359292015-03-26 07:52:43 -07001768}
1769
caryclark1049f122015-04-20 08:31:59 -07001770template<typename TCurve, typename OppCurve>
1771void SkTSect<TCurve, OppCurve>::removeSpans(SkTSpan<TCurve, OppCurve>* span,
1772 SkTSect<OppCurve, TCurve>* opp) {
1773 SkTSpanBounded<OppCurve, TCurve>* bounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001774 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -07001775 SkTSpan<OppCurve, TCurve>* spanBounded = bounded->fBounded;
1776 SkTSpanBounded<OppCurve, TCurve>* next = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001777 if (span->removeBounded(spanBounded)) { // shuffles last into position 0
1778 this->removeSpan(span);
1779 }
1780 if (spanBounded->removeBounded(span)) {
1781 opp->removeSpan(spanBounded);
1782 }
1783 SkASSERT(!span->fDeleted || !opp->debugHasBounded(span));
1784 bounded = next;
reed0dc4dd62015-03-24 13:55:33 -07001785 }
1786}
caryclarkccec0f92015-03-24 07:28:17 -07001787
caryclark1049f122015-04-20 08:31:59 -07001788template<typename TCurve, typename OppCurve>
1789SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::spanAtT(double t,
1790 SkTSpan<TCurve, OppCurve>** priorSpan) {
1791 SkTSpan<TCurve, OppCurve>* test = fHead;
halcanary96fcdcc2015-08-27 07:41:13 -07001792 SkTSpan<TCurve, OppCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -07001793 while (test && test->fEndT < t) {
1794 prev = test;
1795 test = test->fNext;
reed0dc4dd62015-03-24 13:55:33 -07001796 }
caryclark54359292015-03-26 07:52:43 -07001797 *priorSpan = prev;
halcanary96fcdcc2015-08-27 07:41:13 -07001798 return test && test->fStartT <= t ? test : nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001799}
1800
caryclark1049f122015-04-20 08:31:59 -07001801template<typename TCurve, typename OppCurve>
1802SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::tail() {
1803 SkTSpan<TCurve, OppCurve>* result = fHead;
1804 SkTSpan<TCurve, OppCurve>* next = fHead;
reed0dc4dd62015-03-24 13:55:33 -07001805 while ((next = next->fNext)) {
1806 if (next->fEndT > result->fEndT) {
1807 result = next;
1808 }
1809 }
1810 return result;
1811}
1812
1813/* Each span has a range of opposite spans it intersects. After the span is split in two,
1814 adjust the range to its new size */
caryclark1049f122015-04-20 08:31:59 -07001815template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -07001816bool SkTSect<TCurve, OppCurve>::trim(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001817 SkTSect<OppCurve, TCurve>* opp) {
caryclarka35ab3e2016-10-20 08:32:18 -07001818 FAIL_IF(!span->initBounds(fCurve));
caryclark1049f122015-04-20 08:31:59 -07001819 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001820 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001821 SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
1822 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001823 int oppSects, sects = this->intersects(span, opp, test, &oppSects);
1824 if (sects >= 1) {
1825 if (oppSects == 2) {
1826 test->initBounds(opp->fCurve);
1827 opp->removeAllBut(span, test, this);
1828 }
1829 if (sects == 2) {
1830 span->initBounds(fCurve);
1831 this->removeAllBut(test, span, opp);
caryclarka35ab3e2016-10-20 08:32:18 -07001832 return true;
caryclark54359292015-03-26 07:52:43 -07001833 }
reed0dc4dd62015-03-24 13:55:33 -07001834 } else {
caryclark54359292015-03-26 07:52:43 -07001835 if (span->removeBounded(test)) {
1836 this->removeSpan(span);
1837 }
1838 if (test->removeBounded(span)) {
1839 opp->removeSpan(test);
1840 }
1841 }
1842 testBounded = next;
1843 }
caryclarka35ab3e2016-10-20 08:32:18 -07001844 return true;
caryclark54359292015-03-26 07:52:43 -07001845}
1846
caryclark1049f122015-04-20 08:31:59 -07001847template<typename TCurve, typename OppCurve>
1848void SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) {
1849 SkTSpan<TCurve, OppCurve>* prev = span->fPrev;
1850 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001851 if (prev) {
1852 prev->fNext = next;
1853 if (next) {
1854 next->fPrev = prev;
caryclark643ede62016-08-08 14:27:45 -07001855 next->validate();
caryclark54359292015-03-26 07:52:43 -07001856 }
1857 } else {
1858 fHead = next;
1859 if (next) {
halcanary96fcdcc2015-08-27 07:41:13 -07001860 next->fPrev = nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001861 }
1862 }
1863}
1864
caryclark1049f122015-04-20 08:31:59 -07001865template<typename TCurve, typename OppCurve>
1866bool SkTSect<TCurve, OppCurve>::updateBounded(SkTSpan<TCurve, OppCurve>* first,
1867 SkTSpan<TCurve, OppCurve>* last, SkTSpan<OppCurve, TCurve>* oppFirst) {
1868 SkTSpan<TCurve, OppCurve>* test = first;
1869 const SkTSpan<TCurve, OppCurve>* final = last->next();
caryclark54359292015-03-26 07:52:43 -07001870 bool deleteSpan = false;
1871 do {
1872 deleteSpan |= test->removeAllBounded();
caryclarke25a4f62016-07-26 09:26:29 -07001873 } while ((test = test->fNext) != final && test);
halcanary96fcdcc2015-08-27 07:41:13 -07001874 first->fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -07001875 first->addBounded(oppFirst, &fHeap);
1876 // cannot call validate until remove span range is called
1877 return deleteSpan;
1878}
1879
1880
caryclark1049f122015-04-20 08:31:59 -07001881template<typename TCurve, typename OppCurve>
1882void SkTSect<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -07001883#if DEBUG_VALIDATE
caryclark45fa4472015-01-16 07:04:10 -08001884 int count = 0;
caryclark643ede62016-08-08 14:27:45 -07001885 double last = 0;
caryclark45fa4472015-01-16 07:04:10 -08001886 if (fHead) {
caryclark1049f122015-04-20 08:31:59 -07001887 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark45fa4472015-01-16 07:04:10 -08001888 SkASSERT(!span->fPrev);
caryclark643ede62016-08-08 14:27:45 -07001889 const SkTSpan<TCurve, OppCurve>* next;
caryclark45fa4472015-01-16 07:04:10 -08001890 do {
1891 span->validate();
1892 SkASSERT(span->fStartT >= last);
caryclark643ede62016-08-08 14:27:45 -07001893 last = span->fEndT;
caryclark45fa4472015-01-16 07:04:10 -08001894 ++count;
caryclark643ede62016-08-08 14:27:45 -07001895 next = span->fNext;
1896 SkASSERT(next != span);
1897 } while ((span = next) != nullptr);
caryclark45fa4472015-01-16 07:04:10 -08001898 }
1899 SkASSERT(count == fActiveCount);
caryclark643ede62016-08-08 14:27:45 -07001900#endif
1901#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -08001902 SkASSERT(fActiveCount <= fDebugAllocatedCount);
1903 int deletedCount = 0;
caryclark1049f122015-04-20 08:31:59 -07001904 const SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001905 while (deleted) {
1906 ++deletedCount;
1907 deleted = deleted->fNext;
1908 }
caryclark1049f122015-04-20 08:31:59 -07001909 const SkTSpan<TCurve, OppCurve>* coincident = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001910 while (coincident) {
1911 ++deletedCount;
1912 coincident = coincident->fNext;
1913 }
caryclark45fa4472015-01-16 07:04:10 -08001914 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount);
caryclarkccec0f92015-03-24 07:28:17 -07001915#endif
caryclark54359292015-03-26 07:52:43 -07001916}
1917
caryclark1049f122015-04-20 08:31:59 -07001918template<typename TCurve, typename OppCurve>
1919void SkTSect<TCurve, OppCurve>::validateBounded() const {
caryclark643ede62016-08-08 14:27:45 -07001920#if DEBUG_VALIDATE
caryclark54359292015-03-26 07:52:43 -07001921 if (!fHead) {
1922 return;
1923 }
caryclark1049f122015-04-20 08:31:59 -07001924 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark54359292015-03-26 07:52:43 -07001925 do {
1926 span->validateBounded();
halcanary96fcdcc2015-08-27 07:41:13 -07001927 } while ((span = span->fNext) != nullptr);
caryclark54359292015-03-26 07:52:43 -07001928#endif
1929}
caryclark45fa4472015-01-16 07:04:10 -08001930
caryclark1049f122015-04-20 08:31:59 -07001931template<typename TCurve, typename OppCurve>
1932int SkTSect<TCurve, OppCurve>::EndsEqual(const SkTSect<TCurve, OppCurve>* sect1,
1933 const SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark45fa4472015-01-16 07:04:10 -08001934 int zeroOneSet = 0;
caryclark54359292015-03-26 07:52:43 -07001935 if (sect1->fCurve[0] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001936 zeroOneSet |= kZeroS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001937 intersections->insert(0, 0, sect1->fCurve[0]);
1938 }
caryclark1049f122015-04-20 08:31:59 -07001939 if (sect1->fCurve[0] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001940 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark54359292015-03-26 07:52:43 -07001941 intersections->insert(0, 1, sect1->fCurve[0]);
1942 }
1943 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001944 zeroOneSet |= kOneS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001945 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
1946 }
caryclark1049f122015-04-20 08:31:59 -07001947 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001948 zeroOneSet |= kOneS1Set | kOneS2Set;
reed0dc4dd62015-03-24 13:55:33 -07001949 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07001950 }
1951 // check for zero
1952 if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set))
1953 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) {
1954 zeroOneSet |= kZeroS1Set | kZeroS2Set;
1955 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
1956 }
1957 if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
caryclark1049f122015-04-20 08:31:59 -07001958 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07001959 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark1049f122015-04-20 08:31:59 -07001960 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[OppCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07001961 }
1962 // check for one
1963 if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
1964 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[0])) {
1965 zeroOneSet |= kOneS1Set | kZeroS2Set;
1966 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], sect2->fCurve[0]);
1967 }
1968 if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
1969 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[
caryclark1049f122015-04-20 08:31:59 -07001970 OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07001971 zeroOneSet |= kOneS1Set | kOneS2Set;
1972 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
caryclark1049f122015-04-20 08:31:59 -07001973 sect2->fCurve[OppCurve::kPointLast]);
caryclark45fa4472015-01-16 07:04:10 -08001974 }
1975 return zeroOneSet;
1976}
1977
caryclark1049f122015-04-20 08:31:59 -07001978template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08001979struct SkClosestRecord {
caryclark54359292015-03-26 07:52:43 -07001980 bool operator<(const SkClosestRecord& rh) const {
1981 return fClosest < rh.fClosest;
1982 }
1983
caryclark45fa4472015-01-16 07:04:10 -08001984 void addIntersection(SkIntersections* intersections) const {
1985 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT();
1986 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT();
1987 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
1988 }
1989
caryclark1049f122015-04-20 08:31:59 -07001990 void findEnd(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2,
caryclark45fa4472015-01-16 07:04:10 -08001991 int c1Index, int c2Index) {
1992 const TCurve& c1 = span1->part();
caryclark1049f122015-04-20 08:31:59 -07001993 const OppCurve& c2 = span2->part();
caryclark45fa4472015-01-16 07:04:10 -08001994 if (!c1[c1Index].approximatelyEqual(c2[c2Index])) {
1995 return;
1996 }
1997 double dist = c1[c1Index].distanceSquared(c2[c2Index]);
1998 if (fClosest < dist) {
1999 return;
2000 }
2001 fC1Span = span1;
2002 fC2Span = span2;
2003 fC1StartT = span1->startT();
2004 fC1EndT = span1->endT();
2005 fC2StartT = span2->startT();
2006 fC2EndT = span2->endT();
2007 fC1Index = c1Index;
2008 fC2Index = c2Index;
2009 fClosest = dist;
2010 }
2011
caryclarkcdeff812016-07-22 03:34:19 -07002012 bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const {
caryclark45fa4472015-01-16 07:04:10 -08002013 SkASSERT(fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT()
2014 || mate.fC1Span->endT() <= fC1Span->startT());
caryclarkcdeff812016-07-22 03:34:19 -07002015 SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002016 || mate.fC2Span->endT() <= fC2Span->startT());
2017 return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT()
2018 || fC1Span->startT() == mate.fC1Span->endT()
2019 || fC2Span == mate.fC2Span
2020 || fC2Span->endT() == mate.fC2Span->startT()
2021 || fC2Span->startT() == mate.fC2Span->endT();
2022 }
2023
2024 void merge(const SkClosestRecord& mate) {
2025 fC1Span = mate.fC1Span;
2026 fC2Span = mate.fC2Span;
2027 fClosest = mate.fClosest;
2028 fC1Index = mate.fC1Index;
2029 fC2Index = mate.fC2Index;
2030 }
caryclark55888e42016-07-18 10:01:36 -07002031
caryclark45fa4472015-01-16 07:04:10 -08002032 void reset() {
2033 fClosest = FLT_MAX;
halcanary96fcdcc2015-08-27 07:41:13 -07002034 SkDEBUGCODE(fC1Span = nullptr);
2035 SkDEBUGCODE(fC2Span = nullptr);
caryclark45fa4472015-01-16 07:04:10 -08002036 SkDEBUGCODE(fC1Index = fC2Index = -1);
2037 }
2038
2039 void update(const SkClosestRecord& mate) {
2040 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT);
2041 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT);
2042 fC2StartT = SkTMin(fC2StartT, mate.fC2StartT);
2043 fC2EndT = SkTMax(fC2EndT, mate.fC2EndT);
2044 }
2045
caryclark1049f122015-04-20 08:31:59 -07002046 const SkTSpan<TCurve, OppCurve>* fC1Span;
2047 const SkTSpan<OppCurve, TCurve>* fC2Span;
caryclark45fa4472015-01-16 07:04:10 -08002048 double fC1StartT;
2049 double fC1EndT;
2050 double fC2StartT;
2051 double fC2EndT;
2052 double fClosest;
2053 int fC1Index;
2054 int fC2Index;
2055};
2056
caryclark1049f122015-04-20 08:31:59 -07002057template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002058struct SkClosestSect {
2059 SkClosestSect()
2060 : fUsed(0) {
2061 fClosest.push_back().reset();
2062 }
2063
caryclarkcdeff812016-07-22 03:34:19 -07002064 bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2
2065 SkDEBUGPARAMS(SkIntersections* i)) {
caryclark1049f122015-04-20 08:31:59 -07002066 SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed];
caryclark45fa4472015-01-16 07:04:10 -08002067 record->findEnd(span1, span2, 0, 0);
caryclark1049f122015-04-20 08:31:59 -07002068 record->findEnd(span1, span2, 0, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002069 record->findEnd(span1, span2, TCurve::kPointLast, 0);
caryclark1049f122015-04-20 08:31:59 -07002070 record->findEnd(span1, span2, TCurve::kPointLast, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002071 if (record->fClosest == FLT_MAX) {
caryclark54359292015-03-26 07:52:43 -07002072 return false;
caryclark45fa4472015-01-16 07:04:10 -08002073 }
2074 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002075 SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index];
caryclarkcdeff812016-07-22 03:34:19 -07002076 if (test->matesWith(*record SkDEBUGPARAMS(i))) {
caryclark45fa4472015-01-16 07:04:10 -08002077 if (test->fClosest > record->fClosest) {
2078 test->merge(*record);
2079 }
2080 test->update(*record);
2081 record->reset();
caryclark54359292015-03-26 07:52:43 -07002082 return false;
caryclark45fa4472015-01-16 07:04:10 -08002083 }
2084 }
2085 ++fUsed;
2086 fClosest.push_back().reset();
caryclark54359292015-03-26 07:52:43 -07002087 return true;
caryclark45fa4472015-01-16 07:04:10 -08002088 }
2089
2090 void finish(SkIntersections* intersections) const {
caryclark1049f122015-04-20 08:31:59 -07002091 SkSTArray<TCurve::kMaxIntersections * 3,
2092 const SkClosestRecord<TCurve, OppCurve>*, true> closestPtrs;
caryclark45fa4472015-01-16 07:04:10 -08002093 for (int index = 0; index < fUsed; ++index) {
caryclark54359292015-03-26 07:52:43 -07002094 closestPtrs.push_back(&fClosest[index]);
2095 }
caryclark1049f122015-04-20 08:31:59 -07002096 SkTQSort<const SkClosestRecord<TCurve, OppCurve> >(closestPtrs.begin(), closestPtrs.end()
2097 - 1);
caryclark54359292015-03-26 07:52:43 -07002098 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002099 const SkClosestRecord<TCurve, OppCurve>* test = closestPtrs[index];
caryclark54359292015-03-26 07:52:43 -07002100 test->addIntersection(intersections);
caryclark45fa4472015-01-16 07:04:10 -08002101 }
2102 }
2103
caryclark54359292015-03-26 07:52:43 -07002104 // this is oversized so that an extra records can merge into final one
caryclark1049f122015-04-20 08:31:59 -07002105 SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve, OppCurve>, true> fClosest;
caryclark45fa4472015-01-16 07:04:10 -08002106 int fUsed;
2107};
2108
2109// returns true if the rect is too small to consider
caryclark1049f122015-04-20 08:31:59 -07002110template<typename TCurve, typename OppCurve>
2111void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
2112 SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark54359292015-03-26 07:52:43 -07002113#if DEBUG_T_SECT_DUMP > 1
2114 gDumpTSectNum = 0;
2115#endif
caryclark1049f122015-04-20 08:31:59 -07002116 SkDEBUGCODE(sect1->fOppSect = sect2);
2117 SkDEBUGCODE(sect2->fOppSect = sect1);
caryclark45fa4472015-01-16 07:04:10 -08002118 intersections->reset();
caryclarka35ab3e2016-10-20 08:32:18 -07002119 intersections->setMax(TCurve::kMaxIntersections + 4); // give extra for slop
caryclark1049f122015-04-20 08:31:59 -07002120 SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
2121 SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002122 int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
2123// SkASSERT(between(0, sect, 2));
2124 if (!sect) {
caryclark45fa4472015-01-16 07:04:10 -08002125 return;
2126 }
caryclark54359292015-03-26 07:52:43 -07002127 if (sect == 2 && oppSect == 2) {
caryclark45fa4472015-01-16 07:04:10 -08002128 (void) EndsEqual(sect1, sect2, intersections);
2129 return;
2130 }
caryclark54359292015-03-26 07:52:43 -07002131 span1->addBounded(span2, &sect1->fHeap);
2132 span2->addBounded(span1, &sect2->fHeap);
caryclark26ad22a2015-10-16 09:03:38 -07002133 const int kMaxCoinLoopCount = 8;
2134 int coinLoopCount = kMaxCoinLoopCount;
2135 double start1s SK_INIT_TO_AVOID_WARNING;
2136 double start1e SK_INIT_TO_AVOID_WARNING;
caryclark45fa4472015-01-16 07:04:10 -08002137 do {
2138 // find the largest bounds
caryclark1049f122015-04-20 08:31:59 -07002139 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002140 if (!largest1) {
2141 break;
2142 }
caryclark1049f122015-04-20 08:31:59 -07002143 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
caryclark6c3b9cd2016-09-26 05:36:58 -07002144 sect1->fRemovedStartT = sect1->fRemovedEndT = false;
2145 sect2->fRemovedStartT = sect2->fRemovedEndT = false;
caryclark45fa4472015-01-16 07:04:10 -08002146 // split it
caryclark1049f122015-04-20 08:31:59 -07002147 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
2148 || (!largest1->fCollapsed && largest2->fCollapsed)))) {
2149 if (largest1->fCollapsed) {
2150 break;
2151 }
2152 // trim parts that don't intersect the opposite
2153 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
caryclark643ede62016-08-08 14:27:45 -07002154 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002155 if (!half1->split(largest1, &sect1->fHeap)) {
2156 break;
2157 }
caryclarka35ab3e2016-10-20 08:32:18 -07002158 if (!sect1->trim(largest1, sect2)) {
2159 SkOPOBJASSERT(intersections, 0);
2160 return;
2161 }
2162 if (!sect1->trim(half1, sect2)) {
2163 SkOPOBJASSERT(intersections, 0);
2164 return;
2165 }
caryclark1049f122015-04-20 08:31:59 -07002166 } else {
2167 if (largest2->fCollapsed) {
2168 break;
2169 }
2170 // trim parts that don't intersect the opposite
2171 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
caryclark643ede62016-08-08 14:27:45 -07002172 SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002173 if (!half2->split(largest2, &sect2->fHeap)) {
2174 break;
2175 }
caryclarka35ab3e2016-10-20 08:32:18 -07002176 if (!sect2->trim(largest2, sect1)) {
2177 SkOPOBJASSERT(intersections, 0);
2178 return;
2179 }
2180 if (!sect2->trim(half2, sect1)) {
2181 SkOPOBJASSERT(intersections, 0);
2182 return;
2183 }
caryclark45fa4472015-01-16 07:04:10 -08002184 }
caryclark54359292015-03-26 07:52:43 -07002185 sect1->validate();
2186 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002187#if DEBUG_T_SECT_LOOP_COUNT
2188 intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop);
2189#endif
caryclark45fa4472015-01-16 07:04:10 -08002190 // if there are 9 or more continuous spans on both sects, suspect coincidence
2191 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2192 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
caryclark26ad22a2015-10-16 09:03:38 -07002193 if (coinLoopCount == kMaxCoinLoopCount) {
2194 start1s = sect1->fHead->fStartT;
2195 start1e = sect1->tail()->fEndT;
2196 }
caryclarkef7cee42016-09-06 09:05:54 -07002197 if (!sect1->coincidentCheck(sect2)) {
2198 return;
2199 }
caryclark54359292015-03-26 07:52:43 -07002200 sect1->validate();
2201 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002202#if DEBUG_T_SECT_LOOP_COUNT
2203 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop);
2204#endif
caryclarkef784fb2015-10-30 12:03:06 -07002205 if (!--coinLoopCount && sect1->fHead && sect2->fHead) {
caryclark26ad22a2015-10-16 09:03:38 -07002206 /* All known working cases resolve in two tries. Sadly, cubicConicTests[0]
2207 gets stuck in a loop. It adds an extension to allow a coincident end
2208 perpendicular to track its intersection in the opposite curve. However,
2209 the bounding box of the extension does not intersect the original curve,
caryclark55888e42016-07-18 10:01:36 -07002210 so the extension is discarded, only to be added again the next time around. */
caryclark26ad22a2015-10-16 09:03:38 -07002211 sect1->coincidentForce(sect2, start1s, start1e);
2212 sect1->validate();
2213 sect2->validate();
2214 }
caryclark45fa4472015-01-16 07:04:10 -08002215 }
caryclark54359292015-03-26 07:52:43 -07002216 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2217 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
2218 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail());
2219 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail());
2220 sect1->removeByPerpendicular(sect2);
2221 sect1->validate();
2222 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002223#if DEBUG_T_SECT_LOOP_COUNT
2224 intersections->debugBumpLoopCount(SkIntersections::kComputePerp_DebugLoop);
2225#endif
caryclark1049f122015-04-20 08:31:59 -07002226 if (sect1->collapsed() > TCurve::kMaxIntersections) {
2227 break;
2228 }
caryclark54359292015-03-26 07:52:43 -07002229 }
2230#if DEBUG_T_SECT_DUMP
2231 sect1->dumpBoth(sect2);
caryclark45fa4472015-01-16 07:04:10 -08002232#endif
2233 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002234 break;
caryclark45fa4472015-01-16 07:04:10 -08002235 }
2236 } while (true);
caryclark1049f122015-04-20 08:31:59 -07002237 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident;
caryclark54359292015-03-26 07:52:43 -07002238 if (coincident) {
2239 // if there is more than one coincident span, check loosely to see if they should be joined
2240 if (coincident->fNext) {
2241 sect1->mergeCoincidence(sect2);
2242 coincident = sect1->fCoincident;
2243 }
2244 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1
caryclark45fa4472015-01-16 07:04:10 -08002245 do {
caryclark221a4bb2016-10-07 11:15:15 -07002246 if (!coincident) {
2247 return;
2248 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002249 if (!coincident->fCoinStart.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002250 continue;
2251 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002252 if (!coincident->fCoinEnd.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002253 continue;
2254 }
caryclark54359292015-03-26 07:52:43 -07002255 int index = intersections->insertCoincident(coincident->fStartT,
2256 coincident->fCoinStart.perpT(), coincident->fPart[0]);
2257 if ((intersections->insertCoincident(coincident->fEndT,
2258 coincident->fCoinEnd.perpT(),
2259 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) {
caryclark45fa4472015-01-16 07:04:10 -08002260 intersections->clearCoincidence(index);
2261 }
caryclark54359292015-03-26 07:52:43 -07002262 } while ((coincident = coincident->fNext));
2263 }
caryclark1049f122015-04-20 08:31:59 -07002264 int zeroOneSet = EndsEqual(sect1, sect2, intersections);
caryclark54359292015-03-26 07:52:43 -07002265 if (!sect1->fHead || !sect2->fHead) {
caryclark6c3b9cd2016-09-26 05:36:58 -07002266 // if the final iteration contains an end (0 or 1),
2267 if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) {
2268 SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular with opposite curve
caryclarka35ab3e2016-10-20 08:32:18 -07002269 perp.setPerp(sect1->fCurve, 0, sect1->fCurve[0], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002270 if (perp.isMatch()) {
2271 intersections->insert(0, perp.perpT(), perp.perpPt());
2272 }
2273 }
2274 if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) {
2275 SkTCoincident<TCurve, OppCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002276 perp.setPerp(sect1->fCurve, 1, sect1->fCurve[TCurve::kPointLast], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002277 if (perp.isMatch()) {
2278 intersections->insert(1, perp.perpT(), perp.perpPt());
2279 }
2280 }
2281 if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) {
2282 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002283 perp.setPerp(sect2->fCurve, 0, sect2->fCurve[0], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002284 if (perp.isMatch()) {
2285 intersections->insert(perp.perpT(), 0, perp.perpPt());
2286 }
2287 }
2288 if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) {
2289 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002290 perp.setPerp(sect2->fCurve, 1, sect2->fCurve[OppCurve::kPointLast], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002291 if (perp.isMatch()) {
2292 intersections->insert(perp.perpT(), 1, perp.perpPt());
2293 }
2294 }
caryclark54359292015-03-26 07:52:43 -07002295 return;
caryclark45fa4472015-01-16 07:04:10 -08002296 }
caryclark45fa4472015-01-16 07:04:10 -08002297 sect1->recoverCollapsed();
2298 sect2->recoverCollapsed();
caryclark1049f122015-04-20 08:31:59 -07002299 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002300 // check heads and tails for zero and ones and insert them if we haven't already done so
caryclark1049f122015-04-20 08:31:59 -07002301 const SkTSpan<TCurve, OppCurve>* head1 = result1;
caryclark45fa4472015-01-16 07:04:10 -08002302 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) {
2303 const SkDPoint& start1 = sect1->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002304 if (head1->isBounded()) {
2305 double t = head1->closestBoundedT(start1);
2306 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) {
2307 intersections->insert(0, t, start1);
2308 }
caryclark45fa4472015-01-16 07:04:10 -08002309 }
2310 }
caryclark1049f122015-04-20 08:31:59 -07002311 const SkTSpan<OppCurve, TCurve>* head2 = sect2->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002312 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) {
2313 const SkDPoint& start2 = sect2->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002314 if (head2->isBounded()) {
2315 double t = head2->closestBoundedT(start2);
2316 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) {
2317 intersections->insert(t, 0, start2);
2318 }
caryclark45fa4472015-01-16 07:04:10 -08002319 }
2320 }
caryclark1049f122015-04-20 08:31:59 -07002321 const SkTSpan<TCurve, OppCurve>* tail1 = sect1->tail();
caryclark45fa4472015-01-16 07:04:10 -08002322 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT)) {
2323 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002324 if (tail1->isBounded()) {
2325 double t = tail1->closestBoundedT(end1);
2326 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) {
2327 intersections->insert(1, t, end1);
2328 }
caryclark45fa4472015-01-16 07:04:10 -08002329 }
2330 }
caryclark1049f122015-04-20 08:31:59 -07002331 const SkTSpan<OppCurve, TCurve>* tail2 = sect2->tail();
caryclark45fa4472015-01-16 07:04:10 -08002332 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT)) {
caryclark1049f122015-04-20 08:31:59 -07002333 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002334 if (tail2->isBounded()) {
2335 double t = tail2->closestBoundedT(end2);
2336 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
2337 intersections->insert(t, 1, end2);
2338 }
caryclark45fa4472015-01-16 07:04:10 -08002339 }
2340 }
caryclark1049f122015-04-20 08:31:59 -07002341 SkClosestSect<TCurve, OppCurve> closest;
caryclark45fa4472015-01-16 07:04:10 -08002342 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07002343 while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) {
caryclark45fa4472015-01-16 07:04:10 -08002344 result1 = result1->fNext;
2345 }
2346 if (!result1) {
2347 break;
2348 }
caryclark1049f122015-04-20 08:31:59 -07002349 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002350 bool found = false;
caryclark45fa4472015-01-16 07:04:10 -08002351 while (result2) {
caryclarkcdeff812016-07-22 03:34:19 -07002352 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections));
caryclark45fa4472015-01-16 07:04:10 -08002353 result2 = result2->fNext;
2354 }
caryclark45fa4472015-01-16 07:04:10 -08002355 } while ((result1 = result1->fNext));
2356 closest.finish(intersections);
caryclark54359292015-03-26 07:52:43 -07002357 // if there is more than one intersection and it isn't already coincident, check
2358 int last = intersections->used() - 1;
2359 for (int index = 0; index < last; ) {
2360 if (intersections->isCoincident(index) && intersections->isCoincident(index + 1)) {
2361 ++index;
2362 continue;
2363 }
2364 double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
2365 SkDPoint midPt = sect1->fCurve.ptAtT(midT);
2366 // intersect perpendicular with opposite curve
caryclark1049f122015-04-20 08:31:59 -07002367 SkTCoincident<TCurve, OppCurve> perp;
caryclark54359292015-03-26 07:52:43 -07002368 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002369 if (!perp.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07002370 ++index;
2371 continue;
2372 }
2373 if (intersections->isCoincident(index)) {
2374 intersections->removeOne(index);
2375 --last;
2376 } else if (intersections->isCoincident(index + 1)) {
2377 intersections->removeOne(index + 1);
2378 --last;
2379 } else {
2380 intersections->setCoincident(index++);
2381 }
2382 intersections->setCoincident(index);
2383 }
caryclarka35ab3e2016-10-20 08:32:18 -07002384 SkOPOBJASSERT(intersections, intersections->used() <= TCurve::kMaxIntersections);
caryclark45fa4472015-01-16 07:04:10 -08002385}
deanm12670eb2016-04-26 14:09:01 -07002386
2387#endif