blob: 4dc2b34bb779cc288725d2da8ec419d3304075a6 [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
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050010#include "SkArenaAlloc.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
Cary Clark0949bee2018-03-19 09:42:00 -040022static inline bool SkDoubleIsNaN(double x) {
23 return x != x;
24}
25
caryclark1049f122015-04-20 08:31:59 -070026/* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */
27template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080028class SkTCoincident {
29public:
caryclark697ac1c2015-04-13 09:36:01 -070030 SkTCoincident() {
caryclarkdf386c52015-04-21 05:27:02 -070031 this->init();
caryclark1049f122015-04-20 08:31:59 -070032 }
33
caryclarked0935a2015-10-22 07:23:52 -070034 void debugInit() {
35#ifdef SK_DEBUG
36 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
37 this->fPerpT = SK_ScalarNaN;
caryclark6c3b9cd2016-09-26 05:36:58 -070038 this->fMatch = 0xFF;
caryclarked0935a2015-10-22 07:23:52 -070039#endif
40 }
41
42 char dumpIsCoincidentStr() const;
caryclark1049f122015-04-20 08:31:59 -070043 void dump() const;
44
caryclark6c3b9cd2016-09-26 05:36:58 -070045 bool isMatch() const {
46 SkASSERT(!!fMatch == fMatch);
47 return SkToBool(fMatch);
caryclark45fa4472015-01-16 07:04:10 -080048 }
49
50 void init() {
caryclarkdf386c52015-04-21 05:27:02 -070051 fPerpT = -1;
caryclark6c3b9cd2016-09-26 05:36:58 -070052 fMatch = false;
caryclarkdf386c52015-04-21 05:27:02 -070053 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
caryclark45fa4472015-01-16 07:04:10 -080054 }
55
56 void markCoincident() {
caryclark6c3b9cd2016-09-26 05:36:58 -070057 if (!fMatch) {
caryclark45fa4472015-01-16 07:04:10 -080058 fPerpT = -1;
59 }
caryclark6c3b9cd2016-09-26 05:36:58 -070060 fMatch = true;
caryclark45fa4472015-01-16 07:04:10 -080061 }
62
63 const SkDPoint& perpPt() const {
64 return fPerpPt;
65 }
66
67 double perpT() const {
68 return fPerpT;
69 }
70
caryclark1049f122015-04-20 08:31:59 -070071 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve& );
caryclark45fa4472015-01-16 07:04:10 -080072
73private:
74 SkDPoint fPerpPt;
75 double fPerpT; // perpendicular intersection on opposite curve
caryclark6c3b9cd2016-09-26 05:36:58 -070076 SkOpDebugBool fMatch;
caryclark45fa4472015-01-16 07:04:10 -080077};
78
caryclark1049f122015-04-20 08:31:59 -070079template<typename TCurve, typename OppCurve> class SkTSect;
80template<typename TCurve, typename OppCurve> class SkTSpan;
caryclark54359292015-03-26 07:52:43 -070081
caryclark1049f122015-04-20 08:31:59 -070082template<typename TCurve, typename OppCurve>
caryclark54359292015-03-26 07:52:43 -070083struct SkTSpanBounded {
caryclark1049f122015-04-20 08:31:59 -070084 SkTSpan<TCurve, OppCurve>* fBounded;
caryclark54359292015-03-26 07:52:43 -070085 SkTSpanBounded* fNext;
86};
caryclark45fa4472015-01-16 07:04:10 -080087
88/* Curve is either TCurve or SkDCubic */
caryclark1049f122015-04-20 08:31:59 -070089template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080090class SkTSpan {
91public:
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050092 void addBounded(SkTSpan<OppCurve, TCurve>* , SkArenaAlloc* );
reed0dc4dd62015-03-24 13:55:33 -070093 double closestBoundedT(const SkDPoint& pt) const;
caryclark54359292015-03-26 07:52:43 -070094 bool contains(double t) const;
reed0dc4dd62015-03-24 13:55:33 -070095
caryclark1049f122015-04-20 08:31:59 -070096 void debugInit() {
97 TCurve dummy;
98 dummy.debugInit();
99 init(dummy);
100 initBounds(dummy);
caryclarkdf386c52015-04-21 05:27:02 -0700101 fCoinStart.init();
102 fCoinEnd.init();
caryclark1049f122015-04-20 08:31:59 -0700103 }
104
105 const SkTSect<OppCurve, TCurve>* debugOpp() const;
caryclark643ede62016-08-08 14:27:45 -0700106
107#ifdef SK_DEBUG
108 void debugSetGlobalState(SkOpGlobalState* state) {
109 fDebugGlobalState = state;
110 }
111#endif
112
caryclark54359292015-03-26 07:52:43 -0700113 const SkTSpan* debugSpan(int ) const;
114 const SkTSpan* debugT(double t) const;
115#ifdef SK_DEBUG
116 bool debugIsBefore(const SkTSpan* span) const;
117#endif
118 void dump() const;
caryclark26ad22a2015-10-16 09:03:38 -0700119 void dumpAll() const;
caryclark1049f122015-04-20 08:31:59 -0700120 void dumpBounded(int id) const;
121 void dumpBounds() const;
122 void dumpCoin() const;
caryclark45fa4472015-01-16 07:04:10 -0800123
124 double endT() const {
125 return fEndT;
126 }
127
caryclark1049f122015-04-20 08:31:59 -0700128 SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp) const;
caryclark54359292015-03-26 07:52:43 -0700129
caryclark1049f122015-04-20 08:31:59 -0700130 SkTSpan<OppCurve, TCurve>* findOppT(double t) const {
131 SkTSpan<OppCurve, TCurve>* result = oppT(t);
caryclark643ede62016-08-08 14:27:45 -0700132 SkOPASSERT(result);
caryclark45fa4472015-01-16 07:04:10 -0800133 return result;
134 }
135
caryclark643ede62016-08-08 14:27:45 -0700136 SkDEBUGCODE(SkOpGlobalState* globalState() const { return fDebugGlobalState; })
137
caryclark54359292015-03-26 07:52:43 -0700138 bool hasOppT(double t) const {
139 return SkToBool(oppT(t));
140 }
141
caryclark1049f122015-04-20 08:31:59 -0700142 int hullsIntersect(SkTSpan<OppCurve, TCurve>* span, bool* start, bool* oppStart);
caryclark54359292015-03-26 07:52:43 -0700143 void init(const TCurve& );
caryclarka35ab3e2016-10-20 08:32:18 -0700144 bool initBounds(const TCurve& );
caryclark54359292015-03-26 07:52:43 -0700145
146 bool isBounded() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700147 return fBounded != nullptr;
caryclark54359292015-03-26 07:52:43 -0700148 }
149
caryclark1049f122015-04-20 08:31:59 -0700150 bool linearsIntersect(SkTSpan<OppCurve, TCurve>* span);
caryclark54359292015-03-26 07:52:43 -0700151 double linearT(const SkDPoint& ) const;
152
153 void markCoincident() {
154 fCoinStart.markCoincident();
155 fCoinEnd.markCoincident();
156 }
caryclark45fa4472015-01-16 07:04:10 -0800157
158 const SkTSpan* next() const {
159 return fNext;
160 }
161
caryclark1049f122015-04-20 08:31:59 -0700162 bool onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp, bool* start,
163 bool* oppStart, bool* ptsInCommon);
caryclark54359292015-03-26 07:52:43 -0700164
caryclark45fa4472015-01-16 07:04:10 -0800165 const TCurve& part() const {
166 return fPart;
167 }
168
caryclark54359292015-03-26 07:52:43 -0700169 bool removeAllBounded();
caryclark1049f122015-04-20 08:31:59 -0700170 bool removeBounded(const SkTSpan<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700171
caryclark45fa4472015-01-16 07:04:10 -0800172 void reset() {
halcanary96fcdcc2015-08-27 07:41:13 -0700173 fBounded = nullptr;
caryclark45fa4472015-01-16 07:04:10 -0800174 }
175
caryclark54359292015-03-26 07:52:43 -0700176 void resetBounds(const TCurve& curve) {
177 fIsLinear = fIsLine = false;
178 initBounds(curve);
caryclark45fa4472015-01-16 07:04:10 -0800179 }
180
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500181 bool split(SkTSpan* work, SkArenaAlloc* heap) {
caryclark54359292015-03-26 07:52:43 -0700182 return splitAt(work, (work->fStartT + work->fEndT) * 0.5, heap);
183 }
184
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500185 bool splitAt(SkTSpan* work, double t, SkArenaAlloc* heap);
caryclark45fa4472015-01-16 07:04:10 -0800186
187 double startT() const {
188 return fStartT;
189 }
190
caryclark54359292015-03-26 07:52:43 -0700191private:
caryclark45fa4472015-01-16 07:04:10 -0800192
193 // implementation is for testing only
caryclark54359292015-03-26 07:52:43 -0700194 int debugID() const {
195 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
caryclark45fa4472015-01-16 07:04:10 -0800196 }
197
caryclark54359292015-03-26 07:52:43 -0700198 void dumpID() const;
caryclark45fa4472015-01-16 07:04:10 -0800199
caryclark1049f122015-04-20 08:31:59 -0700200 int hullCheck(const SkTSpan<OppCurve, TCurve>* opp, bool* start, bool* oppStart);
201 int linearIntersects(const OppCurve& ) const;
202 SkTSpan<OppCurve, TCurve>* oppT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800203
caryclark45fa4472015-01-16 07:04:10 -0800204 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700205 void validateBounded() const;
206 void validatePerpT(double oppT) const;
207 void validatePerpPt(double t, const SkDPoint& ) const;
caryclark45fa4472015-01-16 07:04:10 -0800208
209 TCurve fPart;
caryclark1049f122015-04-20 08:31:59 -0700210 SkTCoincident<TCurve, OppCurve> fCoinStart;
211 SkTCoincident<TCurve, OppCurve> fCoinEnd;
212 SkTSpanBounded<OppCurve, TCurve>* fBounded;
caryclark45fa4472015-01-16 07:04:10 -0800213 SkTSpan* fPrev;
214 SkTSpan* fNext;
215 SkDRect fBounds;
216 double fStartT;
217 double fEndT;
218 double fBoundsMax;
caryclarked0935a2015-10-22 07:23:52 -0700219 SkOpDebugBool fCollapsed;
220 SkOpDebugBool fHasPerp;
221 SkOpDebugBool fIsLinear;
222 SkOpDebugBool fIsLine;
223 SkOpDebugBool fDeleted;
caryclark643ede62016-08-08 14:27:45 -0700224 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700225 SkDEBUGCODE(SkTSect<TCurve, OppCurve>* fDebugSect);
caryclark54359292015-03-26 07:52:43 -0700226 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
caryclark1049f122015-04-20 08:31:59 -0700227 friend class SkTSect<TCurve, OppCurve>;
228 friend class SkTSect<OppCurve, TCurve>;
229 friend class SkTSpan<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800230};
231
caryclark1049f122015-04-20 08:31:59 -0700232template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -0800233class SkTSect {
234public:
caryclarke25a4f62016-07-26 09:26:29 -0700235 SkTSect(const TCurve& c SkDEBUGPARAMS(SkOpGlobalState* ) PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
caryclark1049f122015-04-20 08:31:59 -0700236 static void BinarySearch(SkTSect* sect1, SkTSect<OppCurve, TCurve>* sect2,
237 SkIntersections* intersections);
caryclark45fa4472015-01-16 07:04:10 -0800238
caryclarke25a4f62016-07-26 09:26:29 -0700239 SkDEBUGCODE(SkOpGlobalState* globalState() { return fDebugGlobalState; })
Cary Clark0949bee2018-03-19 09:42:00 -0400240 bool hasBounded(const SkTSpan<OppCurve, TCurve>* ) const;
caryclark54359292015-03-26 07:52:43 -0700241
caryclark1049f122015-04-20 08:31:59 -0700242 const SkTSect<OppCurve, TCurve>* debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700243 return SkDEBUGRELEASE(fOppSect, nullptr);
caryclark54359292015-03-26 07:52:43 -0700244 }
245
caryclark1049f122015-04-20 08:31:59 -0700246 const SkTSpan<TCurve, OppCurve>* debugSpan(int id) const;
247 const SkTSpan<TCurve, OppCurve>* debugT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800248 void dump() const;
caryclark1049f122015-04-20 08:31:59 -0700249 void dumpBoth(SkTSect<OppCurve, TCurve>* ) const;
250 void dumpBounded(int id) const;
251 void dumpBounds() const;
caryclark54359292015-03-26 07:52:43 -0700252 void dumpCoin() const;
253 void dumpCoinCurves() const;
caryclark45fa4472015-01-16 07:04:10 -0800254 void dumpCurves() const;
255
256private:
257 enum {
258 kZeroS1Set = 1,
259 kOneS1Set = 2,
260 kZeroS2Set = 4,
261 kOneS2Set = 8
262 };
263
caryclark1049f122015-04-20 08:31:59 -0700264 SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior);
265 void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t);
266 SkTSpan<TCurve, OppCurve>* addOne();
caryclark55888e42016-07-18 10:01:36 -0700267
caryclark1049f122015-04-20 08:31:59 -0700268 SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, double t) {
269 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700270 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700271 result->splitAt(span, t, &fHeap);
272 result->initBounds(fCurve);
273 span->initBounds(fCurve);
274 return result;
275 }
276
caryclark1049f122015-04-20 08:31:59 -0700277 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
Cary Clark74b42902018-03-09 07:38:47 -0500278 double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst);
caryclark1049f122015-04-20 08:31:59 -0700279 SkTSpan<TCurve, OppCurve>* boundsMax() const;
caryclarkef7cee42016-09-06 09:05:54 -0700280 bool coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
caryclark26ad22a2015-10-16 09:03:38 -0700281 void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, double start1e);
caryclark54359292015-03-26 07:52:43 -0700282 bool coincidentHasT(double t);
caryclark1049f122015-04-20 08:31:59 -0700283 int collapsed() const;
284 void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
285 SkTSpan<TCurve, OppCurve>* last);
286 int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
287 SkTSpan<TCurve, OppCurve>** last) const;
caryclarkccec0f92015-03-24 07:28:17 -0700288
caryclark54359292015-03-26 07:52:43 -0700289 int debugID() const {
290 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
291 }
292
caryclarkef7cee42016-09-06 09:05:54 -0700293 bool deleteEmptySpans();
caryclark1049f122015-04-20 08:31:59 -0700294 void dumpCommon(const SkTSpan<TCurve, OppCurve>* ) const;
295 void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const;
296 static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2,
297 SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700298 bool extractCoincident(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
299 SkTSpan<TCurve, OppCurve>* last, SkTSpan<TCurve, OppCurve>** result);
caryclark1049f122015-04-20 08:31:59 -0700300 SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* first,
301 SkTSpan<TCurve, OppCurve>** lastPtr);
302 int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
303 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult);
caryclarked0935a2015-10-22 07:23:52 -0700304 bool isParallel(const SkDLine& thisLine, const SkTSect<OppCurve, TCurve>* opp) const;
caryclark1049f122015-04-20 08:31:59 -0700305 int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
306 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700307 bool markSpanGone(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700308 bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2) const;
309 void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2,
caryclark54359292015-03-26 07:52:43 -0700310 bool* calcMatched, bool* oppMatched) const;
caryclark1049f122015-04-20 08:31:59 -0700311 void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2);
312 SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const;
Cary Clark0949bee2018-03-19 09:42:00 -0400313 bool removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700314 void recoverCollapsed();
Cary Clark38702ab2017-09-05 18:11:55 -0400315 bool removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween);
caryclark1049f122015-04-20 08:31:59 -0700316 void removeAllBut(const SkTSpan<OppCurve, TCurve>* keep, SkTSpan<TCurve, OppCurve>* span,
317 SkTSect<OppCurve, TCurve>* opp);
caryclarkef7cee42016-09-06 09:05:54 -0700318 bool removeSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700319 void removeSpanRange(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last);
Cary Clark0949bee2018-03-19 09:42:00 -0400320 bool removeSpans(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
caryclark34efb702016-10-24 08:19:06 -0700321 void removedEndCheck(SkTSpan<TCurve, OppCurve>* span);
322
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500323 void resetRemovedEnds() {
caryclark34efb702016-10-24 08:19:06 -0700324 fRemovedStartT = fRemovedEndT = false;
325 }
326
caryclark1049f122015-04-20 08:31:59 -0700327 SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
328 SkTSpan<TCurve, OppCurve>* tail();
caryclarka35ab3e2016-10-20 08:32:18 -0700329 bool trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
Cary Clark38702ab2017-09-05 18:11:55 -0400330 bool unlinkSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700331 bool updateBounded(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
332 SkTSpan<OppCurve, TCurve>* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700333 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700334 void validateBounded() const;
335
caryclark45fa4472015-01-16 07:04:10 -0800336 const TCurve& fCurve;
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500337 SkArenaAlloc fHeap;
caryclark1049f122015-04-20 08:31:59 -0700338 SkTSpan<TCurve, OppCurve>* fHead;
339 SkTSpan<TCurve, OppCurve>* fCoincident;
340 SkTSpan<TCurve, OppCurve>* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800341 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700342 bool fRemovedStartT;
343 bool fRemovedEndT;
caryclarke25a4f62016-07-26 09:26:29 -0700344 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700345 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700346 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
347 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800348#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800349 int fDebugAllocatedCount;
350#endif
caryclark1049f122015-04-20 08:31:59 -0700351 friend class SkTSpan<TCurve, OppCurve>;
352 friend class SkTSpan<OppCurve, TCurve>;
353 friend class SkTSect<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800354};
355
356#define COINCIDENT_SPAN_COUNT 9
357
caryclark1049f122015-04-20 08:31:59 -0700358template<typename TCurve, typename OppCurve>
359void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t,
360 const SkDPoint& cPt, const OppCurve& c2) {
caryclark45fa4472015-01-16 07:04:10 -0800361 SkDVector dxdy = c1.dxdyAtT(t);
362 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
caryclarka35ab3e2016-10-20 08:32:18 -0700363 SkIntersections i SkDEBUGCODE((c1.globalState()));
caryclark45fa4472015-01-16 07:04:10 -0800364 int used = i.intersectRay(c2, perp);
365 // only keep closest
caryclark54359292015-03-26 07:52:43 -0700366 if (used == 0 || used == 3) {
caryclarkdf386c52015-04-21 05:27:02 -0700367 this->init();
caryclark45fa4472015-01-16 07:04:10 -0800368 return;
caryclark55888e42016-07-18 10:01:36 -0700369 }
caryclark45fa4472015-01-16 07:04:10 -0800370 fPerpT = i[0][0];
371 fPerpPt = i.pt(0);
372 SkASSERT(used <= 2);
373 if (used == 2) {
374 double distSq = (fPerpPt - cPt).lengthSquared();
375 double dist2Sq = (i.pt(1) - cPt).lengthSquared();
376 if (dist2Sq < distSq) {
377 fPerpT = i[0][1];
378 fPerpPt = i.pt(1);
379 }
380 }
caryclark54359292015-03-26 07:52:43 -0700381#if DEBUG_T_SECT
caryclark1049f122015-04-20 08:31:59 -0700382 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n",
383 t, cPt.fX, cPt.fY,
384 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY);
caryclark54359292015-03-26 07:52:43 -0700385#endif
caryclark6c3b9cd2016-09-26 05:36:58 -0700386 fMatch = cPt.approximatelyEqual(fPerpPt);
caryclark45fa4472015-01-16 07:04:10 -0800387#if DEBUG_T_SECT
caryclark6c3b9cd2016-09-26 05:36:58 -0700388 if (fMatch) {
caryclark45fa4472015-01-16 07:04:10 -0800389 SkDebugf(""); // allow setting breakpoint
390 }
391#endif
392}
393
caryclark1049f122015-04-20 08:31:59 -0700394template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500395void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkArenaAlloc* heap) {
396 SkTSpanBounded<OppCurve, TCurve>* bounded = heap->make<SkTSpanBounded<OppCurve, TCurve>>();
caryclark54359292015-03-26 07:52:43 -0700397 bounded->fBounded = span;
398 bounded->fNext = fBounded;
399 fBounded = bounded;
400}
401
caryclark1049f122015-04-20 08:31:59 -0700402template<typename TCurve, typename OppCurve>
403SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing(
404 SkTSpan<TCurve, OppCurve>* prior) {
405 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700406 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700407 result->fStartT = prior ? prior->fEndT : 0;
caryclark1049f122015-04-20 08:31:59 -0700408 SkTSpan<TCurve, OppCurve>* next = prior ? prior->fNext : fHead;
caryclark54359292015-03-26 07:52:43 -0700409 result->fEndT = next ? next->fStartT : 1;
410 result->fPrev = prior;
411 result->fNext = next;
412 if (prior) {
413 prior->fNext = result;
414 } else {
415 fHead = result;
416 }
417 if (next) {
418 next->fPrev = result;
419 }
420 result->resetBounds(fCurve);
Cary Clarkb8421ed2018-03-14 15:55:02 -0400421 // world may not be consistent to call validate here
caryclark643ede62016-08-08 14:27:45 -0700422 result->validate();
caryclark54359292015-03-26 07:52:43 -0700423 return result;
424}
425
caryclark1049f122015-04-20 08:31:59 -0700426template<typename TCurve, typename OppCurve>
427void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, double t) {
caryclark54359292015-03-26 07:52:43 -0700428 if (!span->hasOppT(t)) {
caryclark1049f122015-04-20 08:31:59 -0700429 SkTSpan<TCurve, OppCurve>* priorSpan;
430 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan);
caryclark54359292015-03-26 07:52:43 -0700431 if (!opp) {
432 opp = this->addFollowing(priorSpan);
433#if DEBUG_PERP
caryclark26ad22a2015-10-16 09:03:38 -0700434 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ?
435 priorSpan->debugID() : -1, t, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700436#endif
437 }
438#if DEBUG_PERP
439 opp->dump(); SkDebugf("\n");
caryclark26ad22a2015-10-16 09:03:38 -0700440 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ?
441 priorSpan->debugID() : -1, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700442#endif
443 opp->addBounded(span, &fHeap);
444 span->addBounded(opp, &fHeap);
445 }
446 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700447#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700448 span->validatePerpT(t);
caryclark1049f122015-04-20 08:31:59 -0700449#endif
caryclark54359292015-03-26 07:52:43 -0700450}
451
caryclark1049f122015-04-20 08:31:59 -0700452template<typename TCurve, typename OppCurve>
453double SkTSpan<TCurve, OppCurve>::closestBoundedT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700454 double result = -1;
caryclark343382e2016-06-29 08:18:38 -0700455 double closest = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -0700456 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700457 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700458 const SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700459 double startDist = test->fPart[0].distanceSquared(pt);
460 if (closest > startDist) {
461 closest = startDist;
462 result = test->fStartT;
463 }
caryclark1049f122015-04-20 08:31:59 -0700464 double endDist = test->fPart[OppCurve::kPointLast].distanceSquared(pt);
caryclark54359292015-03-26 07:52:43 -0700465 if (closest > endDist) {
466 closest = endDist;
467 result = test->fEndT;
468 }
469 testBounded = testBounded->fNext;
470 }
471 SkASSERT(between(0, result, 1));
472 return result;
473}
474
475#ifdef SK_DEBUG
caryclark1049f122015-04-20 08:31:59 -0700476template<typename TCurve, typename OppCurve>
477bool SkTSpan<TCurve, OppCurve>::debugIsBefore(const SkTSpan* span) const {
caryclark54359292015-03-26 07:52:43 -0700478 const SkTSpan* work = this;
479 do {
480 if (span == work) {
481 return true;
482 }
483 } while ((work = work->fNext));
484 return false;
485}
486#endif
487
caryclark1049f122015-04-20 08:31:59 -0700488template<typename TCurve, typename OppCurve>
489bool SkTSpan<TCurve, OppCurve>::contains(double t) const {
caryclark54359292015-03-26 07:52:43 -0700490 const SkTSpan* work = this;
491 do {
492 if (between(work->fStartT, t, work->fEndT)) {
493 return true;
494 }
495 } while ((work = work->fNext));
496 return false;
497}
498
caryclark1049f122015-04-20 08:31:59 -0700499template<typename TCurve, typename OppCurve>
500const SkTSect<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700501 return SkDEBUGRELEASE(fDebugSect->debugOpp(), nullptr);
caryclark54359292015-03-26 07:52:43 -0700502}
503
caryclark1049f122015-04-20 08:31:59 -0700504template<typename TCurve, typename OppCurve>
505SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::findOppSpan(
506 const SkTSpan<OppCurve, TCurve>* opp) const {
507 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700508 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700509 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700510 if (opp == test) {
511 return test;
512 }
513 bounded = bounded->fNext;
514 }
halcanary96fcdcc2015-08-27 07:41:13 -0700515 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700516}
517
518// returns 0 if no hull intersection
519// 1 if hulls intersect
520// 2 if hulls only share a common endpoint
521// -1 if linear and further checking is required
caryclark1049f122015-04-20 08:31:59 -0700522template<typename TCurve, typename OppCurve>
523int SkTSpan<TCurve, OppCurve>::hullCheck(const SkTSpan<OppCurve, TCurve>* opp,
524 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700525 if (fIsLinear) {
526 return -1;
527 }
528 bool ptsInCommon;
529 if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) {
530 SkASSERT(ptsInCommon);
531 return 2;
532 }
533 bool linear;
534 if (fPart.hullIntersects(opp->fPart, &linear)) {
535 if (!linear) { // check set true if linear
536 return 1;
537 }
538 fIsLinear = true;
539 fIsLine = fPart.controlsInside();
caryclark2bec26a2016-05-26 09:01:47 -0700540 return ptsInCommon ? 1 : -1;
caryclark54359292015-03-26 07:52:43 -0700541 } else { // hull is not linear; check set true if intersected at the end points
542 return ((int) ptsInCommon) << 1; // 0 or 2
543 }
544 return 0;
545}
546
547// OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
548// use line intersection to guess a better split than 0.5
549// OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear
caryclark1049f122015-04-20 08:31:59 -0700550template<typename TCurve, typename OppCurve>
551int SkTSpan<TCurve, OppCurve>::hullsIntersect(SkTSpan<OppCurve, TCurve>* opp,
552 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700553 if (!fBounds.intersects(opp->fBounds)) {
554 return 0;
555 }
556 int hullSect = this->hullCheck(opp, start, oppStart);
557 if (hullSect >= 0) {
558 return hullSect;
559 }
560 hullSect = opp->hullCheck(this, oppStart, start);
561 if (hullSect >= 0) {
562 return hullSect;
563 }
564 return -1;
565}
566
caryclark1049f122015-04-20 08:31:59 -0700567template<typename TCurve, typename OppCurve>
568void SkTSpan<TCurve, OppCurve>::init(const TCurve& c) {
halcanary96fcdcc2015-08-27 07:41:13 -0700569 fPrev = fNext = nullptr;
reed0dc4dd62015-03-24 13:55:33 -0700570 fStartT = 0;
571 fEndT = 1;
halcanary96fcdcc2015-08-27 07:41:13 -0700572 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700573 resetBounds(c);
caryclark45fa4472015-01-16 07:04:10 -0800574}
575
caryclark1049f122015-04-20 08:31:59 -0700576template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -0700577bool SkTSpan<TCurve, OppCurve>::initBounds(const TCurve& c) {
Cary Clark0949bee2018-03-19 09:42:00 -0400578 if (SkDoubleIsNaN(fStartT) || SkDoubleIsNaN(fEndT)) {
579 return false;
580 }
reed0dc4dd62015-03-24 13:55:33 -0700581 fPart = c.subDivide(fStartT, fEndT);
582 fBounds.setBounds(fPart);
583 fCoinStart.init();
584 fCoinEnd.init();
585 fBoundsMax = SkTMax(fBounds.width(), fBounds.height());
586 fCollapsed = fPart.collapsed();
587 fHasPerp = false;
caryclark54359292015-03-26 07:52:43 -0700588 fDeleted = false;
reed0dc4dd62015-03-24 13:55:33 -0700589#if DEBUG_T_SECT
reed0dc4dd62015-03-24 13:55:33 -0700590 if (fCollapsed) {
591 SkDebugf(""); // for convenient breakpoints
caryclark45fa4472015-01-16 07:04:10 -0800592 }
593#endif
caryclarka35ab3e2016-10-20 08:32:18 -0700594 return fBounds.valid();
caryclark45fa4472015-01-16 07:04:10 -0800595}
596
caryclark1049f122015-04-20 08:31:59 -0700597template<typename TCurve, typename OppCurve>
598bool SkTSpan<TCurve, OppCurve>::linearsIntersect(SkTSpan<OppCurve, TCurve>* span) {
caryclark54359292015-03-26 07:52:43 -0700599 int result = this->linearIntersects(span->fPart);
600 if (result <= 1) {
601 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800602 }
caryclark54359292015-03-26 07:52:43 -0700603 SkASSERT(span->fIsLinear);
604 result = span->linearIntersects(this->fPart);
605// SkASSERT(result <= 1);
606 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800607}
608
caryclark1049f122015-04-20 08:31:59 -0700609template<typename TCurve, typename OppCurve>
610double SkTSpan<TCurve, OppCurve>::linearT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700611 SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
612 return fabs(len.fX) > fabs(len.fY)
613 ? (pt.fX - fPart[0].fX) / len.fX
614 : (pt.fY - fPart[0].fY) / len.fY;
caryclark45fa4472015-01-16 07:04:10 -0800615}
616
caryclark1049f122015-04-20 08:31:59 -0700617template<typename TCurve, typename OppCurve>
618int SkTSpan<TCurve, OppCurve>::linearIntersects(const OppCurve& q2) const {
caryclark45fa4472015-01-16 07:04:10 -0800619 // looks like q1 is near-linear
caryclark54359292015-03-26 07:52:43 -0700620 int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
caryclark45fa4472015-01-16 07:04:10 -0800621 if (!fPart.controlsInside()) {
622 double dist = 0; // if there's any question, compute distance to find best outsiders
623 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) {
624 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) {
625 double test = (fPart[outer] - fPart[inner]).lengthSquared();
626 if (dist > test) {
627 continue;
628 }
629 dist = test;
630 start = outer;
631 end = inner;
632 }
633 }
634 }
635 // see if q2 is on one side of the line formed by the extreme points
636 double origX = fPart[start].fX;
637 double origY = fPart[start].fY;
638 double adj = fPart[end].fX - origX;
639 double opp = fPart[end].fY - origY;
caryclark54359292015-03-26 07:52:43 -0700640 double maxPart = SkTMax(fabs(adj), fabs(opp));
641 double sign = 0; // initialization to shut up warning in release build
caryclark1049f122015-04-20 08:31:59 -0700642 for (int n = 0; n < OppCurve::kPointCount; ++n) {
caryclark54359292015-03-26 07:52:43 -0700643 double dx = q2[n].fY - origY;
644 double dy = q2[n].fX - origX;
645 double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
caryclark45fa4472015-01-16 07:04:10 -0800646 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp;
caryclark54359292015-03-26 07:52:43 -0700647 if (precisely_zero_when_compared_to(test, maxVal)) {
648 return 1;
649 }
650 if (approximately_zero_when_compared_to(test, maxVal)) {
651 return 3;
caryclark45fa4472015-01-16 07:04:10 -0800652 }
653 if (n == 0) {
654 sign = test;
655 continue;
656 }
657 if (test * sign < 0) {
caryclark54359292015-03-26 07:52:43 -0700658 return 1;
caryclark45fa4472015-01-16 07:04:10 -0800659 }
660 }
caryclark54359292015-03-26 07:52:43 -0700661 return 0;
662}
663
caryclark1049f122015-04-20 08:31:59 -0700664template<typename TCurve, typename OppCurve>
665bool SkTSpan<TCurve, OppCurve>::onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp,
666 bool* start, bool* oppStart, bool* ptsInCommon) {
caryclark54359292015-03-26 07:52:43 -0700667 if (opp->fPart[0] == fPart[0]) {
668 *start = *oppStart = true;
669 } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
670 *start = false;
671 *oppStart = true;
caryclark1049f122015-04-20 08:31:59 -0700672 } else if (opp->fPart[OppCurve::kPointLast] == fPart[0]) {
caryclark54359292015-03-26 07:52:43 -0700673 *start = true;
674 *oppStart = false;
caryclark1049f122015-04-20 08:31:59 -0700675 } else if (opp->fPart[OppCurve::kPointLast] == fPart[TCurve::kPointLast]) {
caryclark54359292015-03-26 07:52:43 -0700676 *start = *oppStart = false;
677 } else {
678 *ptsInCommon = false;
679 return false;
680 }
681 *ptsInCommon = true;
caryclark1049f122015-04-20 08:31:59 -0700682 const SkDPoint* otherPts[TCurve::kPointCount - 1], * oppOtherPts[OppCurve::kPointCount - 1];
caryclark54359292015-03-26 07:52:43 -0700683 int baseIndex = *start ? 0 : TCurve::kPointLast;
caryclark1049f122015-04-20 08:31:59 -0700684 fPart.otherPts(baseIndex, otherPts);
685 opp->fPart.otherPts(*oppStart ? 0 : OppCurve::kPointLast, oppOtherPts);
caryclark54359292015-03-26 07:52:43 -0700686 const SkDPoint& base = fPart[baseIndex];
caryclark1049f122015-04-20 08:31:59 -0700687 for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(otherPts); ++o1) {
688 SkDVector v1 = *otherPts[o1] - base;
689 for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(oppOtherPts); ++o2) {
690 SkDVector v2 = *oppOtherPts[o2] - base;
caryclark54359292015-03-26 07:52:43 -0700691 if (v2.dot(v1) >= 0) {
692 return false;
693 }
694 }
695 }
696 return true;
697}
698
caryclark1049f122015-04-20 08:31:59 -0700699template<typename TCurve, typename OppCurve>
700SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::oppT(double t) const {
701 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700702 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700703 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700704 if (between(test->fStartT, t, test->fEndT)) {
705 return test;
706 }
707 bounded = bounded->fNext;
708 }
halcanary96fcdcc2015-08-27 07:41:13 -0700709 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700710}
711
caryclark1049f122015-04-20 08:31:59 -0700712template<typename TCurve, typename OppCurve>
713bool SkTSpan<TCurve, OppCurve>::removeAllBounded() {
caryclark54359292015-03-26 07:52:43 -0700714 bool deleteSpan = false;
caryclark1049f122015-04-20 08:31:59 -0700715 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700716 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700717 SkTSpan<OppCurve, TCurve>* opp = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700718 deleteSpan |= opp->removeBounded(this);
719 bounded = bounded->fNext;
720 }
721 return deleteSpan;
722}
723
caryclark1049f122015-04-20 08:31:59 -0700724template<typename TCurve, typename OppCurve>
725bool SkTSpan<TCurve, OppCurve>::removeBounded(const SkTSpan<OppCurve, TCurve>* opp) {
caryclark54359292015-03-26 07:52:43 -0700726 if (fHasPerp) {
727 bool foundStart = false;
728 bool foundEnd = false;
caryclark1049f122015-04-20 08:31:59 -0700729 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700730 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700731 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700732 if (opp != test) {
733 foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT);
734 foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
735 }
736 bounded = bounded->fNext;
737 }
738 if (!foundStart || !foundEnd) {
739 fHasPerp = false;
740 fCoinStart.init();
741 fCoinEnd.init();
742 }
743 }
caryclark1049f122015-04-20 08:31:59 -0700744 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700745 SkTSpanBounded<OppCurve, TCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -0700746 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700747 SkTSpanBounded<OppCurve, TCurve>* boundedNext = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -0700748 if (opp == bounded->fBounded) {
749 if (prev) {
750 prev->fNext = boundedNext;
751 return false;
752 } else {
753 fBounded = boundedNext;
halcanary96fcdcc2015-08-27 07:41:13 -0700754 return fBounded == nullptr;
caryclark54359292015-03-26 07:52:43 -0700755 }
756 }
757 prev = bounded;
758 bounded = boundedNext;
759 }
caryclark643ede62016-08-08 14:27:45 -0700760 SkOPASSERT(0);
caryclark45fa4472015-01-16 07:04:10 -0800761 return false;
762}
763
caryclark1049f122015-04-20 08:31:59 -0700764template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500765bool SkTSpan<TCurve, OppCurve>::splitAt(SkTSpan* work, double t, SkArenaAlloc* heap) {
caryclark45fa4472015-01-16 07:04:10 -0800766 fStartT = t;
767 fEndT = work->fEndT;
768 if (fStartT == fEndT) {
769 fCollapsed = true;
770 return false;
771 }
772 work->fEndT = t;
773 if (work->fStartT == work->fEndT) {
774 work->fCollapsed = true;
775 return false;
776 }
777 fPrev = work;
778 fNext = work->fNext;
779 fIsLinear = work->fIsLinear;
caryclark54359292015-03-26 07:52:43 -0700780 fIsLine = work->fIsLine;
781
caryclark45fa4472015-01-16 07:04:10 -0800782 work->fNext = this;
783 if (fNext) {
784 fNext->fPrev = this;
785 }
caryclark643ede62016-08-08 14:27:45 -0700786 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700787 SkTSpanBounded<OppCurve, TCurve>* bounded = work->fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700788 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700789 while (bounded) {
790 this->addBounded(bounded->fBounded, heap);
791 bounded = bounded->fNext;
792 }
793 bounded = fBounded;
794 while (bounded) {
795 bounded->fBounded->addBounded(this, heap);
796 bounded = bounded->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800797 }
798 return true;
799}
800
caryclark1049f122015-04-20 08:31:59 -0700801template<typename TCurve, typename OppCurve>
802void SkTSpan<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -0700803#if DEBUG_VALIDATE
804 SkASSERT(this != fPrev);
805 SkASSERT(this != fNext);
halcanary96fcdcc2015-08-27 07:41:13 -0700806 SkASSERT(fNext == nullptr || fNext != fPrev);
807 SkASSERT(fNext == nullptr || this == fNext->fPrev);
808 SkASSERT(fPrev == nullptr || this == fPrev->fNext);
caryclark643ede62016-08-08 14:27:45 -0700809 this->validateBounded();
810#endif
811#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700812 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed);
caryclarke839e782016-09-15 07:48:18 -0700813 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollapsed == 0xFF);
caryclark45fa4472015-01-16 07:04:10 -0800814 SkASSERT(0 <= fStartT);
815 SkASSERT(fEndT <= 1);
caryclark54359292015-03-26 07:52:43 -0700816 SkASSERT(fStartT <= fEndT);
caryclarke839e782016-09-15 07:48:18 -0700817 SkASSERT(fBounded || fCollapsed == 0xFF);
caryclark54359292015-03-26 07:52:43 -0700818 if (fHasPerp) {
caryclark6c3b9cd2016-09-26 05:36:58 -0700819 if (fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700820 validatePerpT(fCoinStart.perpT());
821 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt());
822 }
caryclark6c3b9cd2016-09-26 05:36:58 -0700823 if (fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700824 validatePerpT(fCoinEnd.perpT());
825 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt());
826 }
caryclarkccec0f92015-03-24 07:28:17 -0700827 }
reed0dc4dd62015-03-24 13:55:33 -0700828#endif
caryclark54359292015-03-26 07:52:43 -0700829}
caryclarkccec0f92015-03-24 07:28:17 -0700830
caryclark1049f122015-04-20 08:31:59 -0700831template<typename TCurve, typename OppCurve>
832void SkTSpan<TCurve, OppCurve>::validateBounded() const {
caryclark54359292015-03-26 07:52:43 -0700833#if DEBUG_VALIDATE
caryclark1049f122015-04-20 08:31:59 -0700834 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700835 while (testBounded) {
csmartdaltonceeaa782016-08-10 10:07:57 -0700836 SkDEBUGCODE(const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded);
caryclark54359292015-03-26 07:52:43 -0700837 SkASSERT(!overlap->fDeleted);
caryclark643ede62016-08-08 14:27:45 -0700838#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700839 SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
840 SkASSERT(overlap->findOppSpan(this));
caryclark643ede62016-08-08 14:27:45 -0700841#endif
caryclark54359292015-03-26 07:52:43 -0700842 testBounded = testBounded->fNext;
843 }
844#endif
845}
846
caryclark1049f122015-04-20 08:31:59 -0700847template<typename TCurve, typename OppCurve>
848void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const {
849 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700850 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700851 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded;
caryclark26ad22a2015-10-16 09:03:38 -0700852 if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) {
caryclark54359292015-03-26 07:52:43 -0700853 return;
854 }
855 testBounded = testBounded->fNext;
856 }
857 SkASSERT(0);
caryclark54359292015-03-26 07:52:43 -0700858}
859
caryclark1049f122015-04-20 08:31:59 -0700860template<typename TCurve, typename OppCurve>
861void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
862 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt);
caryclark54359292015-03-26 07:52:43 -0700863}
864
865
caryclark1049f122015-04-20 08:31:59 -0700866template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500867SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
caryclarke25a4f62016-07-26 09:26:29 -0700868 SkDEBUGPARAMS(SkOpGlobalState* debugGlobalState)
869 PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
caryclark45fa4472015-01-16 07:04:10 -0800870 : fCurve(c)
caryclark1049f122015-04-20 08:31:59 -0700871 , fHeap(sizeof(SkTSpan<TCurve, OppCurve>) * 4)
halcanary96fcdcc2015-08-27 07:41:13 -0700872 , fCoincident(nullptr)
873 , fDeleted(nullptr)
caryclark45fa4472015-01-16 07:04:10 -0800874 , fActiveCount(0)
caryclarke25a4f62016-07-26 09:26:29 -0700875 SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState))
caryclark54359292015-03-26 07:52:43 -0700876 PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
877 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
878 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
caryclark45fa4472015-01-16 07:04:10 -0800879{
caryclark34efb702016-10-24 08:19:06 -0700880 this->resetRemovedEnds();
881 fHead = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700882 SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState));
caryclark45fa4472015-01-16 07:04:10 -0800883 fHead->init(c);
884}
885
caryclark1049f122015-04-20 08:31:59 -0700886template<typename TCurve, typename OppCurve>
887SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
888 SkTSpan<TCurve, OppCurve>* result;
caryclark45fa4472015-01-16 07:04:10 -0800889 if (fDeleted) {
890 result = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800891 fDeleted = result->fNext;
892 } else {
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500893 result = fHeap.make<SkTSpan<TCurve, OppCurve>>();
caryclark45fa4472015-01-16 07:04:10 -0800894#if DEBUG_T_SECT
895 ++fDebugAllocatedCount;
896#endif
897 }
caryclarked0935a2015-10-22 07:23:52 -0700898 result->reset();
caryclark08b32492015-04-06 11:41:29 -0700899 result->fHasPerp = false;
900 result->fDeleted = false;
caryclark55888e42016-07-18 10:01:36 -0700901 ++fActiveCount;
caryclark54359292015-03-26 07:52:43 -0700902 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
caryclark1049f122015-04-20 08:31:59 -0700903 SkDEBUGCODE(result->fDebugSect = this);
caryclarked0935a2015-10-22 07:23:52 -0700904#ifdef SK_DEBUG
905 result->fPart.debugInit();
906 result->fCoinStart.debugInit();
907 result->fCoinEnd.debugInit();
908 result->fPrev = result->fNext = nullptr;
909 result->fBounds.debugInit();
910 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN;
911 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF;
912#endif
caryclark45fa4472015-01-16 07:04:10 -0800913 return result;
914}
915
caryclark1049f122015-04-20 08:31:59 -0700916template<typename TCurve, typename OppCurve>
917bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
Cary Clark74b42902018-03-09 07:38:47 -0500918 double tStep, double* resultT, double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst) {
caryclark1049f122015-04-20 08:31:59 -0700919 SkTSpan<TCurve, OppCurve> work;
caryclark45fa4472015-01-16 07:04:10 -0800920 double result = work.fStartT = work.fEndT = tStart;
caryclark1049f122015-04-20 08:31:59 -0700921 SkDEBUGCODE(work.fDebugSect = this);
caryclark45fa4472015-01-16 07:04:10 -0800922 SkDPoint last = fCurve.ptAtT(tStart);
923 SkDPoint oppPt;
924 bool flip = false;
caryclarkcdeff812016-07-22 03:34:19 -0700925 bool contained = false;
Cary Clark74b42902018-03-09 07:38:47 -0500926 bool down = tStep < 0;
caryclark1049f122015-04-20 08:31:59 -0700927 const OppCurve& opp = sect2->fCurve;
caryclark45fa4472015-01-16 07:04:10 -0800928 do {
929 tStep *= 0.5;
930 work.fStartT += tStep;
931 if (flip) {
932 tStep = -tStep;
933 flip = false;
934 }
935 work.initBounds(fCurve);
936 if (work.fCollapsed) {
937 return false;
938 }
939 if (last.approximatelyEqual(work.fPart[0])) {
940 break;
941 }
942 last = work.fPart[0];
943 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp);
caryclark6c3b9cd2016-09-26 05:36:58 -0700944 if (work.fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700945#if DEBUG_T_SECT
946 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt());
947#endif
caryclark45fa4472015-01-16 07:04:10 -0800948 double oppTTest = work.fCoinStart.perpT();
caryclark54359292015-03-26 07:52:43 -0700949 if (sect2->fHead->contains(oppTTest)) {
caryclark45fa4472015-01-16 07:04:10 -0800950 *oppT = oppTTest;
951 oppPt = work.fCoinStart.perpPt();
caryclarkcdeff812016-07-22 03:34:19 -0700952 contained = true;
Cary Clark74b42902018-03-09 07:38:47 -0500953 if (down ? result <= work.fStartT : result >= work.fStartT) {
954 *oppFirst = nullptr; // signal caller to fail
955 return false;
956 }
caryclark45fa4472015-01-16 07:04:10 -0800957 result = work.fStartT;
958 continue;
959 }
960 }
961 tStep = -tStep;
962 flip = true;
963 } while (true);
caryclarkcdeff812016-07-22 03:34:19 -0700964 if (!contained) {
965 return false;
966 }
caryclark45fa4472015-01-16 07:04:10 -0800967 if (last.approximatelyEqual(fCurve[0])) {
968 result = 0;
969 } else if (last.approximatelyEqual(fCurve[TCurve::kPointLast])) {
970 result = 1;
971 }
972 if (oppPt.approximatelyEqual(opp[0])) {
973 *oppT = 0;
caryclark1049f122015-04-20 08:31:59 -0700974 } else if (oppPt.approximatelyEqual(opp[OppCurve::kPointLast])) {
caryclark45fa4472015-01-16 07:04:10 -0800975 *oppT = 1;
976 }
977 *resultT = result;
978 return true;
979}
980
981// OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
982// so that each quad sect has a pointer to the largest, and can update it as spans
983// are split
caryclark1049f122015-04-20 08:31:59 -0700984template<typename TCurve, typename OppCurve>
985SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
986 SkTSpan<TCurve, OppCurve>* test = fHead;
987 SkTSpan<TCurve, OppCurve>* largest = fHead;
caryclark54359292015-03-26 07:52:43 -0700988 bool lCollapsed = largest->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800989 while ((test = test->fNext)) {
caryclark54359292015-03-26 07:52:43 -0700990 bool tCollapsed = test->fCollapsed;
991 if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
992 largest->fBoundsMax < test->fBoundsMax)) {
caryclark45fa4472015-01-16 07:04:10 -0800993 largest = test;
caryclark1049f122015-04-20 08:31:59 -0700994 lCollapsed = test->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800995 }
996 }
caryclark54359292015-03-26 07:52:43 -0700997 return largest;
caryclark45fa4472015-01-16 07:04:10 -0800998}
999
caryclark1049f122015-04-20 08:31:59 -07001000template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001001bool SkTSect<TCurve, OppCurve>::coincidentCheck(SkTSect<OppCurve, TCurve>* sect2) {
caryclark1049f122015-04-20 08:31:59 -07001002 SkTSpan<TCurve, OppCurve>* first = fHead;
caryclark9feb6322016-10-25 08:58:26 -07001003 if (!first) {
1004 return false;
1005 }
caryclark1049f122015-04-20 08:31:59 -07001006 SkTSpan<TCurve, OppCurve>* last, * next;
caryclark45fa4472015-01-16 07:04:10 -08001007 do {
caryclark54359292015-03-26 07:52:43 -07001008 int consecutive = this->countConsecutiveSpans(first, &last);
1009 next = last->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001010 if (consecutive < COINCIDENT_SPAN_COUNT) {
1011 continue;
1012 }
caryclark54359292015-03-26 07:52:43 -07001013 this->validate();
1014 sect2->validate();
1015 this->computePerpendiculars(sect2, first, last);
1016 this->validate();
1017 sect2->validate();
caryclark45fa4472015-01-16 07:04:10 -08001018 // check to see if a range of points are on the curve
caryclark1049f122015-04-20 08:31:59 -07001019 SkTSpan<TCurve, OppCurve>* coinStart = first;
caryclark54359292015-03-26 07:52:43 -07001020 do {
caryclarkef7cee42016-09-06 09:05:54 -07001021 bool success = this->extractCoincident(sect2, coinStart, last, &coinStart);
1022 if (!success) {
1023 return false;
1024 }
caryclark54359292015-03-26 07:52:43 -07001025 } while (coinStart && !last->fDeleted);
caryclark55888e42016-07-18 10:01:36 -07001026 if (!fHead || !sect2->fHead) {
1027 break;
1028 }
caryclark643ede62016-08-08 14:27:45 -07001029 if (!next || next->fDeleted) {
1030 break;
1031 }
caryclark45fa4472015-01-16 07:04:10 -08001032 } while ((first = next));
caryclarkef7cee42016-09-06 09:05:54 -07001033 return true;
caryclark45fa4472015-01-16 07:04:10 -08001034}
1035
caryclark1049f122015-04-20 08:31:59 -07001036template<typename TCurve, typename OppCurve>
caryclark26ad22a2015-10-16 09:03:38 -07001037void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2,
1038 double start1s, double start1e) {
1039 SkTSpan<TCurve, OppCurve>* first = fHead;
1040 SkTSpan<TCurve, OppCurve>* last = this->tail();
1041 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead;
1042 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail();
1043 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1044 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
1045 this->removeSpanRange(first, last);
1046 sect2->removeSpanRange(oppFirst, oppLast);
1047 first->fStartT = start1s;
1048 first->fEndT = start1e;
1049 first->resetBounds(fCurve);
1050 first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve);
1051 first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->fCurve);
1052 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
caryclarkef784fb2015-10-30 12:03:06 -07001053 double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : SkTMax(0., first->fCoinStart.perpT());
1054 double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : SkTMin(1., first->fCoinEnd.perpT());
caryclark26ad22a2015-10-16 09:03:38 -07001055 if (!oppMatched) {
1056 SkTSwap(oppStartT, oppEndT);
1057 }
1058 oppFirst->fStartT = oppStartT;
1059 oppFirst->fEndT = oppEndT;
1060 oppFirst->resetBounds(sect2->fCurve);
1061 this->removeCoincident(first, false);
1062 sect2->removeCoincident(oppFirst, true);
1063 if (deleteEmptySpans) {
1064 this->deleteEmptySpans();
1065 sect2->deleteEmptySpans();
1066 }
1067}
1068
1069template<typename TCurve, typename OppCurve>
caryclark1049f122015-04-20 08:31:59 -07001070bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) {
1071 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001072 while (test) {
1073 if (between(test->fStartT, t, test->fEndT)) {
1074 return true;
1075 }
1076 test = test->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001077 }
caryclark54359292015-03-26 07:52:43 -07001078 return false;
caryclark45fa4472015-01-16 07:04:10 -08001079}
1080
caryclark1049f122015-04-20 08:31:59 -07001081template<typename TCurve, typename OppCurve>
1082int SkTSect<TCurve, OppCurve>::collapsed() const {
1083 int result = 0;
1084 const SkTSpan<TCurve, OppCurve>* test = fHead;
1085 while (test) {
1086 if (test->fCollapsed) {
1087 ++result;
1088 }
1089 test = test->next();
1090 }
1091 return result;
1092}
1093
1094template<typename TCurve, typename OppCurve>
1095void SkTSect<TCurve, OppCurve>::computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2,
1096 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
1097 const OppCurve& opp = sect2->fCurve;
1098 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001099 SkTSpan<TCurve, OppCurve>* prior = nullptr;
caryclark45fa4472015-01-16 07:04:10 -08001100 do {
caryclark54359292015-03-26 07:52:43 -07001101 if (!work->fHasPerp && !work->fCollapsed) {
1102 if (prior) {
1103 work->fCoinStart = prior->fCoinEnd;
1104 } else {
1105 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp);
caryclark45fa4472015-01-16 07:04:10 -08001106 }
caryclark6c3b9cd2016-09-26 05:36:58 -07001107 if (work->fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001108 double perpT = work->fCoinStart.perpT();
1109 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001110 work->fCoinStart.init();
caryclark54359292015-03-26 07:52:43 -07001111 } else {
1112 sect2->addForPerp(work, perpT);
1113 }
1114 }
1115 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPointLast], opp);
caryclark6c3b9cd2016-09-26 05:36:58 -07001116 if (work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001117 double perpT = work->fCoinEnd.perpT();
1118 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001119 work->fCoinEnd.init();
caryclark54359292015-03-26 07:52:43 -07001120 } else {
1121 sect2->addForPerp(work, perpT);
1122 }
1123 }
1124 work->fHasPerp = true;
caryclark45fa4472015-01-16 07:04:10 -08001125 }
1126 if (work == last) {
1127 break;
1128 }
caryclark54359292015-03-26 07:52:43 -07001129 prior = work;
caryclark45fa4472015-01-16 07:04:10 -08001130 work = work->fNext;
1131 SkASSERT(work);
1132 } while (true);
caryclark54359292015-03-26 07:52:43 -07001133}
1134
caryclark1049f122015-04-20 08:31:59 -07001135template<typename TCurve, typename OppCurve>
1136int SkTSect<TCurve, OppCurve>::countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
1137 SkTSpan<TCurve, OppCurve>** lastPtr) const {
caryclark54359292015-03-26 07:52:43 -07001138 int consecutive = 1;
caryclark1049f122015-04-20 08:31:59 -07001139 SkTSpan<TCurve, OppCurve>* last = first;
caryclark54359292015-03-26 07:52:43 -07001140 do {
caryclark1049f122015-04-20 08:31:59 -07001141 SkTSpan<TCurve, OppCurve>* next = last->fNext;
caryclark54359292015-03-26 07:52:43 -07001142 if (!next) {
1143 break;
1144 }
1145 if (next->fStartT > last->fEndT) {
1146 break;
1147 }
1148 ++consecutive;
1149 last = next;
1150 } while (true);
1151 *lastPtr = last;
1152 return consecutive;
1153}
1154
caryclark1049f122015-04-20 08:31:59 -07001155template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001156bool SkTSect<TCurve, OppCurve>::hasBounded(const SkTSpan<OppCurve, TCurve>* span) const {
caryclark1049f122015-04-20 08:31:59 -07001157 const SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001158 if (!test) {
1159 return false;
1160 }
1161 do {
1162 if (test->findOppSpan(span)) {
1163 return true;
1164 }
1165 } while ((test = test->next()));
1166 return false;
1167}
1168
caryclark1049f122015-04-20 08:31:59 -07001169template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001170bool SkTSect<TCurve, OppCurve>::deleteEmptySpans() {
caryclark1049f122015-04-20 08:31:59 -07001171 SkTSpan<TCurve, OppCurve>* test;
1172 SkTSpan<TCurve, OppCurve>* next = fHead;
Cary Clark59ed4822016-12-08 16:17:56 -05001173 int safetyHatch = 1000;
caryclark54359292015-03-26 07:52:43 -07001174 while ((test = next)) {
1175 next = test->fNext;
1176 if (!test->fBounded) {
caryclarkef7cee42016-09-06 09:05:54 -07001177 if (!this->removeSpan(test)) {
1178 return false;
1179 }
caryclark54359292015-03-26 07:52:43 -07001180 }
Cary Clark59ed4822016-12-08 16:17:56 -05001181 if (--safetyHatch < 0) {
1182 return false;
1183 }
caryclark54359292015-03-26 07:52:43 -07001184 }
caryclarkef7cee42016-09-06 09:05:54 -07001185 return true;
caryclark54359292015-03-26 07:52:43 -07001186}
1187
caryclark1049f122015-04-20 08:31:59 -07001188template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001189bool SkTSect<TCurve, OppCurve>::extractCoincident(
caryclark1049f122015-04-20 08:31:59 -07001190 SkTSect<OppCurve, TCurve>* sect2,
caryclarkef7cee42016-09-06 09:05:54 -07001191 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
1192 SkTSpan<TCurve, OppCurve>** result) {
caryclark1049f122015-04-20 08:31:59 -07001193 first = findCoincidentRun(first, &last);
caryclarka1b42d92016-08-16 10:25:29 -07001194 if (!first || !last) {
caryclarkef7cee42016-09-06 09:05:54 -07001195 *result = nullptr;
1196 return true;
caryclark45fa4472015-01-16 07:04:10 -08001197 }
1198 // march outwards to find limit of coincidence from here to previous and next spans
1199 double startT = first->fStartT;
caryclarkd8bc16b2015-03-26 09:05:12 -07001200 double oppStartT SK_INIT_TO_AVOID_WARNING;
caryclark54359292015-03-26 07:52:43 -07001201 double oppEndT SK_INIT_TO_AVOID_WARNING;
caryclark1049f122015-04-20 08:31:59 -07001202 SkTSpan<TCurve, OppCurve>* prev = first->fPrev;
caryclark6c3b9cd2016-09-26 05:36:58 -07001203 SkASSERT(first->fCoinStart.isMatch());
caryclark1049f122015-04-20 08:31:59 -07001204 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
caryclark6c3b9cd2016-09-26 05:36:58 -07001205 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001206 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
1207 double coinStart;
1208 SkDEBUGCODE(double coinEnd);
caryclark1049f122015-04-20 08:31:59 -07001209 SkTSpan<OppCurve, TCurve>* cutFirst;
caryclark54359292015-03-26 07:52:43 -07001210 if (prev && prev->fEndT == startT
1211 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
Cary Clark74b42902018-03-09 07:38:47 -05001212 &oppStartT, &oppFirst)
caryclark1049f122015-04-20 08:31:59 -07001213 && prev->fStartT < coinStart && coinStart < startT
1214 && (cutFirst = prev->oppT(oppStartT))) {
1215 oppFirst = cutFirst;
caryclark54359292015-03-26 07:52:43 -07001216 first = this->addSplitAt(prev, coinStart);
1217 first->markCoincident();
1218 prev->fCoinEnd.markCoincident();
1219 if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
caryclark1049f122015-04-20 08:31:59 -07001220 SkTSpan<OppCurve, TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
caryclark54359292015-03-26 07:52:43 -07001221 if (oppMatched) {
1222 oppFirst->fCoinEnd.markCoincident();
1223 oppHalf->markCoincident();
1224 oppFirst = oppHalf;
1225 } else {
1226 oppFirst->markCoincident();
1227 oppHalf->fCoinStart.markCoincident();
1228 }
1229 }
1230 } else {
Cary Clark74b42902018-03-09 07:38:47 -05001231 if (!oppFirst) {
1232 return false;
1233 }
caryclark54359292015-03-26 07:52:43 -07001234 SkDEBUGCODE(coinStart = first->fStartT);
1235 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
1236 }
caryclark1049f122015-04-20 08:31:59 -07001237 // FIXME: incomplete : if we're not at the end, find end of coin
1238 SkTSpan<OppCurve, TCurve>* oppLast;
caryclark6c3b9cd2016-09-26 05:36:58 -07001239 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001240 oppLast = last->findOppT(last->fCoinEnd.perpT());
1241 SkDEBUGCODE(coinEnd = last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001242#ifdef SK_DEBUG
1243 if (!this->globalState() || !this->globalState()->debugSkipAssert()) {
1244 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT;
1245 }
1246#endif
caryclark54359292015-03-26 07:52:43 -07001247 if (!oppMatched) {
1248 SkTSwap(oppFirst, oppLast);
1249 SkTSwap(oppStartT, oppEndT);
1250 }
caryclarke25a4f62016-07-26 09:26:29 -07001251 SkOPASSERT(oppStartT < oppEndT);
caryclark54359292015-03-26 07:52:43 -07001252 SkASSERT(coinStart == first->fStartT);
1253 SkASSERT(coinEnd == last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001254 SkOPASSERT(oppStartT == oppFirst->fStartT);
1255 SkOPASSERT(oppEndT == oppLast->fEndT);
1256 if (!oppFirst) {
caryclarkef7cee42016-09-06 09:05:54 -07001257 *result = nullptr;
1258 return true;
caryclark643ede62016-08-08 14:27:45 -07001259 }
caryclark42942862016-08-19 07:01:33 -07001260 if (!oppLast) {
caryclarkef7cee42016-09-06 09:05:54 -07001261 *result = nullptr;
1262 return true;
caryclark42942862016-08-19 07:01:33 -07001263 }
caryclark54359292015-03-26 07:52:43 -07001264 // reduce coincident runs to single entries
1265 this->validate();
1266 sect2->validate();
caryclark1049f122015-04-20 08:31:59 -07001267 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1268 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
caryclark54359292015-03-26 07:52:43 -07001269 this->removeSpanRange(first, last);
1270 sect2->removeSpanRange(oppFirst, oppLast);
1271 first->fEndT = last->fEndT;
1272 first->resetBounds(this->fCurve);
1273 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], sect2->fCurve);
1274 first->fCoinEnd.setPerp(fCurve, first->fEndT, first->fPart[TCurve::kPointLast], sect2->fCurve);
1275 oppStartT = first->fCoinStart.perpT();
1276 oppEndT = first->fCoinEnd.perpT();
1277 if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) {
1278 if (!oppMatched) {
1279 SkTSwap(oppStartT, oppEndT);
1280 }
1281 oppFirst->fStartT = oppStartT;
1282 oppFirst->fEndT = oppEndT;
1283 oppFirst->resetBounds(sect2->fCurve);
1284 }
1285 this->validateBounded();
1286 sect2->validateBounded();
1287 last = first->fNext;
Cary Clark38702ab2017-09-05 18:11:55 -04001288 if (!this->removeCoincident(first, false)) {
1289 return false;
1290 }
1291 if (!sect2->removeCoincident(oppFirst, true)) {
1292 return false;
1293 }
caryclark1049f122015-04-20 08:31:59 -07001294 if (deleteEmptySpans) {
caryclarkef7cee42016-09-06 09:05:54 -07001295 if (!this->deleteEmptySpans() || !sect2->deleteEmptySpans()) {
1296 *result = nullptr;
1297 return false;
1298 }
caryclark54359292015-03-26 07:52:43 -07001299 }
1300 this->validate();
1301 sect2->validate();
caryclarkef7cee42016-09-06 09:05:54 -07001302 *result = last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr;
1303 return true;
caryclark54359292015-03-26 07:52:43 -07001304}
1305
caryclark1049f122015-04-20 08:31:59 -07001306template<typename TCurve, typename OppCurve>
1307SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun(
1308 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) {
1309 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001310 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr;
1311 first = nullptr;
caryclark54359292015-03-26 07:52:43 -07001312 // find the first fully coincident span
1313 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07001314 if (work->fCoinStart.isMatch()) {
caryclark1049f122015-04-20 08:31:59 -07001315#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -07001316 work->validatePerpT(work->fCoinStart.perpT());
1317 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt());
caryclark1049f122015-04-20 08:31:59 -07001318#endif
caryclarka35ab3e2016-10-20 08:32:18 -07001319 SkOPASSERT(work->hasOppT(work->fCoinStart.perpT()));
caryclark6c3b9cd2016-09-26 05:36:58 -07001320 if (!work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001321 break;
1322 }
1323 lastCandidate = work;
1324 if (!first) {
1325 first = work;
1326 }
caryclark1049f122015-04-20 08:31:59 -07001327 } else if (first && work->fCollapsed) {
1328 *lastPtr = lastCandidate;
1329 return first;
caryclark54359292015-03-26 07:52:43 -07001330 } else {
halcanary96fcdcc2015-08-27 07:41:13 -07001331 lastCandidate = nullptr;
caryclark643ede62016-08-08 14:27:45 -07001332 SkOPASSERT(!first);
caryclark54359292015-03-26 07:52:43 -07001333 }
1334 if (work == *lastPtr) {
1335 return first;
1336 }
1337 work = work->fNext;
caryclarke25a4f62016-07-26 09:26:29 -07001338 if (!work) {
1339 return nullptr;
1340 }
caryclark54359292015-03-26 07:52:43 -07001341 } while (true);
1342 if (lastCandidate) {
1343 *lastPtr = lastCandidate;
1344 }
1345 return first;
1346}
1347
caryclark1049f122015-04-20 08:31:59 -07001348template<typename TCurve, typename OppCurve>
1349int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
1350 SkTSect<OppCurve, TCurve>* opp,
1351 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult) {
caryclark54359292015-03-26 07:52:43 -07001352 bool spanStart, oppStart;
1353 int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
1354 if (hullResult >= 0) {
1355 if (hullResult == 2) { // hulls have one point in common
1356 if (!span->fBounded || !span->fBounded->fNext) {
1357 SkASSERT(!span->fBounded || span->fBounded->fBounded == oppSpan);
1358 if (spanStart) {
1359 span->fEndT = span->fStartT;
caryclark45fa4472015-01-16 07:04:10 -08001360 } else {
caryclark54359292015-03-26 07:52:43 -07001361 span->fStartT = span->fEndT;
1362 }
1363 } else {
1364 hullResult = 1;
1365 }
1366 if (!oppSpan->fBounded || !oppSpan->fBounded->fNext) {
1367 SkASSERT(!oppSpan->fBounded || oppSpan->fBounded->fBounded == span);
1368 if (oppStart) {
1369 oppSpan->fEndT = oppSpan->fStartT;
1370 } else {
1371 oppSpan->fStartT = oppSpan->fEndT;
1372 }
1373 *oppResult = 2;
1374 } else {
1375 *oppResult = 1;
1376 }
1377 } else {
1378 *oppResult = 1;
1379 }
1380 return hullResult;
1381 }
1382 if (span->fIsLine && oppSpan->fIsLine) {
1383 SkIntersections i;
1384 int sects = this->linesIntersect(span, opp, oppSpan, &i);
caryclark26ad22a2015-10-16 09:03:38 -07001385 if (sects == 2) {
1386 return *oppResult = 1;
1387 }
caryclark54359292015-03-26 07:52:43 -07001388 if (!sects) {
1389 return -1;
1390 }
caryclark34efb702016-10-24 08:19:06 -07001391 this->removedEndCheck(span);
caryclark54359292015-03-26 07:52:43 -07001392 span->fStartT = span->fEndT = i[0][0];
caryclark34efb702016-10-24 08:19:06 -07001393 opp->removedEndCheck(oppSpan);
caryclark54359292015-03-26 07:52:43 -07001394 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1395 return *oppResult = 2;
1396 }
1397 if (span->fIsLinear || oppSpan->fIsLinear) {
1398 return *oppResult = (int) span->linearsIntersect(oppSpan);
1399 }
1400 return *oppResult = 1;
1401}
1402
caryclarked0935a2015-10-22 07:23:52 -07001403template<typename TCurve>
1404static bool is_parallel(const SkDLine& thisLine, const TCurve& opp) {
1405 if (!opp.IsConic()) {
1406 return false; // FIXME : breaks a lot of stuff now
1407 }
1408 int finds = 0;
1409 SkDLine thisPerp;
1410 thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1411 thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1412 thisPerp.fPts[1] = thisLine.fPts[1];
1413 SkIntersections perpRayI;
1414 perpRayI.intersectRay(opp, thisPerp);
1415 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1416 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]);
1417 }
1418 thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1419 thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1420 thisPerp.fPts[0] = thisLine.fPts[0];
1421 perpRayI.intersectRay(opp, thisPerp);
1422 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1423 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]);
1424 }
1425 return finds >= 2;
1426}
1427
caryclark54359292015-03-26 07:52:43 -07001428// while the intersection points are sufficiently far apart:
1429// construct the tangent lines from the intersections
1430// find the point where the tangent line intersects the opposite curve
caryclark1049f122015-04-20 08:31:59 -07001431template<typename TCurve, typename OppCurve>
1432int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
1433 SkTSect<OppCurve, TCurve>* opp,
1434 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
caryclarka35ab3e2016-10-20 08:32:18 -07001435 SkIntersections thisRayI SkDEBUGCODE((span->fDebugGlobalState));
1436 SkIntersections oppRayI SkDEBUGCODE((span->fDebugGlobalState));
caryclark54359292015-03-26 07:52:43 -07001437 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
caryclark1049f122015-04-20 08:31:59 -07001438 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
caryclark54359292015-03-26 07:52:43 -07001439 int loopCount = 0;
1440 double bestDistSq = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -07001441 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1442 return 0;
1443 }
1444 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1445 return 0;
1446 }
caryclark26ad22a2015-10-16 09:03:38 -07001447 // if the ends of each line intersect the opposite curve, the lines are coincident
1448 if (thisRayI.used() > 1) {
1449 int ptMatches = 0;
1450 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) {
1451 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1452 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPts[lIndex]);
1453 }
1454 }
caryclarked0935a2015-10-22 07:23:52 -07001455 if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001456 return 2;
1457 }
1458 }
1459 if (oppRayI.used() > 1) {
1460 int ptMatches = 0;
1461 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) {
Cary Clarkd80870f2017-10-17 11:57:26 -04001462 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(oppLine.fPts); ++lIndex) {
caryclark26ad22a2015-10-16 09:03:38 -07001463 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[lIndex]);
1464 }
1465 }
caryclarked0935a2015-10-22 07:23:52 -07001466 if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001467 return 2;
1468 }
1469 }
caryclark54359292015-03-26 07:52:43 -07001470 do {
caryclark54359292015-03-26 07:52:43 -07001471 // pick the closest pair of points
1472 double closest = DBL_MAX;
1473 int closeIndex SK_INIT_TO_AVOID_WARNING;
1474 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1475 for (int index = 0; index < oppRayI.used(); ++index) {
1476 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
1477 continue;
1478 }
1479 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) {
1480 if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppSpan->fEndT)) {
1481 continue;
1482 }
1483 double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oIndex));
1484 if (closest > distSq) {
1485 closest = distSq;
1486 closeIndex = index;
1487 oppCloseIndex = oIndex;
caryclarkccec0f92015-03-24 07:28:17 -07001488 }
caryclarkccec0f92015-03-24 07:28:17 -07001489 }
reed0dc4dd62015-03-24 13:55:33 -07001490 }
caryclark54359292015-03-26 07:52:43 -07001491 if (closest == DBL_MAX) {
caryclark1049f122015-04-20 08:31:59 -07001492 break;
reed0dc4dd62015-03-24 13:55:33 -07001493 }
caryclark54359292015-03-26 07:52:43 -07001494 const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
1495 const SkDPoint& iPt = oppRayI.pt(closeIndex);
1496 if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT)
1497 && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan->fEndT)
1498 && oppIPt.approximatelyEqual(iPt)) {
1499 i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex);
1500 return i->used();
1501 }
1502 double distSq = oppIPt.distanceSquared(iPt);
1503 if (bestDistSq < distSq || ++loopCount > 5) {
caryclark1049f122015-04-20 08:31:59 -07001504 return 0;
caryclark54359292015-03-26 07:52:43 -07001505 }
1506 bestDistSq = distSq;
caryclark1049f122015-04-20 08:31:59 -07001507 double oppStart = oppRayI[0][closeIndex];
1508 thisLine[0] = fCurve.ptAtT(oppStart);
1509 thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart);
1510 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1511 break;
1512 }
1513 double start = thisRayI[0][oppCloseIndex];
1514 oppLine[0] = opp->fCurve.ptAtT(start);
1515 oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start);
1516 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1517 break;
1518 }
caryclark54359292015-03-26 07:52:43 -07001519 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001520 // convergence may fail if the curves are nearly coincident
1521 SkTCoincident<OppCurve, TCurve> oCoinS, oCoinE;
1522 oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->fPart[0], fCurve);
1523 oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->fPart[OppCurve::kPointLast], fCurve);
1524 double tStart = oCoinS.perpT();
1525 double tEnd = oCoinE.perpT();
1526 bool swap = tStart > tEnd;
1527 if (swap) {
1528 SkTSwap(tStart, tEnd);
1529 }
1530 tStart = SkTMax(tStart, span->fStartT);
1531 tEnd = SkTMin(tEnd, span->fEndT);
1532 if (tStart > tEnd) {
1533 return 0;
1534 }
1535 SkDVector perpS, perpE;
1536 if (tStart == span->fStartT) {
1537 SkTCoincident<TCurve, OppCurve> coinS;
1538 coinS.setPerp(fCurve, span->fStartT, span->fPart[0], opp->fCurve);
1539 perpS = span->fPart[0] - coinS.perpPt();
1540 } else if (swap) {
1541 perpS = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1542 } else {
1543 perpS = oCoinS.perpPt() - oppSpan->fPart[0];
1544 }
1545 if (tEnd == span->fEndT) {
1546 SkTCoincident<TCurve, OppCurve> coinE;
1547 coinE.setPerp(fCurve, span->fEndT, span->fPart[TCurve::kPointLast], opp->fCurve);
1548 perpE = span->fPart[TCurve::kPointLast] - coinE.perpPt();
1549 } else if (swap) {
1550 perpE = oCoinS.perpPt() - oppSpan->fPart[0];
1551 } else {
1552 perpE = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1553 }
1554 if (perpS.dot(perpE) >= 0) {
1555 return 0;
1556 }
1557 SkTCoincident<TCurve, OppCurve> coinW;
1558 double workT = tStart;
1559 double tStep = tEnd - tStart;
1560 SkDPoint workPt;
1561 do {
1562 tStep *= 0.5;
1563 if (precisely_zero(tStep)) {
1564 return 0;
1565 }
1566 workT += tStep;
1567 workPt = fCurve.ptAtT(workT);
1568 coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
caryclark27c015d2016-09-23 05:47:20 -07001569 double perpT = coinW.perpT();
caryclark6c3b9cd2016-09-26 05:36:58 -07001570 if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) {
caryclarkb6693002015-12-16 12:28:35 -08001571 continue;
1572 }
caryclark1049f122015-04-20 08:31:59 -07001573 SkDVector perpW = workPt - coinW.perpPt();
1574 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
1575 tStep = -tStep;
1576 }
caryclarkb6693002015-12-16 12:28:35 -08001577 if (workPt.approximatelyEqual(coinW.perpPt())) {
1578 break;
1579 }
1580 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001581 double oppTTest = coinW.perpT();
1582 if (!opp->fHead->contains(oppTTest)) {
1583 return 0;
1584 }
1585 i->setMax(1);
1586 i->insert(workT, oppTTest, workPt);
1587 return 1;
caryclark54359292015-03-26 07:52:43 -07001588}
1589
1590
caryclark1049f122015-04-20 08:31:59 -07001591template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001592bool SkTSect<TCurve, OppCurve>::markSpanGone(SkTSpan<TCurve, OppCurve>* span) {
1593 if (--fActiveCount < 0) {
1594 return false;
1595 }
caryclark54359292015-03-26 07:52:43 -07001596 span->fNext = fDeleted;
1597 fDeleted = span;
caryclarke25a4f62016-07-26 09:26:29 -07001598 SkOPASSERT(!span->fDeleted);
caryclark54359292015-03-26 07:52:43 -07001599 span->fDeleted = true;
caryclarkef7cee42016-09-06 09:05:54 -07001600 return true;
caryclark54359292015-03-26 07:52:43 -07001601}
1602
caryclark1049f122015-04-20 08:31:59 -07001603template<typename TCurve, typename OppCurve>
1604bool SkTSect<TCurve, OppCurve>::matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2,
1605 double t2) const {
caryclark54359292015-03-26 07:52:43 -07001606 SkDVector dxdy = this->fCurve.dxdyAtT(t);
1607 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
1608 return dxdy.dot(dxdy2) >= 0;
1609}
1610
caryclark1049f122015-04-20 08:31:59 -07001611template<typename TCurve, typename OppCurve>
1612void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2,
1613 double t2, bool* calcMatched, bool* oppMatched) const {
caryclark54359292015-03-26 07:52:43 -07001614 if (*calcMatched) {
caryclark55888e42016-07-18 10:01:36 -07001615 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
caryclark54359292015-03-26 07:52:43 -07001616 } else {
1617 *oppMatched = this->matchedDirection(t, sect2, t2);
1618 *calcMatched = true;
1619 }
1620}
1621
caryclark1049f122015-04-20 08:31:59 -07001622template<typename TCurve, typename OppCurve>
1623void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2) {
caryclark54359292015-03-26 07:52:43 -07001624 double smallLimit = 0;
1625 do {
1626 // find the smallest unprocessed span
halcanary96fcdcc2015-08-27 07:41:13 -07001627 SkTSpan<TCurve, OppCurve>* smaller = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001628 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001629 do {
caryclark221a4bb2016-10-07 11:15:15 -07001630 if (!test) {
1631 return;
1632 }
caryclark54359292015-03-26 07:52:43 -07001633 if (test->fStartT < smallLimit) {
1634 continue;
1635 }
1636 if (smaller && smaller->fEndT < test->fStartT) {
1637 continue;
1638 }
1639 smaller = test;
1640 } while ((test = test->fNext));
1641 if (!smaller) {
1642 return;
1643 }
1644 smallLimit = smaller->fEndT;
1645 // find next larger span
halcanary96fcdcc2015-08-27 07:41:13 -07001646 SkTSpan<TCurve, OppCurve>* prior = nullptr;
1647 SkTSpan<TCurve, OppCurve>* larger = nullptr;
1648 SkTSpan<TCurve, OppCurve>* largerPrior = nullptr;
caryclark54359292015-03-26 07:52:43 -07001649 test = fCoincident;
1650 do {
1651 if (test->fStartT < smaller->fEndT) {
1652 continue;
1653 }
caryclark221a4bb2016-10-07 11:15:15 -07001654 SkOPASSERT(test->fStartT != smaller->fEndT);
caryclark54359292015-03-26 07:52:43 -07001655 if (larger && larger->fStartT < test->fStartT) {
1656 continue;
1657 }
1658 largerPrior = prior;
1659 larger = test;
1660 } while ((prior = test), (test = test->fNext));
1661 if (!larger) {
1662 continue;
1663 }
1664 // check middle t value to see if it is coincident as well
1665 double midT = (smaller->fEndT + larger->fStartT) / 2;
1666 SkDPoint midPt = fCurve.ptAtT(midT);
caryclark1049f122015-04-20 08:31:59 -07001667 SkTCoincident<TCurve, OppCurve> coin;
caryclark54359292015-03-26 07:52:43 -07001668 coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07001669 if (coin.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001670 smaller->fEndT = larger->fEndT;
1671 smaller->fCoinEnd = larger->fCoinEnd;
1672 if (largerPrior) {
1673 largerPrior->fNext = larger->fNext;
caryclark643ede62016-08-08 14:27:45 -07001674 largerPrior->validate();
caryclark54359292015-03-26 07:52:43 -07001675 } else {
1676 fCoincident = larger->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001677 }
1678 }
caryclark54359292015-03-26 07:52:43 -07001679 } while (true);
1680}
1681
caryclark1049f122015-04-20 08:31:59 -07001682template<typename TCurve, typename OppCurve>
1683SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev(
1684 SkTSpan<TCurve, OppCurve>* span) const {
halcanary96fcdcc2015-08-27 07:41:13 -07001685 SkTSpan<TCurve, OppCurve>* result = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001686 SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001687 while (span != test) {
1688 result = test;
1689 test = test->fNext;
1690 SkASSERT(test);
caryclarkccec0f92015-03-24 07:28:17 -07001691 }
caryclark55888e42016-07-18 10:01:36 -07001692 return result;
caryclarkccec0f92015-03-24 07:28:17 -07001693}
1694
caryclark1049f122015-04-20 08:31:59 -07001695template<typename TCurve, typename OppCurve>
1696void SkTSect<TCurve, OppCurve>::recoverCollapsed() {
1697 SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001698 while (deleted) {
caryclark1049f122015-04-20 08:31:59 -07001699 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001700 if (deleted->fCollapsed) {
caryclark1049f122015-04-20 08:31:59 -07001701 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead;
caryclark45fa4472015-01-16 07:04:10 -08001702 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
1703 spanPtr = &(*spanPtr)->fNext;
1704 }
1705 deleted->fNext = *spanPtr;
1706 *spanPtr = deleted;
1707 }
1708 deleted = delNext;
1709 }
1710}
1711
caryclark1049f122015-04-20 08:31:59 -07001712template<typename TCurve, typename OppCurve>
1713void SkTSect<TCurve, OppCurve>::removeAllBut(const SkTSpan<OppCurve, TCurve>* keep,
1714 SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp) {
1715 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001716 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001717 SkTSpan<OppCurve, TCurve>* bounded = testBounded->fBounded;
1718 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001719 // may have been deleted when opp did 'remove all but'
1720 if (bounded != keep && !bounded->fDeleted) {
1721 SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
1722 if (bounded->removeBounded(span)) {
1723 opp->removeSpan(bounded);
1724 }
caryclarkccec0f92015-03-24 07:28:17 -07001725 }
caryclark54359292015-03-26 07:52:43 -07001726 testBounded = next;
caryclarkccec0f92015-03-24 07:28:17 -07001727 }
caryclark54359292015-03-26 07:52:43 -07001728 SkASSERT(!span->fDeleted);
1729 SkASSERT(span->findOppSpan(keep));
1730 SkASSERT(keep->findOppSpan(span));
caryclarkccec0f92015-03-24 07:28:17 -07001731}
1732
caryclark1049f122015-04-20 08:31:59 -07001733template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001734bool SkTSect<TCurve, OppCurve>::removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp) {
caryclark1049f122015-04-20 08:31:59 -07001735 SkTSpan<TCurve, OppCurve>* test = fHead;
1736 SkTSpan<TCurve, OppCurve>* next;
caryclark54359292015-03-26 07:52:43 -07001737 do {
1738 next = test->fNext;
1739 if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
1740 continue;
reed0dc4dd62015-03-24 13:55:33 -07001741 }
caryclark54359292015-03-26 07:52:43 -07001742 SkDVector startV = test->fCoinStart.perpPt() - test->fPart[0];
1743 SkDVector endV = test->fCoinEnd.perpPt() - test->fPart[TCurve::kPointLast];
1744#if DEBUG_T_SECT
1745 SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUNCTION__,
1746 startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV));
1747#endif
1748 if (startV.dot(endV) <= 0) {
1749 continue;
1750 }
Cary Clark0949bee2018-03-19 09:42:00 -04001751 if (!this->removeSpans(test, opp)) {
1752 return false;
1753 }
caryclark54359292015-03-26 07:52:43 -07001754 } while ((test = next));
Cary Clark0949bee2018-03-19 09:42:00 -04001755 return true;
caryclark54359292015-03-26 07:52:43 -07001756}
1757
caryclark1049f122015-04-20 08:31:59 -07001758template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001759bool SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween) {
1760 if (!this->unlinkSpan(span)) {
1761 return false;
1762 }
caryclark54359292015-03-26 07:52:43 -07001763 if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
1764 --fActiveCount;
1765 span->fNext = fCoincident;
1766 fCoincident = span;
1767 } else {
1768 this->markSpanGone(span);
reed0dc4dd62015-03-24 13:55:33 -07001769 }
Cary Clark38702ab2017-09-05 18:11:55 -04001770 return true;
caryclarkccec0f92015-03-24 07:28:17 -07001771}
1772
caryclark1049f122015-04-20 08:31:59 -07001773template<typename TCurve, typename OppCurve>
caryclark34efb702016-10-24 08:19:06 -07001774void SkTSect<TCurve, OppCurve>::removedEndCheck(SkTSpan<TCurve, OppCurve>* span) {
caryclark6c3b9cd2016-09-26 05:36:58 -07001775 if (!span->fStartT) {
1776 fRemovedStartT = true;
1777 }
1778 if (1 == span->fEndT) {
1779 fRemovedEndT = true;
1780 }
caryclark34efb702016-10-24 08:19:06 -07001781}
1782
1783template<typename TCurve, typename OppCurve>
1784bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {\
1785 this->removedEndCheck(span);
Cary Clark38702ab2017-09-05 18:11:55 -04001786 if (!this->unlinkSpan(span)) {
1787 return false;
1788 }
caryclarkef7cee42016-09-06 09:05:54 -07001789 return this->markSpanGone(span);
caryclark54359292015-03-26 07:52:43 -07001790}
1791
caryclark1049f122015-04-20 08:31:59 -07001792template<typename TCurve, typename OppCurve>
1793void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first,
1794 SkTSpan<TCurve, OppCurve>* last) {
caryclark54359292015-03-26 07:52:43 -07001795 if (first == last) {
1796 return;
1797 }
caryclark1049f122015-04-20 08:31:59 -07001798 SkTSpan<TCurve, OppCurve>* span = first;
caryclark54359292015-03-26 07:52:43 -07001799 SkASSERT(span);
caryclark1049f122015-04-20 08:31:59 -07001800 SkTSpan<TCurve, OppCurve>* final = last->fNext;
1801 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001802 while ((span = next) && span != final) {
1803 next = span->fNext;
1804 this->markSpanGone(span);
1805 }
1806 if (final) {
1807 final->fPrev = first;
1808 }
1809 first->fNext = final;
Cary Clarkb8421ed2018-03-14 15:55:02 -04001810 // world may not be ready for validation here
caryclark643ede62016-08-08 14:27:45 -07001811 first->validate();
caryclark54359292015-03-26 07:52:43 -07001812}
1813
caryclark1049f122015-04-20 08:31:59 -07001814template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001815bool SkTSect<TCurve, OppCurve>::removeSpans(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001816 SkTSect<OppCurve, TCurve>* opp) {
1817 SkTSpanBounded<OppCurve, TCurve>* bounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001818 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -07001819 SkTSpan<OppCurve, TCurve>* spanBounded = bounded->fBounded;
1820 SkTSpanBounded<OppCurve, TCurve>* next = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001821 if (span->removeBounded(spanBounded)) { // shuffles last into position 0
1822 this->removeSpan(span);
1823 }
1824 if (spanBounded->removeBounded(span)) {
1825 opp->removeSpan(spanBounded);
1826 }
Cary Clark0949bee2018-03-19 09:42:00 -04001827 if (span->fDeleted && opp->hasBounded(span)) {
1828 return false;
1829 }
caryclark54359292015-03-26 07:52:43 -07001830 bounded = next;
reed0dc4dd62015-03-24 13:55:33 -07001831 }
Cary Clark0949bee2018-03-19 09:42:00 -04001832 return true;
reed0dc4dd62015-03-24 13:55:33 -07001833}
caryclarkccec0f92015-03-24 07:28:17 -07001834
caryclark1049f122015-04-20 08:31:59 -07001835template<typename TCurve, typename OppCurve>
1836SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::spanAtT(double t,
1837 SkTSpan<TCurve, OppCurve>** priorSpan) {
1838 SkTSpan<TCurve, OppCurve>* test = fHead;
halcanary96fcdcc2015-08-27 07:41:13 -07001839 SkTSpan<TCurve, OppCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -07001840 while (test && test->fEndT < t) {
1841 prev = test;
1842 test = test->fNext;
reed0dc4dd62015-03-24 13:55:33 -07001843 }
caryclark54359292015-03-26 07:52:43 -07001844 *priorSpan = prev;
halcanary96fcdcc2015-08-27 07:41:13 -07001845 return test && test->fStartT <= t ? test : nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001846}
1847
caryclark1049f122015-04-20 08:31:59 -07001848template<typename TCurve, typename OppCurve>
1849SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::tail() {
1850 SkTSpan<TCurve, OppCurve>* result = fHead;
1851 SkTSpan<TCurve, OppCurve>* next = fHead;
reed0dc4dd62015-03-24 13:55:33 -07001852 while ((next = next->fNext)) {
1853 if (next->fEndT > result->fEndT) {
1854 result = next;
1855 }
1856 }
1857 return result;
1858}
1859
1860/* Each span has a range of opposite spans it intersects. After the span is split in two,
1861 adjust the range to its new size */
caryclark1049f122015-04-20 08:31:59 -07001862template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -07001863bool SkTSect<TCurve, OppCurve>::trim(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001864 SkTSect<OppCurve, TCurve>* opp) {
caryclarka35ab3e2016-10-20 08:32:18 -07001865 FAIL_IF(!span->initBounds(fCurve));
caryclark1049f122015-04-20 08:31:59 -07001866 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001867 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001868 SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
1869 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001870 int oppSects, sects = this->intersects(span, opp, test, &oppSects);
1871 if (sects >= 1) {
1872 if (oppSects == 2) {
1873 test->initBounds(opp->fCurve);
1874 opp->removeAllBut(span, test, this);
1875 }
1876 if (sects == 2) {
1877 span->initBounds(fCurve);
1878 this->removeAllBut(test, span, opp);
caryclarka35ab3e2016-10-20 08:32:18 -07001879 return true;
caryclark54359292015-03-26 07:52:43 -07001880 }
reed0dc4dd62015-03-24 13:55:33 -07001881 } else {
caryclark54359292015-03-26 07:52:43 -07001882 if (span->removeBounded(test)) {
1883 this->removeSpan(span);
1884 }
1885 if (test->removeBounded(span)) {
1886 opp->removeSpan(test);
1887 }
1888 }
1889 testBounded = next;
1890 }
caryclarka35ab3e2016-10-20 08:32:18 -07001891 return true;
caryclark54359292015-03-26 07:52:43 -07001892}
1893
caryclark1049f122015-04-20 08:31:59 -07001894template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001895bool SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) {
caryclark1049f122015-04-20 08:31:59 -07001896 SkTSpan<TCurve, OppCurve>* prev = span->fPrev;
1897 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001898 if (prev) {
1899 prev->fNext = next;
1900 if (next) {
1901 next->fPrev = prev;
Cary Clark38702ab2017-09-05 18:11:55 -04001902 if (next->fStartT > next->fEndT) {
1903 return false;
1904 }
Cary Clarkb8421ed2018-03-14 15:55:02 -04001905 // world may not be ready for validate here
caryclark643ede62016-08-08 14:27:45 -07001906 next->validate();
caryclark54359292015-03-26 07:52:43 -07001907 }
1908 } else {
1909 fHead = next;
1910 if (next) {
halcanary96fcdcc2015-08-27 07:41:13 -07001911 next->fPrev = nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001912 }
1913 }
Cary Clark38702ab2017-09-05 18:11:55 -04001914 return true;
reed0dc4dd62015-03-24 13:55:33 -07001915}
1916
caryclark1049f122015-04-20 08:31:59 -07001917template<typename TCurve, typename OppCurve>
1918bool SkTSect<TCurve, OppCurve>::updateBounded(SkTSpan<TCurve, OppCurve>* first,
1919 SkTSpan<TCurve, OppCurve>* last, SkTSpan<OppCurve, TCurve>* oppFirst) {
1920 SkTSpan<TCurve, OppCurve>* test = first;
1921 const SkTSpan<TCurve, OppCurve>* final = last->next();
caryclark54359292015-03-26 07:52:43 -07001922 bool deleteSpan = false;
1923 do {
1924 deleteSpan |= test->removeAllBounded();
caryclarke25a4f62016-07-26 09:26:29 -07001925 } while ((test = test->fNext) != final && test);
halcanary96fcdcc2015-08-27 07:41:13 -07001926 first->fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -07001927 first->addBounded(oppFirst, &fHeap);
1928 // cannot call validate until remove span range is called
1929 return deleteSpan;
1930}
1931
1932
caryclark1049f122015-04-20 08:31:59 -07001933template<typename TCurve, typename OppCurve>
1934void SkTSect<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -07001935#if DEBUG_VALIDATE
caryclark45fa4472015-01-16 07:04:10 -08001936 int count = 0;
caryclark643ede62016-08-08 14:27:45 -07001937 double last = 0;
caryclark45fa4472015-01-16 07:04:10 -08001938 if (fHead) {
caryclark1049f122015-04-20 08:31:59 -07001939 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark45fa4472015-01-16 07:04:10 -08001940 SkASSERT(!span->fPrev);
caryclark643ede62016-08-08 14:27:45 -07001941 const SkTSpan<TCurve, OppCurve>* next;
caryclark45fa4472015-01-16 07:04:10 -08001942 do {
1943 span->validate();
1944 SkASSERT(span->fStartT >= last);
caryclark643ede62016-08-08 14:27:45 -07001945 last = span->fEndT;
caryclark45fa4472015-01-16 07:04:10 -08001946 ++count;
caryclark643ede62016-08-08 14:27:45 -07001947 next = span->fNext;
1948 SkASSERT(next != span);
1949 } while ((span = next) != nullptr);
caryclark45fa4472015-01-16 07:04:10 -08001950 }
1951 SkASSERT(count == fActiveCount);
caryclark643ede62016-08-08 14:27:45 -07001952#endif
1953#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -08001954 SkASSERT(fActiveCount <= fDebugAllocatedCount);
1955 int deletedCount = 0;
caryclark1049f122015-04-20 08:31:59 -07001956 const SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001957 while (deleted) {
1958 ++deletedCount;
1959 deleted = deleted->fNext;
1960 }
caryclark1049f122015-04-20 08:31:59 -07001961 const SkTSpan<TCurve, OppCurve>* coincident = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001962 while (coincident) {
1963 ++deletedCount;
1964 coincident = coincident->fNext;
1965 }
caryclark45fa4472015-01-16 07:04:10 -08001966 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount);
caryclarkccec0f92015-03-24 07:28:17 -07001967#endif
caryclark54359292015-03-26 07:52:43 -07001968}
1969
caryclark1049f122015-04-20 08:31:59 -07001970template<typename TCurve, typename OppCurve>
1971void SkTSect<TCurve, OppCurve>::validateBounded() const {
caryclark643ede62016-08-08 14:27:45 -07001972#if DEBUG_VALIDATE
caryclark54359292015-03-26 07:52:43 -07001973 if (!fHead) {
1974 return;
1975 }
caryclark1049f122015-04-20 08:31:59 -07001976 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark54359292015-03-26 07:52:43 -07001977 do {
1978 span->validateBounded();
halcanary96fcdcc2015-08-27 07:41:13 -07001979 } while ((span = span->fNext) != nullptr);
caryclark54359292015-03-26 07:52:43 -07001980#endif
1981}
caryclark45fa4472015-01-16 07:04:10 -08001982
caryclark1049f122015-04-20 08:31:59 -07001983template<typename TCurve, typename OppCurve>
1984int SkTSect<TCurve, OppCurve>::EndsEqual(const SkTSect<TCurve, OppCurve>* sect1,
1985 const SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark45fa4472015-01-16 07:04:10 -08001986 int zeroOneSet = 0;
caryclark54359292015-03-26 07:52:43 -07001987 if (sect1->fCurve[0] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001988 zeroOneSet |= kZeroS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001989 intersections->insert(0, 0, sect1->fCurve[0]);
1990 }
caryclark1049f122015-04-20 08:31:59 -07001991 if (sect1->fCurve[0] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001992 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark54359292015-03-26 07:52:43 -07001993 intersections->insert(0, 1, sect1->fCurve[0]);
1994 }
1995 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001996 zeroOneSet |= kOneS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001997 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
1998 }
caryclark1049f122015-04-20 08:31:59 -07001999 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07002000 zeroOneSet |= kOneS1Set | kOneS2Set;
reed0dc4dd62015-03-24 13:55:33 -07002001 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07002002 }
2003 // check for zero
2004 if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set))
2005 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) {
2006 zeroOneSet |= kZeroS1Set | kZeroS2Set;
2007 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
2008 }
2009 if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
caryclark1049f122015-04-20 08:31:59 -07002010 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07002011 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark1049f122015-04-20 08:31:59 -07002012 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[OppCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07002013 }
2014 // check for one
2015 if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
2016 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[0])) {
2017 zeroOneSet |= kOneS1Set | kZeroS2Set;
2018 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], sect2->fCurve[0]);
2019 }
2020 if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
2021 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[
caryclark1049f122015-04-20 08:31:59 -07002022 OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07002023 zeroOneSet |= kOneS1Set | kOneS2Set;
2024 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
caryclark1049f122015-04-20 08:31:59 -07002025 sect2->fCurve[OppCurve::kPointLast]);
caryclark45fa4472015-01-16 07:04:10 -08002026 }
2027 return zeroOneSet;
2028}
2029
caryclark1049f122015-04-20 08:31:59 -07002030template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002031struct SkClosestRecord {
caryclark54359292015-03-26 07:52:43 -07002032 bool operator<(const SkClosestRecord& rh) const {
2033 return fClosest < rh.fClosest;
2034 }
2035
caryclark45fa4472015-01-16 07:04:10 -08002036 void addIntersection(SkIntersections* intersections) const {
2037 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT();
2038 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT();
2039 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
2040 }
2041
caryclark1049f122015-04-20 08:31:59 -07002042 void findEnd(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2,
caryclark45fa4472015-01-16 07:04:10 -08002043 int c1Index, int c2Index) {
2044 const TCurve& c1 = span1->part();
caryclark1049f122015-04-20 08:31:59 -07002045 const OppCurve& c2 = span2->part();
caryclark45fa4472015-01-16 07:04:10 -08002046 if (!c1[c1Index].approximatelyEqual(c2[c2Index])) {
2047 return;
2048 }
2049 double dist = c1[c1Index].distanceSquared(c2[c2Index]);
2050 if (fClosest < dist) {
2051 return;
2052 }
2053 fC1Span = span1;
2054 fC2Span = span2;
2055 fC1StartT = span1->startT();
2056 fC1EndT = span1->endT();
2057 fC2StartT = span2->startT();
2058 fC2EndT = span2->endT();
2059 fC1Index = c1Index;
2060 fC2Index = c2Index;
2061 fClosest = dist;
2062 }
2063
caryclarkcdeff812016-07-22 03:34:19 -07002064 bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const {
Cary Clark67116382017-01-03 16:25:18 -05002065 SkOPOBJASSERT(i, fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002066 || mate.fC1Span->endT() <= fC1Span->startT());
caryclarkcdeff812016-07-22 03:34:19 -07002067 SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002068 || mate.fC2Span->endT() <= fC2Span->startT());
2069 return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT()
2070 || fC1Span->startT() == mate.fC1Span->endT()
2071 || fC2Span == mate.fC2Span
2072 || fC2Span->endT() == mate.fC2Span->startT()
2073 || fC2Span->startT() == mate.fC2Span->endT();
2074 }
2075
2076 void merge(const SkClosestRecord& mate) {
2077 fC1Span = mate.fC1Span;
2078 fC2Span = mate.fC2Span;
2079 fClosest = mate.fClosest;
2080 fC1Index = mate.fC1Index;
2081 fC2Index = mate.fC2Index;
2082 }
caryclark55888e42016-07-18 10:01:36 -07002083
caryclark45fa4472015-01-16 07:04:10 -08002084 void reset() {
2085 fClosest = FLT_MAX;
halcanary96fcdcc2015-08-27 07:41:13 -07002086 SkDEBUGCODE(fC1Span = nullptr);
2087 SkDEBUGCODE(fC2Span = nullptr);
caryclark45fa4472015-01-16 07:04:10 -08002088 SkDEBUGCODE(fC1Index = fC2Index = -1);
2089 }
2090
2091 void update(const SkClosestRecord& mate) {
2092 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT);
2093 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT);
2094 fC2StartT = SkTMin(fC2StartT, mate.fC2StartT);
2095 fC2EndT = SkTMax(fC2EndT, mate.fC2EndT);
2096 }
2097
caryclark1049f122015-04-20 08:31:59 -07002098 const SkTSpan<TCurve, OppCurve>* fC1Span;
2099 const SkTSpan<OppCurve, TCurve>* fC2Span;
caryclark45fa4472015-01-16 07:04:10 -08002100 double fC1StartT;
2101 double fC1EndT;
2102 double fC2StartT;
2103 double fC2EndT;
2104 double fClosest;
2105 int fC1Index;
2106 int fC2Index;
2107};
2108
caryclark1049f122015-04-20 08:31:59 -07002109template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002110struct SkClosestSect {
2111 SkClosestSect()
2112 : fUsed(0) {
2113 fClosest.push_back().reset();
2114 }
2115
caryclarkcdeff812016-07-22 03:34:19 -07002116 bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2
2117 SkDEBUGPARAMS(SkIntersections* i)) {
caryclark1049f122015-04-20 08:31:59 -07002118 SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed];
caryclark45fa4472015-01-16 07:04:10 -08002119 record->findEnd(span1, span2, 0, 0);
caryclark1049f122015-04-20 08:31:59 -07002120 record->findEnd(span1, span2, 0, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002121 record->findEnd(span1, span2, TCurve::kPointLast, 0);
caryclark1049f122015-04-20 08:31:59 -07002122 record->findEnd(span1, span2, TCurve::kPointLast, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002123 if (record->fClosest == FLT_MAX) {
caryclark54359292015-03-26 07:52:43 -07002124 return false;
caryclark45fa4472015-01-16 07:04:10 -08002125 }
2126 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002127 SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index];
caryclarkcdeff812016-07-22 03:34:19 -07002128 if (test->matesWith(*record SkDEBUGPARAMS(i))) {
caryclark45fa4472015-01-16 07:04:10 -08002129 if (test->fClosest > record->fClosest) {
2130 test->merge(*record);
2131 }
2132 test->update(*record);
2133 record->reset();
caryclark54359292015-03-26 07:52:43 -07002134 return false;
caryclark45fa4472015-01-16 07:04:10 -08002135 }
2136 }
2137 ++fUsed;
2138 fClosest.push_back().reset();
caryclark54359292015-03-26 07:52:43 -07002139 return true;
caryclark45fa4472015-01-16 07:04:10 -08002140 }
2141
2142 void finish(SkIntersections* intersections) const {
caryclark1049f122015-04-20 08:31:59 -07002143 SkSTArray<TCurve::kMaxIntersections * 3,
2144 const SkClosestRecord<TCurve, OppCurve>*, true> closestPtrs;
caryclark45fa4472015-01-16 07:04:10 -08002145 for (int index = 0; index < fUsed; ++index) {
caryclark54359292015-03-26 07:52:43 -07002146 closestPtrs.push_back(&fClosest[index]);
2147 }
caryclark1049f122015-04-20 08:31:59 -07002148 SkTQSort<const SkClosestRecord<TCurve, OppCurve> >(closestPtrs.begin(), closestPtrs.end()
2149 - 1);
caryclark54359292015-03-26 07:52:43 -07002150 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002151 const SkClosestRecord<TCurve, OppCurve>* test = closestPtrs[index];
caryclark54359292015-03-26 07:52:43 -07002152 test->addIntersection(intersections);
caryclark45fa4472015-01-16 07:04:10 -08002153 }
2154 }
2155
caryclark54359292015-03-26 07:52:43 -07002156 // this is oversized so that an extra records can merge into final one
caryclark1049f122015-04-20 08:31:59 -07002157 SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve, OppCurve>, true> fClosest;
caryclark45fa4472015-01-16 07:04:10 -08002158 int fUsed;
2159};
2160
2161// returns true if the rect is too small to consider
caryclark1049f122015-04-20 08:31:59 -07002162template<typename TCurve, typename OppCurve>
2163void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
2164 SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark54359292015-03-26 07:52:43 -07002165#if DEBUG_T_SECT_DUMP > 1
2166 gDumpTSectNum = 0;
2167#endif
caryclark1049f122015-04-20 08:31:59 -07002168 SkDEBUGCODE(sect1->fOppSect = sect2);
2169 SkDEBUGCODE(sect2->fOppSect = sect1);
caryclark45fa4472015-01-16 07:04:10 -08002170 intersections->reset();
caryclarka35ab3e2016-10-20 08:32:18 -07002171 intersections->setMax(TCurve::kMaxIntersections + 4); // give extra for slop
caryclark1049f122015-04-20 08:31:59 -07002172 SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
2173 SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002174 int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
2175// SkASSERT(between(0, sect, 2));
2176 if (!sect) {
caryclark45fa4472015-01-16 07:04:10 -08002177 return;
2178 }
caryclark54359292015-03-26 07:52:43 -07002179 if (sect == 2 && oppSect == 2) {
caryclark45fa4472015-01-16 07:04:10 -08002180 (void) EndsEqual(sect1, sect2, intersections);
2181 return;
2182 }
caryclark54359292015-03-26 07:52:43 -07002183 span1->addBounded(span2, &sect1->fHeap);
2184 span2->addBounded(span1, &sect2->fHeap);
caryclark26ad22a2015-10-16 09:03:38 -07002185 const int kMaxCoinLoopCount = 8;
2186 int coinLoopCount = kMaxCoinLoopCount;
2187 double start1s SK_INIT_TO_AVOID_WARNING;
2188 double start1e SK_INIT_TO_AVOID_WARNING;
caryclark45fa4472015-01-16 07:04:10 -08002189 do {
2190 // find the largest bounds
caryclark1049f122015-04-20 08:31:59 -07002191 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002192 if (!largest1) {
2193 break;
2194 }
caryclark1049f122015-04-20 08:31:59 -07002195 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002196 // split it
caryclark1049f122015-04-20 08:31:59 -07002197 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
2198 || (!largest1->fCollapsed && largest2->fCollapsed)))) {
2199 if (largest1->fCollapsed) {
2200 break;
2201 }
caryclark34efb702016-10-24 08:19:06 -07002202 sect1->resetRemovedEnds();
2203 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002204 // trim parts that don't intersect the opposite
2205 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
caryclark643ede62016-08-08 14:27:45 -07002206 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002207 if (!half1->split(largest1, &sect1->fHeap)) {
2208 break;
2209 }
caryclarka35ab3e2016-10-20 08:32:18 -07002210 if (!sect1->trim(largest1, sect2)) {
2211 SkOPOBJASSERT(intersections, 0);
2212 return;
2213 }
2214 if (!sect1->trim(half1, sect2)) {
2215 SkOPOBJASSERT(intersections, 0);
2216 return;
2217 }
caryclark1049f122015-04-20 08:31:59 -07002218 } else {
2219 if (largest2->fCollapsed) {
2220 break;
2221 }
caryclark34efb702016-10-24 08:19:06 -07002222 sect1->resetRemovedEnds();
2223 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002224 // trim parts that don't intersect the opposite
2225 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
caryclark643ede62016-08-08 14:27:45 -07002226 SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002227 if (!half2->split(largest2, &sect2->fHeap)) {
2228 break;
2229 }
caryclarka35ab3e2016-10-20 08:32:18 -07002230 if (!sect2->trim(largest2, sect1)) {
2231 SkOPOBJASSERT(intersections, 0);
2232 return;
2233 }
2234 if (!sect2->trim(half2, sect1)) {
2235 SkOPOBJASSERT(intersections, 0);
2236 return;
2237 }
caryclark45fa4472015-01-16 07:04:10 -08002238 }
caryclark54359292015-03-26 07:52:43 -07002239 sect1->validate();
2240 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002241#if DEBUG_T_SECT_LOOP_COUNT
2242 intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop);
2243#endif
caryclark45fa4472015-01-16 07:04:10 -08002244 // if there are 9 or more continuous spans on both sects, suspect coincidence
2245 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2246 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
caryclark26ad22a2015-10-16 09:03:38 -07002247 if (coinLoopCount == kMaxCoinLoopCount) {
2248 start1s = sect1->fHead->fStartT;
2249 start1e = sect1->tail()->fEndT;
2250 }
caryclarkef7cee42016-09-06 09:05:54 -07002251 if (!sect1->coincidentCheck(sect2)) {
2252 return;
2253 }
caryclark54359292015-03-26 07:52:43 -07002254 sect1->validate();
2255 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002256#if DEBUG_T_SECT_LOOP_COUNT
2257 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop);
2258#endif
caryclarkef784fb2015-10-30 12:03:06 -07002259 if (!--coinLoopCount && sect1->fHead && sect2->fHead) {
caryclark26ad22a2015-10-16 09:03:38 -07002260 /* All known working cases resolve in two tries. Sadly, cubicConicTests[0]
2261 gets stuck in a loop. It adds an extension to allow a coincident end
2262 perpendicular to track its intersection in the opposite curve. However,
2263 the bounding box of the extension does not intersect the original curve,
caryclark55888e42016-07-18 10:01:36 -07002264 so the extension is discarded, only to be added again the next time around. */
caryclark26ad22a2015-10-16 09:03:38 -07002265 sect1->coincidentForce(sect2, start1s, start1e);
2266 sect1->validate();
2267 sect2->validate();
2268 }
caryclark45fa4472015-01-16 07:04:10 -08002269 }
caryclark54359292015-03-26 07:52:43 -07002270 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2271 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
Cary Clark59ed4822016-12-08 16:17:56 -05002272 if (!sect1->fHead) {
2273 return;
2274 }
caryclark54359292015-03-26 07:52:43 -07002275 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail());
Cary Clark59ed4822016-12-08 16:17:56 -05002276 if (!sect2->fHead) {
2277 return;
2278 }
caryclark54359292015-03-26 07:52:43 -07002279 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail());
Cary Clark0949bee2018-03-19 09:42:00 -04002280 if (!sect1->removeByPerpendicular(sect2)) {
2281 return;
2282 }
caryclark54359292015-03-26 07:52:43 -07002283 sect1->validate();
2284 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002285#if DEBUG_T_SECT_LOOP_COUNT
2286 intersections->debugBumpLoopCount(SkIntersections::kComputePerp_DebugLoop);
2287#endif
caryclark1049f122015-04-20 08:31:59 -07002288 if (sect1->collapsed() > TCurve::kMaxIntersections) {
2289 break;
2290 }
caryclark54359292015-03-26 07:52:43 -07002291 }
2292#if DEBUG_T_SECT_DUMP
2293 sect1->dumpBoth(sect2);
caryclark45fa4472015-01-16 07:04:10 -08002294#endif
2295 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002296 break;
caryclark45fa4472015-01-16 07:04:10 -08002297 }
2298 } while (true);
caryclark1049f122015-04-20 08:31:59 -07002299 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident;
caryclark54359292015-03-26 07:52:43 -07002300 if (coincident) {
2301 // if there is more than one coincident span, check loosely to see if they should be joined
2302 if (coincident->fNext) {
2303 sect1->mergeCoincidence(sect2);
2304 coincident = sect1->fCoincident;
2305 }
2306 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1
caryclark45fa4472015-01-16 07:04:10 -08002307 do {
caryclark221a4bb2016-10-07 11:15:15 -07002308 if (!coincident) {
2309 return;
2310 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002311 if (!coincident->fCoinStart.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002312 continue;
2313 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002314 if (!coincident->fCoinEnd.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002315 continue;
2316 }
Cary Clark67116382017-01-03 16:25:18 -05002317 double perpT = coincident->fCoinStart.perpT();
2318 if (perpT < 0) {
2319 return;
2320 }
caryclark54359292015-03-26 07:52:43 -07002321 int index = intersections->insertCoincident(coincident->fStartT,
Cary Clark67116382017-01-03 16:25:18 -05002322 perpT, coincident->fPart[0]);
caryclark54359292015-03-26 07:52:43 -07002323 if ((intersections->insertCoincident(coincident->fEndT,
2324 coincident->fCoinEnd.perpT(),
2325 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) {
caryclark45fa4472015-01-16 07:04:10 -08002326 intersections->clearCoincidence(index);
2327 }
caryclark54359292015-03-26 07:52:43 -07002328 } while ((coincident = coincident->fNext));
2329 }
caryclark1049f122015-04-20 08:31:59 -07002330 int zeroOneSet = EndsEqual(sect1, sect2, intersections);
caryclark34efb702016-10-24 08:19:06 -07002331// if (!sect1->fHead || !sect2->fHead) {
caryclark6c3b9cd2016-09-26 05:36:58 -07002332 // if the final iteration contains an end (0 or 1),
2333 if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) {
2334 SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular with opposite curve
caryclarka35ab3e2016-10-20 08:32:18 -07002335 perp.setPerp(sect1->fCurve, 0, sect1->fCurve[0], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002336 if (perp.isMatch()) {
2337 intersections->insert(0, perp.perpT(), perp.perpPt());
2338 }
2339 }
2340 if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) {
2341 SkTCoincident<TCurve, OppCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002342 perp.setPerp(sect1->fCurve, 1, sect1->fCurve[TCurve::kPointLast], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002343 if (perp.isMatch()) {
2344 intersections->insert(1, perp.perpT(), perp.perpPt());
2345 }
2346 }
2347 if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) {
2348 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002349 perp.setPerp(sect2->fCurve, 0, sect2->fCurve[0], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002350 if (perp.isMatch()) {
2351 intersections->insert(perp.perpT(), 0, perp.perpPt());
2352 }
2353 }
2354 if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) {
2355 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002356 perp.setPerp(sect2->fCurve, 1, sect2->fCurve[OppCurve::kPointLast], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002357 if (perp.isMatch()) {
2358 intersections->insert(perp.perpT(), 1, perp.perpPt());
2359 }
2360 }
caryclark34efb702016-10-24 08:19:06 -07002361// }
2362 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002363 return;
caryclark45fa4472015-01-16 07:04:10 -08002364 }
caryclark45fa4472015-01-16 07:04:10 -08002365 sect1->recoverCollapsed();
2366 sect2->recoverCollapsed();
caryclark1049f122015-04-20 08:31:59 -07002367 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002368 // check heads and tails for zero and ones and insert them if we haven't already done so
caryclark1049f122015-04-20 08:31:59 -07002369 const SkTSpan<TCurve, OppCurve>* head1 = result1;
caryclark45fa4472015-01-16 07:04:10 -08002370 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) {
2371 const SkDPoint& start1 = sect1->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002372 if (head1->isBounded()) {
2373 double t = head1->closestBoundedT(start1);
2374 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) {
2375 intersections->insert(0, t, start1);
2376 }
caryclark45fa4472015-01-16 07:04:10 -08002377 }
2378 }
caryclark1049f122015-04-20 08:31:59 -07002379 const SkTSpan<OppCurve, TCurve>* head2 = sect2->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002380 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) {
2381 const SkDPoint& start2 = sect2->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002382 if (head2->isBounded()) {
2383 double t = head2->closestBoundedT(start2);
2384 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) {
2385 intersections->insert(t, 0, start2);
2386 }
caryclark45fa4472015-01-16 07:04:10 -08002387 }
2388 }
caryclark1049f122015-04-20 08:31:59 -07002389 const SkTSpan<TCurve, OppCurve>* tail1 = sect1->tail();
caryclark45fa4472015-01-16 07:04:10 -08002390 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT)) {
2391 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002392 if (tail1->isBounded()) {
2393 double t = tail1->closestBoundedT(end1);
2394 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) {
2395 intersections->insert(1, t, end1);
2396 }
caryclark45fa4472015-01-16 07:04:10 -08002397 }
2398 }
caryclark1049f122015-04-20 08:31:59 -07002399 const SkTSpan<OppCurve, TCurve>* tail2 = sect2->tail();
caryclark45fa4472015-01-16 07:04:10 -08002400 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT)) {
caryclark1049f122015-04-20 08:31:59 -07002401 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002402 if (tail2->isBounded()) {
2403 double t = tail2->closestBoundedT(end2);
2404 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
2405 intersections->insert(t, 1, end2);
2406 }
caryclark45fa4472015-01-16 07:04:10 -08002407 }
2408 }
caryclark1049f122015-04-20 08:31:59 -07002409 SkClosestSect<TCurve, OppCurve> closest;
caryclark45fa4472015-01-16 07:04:10 -08002410 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07002411 while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) {
caryclark45fa4472015-01-16 07:04:10 -08002412 result1 = result1->fNext;
2413 }
2414 if (!result1) {
2415 break;
2416 }
caryclark1049f122015-04-20 08:31:59 -07002417 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002418 bool found = false;
caryclark45fa4472015-01-16 07:04:10 -08002419 while (result2) {
caryclarkcdeff812016-07-22 03:34:19 -07002420 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections));
caryclark45fa4472015-01-16 07:04:10 -08002421 result2 = result2->fNext;
2422 }
caryclark45fa4472015-01-16 07:04:10 -08002423 } while ((result1 = result1->fNext));
2424 closest.finish(intersections);
caryclark54359292015-03-26 07:52:43 -07002425 // if there is more than one intersection and it isn't already coincident, check
2426 int last = intersections->used() - 1;
2427 for (int index = 0; index < last; ) {
2428 if (intersections->isCoincident(index) && intersections->isCoincident(index + 1)) {
2429 ++index;
2430 continue;
2431 }
2432 double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
2433 SkDPoint midPt = sect1->fCurve.ptAtT(midT);
2434 // intersect perpendicular with opposite curve
caryclark1049f122015-04-20 08:31:59 -07002435 SkTCoincident<TCurve, OppCurve> perp;
caryclark54359292015-03-26 07:52:43 -07002436 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002437 if (!perp.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07002438 ++index;
2439 continue;
2440 }
2441 if (intersections->isCoincident(index)) {
2442 intersections->removeOne(index);
2443 --last;
2444 } else if (intersections->isCoincident(index + 1)) {
2445 intersections->removeOne(index + 1);
2446 --last;
2447 } else {
2448 intersections->setCoincident(index++);
2449 }
2450 intersections->setCoincident(index);
2451 }
caryclarka35ab3e2016-10-20 08:32:18 -07002452 SkOPOBJASSERT(intersections, intersections->used() <= TCurve::kMaxIntersections);
caryclark45fa4472015-01-16 07:04:10 -08002453}
deanm12670eb2016-04-26 14:09:01 -07002454
2455#endif