blob: 833e735da672b8334f249d76485eb2f5cd34b7f4 [file] [log] [blame]
caryclark45fa4472015-01-16 07:04:10 -08001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
deanm12670eb2016-04-26 14:09:01 -07007#ifndef SkPathOpsTSect_DEFINED
8#define SkPathOpsTSect_DEFINED
caryclark45fa4472015-01-16 07:04:10 -08009
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050010#include "SkArenaAlloc.h"
caryclark54359292015-03-26 07:52:43 -070011#include "SkPathOpsBounds.h"
caryclark45fa4472015-01-16 07:04:10 -080012#include "SkPathOpsRect.h"
caryclark45fa4472015-01-16 07:04:10 -080013#include "SkIntersections.h"
caryclark54359292015-03-26 07:52:43 -070014#include "SkTSort.h"
caryclark45fa4472015-01-16 07:04:10 -080015
caryclarked0935a2015-10-22 07:23:52 -070016#ifdef SK_DEBUG
17typedef uint8_t SkOpDebugBool;
18#else
19typedef bool SkOpDebugBool;
20#endif
21
caryclark1049f122015-04-20 08:31:59 -070022/* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */
23template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080024class SkTCoincident {
25public:
caryclark697ac1c2015-04-13 09:36:01 -070026 SkTCoincident() {
caryclarkdf386c52015-04-21 05:27:02 -070027 this->init();
caryclark1049f122015-04-20 08:31:59 -070028 }
29
caryclarked0935a2015-10-22 07:23:52 -070030 void debugInit() {
31#ifdef SK_DEBUG
32 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
33 this->fPerpT = SK_ScalarNaN;
caryclark6c3b9cd2016-09-26 05:36:58 -070034 this->fMatch = 0xFF;
caryclarked0935a2015-10-22 07:23:52 -070035#endif
36 }
37
38 char dumpIsCoincidentStr() const;
caryclark1049f122015-04-20 08:31:59 -070039 void dump() const;
40
caryclark6c3b9cd2016-09-26 05:36:58 -070041 bool isMatch() const {
42 SkASSERT(!!fMatch == fMatch);
43 return SkToBool(fMatch);
caryclark45fa4472015-01-16 07:04:10 -080044 }
45
46 void init() {
caryclarkdf386c52015-04-21 05:27:02 -070047 fPerpT = -1;
caryclark6c3b9cd2016-09-26 05:36:58 -070048 fMatch = false;
caryclarkdf386c52015-04-21 05:27:02 -070049 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
caryclark45fa4472015-01-16 07:04:10 -080050 }
51
52 void markCoincident() {
caryclark6c3b9cd2016-09-26 05:36:58 -070053 if (!fMatch) {
caryclark45fa4472015-01-16 07:04:10 -080054 fPerpT = -1;
55 }
caryclark6c3b9cd2016-09-26 05:36:58 -070056 fMatch = true;
caryclark45fa4472015-01-16 07:04:10 -080057 }
58
59 const SkDPoint& perpPt() const {
60 return fPerpPt;
61 }
62
63 double perpT() const {
64 return fPerpT;
65 }
66
caryclark1049f122015-04-20 08:31:59 -070067 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve& );
caryclark45fa4472015-01-16 07:04:10 -080068
69private:
70 SkDPoint fPerpPt;
71 double fPerpT; // perpendicular intersection on opposite curve
caryclark6c3b9cd2016-09-26 05:36:58 -070072 SkOpDebugBool fMatch;
caryclark45fa4472015-01-16 07:04:10 -080073};
74
caryclark1049f122015-04-20 08:31:59 -070075template<typename TCurve, typename OppCurve> class SkTSect;
76template<typename TCurve, typename OppCurve> class SkTSpan;
caryclark54359292015-03-26 07:52:43 -070077
caryclark1049f122015-04-20 08:31:59 -070078template<typename TCurve, typename OppCurve>
caryclark54359292015-03-26 07:52:43 -070079struct SkTSpanBounded {
caryclark1049f122015-04-20 08:31:59 -070080 SkTSpan<TCurve, OppCurve>* fBounded;
caryclark54359292015-03-26 07:52:43 -070081 SkTSpanBounded* fNext;
82};
caryclark45fa4472015-01-16 07:04:10 -080083
84/* Curve is either TCurve or SkDCubic */
caryclark1049f122015-04-20 08:31:59 -070085template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080086class SkTSpan {
87public:
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050088 void addBounded(SkTSpan<OppCurve, TCurve>* , SkArenaAlloc* );
reed0dc4dd62015-03-24 13:55:33 -070089 double closestBoundedT(const SkDPoint& pt) const;
caryclark54359292015-03-26 07:52:43 -070090 bool contains(double t) const;
reed0dc4dd62015-03-24 13:55:33 -070091
caryclark1049f122015-04-20 08:31:59 -070092 void debugInit() {
93 TCurve dummy;
94 dummy.debugInit();
95 init(dummy);
96 initBounds(dummy);
caryclarkdf386c52015-04-21 05:27:02 -070097 fCoinStart.init();
98 fCoinEnd.init();
caryclark1049f122015-04-20 08:31:59 -070099 }
100
101 const SkTSect<OppCurve, TCurve>* debugOpp() const;
caryclark643ede62016-08-08 14:27:45 -0700102
103#ifdef SK_DEBUG
104 void debugSetGlobalState(SkOpGlobalState* state) {
105 fDebugGlobalState = state;
106 }
107#endif
108
caryclark54359292015-03-26 07:52:43 -0700109 const SkTSpan* debugSpan(int ) const;
110 const SkTSpan* debugT(double t) const;
111#ifdef SK_DEBUG
112 bool debugIsBefore(const SkTSpan* span) const;
113#endif
114 void dump() const;
caryclark26ad22a2015-10-16 09:03:38 -0700115 void dumpAll() const;
caryclark1049f122015-04-20 08:31:59 -0700116 void dumpBounded(int id) const;
117 void dumpBounds() const;
118 void dumpCoin() const;
caryclark45fa4472015-01-16 07:04:10 -0800119
120 double endT() const {
121 return fEndT;
122 }
123
caryclark1049f122015-04-20 08:31:59 -0700124 SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp) const;
caryclark54359292015-03-26 07:52:43 -0700125
caryclark1049f122015-04-20 08:31:59 -0700126 SkTSpan<OppCurve, TCurve>* findOppT(double t) const {
127 SkTSpan<OppCurve, TCurve>* result = oppT(t);
caryclark643ede62016-08-08 14:27:45 -0700128 SkOPASSERT(result);
caryclark45fa4472015-01-16 07:04:10 -0800129 return result;
130 }
131
caryclark643ede62016-08-08 14:27:45 -0700132 SkDEBUGCODE(SkOpGlobalState* globalState() const { return fDebugGlobalState; })
133
caryclark54359292015-03-26 07:52:43 -0700134 bool hasOppT(double t) const {
135 return SkToBool(oppT(t));
136 }
137
caryclark1049f122015-04-20 08:31:59 -0700138 int hullsIntersect(SkTSpan<OppCurve, TCurve>* span, bool* start, bool* oppStart);
caryclark54359292015-03-26 07:52:43 -0700139 void init(const TCurve& );
caryclarka35ab3e2016-10-20 08:32:18 -0700140 bool initBounds(const TCurve& );
caryclark54359292015-03-26 07:52:43 -0700141
142 bool isBounded() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700143 return fBounded != nullptr;
caryclark54359292015-03-26 07:52:43 -0700144 }
145
caryclark1049f122015-04-20 08:31:59 -0700146 bool linearsIntersect(SkTSpan<OppCurve, TCurve>* span);
caryclark54359292015-03-26 07:52:43 -0700147 double linearT(const SkDPoint& ) const;
148
149 void markCoincident() {
150 fCoinStart.markCoincident();
151 fCoinEnd.markCoincident();
152 }
caryclark45fa4472015-01-16 07:04:10 -0800153
154 const SkTSpan* next() const {
155 return fNext;
156 }
157
caryclark1049f122015-04-20 08:31:59 -0700158 bool onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp, bool* start,
159 bool* oppStart, bool* ptsInCommon);
caryclark54359292015-03-26 07:52:43 -0700160
caryclark45fa4472015-01-16 07:04:10 -0800161 const TCurve& part() const {
162 return fPart;
163 }
164
caryclark54359292015-03-26 07:52:43 -0700165 bool removeAllBounded();
caryclark1049f122015-04-20 08:31:59 -0700166 bool removeBounded(const SkTSpan<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700167
caryclark45fa4472015-01-16 07:04:10 -0800168 void reset() {
halcanary96fcdcc2015-08-27 07:41:13 -0700169 fBounded = nullptr;
caryclark45fa4472015-01-16 07:04:10 -0800170 }
171
caryclark54359292015-03-26 07:52:43 -0700172 void resetBounds(const TCurve& curve) {
173 fIsLinear = fIsLine = false;
174 initBounds(curve);
caryclark45fa4472015-01-16 07:04:10 -0800175 }
176
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500177 bool split(SkTSpan* work, SkArenaAlloc* heap) {
caryclark54359292015-03-26 07:52:43 -0700178 return splitAt(work, (work->fStartT + work->fEndT) * 0.5, heap);
179 }
180
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500181 bool splitAt(SkTSpan* work, double t, SkArenaAlloc* heap);
caryclark45fa4472015-01-16 07:04:10 -0800182
183 double startT() const {
184 return fStartT;
185 }
186
caryclark54359292015-03-26 07:52:43 -0700187private:
caryclark45fa4472015-01-16 07:04:10 -0800188
189 // implementation is for testing only
caryclark54359292015-03-26 07:52:43 -0700190 int debugID() const {
191 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
caryclark45fa4472015-01-16 07:04:10 -0800192 }
193
caryclark54359292015-03-26 07:52:43 -0700194 void dumpID() const;
caryclark45fa4472015-01-16 07:04:10 -0800195
caryclark1049f122015-04-20 08:31:59 -0700196 int hullCheck(const SkTSpan<OppCurve, TCurve>* opp, bool* start, bool* oppStart);
197 int linearIntersects(const OppCurve& ) const;
198 SkTSpan<OppCurve, TCurve>* oppT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800199
caryclark45fa4472015-01-16 07:04:10 -0800200 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700201 void validateBounded() const;
202 void validatePerpT(double oppT) const;
203 void validatePerpPt(double t, const SkDPoint& ) const;
caryclark45fa4472015-01-16 07:04:10 -0800204
205 TCurve fPart;
caryclark1049f122015-04-20 08:31:59 -0700206 SkTCoincident<TCurve, OppCurve> fCoinStart;
207 SkTCoincident<TCurve, OppCurve> fCoinEnd;
208 SkTSpanBounded<OppCurve, TCurve>* fBounded;
caryclark45fa4472015-01-16 07:04:10 -0800209 SkTSpan* fPrev;
210 SkTSpan* fNext;
211 SkDRect fBounds;
212 double fStartT;
213 double fEndT;
214 double fBoundsMax;
caryclarked0935a2015-10-22 07:23:52 -0700215 SkOpDebugBool fCollapsed;
216 SkOpDebugBool fHasPerp;
217 SkOpDebugBool fIsLinear;
218 SkOpDebugBool fIsLine;
219 SkOpDebugBool fDeleted;
caryclark643ede62016-08-08 14:27:45 -0700220 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700221 SkDEBUGCODE(SkTSect<TCurve, OppCurve>* fDebugSect);
caryclark54359292015-03-26 07:52:43 -0700222 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
caryclark1049f122015-04-20 08:31:59 -0700223 friend class SkTSect<TCurve, OppCurve>;
224 friend class SkTSect<OppCurve, TCurve>;
225 friend class SkTSpan<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800226};
227
caryclark1049f122015-04-20 08:31:59 -0700228template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -0800229class SkTSect {
230public:
caryclarke25a4f62016-07-26 09:26:29 -0700231 SkTSect(const TCurve& c SkDEBUGPARAMS(SkOpGlobalState* ) PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
caryclark1049f122015-04-20 08:31:59 -0700232 static void BinarySearch(SkTSect* sect1, SkTSect<OppCurve, TCurve>* sect2,
233 SkIntersections* intersections);
caryclark45fa4472015-01-16 07:04:10 -0800234
caryclarke25a4f62016-07-26 09:26:29 -0700235 SkDEBUGCODE(SkOpGlobalState* globalState() { return fDebugGlobalState; })
caryclark45fa4472015-01-16 07:04:10 -0800236 // for testing only
caryclark1049f122015-04-20 08:31:59 -0700237 bool debugHasBounded(const SkTSpan<OppCurve, TCurve>* ) const;
caryclark54359292015-03-26 07:52:43 -0700238
caryclark1049f122015-04-20 08:31:59 -0700239 const SkTSect<OppCurve, TCurve>* debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700240 return SkDEBUGRELEASE(fOppSect, nullptr);
caryclark54359292015-03-26 07:52:43 -0700241 }
242
caryclark1049f122015-04-20 08:31:59 -0700243 const SkTSpan<TCurve, OppCurve>* debugSpan(int id) const;
244 const SkTSpan<TCurve, OppCurve>* debugT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800245 void dump() const;
caryclark1049f122015-04-20 08:31:59 -0700246 void dumpBoth(SkTSect<OppCurve, TCurve>* ) const;
247 void dumpBounded(int id) const;
248 void dumpBounds() const;
caryclark54359292015-03-26 07:52:43 -0700249 void dumpCoin() const;
250 void dumpCoinCurves() const;
caryclark45fa4472015-01-16 07:04:10 -0800251 void dumpCurves() const;
252
253private:
254 enum {
255 kZeroS1Set = 1,
256 kOneS1Set = 2,
257 kZeroS2Set = 4,
258 kOneS2Set = 8
259 };
260
caryclark1049f122015-04-20 08:31:59 -0700261 SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior);
262 void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t);
263 SkTSpan<TCurve, OppCurve>* addOne();
caryclark55888e42016-07-18 10:01:36 -0700264
caryclark1049f122015-04-20 08:31:59 -0700265 SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, double t) {
266 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700267 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700268 result->splitAt(span, t, &fHeap);
269 result->initBounds(fCurve);
270 span->initBounds(fCurve);
271 return result;
272 }
273
caryclark1049f122015-04-20 08:31:59 -0700274 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
Cary Clark74b42902018-03-09 07:38:47 -0500275 double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst);
caryclark1049f122015-04-20 08:31:59 -0700276 SkTSpan<TCurve, OppCurve>* boundsMax() const;
caryclarkef7cee42016-09-06 09:05:54 -0700277 bool coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
caryclark26ad22a2015-10-16 09:03:38 -0700278 void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, double start1e);
caryclark54359292015-03-26 07:52:43 -0700279 bool coincidentHasT(double t);
caryclark1049f122015-04-20 08:31:59 -0700280 int collapsed() const;
281 void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
282 SkTSpan<TCurve, OppCurve>* last);
283 int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
284 SkTSpan<TCurve, OppCurve>** last) const;
caryclarkccec0f92015-03-24 07:28:17 -0700285
caryclark54359292015-03-26 07:52:43 -0700286 int debugID() const {
287 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
288 }
289
caryclarkef7cee42016-09-06 09:05:54 -0700290 bool deleteEmptySpans();
caryclark1049f122015-04-20 08:31:59 -0700291 void dumpCommon(const SkTSpan<TCurve, OppCurve>* ) const;
292 void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const;
293 static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2,
294 SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700295 bool extractCoincident(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
296 SkTSpan<TCurve, OppCurve>* last, SkTSpan<TCurve, OppCurve>** result);
caryclark1049f122015-04-20 08:31:59 -0700297 SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* first,
298 SkTSpan<TCurve, OppCurve>** lastPtr);
299 int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
300 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult);
caryclarked0935a2015-10-22 07:23:52 -0700301 bool isParallel(const SkDLine& thisLine, const SkTSect<OppCurve, TCurve>* opp) const;
caryclark1049f122015-04-20 08:31:59 -0700302 int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
303 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700304 bool markSpanGone(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700305 bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2) const;
306 void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2,
caryclark54359292015-03-26 07:52:43 -0700307 bool* calcMatched, bool* oppMatched) const;
caryclark1049f122015-04-20 08:31:59 -0700308 void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2);
309 SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const;
310 void removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700311 void recoverCollapsed();
Cary Clark38702ab2017-09-05 18:11:55 -0400312 bool removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween);
caryclark1049f122015-04-20 08:31:59 -0700313 void removeAllBut(const SkTSpan<OppCurve, TCurve>* keep, SkTSpan<TCurve, OppCurve>* span,
314 SkTSect<OppCurve, TCurve>* opp);
caryclarkef7cee42016-09-06 09:05:54 -0700315 bool removeSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700316 void removeSpanRange(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last);
317 void removeSpans(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
caryclark34efb702016-10-24 08:19:06 -0700318 void removedEndCheck(SkTSpan<TCurve, OppCurve>* span);
319
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500320 void resetRemovedEnds() {
caryclark34efb702016-10-24 08:19:06 -0700321 fRemovedStartT = fRemovedEndT = false;
322 }
323
caryclark1049f122015-04-20 08:31:59 -0700324 SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
325 SkTSpan<TCurve, OppCurve>* tail();
caryclarka35ab3e2016-10-20 08:32:18 -0700326 bool trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
Cary Clark38702ab2017-09-05 18:11:55 -0400327 bool unlinkSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700328 bool updateBounded(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
329 SkTSpan<OppCurve, TCurve>* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700330 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700331 void validateBounded() const;
332
caryclark45fa4472015-01-16 07:04:10 -0800333 const TCurve& fCurve;
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500334 SkArenaAlloc fHeap;
caryclark1049f122015-04-20 08:31:59 -0700335 SkTSpan<TCurve, OppCurve>* fHead;
336 SkTSpan<TCurve, OppCurve>* fCoincident;
337 SkTSpan<TCurve, OppCurve>* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800338 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700339 bool fRemovedStartT;
340 bool fRemovedEndT;
caryclarke25a4f62016-07-26 09:26:29 -0700341 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700342 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700343 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
344 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800345#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800346 int fDebugAllocatedCount;
347#endif
caryclark1049f122015-04-20 08:31:59 -0700348 friend class SkTSpan<TCurve, OppCurve>;
349 friend class SkTSpan<OppCurve, TCurve>;
350 friend class SkTSect<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800351};
352
353#define COINCIDENT_SPAN_COUNT 9
354
caryclark1049f122015-04-20 08:31:59 -0700355template<typename TCurve, typename OppCurve>
356void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t,
357 const SkDPoint& cPt, const OppCurve& c2) {
caryclark45fa4472015-01-16 07:04:10 -0800358 SkDVector dxdy = c1.dxdyAtT(t);
359 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
caryclarka35ab3e2016-10-20 08:32:18 -0700360 SkIntersections i SkDEBUGCODE((c1.globalState()));
caryclark45fa4472015-01-16 07:04:10 -0800361 int used = i.intersectRay(c2, perp);
362 // only keep closest
caryclark54359292015-03-26 07:52:43 -0700363 if (used == 0 || used == 3) {
caryclarkdf386c52015-04-21 05:27:02 -0700364 this->init();
caryclark45fa4472015-01-16 07:04:10 -0800365 return;
caryclark55888e42016-07-18 10:01:36 -0700366 }
caryclark45fa4472015-01-16 07:04:10 -0800367 fPerpT = i[0][0];
368 fPerpPt = i.pt(0);
369 SkASSERT(used <= 2);
370 if (used == 2) {
371 double distSq = (fPerpPt - cPt).lengthSquared();
372 double dist2Sq = (i.pt(1) - cPt).lengthSquared();
373 if (dist2Sq < distSq) {
374 fPerpT = i[0][1];
375 fPerpPt = i.pt(1);
376 }
377 }
caryclark54359292015-03-26 07:52:43 -0700378#if DEBUG_T_SECT
caryclark1049f122015-04-20 08:31:59 -0700379 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n",
380 t, cPt.fX, cPt.fY,
381 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY);
caryclark54359292015-03-26 07:52:43 -0700382#endif
caryclark6c3b9cd2016-09-26 05:36:58 -0700383 fMatch = cPt.approximatelyEqual(fPerpPt);
caryclark45fa4472015-01-16 07:04:10 -0800384#if DEBUG_T_SECT
caryclark6c3b9cd2016-09-26 05:36:58 -0700385 if (fMatch) {
caryclark45fa4472015-01-16 07:04:10 -0800386 SkDebugf(""); // allow setting breakpoint
387 }
388#endif
389}
390
caryclark1049f122015-04-20 08:31:59 -0700391template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500392void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkArenaAlloc* heap) {
393 SkTSpanBounded<OppCurve, TCurve>* bounded = heap->make<SkTSpanBounded<OppCurve, TCurve>>();
caryclark54359292015-03-26 07:52:43 -0700394 bounded->fBounded = span;
395 bounded->fNext = fBounded;
396 fBounded = bounded;
397}
398
caryclark1049f122015-04-20 08:31:59 -0700399template<typename TCurve, typename OppCurve>
400SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing(
401 SkTSpan<TCurve, OppCurve>* prior) {
402 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700403 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700404 result->fStartT = prior ? prior->fEndT : 0;
caryclark1049f122015-04-20 08:31:59 -0700405 SkTSpan<TCurve, OppCurve>* next = prior ? prior->fNext : fHead;
caryclark54359292015-03-26 07:52:43 -0700406 result->fEndT = next ? next->fStartT : 1;
407 result->fPrev = prior;
408 result->fNext = next;
409 if (prior) {
410 prior->fNext = result;
411 } else {
412 fHead = result;
413 }
414 if (next) {
415 next->fPrev = result;
416 }
417 result->resetBounds(fCurve);
caryclark643ede62016-08-08 14:27:45 -0700418 result->validate();
caryclark54359292015-03-26 07:52:43 -0700419 return result;
420}
421
caryclark1049f122015-04-20 08:31:59 -0700422template<typename TCurve, typename OppCurve>
423void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, double t) {
caryclark54359292015-03-26 07:52:43 -0700424 if (!span->hasOppT(t)) {
caryclark1049f122015-04-20 08:31:59 -0700425 SkTSpan<TCurve, OppCurve>* priorSpan;
426 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan);
caryclark54359292015-03-26 07:52:43 -0700427 if (!opp) {
428 opp = this->addFollowing(priorSpan);
429#if DEBUG_PERP
caryclark26ad22a2015-10-16 09:03:38 -0700430 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ?
431 priorSpan->debugID() : -1, t, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700432#endif
433 }
434#if DEBUG_PERP
435 opp->dump(); SkDebugf("\n");
caryclark26ad22a2015-10-16 09:03:38 -0700436 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ?
437 priorSpan->debugID() : -1, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700438#endif
439 opp->addBounded(span, &fHeap);
440 span->addBounded(opp, &fHeap);
441 }
442 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700443#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700444 span->validatePerpT(t);
caryclark1049f122015-04-20 08:31:59 -0700445#endif
caryclark54359292015-03-26 07:52:43 -0700446}
447
caryclark1049f122015-04-20 08:31:59 -0700448template<typename TCurve, typename OppCurve>
449double SkTSpan<TCurve, OppCurve>::closestBoundedT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700450 double result = -1;
caryclark343382e2016-06-29 08:18:38 -0700451 double closest = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -0700452 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700453 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700454 const SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700455 double startDist = test->fPart[0].distanceSquared(pt);
456 if (closest > startDist) {
457 closest = startDist;
458 result = test->fStartT;
459 }
caryclark1049f122015-04-20 08:31:59 -0700460 double endDist = test->fPart[OppCurve::kPointLast].distanceSquared(pt);
caryclark54359292015-03-26 07:52:43 -0700461 if (closest > endDist) {
462 closest = endDist;
463 result = test->fEndT;
464 }
465 testBounded = testBounded->fNext;
466 }
467 SkASSERT(between(0, result, 1));
468 return result;
469}
470
471#ifdef SK_DEBUG
caryclark1049f122015-04-20 08:31:59 -0700472template<typename TCurve, typename OppCurve>
473bool SkTSpan<TCurve, OppCurve>::debugIsBefore(const SkTSpan* span) const {
caryclark54359292015-03-26 07:52:43 -0700474 const SkTSpan* work = this;
475 do {
476 if (span == work) {
477 return true;
478 }
479 } while ((work = work->fNext));
480 return false;
481}
482#endif
483
caryclark1049f122015-04-20 08:31:59 -0700484template<typename TCurve, typename OppCurve>
485bool SkTSpan<TCurve, OppCurve>::contains(double t) const {
caryclark54359292015-03-26 07:52:43 -0700486 const SkTSpan* work = this;
487 do {
488 if (between(work->fStartT, t, work->fEndT)) {
489 return true;
490 }
491 } while ((work = work->fNext));
492 return false;
493}
494
caryclark1049f122015-04-20 08:31:59 -0700495template<typename TCurve, typename OppCurve>
496const SkTSect<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700497 return SkDEBUGRELEASE(fDebugSect->debugOpp(), nullptr);
caryclark54359292015-03-26 07:52:43 -0700498}
499
caryclark1049f122015-04-20 08:31:59 -0700500template<typename TCurve, typename OppCurve>
501SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::findOppSpan(
502 const SkTSpan<OppCurve, TCurve>* opp) const {
503 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700504 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700505 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700506 if (opp == test) {
507 return test;
508 }
509 bounded = bounded->fNext;
510 }
halcanary96fcdcc2015-08-27 07:41:13 -0700511 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700512}
513
514// returns 0 if no hull intersection
515// 1 if hulls intersect
516// 2 if hulls only share a common endpoint
517// -1 if linear and further checking is required
caryclark1049f122015-04-20 08:31:59 -0700518template<typename TCurve, typename OppCurve>
519int SkTSpan<TCurve, OppCurve>::hullCheck(const SkTSpan<OppCurve, TCurve>* opp,
520 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700521 if (fIsLinear) {
522 return -1;
523 }
524 bool ptsInCommon;
525 if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) {
526 SkASSERT(ptsInCommon);
527 return 2;
528 }
529 bool linear;
530 if (fPart.hullIntersects(opp->fPart, &linear)) {
531 if (!linear) { // check set true if linear
532 return 1;
533 }
534 fIsLinear = true;
535 fIsLine = fPart.controlsInside();
caryclark2bec26a2016-05-26 09:01:47 -0700536 return ptsInCommon ? 1 : -1;
caryclark54359292015-03-26 07:52:43 -0700537 } else { // hull is not linear; check set true if intersected at the end points
538 return ((int) ptsInCommon) << 1; // 0 or 2
539 }
540 return 0;
541}
542
543// OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
544// use line intersection to guess a better split than 0.5
545// OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear
caryclark1049f122015-04-20 08:31:59 -0700546template<typename TCurve, typename OppCurve>
547int SkTSpan<TCurve, OppCurve>::hullsIntersect(SkTSpan<OppCurve, TCurve>* opp,
548 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700549 if (!fBounds.intersects(opp->fBounds)) {
550 return 0;
551 }
552 int hullSect = this->hullCheck(opp, start, oppStart);
553 if (hullSect >= 0) {
554 return hullSect;
555 }
556 hullSect = opp->hullCheck(this, oppStart, start);
557 if (hullSect >= 0) {
558 return hullSect;
559 }
560 return -1;
561}
562
caryclark1049f122015-04-20 08:31:59 -0700563template<typename TCurve, typename OppCurve>
564void SkTSpan<TCurve, OppCurve>::init(const TCurve& c) {
halcanary96fcdcc2015-08-27 07:41:13 -0700565 fPrev = fNext = nullptr;
reed0dc4dd62015-03-24 13:55:33 -0700566 fStartT = 0;
567 fEndT = 1;
halcanary96fcdcc2015-08-27 07:41:13 -0700568 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700569 resetBounds(c);
caryclark45fa4472015-01-16 07:04:10 -0800570}
571
caryclark1049f122015-04-20 08:31:59 -0700572template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -0700573bool SkTSpan<TCurve, OppCurve>::initBounds(const TCurve& c) {
reed0dc4dd62015-03-24 13:55:33 -0700574 fPart = c.subDivide(fStartT, fEndT);
575 fBounds.setBounds(fPart);
576 fCoinStart.init();
577 fCoinEnd.init();
578 fBoundsMax = SkTMax(fBounds.width(), fBounds.height());
579 fCollapsed = fPart.collapsed();
580 fHasPerp = false;
caryclark54359292015-03-26 07:52:43 -0700581 fDeleted = false;
reed0dc4dd62015-03-24 13:55:33 -0700582#if DEBUG_T_SECT
reed0dc4dd62015-03-24 13:55:33 -0700583 if (fCollapsed) {
584 SkDebugf(""); // for convenient breakpoints
caryclark45fa4472015-01-16 07:04:10 -0800585 }
586#endif
caryclarka35ab3e2016-10-20 08:32:18 -0700587 return fBounds.valid();
caryclark45fa4472015-01-16 07:04:10 -0800588}
589
caryclark1049f122015-04-20 08:31:59 -0700590template<typename TCurve, typename OppCurve>
591bool SkTSpan<TCurve, OppCurve>::linearsIntersect(SkTSpan<OppCurve, TCurve>* span) {
caryclark54359292015-03-26 07:52:43 -0700592 int result = this->linearIntersects(span->fPart);
593 if (result <= 1) {
594 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800595 }
caryclark54359292015-03-26 07:52:43 -0700596 SkASSERT(span->fIsLinear);
597 result = span->linearIntersects(this->fPart);
598// SkASSERT(result <= 1);
599 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800600}
601
caryclark1049f122015-04-20 08:31:59 -0700602template<typename TCurve, typename OppCurve>
603double SkTSpan<TCurve, OppCurve>::linearT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700604 SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
605 return fabs(len.fX) > fabs(len.fY)
606 ? (pt.fX - fPart[0].fX) / len.fX
607 : (pt.fY - fPart[0].fY) / len.fY;
caryclark45fa4472015-01-16 07:04:10 -0800608}
609
caryclark1049f122015-04-20 08:31:59 -0700610template<typename TCurve, typename OppCurve>
611int SkTSpan<TCurve, OppCurve>::linearIntersects(const OppCurve& q2) const {
caryclark45fa4472015-01-16 07:04:10 -0800612 // looks like q1 is near-linear
caryclark54359292015-03-26 07:52:43 -0700613 int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
caryclark45fa4472015-01-16 07:04:10 -0800614 if (!fPart.controlsInside()) {
615 double dist = 0; // if there's any question, compute distance to find best outsiders
616 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) {
617 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) {
618 double test = (fPart[outer] - fPart[inner]).lengthSquared();
619 if (dist > test) {
620 continue;
621 }
622 dist = test;
623 start = outer;
624 end = inner;
625 }
626 }
627 }
628 // see if q2 is on one side of the line formed by the extreme points
629 double origX = fPart[start].fX;
630 double origY = fPart[start].fY;
631 double adj = fPart[end].fX - origX;
632 double opp = fPart[end].fY - origY;
caryclark54359292015-03-26 07:52:43 -0700633 double maxPart = SkTMax(fabs(adj), fabs(opp));
634 double sign = 0; // initialization to shut up warning in release build
caryclark1049f122015-04-20 08:31:59 -0700635 for (int n = 0; n < OppCurve::kPointCount; ++n) {
caryclark54359292015-03-26 07:52:43 -0700636 double dx = q2[n].fY - origY;
637 double dy = q2[n].fX - origX;
638 double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
caryclark45fa4472015-01-16 07:04:10 -0800639 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp;
caryclark54359292015-03-26 07:52:43 -0700640 if (precisely_zero_when_compared_to(test, maxVal)) {
641 return 1;
642 }
643 if (approximately_zero_when_compared_to(test, maxVal)) {
644 return 3;
caryclark45fa4472015-01-16 07:04:10 -0800645 }
646 if (n == 0) {
647 sign = test;
648 continue;
649 }
650 if (test * sign < 0) {
caryclark54359292015-03-26 07:52:43 -0700651 return 1;
caryclark45fa4472015-01-16 07:04:10 -0800652 }
653 }
caryclark54359292015-03-26 07:52:43 -0700654 return 0;
655}
656
caryclark1049f122015-04-20 08:31:59 -0700657template<typename TCurve, typename OppCurve>
658bool SkTSpan<TCurve, OppCurve>::onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp,
659 bool* start, bool* oppStart, bool* ptsInCommon) {
caryclark54359292015-03-26 07:52:43 -0700660 if (opp->fPart[0] == fPart[0]) {
661 *start = *oppStart = true;
662 } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
663 *start = false;
664 *oppStart = true;
caryclark1049f122015-04-20 08:31:59 -0700665 } else if (opp->fPart[OppCurve::kPointLast] == fPart[0]) {
caryclark54359292015-03-26 07:52:43 -0700666 *start = true;
667 *oppStart = false;
caryclark1049f122015-04-20 08:31:59 -0700668 } else if (opp->fPart[OppCurve::kPointLast] == fPart[TCurve::kPointLast]) {
caryclark54359292015-03-26 07:52:43 -0700669 *start = *oppStart = false;
670 } else {
671 *ptsInCommon = false;
672 return false;
673 }
674 *ptsInCommon = true;
caryclark1049f122015-04-20 08:31:59 -0700675 const SkDPoint* otherPts[TCurve::kPointCount - 1], * oppOtherPts[OppCurve::kPointCount - 1];
caryclark54359292015-03-26 07:52:43 -0700676 int baseIndex = *start ? 0 : TCurve::kPointLast;
caryclark1049f122015-04-20 08:31:59 -0700677 fPart.otherPts(baseIndex, otherPts);
678 opp->fPart.otherPts(*oppStart ? 0 : OppCurve::kPointLast, oppOtherPts);
caryclark54359292015-03-26 07:52:43 -0700679 const SkDPoint& base = fPart[baseIndex];
caryclark1049f122015-04-20 08:31:59 -0700680 for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(otherPts); ++o1) {
681 SkDVector v1 = *otherPts[o1] - base;
682 for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(oppOtherPts); ++o2) {
683 SkDVector v2 = *oppOtherPts[o2] - base;
caryclark54359292015-03-26 07:52:43 -0700684 if (v2.dot(v1) >= 0) {
685 return false;
686 }
687 }
688 }
689 return true;
690}
691
caryclark1049f122015-04-20 08:31:59 -0700692template<typename TCurve, typename OppCurve>
693SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::oppT(double t) const {
694 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700695 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700696 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700697 if (between(test->fStartT, t, test->fEndT)) {
698 return test;
699 }
700 bounded = bounded->fNext;
701 }
halcanary96fcdcc2015-08-27 07:41:13 -0700702 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700703}
704
caryclark1049f122015-04-20 08:31:59 -0700705template<typename TCurve, typename OppCurve>
706bool SkTSpan<TCurve, OppCurve>::removeAllBounded() {
caryclark54359292015-03-26 07:52:43 -0700707 bool deleteSpan = false;
caryclark1049f122015-04-20 08:31:59 -0700708 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700709 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700710 SkTSpan<OppCurve, TCurve>* opp = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700711 deleteSpan |= opp->removeBounded(this);
712 bounded = bounded->fNext;
713 }
714 return deleteSpan;
715}
716
caryclark1049f122015-04-20 08:31:59 -0700717template<typename TCurve, typename OppCurve>
718bool SkTSpan<TCurve, OppCurve>::removeBounded(const SkTSpan<OppCurve, TCurve>* opp) {
caryclark54359292015-03-26 07:52:43 -0700719 if (fHasPerp) {
720 bool foundStart = false;
721 bool foundEnd = false;
caryclark1049f122015-04-20 08:31:59 -0700722 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700723 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700724 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700725 if (opp != test) {
726 foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT);
727 foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
728 }
729 bounded = bounded->fNext;
730 }
731 if (!foundStart || !foundEnd) {
732 fHasPerp = false;
733 fCoinStart.init();
734 fCoinEnd.init();
735 }
736 }
caryclark1049f122015-04-20 08:31:59 -0700737 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700738 SkTSpanBounded<OppCurve, TCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -0700739 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700740 SkTSpanBounded<OppCurve, TCurve>* boundedNext = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -0700741 if (opp == bounded->fBounded) {
742 if (prev) {
743 prev->fNext = boundedNext;
744 return false;
745 } else {
746 fBounded = boundedNext;
halcanary96fcdcc2015-08-27 07:41:13 -0700747 return fBounded == nullptr;
caryclark54359292015-03-26 07:52:43 -0700748 }
749 }
750 prev = bounded;
751 bounded = boundedNext;
752 }
caryclark643ede62016-08-08 14:27:45 -0700753 SkOPASSERT(0);
caryclark45fa4472015-01-16 07:04:10 -0800754 return false;
755}
756
caryclark1049f122015-04-20 08:31:59 -0700757template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500758bool SkTSpan<TCurve, OppCurve>::splitAt(SkTSpan* work, double t, SkArenaAlloc* heap) {
caryclark45fa4472015-01-16 07:04:10 -0800759 fStartT = t;
760 fEndT = work->fEndT;
761 if (fStartT == fEndT) {
762 fCollapsed = true;
763 return false;
764 }
765 work->fEndT = t;
766 if (work->fStartT == work->fEndT) {
767 work->fCollapsed = true;
768 return false;
769 }
770 fPrev = work;
771 fNext = work->fNext;
772 fIsLinear = work->fIsLinear;
caryclark54359292015-03-26 07:52:43 -0700773 fIsLine = work->fIsLine;
774
caryclark45fa4472015-01-16 07:04:10 -0800775 work->fNext = this;
776 if (fNext) {
777 fNext->fPrev = this;
778 }
caryclark643ede62016-08-08 14:27:45 -0700779 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700780 SkTSpanBounded<OppCurve, TCurve>* bounded = work->fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700781 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700782 while (bounded) {
783 this->addBounded(bounded->fBounded, heap);
784 bounded = bounded->fNext;
785 }
786 bounded = fBounded;
787 while (bounded) {
788 bounded->fBounded->addBounded(this, heap);
789 bounded = bounded->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800790 }
791 return true;
792}
793
caryclark1049f122015-04-20 08:31:59 -0700794template<typename TCurve, typename OppCurve>
795void SkTSpan<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -0700796#if DEBUG_VALIDATE
797 SkASSERT(this != fPrev);
798 SkASSERT(this != fNext);
halcanary96fcdcc2015-08-27 07:41:13 -0700799 SkASSERT(fNext == nullptr || fNext != fPrev);
800 SkASSERT(fNext == nullptr || this == fNext->fPrev);
801 SkASSERT(fPrev == nullptr || this == fPrev->fNext);
caryclark643ede62016-08-08 14:27:45 -0700802 this->validateBounded();
803#endif
804#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700805 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed);
caryclarke839e782016-09-15 07:48:18 -0700806 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollapsed == 0xFF);
caryclark45fa4472015-01-16 07:04:10 -0800807 SkASSERT(0 <= fStartT);
808 SkASSERT(fEndT <= 1);
caryclark54359292015-03-26 07:52:43 -0700809 SkASSERT(fStartT <= fEndT);
caryclarke839e782016-09-15 07:48:18 -0700810 SkASSERT(fBounded || fCollapsed == 0xFF);
caryclark54359292015-03-26 07:52:43 -0700811 if (fHasPerp) {
caryclark6c3b9cd2016-09-26 05:36:58 -0700812 if (fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700813 validatePerpT(fCoinStart.perpT());
814 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt());
815 }
caryclark6c3b9cd2016-09-26 05:36:58 -0700816 if (fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700817 validatePerpT(fCoinEnd.perpT());
818 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt());
819 }
caryclarkccec0f92015-03-24 07:28:17 -0700820 }
reed0dc4dd62015-03-24 13:55:33 -0700821#endif
caryclark54359292015-03-26 07:52:43 -0700822}
caryclarkccec0f92015-03-24 07:28:17 -0700823
caryclark1049f122015-04-20 08:31:59 -0700824template<typename TCurve, typename OppCurve>
825void SkTSpan<TCurve, OppCurve>::validateBounded() const {
caryclark54359292015-03-26 07:52:43 -0700826#if DEBUG_VALIDATE
caryclark1049f122015-04-20 08:31:59 -0700827 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700828 while (testBounded) {
csmartdaltonceeaa782016-08-10 10:07:57 -0700829 SkDEBUGCODE(const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded);
caryclark54359292015-03-26 07:52:43 -0700830 SkASSERT(!overlap->fDeleted);
caryclark643ede62016-08-08 14:27:45 -0700831#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700832 SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
833 SkASSERT(overlap->findOppSpan(this));
caryclark643ede62016-08-08 14:27:45 -0700834#endif
caryclark54359292015-03-26 07:52:43 -0700835 testBounded = testBounded->fNext;
836 }
837#endif
838}
839
caryclark1049f122015-04-20 08:31:59 -0700840template<typename TCurve, typename OppCurve>
841void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const {
842 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700843 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700844 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded;
caryclark26ad22a2015-10-16 09:03:38 -0700845 if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) {
caryclark54359292015-03-26 07:52:43 -0700846 return;
847 }
848 testBounded = testBounded->fNext;
849 }
850 SkASSERT(0);
caryclark54359292015-03-26 07:52:43 -0700851}
852
caryclark1049f122015-04-20 08:31:59 -0700853template<typename TCurve, typename OppCurve>
854void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
855 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt);
caryclark54359292015-03-26 07:52:43 -0700856}
857
858
caryclark1049f122015-04-20 08:31:59 -0700859template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500860SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
caryclarke25a4f62016-07-26 09:26:29 -0700861 SkDEBUGPARAMS(SkOpGlobalState* debugGlobalState)
862 PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
caryclark45fa4472015-01-16 07:04:10 -0800863 : fCurve(c)
caryclark1049f122015-04-20 08:31:59 -0700864 , fHeap(sizeof(SkTSpan<TCurve, OppCurve>) * 4)
halcanary96fcdcc2015-08-27 07:41:13 -0700865 , fCoincident(nullptr)
866 , fDeleted(nullptr)
caryclark45fa4472015-01-16 07:04:10 -0800867 , fActiveCount(0)
caryclarke25a4f62016-07-26 09:26:29 -0700868 SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState))
caryclark54359292015-03-26 07:52:43 -0700869 PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
870 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
871 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
caryclark45fa4472015-01-16 07:04:10 -0800872{
caryclark34efb702016-10-24 08:19:06 -0700873 this->resetRemovedEnds();
874 fHead = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700875 SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState));
caryclark45fa4472015-01-16 07:04:10 -0800876 fHead->init(c);
877}
878
caryclark1049f122015-04-20 08:31:59 -0700879template<typename TCurve, typename OppCurve>
880SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
881 SkTSpan<TCurve, OppCurve>* result;
caryclark45fa4472015-01-16 07:04:10 -0800882 if (fDeleted) {
883 result = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800884 fDeleted = result->fNext;
885 } else {
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500886 result = fHeap.make<SkTSpan<TCurve, OppCurve>>();
caryclark45fa4472015-01-16 07:04:10 -0800887#if DEBUG_T_SECT
888 ++fDebugAllocatedCount;
889#endif
890 }
caryclarked0935a2015-10-22 07:23:52 -0700891 result->reset();
caryclark08b32492015-04-06 11:41:29 -0700892 result->fHasPerp = false;
893 result->fDeleted = false;
caryclark55888e42016-07-18 10:01:36 -0700894 ++fActiveCount;
caryclark54359292015-03-26 07:52:43 -0700895 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
caryclark1049f122015-04-20 08:31:59 -0700896 SkDEBUGCODE(result->fDebugSect = this);
caryclarked0935a2015-10-22 07:23:52 -0700897#ifdef SK_DEBUG
898 result->fPart.debugInit();
899 result->fCoinStart.debugInit();
900 result->fCoinEnd.debugInit();
901 result->fPrev = result->fNext = nullptr;
902 result->fBounds.debugInit();
903 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN;
904 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF;
905#endif
caryclark45fa4472015-01-16 07:04:10 -0800906 return result;
907}
908
caryclark1049f122015-04-20 08:31:59 -0700909template<typename TCurve, typename OppCurve>
910bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
Cary Clark74b42902018-03-09 07:38:47 -0500911 double tStep, double* resultT, double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst) {
caryclark1049f122015-04-20 08:31:59 -0700912 SkTSpan<TCurve, OppCurve> work;
caryclark45fa4472015-01-16 07:04:10 -0800913 double result = work.fStartT = work.fEndT = tStart;
caryclark1049f122015-04-20 08:31:59 -0700914 SkDEBUGCODE(work.fDebugSect = this);
caryclark45fa4472015-01-16 07:04:10 -0800915 SkDPoint last = fCurve.ptAtT(tStart);
916 SkDPoint oppPt;
917 bool flip = false;
caryclarkcdeff812016-07-22 03:34:19 -0700918 bool contained = false;
Cary Clark74b42902018-03-09 07:38:47 -0500919 bool down = tStep < 0;
caryclark1049f122015-04-20 08:31:59 -0700920 const OppCurve& opp = sect2->fCurve;
caryclark45fa4472015-01-16 07:04:10 -0800921 do {
922 tStep *= 0.5;
923 work.fStartT += tStep;
924 if (flip) {
925 tStep = -tStep;
926 flip = false;
927 }
928 work.initBounds(fCurve);
929 if (work.fCollapsed) {
930 return false;
931 }
932 if (last.approximatelyEqual(work.fPart[0])) {
933 break;
934 }
935 last = work.fPart[0];
936 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp);
caryclark6c3b9cd2016-09-26 05:36:58 -0700937 if (work.fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700938#if DEBUG_T_SECT
939 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt());
940#endif
caryclark45fa4472015-01-16 07:04:10 -0800941 double oppTTest = work.fCoinStart.perpT();
caryclark54359292015-03-26 07:52:43 -0700942 if (sect2->fHead->contains(oppTTest)) {
caryclark45fa4472015-01-16 07:04:10 -0800943 *oppT = oppTTest;
944 oppPt = work.fCoinStart.perpPt();
caryclarkcdeff812016-07-22 03:34:19 -0700945 contained = true;
Cary Clark74b42902018-03-09 07:38:47 -0500946 if (down ? result <= work.fStartT : result >= work.fStartT) {
947 *oppFirst = nullptr; // signal caller to fail
948 return false;
949 }
caryclark45fa4472015-01-16 07:04:10 -0800950 result = work.fStartT;
951 continue;
952 }
953 }
954 tStep = -tStep;
955 flip = true;
956 } while (true);
caryclarkcdeff812016-07-22 03:34:19 -0700957 if (!contained) {
958 return false;
959 }
caryclark45fa4472015-01-16 07:04:10 -0800960 if (last.approximatelyEqual(fCurve[0])) {
961 result = 0;
962 } else if (last.approximatelyEqual(fCurve[TCurve::kPointLast])) {
963 result = 1;
964 }
965 if (oppPt.approximatelyEqual(opp[0])) {
966 *oppT = 0;
caryclark1049f122015-04-20 08:31:59 -0700967 } else if (oppPt.approximatelyEqual(opp[OppCurve::kPointLast])) {
caryclark45fa4472015-01-16 07:04:10 -0800968 *oppT = 1;
969 }
970 *resultT = result;
971 return true;
972}
973
974// OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
975// so that each quad sect has a pointer to the largest, and can update it as spans
976// are split
caryclark1049f122015-04-20 08:31:59 -0700977template<typename TCurve, typename OppCurve>
978SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
979 SkTSpan<TCurve, OppCurve>* test = fHead;
980 SkTSpan<TCurve, OppCurve>* largest = fHead;
caryclark54359292015-03-26 07:52:43 -0700981 bool lCollapsed = largest->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800982 while ((test = test->fNext)) {
caryclark54359292015-03-26 07:52:43 -0700983 bool tCollapsed = test->fCollapsed;
984 if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
985 largest->fBoundsMax < test->fBoundsMax)) {
caryclark45fa4472015-01-16 07:04:10 -0800986 largest = test;
caryclark1049f122015-04-20 08:31:59 -0700987 lCollapsed = test->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800988 }
989 }
caryclark54359292015-03-26 07:52:43 -0700990 return largest;
caryclark45fa4472015-01-16 07:04:10 -0800991}
992
caryclark1049f122015-04-20 08:31:59 -0700993template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -0700994bool SkTSect<TCurve, OppCurve>::coincidentCheck(SkTSect<OppCurve, TCurve>* sect2) {
caryclark1049f122015-04-20 08:31:59 -0700995 SkTSpan<TCurve, OppCurve>* first = fHead;
caryclark9feb6322016-10-25 08:58:26 -0700996 if (!first) {
997 return false;
998 }
caryclark1049f122015-04-20 08:31:59 -0700999 SkTSpan<TCurve, OppCurve>* last, * next;
caryclark45fa4472015-01-16 07:04:10 -08001000 do {
caryclark54359292015-03-26 07:52:43 -07001001 int consecutive = this->countConsecutiveSpans(first, &last);
1002 next = last->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001003 if (consecutive < COINCIDENT_SPAN_COUNT) {
1004 continue;
1005 }
caryclark54359292015-03-26 07:52:43 -07001006 this->validate();
1007 sect2->validate();
1008 this->computePerpendiculars(sect2, first, last);
1009 this->validate();
1010 sect2->validate();
caryclark45fa4472015-01-16 07:04:10 -08001011 // check to see if a range of points are on the curve
caryclark1049f122015-04-20 08:31:59 -07001012 SkTSpan<TCurve, OppCurve>* coinStart = first;
caryclark54359292015-03-26 07:52:43 -07001013 do {
caryclarkef7cee42016-09-06 09:05:54 -07001014 bool success = this->extractCoincident(sect2, coinStart, last, &coinStart);
1015 if (!success) {
1016 return false;
1017 }
caryclark54359292015-03-26 07:52:43 -07001018 } while (coinStart && !last->fDeleted);
caryclark55888e42016-07-18 10:01:36 -07001019 if (!fHead || !sect2->fHead) {
1020 break;
1021 }
caryclark643ede62016-08-08 14:27:45 -07001022 if (!next || next->fDeleted) {
1023 break;
1024 }
caryclark45fa4472015-01-16 07:04:10 -08001025 } while ((first = next));
caryclarkef7cee42016-09-06 09:05:54 -07001026 return true;
caryclark45fa4472015-01-16 07:04:10 -08001027}
1028
caryclark1049f122015-04-20 08:31:59 -07001029template<typename TCurve, typename OppCurve>
caryclark26ad22a2015-10-16 09:03:38 -07001030void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2,
1031 double start1s, double start1e) {
1032 SkTSpan<TCurve, OppCurve>* first = fHead;
1033 SkTSpan<TCurve, OppCurve>* last = this->tail();
1034 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead;
1035 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail();
1036 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1037 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
1038 this->removeSpanRange(first, last);
1039 sect2->removeSpanRange(oppFirst, oppLast);
1040 first->fStartT = start1s;
1041 first->fEndT = start1e;
1042 first->resetBounds(fCurve);
1043 first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve);
1044 first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->fCurve);
1045 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
caryclarkef784fb2015-10-30 12:03:06 -07001046 double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : SkTMax(0., first->fCoinStart.perpT());
1047 double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : SkTMin(1., first->fCoinEnd.perpT());
caryclark26ad22a2015-10-16 09:03:38 -07001048 if (!oppMatched) {
1049 SkTSwap(oppStartT, oppEndT);
1050 }
1051 oppFirst->fStartT = oppStartT;
1052 oppFirst->fEndT = oppEndT;
1053 oppFirst->resetBounds(sect2->fCurve);
1054 this->removeCoincident(first, false);
1055 sect2->removeCoincident(oppFirst, true);
1056 if (deleteEmptySpans) {
1057 this->deleteEmptySpans();
1058 sect2->deleteEmptySpans();
1059 }
1060}
1061
1062template<typename TCurve, typename OppCurve>
caryclark1049f122015-04-20 08:31:59 -07001063bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) {
1064 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001065 while (test) {
1066 if (between(test->fStartT, t, test->fEndT)) {
1067 return true;
1068 }
1069 test = test->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001070 }
caryclark54359292015-03-26 07:52:43 -07001071 return false;
caryclark45fa4472015-01-16 07:04:10 -08001072}
1073
caryclark1049f122015-04-20 08:31:59 -07001074template<typename TCurve, typename OppCurve>
1075int SkTSect<TCurve, OppCurve>::collapsed() const {
1076 int result = 0;
1077 const SkTSpan<TCurve, OppCurve>* test = fHead;
1078 while (test) {
1079 if (test->fCollapsed) {
1080 ++result;
1081 }
1082 test = test->next();
1083 }
1084 return result;
1085}
1086
1087template<typename TCurve, typename OppCurve>
1088void SkTSect<TCurve, OppCurve>::computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2,
1089 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
1090 const OppCurve& opp = sect2->fCurve;
1091 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001092 SkTSpan<TCurve, OppCurve>* prior = nullptr;
caryclark45fa4472015-01-16 07:04:10 -08001093 do {
caryclark54359292015-03-26 07:52:43 -07001094 if (!work->fHasPerp && !work->fCollapsed) {
1095 if (prior) {
1096 work->fCoinStart = prior->fCoinEnd;
1097 } else {
1098 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp);
caryclark45fa4472015-01-16 07:04:10 -08001099 }
caryclark6c3b9cd2016-09-26 05:36:58 -07001100 if (work->fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001101 double perpT = work->fCoinStart.perpT();
1102 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001103 work->fCoinStart.init();
caryclark54359292015-03-26 07:52:43 -07001104 } else {
1105 sect2->addForPerp(work, perpT);
1106 }
1107 }
1108 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPointLast], opp);
caryclark6c3b9cd2016-09-26 05:36:58 -07001109 if (work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001110 double perpT = work->fCoinEnd.perpT();
1111 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001112 work->fCoinEnd.init();
caryclark54359292015-03-26 07:52:43 -07001113 } else {
1114 sect2->addForPerp(work, perpT);
1115 }
1116 }
1117 work->fHasPerp = true;
caryclark45fa4472015-01-16 07:04:10 -08001118 }
1119 if (work == last) {
1120 break;
1121 }
caryclark54359292015-03-26 07:52:43 -07001122 prior = work;
caryclark45fa4472015-01-16 07:04:10 -08001123 work = work->fNext;
1124 SkASSERT(work);
1125 } while (true);
caryclark54359292015-03-26 07:52:43 -07001126}
1127
caryclark1049f122015-04-20 08:31:59 -07001128template<typename TCurve, typename OppCurve>
1129int SkTSect<TCurve, OppCurve>::countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
1130 SkTSpan<TCurve, OppCurve>** lastPtr) const {
caryclark54359292015-03-26 07:52:43 -07001131 int consecutive = 1;
caryclark1049f122015-04-20 08:31:59 -07001132 SkTSpan<TCurve, OppCurve>* last = first;
caryclark54359292015-03-26 07:52:43 -07001133 do {
caryclark1049f122015-04-20 08:31:59 -07001134 SkTSpan<TCurve, OppCurve>* next = last->fNext;
caryclark54359292015-03-26 07:52:43 -07001135 if (!next) {
1136 break;
1137 }
1138 if (next->fStartT > last->fEndT) {
1139 break;
1140 }
1141 ++consecutive;
1142 last = next;
1143 } while (true);
1144 *lastPtr = last;
1145 return consecutive;
1146}
1147
caryclark1049f122015-04-20 08:31:59 -07001148template<typename TCurve, typename OppCurve>
1149bool SkTSect<TCurve, OppCurve>::debugHasBounded(const SkTSpan<OppCurve, TCurve>* span) const {
1150 const SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001151 if (!test) {
1152 return false;
1153 }
1154 do {
1155 if (test->findOppSpan(span)) {
1156 return true;
1157 }
1158 } while ((test = test->next()));
1159 return false;
1160}
1161
caryclark1049f122015-04-20 08:31:59 -07001162template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001163bool SkTSect<TCurve, OppCurve>::deleteEmptySpans() {
caryclark1049f122015-04-20 08:31:59 -07001164 SkTSpan<TCurve, OppCurve>* test;
1165 SkTSpan<TCurve, OppCurve>* next = fHead;
Cary Clark59ed4822016-12-08 16:17:56 -05001166 int safetyHatch = 1000;
caryclark54359292015-03-26 07:52:43 -07001167 while ((test = next)) {
1168 next = test->fNext;
1169 if (!test->fBounded) {
caryclarkef7cee42016-09-06 09:05:54 -07001170 if (!this->removeSpan(test)) {
1171 return false;
1172 }
caryclark54359292015-03-26 07:52:43 -07001173 }
Cary Clark59ed4822016-12-08 16:17:56 -05001174 if (--safetyHatch < 0) {
1175 return false;
1176 }
caryclark54359292015-03-26 07:52:43 -07001177 }
caryclarkef7cee42016-09-06 09:05:54 -07001178 return true;
caryclark54359292015-03-26 07:52:43 -07001179}
1180
caryclark1049f122015-04-20 08:31:59 -07001181template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001182bool SkTSect<TCurve, OppCurve>::extractCoincident(
caryclark1049f122015-04-20 08:31:59 -07001183 SkTSect<OppCurve, TCurve>* sect2,
caryclarkef7cee42016-09-06 09:05:54 -07001184 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
1185 SkTSpan<TCurve, OppCurve>** result) {
caryclark1049f122015-04-20 08:31:59 -07001186 first = findCoincidentRun(first, &last);
caryclarka1b42d92016-08-16 10:25:29 -07001187 if (!first || !last) {
caryclarkef7cee42016-09-06 09:05:54 -07001188 *result = nullptr;
1189 return true;
caryclark45fa4472015-01-16 07:04:10 -08001190 }
1191 // march outwards to find limit of coincidence from here to previous and next spans
1192 double startT = first->fStartT;
caryclarkd8bc16b2015-03-26 09:05:12 -07001193 double oppStartT SK_INIT_TO_AVOID_WARNING;
caryclark54359292015-03-26 07:52:43 -07001194 double oppEndT SK_INIT_TO_AVOID_WARNING;
caryclark1049f122015-04-20 08:31:59 -07001195 SkTSpan<TCurve, OppCurve>* prev = first->fPrev;
caryclark6c3b9cd2016-09-26 05:36:58 -07001196 SkASSERT(first->fCoinStart.isMatch());
caryclark1049f122015-04-20 08:31:59 -07001197 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
caryclark6c3b9cd2016-09-26 05:36:58 -07001198 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001199 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
1200 double coinStart;
1201 SkDEBUGCODE(double coinEnd);
caryclark1049f122015-04-20 08:31:59 -07001202 SkTSpan<OppCurve, TCurve>* cutFirst;
caryclark54359292015-03-26 07:52:43 -07001203 if (prev && prev->fEndT == startT
1204 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
Cary Clark74b42902018-03-09 07:38:47 -05001205 &oppStartT, &oppFirst)
caryclark1049f122015-04-20 08:31:59 -07001206 && prev->fStartT < coinStart && coinStart < startT
1207 && (cutFirst = prev->oppT(oppStartT))) {
1208 oppFirst = cutFirst;
caryclark54359292015-03-26 07:52:43 -07001209 first = this->addSplitAt(prev, coinStart);
1210 first->markCoincident();
1211 prev->fCoinEnd.markCoincident();
1212 if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
caryclark1049f122015-04-20 08:31:59 -07001213 SkTSpan<OppCurve, TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
caryclark54359292015-03-26 07:52:43 -07001214 if (oppMatched) {
1215 oppFirst->fCoinEnd.markCoincident();
1216 oppHalf->markCoincident();
1217 oppFirst = oppHalf;
1218 } else {
1219 oppFirst->markCoincident();
1220 oppHalf->fCoinStart.markCoincident();
1221 }
1222 }
1223 } else {
Cary Clark74b42902018-03-09 07:38:47 -05001224 if (!oppFirst) {
1225 return false;
1226 }
caryclark54359292015-03-26 07:52:43 -07001227 SkDEBUGCODE(coinStart = first->fStartT);
1228 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
1229 }
caryclark1049f122015-04-20 08:31:59 -07001230 // FIXME: incomplete : if we're not at the end, find end of coin
1231 SkTSpan<OppCurve, TCurve>* oppLast;
caryclark6c3b9cd2016-09-26 05:36:58 -07001232 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001233 oppLast = last->findOppT(last->fCoinEnd.perpT());
1234 SkDEBUGCODE(coinEnd = last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001235#ifdef SK_DEBUG
1236 if (!this->globalState() || !this->globalState()->debugSkipAssert()) {
1237 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT;
1238 }
1239#endif
caryclark54359292015-03-26 07:52:43 -07001240 if (!oppMatched) {
1241 SkTSwap(oppFirst, oppLast);
1242 SkTSwap(oppStartT, oppEndT);
1243 }
caryclarke25a4f62016-07-26 09:26:29 -07001244 SkOPASSERT(oppStartT < oppEndT);
caryclark54359292015-03-26 07:52:43 -07001245 SkASSERT(coinStart == first->fStartT);
1246 SkASSERT(coinEnd == last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001247 SkOPASSERT(oppStartT == oppFirst->fStartT);
1248 SkOPASSERT(oppEndT == oppLast->fEndT);
1249 if (!oppFirst) {
caryclarkef7cee42016-09-06 09:05:54 -07001250 *result = nullptr;
1251 return true;
caryclark643ede62016-08-08 14:27:45 -07001252 }
caryclark42942862016-08-19 07:01:33 -07001253 if (!oppLast) {
caryclarkef7cee42016-09-06 09:05:54 -07001254 *result = nullptr;
1255 return true;
caryclark42942862016-08-19 07:01:33 -07001256 }
caryclark54359292015-03-26 07:52:43 -07001257 // reduce coincident runs to single entries
1258 this->validate();
1259 sect2->validate();
caryclark1049f122015-04-20 08:31:59 -07001260 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1261 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
caryclark54359292015-03-26 07:52:43 -07001262 this->removeSpanRange(first, last);
1263 sect2->removeSpanRange(oppFirst, oppLast);
1264 first->fEndT = last->fEndT;
1265 first->resetBounds(this->fCurve);
1266 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], sect2->fCurve);
1267 first->fCoinEnd.setPerp(fCurve, first->fEndT, first->fPart[TCurve::kPointLast], sect2->fCurve);
1268 oppStartT = first->fCoinStart.perpT();
1269 oppEndT = first->fCoinEnd.perpT();
1270 if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) {
1271 if (!oppMatched) {
1272 SkTSwap(oppStartT, oppEndT);
1273 }
1274 oppFirst->fStartT = oppStartT;
1275 oppFirst->fEndT = oppEndT;
1276 oppFirst->resetBounds(sect2->fCurve);
1277 }
1278 this->validateBounded();
1279 sect2->validateBounded();
1280 last = first->fNext;
Cary Clark38702ab2017-09-05 18:11:55 -04001281 if (!this->removeCoincident(first, false)) {
1282 return false;
1283 }
1284 if (!sect2->removeCoincident(oppFirst, true)) {
1285 return false;
1286 }
caryclark1049f122015-04-20 08:31:59 -07001287 if (deleteEmptySpans) {
caryclarkef7cee42016-09-06 09:05:54 -07001288 if (!this->deleteEmptySpans() || !sect2->deleteEmptySpans()) {
1289 *result = nullptr;
1290 return false;
1291 }
caryclark54359292015-03-26 07:52:43 -07001292 }
1293 this->validate();
1294 sect2->validate();
caryclarkef7cee42016-09-06 09:05:54 -07001295 *result = last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr;
1296 return true;
caryclark54359292015-03-26 07:52:43 -07001297}
1298
caryclark1049f122015-04-20 08:31:59 -07001299template<typename TCurve, typename OppCurve>
1300SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun(
1301 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) {
1302 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001303 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr;
1304 first = nullptr;
caryclark54359292015-03-26 07:52:43 -07001305 // find the first fully coincident span
1306 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07001307 if (work->fCoinStart.isMatch()) {
caryclark1049f122015-04-20 08:31:59 -07001308#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -07001309 work->validatePerpT(work->fCoinStart.perpT());
1310 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt());
caryclark1049f122015-04-20 08:31:59 -07001311#endif
caryclarka35ab3e2016-10-20 08:32:18 -07001312 SkOPASSERT(work->hasOppT(work->fCoinStart.perpT()));
caryclark6c3b9cd2016-09-26 05:36:58 -07001313 if (!work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001314 break;
1315 }
1316 lastCandidate = work;
1317 if (!first) {
1318 first = work;
1319 }
caryclark1049f122015-04-20 08:31:59 -07001320 } else if (first && work->fCollapsed) {
1321 *lastPtr = lastCandidate;
1322 return first;
caryclark54359292015-03-26 07:52:43 -07001323 } else {
halcanary96fcdcc2015-08-27 07:41:13 -07001324 lastCandidate = nullptr;
caryclark643ede62016-08-08 14:27:45 -07001325 SkOPASSERT(!first);
caryclark54359292015-03-26 07:52:43 -07001326 }
1327 if (work == *lastPtr) {
1328 return first;
1329 }
1330 work = work->fNext;
caryclarke25a4f62016-07-26 09:26:29 -07001331 if (!work) {
1332 return nullptr;
1333 }
caryclark54359292015-03-26 07:52:43 -07001334 } while (true);
1335 if (lastCandidate) {
1336 *lastPtr = lastCandidate;
1337 }
1338 return first;
1339}
1340
caryclark1049f122015-04-20 08:31:59 -07001341template<typename TCurve, typename OppCurve>
1342int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
1343 SkTSect<OppCurve, TCurve>* opp,
1344 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult) {
caryclark54359292015-03-26 07:52:43 -07001345 bool spanStart, oppStart;
1346 int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
1347 if (hullResult >= 0) {
1348 if (hullResult == 2) { // hulls have one point in common
1349 if (!span->fBounded || !span->fBounded->fNext) {
1350 SkASSERT(!span->fBounded || span->fBounded->fBounded == oppSpan);
1351 if (spanStart) {
1352 span->fEndT = span->fStartT;
caryclark45fa4472015-01-16 07:04:10 -08001353 } else {
caryclark54359292015-03-26 07:52:43 -07001354 span->fStartT = span->fEndT;
1355 }
1356 } else {
1357 hullResult = 1;
1358 }
1359 if (!oppSpan->fBounded || !oppSpan->fBounded->fNext) {
1360 SkASSERT(!oppSpan->fBounded || oppSpan->fBounded->fBounded == span);
1361 if (oppStart) {
1362 oppSpan->fEndT = oppSpan->fStartT;
1363 } else {
1364 oppSpan->fStartT = oppSpan->fEndT;
1365 }
1366 *oppResult = 2;
1367 } else {
1368 *oppResult = 1;
1369 }
1370 } else {
1371 *oppResult = 1;
1372 }
1373 return hullResult;
1374 }
1375 if (span->fIsLine && oppSpan->fIsLine) {
1376 SkIntersections i;
1377 int sects = this->linesIntersect(span, opp, oppSpan, &i);
caryclark26ad22a2015-10-16 09:03:38 -07001378 if (sects == 2) {
1379 return *oppResult = 1;
1380 }
caryclark54359292015-03-26 07:52:43 -07001381 if (!sects) {
1382 return -1;
1383 }
caryclark34efb702016-10-24 08:19:06 -07001384 this->removedEndCheck(span);
caryclark54359292015-03-26 07:52:43 -07001385 span->fStartT = span->fEndT = i[0][0];
caryclark34efb702016-10-24 08:19:06 -07001386 opp->removedEndCheck(oppSpan);
caryclark54359292015-03-26 07:52:43 -07001387 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1388 return *oppResult = 2;
1389 }
1390 if (span->fIsLinear || oppSpan->fIsLinear) {
1391 return *oppResult = (int) span->linearsIntersect(oppSpan);
1392 }
1393 return *oppResult = 1;
1394}
1395
caryclarked0935a2015-10-22 07:23:52 -07001396template<typename TCurve>
1397static bool is_parallel(const SkDLine& thisLine, const TCurve& opp) {
1398 if (!opp.IsConic()) {
1399 return false; // FIXME : breaks a lot of stuff now
1400 }
1401 int finds = 0;
1402 SkDLine thisPerp;
1403 thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1404 thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1405 thisPerp.fPts[1] = thisLine.fPts[1];
1406 SkIntersections perpRayI;
1407 perpRayI.intersectRay(opp, thisPerp);
1408 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1409 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]);
1410 }
1411 thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1412 thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1413 thisPerp.fPts[0] = thisLine.fPts[0];
1414 perpRayI.intersectRay(opp, thisPerp);
1415 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1416 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]);
1417 }
1418 return finds >= 2;
1419}
1420
caryclark54359292015-03-26 07:52:43 -07001421// while the intersection points are sufficiently far apart:
1422// construct the tangent lines from the intersections
1423// find the point where the tangent line intersects the opposite curve
caryclark1049f122015-04-20 08:31:59 -07001424template<typename TCurve, typename OppCurve>
1425int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
1426 SkTSect<OppCurve, TCurve>* opp,
1427 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
caryclarka35ab3e2016-10-20 08:32:18 -07001428 SkIntersections thisRayI SkDEBUGCODE((span->fDebugGlobalState));
1429 SkIntersections oppRayI SkDEBUGCODE((span->fDebugGlobalState));
caryclark54359292015-03-26 07:52:43 -07001430 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
caryclark1049f122015-04-20 08:31:59 -07001431 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
caryclark54359292015-03-26 07:52:43 -07001432 int loopCount = 0;
1433 double bestDistSq = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -07001434 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1435 return 0;
1436 }
1437 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1438 return 0;
1439 }
caryclark26ad22a2015-10-16 09:03:38 -07001440 // if the ends of each line intersect the opposite curve, the lines are coincident
1441 if (thisRayI.used() > 1) {
1442 int ptMatches = 0;
1443 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) {
1444 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1445 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPts[lIndex]);
1446 }
1447 }
caryclarked0935a2015-10-22 07:23:52 -07001448 if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001449 return 2;
1450 }
1451 }
1452 if (oppRayI.used() > 1) {
1453 int ptMatches = 0;
1454 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) {
Cary Clarkd80870f2017-10-17 11:57:26 -04001455 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(oppLine.fPts); ++lIndex) {
caryclark26ad22a2015-10-16 09:03:38 -07001456 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[lIndex]);
1457 }
1458 }
caryclarked0935a2015-10-22 07:23:52 -07001459 if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001460 return 2;
1461 }
1462 }
caryclark54359292015-03-26 07:52:43 -07001463 do {
caryclark54359292015-03-26 07:52:43 -07001464 // pick the closest pair of points
1465 double closest = DBL_MAX;
1466 int closeIndex SK_INIT_TO_AVOID_WARNING;
1467 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1468 for (int index = 0; index < oppRayI.used(); ++index) {
1469 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
1470 continue;
1471 }
1472 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) {
1473 if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppSpan->fEndT)) {
1474 continue;
1475 }
1476 double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oIndex));
1477 if (closest > distSq) {
1478 closest = distSq;
1479 closeIndex = index;
1480 oppCloseIndex = oIndex;
caryclarkccec0f92015-03-24 07:28:17 -07001481 }
caryclarkccec0f92015-03-24 07:28:17 -07001482 }
reed0dc4dd62015-03-24 13:55:33 -07001483 }
caryclark54359292015-03-26 07:52:43 -07001484 if (closest == DBL_MAX) {
caryclark1049f122015-04-20 08:31:59 -07001485 break;
reed0dc4dd62015-03-24 13:55:33 -07001486 }
caryclark54359292015-03-26 07:52:43 -07001487 const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
1488 const SkDPoint& iPt = oppRayI.pt(closeIndex);
1489 if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT)
1490 && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan->fEndT)
1491 && oppIPt.approximatelyEqual(iPt)) {
1492 i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex);
1493 return i->used();
1494 }
1495 double distSq = oppIPt.distanceSquared(iPt);
1496 if (bestDistSq < distSq || ++loopCount > 5) {
caryclark1049f122015-04-20 08:31:59 -07001497 return 0;
caryclark54359292015-03-26 07:52:43 -07001498 }
1499 bestDistSq = distSq;
caryclark1049f122015-04-20 08:31:59 -07001500 double oppStart = oppRayI[0][closeIndex];
1501 thisLine[0] = fCurve.ptAtT(oppStart);
1502 thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart);
1503 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1504 break;
1505 }
1506 double start = thisRayI[0][oppCloseIndex];
1507 oppLine[0] = opp->fCurve.ptAtT(start);
1508 oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start);
1509 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1510 break;
1511 }
caryclark54359292015-03-26 07:52:43 -07001512 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001513 // convergence may fail if the curves are nearly coincident
1514 SkTCoincident<OppCurve, TCurve> oCoinS, oCoinE;
1515 oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->fPart[0], fCurve);
1516 oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->fPart[OppCurve::kPointLast], fCurve);
1517 double tStart = oCoinS.perpT();
1518 double tEnd = oCoinE.perpT();
1519 bool swap = tStart > tEnd;
1520 if (swap) {
1521 SkTSwap(tStart, tEnd);
1522 }
1523 tStart = SkTMax(tStart, span->fStartT);
1524 tEnd = SkTMin(tEnd, span->fEndT);
1525 if (tStart > tEnd) {
1526 return 0;
1527 }
1528 SkDVector perpS, perpE;
1529 if (tStart == span->fStartT) {
1530 SkTCoincident<TCurve, OppCurve> coinS;
1531 coinS.setPerp(fCurve, span->fStartT, span->fPart[0], opp->fCurve);
1532 perpS = span->fPart[0] - coinS.perpPt();
1533 } else if (swap) {
1534 perpS = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1535 } else {
1536 perpS = oCoinS.perpPt() - oppSpan->fPart[0];
1537 }
1538 if (tEnd == span->fEndT) {
1539 SkTCoincident<TCurve, OppCurve> coinE;
1540 coinE.setPerp(fCurve, span->fEndT, span->fPart[TCurve::kPointLast], opp->fCurve);
1541 perpE = span->fPart[TCurve::kPointLast] - coinE.perpPt();
1542 } else if (swap) {
1543 perpE = oCoinS.perpPt() - oppSpan->fPart[0];
1544 } else {
1545 perpE = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1546 }
1547 if (perpS.dot(perpE) >= 0) {
1548 return 0;
1549 }
1550 SkTCoincident<TCurve, OppCurve> coinW;
1551 double workT = tStart;
1552 double tStep = tEnd - tStart;
1553 SkDPoint workPt;
1554 do {
1555 tStep *= 0.5;
1556 if (precisely_zero(tStep)) {
1557 return 0;
1558 }
1559 workT += tStep;
1560 workPt = fCurve.ptAtT(workT);
1561 coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
caryclark27c015d2016-09-23 05:47:20 -07001562 double perpT = coinW.perpT();
caryclark6c3b9cd2016-09-26 05:36:58 -07001563 if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) {
caryclarkb6693002015-12-16 12:28:35 -08001564 continue;
1565 }
caryclark1049f122015-04-20 08:31:59 -07001566 SkDVector perpW = workPt - coinW.perpPt();
1567 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
1568 tStep = -tStep;
1569 }
caryclarkb6693002015-12-16 12:28:35 -08001570 if (workPt.approximatelyEqual(coinW.perpPt())) {
1571 break;
1572 }
1573 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001574 double oppTTest = coinW.perpT();
1575 if (!opp->fHead->contains(oppTTest)) {
1576 return 0;
1577 }
1578 i->setMax(1);
1579 i->insert(workT, oppTTest, workPt);
1580 return 1;
caryclark54359292015-03-26 07:52:43 -07001581}
1582
1583
caryclark1049f122015-04-20 08:31:59 -07001584template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001585bool SkTSect<TCurve, OppCurve>::markSpanGone(SkTSpan<TCurve, OppCurve>* span) {
1586 if (--fActiveCount < 0) {
1587 return false;
1588 }
caryclark54359292015-03-26 07:52:43 -07001589 span->fNext = fDeleted;
1590 fDeleted = span;
caryclarke25a4f62016-07-26 09:26:29 -07001591 SkOPASSERT(!span->fDeleted);
caryclark54359292015-03-26 07:52:43 -07001592 span->fDeleted = true;
caryclarkef7cee42016-09-06 09:05:54 -07001593 return true;
caryclark54359292015-03-26 07:52:43 -07001594}
1595
caryclark1049f122015-04-20 08:31:59 -07001596template<typename TCurve, typename OppCurve>
1597bool SkTSect<TCurve, OppCurve>::matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2,
1598 double t2) const {
caryclark54359292015-03-26 07:52:43 -07001599 SkDVector dxdy = this->fCurve.dxdyAtT(t);
1600 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
1601 return dxdy.dot(dxdy2) >= 0;
1602}
1603
caryclark1049f122015-04-20 08:31:59 -07001604template<typename TCurve, typename OppCurve>
1605void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2,
1606 double t2, bool* calcMatched, bool* oppMatched) const {
caryclark54359292015-03-26 07:52:43 -07001607 if (*calcMatched) {
caryclark55888e42016-07-18 10:01:36 -07001608 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
caryclark54359292015-03-26 07:52:43 -07001609 } else {
1610 *oppMatched = this->matchedDirection(t, sect2, t2);
1611 *calcMatched = true;
1612 }
1613}
1614
caryclark1049f122015-04-20 08:31:59 -07001615template<typename TCurve, typename OppCurve>
1616void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2) {
caryclark54359292015-03-26 07:52:43 -07001617 double smallLimit = 0;
1618 do {
1619 // find the smallest unprocessed span
halcanary96fcdcc2015-08-27 07:41:13 -07001620 SkTSpan<TCurve, OppCurve>* smaller = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001621 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001622 do {
caryclark221a4bb2016-10-07 11:15:15 -07001623 if (!test) {
1624 return;
1625 }
caryclark54359292015-03-26 07:52:43 -07001626 if (test->fStartT < smallLimit) {
1627 continue;
1628 }
1629 if (smaller && smaller->fEndT < test->fStartT) {
1630 continue;
1631 }
1632 smaller = test;
1633 } while ((test = test->fNext));
1634 if (!smaller) {
1635 return;
1636 }
1637 smallLimit = smaller->fEndT;
1638 // find next larger span
halcanary96fcdcc2015-08-27 07:41:13 -07001639 SkTSpan<TCurve, OppCurve>* prior = nullptr;
1640 SkTSpan<TCurve, OppCurve>* larger = nullptr;
1641 SkTSpan<TCurve, OppCurve>* largerPrior = nullptr;
caryclark54359292015-03-26 07:52:43 -07001642 test = fCoincident;
1643 do {
1644 if (test->fStartT < smaller->fEndT) {
1645 continue;
1646 }
caryclark221a4bb2016-10-07 11:15:15 -07001647 SkOPASSERT(test->fStartT != smaller->fEndT);
caryclark54359292015-03-26 07:52:43 -07001648 if (larger && larger->fStartT < test->fStartT) {
1649 continue;
1650 }
1651 largerPrior = prior;
1652 larger = test;
1653 } while ((prior = test), (test = test->fNext));
1654 if (!larger) {
1655 continue;
1656 }
1657 // check middle t value to see if it is coincident as well
1658 double midT = (smaller->fEndT + larger->fStartT) / 2;
1659 SkDPoint midPt = fCurve.ptAtT(midT);
caryclark1049f122015-04-20 08:31:59 -07001660 SkTCoincident<TCurve, OppCurve> coin;
caryclark54359292015-03-26 07:52:43 -07001661 coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07001662 if (coin.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001663 smaller->fEndT = larger->fEndT;
1664 smaller->fCoinEnd = larger->fCoinEnd;
1665 if (largerPrior) {
1666 largerPrior->fNext = larger->fNext;
caryclark643ede62016-08-08 14:27:45 -07001667 largerPrior->validate();
caryclark54359292015-03-26 07:52:43 -07001668 } else {
1669 fCoincident = larger->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001670 }
1671 }
caryclark54359292015-03-26 07:52:43 -07001672 } while (true);
1673}
1674
caryclark1049f122015-04-20 08:31:59 -07001675template<typename TCurve, typename OppCurve>
1676SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev(
1677 SkTSpan<TCurve, OppCurve>* span) const {
halcanary96fcdcc2015-08-27 07:41:13 -07001678 SkTSpan<TCurve, OppCurve>* result = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001679 SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001680 while (span != test) {
1681 result = test;
1682 test = test->fNext;
1683 SkASSERT(test);
caryclarkccec0f92015-03-24 07:28:17 -07001684 }
caryclark55888e42016-07-18 10:01:36 -07001685 return result;
caryclarkccec0f92015-03-24 07:28:17 -07001686}
1687
caryclark1049f122015-04-20 08:31:59 -07001688template<typename TCurve, typename OppCurve>
1689void SkTSect<TCurve, OppCurve>::recoverCollapsed() {
1690 SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001691 while (deleted) {
caryclark1049f122015-04-20 08:31:59 -07001692 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001693 if (deleted->fCollapsed) {
caryclark1049f122015-04-20 08:31:59 -07001694 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead;
caryclark45fa4472015-01-16 07:04:10 -08001695 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
1696 spanPtr = &(*spanPtr)->fNext;
1697 }
1698 deleted->fNext = *spanPtr;
1699 *spanPtr = deleted;
1700 }
1701 deleted = delNext;
1702 }
1703}
1704
caryclark1049f122015-04-20 08:31:59 -07001705template<typename TCurve, typename OppCurve>
1706void SkTSect<TCurve, OppCurve>::removeAllBut(const SkTSpan<OppCurve, TCurve>* keep,
1707 SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp) {
1708 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001709 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001710 SkTSpan<OppCurve, TCurve>* bounded = testBounded->fBounded;
1711 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001712 // may have been deleted when opp did 'remove all but'
1713 if (bounded != keep && !bounded->fDeleted) {
1714 SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
1715 if (bounded->removeBounded(span)) {
1716 opp->removeSpan(bounded);
1717 }
caryclarkccec0f92015-03-24 07:28:17 -07001718 }
caryclark54359292015-03-26 07:52:43 -07001719 testBounded = next;
caryclarkccec0f92015-03-24 07:28:17 -07001720 }
caryclark54359292015-03-26 07:52:43 -07001721 SkASSERT(!span->fDeleted);
1722 SkASSERT(span->findOppSpan(keep));
1723 SkASSERT(keep->findOppSpan(span));
caryclarkccec0f92015-03-24 07:28:17 -07001724}
1725
caryclark1049f122015-04-20 08:31:59 -07001726template<typename TCurve, typename OppCurve>
1727void SkTSect<TCurve, OppCurve>::removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp) {
1728 SkTSpan<TCurve, OppCurve>* test = fHead;
1729 SkTSpan<TCurve, OppCurve>* next;
caryclark54359292015-03-26 07:52:43 -07001730 do {
1731 next = test->fNext;
1732 if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
1733 continue;
reed0dc4dd62015-03-24 13:55:33 -07001734 }
caryclark54359292015-03-26 07:52:43 -07001735 SkDVector startV = test->fCoinStart.perpPt() - test->fPart[0];
1736 SkDVector endV = test->fCoinEnd.perpPt() - test->fPart[TCurve::kPointLast];
1737#if DEBUG_T_SECT
1738 SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUNCTION__,
1739 startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV));
1740#endif
1741 if (startV.dot(endV) <= 0) {
1742 continue;
1743 }
1744 this->removeSpans(test, opp);
1745 } while ((test = next));
1746}
1747
caryclark1049f122015-04-20 08:31:59 -07001748template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001749bool SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween) {
1750 if (!this->unlinkSpan(span)) {
1751 return false;
1752 }
caryclark54359292015-03-26 07:52:43 -07001753 if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
1754 --fActiveCount;
1755 span->fNext = fCoincident;
1756 fCoincident = span;
1757 } else {
1758 this->markSpanGone(span);
reed0dc4dd62015-03-24 13:55:33 -07001759 }
Cary Clark38702ab2017-09-05 18:11:55 -04001760 return true;
caryclarkccec0f92015-03-24 07:28:17 -07001761}
1762
caryclark1049f122015-04-20 08:31:59 -07001763template<typename TCurve, typename OppCurve>
caryclark34efb702016-10-24 08:19:06 -07001764void SkTSect<TCurve, OppCurve>::removedEndCheck(SkTSpan<TCurve, OppCurve>* span) {
caryclark6c3b9cd2016-09-26 05:36:58 -07001765 if (!span->fStartT) {
1766 fRemovedStartT = true;
1767 }
1768 if (1 == span->fEndT) {
1769 fRemovedEndT = true;
1770 }
caryclark34efb702016-10-24 08:19:06 -07001771}
1772
1773template<typename TCurve, typename OppCurve>
1774bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {\
1775 this->removedEndCheck(span);
Cary Clark38702ab2017-09-05 18:11:55 -04001776 if (!this->unlinkSpan(span)) {
1777 return false;
1778 }
caryclarkef7cee42016-09-06 09:05:54 -07001779 return this->markSpanGone(span);
caryclark54359292015-03-26 07:52:43 -07001780}
1781
caryclark1049f122015-04-20 08:31:59 -07001782template<typename TCurve, typename OppCurve>
1783void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first,
1784 SkTSpan<TCurve, OppCurve>* last) {
caryclark54359292015-03-26 07:52:43 -07001785 if (first == last) {
1786 return;
1787 }
caryclark1049f122015-04-20 08:31:59 -07001788 SkTSpan<TCurve, OppCurve>* span = first;
caryclark54359292015-03-26 07:52:43 -07001789 SkASSERT(span);
caryclark1049f122015-04-20 08:31:59 -07001790 SkTSpan<TCurve, OppCurve>* final = last->fNext;
1791 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001792 while ((span = next) && span != final) {
1793 next = span->fNext;
1794 this->markSpanGone(span);
1795 }
1796 if (final) {
1797 final->fPrev = first;
1798 }
1799 first->fNext = final;
caryclark643ede62016-08-08 14:27:45 -07001800 first->validate();
caryclark54359292015-03-26 07:52:43 -07001801}
1802
caryclark1049f122015-04-20 08:31:59 -07001803template<typename TCurve, typename OppCurve>
1804void SkTSect<TCurve, OppCurve>::removeSpans(SkTSpan<TCurve, OppCurve>* span,
1805 SkTSect<OppCurve, TCurve>* opp) {
1806 SkTSpanBounded<OppCurve, TCurve>* bounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001807 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -07001808 SkTSpan<OppCurve, TCurve>* spanBounded = bounded->fBounded;
1809 SkTSpanBounded<OppCurve, TCurve>* next = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001810 if (span->removeBounded(spanBounded)) { // shuffles last into position 0
1811 this->removeSpan(span);
1812 }
1813 if (spanBounded->removeBounded(span)) {
1814 opp->removeSpan(spanBounded);
1815 }
1816 SkASSERT(!span->fDeleted || !opp->debugHasBounded(span));
1817 bounded = next;
reed0dc4dd62015-03-24 13:55:33 -07001818 }
1819}
caryclarkccec0f92015-03-24 07:28:17 -07001820
caryclark1049f122015-04-20 08:31:59 -07001821template<typename TCurve, typename OppCurve>
1822SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::spanAtT(double t,
1823 SkTSpan<TCurve, OppCurve>** priorSpan) {
1824 SkTSpan<TCurve, OppCurve>* test = fHead;
halcanary96fcdcc2015-08-27 07:41:13 -07001825 SkTSpan<TCurve, OppCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -07001826 while (test && test->fEndT < t) {
1827 prev = test;
1828 test = test->fNext;
reed0dc4dd62015-03-24 13:55:33 -07001829 }
caryclark54359292015-03-26 07:52:43 -07001830 *priorSpan = prev;
halcanary96fcdcc2015-08-27 07:41:13 -07001831 return test && test->fStartT <= t ? test : nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001832}
1833
caryclark1049f122015-04-20 08:31:59 -07001834template<typename TCurve, typename OppCurve>
1835SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::tail() {
1836 SkTSpan<TCurve, OppCurve>* result = fHead;
1837 SkTSpan<TCurve, OppCurve>* next = fHead;
reed0dc4dd62015-03-24 13:55:33 -07001838 while ((next = next->fNext)) {
1839 if (next->fEndT > result->fEndT) {
1840 result = next;
1841 }
1842 }
1843 return result;
1844}
1845
1846/* Each span has a range of opposite spans it intersects. After the span is split in two,
1847 adjust the range to its new size */
caryclark1049f122015-04-20 08:31:59 -07001848template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -07001849bool SkTSect<TCurve, OppCurve>::trim(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001850 SkTSect<OppCurve, TCurve>* opp) {
caryclarka35ab3e2016-10-20 08:32:18 -07001851 FAIL_IF(!span->initBounds(fCurve));
caryclark1049f122015-04-20 08:31:59 -07001852 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001853 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001854 SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
1855 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001856 int oppSects, sects = this->intersects(span, opp, test, &oppSects);
1857 if (sects >= 1) {
1858 if (oppSects == 2) {
1859 test->initBounds(opp->fCurve);
1860 opp->removeAllBut(span, test, this);
1861 }
1862 if (sects == 2) {
1863 span->initBounds(fCurve);
1864 this->removeAllBut(test, span, opp);
caryclarka35ab3e2016-10-20 08:32:18 -07001865 return true;
caryclark54359292015-03-26 07:52:43 -07001866 }
reed0dc4dd62015-03-24 13:55:33 -07001867 } else {
caryclark54359292015-03-26 07:52:43 -07001868 if (span->removeBounded(test)) {
1869 this->removeSpan(span);
1870 }
1871 if (test->removeBounded(span)) {
1872 opp->removeSpan(test);
1873 }
1874 }
1875 testBounded = next;
1876 }
caryclarka35ab3e2016-10-20 08:32:18 -07001877 return true;
caryclark54359292015-03-26 07:52:43 -07001878}
1879
caryclark1049f122015-04-20 08:31:59 -07001880template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001881bool SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) {
caryclark1049f122015-04-20 08:31:59 -07001882 SkTSpan<TCurve, OppCurve>* prev = span->fPrev;
1883 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001884 if (prev) {
1885 prev->fNext = next;
1886 if (next) {
1887 next->fPrev = prev;
Cary Clark38702ab2017-09-05 18:11:55 -04001888 if (next->fStartT > next->fEndT) {
1889 return false;
1890 }
caryclark643ede62016-08-08 14:27:45 -07001891 next->validate();
caryclark54359292015-03-26 07:52:43 -07001892 }
1893 } else {
1894 fHead = next;
1895 if (next) {
halcanary96fcdcc2015-08-27 07:41:13 -07001896 next->fPrev = nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001897 }
1898 }
Cary Clark38702ab2017-09-05 18:11:55 -04001899 return true;
reed0dc4dd62015-03-24 13:55:33 -07001900}
1901
caryclark1049f122015-04-20 08:31:59 -07001902template<typename TCurve, typename OppCurve>
1903bool SkTSect<TCurve, OppCurve>::updateBounded(SkTSpan<TCurve, OppCurve>* first,
1904 SkTSpan<TCurve, OppCurve>* last, SkTSpan<OppCurve, TCurve>* oppFirst) {
1905 SkTSpan<TCurve, OppCurve>* test = first;
1906 const SkTSpan<TCurve, OppCurve>* final = last->next();
caryclark54359292015-03-26 07:52:43 -07001907 bool deleteSpan = false;
1908 do {
1909 deleteSpan |= test->removeAllBounded();
caryclarke25a4f62016-07-26 09:26:29 -07001910 } while ((test = test->fNext) != final && test);
halcanary96fcdcc2015-08-27 07:41:13 -07001911 first->fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -07001912 first->addBounded(oppFirst, &fHeap);
1913 // cannot call validate until remove span range is called
1914 return deleteSpan;
1915}
1916
1917
caryclark1049f122015-04-20 08:31:59 -07001918template<typename TCurve, typename OppCurve>
1919void SkTSect<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -07001920#if DEBUG_VALIDATE
caryclark45fa4472015-01-16 07:04:10 -08001921 int count = 0;
caryclark643ede62016-08-08 14:27:45 -07001922 double last = 0;
caryclark45fa4472015-01-16 07:04:10 -08001923 if (fHead) {
caryclark1049f122015-04-20 08:31:59 -07001924 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark45fa4472015-01-16 07:04:10 -08001925 SkASSERT(!span->fPrev);
caryclark643ede62016-08-08 14:27:45 -07001926 const SkTSpan<TCurve, OppCurve>* next;
caryclark45fa4472015-01-16 07:04:10 -08001927 do {
1928 span->validate();
1929 SkASSERT(span->fStartT >= last);
caryclark643ede62016-08-08 14:27:45 -07001930 last = span->fEndT;
caryclark45fa4472015-01-16 07:04:10 -08001931 ++count;
caryclark643ede62016-08-08 14:27:45 -07001932 next = span->fNext;
1933 SkASSERT(next != span);
1934 } while ((span = next) != nullptr);
caryclark45fa4472015-01-16 07:04:10 -08001935 }
1936 SkASSERT(count == fActiveCount);
caryclark643ede62016-08-08 14:27:45 -07001937#endif
1938#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -08001939 SkASSERT(fActiveCount <= fDebugAllocatedCount);
1940 int deletedCount = 0;
caryclark1049f122015-04-20 08:31:59 -07001941 const SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001942 while (deleted) {
1943 ++deletedCount;
1944 deleted = deleted->fNext;
1945 }
caryclark1049f122015-04-20 08:31:59 -07001946 const SkTSpan<TCurve, OppCurve>* coincident = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001947 while (coincident) {
1948 ++deletedCount;
1949 coincident = coincident->fNext;
1950 }
caryclark45fa4472015-01-16 07:04:10 -08001951 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount);
caryclarkccec0f92015-03-24 07:28:17 -07001952#endif
caryclark54359292015-03-26 07:52:43 -07001953}
1954
caryclark1049f122015-04-20 08:31:59 -07001955template<typename TCurve, typename OppCurve>
1956void SkTSect<TCurve, OppCurve>::validateBounded() const {
caryclark643ede62016-08-08 14:27:45 -07001957#if DEBUG_VALIDATE
caryclark54359292015-03-26 07:52:43 -07001958 if (!fHead) {
1959 return;
1960 }
caryclark1049f122015-04-20 08:31:59 -07001961 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark54359292015-03-26 07:52:43 -07001962 do {
1963 span->validateBounded();
halcanary96fcdcc2015-08-27 07:41:13 -07001964 } while ((span = span->fNext) != nullptr);
caryclark54359292015-03-26 07:52:43 -07001965#endif
1966}
caryclark45fa4472015-01-16 07:04:10 -08001967
caryclark1049f122015-04-20 08:31:59 -07001968template<typename TCurve, typename OppCurve>
1969int SkTSect<TCurve, OppCurve>::EndsEqual(const SkTSect<TCurve, OppCurve>* sect1,
1970 const SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark45fa4472015-01-16 07:04:10 -08001971 int zeroOneSet = 0;
caryclark54359292015-03-26 07:52:43 -07001972 if (sect1->fCurve[0] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001973 zeroOneSet |= kZeroS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001974 intersections->insert(0, 0, sect1->fCurve[0]);
1975 }
caryclark1049f122015-04-20 08:31:59 -07001976 if (sect1->fCurve[0] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001977 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark54359292015-03-26 07:52:43 -07001978 intersections->insert(0, 1, sect1->fCurve[0]);
1979 }
1980 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001981 zeroOneSet |= kOneS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001982 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
1983 }
caryclark1049f122015-04-20 08:31:59 -07001984 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001985 zeroOneSet |= kOneS1Set | kOneS2Set;
reed0dc4dd62015-03-24 13:55:33 -07001986 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07001987 }
1988 // check for zero
1989 if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set))
1990 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) {
1991 zeroOneSet |= kZeroS1Set | kZeroS2Set;
1992 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
1993 }
1994 if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
caryclark1049f122015-04-20 08:31:59 -07001995 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07001996 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark1049f122015-04-20 08:31:59 -07001997 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[OppCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07001998 }
1999 // check for one
2000 if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
2001 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[0])) {
2002 zeroOneSet |= kOneS1Set | kZeroS2Set;
2003 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], sect2->fCurve[0]);
2004 }
2005 if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
2006 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[
caryclark1049f122015-04-20 08:31:59 -07002007 OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07002008 zeroOneSet |= kOneS1Set | kOneS2Set;
2009 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
caryclark1049f122015-04-20 08:31:59 -07002010 sect2->fCurve[OppCurve::kPointLast]);
caryclark45fa4472015-01-16 07:04:10 -08002011 }
2012 return zeroOneSet;
2013}
2014
caryclark1049f122015-04-20 08:31:59 -07002015template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002016struct SkClosestRecord {
caryclark54359292015-03-26 07:52:43 -07002017 bool operator<(const SkClosestRecord& rh) const {
2018 return fClosest < rh.fClosest;
2019 }
2020
caryclark45fa4472015-01-16 07:04:10 -08002021 void addIntersection(SkIntersections* intersections) const {
2022 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT();
2023 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT();
2024 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
2025 }
2026
caryclark1049f122015-04-20 08:31:59 -07002027 void findEnd(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2,
caryclark45fa4472015-01-16 07:04:10 -08002028 int c1Index, int c2Index) {
2029 const TCurve& c1 = span1->part();
caryclark1049f122015-04-20 08:31:59 -07002030 const OppCurve& c2 = span2->part();
caryclark45fa4472015-01-16 07:04:10 -08002031 if (!c1[c1Index].approximatelyEqual(c2[c2Index])) {
2032 return;
2033 }
2034 double dist = c1[c1Index].distanceSquared(c2[c2Index]);
2035 if (fClosest < dist) {
2036 return;
2037 }
2038 fC1Span = span1;
2039 fC2Span = span2;
2040 fC1StartT = span1->startT();
2041 fC1EndT = span1->endT();
2042 fC2StartT = span2->startT();
2043 fC2EndT = span2->endT();
2044 fC1Index = c1Index;
2045 fC2Index = c2Index;
2046 fClosest = dist;
2047 }
2048
caryclarkcdeff812016-07-22 03:34:19 -07002049 bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const {
Cary Clark67116382017-01-03 16:25:18 -05002050 SkOPOBJASSERT(i, fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002051 || mate.fC1Span->endT() <= fC1Span->startT());
caryclarkcdeff812016-07-22 03:34:19 -07002052 SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002053 || mate.fC2Span->endT() <= fC2Span->startT());
2054 return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT()
2055 || fC1Span->startT() == mate.fC1Span->endT()
2056 || fC2Span == mate.fC2Span
2057 || fC2Span->endT() == mate.fC2Span->startT()
2058 || fC2Span->startT() == mate.fC2Span->endT();
2059 }
2060
2061 void merge(const SkClosestRecord& mate) {
2062 fC1Span = mate.fC1Span;
2063 fC2Span = mate.fC2Span;
2064 fClosest = mate.fClosest;
2065 fC1Index = mate.fC1Index;
2066 fC2Index = mate.fC2Index;
2067 }
caryclark55888e42016-07-18 10:01:36 -07002068
caryclark45fa4472015-01-16 07:04:10 -08002069 void reset() {
2070 fClosest = FLT_MAX;
halcanary96fcdcc2015-08-27 07:41:13 -07002071 SkDEBUGCODE(fC1Span = nullptr);
2072 SkDEBUGCODE(fC2Span = nullptr);
caryclark45fa4472015-01-16 07:04:10 -08002073 SkDEBUGCODE(fC1Index = fC2Index = -1);
2074 }
2075
2076 void update(const SkClosestRecord& mate) {
2077 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT);
2078 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT);
2079 fC2StartT = SkTMin(fC2StartT, mate.fC2StartT);
2080 fC2EndT = SkTMax(fC2EndT, mate.fC2EndT);
2081 }
2082
caryclark1049f122015-04-20 08:31:59 -07002083 const SkTSpan<TCurve, OppCurve>* fC1Span;
2084 const SkTSpan<OppCurve, TCurve>* fC2Span;
caryclark45fa4472015-01-16 07:04:10 -08002085 double fC1StartT;
2086 double fC1EndT;
2087 double fC2StartT;
2088 double fC2EndT;
2089 double fClosest;
2090 int fC1Index;
2091 int fC2Index;
2092};
2093
caryclark1049f122015-04-20 08:31:59 -07002094template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002095struct SkClosestSect {
2096 SkClosestSect()
2097 : fUsed(0) {
2098 fClosest.push_back().reset();
2099 }
2100
caryclarkcdeff812016-07-22 03:34:19 -07002101 bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2
2102 SkDEBUGPARAMS(SkIntersections* i)) {
caryclark1049f122015-04-20 08:31:59 -07002103 SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed];
caryclark45fa4472015-01-16 07:04:10 -08002104 record->findEnd(span1, span2, 0, 0);
caryclark1049f122015-04-20 08:31:59 -07002105 record->findEnd(span1, span2, 0, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002106 record->findEnd(span1, span2, TCurve::kPointLast, 0);
caryclark1049f122015-04-20 08:31:59 -07002107 record->findEnd(span1, span2, TCurve::kPointLast, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002108 if (record->fClosest == FLT_MAX) {
caryclark54359292015-03-26 07:52:43 -07002109 return false;
caryclark45fa4472015-01-16 07:04:10 -08002110 }
2111 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002112 SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index];
caryclarkcdeff812016-07-22 03:34:19 -07002113 if (test->matesWith(*record SkDEBUGPARAMS(i))) {
caryclark45fa4472015-01-16 07:04:10 -08002114 if (test->fClosest > record->fClosest) {
2115 test->merge(*record);
2116 }
2117 test->update(*record);
2118 record->reset();
caryclark54359292015-03-26 07:52:43 -07002119 return false;
caryclark45fa4472015-01-16 07:04:10 -08002120 }
2121 }
2122 ++fUsed;
2123 fClosest.push_back().reset();
caryclark54359292015-03-26 07:52:43 -07002124 return true;
caryclark45fa4472015-01-16 07:04:10 -08002125 }
2126
2127 void finish(SkIntersections* intersections) const {
caryclark1049f122015-04-20 08:31:59 -07002128 SkSTArray<TCurve::kMaxIntersections * 3,
2129 const SkClosestRecord<TCurve, OppCurve>*, true> closestPtrs;
caryclark45fa4472015-01-16 07:04:10 -08002130 for (int index = 0; index < fUsed; ++index) {
caryclark54359292015-03-26 07:52:43 -07002131 closestPtrs.push_back(&fClosest[index]);
2132 }
caryclark1049f122015-04-20 08:31:59 -07002133 SkTQSort<const SkClosestRecord<TCurve, OppCurve> >(closestPtrs.begin(), closestPtrs.end()
2134 - 1);
caryclark54359292015-03-26 07:52:43 -07002135 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002136 const SkClosestRecord<TCurve, OppCurve>* test = closestPtrs[index];
caryclark54359292015-03-26 07:52:43 -07002137 test->addIntersection(intersections);
caryclark45fa4472015-01-16 07:04:10 -08002138 }
2139 }
2140
caryclark54359292015-03-26 07:52:43 -07002141 // this is oversized so that an extra records can merge into final one
caryclark1049f122015-04-20 08:31:59 -07002142 SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve, OppCurve>, true> fClosest;
caryclark45fa4472015-01-16 07:04:10 -08002143 int fUsed;
2144};
2145
2146// returns true if the rect is too small to consider
caryclark1049f122015-04-20 08:31:59 -07002147template<typename TCurve, typename OppCurve>
2148void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
2149 SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark54359292015-03-26 07:52:43 -07002150#if DEBUG_T_SECT_DUMP > 1
2151 gDumpTSectNum = 0;
2152#endif
caryclark1049f122015-04-20 08:31:59 -07002153 SkDEBUGCODE(sect1->fOppSect = sect2);
2154 SkDEBUGCODE(sect2->fOppSect = sect1);
caryclark45fa4472015-01-16 07:04:10 -08002155 intersections->reset();
caryclarka35ab3e2016-10-20 08:32:18 -07002156 intersections->setMax(TCurve::kMaxIntersections + 4); // give extra for slop
caryclark1049f122015-04-20 08:31:59 -07002157 SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
2158 SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002159 int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
2160// SkASSERT(between(0, sect, 2));
2161 if (!sect) {
caryclark45fa4472015-01-16 07:04:10 -08002162 return;
2163 }
caryclark54359292015-03-26 07:52:43 -07002164 if (sect == 2 && oppSect == 2) {
caryclark45fa4472015-01-16 07:04:10 -08002165 (void) EndsEqual(sect1, sect2, intersections);
2166 return;
2167 }
caryclark54359292015-03-26 07:52:43 -07002168 span1->addBounded(span2, &sect1->fHeap);
2169 span2->addBounded(span1, &sect2->fHeap);
caryclark26ad22a2015-10-16 09:03:38 -07002170 const int kMaxCoinLoopCount = 8;
2171 int coinLoopCount = kMaxCoinLoopCount;
2172 double start1s SK_INIT_TO_AVOID_WARNING;
2173 double start1e SK_INIT_TO_AVOID_WARNING;
caryclark45fa4472015-01-16 07:04:10 -08002174 do {
2175 // find the largest bounds
caryclark1049f122015-04-20 08:31:59 -07002176 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002177 if (!largest1) {
2178 break;
2179 }
caryclark1049f122015-04-20 08:31:59 -07002180 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002181 // split it
caryclark1049f122015-04-20 08:31:59 -07002182 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
2183 || (!largest1->fCollapsed && largest2->fCollapsed)))) {
2184 if (largest1->fCollapsed) {
2185 break;
2186 }
caryclark34efb702016-10-24 08:19:06 -07002187 sect1->resetRemovedEnds();
2188 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002189 // trim parts that don't intersect the opposite
2190 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
caryclark643ede62016-08-08 14:27:45 -07002191 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002192 if (!half1->split(largest1, &sect1->fHeap)) {
2193 break;
2194 }
caryclarka35ab3e2016-10-20 08:32:18 -07002195 if (!sect1->trim(largest1, sect2)) {
2196 SkOPOBJASSERT(intersections, 0);
2197 return;
2198 }
2199 if (!sect1->trim(half1, sect2)) {
2200 SkOPOBJASSERT(intersections, 0);
2201 return;
2202 }
caryclark1049f122015-04-20 08:31:59 -07002203 } else {
2204 if (largest2->fCollapsed) {
2205 break;
2206 }
caryclark34efb702016-10-24 08:19:06 -07002207 sect1->resetRemovedEnds();
2208 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002209 // trim parts that don't intersect the opposite
2210 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
caryclark643ede62016-08-08 14:27:45 -07002211 SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002212 if (!half2->split(largest2, &sect2->fHeap)) {
2213 break;
2214 }
caryclarka35ab3e2016-10-20 08:32:18 -07002215 if (!sect2->trim(largest2, sect1)) {
2216 SkOPOBJASSERT(intersections, 0);
2217 return;
2218 }
2219 if (!sect2->trim(half2, sect1)) {
2220 SkOPOBJASSERT(intersections, 0);
2221 return;
2222 }
caryclark45fa4472015-01-16 07:04:10 -08002223 }
caryclark54359292015-03-26 07:52:43 -07002224 sect1->validate();
2225 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002226#if DEBUG_T_SECT_LOOP_COUNT
2227 intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop);
2228#endif
caryclark45fa4472015-01-16 07:04:10 -08002229 // if there are 9 or more continuous spans on both sects, suspect coincidence
2230 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2231 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
caryclark26ad22a2015-10-16 09:03:38 -07002232 if (coinLoopCount == kMaxCoinLoopCount) {
2233 start1s = sect1->fHead->fStartT;
2234 start1e = sect1->tail()->fEndT;
2235 }
caryclarkef7cee42016-09-06 09:05:54 -07002236 if (!sect1->coincidentCheck(sect2)) {
2237 return;
2238 }
caryclark54359292015-03-26 07:52:43 -07002239 sect1->validate();
2240 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002241#if DEBUG_T_SECT_LOOP_COUNT
2242 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop);
2243#endif
caryclarkef784fb2015-10-30 12:03:06 -07002244 if (!--coinLoopCount && sect1->fHead && sect2->fHead) {
caryclark26ad22a2015-10-16 09:03:38 -07002245 /* All known working cases resolve in two tries. Sadly, cubicConicTests[0]
2246 gets stuck in a loop. It adds an extension to allow a coincident end
2247 perpendicular to track its intersection in the opposite curve. However,
2248 the bounding box of the extension does not intersect the original curve,
caryclark55888e42016-07-18 10:01:36 -07002249 so the extension is discarded, only to be added again the next time around. */
caryclark26ad22a2015-10-16 09:03:38 -07002250 sect1->coincidentForce(sect2, start1s, start1e);
2251 sect1->validate();
2252 sect2->validate();
2253 }
caryclark45fa4472015-01-16 07:04:10 -08002254 }
caryclark54359292015-03-26 07:52:43 -07002255 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2256 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
Cary Clark59ed4822016-12-08 16:17:56 -05002257 if (!sect1->fHead) {
2258 return;
2259 }
caryclark54359292015-03-26 07:52:43 -07002260 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail());
Cary Clark59ed4822016-12-08 16:17:56 -05002261 if (!sect2->fHead) {
2262 return;
2263 }
caryclark54359292015-03-26 07:52:43 -07002264 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail());
2265 sect1->removeByPerpendicular(sect2);
2266 sect1->validate();
2267 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002268#if DEBUG_T_SECT_LOOP_COUNT
2269 intersections->debugBumpLoopCount(SkIntersections::kComputePerp_DebugLoop);
2270#endif
caryclark1049f122015-04-20 08:31:59 -07002271 if (sect1->collapsed() > TCurve::kMaxIntersections) {
2272 break;
2273 }
caryclark54359292015-03-26 07:52:43 -07002274 }
2275#if DEBUG_T_SECT_DUMP
2276 sect1->dumpBoth(sect2);
caryclark45fa4472015-01-16 07:04:10 -08002277#endif
2278 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002279 break;
caryclark45fa4472015-01-16 07:04:10 -08002280 }
2281 } while (true);
caryclark1049f122015-04-20 08:31:59 -07002282 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident;
caryclark54359292015-03-26 07:52:43 -07002283 if (coincident) {
2284 // if there is more than one coincident span, check loosely to see if they should be joined
2285 if (coincident->fNext) {
2286 sect1->mergeCoincidence(sect2);
2287 coincident = sect1->fCoincident;
2288 }
2289 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1
caryclark45fa4472015-01-16 07:04:10 -08002290 do {
caryclark221a4bb2016-10-07 11:15:15 -07002291 if (!coincident) {
2292 return;
2293 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002294 if (!coincident->fCoinStart.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002295 continue;
2296 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002297 if (!coincident->fCoinEnd.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002298 continue;
2299 }
Cary Clark67116382017-01-03 16:25:18 -05002300 double perpT = coincident->fCoinStart.perpT();
2301 if (perpT < 0) {
2302 return;
2303 }
caryclark54359292015-03-26 07:52:43 -07002304 int index = intersections->insertCoincident(coincident->fStartT,
Cary Clark67116382017-01-03 16:25:18 -05002305 perpT, coincident->fPart[0]);
caryclark54359292015-03-26 07:52:43 -07002306 if ((intersections->insertCoincident(coincident->fEndT,
2307 coincident->fCoinEnd.perpT(),
2308 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) {
caryclark45fa4472015-01-16 07:04:10 -08002309 intersections->clearCoincidence(index);
2310 }
caryclark54359292015-03-26 07:52:43 -07002311 } while ((coincident = coincident->fNext));
2312 }
caryclark1049f122015-04-20 08:31:59 -07002313 int zeroOneSet = EndsEqual(sect1, sect2, intersections);
caryclark34efb702016-10-24 08:19:06 -07002314// if (!sect1->fHead || !sect2->fHead) {
caryclark6c3b9cd2016-09-26 05:36:58 -07002315 // if the final iteration contains an end (0 or 1),
2316 if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) {
2317 SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular with opposite curve
caryclarka35ab3e2016-10-20 08:32:18 -07002318 perp.setPerp(sect1->fCurve, 0, sect1->fCurve[0], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002319 if (perp.isMatch()) {
2320 intersections->insert(0, perp.perpT(), perp.perpPt());
2321 }
2322 }
2323 if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) {
2324 SkTCoincident<TCurve, OppCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002325 perp.setPerp(sect1->fCurve, 1, sect1->fCurve[TCurve::kPointLast], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002326 if (perp.isMatch()) {
2327 intersections->insert(1, perp.perpT(), perp.perpPt());
2328 }
2329 }
2330 if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) {
2331 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002332 perp.setPerp(sect2->fCurve, 0, sect2->fCurve[0], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002333 if (perp.isMatch()) {
2334 intersections->insert(perp.perpT(), 0, perp.perpPt());
2335 }
2336 }
2337 if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) {
2338 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002339 perp.setPerp(sect2->fCurve, 1, sect2->fCurve[OppCurve::kPointLast], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002340 if (perp.isMatch()) {
2341 intersections->insert(perp.perpT(), 1, perp.perpPt());
2342 }
2343 }
caryclark34efb702016-10-24 08:19:06 -07002344// }
2345 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002346 return;
caryclark45fa4472015-01-16 07:04:10 -08002347 }
caryclark45fa4472015-01-16 07:04:10 -08002348 sect1->recoverCollapsed();
2349 sect2->recoverCollapsed();
caryclark1049f122015-04-20 08:31:59 -07002350 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002351 // check heads and tails for zero and ones and insert them if we haven't already done so
caryclark1049f122015-04-20 08:31:59 -07002352 const SkTSpan<TCurve, OppCurve>* head1 = result1;
caryclark45fa4472015-01-16 07:04:10 -08002353 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) {
2354 const SkDPoint& start1 = sect1->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002355 if (head1->isBounded()) {
2356 double t = head1->closestBoundedT(start1);
2357 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) {
2358 intersections->insert(0, t, start1);
2359 }
caryclark45fa4472015-01-16 07:04:10 -08002360 }
2361 }
caryclark1049f122015-04-20 08:31:59 -07002362 const SkTSpan<OppCurve, TCurve>* head2 = sect2->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002363 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) {
2364 const SkDPoint& start2 = sect2->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002365 if (head2->isBounded()) {
2366 double t = head2->closestBoundedT(start2);
2367 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) {
2368 intersections->insert(t, 0, start2);
2369 }
caryclark45fa4472015-01-16 07:04:10 -08002370 }
2371 }
caryclark1049f122015-04-20 08:31:59 -07002372 const SkTSpan<TCurve, OppCurve>* tail1 = sect1->tail();
caryclark45fa4472015-01-16 07:04:10 -08002373 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT)) {
2374 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002375 if (tail1->isBounded()) {
2376 double t = tail1->closestBoundedT(end1);
2377 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) {
2378 intersections->insert(1, t, end1);
2379 }
caryclark45fa4472015-01-16 07:04:10 -08002380 }
2381 }
caryclark1049f122015-04-20 08:31:59 -07002382 const SkTSpan<OppCurve, TCurve>* tail2 = sect2->tail();
caryclark45fa4472015-01-16 07:04:10 -08002383 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT)) {
caryclark1049f122015-04-20 08:31:59 -07002384 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002385 if (tail2->isBounded()) {
2386 double t = tail2->closestBoundedT(end2);
2387 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
2388 intersections->insert(t, 1, end2);
2389 }
caryclark45fa4472015-01-16 07:04:10 -08002390 }
2391 }
caryclark1049f122015-04-20 08:31:59 -07002392 SkClosestSect<TCurve, OppCurve> closest;
caryclark45fa4472015-01-16 07:04:10 -08002393 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07002394 while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) {
caryclark45fa4472015-01-16 07:04:10 -08002395 result1 = result1->fNext;
2396 }
2397 if (!result1) {
2398 break;
2399 }
caryclark1049f122015-04-20 08:31:59 -07002400 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002401 bool found = false;
caryclark45fa4472015-01-16 07:04:10 -08002402 while (result2) {
caryclarkcdeff812016-07-22 03:34:19 -07002403 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections));
caryclark45fa4472015-01-16 07:04:10 -08002404 result2 = result2->fNext;
2405 }
caryclark45fa4472015-01-16 07:04:10 -08002406 } while ((result1 = result1->fNext));
2407 closest.finish(intersections);
caryclark54359292015-03-26 07:52:43 -07002408 // if there is more than one intersection and it isn't already coincident, check
2409 int last = intersections->used() - 1;
2410 for (int index = 0; index < last; ) {
2411 if (intersections->isCoincident(index) && intersections->isCoincident(index + 1)) {
2412 ++index;
2413 continue;
2414 }
2415 double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
2416 SkDPoint midPt = sect1->fCurve.ptAtT(midT);
2417 // intersect perpendicular with opposite curve
caryclark1049f122015-04-20 08:31:59 -07002418 SkTCoincident<TCurve, OppCurve> perp;
caryclark54359292015-03-26 07:52:43 -07002419 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002420 if (!perp.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07002421 ++index;
2422 continue;
2423 }
2424 if (intersections->isCoincident(index)) {
2425 intersections->removeOne(index);
2426 --last;
2427 } else if (intersections->isCoincident(index + 1)) {
2428 intersections->removeOne(index + 1);
2429 --last;
2430 } else {
2431 intersections->setCoincident(index++);
2432 }
2433 intersections->setCoincident(index);
2434 }
caryclarka35ab3e2016-10-20 08:32:18 -07002435 SkOPOBJASSERT(intersections, intersections->used() <= TCurve::kMaxIntersections);
caryclark45fa4472015-01-16 07:04:10 -08002436}
deanm12670eb2016-04-26 14:09:01 -07002437
2438#endif