blob: b052df97dbf804d1a584a3ebb6c23bd00b4a3ee5 [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"
Hal Canary50dbc092018-06-12 14:50:37 -040011#include "SkIntersections.h"
12#include "SkMacros.h"
caryclark54359292015-03-26 07:52:43 -070013#include "SkPathOpsBounds.h"
caryclark45fa4472015-01-16 07:04:10 -080014#include "SkPathOpsRect.h"
caryclark54359292015-03-26 07:52:43 -070015#include "SkTSort.h"
caryclark45fa4472015-01-16 07:04:10 -080016
caryclarked0935a2015-10-22 07:23:52 -070017#ifdef SK_DEBUG
18typedef uint8_t SkOpDebugBool;
19#else
20typedef bool SkOpDebugBool;
21#endif
22
Cary Clark0949bee2018-03-19 09:42:00 -040023static inline bool SkDoubleIsNaN(double x) {
24 return x != x;
25}
26
caryclark1049f122015-04-20 08:31:59 -070027/* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */
28template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080029class SkTCoincident {
30public:
caryclark697ac1c2015-04-13 09:36:01 -070031 SkTCoincident() {
caryclarkdf386c52015-04-21 05:27:02 -070032 this->init();
caryclark1049f122015-04-20 08:31:59 -070033 }
34
caryclarked0935a2015-10-22 07:23:52 -070035 void debugInit() {
36#ifdef SK_DEBUG
37 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
38 this->fPerpT = SK_ScalarNaN;
caryclark6c3b9cd2016-09-26 05:36:58 -070039 this->fMatch = 0xFF;
caryclarked0935a2015-10-22 07:23:52 -070040#endif
41 }
42
43 char dumpIsCoincidentStr() const;
caryclark1049f122015-04-20 08:31:59 -070044 void dump() const;
45
caryclark6c3b9cd2016-09-26 05:36:58 -070046 bool isMatch() const {
47 SkASSERT(!!fMatch == fMatch);
48 return SkToBool(fMatch);
caryclark45fa4472015-01-16 07:04:10 -080049 }
50
51 void init() {
caryclarkdf386c52015-04-21 05:27:02 -070052 fPerpT = -1;
caryclark6c3b9cd2016-09-26 05:36:58 -070053 fMatch = false;
caryclarkdf386c52015-04-21 05:27:02 -070054 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
caryclark45fa4472015-01-16 07:04:10 -080055 }
56
57 void markCoincident() {
caryclark6c3b9cd2016-09-26 05:36:58 -070058 if (!fMatch) {
caryclark45fa4472015-01-16 07:04:10 -080059 fPerpT = -1;
60 }
caryclark6c3b9cd2016-09-26 05:36:58 -070061 fMatch = true;
caryclark45fa4472015-01-16 07:04:10 -080062 }
63
64 const SkDPoint& perpPt() const {
65 return fPerpPt;
66 }
67
68 double perpT() const {
69 return fPerpT;
70 }
71
caryclark1049f122015-04-20 08:31:59 -070072 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve& );
caryclark45fa4472015-01-16 07:04:10 -080073
74private:
75 SkDPoint fPerpPt;
76 double fPerpT; // perpendicular intersection on opposite curve
caryclark6c3b9cd2016-09-26 05:36:58 -070077 SkOpDebugBool fMatch;
caryclark45fa4472015-01-16 07:04:10 -080078};
79
caryclark1049f122015-04-20 08:31:59 -070080template<typename TCurve, typename OppCurve> class SkTSect;
81template<typename TCurve, typename OppCurve> class SkTSpan;
caryclark54359292015-03-26 07:52:43 -070082
caryclark1049f122015-04-20 08:31:59 -070083template<typename TCurve, typename OppCurve>
caryclark54359292015-03-26 07:52:43 -070084struct SkTSpanBounded {
caryclark1049f122015-04-20 08:31:59 -070085 SkTSpan<TCurve, OppCurve>* fBounded;
caryclark54359292015-03-26 07:52:43 -070086 SkTSpanBounded* fNext;
87};
caryclark45fa4472015-01-16 07:04:10 -080088
89/* Curve is either TCurve or SkDCubic */
caryclark1049f122015-04-20 08:31:59 -070090template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080091class SkTSpan {
92public:
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050093 void addBounded(SkTSpan<OppCurve, TCurve>* , SkArenaAlloc* );
reed0dc4dd62015-03-24 13:55:33 -070094 double closestBoundedT(const SkDPoint& pt) const;
caryclark54359292015-03-26 07:52:43 -070095 bool contains(double t) const;
reed0dc4dd62015-03-24 13:55:33 -070096
caryclark1049f122015-04-20 08:31:59 -070097 void debugInit() {
98 TCurve dummy;
99 dummy.debugInit();
100 init(dummy);
101 initBounds(dummy);
caryclarkdf386c52015-04-21 05:27:02 -0700102 fCoinStart.init();
103 fCoinEnd.init();
caryclark1049f122015-04-20 08:31:59 -0700104 }
105
106 const SkTSect<OppCurve, TCurve>* debugOpp() const;
caryclark643ede62016-08-08 14:27:45 -0700107
108#ifdef SK_DEBUG
109 void debugSetGlobalState(SkOpGlobalState* state) {
110 fDebugGlobalState = state;
111 }
112#endif
113
caryclark54359292015-03-26 07:52:43 -0700114 const SkTSpan* debugSpan(int ) const;
115 const SkTSpan* debugT(double t) const;
116#ifdef SK_DEBUG
117 bool debugIsBefore(const SkTSpan* span) const;
118#endif
119 void dump() const;
caryclark26ad22a2015-10-16 09:03:38 -0700120 void dumpAll() const;
caryclark1049f122015-04-20 08:31:59 -0700121 void dumpBounded(int id) const;
122 void dumpBounds() const;
123 void dumpCoin() const;
caryclark45fa4472015-01-16 07:04:10 -0800124
125 double endT() const {
126 return fEndT;
127 }
128
caryclark1049f122015-04-20 08:31:59 -0700129 SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp) const;
caryclark54359292015-03-26 07:52:43 -0700130
caryclark1049f122015-04-20 08:31:59 -0700131 SkTSpan<OppCurve, TCurve>* findOppT(double t) const {
132 SkTSpan<OppCurve, TCurve>* result = oppT(t);
caryclark643ede62016-08-08 14:27:45 -0700133 SkOPASSERT(result);
caryclark45fa4472015-01-16 07:04:10 -0800134 return result;
135 }
136
caryclark643ede62016-08-08 14:27:45 -0700137 SkDEBUGCODE(SkOpGlobalState* globalState() const { return fDebugGlobalState; })
138
caryclark54359292015-03-26 07:52:43 -0700139 bool hasOppT(double t) const {
140 return SkToBool(oppT(t));
141 }
142
caryclark1049f122015-04-20 08:31:59 -0700143 int hullsIntersect(SkTSpan<OppCurve, TCurve>* span, bool* start, bool* oppStart);
caryclark54359292015-03-26 07:52:43 -0700144 void init(const TCurve& );
caryclarka35ab3e2016-10-20 08:32:18 -0700145 bool initBounds(const TCurve& );
caryclark54359292015-03-26 07:52:43 -0700146
147 bool isBounded() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700148 return fBounded != nullptr;
caryclark54359292015-03-26 07:52:43 -0700149 }
150
caryclark1049f122015-04-20 08:31:59 -0700151 bool linearsIntersect(SkTSpan<OppCurve, TCurve>* span);
caryclark54359292015-03-26 07:52:43 -0700152 double linearT(const SkDPoint& ) const;
153
154 void markCoincident() {
155 fCoinStart.markCoincident();
156 fCoinEnd.markCoincident();
157 }
caryclark45fa4472015-01-16 07:04:10 -0800158
159 const SkTSpan* next() const {
160 return fNext;
161 }
162
caryclark1049f122015-04-20 08:31:59 -0700163 bool onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp, bool* start,
164 bool* oppStart, bool* ptsInCommon);
caryclark54359292015-03-26 07:52:43 -0700165
caryclark45fa4472015-01-16 07:04:10 -0800166 const TCurve& part() const {
167 return fPart;
168 }
169
caryclark54359292015-03-26 07:52:43 -0700170 bool removeAllBounded();
caryclark1049f122015-04-20 08:31:59 -0700171 bool removeBounded(const SkTSpan<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700172
caryclark45fa4472015-01-16 07:04:10 -0800173 void reset() {
halcanary96fcdcc2015-08-27 07:41:13 -0700174 fBounded = nullptr;
caryclark45fa4472015-01-16 07:04:10 -0800175 }
176
caryclark54359292015-03-26 07:52:43 -0700177 void resetBounds(const TCurve& curve) {
178 fIsLinear = fIsLine = false;
179 initBounds(curve);
caryclark45fa4472015-01-16 07:04:10 -0800180 }
181
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500182 bool split(SkTSpan* work, SkArenaAlloc* heap) {
caryclark54359292015-03-26 07:52:43 -0700183 return splitAt(work, (work->fStartT + work->fEndT) * 0.5, heap);
184 }
185
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500186 bool splitAt(SkTSpan* work, double t, SkArenaAlloc* heap);
caryclark45fa4472015-01-16 07:04:10 -0800187
188 double startT() const {
189 return fStartT;
190 }
191
caryclark54359292015-03-26 07:52:43 -0700192private:
caryclark45fa4472015-01-16 07:04:10 -0800193
194 // implementation is for testing only
caryclark54359292015-03-26 07:52:43 -0700195 int debugID() const {
196 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
caryclark45fa4472015-01-16 07:04:10 -0800197 }
198
caryclark54359292015-03-26 07:52:43 -0700199 void dumpID() const;
caryclark45fa4472015-01-16 07:04:10 -0800200
caryclark1049f122015-04-20 08:31:59 -0700201 int hullCheck(const SkTSpan<OppCurve, TCurve>* opp, bool* start, bool* oppStart);
202 int linearIntersects(const OppCurve& ) const;
203 SkTSpan<OppCurve, TCurve>* oppT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800204
caryclark45fa4472015-01-16 07:04:10 -0800205 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700206 void validateBounded() const;
207 void validatePerpT(double oppT) const;
208 void validatePerpPt(double t, const SkDPoint& ) const;
caryclark45fa4472015-01-16 07:04:10 -0800209
210 TCurve fPart;
caryclark1049f122015-04-20 08:31:59 -0700211 SkTCoincident<TCurve, OppCurve> fCoinStart;
212 SkTCoincident<TCurve, OppCurve> fCoinEnd;
213 SkTSpanBounded<OppCurve, TCurve>* fBounded;
caryclark45fa4472015-01-16 07:04:10 -0800214 SkTSpan* fPrev;
215 SkTSpan* fNext;
216 SkDRect fBounds;
217 double fStartT;
218 double fEndT;
219 double fBoundsMax;
caryclarked0935a2015-10-22 07:23:52 -0700220 SkOpDebugBool fCollapsed;
221 SkOpDebugBool fHasPerp;
222 SkOpDebugBool fIsLinear;
223 SkOpDebugBool fIsLine;
224 SkOpDebugBool fDeleted;
caryclark643ede62016-08-08 14:27:45 -0700225 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700226 SkDEBUGCODE(SkTSect<TCurve, OppCurve>* fDebugSect);
caryclark54359292015-03-26 07:52:43 -0700227 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
caryclark1049f122015-04-20 08:31:59 -0700228 friend class SkTSect<TCurve, OppCurve>;
229 friend class SkTSect<OppCurve, TCurve>;
230 friend class SkTSpan<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800231};
232
caryclark1049f122015-04-20 08:31:59 -0700233template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -0800234class SkTSect {
235public:
caryclarke25a4f62016-07-26 09:26:29 -0700236 SkTSect(const TCurve& c SkDEBUGPARAMS(SkOpGlobalState* ) PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
caryclark1049f122015-04-20 08:31:59 -0700237 static void BinarySearch(SkTSect* sect1, SkTSect<OppCurve, TCurve>* sect2,
238 SkIntersections* intersections);
caryclark45fa4472015-01-16 07:04:10 -0800239
caryclarke25a4f62016-07-26 09:26:29 -0700240 SkDEBUGCODE(SkOpGlobalState* globalState() { return fDebugGlobalState; })
Cary Clark0949bee2018-03-19 09:42:00 -0400241 bool hasBounded(const SkTSpan<OppCurve, TCurve>* ) const;
caryclark54359292015-03-26 07:52:43 -0700242
caryclark1049f122015-04-20 08:31:59 -0700243 const SkTSect<OppCurve, TCurve>* debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700244 return SkDEBUGRELEASE(fOppSect, nullptr);
caryclark54359292015-03-26 07:52:43 -0700245 }
246
caryclark1049f122015-04-20 08:31:59 -0700247 const SkTSpan<TCurve, OppCurve>* debugSpan(int id) const;
248 const SkTSpan<TCurve, OppCurve>* debugT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800249 void dump() const;
caryclark1049f122015-04-20 08:31:59 -0700250 void dumpBoth(SkTSect<OppCurve, TCurve>* ) const;
251 void dumpBounded(int id) const;
252 void dumpBounds() const;
caryclark54359292015-03-26 07:52:43 -0700253 void dumpCoin() const;
254 void dumpCoinCurves() const;
caryclark45fa4472015-01-16 07:04:10 -0800255 void dumpCurves() const;
256
257private:
258 enum {
259 kZeroS1Set = 1,
260 kOneS1Set = 2,
261 kZeroS2Set = 4,
262 kOneS2Set = 8
263 };
264
caryclark1049f122015-04-20 08:31:59 -0700265 SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior);
266 void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t);
267 SkTSpan<TCurve, OppCurve>* addOne();
caryclark55888e42016-07-18 10:01:36 -0700268
caryclark1049f122015-04-20 08:31:59 -0700269 SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, double t) {
270 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700271 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700272 result->splitAt(span, t, &fHeap);
273 result->initBounds(fCurve);
274 span->initBounds(fCurve);
275 return result;
276 }
277
caryclark1049f122015-04-20 08:31:59 -0700278 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
Cary Clark74b42902018-03-09 07:38:47 -0500279 double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst);
caryclark1049f122015-04-20 08:31:59 -0700280 SkTSpan<TCurve, OppCurve>* boundsMax() const;
caryclarkef7cee42016-09-06 09:05:54 -0700281 bool coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
caryclark26ad22a2015-10-16 09:03:38 -0700282 void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, double start1e);
caryclark54359292015-03-26 07:52:43 -0700283 bool coincidentHasT(double t);
caryclark1049f122015-04-20 08:31:59 -0700284 int collapsed() const;
285 void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
286 SkTSpan<TCurve, OppCurve>* last);
287 int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
288 SkTSpan<TCurve, OppCurve>** last) const;
caryclarkccec0f92015-03-24 07:28:17 -0700289
caryclark54359292015-03-26 07:52:43 -0700290 int debugID() const {
291 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
292 }
293
caryclarkef7cee42016-09-06 09:05:54 -0700294 bool deleteEmptySpans();
caryclark1049f122015-04-20 08:31:59 -0700295 void dumpCommon(const SkTSpan<TCurve, OppCurve>* ) const;
296 void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const;
297 static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2,
298 SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700299 bool extractCoincident(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
300 SkTSpan<TCurve, OppCurve>* last, SkTSpan<TCurve, OppCurve>** result);
caryclark1049f122015-04-20 08:31:59 -0700301 SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* first,
302 SkTSpan<TCurve, OppCurve>** lastPtr);
303 int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
304 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult);
caryclarked0935a2015-10-22 07:23:52 -0700305 bool isParallel(const SkDLine& thisLine, const SkTSect<OppCurve, TCurve>* opp) const;
caryclark1049f122015-04-20 08:31:59 -0700306 int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
307 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700308 bool markSpanGone(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700309 bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2) const;
310 void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2,
caryclark54359292015-03-26 07:52:43 -0700311 bool* calcMatched, bool* oppMatched) const;
caryclark1049f122015-04-20 08:31:59 -0700312 void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2);
313 SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const;
Cary Clark0949bee2018-03-19 09:42:00 -0400314 bool removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700315 void recoverCollapsed();
Cary Clark38702ab2017-09-05 18:11:55 -0400316 bool removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween);
caryclark1049f122015-04-20 08:31:59 -0700317 void removeAllBut(const SkTSpan<OppCurve, TCurve>* keep, SkTSpan<TCurve, OppCurve>* span,
318 SkTSect<OppCurve, TCurve>* opp);
caryclarkef7cee42016-09-06 09:05:54 -0700319 bool removeSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700320 void removeSpanRange(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last);
Cary Clark0949bee2018-03-19 09:42:00 -0400321 bool removeSpans(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
caryclark34efb702016-10-24 08:19:06 -0700322 void removedEndCheck(SkTSpan<TCurve, OppCurve>* span);
323
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500324 void resetRemovedEnds() {
caryclark34efb702016-10-24 08:19:06 -0700325 fRemovedStartT = fRemovedEndT = false;
326 }
327
caryclark1049f122015-04-20 08:31:59 -0700328 SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
329 SkTSpan<TCurve, OppCurve>* tail();
caryclarka35ab3e2016-10-20 08:32:18 -0700330 bool trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
Cary Clark38702ab2017-09-05 18:11:55 -0400331 bool unlinkSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700332 bool updateBounded(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
333 SkTSpan<OppCurve, TCurve>* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700334 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700335 void validateBounded() const;
336
caryclark45fa4472015-01-16 07:04:10 -0800337 const TCurve& fCurve;
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500338 SkArenaAlloc fHeap;
caryclark1049f122015-04-20 08:31:59 -0700339 SkTSpan<TCurve, OppCurve>* fHead;
340 SkTSpan<TCurve, OppCurve>* fCoincident;
341 SkTSpan<TCurve, OppCurve>* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800342 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700343 bool fRemovedStartT;
344 bool fRemovedEndT;
caryclarke25a4f62016-07-26 09:26:29 -0700345 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700346 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700347 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
348 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800349#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800350 int fDebugAllocatedCount;
351#endif
caryclark1049f122015-04-20 08:31:59 -0700352 friend class SkTSpan<TCurve, OppCurve>;
353 friend class SkTSpan<OppCurve, TCurve>;
354 friend class SkTSect<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800355};
356
357#define COINCIDENT_SPAN_COUNT 9
358
caryclark1049f122015-04-20 08:31:59 -0700359template<typename TCurve, typename OppCurve>
360void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t,
361 const SkDPoint& cPt, const OppCurve& c2) {
caryclark45fa4472015-01-16 07:04:10 -0800362 SkDVector dxdy = c1.dxdyAtT(t);
363 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
caryclarka35ab3e2016-10-20 08:32:18 -0700364 SkIntersections i SkDEBUGCODE((c1.globalState()));
caryclark45fa4472015-01-16 07:04:10 -0800365 int used = i.intersectRay(c2, perp);
366 // only keep closest
caryclark54359292015-03-26 07:52:43 -0700367 if (used == 0 || used == 3) {
caryclarkdf386c52015-04-21 05:27:02 -0700368 this->init();
caryclark45fa4472015-01-16 07:04:10 -0800369 return;
caryclark55888e42016-07-18 10:01:36 -0700370 }
caryclark45fa4472015-01-16 07:04:10 -0800371 fPerpT = i[0][0];
372 fPerpPt = i.pt(0);
373 SkASSERT(used <= 2);
374 if (used == 2) {
375 double distSq = (fPerpPt - cPt).lengthSquared();
376 double dist2Sq = (i.pt(1) - cPt).lengthSquared();
377 if (dist2Sq < distSq) {
378 fPerpT = i[0][1];
379 fPerpPt = i.pt(1);
380 }
381 }
caryclark54359292015-03-26 07:52:43 -0700382#if DEBUG_T_SECT
caryclark1049f122015-04-20 08:31:59 -0700383 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n",
384 t, cPt.fX, cPt.fY,
385 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY);
caryclark54359292015-03-26 07:52:43 -0700386#endif
caryclark6c3b9cd2016-09-26 05:36:58 -0700387 fMatch = cPt.approximatelyEqual(fPerpPt);
caryclark45fa4472015-01-16 07:04:10 -0800388#if DEBUG_T_SECT
caryclark6c3b9cd2016-09-26 05:36:58 -0700389 if (fMatch) {
caryclark45fa4472015-01-16 07:04:10 -0800390 SkDebugf(""); // allow setting breakpoint
391 }
392#endif
393}
394
caryclark1049f122015-04-20 08:31:59 -0700395template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500396void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkArenaAlloc* heap) {
397 SkTSpanBounded<OppCurve, TCurve>* bounded = heap->make<SkTSpanBounded<OppCurve, TCurve>>();
caryclark54359292015-03-26 07:52:43 -0700398 bounded->fBounded = span;
399 bounded->fNext = fBounded;
400 fBounded = bounded;
401}
402
caryclark1049f122015-04-20 08:31:59 -0700403template<typename TCurve, typename OppCurve>
404SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing(
405 SkTSpan<TCurve, OppCurve>* prior) {
406 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700407 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700408 result->fStartT = prior ? prior->fEndT : 0;
caryclark1049f122015-04-20 08:31:59 -0700409 SkTSpan<TCurve, OppCurve>* next = prior ? prior->fNext : fHead;
caryclark54359292015-03-26 07:52:43 -0700410 result->fEndT = next ? next->fStartT : 1;
411 result->fPrev = prior;
412 result->fNext = next;
413 if (prior) {
414 prior->fNext = result;
415 } else {
416 fHead = result;
417 }
418 if (next) {
419 next->fPrev = result;
420 }
421 result->resetBounds(fCurve);
Cary Clarkb8421ed2018-03-14 15:55:02 -0400422 // world may not be consistent to call validate here
caryclark643ede62016-08-08 14:27:45 -0700423 result->validate();
caryclark54359292015-03-26 07:52:43 -0700424 return result;
425}
426
caryclark1049f122015-04-20 08:31:59 -0700427template<typename TCurve, typename OppCurve>
428void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, double t) {
caryclark54359292015-03-26 07:52:43 -0700429 if (!span->hasOppT(t)) {
caryclark1049f122015-04-20 08:31:59 -0700430 SkTSpan<TCurve, OppCurve>* priorSpan;
431 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan);
caryclark54359292015-03-26 07:52:43 -0700432 if (!opp) {
433 opp = this->addFollowing(priorSpan);
434#if DEBUG_PERP
caryclark26ad22a2015-10-16 09:03:38 -0700435 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ?
436 priorSpan->debugID() : -1, t, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700437#endif
438 }
439#if DEBUG_PERP
440 opp->dump(); SkDebugf("\n");
caryclark26ad22a2015-10-16 09:03:38 -0700441 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ?
442 priorSpan->debugID() : -1, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700443#endif
444 opp->addBounded(span, &fHeap);
445 span->addBounded(opp, &fHeap);
446 }
447 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700448#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700449 span->validatePerpT(t);
caryclark1049f122015-04-20 08:31:59 -0700450#endif
caryclark54359292015-03-26 07:52:43 -0700451}
452
caryclark1049f122015-04-20 08:31:59 -0700453template<typename TCurve, typename OppCurve>
454double SkTSpan<TCurve, OppCurve>::closestBoundedT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700455 double result = -1;
caryclark343382e2016-06-29 08:18:38 -0700456 double closest = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -0700457 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700458 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700459 const SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700460 double startDist = test->fPart[0].distanceSquared(pt);
461 if (closest > startDist) {
462 closest = startDist;
463 result = test->fStartT;
464 }
caryclark1049f122015-04-20 08:31:59 -0700465 double endDist = test->fPart[OppCurve::kPointLast].distanceSquared(pt);
caryclark54359292015-03-26 07:52:43 -0700466 if (closest > endDist) {
467 closest = endDist;
468 result = test->fEndT;
469 }
470 testBounded = testBounded->fNext;
471 }
472 SkASSERT(between(0, result, 1));
473 return result;
474}
475
476#ifdef SK_DEBUG
caryclark1049f122015-04-20 08:31:59 -0700477template<typename TCurve, typename OppCurve>
478bool SkTSpan<TCurve, OppCurve>::debugIsBefore(const SkTSpan* span) const {
caryclark54359292015-03-26 07:52:43 -0700479 const SkTSpan* work = this;
480 do {
481 if (span == work) {
482 return true;
483 }
484 } while ((work = work->fNext));
485 return false;
486}
487#endif
488
caryclark1049f122015-04-20 08:31:59 -0700489template<typename TCurve, typename OppCurve>
490bool SkTSpan<TCurve, OppCurve>::contains(double t) const {
caryclark54359292015-03-26 07:52:43 -0700491 const SkTSpan* work = this;
492 do {
493 if (between(work->fStartT, t, work->fEndT)) {
494 return true;
495 }
496 } while ((work = work->fNext));
497 return false;
498}
499
caryclark1049f122015-04-20 08:31:59 -0700500template<typename TCurve, typename OppCurve>
501const SkTSect<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700502 return SkDEBUGRELEASE(fDebugSect->debugOpp(), nullptr);
caryclark54359292015-03-26 07:52:43 -0700503}
504
caryclark1049f122015-04-20 08:31:59 -0700505template<typename TCurve, typename OppCurve>
506SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::findOppSpan(
507 const SkTSpan<OppCurve, TCurve>* opp) const {
508 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700509 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700510 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700511 if (opp == test) {
512 return test;
513 }
514 bounded = bounded->fNext;
515 }
halcanary96fcdcc2015-08-27 07:41:13 -0700516 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700517}
518
519// returns 0 if no hull intersection
520// 1 if hulls intersect
521// 2 if hulls only share a common endpoint
522// -1 if linear and further checking is required
caryclark1049f122015-04-20 08:31:59 -0700523template<typename TCurve, typename OppCurve>
524int SkTSpan<TCurve, OppCurve>::hullCheck(const SkTSpan<OppCurve, TCurve>* opp,
525 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700526 if (fIsLinear) {
527 return -1;
528 }
529 bool ptsInCommon;
530 if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) {
531 SkASSERT(ptsInCommon);
532 return 2;
533 }
534 bool linear;
535 if (fPart.hullIntersects(opp->fPart, &linear)) {
536 if (!linear) { // check set true if linear
537 return 1;
538 }
539 fIsLinear = true;
540 fIsLine = fPart.controlsInside();
caryclark2bec26a2016-05-26 09:01:47 -0700541 return ptsInCommon ? 1 : -1;
caryclark54359292015-03-26 07:52:43 -0700542 } else { // hull is not linear; check set true if intersected at the end points
543 return ((int) ptsInCommon) << 1; // 0 or 2
544 }
545 return 0;
546}
547
548// OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
549// use line intersection to guess a better split than 0.5
550// OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear
caryclark1049f122015-04-20 08:31:59 -0700551template<typename TCurve, typename OppCurve>
552int SkTSpan<TCurve, OppCurve>::hullsIntersect(SkTSpan<OppCurve, TCurve>* opp,
553 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700554 if (!fBounds.intersects(opp->fBounds)) {
555 return 0;
556 }
557 int hullSect = this->hullCheck(opp, start, oppStart);
558 if (hullSect >= 0) {
559 return hullSect;
560 }
561 hullSect = opp->hullCheck(this, oppStart, start);
562 if (hullSect >= 0) {
563 return hullSect;
564 }
565 return -1;
566}
567
caryclark1049f122015-04-20 08:31:59 -0700568template<typename TCurve, typename OppCurve>
569void SkTSpan<TCurve, OppCurve>::init(const TCurve& c) {
halcanary96fcdcc2015-08-27 07:41:13 -0700570 fPrev = fNext = nullptr;
reed0dc4dd62015-03-24 13:55:33 -0700571 fStartT = 0;
572 fEndT = 1;
halcanary96fcdcc2015-08-27 07:41:13 -0700573 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700574 resetBounds(c);
caryclark45fa4472015-01-16 07:04:10 -0800575}
576
caryclark1049f122015-04-20 08:31:59 -0700577template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -0700578bool SkTSpan<TCurve, OppCurve>::initBounds(const TCurve& c) {
Cary Clark0949bee2018-03-19 09:42:00 -0400579 if (SkDoubleIsNaN(fStartT) || SkDoubleIsNaN(fEndT)) {
580 return false;
581 }
reed0dc4dd62015-03-24 13:55:33 -0700582 fPart = c.subDivide(fStartT, fEndT);
583 fBounds.setBounds(fPart);
584 fCoinStart.init();
585 fCoinEnd.init();
586 fBoundsMax = SkTMax(fBounds.width(), fBounds.height());
587 fCollapsed = fPart.collapsed();
588 fHasPerp = false;
caryclark54359292015-03-26 07:52:43 -0700589 fDeleted = false;
reed0dc4dd62015-03-24 13:55:33 -0700590#if DEBUG_T_SECT
reed0dc4dd62015-03-24 13:55:33 -0700591 if (fCollapsed) {
592 SkDebugf(""); // for convenient breakpoints
caryclark45fa4472015-01-16 07:04:10 -0800593 }
594#endif
caryclarka35ab3e2016-10-20 08:32:18 -0700595 return fBounds.valid();
caryclark45fa4472015-01-16 07:04:10 -0800596}
597
caryclark1049f122015-04-20 08:31:59 -0700598template<typename TCurve, typename OppCurve>
599bool SkTSpan<TCurve, OppCurve>::linearsIntersect(SkTSpan<OppCurve, TCurve>* span) {
caryclark54359292015-03-26 07:52:43 -0700600 int result = this->linearIntersects(span->fPart);
601 if (result <= 1) {
602 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800603 }
caryclark54359292015-03-26 07:52:43 -0700604 SkASSERT(span->fIsLinear);
605 result = span->linearIntersects(this->fPart);
606// SkASSERT(result <= 1);
607 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800608}
609
caryclark1049f122015-04-20 08:31:59 -0700610template<typename TCurve, typename OppCurve>
611double SkTSpan<TCurve, OppCurve>::linearT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700612 SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
613 return fabs(len.fX) > fabs(len.fY)
614 ? (pt.fX - fPart[0].fX) / len.fX
615 : (pt.fY - fPart[0].fY) / len.fY;
caryclark45fa4472015-01-16 07:04:10 -0800616}
617
caryclark1049f122015-04-20 08:31:59 -0700618template<typename TCurve, typename OppCurve>
619int SkTSpan<TCurve, OppCurve>::linearIntersects(const OppCurve& q2) const {
caryclark45fa4472015-01-16 07:04:10 -0800620 // looks like q1 is near-linear
caryclark54359292015-03-26 07:52:43 -0700621 int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
caryclark45fa4472015-01-16 07:04:10 -0800622 if (!fPart.controlsInside()) {
623 double dist = 0; // if there's any question, compute distance to find best outsiders
624 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) {
625 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) {
626 double test = (fPart[outer] - fPart[inner]).lengthSquared();
627 if (dist > test) {
628 continue;
629 }
630 dist = test;
631 start = outer;
632 end = inner;
633 }
634 }
635 }
636 // see if q2 is on one side of the line formed by the extreme points
637 double origX = fPart[start].fX;
638 double origY = fPart[start].fY;
639 double adj = fPart[end].fX - origX;
640 double opp = fPart[end].fY - origY;
caryclark54359292015-03-26 07:52:43 -0700641 double maxPart = SkTMax(fabs(adj), fabs(opp));
642 double sign = 0; // initialization to shut up warning in release build
caryclark1049f122015-04-20 08:31:59 -0700643 for (int n = 0; n < OppCurve::kPointCount; ++n) {
caryclark54359292015-03-26 07:52:43 -0700644 double dx = q2[n].fY - origY;
645 double dy = q2[n].fX - origX;
646 double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
caryclark45fa4472015-01-16 07:04:10 -0800647 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp;
caryclark54359292015-03-26 07:52:43 -0700648 if (precisely_zero_when_compared_to(test, maxVal)) {
649 return 1;
650 }
651 if (approximately_zero_when_compared_to(test, maxVal)) {
652 return 3;
caryclark45fa4472015-01-16 07:04:10 -0800653 }
654 if (n == 0) {
655 sign = test;
656 continue;
657 }
658 if (test * sign < 0) {
caryclark54359292015-03-26 07:52:43 -0700659 return 1;
caryclark45fa4472015-01-16 07:04:10 -0800660 }
661 }
caryclark54359292015-03-26 07:52:43 -0700662 return 0;
663}
664
caryclark1049f122015-04-20 08:31:59 -0700665template<typename TCurve, typename OppCurve>
666bool SkTSpan<TCurve, OppCurve>::onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp,
667 bool* start, bool* oppStart, bool* ptsInCommon) {
caryclark54359292015-03-26 07:52:43 -0700668 if (opp->fPart[0] == fPart[0]) {
669 *start = *oppStart = true;
670 } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
671 *start = false;
672 *oppStart = true;
caryclark1049f122015-04-20 08:31:59 -0700673 } else if (opp->fPart[OppCurve::kPointLast] == fPart[0]) {
caryclark54359292015-03-26 07:52:43 -0700674 *start = true;
675 *oppStart = false;
caryclark1049f122015-04-20 08:31:59 -0700676 } else if (opp->fPart[OppCurve::kPointLast] == fPart[TCurve::kPointLast]) {
caryclark54359292015-03-26 07:52:43 -0700677 *start = *oppStart = false;
678 } else {
679 *ptsInCommon = false;
680 return false;
681 }
682 *ptsInCommon = true;
caryclark1049f122015-04-20 08:31:59 -0700683 const SkDPoint* otherPts[TCurve::kPointCount - 1], * oppOtherPts[OppCurve::kPointCount - 1];
caryclark54359292015-03-26 07:52:43 -0700684 int baseIndex = *start ? 0 : TCurve::kPointLast;
caryclark1049f122015-04-20 08:31:59 -0700685 fPart.otherPts(baseIndex, otherPts);
686 opp->fPart.otherPts(*oppStart ? 0 : OppCurve::kPointLast, oppOtherPts);
caryclark54359292015-03-26 07:52:43 -0700687 const SkDPoint& base = fPart[baseIndex];
caryclark1049f122015-04-20 08:31:59 -0700688 for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(otherPts); ++o1) {
689 SkDVector v1 = *otherPts[o1] - base;
690 for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(oppOtherPts); ++o2) {
691 SkDVector v2 = *oppOtherPts[o2] - base;
caryclark54359292015-03-26 07:52:43 -0700692 if (v2.dot(v1) >= 0) {
693 return false;
694 }
695 }
696 }
697 return true;
698}
699
caryclark1049f122015-04-20 08:31:59 -0700700template<typename TCurve, typename OppCurve>
701SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::oppT(double t) const {
702 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700703 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700704 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700705 if (between(test->fStartT, t, test->fEndT)) {
706 return test;
707 }
708 bounded = bounded->fNext;
709 }
halcanary96fcdcc2015-08-27 07:41:13 -0700710 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700711}
712
caryclark1049f122015-04-20 08:31:59 -0700713template<typename TCurve, typename OppCurve>
714bool SkTSpan<TCurve, OppCurve>::removeAllBounded() {
caryclark54359292015-03-26 07:52:43 -0700715 bool deleteSpan = false;
caryclark1049f122015-04-20 08:31:59 -0700716 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700717 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700718 SkTSpan<OppCurve, TCurve>* opp = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700719 deleteSpan |= opp->removeBounded(this);
720 bounded = bounded->fNext;
721 }
722 return deleteSpan;
723}
724
caryclark1049f122015-04-20 08:31:59 -0700725template<typename TCurve, typename OppCurve>
726bool SkTSpan<TCurve, OppCurve>::removeBounded(const SkTSpan<OppCurve, TCurve>* opp) {
caryclark54359292015-03-26 07:52:43 -0700727 if (fHasPerp) {
728 bool foundStart = false;
729 bool foundEnd = false;
caryclark1049f122015-04-20 08:31:59 -0700730 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700731 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700732 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700733 if (opp != test) {
734 foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT);
735 foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
736 }
737 bounded = bounded->fNext;
738 }
739 if (!foundStart || !foundEnd) {
740 fHasPerp = false;
741 fCoinStart.init();
742 fCoinEnd.init();
743 }
744 }
caryclark1049f122015-04-20 08:31:59 -0700745 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700746 SkTSpanBounded<OppCurve, TCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -0700747 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700748 SkTSpanBounded<OppCurve, TCurve>* boundedNext = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -0700749 if (opp == bounded->fBounded) {
750 if (prev) {
751 prev->fNext = boundedNext;
752 return false;
753 } else {
754 fBounded = boundedNext;
halcanary96fcdcc2015-08-27 07:41:13 -0700755 return fBounded == nullptr;
caryclark54359292015-03-26 07:52:43 -0700756 }
757 }
758 prev = bounded;
759 bounded = boundedNext;
760 }
caryclark643ede62016-08-08 14:27:45 -0700761 SkOPASSERT(0);
caryclark45fa4472015-01-16 07:04:10 -0800762 return false;
763}
764
caryclark1049f122015-04-20 08:31:59 -0700765template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500766bool SkTSpan<TCurve, OppCurve>::splitAt(SkTSpan* work, double t, SkArenaAlloc* heap) {
caryclark45fa4472015-01-16 07:04:10 -0800767 fStartT = t;
768 fEndT = work->fEndT;
769 if (fStartT == fEndT) {
770 fCollapsed = true;
771 return false;
772 }
773 work->fEndT = t;
774 if (work->fStartT == work->fEndT) {
775 work->fCollapsed = true;
776 return false;
777 }
778 fPrev = work;
779 fNext = work->fNext;
780 fIsLinear = work->fIsLinear;
caryclark54359292015-03-26 07:52:43 -0700781 fIsLine = work->fIsLine;
782
caryclark45fa4472015-01-16 07:04:10 -0800783 work->fNext = this;
784 if (fNext) {
785 fNext->fPrev = this;
786 }
caryclark643ede62016-08-08 14:27:45 -0700787 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700788 SkTSpanBounded<OppCurve, TCurve>* bounded = work->fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700789 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700790 while (bounded) {
791 this->addBounded(bounded->fBounded, heap);
792 bounded = bounded->fNext;
793 }
794 bounded = fBounded;
795 while (bounded) {
796 bounded->fBounded->addBounded(this, heap);
797 bounded = bounded->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800798 }
799 return true;
800}
801
caryclark1049f122015-04-20 08:31:59 -0700802template<typename TCurve, typename OppCurve>
803void SkTSpan<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -0700804#if DEBUG_VALIDATE
805 SkASSERT(this != fPrev);
806 SkASSERT(this != fNext);
halcanary96fcdcc2015-08-27 07:41:13 -0700807 SkASSERT(fNext == nullptr || fNext != fPrev);
808 SkASSERT(fNext == nullptr || this == fNext->fPrev);
809 SkASSERT(fPrev == nullptr || this == fPrev->fNext);
caryclark643ede62016-08-08 14:27:45 -0700810 this->validateBounded();
811#endif
812#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700813 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed);
caryclarke839e782016-09-15 07:48:18 -0700814 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollapsed == 0xFF);
caryclark45fa4472015-01-16 07:04:10 -0800815 SkASSERT(0 <= fStartT);
816 SkASSERT(fEndT <= 1);
caryclark54359292015-03-26 07:52:43 -0700817 SkASSERT(fStartT <= fEndT);
caryclarke839e782016-09-15 07:48:18 -0700818 SkASSERT(fBounded || fCollapsed == 0xFF);
caryclark54359292015-03-26 07:52:43 -0700819 if (fHasPerp) {
caryclark6c3b9cd2016-09-26 05:36:58 -0700820 if (fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700821 validatePerpT(fCoinStart.perpT());
822 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt());
823 }
caryclark6c3b9cd2016-09-26 05:36:58 -0700824 if (fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700825 validatePerpT(fCoinEnd.perpT());
826 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt());
827 }
caryclarkccec0f92015-03-24 07:28:17 -0700828 }
reed0dc4dd62015-03-24 13:55:33 -0700829#endif
caryclark54359292015-03-26 07:52:43 -0700830}
caryclarkccec0f92015-03-24 07:28:17 -0700831
caryclark1049f122015-04-20 08:31:59 -0700832template<typename TCurve, typename OppCurve>
833void SkTSpan<TCurve, OppCurve>::validateBounded() const {
caryclark54359292015-03-26 07:52:43 -0700834#if DEBUG_VALIDATE
caryclark1049f122015-04-20 08:31:59 -0700835 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700836 while (testBounded) {
csmartdaltonceeaa782016-08-10 10:07:57 -0700837 SkDEBUGCODE(const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded);
caryclark54359292015-03-26 07:52:43 -0700838 SkASSERT(!overlap->fDeleted);
caryclark643ede62016-08-08 14:27:45 -0700839#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700840 SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
841 SkASSERT(overlap->findOppSpan(this));
caryclark643ede62016-08-08 14:27:45 -0700842#endif
caryclark54359292015-03-26 07:52:43 -0700843 testBounded = testBounded->fNext;
844 }
845#endif
846}
847
caryclark1049f122015-04-20 08:31:59 -0700848template<typename TCurve, typename OppCurve>
849void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const {
850 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700851 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700852 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded;
caryclark26ad22a2015-10-16 09:03:38 -0700853 if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) {
caryclark54359292015-03-26 07:52:43 -0700854 return;
855 }
856 testBounded = testBounded->fNext;
857 }
858 SkASSERT(0);
caryclark54359292015-03-26 07:52:43 -0700859}
860
caryclark1049f122015-04-20 08:31:59 -0700861template<typename TCurve, typename OppCurve>
862void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
863 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt);
caryclark54359292015-03-26 07:52:43 -0700864}
865
866
caryclark1049f122015-04-20 08:31:59 -0700867template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500868SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
caryclarke25a4f62016-07-26 09:26:29 -0700869 SkDEBUGPARAMS(SkOpGlobalState* debugGlobalState)
870 PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
caryclark45fa4472015-01-16 07:04:10 -0800871 : fCurve(c)
caryclark1049f122015-04-20 08:31:59 -0700872 , fHeap(sizeof(SkTSpan<TCurve, OppCurve>) * 4)
halcanary96fcdcc2015-08-27 07:41:13 -0700873 , fCoincident(nullptr)
874 , fDeleted(nullptr)
caryclark45fa4472015-01-16 07:04:10 -0800875 , fActiveCount(0)
caryclarke25a4f62016-07-26 09:26:29 -0700876 SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState))
caryclark54359292015-03-26 07:52:43 -0700877 PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
878 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
879 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
caryclark45fa4472015-01-16 07:04:10 -0800880{
caryclark34efb702016-10-24 08:19:06 -0700881 this->resetRemovedEnds();
882 fHead = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700883 SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState));
caryclark45fa4472015-01-16 07:04:10 -0800884 fHead->init(c);
885}
886
caryclark1049f122015-04-20 08:31:59 -0700887template<typename TCurve, typename OppCurve>
888SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
889 SkTSpan<TCurve, OppCurve>* result;
caryclark45fa4472015-01-16 07:04:10 -0800890 if (fDeleted) {
891 result = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800892 fDeleted = result->fNext;
893 } else {
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500894 result = fHeap.make<SkTSpan<TCurve, OppCurve>>();
caryclark45fa4472015-01-16 07:04:10 -0800895#if DEBUG_T_SECT
896 ++fDebugAllocatedCount;
897#endif
898 }
caryclarked0935a2015-10-22 07:23:52 -0700899 result->reset();
caryclark08b32492015-04-06 11:41:29 -0700900 result->fHasPerp = false;
901 result->fDeleted = false;
caryclark55888e42016-07-18 10:01:36 -0700902 ++fActiveCount;
caryclark54359292015-03-26 07:52:43 -0700903 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
caryclark1049f122015-04-20 08:31:59 -0700904 SkDEBUGCODE(result->fDebugSect = this);
caryclarked0935a2015-10-22 07:23:52 -0700905#ifdef SK_DEBUG
906 result->fPart.debugInit();
907 result->fCoinStart.debugInit();
908 result->fCoinEnd.debugInit();
909 result->fPrev = result->fNext = nullptr;
910 result->fBounds.debugInit();
911 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN;
912 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF;
913#endif
caryclark45fa4472015-01-16 07:04:10 -0800914 return result;
915}
916
caryclark1049f122015-04-20 08:31:59 -0700917template<typename TCurve, typename OppCurve>
918bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
Cary Clark74b42902018-03-09 07:38:47 -0500919 double tStep, double* resultT, double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst) {
caryclark1049f122015-04-20 08:31:59 -0700920 SkTSpan<TCurve, OppCurve> work;
caryclark45fa4472015-01-16 07:04:10 -0800921 double result = work.fStartT = work.fEndT = tStart;
caryclark1049f122015-04-20 08:31:59 -0700922 SkDEBUGCODE(work.fDebugSect = this);
caryclark45fa4472015-01-16 07:04:10 -0800923 SkDPoint last = fCurve.ptAtT(tStart);
924 SkDPoint oppPt;
925 bool flip = false;
caryclarkcdeff812016-07-22 03:34:19 -0700926 bool contained = false;
Cary Clark74b42902018-03-09 07:38:47 -0500927 bool down = tStep < 0;
caryclark1049f122015-04-20 08:31:59 -0700928 const OppCurve& opp = sect2->fCurve;
caryclark45fa4472015-01-16 07:04:10 -0800929 do {
930 tStep *= 0.5;
931 work.fStartT += tStep;
932 if (flip) {
933 tStep = -tStep;
934 flip = false;
935 }
936 work.initBounds(fCurve);
937 if (work.fCollapsed) {
938 return false;
939 }
940 if (last.approximatelyEqual(work.fPart[0])) {
941 break;
942 }
943 last = work.fPart[0];
944 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp);
caryclark6c3b9cd2016-09-26 05:36:58 -0700945 if (work.fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700946#if DEBUG_T_SECT
947 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt());
948#endif
caryclark45fa4472015-01-16 07:04:10 -0800949 double oppTTest = work.fCoinStart.perpT();
caryclark54359292015-03-26 07:52:43 -0700950 if (sect2->fHead->contains(oppTTest)) {
caryclark45fa4472015-01-16 07:04:10 -0800951 *oppT = oppTTest;
952 oppPt = work.fCoinStart.perpPt();
caryclarkcdeff812016-07-22 03:34:19 -0700953 contained = true;
Cary Clark74b42902018-03-09 07:38:47 -0500954 if (down ? result <= work.fStartT : result >= work.fStartT) {
955 *oppFirst = nullptr; // signal caller to fail
956 return false;
957 }
caryclark45fa4472015-01-16 07:04:10 -0800958 result = work.fStartT;
959 continue;
960 }
961 }
962 tStep = -tStep;
963 flip = true;
964 } while (true);
caryclarkcdeff812016-07-22 03:34:19 -0700965 if (!contained) {
966 return false;
967 }
caryclark45fa4472015-01-16 07:04:10 -0800968 if (last.approximatelyEqual(fCurve[0])) {
969 result = 0;
970 } else if (last.approximatelyEqual(fCurve[TCurve::kPointLast])) {
971 result = 1;
972 }
973 if (oppPt.approximatelyEqual(opp[0])) {
974 *oppT = 0;
caryclark1049f122015-04-20 08:31:59 -0700975 } else if (oppPt.approximatelyEqual(opp[OppCurve::kPointLast])) {
caryclark45fa4472015-01-16 07:04:10 -0800976 *oppT = 1;
977 }
978 *resultT = result;
979 return true;
980}
981
982// OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
983// so that each quad sect has a pointer to the largest, and can update it as spans
984// are split
caryclark1049f122015-04-20 08:31:59 -0700985template<typename TCurve, typename OppCurve>
986SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
987 SkTSpan<TCurve, OppCurve>* test = fHead;
988 SkTSpan<TCurve, OppCurve>* largest = fHead;
caryclark54359292015-03-26 07:52:43 -0700989 bool lCollapsed = largest->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800990 while ((test = test->fNext)) {
caryclark54359292015-03-26 07:52:43 -0700991 bool tCollapsed = test->fCollapsed;
992 if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
993 largest->fBoundsMax < test->fBoundsMax)) {
caryclark45fa4472015-01-16 07:04:10 -0800994 largest = test;
caryclark1049f122015-04-20 08:31:59 -0700995 lCollapsed = test->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800996 }
997 }
caryclark54359292015-03-26 07:52:43 -0700998 return largest;
caryclark45fa4472015-01-16 07:04:10 -0800999}
1000
caryclark1049f122015-04-20 08:31:59 -07001001template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001002bool SkTSect<TCurve, OppCurve>::coincidentCheck(SkTSect<OppCurve, TCurve>* sect2) {
caryclark1049f122015-04-20 08:31:59 -07001003 SkTSpan<TCurve, OppCurve>* first = fHead;
caryclark9feb6322016-10-25 08:58:26 -07001004 if (!first) {
1005 return false;
1006 }
caryclark1049f122015-04-20 08:31:59 -07001007 SkTSpan<TCurve, OppCurve>* last, * next;
caryclark45fa4472015-01-16 07:04:10 -08001008 do {
caryclark54359292015-03-26 07:52:43 -07001009 int consecutive = this->countConsecutiveSpans(first, &last);
1010 next = last->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001011 if (consecutive < COINCIDENT_SPAN_COUNT) {
1012 continue;
1013 }
caryclark54359292015-03-26 07:52:43 -07001014 this->validate();
1015 sect2->validate();
1016 this->computePerpendiculars(sect2, first, last);
1017 this->validate();
1018 sect2->validate();
caryclark45fa4472015-01-16 07:04:10 -08001019 // check to see if a range of points are on the curve
caryclark1049f122015-04-20 08:31:59 -07001020 SkTSpan<TCurve, OppCurve>* coinStart = first;
caryclark54359292015-03-26 07:52:43 -07001021 do {
caryclarkef7cee42016-09-06 09:05:54 -07001022 bool success = this->extractCoincident(sect2, coinStart, last, &coinStart);
1023 if (!success) {
1024 return false;
1025 }
caryclark54359292015-03-26 07:52:43 -07001026 } while (coinStart && !last->fDeleted);
caryclark55888e42016-07-18 10:01:36 -07001027 if (!fHead || !sect2->fHead) {
1028 break;
1029 }
caryclark643ede62016-08-08 14:27:45 -07001030 if (!next || next->fDeleted) {
1031 break;
1032 }
caryclark45fa4472015-01-16 07:04:10 -08001033 } while ((first = next));
caryclarkef7cee42016-09-06 09:05:54 -07001034 return true;
caryclark45fa4472015-01-16 07:04:10 -08001035}
1036
caryclark1049f122015-04-20 08:31:59 -07001037template<typename TCurve, typename OppCurve>
caryclark26ad22a2015-10-16 09:03:38 -07001038void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2,
1039 double start1s, double start1e) {
1040 SkTSpan<TCurve, OppCurve>* first = fHead;
1041 SkTSpan<TCurve, OppCurve>* last = this->tail();
1042 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead;
1043 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail();
1044 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1045 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
1046 this->removeSpanRange(first, last);
1047 sect2->removeSpanRange(oppFirst, oppLast);
1048 first->fStartT = start1s;
1049 first->fEndT = start1e;
1050 first->resetBounds(fCurve);
1051 first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve);
1052 first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->fCurve);
1053 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
caryclarkef784fb2015-10-30 12:03:06 -07001054 double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : SkTMax(0., first->fCoinStart.perpT());
1055 double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : SkTMin(1., first->fCoinEnd.perpT());
caryclark26ad22a2015-10-16 09:03:38 -07001056 if (!oppMatched) {
1057 SkTSwap(oppStartT, oppEndT);
1058 }
1059 oppFirst->fStartT = oppStartT;
1060 oppFirst->fEndT = oppEndT;
1061 oppFirst->resetBounds(sect2->fCurve);
1062 this->removeCoincident(first, false);
1063 sect2->removeCoincident(oppFirst, true);
1064 if (deleteEmptySpans) {
1065 this->deleteEmptySpans();
1066 sect2->deleteEmptySpans();
1067 }
1068}
1069
1070template<typename TCurve, typename OppCurve>
caryclark1049f122015-04-20 08:31:59 -07001071bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) {
1072 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001073 while (test) {
1074 if (between(test->fStartT, t, test->fEndT)) {
1075 return true;
1076 }
1077 test = test->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001078 }
caryclark54359292015-03-26 07:52:43 -07001079 return false;
caryclark45fa4472015-01-16 07:04:10 -08001080}
1081
caryclark1049f122015-04-20 08:31:59 -07001082template<typename TCurve, typename OppCurve>
1083int SkTSect<TCurve, OppCurve>::collapsed() const {
1084 int result = 0;
1085 const SkTSpan<TCurve, OppCurve>* test = fHead;
1086 while (test) {
1087 if (test->fCollapsed) {
1088 ++result;
1089 }
1090 test = test->next();
1091 }
1092 return result;
1093}
1094
1095template<typename TCurve, typename OppCurve>
1096void SkTSect<TCurve, OppCurve>::computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2,
1097 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
1098 const OppCurve& opp = sect2->fCurve;
1099 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001100 SkTSpan<TCurve, OppCurve>* prior = nullptr;
caryclark45fa4472015-01-16 07:04:10 -08001101 do {
caryclark54359292015-03-26 07:52:43 -07001102 if (!work->fHasPerp && !work->fCollapsed) {
1103 if (prior) {
1104 work->fCoinStart = prior->fCoinEnd;
1105 } else {
1106 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp);
caryclark45fa4472015-01-16 07:04:10 -08001107 }
caryclark6c3b9cd2016-09-26 05:36:58 -07001108 if (work->fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001109 double perpT = work->fCoinStart.perpT();
1110 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001111 work->fCoinStart.init();
caryclark54359292015-03-26 07:52:43 -07001112 } else {
1113 sect2->addForPerp(work, perpT);
1114 }
1115 }
1116 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPointLast], opp);
caryclark6c3b9cd2016-09-26 05:36:58 -07001117 if (work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001118 double perpT = work->fCoinEnd.perpT();
1119 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001120 work->fCoinEnd.init();
caryclark54359292015-03-26 07:52:43 -07001121 } else {
1122 sect2->addForPerp(work, perpT);
1123 }
1124 }
1125 work->fHasPerp = true;
caryclark45fa4472015-01-16 07:04:10 -08001126 }
1127 if (work == last) {
1128 break;
1129 }
caryclark54359292015-03-26 07:52:43 -07001130 prior = work;
caryclark45fa4472015-01-16 07:04:10 -08001131 work = work->fNext;
1132 SkASSERT(work);
1133 } while (true);
caryclark54359292015-03-26 07:52:43 -07001134}
1135
caryclark1049f122015-04-20 08:31:59 -07001136template<typename TCurve, typename OppCurve>
1137int SkTSect<TCurve, OppCurve>::countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
1138 SkTSpan<TCurve, OppCurve>** lastPtr) const {
caryclark54359292015-03-26 07:52:43 -07001139 int consecutive = 1;
caryclark1049f122015-04-20 08:31:59 -07001140 SkTSpan<TCurve, OppCurve>* last = first;
caryclark54359292015-03-26 07:52:43 -07001141 do {
caryclark1049f122015-04-20 08:31:59 -07001142 SkTSpan<TCurve, OppCurve>* next = last->fNext;
caryclark54359292015-03-26 07:52:43 -07001143 if (!next) {
1144 break;
1145 }
1146 if (next->fStartT > last->fEndT) {
1147 break;
1148 }
1149 ++consecutive;
1150 last = next;
1151 } while (true);
1152 *lastPtr = last;
1153 return consecutive;
1154}
1155
caryclark1049f122015-04-20 08:31:59 -07001156template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001157bool SkTSect<TCurve, OppCurve>::hasBounded(const SkTSpan<OppCurve, TCurve>* span) const {
caryclark1049f122015-04-20 08:31:59 -07001158 const SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001159 if (!test) {
1160 return false;
1161 }
1162 do {
1163 if (test->findOppSpan(span)) {
1164 return true;
1165 }
1166 } while ((test = test->next()));
1167 return false;
1168}
1169
caryclark1049f122015-04-20 08:31:59 -07001170template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001171bool SkTSect<TCurve, OppCurve>::deleteEmptySpans() {
caryclark1049f122015-04-20 08:31:59 -07001172 SkTSpan<TCurve, OppCurve>* test;
1173 SkTSpan<TCurve, OppCurve>* next = fHead;
Cary Clark59ed4822016-12-08 16:17:56 -05001174 int safetyHatch = 1000;
caryclark54359292015-03-26 07:52:43 -07001175 while ((test = next)) {
1176 next = test->fNext;
1177 if (!test->fBounded) {
caryclarkef7cee42016-09-06 09:05:54 -07001178 if (!this->removeSpan(test)) {
1179 return false;
1180 }
caryclark54359292015-03-26 07:52:43 -07001181 }
Cary Clark59ed4822016-12-08 16:17:56 -05001182 if (--safetyHatch < 0) {
1183 return false;
1184 }
caryclark54359292015-03-26 07:52:43 -07001185 }
caryclarkef7cee42016-09-06 09:05:54 -07001186 return true;
caryclark54359292015-03-26 07:52:43 -07001187}
1188
caryclark1049f122015-04-20 08:31:59 -07001189template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001190bool SkTSect<TCurve, OppCurve>::extractCoincident(
caryclark1049f122015-04-20 08:31:59 -07001191 SkTSect<OppCurve, TCurve>* sect2,
caryclarkef7cee42016-09-06 09:05:54 -07001192 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
1193 SkTSpan<TCurve, OppCurve>** result) {
caryclark1049f122015-04-20 08:31:59 -07001194 first = findCoincidentRun(first, &last);
caryclarka1b42d92016-08-16 10:25:29 -07001195 if (!first || !last) {
caryclarkef7cee42016-09-06 09:05:54 -07001196 *result = nullptr;
1197 return true;
caryclark45fa4472015-01-16 07:04:10 -08001198 }
1199 // march outwards to find limit of coincidence from here to previous and next spans
1200 double startT = first->fStartT;
caryclarkd8bc16b2015-03-26 09:05:12 -07001201 double oppStartT SK_INIT_TO_AVOID_WARNING;
caryclark54359292015-03-26 07:52:43 -07001202 double oppEndT SK_INIT_TO_AVOID_WARNING;
caryclark1049f122015-04-20 08:31:59 -07001203 SkTSpan<TCurve, OppCurve>* prev = first->fPrev;
caryclark6c3b9cd2016-09-26 05:36:58 -07001204 SkASSERT(first->fCoinStart.isMatch());
caryclark1049f122015-04-20 08:31:59 -07001205 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
caryclark6c3b9cd2016-09-26 05:36:58 -07001206 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001207 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
1208 double coinStart;
1209 SkDEBUGCODE(double coinEnd);
caryclark1049f122015-04-20 08:31:59 -07001210 SkTSpan<OppCurve, TCurve>* cutFirst;
caryclark54359292015-03-26 07:52:43 -07001211 if (prev && prev->fEndT == startT
1212 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
Cary Clark74b42902018-03-09 07:38:47 -05001213 &oppStartT, &oppFirst)
caryclark1049f122015-04-20 08:31:59 -07001214 && prev->fStartT < coinStart && coinStart < startT
1215 && (cutFirst = prev->oppT(oppStartT))) {
1216 oppFirst = cutFirst;
caryclark54359292015-03-26 07:52:43 -07001217 first = this->addSplitAt(prev, coinStart);
1218 first->markCoincident();
1219 prev->fCoinEnd.markCoincident();
1220 if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
caryclark1049f122015-04-20 08:31:59 -07001221 SkTSpan<OppCurve, TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
caryclark54359292015-03-26 07:52:43 -07001222 if (oppMatched) {
1223 oppFirst->fCoinEnd.markCoincident();
1224 oppHalf->markCoincident();
1225 oppFirst = oppHalf;
1226 } else {
1227 oppFirst->markCoincident();
1228 oppHalf->fCoinStart.markCoincident();
1229 }
1230 }
1231 } else {
Cary Clark74b42902018-03-09 07:38:47 -05001232 if (!oppFirst) {
1233 return false;
1234 }
caryclark54359292015-03-26 07:52:43 -07001235 SkDEBUGCODE(coinStart = first->fStartT);
1236 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
1237 }
caryclark1049f122015-04-20 08:31:59 -07001238 // FIXME: incomplete : if we're not at the end, find end of coin
1239 SkTSpan<OppCurve, TCurve>* oppLast;
caryclark6c3b9cd2016-09-26 05:36:58 -07001240 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001241 oppLast = last->findOppT(last->fCoinEnd.perpT());
1242 SkDEBUGCODE(coinEnd = last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001243#ifdef SK_DEBUG
1244 if (!this->globalState() || !this->globalState()->debugSkipAssert()) {
1245 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT;
1246 }
1247#endif
caryclark54359292015-03-26 07:52:43 -07001248 if (!oppMatched) {
1249 SkTSwap(oppFirst, oppLast);
1250 SkTSwap(oppStartT, oppEndT);
1251 }
caryclarke25a4f62016-07-26 09:26:29 -07001252 SkOPASSERT(oppStartT < oppEndT);
caryclark54359292015-03-26 07:52:43 -07001253 SkASSERT(coinStart == first->fStartT);
1254 SkASSERT(coinEnd == last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001255 SkOPASSERT(oppStartT == oppFirst->fStartT);
1256 SkOPASSERT(oppEndT == oppLast->fEndT);
1257 if (!oppFirst) {
caryclarkef7cee42016-09-06 09:05:54 -07001258 *result = nullptr;
1259 return true;
caryclark643ede62016-08-08 14:27:45 -07001260 }
caryclark42942862016-08-19 07:01:33 -07001261 if (!oppLast) {
caryclarkef7cee42016-09-06 09:05:54 -07001262 *result = nullptr;
1263 return true;
caryclark42942862016-08-19 07:01:33 -07001264 }
caryclark54359292015-03-26 07:52:43 -07001265 // reduce coincident runs to single entries
1266 this->validate();
1267 sect2->validate();
caryclark1049f122015-04-20 08:31:59 -07001268 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1269 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
caryclark54359292015-03-26 07:52:43 -07001270 this->removeSpanRange(first, last);
1271 sect2->removeSpanRange(oppFirst, oppLast);
1272 first->fEndT = last->fEndT;
1273 first->resetBounds(this->fCurve);
1274 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], sect2->fCurve);
1275 first->fCoinEnd.setPerp(fCurve, first->fEndT, first->fPart[TCurve::kPointLast], sect2->fCurve);
1276 oppStartT = first->fCoinStart.perpT();
1277 oppEndT = first->fCoinEnd.perpT();
1278 if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) {
1279 if (!oppMatched) {
1280 SkTSwap(oppStartT, oppEndT);
1281 }
1282 oppFirst->fStartT = oppStartT;
1283 oppFirst->fEndT = oppEndT;
1284 oppFirst->resetBounds(sect2->fCurve);
1285 }
1286 this->validateBounded();
1287 sect2->validateBounded();
1288 last = first->fNext;
Cary Clark38702ab2017-09-05 18:11:55 -04001289 if (!this->removeCoincident(first, false)) {
1290 return false;
1291 }
1292 if (!sect2->removeCoincident(oppFirst, true)) {
1293 return false;
1294 }
caryclark1049f122015-04-20 08:31:59 -07001295 if (deleteEmptySpans) {
caryclarkef7cee42016-09-06 09:05:54 -07001296 if (!this->deleteEmptySpans() || !sect2->deleteEmptySpans()) {
1297 *result = nullptr;
1298 return false;
1299 }
caryclark54359292015-03-26 07:52:43 -07001300 }
1301 this->validate();
1302 sect2->validate();
caryclarkef7cee42016-09-06 09:05:54 -07001303 *result = last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr;
1304 return true;
caryclark54359292015-03-26 07:52:43 -07001305}
1306
caryclark1049f122015-04-20 08:31:59 -07001307template<typename TCurve, typename OppCurve>
1308SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun(
1309 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) {
1310 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001311 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr;
1312 first = nullptr;
caryclark54359292015-03-26 07:52:43 -07001313 // find the first fully coincident span
1314 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07001315 if (work->fCoinStart.isMatch()) {
caryclark1049f122015-04-20 08:31:59 -07001316#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -07001317 work->validatePerpT(work->fCoinStart.perpT());
1318 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt());
caryclark1049f122015-04-20 08:31:59 -07001319#endif
caryclarka35ab3e2016-10-20 08:32:18 -07001320 SkOPASSERT(work->hasOppT(work->fCoinStart.perpT()));
caryclark6c3b9cd2016-09-26 05:36:58 -07001321 if (!work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001322 break;
1323 }
1324 lastCandidate = work;
1325 if (!first) {
1326 first = work;
1327 }
caryclark1049f122015-04-20 08:31:59 -07001328 } else if (first && work->fCollapsed) {
1329 *lastPtr = lastCandidate;
1330 return first;
caryclark54359292015-03-26 07:52:43 -07001331 } else {
halcanary96fcdcc2015-08-27 07:41:13 -07001332 lastCandidate = nullptr;
caryclark643ede62016-08-08 14:27:45 -07001333 SkOPASSERT(!first);
caryclark54359292015-03-26 07:52:43 -07001334 }
1335 if (work == *lastPtr) {
1336 return first;
1337 }
1338 work = work->fNext;
caryclarke25a4f62016-07-26 09:26:29 -07001339 if (!work) {
1340 return nullptr;
1341 }
caryclark54359292015-03-26 07:52:43 -07001342 } while (true);
1343 if (lastCandidate) {
1344 *lastPtr = lastCandidate;
1345 }
1346 return first;
1347}
1348
caryclark1049f122015-04-20 08:31:59 -07001349template<typename TCurve, typename OppCurve>
1350int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
1351 SkTSect<OppCurve, TCurve>* opp,
1352 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult) {
caryclark54359292015-03-26 07:52:43 -07001353 bool spanStart, oppStart;
1354 int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
1355 if (hullResult >= 0) {
1356 if (hullResult == 2) { // hulls have one point in common
1357 if (!span->fBounded || !span->fBounded->fNext) {
1358 SkASSERT(!span->fBounded || span->fBounded->fBounded == oppSpan);
1359 if (spanStart) {
1360 span->fEndT = span->fStartT;
caryclark45fa4472015-01-16 07:04:10 -08001361 } else {
caryclark54359292015-03-26 07:52:43 -07001362 span->fStartT = span->fEndT;
1363 }
1364 } else {
1365 hullResult = 1;
1366 }
1367 if (!oppSpan->fBounded || !oppSpan->fBounded->fNext) {
1368 SkASSERT(!oppSpan->fBounded || oppSpan->fBounded->fBounded == span);
1369 if (oppStart) {
1370 oppSpan->fEndT = oppSpan->fStartT;
1371 } else {
1372 oppSpan->fStartT = oppSpan->fEndT;
1373 }
1374 *oppResult = 2;
1375 } else {
1376 *oppResult = 1;
1377 }
1378 } else {
1379 *oppResult = 1;
1380 }
1381 return hullResult;
1382 }
1383 if (span->fIsLine && oppSpan->fIsLine) {
1384 SkIntersections i;
1385 int sects = this->linesIntersect(span, opp, oppSpan, &i);
caryclark26ad22a2015-10-16 09:03:38 -07001386 if (sects == 2) {
1387 return *oppResult = 1;
1388 }
caryclark54359292015-03-26 07:52:43 -07001389 if (!sects) {
1390 return -1;
1391 }
caryclark34efb702016-10-24 08:19:06 -07001392 this->removedEndCheck(span);
caryclark54359292015-03-26 07:52:43 -07001393 span->fStartT = span->fEndT = i[0][0];
caryclark34efb702016-10-24 08:19:06 -07001394 opp->removedEndCheck(oppSpan);
caryclark54359292015-03-26 07:52:43 -07001395 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1396 return *oppResult = 2;
1397 }
1398 if (span->fIsLinear || oppSpan->fIsLinear) {
1399 return *oppResult = (int) span->linearsIntersect(oppSpan);
1400 }
1401 return *oppResult = 1;
1402}
1403
caryclarked0935a2015-10-22 07:23:52 -07001404template<typename TCurve>
1405static bool is_parallel(const SkDLine& thisLine, const TCurve& opp) {
1406 if (!opp.IsConic()) {
1407 return false; // FIXME : breaks a lot of stuff now
1408 }
1409 int finds = 0;
1410 SkDLine thisPerp;
1411 thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1412 thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1413 thisPerp.fPts[1] = thisLine.fPts[1];
1414 SkIntersections perpRayI;
1415 perpRayI.intersectRay(opp, thisPerp);
1416 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1417 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]);
1418 }
1419 thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1420 thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1421 thisPerp.fPts[0] = thisLine.fPts[0];
1422 perpRayI.intersectRay(opp, thisPerp);
1423 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1424 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]);
1425 }
1426 return finds >= 2;
1427}
1428
caryclark54359292015-03-26 07:52:43 -07001429// while the intersection points are sufficiently far apart:
1430// construct the tangent lines from the intersections
1431// find the point where the tangent line intersects the opposite curve
caryclark1049f122015-04-20 08:31:59 -07001432template<typename TCurve, typename OppCurve>
1433int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
1434 SkTSect<OppCurve, TCurve>* opp,
1435 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
caryclarka35ab3e2016-10-20 08:32:18 -07001436 SkIntersections thisRayI SkDEBUGCODE((span->fDebugGlobalState));
1437 SkIntersections oppRayI SkDEBUGCODE((span->fDebugGlobalState));
caryclark54359292015-03-26 07:52:43 -07001438 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
caryclark1049f122015-04-20 08:31:59 -07001439 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
caryclark54359292015-03-26 07:52:43 -07001440 int loopCount = 0;
1441 double bestDistSq = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -07001442 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1443 return 0;
1444 }
1445 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1446 return 0;
1447 }
caryclark26ad22a2015-10-16 09:03:38 -07001448 // if the ends of each line intersect the opposite curve, the lines are coincident
1449 if (thisRayI.used() > 1) {
1450 int ptMatches = 0;
1451 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) {
1452 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1453 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPts[lIndex]);
1454 }
1455 }
caryclarked0935a2015-10-22 07:23:52 -07001456 if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001457 return 2;
1458 }
1459 }
1460 if (oppRayI.used() > 1) {
1461 int ptMatches = 0;
1462 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) {
Cary Clarkd80870f2017-10-17 11:57:26 -04001463 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(oppLine.fPts); ++lIndex) {
caryclark26ad22a2015-10-16 09:03:38 -07001464 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[lIndex]);
1465 }
1466 }
caryclarked0935a2015-10-22 07:23:52 -07001467 if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001468 return 2;
1469 }
1470 }
caryclark54359292015-03-26 07:52:43 -07001471 do {
caryclark54359292015-03-26 07:52:43 -07001472 // pick the closest pair of points
1473 double closest = DBL_MAX;
1474 int closeIndex SK_INIT_TO_AVOID_WARNING;
1475 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1476 for (int index = 0; index < oppRayI.used(); ++index) {
1477 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
1478 continue;
1479 }
1480 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) {
1481 if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppSpan->fEndT)) {
1482 continue;
1483 }
1484 double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oIndex));
1485 if (closest > distSq) {
1486 closest = distSq;
1487 closeIndex = index;
1488 oppCloseIndex = oIndex;
caryclarkccec0f92015-03-24 07:28:17 -07001489 }
caryclarkccec0f92015-03-24 07:28:17 -07001490 }
reed0dc4dd62015-03-24 13:55:33 -07001491 }
caryclark54359292015-03-26 07:52:43 -07001492 if (closest == DBL_MAX) {
caryclark1049f122015-04-20 08:31:59 -07001493 break;
reed0dc4dd62015-03-24 13:55:33 -07001494 }
caryclark54359292015-03-26 07:52:43 -07001495 const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
1496 const SkDPoint& iPt = oppRayI.pt(closeIndex);
1497 if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT)
1498 && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan->fEndT)
1499 && oppIPt.approximatelyEqual(iPt)) {
1500 i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex);
1501 return i->used();
1502 }
1503 double distSq = oppIPt.distanceSquared(iPt);
1504 if (bestDistSq < distSq || ++loopCount > 5) {
caryclark1049f122015-04-20 08:31:59 -07001505 return 0;
caryclark54359292015-03-26 07:52:43 -07001506 }
1507 bestDistSq = distSq;
caryclark1049f122015-04-20 08:31:59 -07001508 double oppStart = oppRayI[0][closeIndex];
1509 thisLine[0] = fCurve.ptAtT(oppStart);
1510 thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart);
1511 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1512 break;
1513 }
1514 double start = thisRayI[0][oppCloseIndex];
1515 oppLine[0] = opp->fCurve.ptAtT(start);
1516 oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start);
1517 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1518 break;
1519 }
caryclark54359292015-03-26 07:52:43 -07001520 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001521 // convergence may fail if the curves are nearly coincident
1522 SkTCoincident<OppCurve, TCurve> oCoinS, oCoinE;
1523 oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->fPart[0], fCurve);
1524 oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->fPart[OppCurve::kPointLast], fCurve);
1525 double tStart = oCoinS.perpT();
1526 double tEnd = oCoinE.perpT();
1527 bool swap = tStart > tEnd;
1528 if (swap) {
1529 SkTSwap(tStart, tEnd);
1530 }
1531 tStart = SkTMax(tStart, span->fStartT);
1532 tEnd = SkTMin(tEnd, span->fEndT);
1533 if (tStart > tEnd) {
1534 return 0;
1535 }
1536 SkDVector perpS, perpE;
1537 if (tStart == span->fStartT) {
1538 SkTCoincident<TCurve, OppCurve> coinS;
1539 coinS.setPerp(fCurve, span->fStartT, span->fPart[0], opp->fCurve);
1540 perpS = span->fPart[0] - coinS.perpPt();
1541 } else if (swap) {
1542 perpS = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1543 } else {
1544 perpS = oCoinS.perpPt() - oppSpan->fPart[0];
1545 }
1546 if (tEnd == span->fEndT) {
1547 SkTCoincident<TCurve, OppCurve> coinE;
1548 coinE.setPerp(fCurve, span->fEndT, span->fPart[TCurve::kPointLast], opp->fCurve);
1549 perpE = span->fPart[TCurve::kPointLast] - coinE.perpPt();
1550 } else if (swap) {
1551 perpE = oCoinS.perpPt() - oppSpan->fPart[0];
1552 } else {
1553 perpE = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1554 }
1555 if (perpS.dot(perpE) >= 0) {
1556 return 0;
1557 }
1558 SkTCoincident<TCurve, OppCurve> coinW;
1559 double workT = tStart;
1560 double tStep = tEnd - tStart;
1561 SkDPoint workPt;
1562 do {
1563 tStep *= 0.5;
1564 if (precisely_zero(tStep)) {
1565 return 0;
1566 }
1567 workT += tStep;
1568 workPt = fCurve.ptAtT(workT);
1569 coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
caryclark27c015d2016-09-23 05:47:20 -07001570 double perpT = coinW.perpT();
caryclark6c3b9cd2016-09-26 05:36:58 -07001571 if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) {
caryclarkb6693002015-12-16 12:28:35 -08001572 continue;
1573 }
caryclark1049f122015-04-20 08:31:59 -07001574 SkDVector perpW = workPt - coinW.perpPt();
1575 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
1576 tStep = -tStep;
1577 }
caryclarkb6693002015-12-16 12:28:35 -08001578 if (workPt.approximatelyEqual(coinW.perpPt())) {
1579 break;
1580 }
1581 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001582 double oppTTest = coinW.perpT();
1583 if (!opp->fHead->contains(oppTTest)) {
1584 return 0;
1585 }
1586 i->setMax(1);
1587 i->insert(workT, oppTTest, workPt);
1588 return 1;
caryclark54359292015-03-26 07:52:43 -07001589}
1590
1591
caryclark1049f122015-04-20 08:31:59 -07001592template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001593bool SkTSect<TCurve, OppCurve>::markSpanGone(SkTSpan<TCurve, OppCurve>* span) {
1594 if (--fActiveCount < 0) {
1595 return false;
1596 }
caryclark54359292015-03-26 07:52:43 -07001597 span->fNext = fDeleted;
1598 fDeleted = span;
caryclarke25a4f62016-07-26 09:26:29 -07001599 SkOPASSERT(!span->fDeleted);
caryclark54359292015-03-26 07:52:43 -07001600 span->fDeleted = true;
caryclarkef7cee42016-09-06 09:05:54 -07001601 return true;
caryclark54359292015-03-26 07:52:43 -07001602}
1603
caryclark1049f122015-04-20 08:31:59 -07001604template<typename TCurve, typename OppCurve>
1605bool SkTSect<TCurve, OppCurve>::matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2,
1606 double t2) const {
caryclark54359292015-03-26 07:52:43 -07001607 SkDVector dxdy = this->fCurve.dxdyAtT(t);
1608 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
1609 return dxdy.dot(dxdy2) >= 0;
1610}
1611
caryclark1049f122015-04-20 08:31:59 -07001612template<typename TCurve, typename OppCurve>
1613void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2,
1614 double t2, bool* calcMatched, bool* oppMatched) const {
caryclark54359292015-03-26 07:52:43 -07001615 if (*calcMatched) {
caryclark55888e42016-07-18 10:01:36 -07001616 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
caryclark54359292015-03-26 07:52:43 -07001617 } else {
1618 *oppMatched = this->matchedDirection(t, sect2, t2);
1619 *calcMatched = true;
1620 }
1621}
1622
caryclark1049f122015-04-20 08:31:59 -07001623template<typename TCurve, typename OppCurve>
1624void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2) {
caryclark54359292015-03-26 07:52:43 -07001625 double smallLimit = 0;
1626 do {
1627 // find the smallest unprocessed span
halcanary96fcdcc2015-08-27 07:41:13 -07001628 SkTSpan<TCurve, OppCurve>* smaller = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001629 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001630 do {
caryclark221a4bb2016-10-07 11:15:15 -07001631 if (!test) {
1632 return;
1633 }
caryclark54359292015-03-26 07:52:43 -07001634 if (test->fStartT < smallLimit) {
1635 continue;
1636 }
1637 if (smaller && smaller->fEndT < test->fStartT) {
1638 continue;
1639 }
1640 smaller = test;
1641 } while ((test = test->fNext));
1642 if (!smaller) {
1643 return;
1644 }
1645 smallLimit = smaller->fEndT;
1646 // find next larger span
halcanary96fcdcc2015-08-27 07:41:13 -07001647 SkTSpan<TCurve, OppCurve>* prior = nullptr;
1648 SkTSpan<TCurve, OppCurve>* larger = nullptr;
1649 SkTSpan<TCurve, OppCurve>* largerPrior = nullptr;
caryclark54359292015-03-26 07:52:43 -07001650 test = fCoincident;
1651 do {
1652 if (test->fStartT < smaller->fEndT) {
1653 continue;
1654 }
caryclark221a4bb2016-10-07 11:15:15 -07001655 SkOPASSERT(test->fStartT != smaller->fEndT);
caryclark54359292015-03-26 07:52:43 -07001656 if (larger && larger->fStartT < test->fStartT) {
1657 continue;
1658 }
1659 largerPrior = prior;
1660 larger = test;
1661 } while ((prior = test), (test = test->fNext));
1662 if (!larger) {
1663 continue;
1664 }
1665 // check middle t value to see if it is coincident as well
1666 double midT = (smaller->fEndT + larger->fStartT) / 2;
1667 SkDPoint midPt = fCurve.ptAtT(midT);
caryclark1049f122015-04-20 08:31:59 -07001668 SkTCoincident<TCurve, OppCurve> coin;
caryclark54359292015-03-26 07:52:43 -07001669 coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07001670 if (coin.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001671 smaller->fEndT = larger->fEndT;
1672 smaller->fCoinEnd = larger->fCoinEnd;
1673 if (largerPrior) {
1674 largerPrior->fNext = larger->fNext;
caryclark643ede62016-08-08 14:27:45 -07001675 largerPrior->validate();
caryclark54359292015-03-26 07:52:43 -07001676 } else {
1677 fCoincident = larger->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001678 }
1679 }
caryclark54359292015-03-26 07:52:43 -07001680 } while (true);
1681}
1682
caryclark1049f122015-04-20 08:31:59 -07001683template<typename TCurve, typename OppCurve>
1684SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev(
1685 SkTSpan<TCurve, OppCurve>* span) const {
halcanary96fcdcc2015-08-27 07:41:13 -07001686 SkTSpan<TCurve, OppCurve>* result = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001687 SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001688 while (span != test) {
1689 result = test;
1690 test = test->fNext;
1691 SkASSERT(test);
caryclarkccec0f92015-03-24 07:28:17 -07001692 }
caryclark55888e42016-07-18 10:01:36 -07001693 return result;
caryclarkccec0f92015-03-24 07:28:17 -07001694}
1695
caryclark1049f122015-04-20 08:31:59 -07001696template<typename TCurve, typename OppCurve>
1697void SkTSect<TCurve, OppCurve>::recoverCollapsed() {
1698 SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001699 while (deleted) {
caryclark1049f122015-04-20 08:31:59 -07001700 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001701 if (deleted->fCollapsed) {
caryclark1049f122015-04-20 08:31:59 -07001702 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead;
caryclark45fa4472015-01-16 07:04:10 -08001703 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
1704 spanPtr = &(*spanPtr)->fNext;
1705 }
1706 deleted->fNext = *spanPtr;
1707 *spanPtr = deleted;
1708 }
1709 deleted = delNext;
1710 }
1711}
1712
caryclark1049f122015-04-20 08:31:59 -07001713template<typename TCurve, typename OppCurve>
1714void SkTSect<TCurve, OppCurve>::removeAllBut(const SkTSpan<OppCurve, TCurve>* keep,
1715 SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp) {
1716 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001717 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001718 SkTSpan<OppCurve, TCurve>* bounded = testBounded->fBounded;
1719 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001720 // may have been deleted when opp did 'remove all but'
1721 if (bounded != keep && !bounded->fDeleted) {
1722 SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
1723 if (bounded->removeBounded(span)) {
1724 opp->removeSpan(bounded);
1725 }
caryclarkccec0f92015-03-24 07:28:17 -07001726 }
caryclark54359292015-03-26 07:52:43 -07001727 testBounded = next;
caryclarkccec0f92015-03-24 07:28:17 -07001728 }
caryclark54359292015-03-26 07:52:43 -07001729 SkASSERT(!span->fDeleted);
1730 SkASSERT(span->findOppSpan(keep));
1731 SkASSERT(keep->findOppSpan(span));
caryclarkccec0f92015-03-24 07:28:17 -07001732}
1733
caryclark1049f122015-04-20 08:31:59 -07001734template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001735bool SkTSect<TCurve, OppCurve>::removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp) {
caryclark1049f122015-04-20 08:31:59 -07001736 SkTSpan<TCurve, OppCurve>* test = fHead;
1737 SkTSpan<TCurve, OppCurve>* next;
caryclark54359292015-03-26 07:52:43 -07001738 do {
1739 next = test->fNext;
1740 if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
1741 continue;
reed0dc4dd62015-03-24 13:55:33 -07001742 }
caryclark54359292015-03-26 07:52:43 -07001743 SkDVector startV = test->fCoinStart.perpPt() - test->fPart[0];
1744 SkDVector endV = test->fCoinEnd.perpPt() - test->fPart[TCurve::kPointLast];
1745#if DEBUG_T_SECT
1746 SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUNCTION__,
1747 startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV));
1748#endif
1749 if (startV.dot(endV) <= 0) {
1750 continue;
1751 }
Cary Clark0949bee2018-03-19 09:42:00 -04001752 if (!this->removeSpans(test, opp)) {
1753 return false;
1754 }
caryclark54359292015-03-26 07:52:43 -07001755 } while ((test = next));
Cary Clark0949bee2018-03-19 09:42:00 -04001756 return true;
caryclark54359292015-03-26 07:52:43 -07001757}
1758
caryclark1049f122015-04-20 08:31:59 -07001759template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001760bool SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween) {
1761 if (!this->unlinkSpan(span)) {
1762 return false;
1763 }
caryclark54359292015-03-26 07:52:43 -07001764 if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
1765 --fActiveCount;
1766 span->fNext = fCoincident;
1767 fCoincident = span;
1768 } else {
1769 this->markSpanGone(span);
reed0dc4dd62015-03-24 13:55:33 -07001770 }
Cary Clark38702ab2017-09-05 18:11:55 -04001771 return true;
caryclarkccec0f92015-03-24 07:28:17 -07001772}
1773
caryclark1049f122015-04-20 08:31:59 -07001774template<typename TCurve, typename OppCurve>
caryclark34efb702016-10-24 08:19:06 -07001775void SkTSect<TCurve, OppCurve>::removedEndCheck(SkTSpan<TCurve, OppCurve>* span) {
caryclark6c3b9cd2016-09-26 05:36:58 -07001776 if (!span->fStartT) {
1777 fRemovedStartT = true;
1778 }
1779 if (1 == span->fEndT) {
1780 fRemovedEndT = true;
1781 }
caryclark34efb702016-10-24 08:19:06 -07001782}
1783
1784template<typename TCurve, typename OppCurve>
1785bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {\
1786 this->removedEndCheck(span);
Cary Clark38702ab2017-09-05 18:11:55 -04001787 if (!this->unlinkSpan(span)) {
1788 return false;
1789 }
caryclarkef7cee42016-09-06 09:05:54 -07001790 return this->markSpanGone(span);
caryclark54359292015-03-26 07:52:43 -07001791}
1792
caryclark1049f122015-04-20 08:31:59 -07001793template<typename TCurve, typename OppCurve>
1794void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first,
1795 SkTSpan<TCurve, OppCurve>* last) {
caryclark54359292015-03-26 07:52:43 -07001796 if (first == last) {
1797 return;
1798 }
caryclark1049f122015-04-20 08:31:59 -07001799 SkTSpan<TCurve, OppCurve>* span = first;
caryclark54359292015-03-26 07:52:43 -07001800 SkASSERT(span);
caryclark1049f122015-04-20 08:31:59 -07001801 SkTSpan<TCurve, OppCurve>* final = last->fNext;
1802 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001803 while ((span = next) && span != final) {
1804 next = span->fNext;
1805 this->markSpanGone(span);
1806 }
1807 if (final) {
1808 final->fPrev = first;
1809 }
1810 first->fNext = final;
Cary Clarkb8421ed2018-03-14 15:55:02 -04001811 // world may not be ready for validation here
caryclark643ede62016-08-08 14:27:45 -07001812 first->validate();
caryclark54359292015-03-26 07:52:43 -07001813}
1814
caryclark1049f122015-04-20 08:31:59 -07001815template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001816bool SkTSect<TCurve, OppCurve>::removeSpans(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001817 SkTSect<OppCurve, TCurve>* opp) {
1818 SkTSpanBounded<OppCurve, TCurve>* bounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001819 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -07001820 SkTSpan<OppCurve, TCurve>* spanBounded = bounded->fBounded;
1821 SkTSpanBounded<OppCurve, TCurve>* next = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001822 if (span->removeBounded(spanBounded)) { // shuffles last into position 0
1823 this->removeSpan(span);
1824 }
1825 if (spanBounded->removeBounded(span)) {
1826 opp->removeSpan(spanBounded);
1827 }
Cary Clark0949bee2018-03-19 09:42:00 -04001828 if (span->fDeleted && opp->hasBounded(span)) {
1829 return false;
1830 }
caryclark54359292015-03-26 07:52:43 -07001831 bounded = next;
reed0dc4dd62015-03-24 13:55:33 -07001832 }
Cary Clark0949bee2018-03-19 09:42:00 -04001833 return true;
reed0dc4dd62015-03-24 13:55:33 -07001834}
caryclarkccec0f92015-03-24 07:28:17 -07001835
caryclark1049f122015-04-20 08:31:59 -07001836template<typename TCurve, typename OppCurve>
1837SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::spanAtT(double t,
1838 SkTSpan<TCurve, OppCurve>** priorSpan) {
1839 SkTSpan<TCurve, OppCurve>* test = fHead;
halcanary96fcdcc2015-08-27 07:41:13 -07001840 SkTSpan<TCurve, OppCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -07001841 while (test && test->fEndT < t) {
1842 prev = test;
1843 test = test->fNext;
reed0dc4dd62015-03-24 13:55:33 -07001844 }
caryclark54359292015-03-26 07:52:43 -07001845 *priorSpan = prev;
halcanary96fcdcc2015-08-27 07:41:13 -07001846 return test && test->fStartT <= t ? test : nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001847}
1848
caryclark1049f122015-04-20 08:31:59 -07001849template<typename TCurve, typename OppCurve>
1850SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::tail() {
1851 SkTSpan<TCurve, OppCurve>* result = fHead;
1852 SkTSpan<TCurve, OppCurve>* next = fHead;
reed0dc4dd62015-03-24 13:55:33 -07001853 while ((next = next->fNext)) {
1854 if (next->fEndT > result->fEndT) {
1855 result = next;
1856 }
1857 }
1858 return result;
1859}
1860
1861/* Each span has a range of opposite spans it intersects. After the span is split in two,
1862 adjust the range to its new size */
caryclark1049f122015-04-20 08:31:59 -07001863template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -07001864bool SkTSect<TCurve, OppCurve>::trim(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001865 SkTSect<OppCurve, TCurve>* opp) {
caryclarka35ab3e2016-10-20 08:32:18 -07001866 FAIL_IF(!span->initBounds(fCurve));
caryclark1049f122015-04-20 08:31:59 -07001867 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001868 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001869 SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
1870 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001871 int oppSects, sects = this->intersects(span, opp, test, &oppSects);
1872 if (sects >= 1) {
1873 if (oppSects == 2) {
1874 test->initBounds(opp->fCurve);
1875 opp->removeAllBut(span, test, this);
1876 }
1877 if (sects == 2) {
1878 span->initBounds(fCurve);
1879 this->removeAllBut(test, span, opp);
caryclarka35ab3e2016-10-20 08:32:18 -07001880 return true;
caryclark54359292015-03-26 07:52:43 -07001881 }
reed0dc4dd62015-03-24 13:55:33 -07001882 } else {
caryclark54359292015-03-26 07:52:43 -07001883 if (span->removeBounded(test)) {
1884 this->removeSpan(span);
1885 }
1886 if (test->removeBounded(span)) {
1887 opp->removeSpan(test);
1888 }
1889 }
1890 testBounded = next;
1891 }
caryclarka35ab3e2016-10-20 08:32:18 -07001892 return true;
caryclark54359292015-03-26 07:52:43 -07001893}
1894
caryclark1049f122015-04-20 08:31:59 -07001895template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001896bool SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) {
caryclark1049f122015-04-20 08:31:59 -07001897 SkTSpan<TCurve, OppCurve>* prev = span->fPrev;
1898 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001899 if (prev) {
1900 prev->fNext = next;
1901 if (next) {
1902 next->fPrev = prev;
Cary Clark38702ab2017-09-05 18:11:55 -04001903 if (next->fStartT > next->fEndT) {
1904 return false;
1905 }
Cary Clarkb8421ed2018-03-14 15:55:02 -04001906 // world may not be ready for validate here
caryclark643ede62016-08-08 14:27:45 -07001907 next->validate();
caryclark54359292015-03-26 07:52:43 -07001908 }
1909 } else {
1910 fHead = next;
1911 if (next) {
halcanary96fcdcc2015-08-27 07:41:13 -07001912 next->fPrev = nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001913 }
1914 }
Cary Clark38702ab2017-09-05 18:11:55 -04001915 return true;
reed0dc4dd62015-03-24 13:55:33 -07001916}
1917
caryclark1049f122015-04-20 08:31:59 -07001918template<typename TCurve, typename OppCurve>
1919bool SkTSect<TCurve, OppCurve>::updateBounded(SkTSpan<TCurve, OppCurve>* first,
1920 SkTSpan<TCurve, OppCurve>* last, SkTSpan<OppCurve, TCurve>* oppFirst) {
1921 SkTSpan<TCurve, OppCurve>* test = first;
1922 const SkTSpan<TCurve, OppCurve>* final = last->next();
caryclark54359292015-03-26 07:52:43 -07001923 bool deleteSpan = false;
1924 do {
1925 deleteSpan |= test->removeAllBounded();
caryclarke25a4f62016-07-26 09:26:29 -07001926 } while ((test = test->fNext) != final && test);
halcanary96fcdcc2015-08-27 07:41:13 -07001927 first->fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -07001928 first->addBounded(oppFirst, &fHeap);
1929 // cannot call validate until remove span range is called
1930 return deleteSpan;
1931}
1932
1933
caryclark1049f122015-04-20 08:31:59 -07001934template<typename TCurve, typename OppCurve>
1935void SkTSect<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -07001936#if DEBUG_VALIDATE
caryclark45fa4472015-01-16 07:04:10 -08001937 int count = 0;
caryclark643ede62016-08-08 14:27:45 -07001938 double last = 0;
caryclark45fa4472015-01-16 07:04:10 -08001939 if (fHead) {
caryclark1049f122015-04-20 08:31:59 -07001940 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark45fa4472015-01-16 07:04:10 -08001941 SkASSERT(!span->fPrev);
caryclark643ede62016-08-08 14:27:45 -07001942 const SkTSpan<TCurve, OppCurve>* next;
caryclark45fa4472015-01-16 07:04:10 -08001943 do {
1944 span->validate();
1945 SkASSERT(span->fStartT >= last);
caryclark643ede62016-08-08 14:27:45 -07001946 last = span->fEndT;
caryclark45fa4472015-01-16 07:04:10 -08001947 ++count;
caryclark643ede62016-08-08 14:27:45 -07001948 next = span->fNext;
1949 SkASSERT(next != span);
1950 } while ((span = next) != nullptr);
caryclark45fa4472015-01-16 07:04:10 -08001951 }
1952 SkASSERT(count == fActiveCount);
caryclark643ede62016-08-08 14:27:45 -07001953#endif
1954#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -08001955 SkASSERT(fActiveCount <= fDebugAllocatedCount);
1956 int deletedCount = 0;
caryclark1049f122015-04-20 08:31:59 -07001957 const SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001958 while (deleted) {
1959 ++deletedCount;
1960 deleted = deleted->fNext;
1961 }
caryclark1049f122015-04-20 08:31:59 -07001962 const SkTSpan<TCurve, OppCurve>* coincident = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001963 while (coincident) {
1964 ++deletedCount;
1965 coincident = coincident->fNext;
1966 }
caryclark45fa4472015-01-16 07:04:10 -08001967 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount);
caryclarkccec0f92015-03-24 07:28:17 -07001968#endif
caryclark54359292015-03-26 07:52:43 -07001969}
1970
caryclark1049f122015-04-20 08:31:59 -07001971template<typename TCurve, typename OppCurve>
1972void SkTSect<TCurve, OppCurve>::validateBounded() const {
caryclark643ede62016-08-08 14:27:45 -07001973#if DEBUG_VALIDATE
caryclark54359292015-03-26 07:52:43 -07001974 if (!fHead) {
1975 return;
1976 }
caryclark1049f122015-04-20 08:31:59 -07001977 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark54359292015-03-26 07:52:43 -07001978 do {
1979 span->validateBounded();
halcanary96fcdcc2015-08-27 07:41:13 -07001980 } while ((span = span->fNext) != nullptr);
caryclark54359292015-03-26 07:52:43 -07001981#endif
1982}
caryclark45fa4472015-01-16 07:04:10 -08001983
caryclark1049f122015-04-20 08:31:59 -07001984template<typename TCurve, typename OppCurve>
1985int SkTSect<TCurve, OppCurve>::EndsEqual(const SkTSect<TCurve, OppCurve>* sect1,
1986 const SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark45fa4472015-01-16 07:04:10 -08001987 int zeroOneSet = 0;
caryclark54359292015-03-26 07:52:43 -07001988 if (sect1->fCurve[0] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001989 zeroOneSet |= kZeroS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001990 intersections->insert(0, 0, sect1->fCurve[0]);
1991 }
caryclark1049f122015-04-20 08:31:59 -07001992 if (sect1->fCurve[0] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001993 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark54359292015-03-26 07:52:43 -07001994 intersections->insert(0, 1, sect1->fCurve[0]);
1995 }
1996 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001997 zeroOneSet |= kOneS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001998 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
1999 }
caryclark1049f122015-04-20 08:31:59 -07002000 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07002001 zeroOneSet |= kOneS1Set | kOneS2Set;
reed0dc4dd62015-03-24 13:55:33 -07002002 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07002003 }
2004 // check for zero
2005 if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set))
2006 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) {
2007 zeroOneSet |= kZeroS1Set | kZeroS2Set;
2008 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
2009 }
2010 if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
caryclark1049f122015-04-20 08:31:59 -07002011 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07002012 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark1049f122015-04-20 08:31:59 -07002013 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[OppCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07002014 }
2015 // check for one
2016 if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
2017 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[0])) {
2018 zeroOneSet |= kOneS1Set | kZeroS2Set;
2019 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], sect2->fCurve[0]);
2020 }
2021 if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
2022 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[
caryclark1049f122015-04-20 08:31:59 -07002023 OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07002024 zeroOneSet |= kOneS1Set | kOneS2Set;
2025 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
caryclark1049f122015-04-20 08:31:59 -07002026 sect2->fCurve[OppCurve::kPointLast]);
caryclark45fa4472015-01-16 07:04:10 -08002027 }
2028 return zeroOneSet;
2029}
2030
caryclark1049f122015-04-20 08:31:59 -07002031template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002032struct SkClosestRecord {
caryclark54359292015-03-26 07:52:43 -07002033 bool operator<(const SkClosestRecord& rh) const {
2034 return fClosest < rh.fClosest;
2035 }
2036
caryclark45fa4472015-01-16 07:04:10 -08002037 void addIntersection(SkIntersections* intersections) const {
2038 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT();
2039 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT();
2040 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
2041 }
2042
caryclark1049f122015-04-20 08:31:59 -07002043 void findEnd(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2,
caryclark45fa4472015-01-16 07:04:10 -08002044 int c1Index, int c2Index) {
2045 const TCurve& c1 = span1->part();
caryclark1049f122015-04-20 08:31:59 -07002046 const OppCurve& c2 = span2->part();
caryclark45fa4472015-01-16 07:04:10 -08002047 if (!c1[c1Index].approximatelyEqual(c2[c2Index])) {
2048 return;
2049 }
2050 double dist = c1[c1Index].distanceSquared(c2[c2Index]);
2051 if (fClosest < dist) {
2052 return;
2053 }
2054 fC1Span = span1;
2055 fC2Span = span2;
2056 fC1StartT = span1->startT();
2057 fC1EndT = span1->endT();
2058 fC2StartT = span2->startT();
2059 fC2EndT = span2->endT();
2060 fC1Index = c1Index;
2061 fC2Index = c2Index;
2062 fClosest = dist;
2063 }
2064
caryclarkcdeff812016-07-22 03:34:19 -07002065 bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const {
Cary Clark67116382017-01-03 16:25:18 -05002066 SkOPOBJASSERT(i, fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002067 || mate.fC1Span->endT() <= fC1Span->startT());
caryclarkcdeff812016-07-22 03:34:19 -07002068 SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002069 || mate.fC2Span->endT() <= fC2Span->startT());
2070 return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT()
2071 || fC1Span->startT() == mate.fC1Span->endT()
2072 || fC2Span == mate.fC2Span
2073 || fC2Span->endT() == mate.fC2Span->startT()
2074 || fC2Span->startT() == mate.fC2Span->endT();
2075 }
2076
2077 void merge(const SkClosestRecord& mate) {
2078 fC1Span = mate.fC1Span;
2079 fC2Span = mate.fC2Span;
2080 fClosest = mate.fClosest;
2081 fC1Index = mate.fC1Index;
2082 fC2Index = mate.fC2Index;
2083 }
caryclark55888e42016-07-18 10:01:36 -07002084
caryclark45fa4472015-01-16 07:04:10 -08002085 void reset() {
2086 fClosest = FLT_MAX;
halcanary96fcdcc2015-08-27 07:41:13 -07002087 SkDEBUGCODE(fC1Span = nullptr);
2088 SkDEBUGCODE(fC2Span = nullptr);
caryclark45fa4472015-01-16 07:04:10 -08002089 SkDEBUGCODE(fC1Index = fC2Index = -1);
2090 }
2091
2092 void update(const SkClosestRecord& mate) {
2093 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT);
2094 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT);
2095 fC2StartT = SkTMin(fC2StartT, mate.fC2StartT);
2096 fC2EndT = SkTMax(fC2EndT, mate.fC2EndT);
2097 }
2098
caryclark1049f122015-04-20 08:31:59 -07002099 const SkTSpan<TCurve, OppCurve>* fC1Span;
2100 const SkTSpan<OppCurve, TCurve>* fC2Span;
caryclark45fa4472015-01-16 07:04:10 -08002101 double fC1StartT;
2102 double fC1EndT;
2103 double fC2StartT;
2104 double fC2EndT;
2105 double fClosest;
2106 int fC1Index;
2107 int fC2Index;
2108};
2109
caryclark1049f122015-04-20 08:31:59 -07002110template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002111struct SkClosestSect {
2112 SkClosestSect()
2113 : fUsed(0) {
2114 fClosest.push_back().reset();
2115 }
2116
caryclarkcdeff812016-07-22 03:34:19 -07002117 bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2
2118 SkDEBUGPARAMS(SkIntersections* i)) {
caryclark1049f122015-04-20 08:31:59 -07002119 SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed];
caryclark45fa4472015-01-16 07:04:10 -08002120 record->findEnd(span1, span2, 0, 0);
caryclark1049f122015-04-20 08:31:59 -07002121 record->findEnd(span1, span2, 0, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002122 record->findEnd(span1, span2, TCurve::kPointLast, 0);
caryclark1049f122015-04-20 08:31:59 -07002123 record->findEnd(span1, span2, TCurve::kPointLast, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002124 if (record->fClosest == FLT_MAX) {
caryclark54359292015-03-26 07:52:43 -07002125 return false;
caryclark45fa4472015-01-16 07:04:10 -08002126 }
2127 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002128 SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index];
caryclarkcdeff812016-07-22 03:34:19 -07002129 if (test->matesWith(*record SkDEBUGPARAMS(i))) {
caryclark45fa4472015-01-16 07:04:10 -08002130 if (test->fClosest > record->fClosest) {
2131 test->merge(*record);
2132 }
2133 test->update(*record);
2134 record->reset();
caryclark54359292015-03-26 07:52:43 -07002135 return false;
caryclark45fa4472015-01-16 07:04:10 -08002136 }
2137 }
2138 ++fUsed;
2139 fClosest.push_back().reset();
caryclark54359292015-03-26 07:52:43 -07002140 return true;
caryclark45fa4472015-01-16 07:04:10 -08002141 }
2142
2143 void finish(SkIntersections* intersections) const {
caryclark1049f122015-04-20 08:31:59 -07002144 SkSTArray<TCurve::kMaxIntersections * 3,
2145 const SkClosestRecord<TCurve, OppCurve>*, true> closestPtrs;
caryclark45fa4472015-01-16 07:04:10 -08002146 for (int index = 0; index < fUsed; ++index) {
caryclark54359292015-03-26 07:52:43 -07002147 closestPtrs.push_back(&fClosest[index]);
2148 }
caryclark1049f122015-04-20 08:31:59 -07002149 SkTQSort<const SkClosestRecord<TCurve, OppCurve> >(closestPtrs.begin(), closestPtrs.end()
2150 - 1);
caryclark54359292015-03-26 07:52:43 -07002151 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002152 const SkClosestRecord<TCurve, OppCurve>* test = closestPtrs[index];
caryclark54359292015-03-26 07:52:43 -07002153 test->addIntersection(intersections);
caryclark45fa4472015-01-16 07:04:10 -08002154 }
2155 }
2156
caryclark54359292015-03-26 07:52:43 -07002157 // this is oversized so that an extra records can merge into final one
caryclark1049f122015-04-20 08:31:59 -07002158 SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve, OppCurve>, true> fClosest;
caryclark45fa4472015-01-16 07:04:10 -08002159 int fUsed;
2160};
2161
2162// returns true if the rect is too small to consider
caryclark1049f122015-04-20 08:31:59 -07002163template<typename TCurve, typename OppCurve>
2164void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
2165 SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark54359292015-03-26 07:52:43 -07002166#if DEBUG_T_SECT_DUMP > 1
2167 gDumpTSectNum = 0;
2168#endif
caryclark1049f122015-04-20 08:31:59 -07002169 SkDEBUGCODE(sect1->fOppSect = sect2);
2170 SkDEBUGCODE(sect2->fOppSect = sect1);
caryclark45fa4472015-01-16 07:04:10 -08002171 intersections->reset();
caryclarka35ab3e2016-10-20 08:32:18 -07002172 intersections->setMax(TCurve::kMaxIntersections + 4); // give extra for slop
caryclark1049f122015-04-20 08:31:59 -07002173 SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
2174 SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002175 int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
2176// SkASSERT(between(0, sect, 2));
2177 if (!sect) {
caryclark45fa4472015-01-16 07:04:10 -08002178 return;
2179 }
caryclark54359292015-03-26 07:52:43 -07002180 if (sect == 2 && oppSect == 2) {
caryclark45fa4472015-01-16 07:04:10 -08002181 (void) EndsEqual(sect1, sect2, intersections);
2182 return;
2183 }
caryclark54359292015-03-26 07:52:43 -07002184 span1->addBounded(span2, &sect1->fHeap);
2185 span2->addBounded(span1, &sect2->fHeap);
caryclark26ad22a2015-10-16 09:03:38 -07002186 const int kMaxCoinLoopCount = 8;
2187 int coinLoopCount = kMaxCoinLoopCount;
2188 double start1s SK_INIT_TO_AVOID_WARNING;
2189 double start1e SK_INIT_TO_AVOID_WARNING;
caryclark45fa4472015-01-16 07:04:10 -08002190 do {
2191 // find the largest bounds
caryclark1049f122015-04-20 08:31:59 -07002192 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002193 if (!largest1) {
2194 break;
2195 }
caryclark1049f122015-04-20 08:31:59 -07002196 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002197 // split it
caryclark1049f122015-04-20 08:31:59 -07002198 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
2199 || (!largest1->fCollapsed && largest2->fCollapsed)))) {
2200 if (largest1->fCollapsed) {
2201 break;
2202 }
caryclark34efb702016-10-24 08:19:06 -07002203 sect1->resetRemovedEnds();
2204 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002205 // trim parts that don't intersect the opposite
2206 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
caryclark643ede62016-08-08 14:27:45 -07002207 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002208 if (!half1->split(largest1, &sect1->fHeap)) {
2209 break;
2210 }
caryclarka35ab3e2016-10-20 08:32:18 -07002211 if (!sect1->trim(largest1, sect2)) {
2212 SkOPOBJASSERT(intersections, 0);
2213 return;
2214 }
2215 if (!sect1->trim(half1, sect2)) {
2216 SkOPOBJASSERT(intersections, 0);
2217 return;
2218 }
caryclark1049f122015-04-20 08:31:59 -07002219 } else {
2220 if (largest2->fCollapsed) {
2221 break;
2222 }
caryclark34efb702016-10-24 08:19:06 -07002223 sect1->resetRemovedEnds();
2224 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002225 // trim parts that don't intersect the opposite
2226 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
caryclark643ede62016-08-08 14:27:45 -07002227 SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002228 if (!half2->split(largest2, &sect2->fHeap)) {
2229 break;
2230 }
caryclarka35ab3e2016-10-20 08:32:18 -07002231 if (!sect2->trim(largest2, sect1)) {
2232 SkOPOBJASSERT(intersections, 0);
2233 return;
2234 }
2235 if (!sect2->trim(half2, sect1)) {
2236 SkOPOBJASSERT(intersections, 0);
2237 return;
2238 }
caryclark45fa4472015-01-16 07:04:10 -08002239 }
caryclark54359292015-03-26 07:52:43 -07002240 sect1->validate();
2241 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002242#if DEBUG_T_SECT_LOOP_COUNT
2243 intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop);
2244#endif
caryclark45fa4472015-01-16 07:04:10 -08002245 // if there are 9 or more continuous spans on both sects, suspect coincidence
2246 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2247 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
caryclark26ad22a2015-10-16 09:03:38 -07002248 if (coinLoopCount == kMaxCoinLoopCount) {
2249 start1s = sect1->fHead->fStartT;
2250 start1e = sect1->tail()->fEndT;
2251 }
caryclarkef7cee42016-09-06 09:05:54 -07002252 if (!sect1->coincidentCheck(sect2)) {
2253 return;
2254 }
caryclark54359292015-03-26 07:52:43 -07002255 sect1->validate();
2256 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002257#if DEBUG_T_SECT_LOOP_COUNT
2258 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop);
2259#endif
caryclarkef784fb2015-10-30 12:03:06 -07002260 if (!--coinLoopCount && sect1->fHead && sect2->fHead) {
caryclark26ad22a2015-10-16 09:03:38 -07002261 /* All known working cases resolve in two tries. Sadly, cubicConicTests[0]
2262 gets stuck in a loop. It adds an extension to allow a coincident end
2263 perpendicular to track its intersection in the opposite curve. However,
2264 the bounding box of the extension does not intersect the original curve,
caryclark55888e42016-07-18 10:01:36 -07002265 so the extension is discarded, only to be added again the next time around. */
caryclark26ad22a2015-10-16 09:03:38 -07002266 sect1->coincidentForce(sect2, start1s, start1e);
2267 sect1->validate();
2268 sect2->validate();
2269 }
caryclark45fa4472015-01-16 07:04:10 -08002270 }
caryclark54359292015-03-26 07:52:43 -07002271 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2272 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
Cary Clark59ed4822016-12-08 16:17:56 -05002273 if (!sect1->fHead) {
2274 return;
2275 }
caryclark54359292015-03-26 07:52:43 -07002276 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail());
Cary Clark59ed4822016-12-08 16:17:56 -05002277 if (!sect2->fHead) {
2278 return;
2279 }
caryclark54359292015-03-26 07:52:43 -07002280 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail());
Cary Clark0949bee2018-03-19 09:42:00 -04002281 if (!sect1->removeByPerpendicular(sect2)) {
2282 return;
2283 }
caryclark54359292015-03-26 07:52:43 -07002284 sect1->validate();
2285 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002286#if DEBUG_T_SECT_LOOP_COUNT
2287 intersections->debugBumpLoopCount(SkIntersections::kComputePerp_DebugLoop);
2288#endif
caryclark1049f122015-04-20 08:31:59 -07002289 if (sect1->collapsed() > TCurve::kMaxIntersections) {
2290 break;
2291 }
caryclark54359292015-03-26 07:52:43 -07002292 }
2293#if DEBUG_T_SECT_DUMP
2294 sect1->dumpBoth(sect2);
caryclark45fa4472015-01-16 07:04:10 -08002295#endif
2296 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002297 break;
caryclark45fa4472015-01-16 07:04:10 -08002298 }
2299 } while (true);
caryclark1049f122015-04-20 08:31:59 -07002300 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident;
caryclark54359292015-03-26 07:52:43 -07002301 if (coincident) {
2302 // if there is more than one coincident span, check loosely to see if they should be joined
2303 if (coincident->fNext) {
2304 sect1->mergeCoincidence(sect2);
2305 coincident = sect1->fCoincident;
2306 }
2307 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1
caryclark45fa4472015-01-16 07:04:10 -08002308 do {
caryclark221a4bb2016-10-07 11:15:15 -07002309 if (!coincident) {
2310 return;
2311 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002312 if (!coincident->fCoinStart.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002313 continue;
2314 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002315 if (!coincident->fCoinEnd.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002316 continue;
2317 }
Cary Clark67116382017-01-03 16:25:18 -05002318 double perpT = coincident->fCoinStart.perpT();
2319 if (perpT < 0) {
2320 return;
2321 }
caryclark54359292015-03-26 07:52:43 -07002322 int index = intersections->insertCoincident(coincident->fStartT,
Cary Clark67116382017-01-03 16:25:18 -05002323 perpT, coincident->fPart[0]);
caryclark54359292015-03-26 07:52:43 -07002324 if ((intersections->insertCoincident(coincident->fEndT,
2325 coincident->fCoinEnd.perpT(),
2326 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) {
caryclark45fa4472015-01-16 07:04:10 -08002327 intersections->clearCoincidence(index);
2328 }
caryclark54359292015-03-26 07:52:43 -07002329 } while ((coincident = coincident->fNext));
2330 }
caryclark1049f122015-04-20 08:31:59 -07002331 int zeroOneSet = EndsEqual(sect1, sect2, intersections);
caryclark34efb702016-10-24 08:19:06 -07002332// if (!sect1->fHead || !sect2->fHead) {
caryclark6c3b9cd2016-09-26 05:36:58 -07002333 // if the final iteration contains an end (0 or 1),
2334 if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) {
2335 SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular with opposite curve
caryclarka35ab3e2016-10-20 08:32:18 -07002336 perp.setPerp(sect1->fCurve, 0, sect1->fCurve[0], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002337 if (perp.isMatch()) {
2338 intersections->insert(0, perp.perpT(), perp.perpPt());
2339 }
2340 }
2341 if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) {
2342 SkTCoincident<TCurve, OppCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002343 perp.setPerp(sect1->fCurve, 1, sect1->fCurve[TCurve::kPointLast], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002344 if (perp.isMatch()) {
2345 intersections->insert(1, perp.perpT(), perp.perpPt());
2346 }
2347 }
2348 if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) {
2349 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002350 perp.setPerp(sect2->fCurve, 0, sect2->fCurve[0], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002351 if (perp.isMatch()) {
2352 intersections->insert(perp.perpT(), 0, perp.perpPt());
2353 }
2354 }
2355 if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) {
2356 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002357 perp.setPerp(sect2->fCurve, 1, sect2->fCurve[OppCurve::kPointLast], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002358 if (perp.isMatch()) {
2359 intersections->insert(perp.perpT(), 1, perp.perpPt());
2360 }
2361 }
caryclark34efb702016-10-24 08:19:06 -07002362// }
2363 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002364 return;
caryclark45fa4472015-01-16 07:04:10 -08002365 }
caryclark45fa4472015-01-16 07:04:10 -08002366 sect1->recoverCollapsed();
2367 sect2->recoverCollapsed();
caryclark1049f122015-04-20 08:31:59 -07002368 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002369 // check heads and tails for zero and ones and insert them if we haven't already done so
caryclark1049f122015-04-20 08:31:59 -07002370 const SkTSpan<TCurve, OppCurve>* head1 = result1;
caryclark45fa4472015-01-16 07:04:10 -08002371 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) {
2372 const SkDPoint& start1 = sect1->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002373 if (head1->isBounded()) {
2374 double t = head1->closestBoundedT(start1);
2375 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) {
2376 intersections->insert(0, t, start1);
2377 }
caryclark45fa4472015-01-16 07:04:10 -08002378 }
2379 }
caryclark1049f122015-04-20 08:31:59 -07002380 const SkTSpan<OppCurve, TCurve>* head2 = sect2->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002381 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) {
2382 const SkDPoint& start2 = sect2->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002383 if (head2->isBounded()) {
2384 double t = head2->closestBoundedT(start2);
2385 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) {
2386 intersections->insert(t, 0, start2);
2387 }
caryclark45fa4472015-01-16 07:04:10 -08002388 }
2389 }
caryclark1049f122015-04-20 08:31:59 -07002390 const SkTSpan<TCurve, OppCurve>* tail1 = sect1->tail();
caryclark45fa4472015-01-16 07:04:10 -08002391 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT)) {
2392 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002393 if (tail1->isBounded()) {
2394 double t = tail1->closestBoundedT(end1);
2395 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) {
2396 intersections->insert(1, t, end1);
2397 }
caryclark45fa4472015-01-16 07:04:10 -08002398 }
2399 }
caryclark1049f122015-04-20 08:31:59 -07002400 const SkTSpan<OppCurve, TCurve>* tail2 = sect2->tail();
caryclark45fa4472015-01-16 07:04:10 -08002401 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT)) {
caryclark1049f122015-04-20 08:31:59 -07002402 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002403 if (tail2->isBounded()) {
2404 double t = tail2->closestBoundedT(end2);
2405 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
2406 intersections->insert(t, 1, end2);
2407 }
caryclark45fa4472015-01-16 07:04:10 -08002408 }
2409 }
caryclark1049f122015-04-20 08:31:59 -07002410 SkClosestSect<TCurve, OppCurve> closest;
caryclark45fa4472015-01-16 07:04:10 -08002411 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07002412 while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) {
caryclark45fa4472015-01-16 07:04:10 -08002413 result1 = result1->fNext;
2414 }
2415 if (!result1) {
2416 break;
2417 }
caryclark1049f122015-04-20 08:31:59 -07002418 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002419 bool found = false;
caryclark45fa4472015-01-16 07:04:10 -08002420 while (result2) {
caryclarkcdeff812016-07-22 03:34:19 -07002421 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections));
caryclark45fa4472015-01-16 07:04:10 -08002422 result2 = result2->fNext;
2423 }
caryclark45fa4472015-01-16 07:04:10 -08002424 } while ((result1 = result1->fNext));
2425 closest.finish(intersections);
caryclark54359292015-03-26 07:52:43 -07002426 // if there is more than one intersection and it isn't already coincident, check
2427 int last = intersections->used() - 1;
2428 for (int index = 0; index < last; ) {
2429 if (intersections->isCoincident(index) && intersections->isCoincident(index + 1)) {
2430 ++index;
2431 continue;
2432 }
2433 double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
2434 SkDPoint midPt = sect1->fCurve.ptAtT(midT);
2435 // intersect perpendicular with opposite curve
caryclark1049f122015-04-20 08:31:59 -07002436 SkTCoincident<TCurve, OppCurve> perp;
caryclark54359292015-03-26 07:52:43 -07002437 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002438 if (!perp.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07002439 ++index;
2440 continue;
2441 }
2442 if (intersections->isCoincident(index)) {
2443 intersections->removeOne(index);
2444 --last;
2445 } else if (intersections->isCoincident(index + 1)) {
2446 intersections->removeOne(index + 1);
2447 --last;
2448 } else {
2449 intersections->setCoincident(index++);
2450 }
2451 intersections->setCoincident(index);
2452 }
caryclarka35ab3e2016-10-20 08:32:18 -07002453 SkOPOBJASSERT(intersections, intersections->used() <= TCurve::kMaxIntersections);
caryclark45fa4472015-01-16 07:04:10 -08002454}
deanm12670eb2016-04-26 14:09:01 -07002455
2456#endif