blob: 379ae34510f9cff4b57993145c6b020dc8fba57d [file] [log] [blame]
caryclark45fa4472015-01-16 07:04:10 -08001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
deanm12670eb2016-04-26 14:09:01 -07007#ifndef SkPathOpsTSect_DEFINED
8#define SkPathOpsTSect_DEFINED
caryclark45fa4472015-01-16 07:04:10 -08009
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050010#include "SkArenaAlloc.h"
Hal Canary50dbc092018-06-12 14:50:37 -040011#include "SkIntersections.h"
12#include "SkMacros.h"
caryclark54359292015-03-26 07:52:43 -070013#include "SkPathOpsBounds.h"
caryclark45fa4472015-01-16 07:04:10 -080014#include "SkPathOpsRect.h"
caryclark54359292015-03-26 07:52:43 -070015#include "SkTSort.h"
caryclark45fa4472015-01-16 07:04:10 -080016
Ben Wagnerf08d1d02018-06-18 15:11:00 -040017#include <utility>
18
caryclarked0935a2015-10-22 07:23:52 -070019#ifdef SK_DEBUG
20typedef uint8_t SkOpDebugBool;
21#else
22typedef bool SkOpDebugBool;
23#endif
24
Cary Clark0949bee2018-03-19 09:42:00 -040025static inline bool SkDoubleIsNaN(double x) {
26 return x != x;
27}
28
caryclark1049f122015-04-20 08:31:59 -070029/* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */
30template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080031class SkTCoincident {
32public:
caryclark697ac1c2015-04-13 09:36:01 -070033 SkTCoincident() {
caryclarkdf386c52015-04-21 05:27:02 -070034 this->init();
caryclark1049f122015-04-20 08:31:59 -070035 }
36
caryclarked0935a2015-10-22 07:23:52 -070037 void debugInit() {
38#ifdef SK_DEBUG
39 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
40 this->fPerpT = SK_ScalarNaN;
caryclark6c3b9cd2016-09-26 05:36:58 -070041 this->fMatch = 0xFF;
caryclarked0935a2015-10-22 07:23:52 -070042#endif
43 }
44
45 char dumpIsCoincidentStr() const;
caryclark1049f122015-04-20 08:31:59 -070046 void dump() const;
47
caryclark6c3b9cd2016-09-26 05:36:58 -070048 bool isMatch() const {
49 SkASSERT(!!fMatch == fMatch);
50 return SkToBool(fMatch);
caryclark45fa4472015-01-16 07:04:10 -080051 }
52
53 void init() {
caryclarkdf386c52015-04-21 05:27:02 -070054 fPerpT = -1;
caryclark6c3b9cd2016-09-26 05:36:58 -070055 fMatch = false;
caryclarkdf386c52015-04-21 05:27:02 -070056 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
caryclark45fa4472015-01-16 07:04:10 -080057 }
58
59 void markCoincident() {
caryclark6c3b9cd2016-09-26 05:36:58 -070060 if (!fMatch) {
caryclark45fa4472015-01-16 07:04:10 -080061 fPerpT = -1;
62 }
caryclark6c3b9cd2016-09-26 05:36:58 -070063 fMatch = true;
caryclark45fa4472015-01-16 07:04:10 -080064 }
65
66 const SkDPoint& perpPt() const {
67 return fPerpPt;
68 }
69
70 double perpT() const {
71 return fPerpT;
72 }
73
caryclark1049f122015-04-20 08:31:59 -070074 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve& );
caryclark45fa4472015-01-16 07:04:10 -080075
76private:
77 SkDPoint fPerpPt;
78 double fPerpT; // perpendicular intersection on opposite curve
caryclark6c3b9cd2016-09-26 05:36:58 -070079 SkOpDebugBool fMatch;
caryclark45fa4472015-01-16 07:04:10 -080080};
81
caryclark1049f122015-04-20 08:31:59 -070082template<typename TCurve, typename OppCurve> class SkTSect;
83template<typename TCurve, typename OppCurve> class SkTSpan;
caryclark54359292015-03-26 07:52:43 -070084
caryclark1049f122015-04-20 08:31:59 -070085template<typename TCurve, typename OppCurve>
caryclark54359292015-03-26 07:52:43 -070086struct SkTSpanBounded {
caryclark1049f122015-04-20 08:31:59 -070087 SkTSpan<TCurve, OppCurve>* fBounded;
caryclark54359292015-03-26 07:52:43 -070088 SkTSpanBounded* fNext;
89};
caryclark45fa4472015-01-16 07:04:10 -080090
91/* Curve is either TCurve or SkDCubic */
caryclark1049f122015-04-20 08:31:59 -070092template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -080093class SkTSpan {
94public:
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050095 void addBounded(SkTSpan<OppCurve, TCurve>* , SkArenaAlloc* );
reed0dc4dd62015-03-24 13:55:33 -070096 double closestBoundedT(const SkDPoint& pt) const;
caryclark54359292015-03-26 07:52:43 -070097 bool contains(double t) const;
reed0dc4dd62015-03-24 13:55:33 -070098
caryclark1049f122015-04-20 08:31:59 -070099 void debugInit() {
100 TCurve dummy;
101 dummy.debugInit();
102 init(dummy);
103 initBounds(dummy);
caryclarkdf386c52015-04-21 05:27:02 -0700104 fCoinStart.init();
105 fCoinEnd.init();
caryclark1049f122015-04-20 08:31:59 -0700106 }
107
108 const SkTSect<OppCurve, TCurve>* debugOpp() const;
caryclark643ede62016-08-08 14:27:45 -0700109
110#ifdef SK_DEBUG
111 void debugSetGlobalState(SkOpGlobalState* state) {
112 fDebugGlobalState = state;
113 }
114#endif
115
caryclark54359292015-03-26 07:52:43 -0700116 const SkTSpan* debugSpan(int ) const;
117 const SkTSpan* debugT(double t) const;
118#ifdef SK_DEBUG
119 bool debugIsBefore(const SkTSpan* span) const;
120#endif
121 void dump() const;
caryclark26ad22a2015-10-16 09:03:38 -0700122 void dumpAll() const;
caryclark1049f122015-04-20 08:31:59 -0700123 void dumpBounded(int id) const;
124 void dumpBounds() const;
125 void dumpCoin() const;
caryclark45fa4472015-01-16 07:04:10 -0800126
127 double endT() const {
128 return fEndT;
129 }
130
caryclark1049f122015-04-20 08:31:59 -0700131 SkTSpan<OppCurve, TCurve>* findOppSpan(const SkTSpan<OppCurve, TCurve>* opp) const;
caryclark54359292015-03-26 07:52:43 -0700132
caryclark1049f122015-04-20 08:31:59 -0700133 SkTSpan<OppCurve, TCurve>* findOppT(double t) const {
134 SkTSpan<OppCurve, TCurve>* result = oppT(t);
caryclark643ede62016-08-08 14:27:45 -0700135 SkOPASSERT(result);
caryclark45fa4472015-01-16 07:04:10 -0800136 return result;
137 }
138
caryclark643ede62016-08-08 14:27:45 -0700139 SkDEBUGCODE(SkOpGlobalState* globalState() const { return fDebugGlobalState; })
140
caryclark54359292015-03-26 07:52:43 -0700141 bool hasOppT(double t) const {
142 return SkToBool(oppT(t));
143 }
144
caryclark1049f122015-04-20 08:31:59 -0700145 int hullsIntersect(SkTSpan<OppCurve, TCurve>* span, bool* start, bool* oppStart);
caryclark54359292015-03-26 07:52:43 -0700146 void init(const TCurve& );
caryclarka35ab3e2016-10-20 08:32:18 -0700147 bool initBounds(const TCurve& );
caryclark54359292015-03-26 07:52:43 -0700148
149 bool isBounded() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700150 return fBounded != nullptr;
caryclark54359292015-03-26 07:52:43 -0700151 }
152
caryclark1049f122015-04-20 08:31:59 -0700153 bool linearsIntersect(SkTSpan<OppCurve, TCurve>* span);
caryclark54359292015-03-26 07:52:43 -0700154 double linearT(const SkDPoint& ) const;
155
156 void markCoincident() {
157 fCoinStart.markCoincident();
158 fCoinEnd.markCoincident();
159 }
caryclark45fa4472015-01-16 07:04:10 -0800160
161 const SkTSpan* next() const {
162 return fNext;
163 }
164
caryclark1049f122015-04-20 08:31:59 -0700165 bool onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp, bool* start,
166 bool* oppStart, bool* ptsInCommon);
caryclark54359292015-03-26 07:52:43 -0700167
caryclark45fa4472015-01-16 07:04:10 -0800168 const TCurve& part() const {
169 return fPart;
170 }
171
caryclark54359292015-03-26 07:52:43 -0700172 bool removeAllBounded();
caryclark1049f122015-04-20 08:31:59 -0700173 bool removeBounded(const SkTSpan<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700174
caryclark45fa4472015-01-16 07:04:10 -0800175 void reset() {
halcanary96fcdcc2015-08-27 07:41:13 -0700176 fBounded = nullptr;
caryclark45fa4472015-01-16 07:04:10 -0800177 }
178
caryclark54359292015-03-26 07:52:43 -0700179 void resetBounds(const TCurve& curve) {
180 fIsLinear = fIsLine = false;
181 initBounds(curve);
caryclark45fa4472015-01-16 07:04:10 -0800182 }
183
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500184 bool split(SkTSpan* work, SkArenaAlloc* heap) {
caryclark54359292015-03-26 07:52:43 -0700185 return splitAt(work, (work->fStartT + work->fEndT) * 0.5, heap);
186 }
187
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500188 bool splitAt(SkTSpan* work, double t, SkArenaAlloc* heap);
caryclark45fa4472015-01-16 07:04:10 -0800189
190 double startT() const {
191 return fStartT;
192 }
193
caryclark54359292015-03-26 07:52:43 -0700194private:
caryclark45fa4472015-01-16 07:04:10 -0800195
196 // implementation is for testing only
caryclark54359292015-03-26 07:52:43 -0700197 int debugID() const {
198 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
caryclark45fa4472015-01-16 07:04:10 -0800199 }
200
caryclark54359292015-03-26 07:52:43 -0700201 void dumpID() const;
caryclark45fa4472015-01-16 07:04:10 -0800202
caryclark1049f122015-04-20 08:31:59 -0700203 int hullCheck(const SkTSpan<OppCurve, TCurve>* opp, bool* start, bool* oppStart);
204 int linearIntersects(const OppCurve& ) const;
205 SkTSpan<OppCurve, TCurve>* oppT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800206
caryclark45fa4472015-01-16 07:04:10 -0800207 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700208 void validateBounded() const;
209 void validatePerpT(double oppT) const;
210 void validatePerpPt(double t, const SkDPoint& ) const;
caryclark45fa4472015-01-16 07:04:10 -0800211
212 TCurve fPart;
caryclark1049f122015-04-20 08:31:59 -0700213 SkTCoincident<TCurve, OppCurve> fCoinStart;
214 SkTCoincident<TCurve, OppCurve> fCoinEnd;
215 SkTSpanBounded<OppCurve, TCurve>* fBounded;
caryclark45fa4472015-01-16 07:04:10 -0800216 SkTSpan* fPrev;
217 SkTSpan* fNext;
218 SkDRect fBounds;
219 double fStartT;
220 double fEndT;
221 double fBoundsMax;
caryclarked0935a2015-10-22 07:23:52 -0700222 SkOpDebugBool fCollapsed;
223 SkOpDebugBool fHasPerp;
224 SkOpDebugBool fIsLinear;
225 SkOpDebugBool fIsLine;
226 SkOpDebugBool fDeleted;
caryclark643ede62016-08-08 14:27:45 -0700227 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700228 SkDEBUGCODE(SkTSect<TCurve, OppCurve>* fDebugSect);
caryclark54359292015-03-26 07:52:43 -0700229 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
caryclark1049f122015-04-20 08:31:59 -0700230 friend class SkTSect<TCurve, OppCurve>;
231 friend class SkTSect<OppCurve, TCurve>;
232 friend class SkTSpan<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800233};
234
caryclark1049f122015-04-20 08:31:59 -0700235template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -0800236class SkTSect {
237public:
caryclarke25a4f62016-07-26 09:26:29 -0700238 SkTSect(const TCurve& c SkDEBUGPARAMS(SkOpGlobalState* ) PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
caryclark1049f122015-04-20 08:31:59 -0700239 static void BinarySearch(SkTSect* sect1, SkTSect<OppCurve, TCurve>* sect2,
240 SkIntersections* intersections);
caryclark45fa4472015-01-16 07:04:10 -0800241
caryclarke25a4f62016-07-26 09:26:29 -0700242 SkDEBUGCODE(SkOpGlobalState* globalState() { return fDebugGlobalState; })
Cary Clark0949bee2018-03-19 09:42:00 -0400243 bool hasBounded(const SkTSpan<OppCurve, TCurve>* ) const;
caryclark54359292015-03-26 07:52:43 -0700244
caryclark1049f122015-04-20 08:31:59 -0700245 const SkTSect<OppCurve, TCurve>* debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700246 return SkDEBUGRELEASE(fOppSect, nullptr);
caryclark54359292015-03-26 07:52:43 -0700247 }
248
caryclark1049f122015-04-20 08:31:59 -0700249 const SkTSpan<TCurve, OppCurve>* debugSpan(int id) const;
250 const SkTSpan<TCurve, OppCurve>* debugT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800251 void dump() const;
caryclark1049f122015-04-20 08:31:59 -0700252 void dumpBoth(SkTSect<OppCurve, TCurve>* ) const;
253 void dumpBounded(int id) const;
254 void dumpBounds() const;
caryclark54359292015-03-26 07:52:43 -0700255 void dumpCoin() const;
256 void dumpCoinCurves() const;
caryclark45fa4472015-01-16 07:04:10 -0800257 void dumpCurves() const;
258
259private:
260 enum {
261 kZeroS1Set = 1,
262 kOneS1Set = 2,
263 kZeroS2Set = 4,
264 kOneS2Set = 8
265 };
266
caryclark1049f122015-04-20 08:31:59 -0700267 SkTSpan<TCurve, OppCurve>* addFollowing(SkTSpan<TCurve, OppCurve>* prior);
268 void addForPerp(SkTSpan<OppCurve, TCurve>* span, double t);
269 SkTSpan<TCurve, OppCurve>* addOne();
caryclark55888e42016-07-18 10:01:36 -0700270
caryclark1049f122015-04-20 08:31:59 -0700271 SkTSpan<TCurve, OppCurve>* addSplitAt(SkTSpan<TCurve, OppCurve>* span, double t) {
272 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700273 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700274 result->splitAt(span, t, &fHeap);
275 result->initBounds(fCurve);
276 span->initBounds(fCurve);
277 return result;
278 }
279
caryclark1049f122015-04-20 08:31:59 -0700280 bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
Cary Clark74b42902018-03-09 07:38:47 -0500281 double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst);
caryclark1049f122015-04-20 08:31:59 -0700282 SkTSpan<TCurve, OppCurve>* boundsMax() const;
caryclarkef7cee42016-09-06 09:05:54 -0700283 bool coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
caryclark26ad22a2015-10-16 09:03:38 -0700284 void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, double start1e);
caryclark54359292015-03-26 07:52:43 -0700285 bool coincidentHasT(double t);
caryclark1049f122015-04-20 08:31:59 -0700286 int collapsed() const;
287 void computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
288 SkTSpan<TCurve, OppCurve>* last);
289 int countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
290 SkTSpan<TCurve, OppCurve>** last) const;
caryclarkccec0f92015-03-24 07:28:17 -0700291
caryclark54359292015-03-26 07:52:43 -0700292 int debugID() const {
293 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
294 }
295
caryclarkef7cee42016-09-06 09:05:54 -0700296 bool deleteEmptySpans();
caryclark1049f122015-04-20 08:31:59 -0700297 void dumpCommon(const SkTSpan<TCurve, OppCurve>* ) const;
298 void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const;
299 static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2,
300 SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700301 bool extractCoincident(SkTSect<OppCurve, TCurve>* sect2, SkTSpan<TCurve, OppCurve>* first,
302 SkTSpan<TCurve, OppCurve>* last, SkTSpan<TCurve, OppCurve>** result);
caryclark1049f122015-04-20 08:31:59 -0700303 SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* first,
304 SkTSpan<TCurve, OppCurve>** lastPtr);
305 int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
306 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult);
caryclarked0935a2015-10-22 07:23:52 -0700307 bool isParallel(const SkDLine& thisLine, const SkTSect<OppCurve, TCurve>* opp) const;
caryclark1049f122015-04-20 08:31:59 -0700308 int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp,
309 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* );
caryclarkef7cee42016-09-06 09:05:54 -0700310 bool markSpanGone(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700311 bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2) const;
312 void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, double t2,
caryclark54359292015-03-26 07:52:43 -0700313 bool* calcMatched, bool* oppMatched) const;
caryclark1049f122015-04-20 08:31:59 -0700314 void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2);
315 SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const;
Cary Clark0949bee2018-03-19 09:42:00 -0400316 bool removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp);
caryclark54359292015-03-26 07:52:43 -0700317 void recoverCollapsed();
Cary Clark38702ab2017-09-05 18:11:55 -0400318 bool removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween);
caryclark1049f122015-04-20 08:31:59 -0700319 void removeAllBut(const SkTSpan<OppCurve, TCurve>* keep, SkTSpan<TCurve, OppCurve>* span,
320 SkTSect<OppCurve, TCurve>* opp);
caryclarkef7cee42016-09-06 09:05:54 -0700321 bool removeSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700322 void removeSpanRange(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last);
Cary Clark0949bee2018-03-19 09:42:00 -0400323 bool removeSpans(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
caryclark34efb702016-10-24 08:19:06 -0700324 void removedEndCheck(SkTSpan<TCurve, OppCurve>* span);
325
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500326 void resetRemovedEnds() {
caryclark34efb702016-10-24 08:19:06 -0700327 fRemovedStartT = fRemovedEndT = false;
328 }
329
caryclark1049f122015-04-20 08:31:59 -0700330 SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
331 SkTSpan<TCurve, OppCurve>* tail();
caryclarka35ab3e2016-10-20 08:32:18 -0700332 bool trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
Cary Clark38702ab2017-09-05 18:11:55 -0400333 bool unlinkSpan(SkTSpan<TCurve, OppCurve>* span);
caryclark1049f122015-04-20 08:31:59 -0700334 bool updateBounded(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
335 SkTSpan<OppCurve, TCurve>* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700336 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700337 void validateBounded() const;
338
caryclark45fa4472015-01-16 07:04:10 -0800339 const TCurve& fCurve;
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500340 SkArenaAlloc fHeap;
caryclark1049f122015-04-20 08:31:59 -0700341 SkTSpan<TCurve, OppCurve>* fHead;
342 SkTSpan<TCurve, OppCurve>* fCoincident;
343 SkTSpan<TCurve, OppCurve>* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800344 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700345 bool fRemovedStartT;
346 bool fRemovedEndT;
caryclarke25a4f62016-07-26 09:26:29 -0700347 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
csmartdaltonceeaa782016-08-10 10:07:57 -0700348 SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700349 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
350 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800351#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800352 int fDebugAllocatedCount;
353#endif
caryclark1049f122015-04-20 08:31:59 -0700354 friend class SkTSpan<TCurve, OppCurve>;
355 friend class SkTSpan<OppCurve, TCurve>;
356 friend class SkTSect<OppCurve, TCurve>;
caryclark45fa4472015-01-16 07:04:10 -0800357};
358
359#define COINCIDENT_SPAN_COUNT 9
360
caryclark1049f122015-04-20 08:31:59 -0700361template<typename TCurve, typename OppCurve>
362void SkTCoincident<TCurve, OppCurve>::setPerp(const TCurve& c1, double t,
363 const SkDPoint& cPt, const OppCurve& c2) {
caryclark45fa4472015-01-16 07:04:10 -0800364 SkDVector dxdy = c1.dxdyAtT(t);
365 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
caryclarka35ab3e2016-10-20 08:32:18 -0700366 SkIntersections i SkDEBUGCODE((c1.globalState()));
caryclark45fa4472015-01-16 07:04:10 -0800367 int used = i.intersectRay(c2, perp);
368 // only keep closest
caryclark54359292015-03-26 07:52:43 -0700369 if (used == 0 || used == 3) {
caryclarkdf386c52015-04-21 05:27:02 -0700370 this->init();
caryclark45fa4472015-01-16 07:04:10 -0800371 return;
caryclark55888e42016-07-18 10:01:36 -0700372 }
caryclark45fa4472015-01-16 07:04:10 -0800373 fPerpT = i[0][0];
374 fPerpPt = i.pt(0);
375 SkASSERT(used <= 2);
376 if (used == 2) {
377 double distSq = (fPerpPt - cPt).lengthSquared();
378 double dist2Sq = (i.pt(1) - cPt).lengthSquared();
379 if (dist2Sq < distSq) {
380 fPerpT = i[0][1];
381 fPerpPt = i.pt(1);
382 }
383 }
caryclark54359292015-03-26 07:52:43 -0700384#if DEBUG_T_SECT
caryclark1049f122015-04-20 08:31:59 -0700385 SkDebugf("setPerp t=%1.9g cPt=(%1.9g,%1.9g) %s oppT=%1.9g fPerpPt=(%1.9g,%1.9g)\n",
386 t, cPt.fX, cPt.fY,
387 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY);
caryclark54359292015-03-26 07:52:43 -0700388#endif
caryclark6c3b9cd2016-09-26 05:36:58 -0700389 fMatch = cPt.approximatelyEqual(fPerpPt);
caryclark45fa4472015-01-16 07:04:10 -0800390#if DEBUG_T_SECT
caryclark6c3b9cd2016-09-26 05:36:58 -0700391 if (fMatch) {
caryclark45fa4472015-01-16 07:04:10 -0800392 SkDebugf(""); // allow setting breakpoint
393 }
394#endif
395}
396
caryclark1049f122015-04-20 08:31:59 -0700397template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500398void SkTSpan<TCurve, OppCurve>::addBounded(SkTSpan<OppCurve, TCurve>* span, SkArenaAlloc* heap) {
399 SkTSpanBounded<OppCurve, TCurve>* bounded = heap->make<SkTSpanBounded<OppCurve, TCurve>>();
caryclark54359292015-03-26 07:52:43 -0700400 bounded->fBounded = span;
401 bounded->fNext = fBounded;
402 fBounded = bounded;
403}
404
caryclark1049f122015-04-20 08:31:59 -0700405template<typename TCurve, typename OppCurve>
406SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addFollowing(
407 SkTSpan<TCurve, OppCurve>* prior) {
408 SkTSpan<TCurve, OppCurve>* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700409 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700410 result->fStartT = prior ? prior->fEndT : 0;
caryclark1049f122015-04-20 08:31:59 -0700411 SkTSpan<TCurve, OppCurve>* next = prior ? prior->fNext : fHead;
caryclark54359292015-03-26 07:52:43 -0700412 result->fEndT = next ? next->fStartT : 1;
413 result->fPrev = prior;
414 result->fNext = next;
415 if (prior) {
416 prior->fNext = result;
417 } else {
418 fHead = result;
419 }
420 if (next) {
421 next->fPrev = result;
422 }
423 result->resetBounds(fCurve);
Cary Clarkb8421ed2018-03-14 15:55:02 -0400424 // world may not be consistent to call validate here
caryclark643ede62016-08-08 14:27:45 -0700425 result->validate();
caryclark54359292015-03-26 07:52:43 -0700426 return result;
427}
428
caryclark1049f122015-04-20 08:31:59 -0700429template<typename TCurve, typename OppCurve>
430void SkTSect<TCurve, OppCurve>::addForPerp(SkTSpan<OppCurve, TCurve>* span, double t) {
caryclark54359292015-03-26 07:52:43 -0700431 if (!span->hasOppT(t)) {
caryclark1049f122015-04-20 08:31:59 -0700432 SkTSpan<TCurve, OppCurve>* priorSpan;
433 SkTSpan<TCurve, OppCurve>* opp = this->spanAtT(t, &priorSpan);
caryclark54359292015-03-26 07:52:43 -0700434 if (!opp) {
435 opp = this->addFollowing(priorSpan);
436#if DEBUG_PERP
caryclark26ad22a2015-10-16 09:03:38 -0700437 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ?
438 priorSpan->debugID() : -1, t, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700439#endif
440 }
441#if DEBUG_PERP
442 opp->dump(); SkDebugf("\n");
caryclark26ad22a2015-10-16 09:03:38 -0700443 SkDebugf("%s addBounded span=%d opp=%d\n", __FUNCTION__, priorSpan ?
444 priorSpan->debugID() : -1, opp->debugID());
caryclark54359292015-03-26 07:52:43 -0700445#endif
446 opp->addBounded(span, &fHeap);
447 span->addBounded(opp, &fHeap);
448 }
449 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700450#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700451 span->validatePerpT(t);
caryclark1049f122015-04-20 08:31:59 -0700452#endif
caryclark54359292015-03-26 07:52:43 -0700453}
454
caryclark1049f122015-04-20 08:31:59 -0700455template<typename TCurve, typename OppCurve>
456double SkTSpan<TCurve, OppCurve>::closestBoundedT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700457 double result = -1;
caryclark343382e2016-06-29 08:18:38 -0700458 double closest = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -0700459 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700460 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700461 const SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700462 double startDist = test->fPart[0].distanceSquared(pt);
463 if (closest > startDist) {
464 closest = startDist;
465 result = test->fStartT;
466 }
caryclark1049f122015-04-20 08:31:59 -0700467 double endDist = test->fPart[OppCurve::kPointLast].distanceSquared(pt);
caryclark54359292015-03-26 07:52:43 -0700468 if (closest > endDist) {
469 closest = endDist;
470 result = test->fEndT;
471 }
472 testBounded = testBounded->fNext;
473 }
474 SkASSERT(between(0, result, 1));
475 return result;
476}
477
478#ifdef SK_DEBUG
caryclark1049f122015-04-20 08:31:59 -0700479template<typename TCurve, typename OppCurve>
480bool SkTSpan<TCurve, OppCurve>::debugIsBefore(const SkTSpan* span) const {
caryclark54359292015-03-26 07:52:43 -0700481 const SkTSpan* work = this;
482 do {
483 if (span == work) {
484 return true;
485 }
486 } while ((work = work->fNext));
487 return false;
488}
489#endif
490
caryclark1049f122015-04-20 08:31:59 -0700491template<typename TCurve, typename OppCurve>
492bool SkTSpan<TCurve, OppCurve>::contains(double t) const {
caryclark54359292015-03-26 07:52:43 -0700493 const SkTSpan* work = this;
494 do {
495 if (between(work->fStartT, t, work->fEndT)) {
496 return true;
497 }
498 } while ((work = work->fNext));
499 return false;
500}
501
caryclark1049f122015-04-20 08:31:59 -0700502template<typename TCurve, typename OppCurve>
503const SkTSect<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700504 return SkDEBUGRELEASE(fDebugSect->debugOpp(), nullptr);
caryclark54359292015-03-26 07:52:43 -0700505}
506
caryclark1049f122015-04-20 08:31:59 -0700507template<typename TCurve, typename OppCurve>
508SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::findOppSpan(
509 const SkTSpan<OppCurve, TCurve>* opp) const {
510 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700511 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700512 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700513 if (opp == test) {
514 return test;
515 }
516 bounded = bounded->fNext;
517 }
halcanary96fcdcc2015-08-27 07:41:13 -0700518 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700519}
520
521// returns 0 if no hull intersection
522// 1 if hulls intersect
523// 2 if hulls only share a common endpoint
524// -1 if linear and further checking is required
caryclark1049f122015-04-20 08:31:59 -0700525template<typename TCurve, typename OppCurve>
526int SkTSpan<TCurve, OppCurve>::hullCheck(const SkTSpan<OppCurve, TCurve>* opp,
527 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700528 if (fIsLinear) {
529 return -1;
530 }
531 bool ptsInCommon;
532 if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) {
533 SkASSERT(ptsInCommon);
534 return 2;
535 }
536 bool linear;
537 if (fPart.hullIntersects(opp->fPart, &linear)) {
538 if (!linear) { // check set true if linear
539 return 1;
540 }
541 fIsLinear = true;
542 fIsLine = fPart.controlsInside();
caryclark2bec26a2016-05-26 09:01:47 -0700543 return ptsInCommon ? 1 : -1;
caryclark54359292015-03-26 07:52:43 -0700544 } else { // hull is not linear; check set true if intersected at the end points
545 return ((int) ptsInCommon) << 1; // 0 or 2
546 }
547 return 0;
548}
549
550// OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
551// use line intersection to guess a better split than 0.5
552// OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all future splits are linear
caryclark1049f122015-04-20 08:31:59 -0700553template<typename TCurve, typename OppCurve>
554int SkTSpan<TCurve, OppCurve>::hullsIntersect(SkTSpan<OppCurve, TCurve>* opp,
555 bool* start, bool* oppStart) {
caryclark54359292015-03-26 07:52:43 -0700556 if (!fBounds.intersects(opp->fBounds)) {
557 return 0;
558 }
559 int hullSect = this->hullCheck(opp, start, oppStart);
560 if (hullSect >= 0) {
561 return hullSect;
562 }
563 hullSect = opp->hullCheck(this, oppStart, start);
564 if (hullSect >= 0) {
565 return hullSect;
566 }
567 return -1;
568}
569
caryclark1049f122015-04-20 08:31:59 -0700570template<typename TCurve, typename OppCurve>
571void SkTSpan<TCurve, OppCurve>::init(const TCurve& c) {
halcanary96fcdcc2015-08-27 07:41:13 -0700572 fPrev = fNext = nullptr;
reed0dc4dd62015-03-24 13:55:33 -0700573 fStartT = 0;
574 fEndT = 1;
halcanary96fcdcc2015-08-27 07:41:13 -0700575 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700576 resetBounds(c);
caryclark45fa4472015-01-16 07:04:10 -0800577}
578
caryclark1049f122015-04-20 08:31:59 -0700579template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -0700580bool SkTSpan<TCurve, OppCurve>::initBounds(const TCurve& c) {
Cary Clark0949bee2018-03-19 09:42:00 -0400581 if (SkDoubleIsNaN(fStartT) || SkDoubleIsNaN(fEndT)) {
582 return false;
583 }
reed0dc4dd62015-03-24 13:55:33 -0700584 fPart = c.subDivide(fStartT, fEndT);
585 fBounds.setBounds(fPart);
586 fCoinStart.init();
587 fCoinEnd.init();
588 fBoundsMax = SkTMax(fBounds.width(), fBounds.height());
589 fCollapsed = fPart.collapsed();
590 fHasPerp = false;
caryclark54359292015-03-26 07:52:43 -0700591 fDeleted = false;
reed0dc4dd62015-03-24 13:55:33 -0700592#if DEBUG_T_SECT
reed0dc4dd62015-03-24 13:55:33 -0700593 if (fCollapsed) {
594 SkDebugf(""); // for convenient breakpoints
caryclark45fa4472015-01-16 07:04:10 -0800595 }
596#endif
caryclarka35ab3e2016-10-20 08:32:18 -0700597 return fBounds.valid();
caryclark45fa4472015-01-16 07:04:10 -0800598}
599
caryclark1049f122015-04-20 08:31:59 -0700600template<typename TCurve, typename OppCurve>
601bool SkTSpan<TCurve, OppCurve>::linearsIntersect(SkTSpan<OppCurve, TCurve>* span) {
caryclark54359292015-03-26 07:52:43 -0700602 int result = this->linearIntersects(span->fPart);
603 if (result <= 1) {
604 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800605 }
caryclark54359292015-03-26 07:52:43 -0700606 SkASSERT(span->fIsLinear);
607 result = span->linearIntersects(this->fPart);
608// SkASSERT(result <= 1);
609 return SkToBool(result);
caryclark45fa4472015-01-16 07:04:10 -0800610}
611
caryclark1049f122015-04-20 08:31:59 -0700612template<typename TCurve, typename OppCurve>
613double SkTSpan<TCurve, OppCurve>::linearT(const SkDPoint& pt) const {
caryclark54359292015-03-26 07:52:43 -0700614 SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
615 return fabs(len.fX) > fabs(len.fY)
616 ? (pt.fX - fPart[0].fX) / len.fX
617 : (pt.fY - fPart[0].fY) / len.fY;
caryclark45fa4472015-01-16 07:04:10 -0800618}
619
caryclark1049f122015-04-20 08:31:59 -0700620template<typename TCurve, typename OppCurve>
621int SkTSpan<TCurve, OppCurve>::linearIntersects(const OppCurve& q2) const {
caryclark45fa4472015-01-16 07:04:10 -0800622 // looks like q1 is near-linear
caryclark54359292015-03-26 07:52:43 -0700623 int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
caryclark45fa4472015-01-16 07:04:10 -0800624 if (!fPart.controlsInside()) {
625 double dist = 0; // if there's any question, compute distance to find best outsiders
626 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) {
627 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) {
628 double test = (fPart[outer] - fPart[inner]).lengthSquared();
629 if (dist > test) {
630 continue;
631 }
632 dist = test;
633 start = outer;
634 end = inner;
635 }
636 }
637 }
638 // see if q2 is on one side of the line formed by the extreme points
639 double origX = fPart[start].fX;
640 double origY = fPart[start].fY;
641 double adj = fPart[end].fX - origX;
642 double opp = fPart[end].fY - origY;
caryclark54359292015-03-26 07:52:43 -0700643 double maxPart = SkTMax(fabs(adj), fabs(opp));
644 double sign = 0; // initialization to shut up warning in release build
caryclark1049f122015-04-20 08:31:59 -0700645 for (int n = 0; n < OppCurve::kPointCount; ++n) {
caryclark54359292015-03-26 07:52:43 -0700646 double dx = q2[n].fY - origY;
647 double dy = q2[n].fX - origX;
648 double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
caryclark45fa4472015-01-16 07:04:10 -0800649 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp;
caryclark54359292015-03-26 07:52:43 -0700650 if (precisely_zero_when_compared_to(test, maxVal)) {
651 return 1;
652 }
653 if (approximately_zero_when_compared_to(test, maxVal)) {
654 return 3;
caryclark45fa4472015-01-16 07:04:10 -0800655 }
656 if (n == 0) {
657 sign = test;
658 continue;
659 }
660 if (test * sign < 0) {
caryclark54359292015-03-26 07:52:43 -0700661 return 1;
caryclark45fa4472015-01-16 07:04:10 -0800662 }
663 }
caryclark54359292015-03-26 07:52:43 -0700664 return 0;
665}
666
caryclark1049f122015-04-20 08:31:59 -0700667template<typename TCurve, typename OppCurve>
668bool SkTSpan<TCurve, OppCurve>::onlyEndPointsInCommon(const SkTSpan<OppCurve, TCurve>* opp,
669 bool* start, bool* oppStart, bool* ptsInCommon) {
caryclark54359292015-03-26 07:52:43 -0700670 if (opp->fPart[0] == fPart[0]) {
671 *start = *oppStart = true;
672 } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
673 *start = false;
674 *oppStart = true;
caryclark1049f122015-04-20 08:31:59 -0700675 } else if (opp->fPart[OppCurve::kPointLast] == fPart[0]) {
caryclark54359292015-03-26 07:52:43 -0700676 *start = true;
677 *oppStart = false;
caryclark1049f122015-04-20 08:31:59 -0700678 } else if (opp->fPart[OppCurve::kPointLast] == fPart[TCurve::kPointLast]) {
caryclark54359292015-03-26 07:52:43 -0700679 *start = *oppStart = false;
680 } else {
681 *ptsInCommon = false;
682 return false;
683 }
684 *ptsInCommon = true;
caryclark1049f122015-04-20 08:31:59 -0700685 const SkDPoint* otherPts[TCurve::kPointCount - 1], * oppOtherPts[OppCurve::kPointCount - 1];
caryclark54359292015-03-26 07:52:43 -0700686 int baseIndex = *start ? 0 : TCurve::kPointLast;
caryclark1049f122015-04-20 08:31:59 -0700687 fPart.otherPts(baseIndex, otherPts);
688 opp->fPart.otherPts(*oppStart ? 0 : OppCurve::kPointLast, oppOtherPts);
caryclark54359292015-03-26 07:52:43 -0700689 const SkDPoint& base = fPart[baseIndex];
caryclark1049f122015-04-20 08:31:59 -0700690 for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(otherPts); ++o1) {
691 SkDVector v1 = *otherPts[o1] - base;
692 for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(oppOtherPts); ++o2) {
693 SkDVector v2 = *oppOtherPts[o2] - base;
caryclark54359292015-03-26 07:52:43 -0700694 if (v2.dot(v1) >= 0) {
695 return false;
696 }
697 }
698 }
699 return true;
700}
701
caryclark1049f122015-04-20 08:31:59 -0700702template<typename TCurve, typename OppCurve>
703SkTSpan<OppCurve, TCurve>* SkTSpan<TCurve, OppCurve>::oppT(double t) const {
704 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700705 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700706 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700707 if (between(test->fStartT, t, test->fEndT)) {
708 return test;
709 }
710 bounded = bounded->fNext;
711 }
halcanary96fcdcc2015-08-27 07:41:13 -0700712 return nullptr;
caryclark54359292015-03-26 07:52:43 -0700713}
714
caryclark1049f122015-04-20 08:31:59 -0700715template<typename TCurve, typename OppCurve>
716bool SkTSpan<TCurve, OppCurve>::removeAllBounded() {
caryclark54359292015-03-26 07:52:43 -0700717 bool deleteSpan = false;
caryclark1049f122015-04-20 08:31:59 -0700718 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700719 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700720 SkTSpan<OppCurve, TCurve>* opp = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700721 deleteSpan |= opp->removeBounded(this);
722 bounded = bounded->fNext;
723 }
724 return deleteSpan;
725}
726
caryclark1049f122015-04-20 08:31:59 -0700727template<typename TCurve, typename OppCurve>
728bool SkTSpan<TCurve, OppCurve>::removeBounded(const SkTSpan<OppCurve, TCurve>* opp) {
caryclark54359292015-03-26 07:52:43 -0700729 if (fHasPerp) {
730 bool foundStart = false;
731 bool foundEnd = false;
caryclark1049f122015-04-20 08:31:59 -0700732 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700733 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700734 SkTSpan<OppCurve, TCurve>* test = bounded->fBounded;
caryclark54359292015-03-26 07:52:43 -0700735 if (opp != test) {
736 foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT);
737 foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
738 }
739 bounded = bounded->fNext;
740 }
741 if (!foundStart || !foundEnd) {
742 fHasPerp = false;
743 fCoinStart.init();
744 fCoinEnd.init();
745 }
746 }
caryclark1049f122015-04-20 08:31:59 -0700747 SkTSpanBounded<OppCurve, TCurve>* bounded = fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700748 SkTSpanBounded<OppCurve, TCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -0700749 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -0700750 SkTSpanBounded<OppCurve, TCurve>* boundedNext = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -0700751 if (opp == bounded->fBounded) {
752 if (prev) {
753 prev->fNext = boundedNext;
754 return false;
755 } else {
756 fBounded = boundedNext;
halcanary96fcdcc2015-08-27 07:41:13 -0700757 return fBounded == nullptr;
caryclark54359292015-03-26 07:52:43 -0700758 }
759 }
760 prev = bounded;
761 bounded = boundedNext;
762 }
caryclark643ede62016-08-08 14:27:45 -0700763 SkOPASSERT(0);
caryclark45fa4472015-01-16 07:04:10 -0800764 return false;
765}
766
caryclark1049f122015-04-20 08:31:59 -0700767template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500768bool SkTSpan<TCurve, OppCurve>::splitAt(SkTSpan* work, double t, SkArenaAlloc* heap) {
caryclark45fa4472015-01-16 07:04:10 -0800769 fStartT = t;
770 fEndT = work->fEndT;
771 if (fStartT == fEndT) {
772 fCollapsed = true;
773 return false;
774 }
775 work->fEndT = t;
776 if (work->fStartT == work->fEndT) {
777 work->fCollapsed = true;
778 return false;
779 }
780 fPrev = work;
781 fNext = work->fNext;
782 fIsLinear = work->fIsLinear;
caryclark54359292015-03-26 07:52:43 -0700783 fIsLine = work->fIsLine;
784
caryclark45fa4472015-01-16 07:04:10 -0800785 work->fNext = this;
786 if (fNext) {
787 fNext->fPrev = this;
788 }
caryclark643ede62016-08-08 14:27:45 -0700789 this->validate();
caryclark1049f122015-04-20 08:31:59 -0700790 SkTSpanBounded<OppCurve, TCurve>* bounded = work->fBounded;
halcanary96fcdcc2015-08-27 07:41:13 -0700791 fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -0700792 while (bounded) {
793 this->addBounded(bounded->fBounded, heap);
794 bounded = bounded->fNext;
795 }
796 bounded = fBounded;
797 while (bounded) {
798 bounded->fBounded->addBounded(this, heap);
799 bounded = bounded->fNext;
caryclark45fa4472015-01-16 07:04:10 -0800800 }
801 return true;
802}
803
caryclark1049f122015-04-20 08:31:59 -0700804template<typename TCurve, typename OppCurve>
805void SkTSpan<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -0700806#if DEBUG_VALIDATE
807 SkASSERT(this != fPrev);
808 SkASSERT(this != fNext);
halcanary96fcdcc2015-08-27 07:41:13 -0700809 SkASSERT(fNext == nullptr || fNext != fPrev);
810 SkASSERT(fNext == nullptr || this == fNext->fPrev);
811 SkASSERT(fPrev == nullptr || this == fPrev->fNext);
caryclark643ede62016-08-08 14:27:45 -0700812 this->validateBounded();
813#endif
814#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700815 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed);
caryclarke839e782016-09-15 07:48:18 -0700816 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()) || fCollapsed == 0xFF);
caryclark45fa4472015-01-16 07:04:10 -0800817 SkASSERT(0 <= fStartT);
818 SkASSERT(fEndT <= 1);
caryclark54359292015-03-26 07:52:43 -0700819 SkASSERT(fStartT <= fEndT);
caryclarke839e782016-09-15 07:48:18 -0700820 SkASSERT(fBounded || fCollapsed == 0xFF);
caryclark54359292015-03-26 07:52:43 -0700821 if (fHasPerp) {
caryclark6c3b9cd2016-09-26 05:36:58 -0700822 if (fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700823 validatePerpT(fCoinStart.perpT());
824 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt());
825 }
caryclark6c3b9cd2016-09-26 05:36:58 -0700826 if (fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700827 validatePerpT(fCoinEnd.perpT());
828 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt());
829 }
caryclarkccec0f92015-03-24 07:28:17 -0700830 }
reed0dc4dd62015-03-24 13:55:33 -0700831#endif
caryclark54359292015-03-26 07:52:43 -0700832}
caryclarkccec0f92015-03-24 07:28:17 -0700833
caryclark1049f122015-04-20 08:31:59 -0700834template<typename TCurve, typename OppCurve>
835void SkTSpan<TCurve, OppCurve>::validateBounded() const {
caryclark54359292015-03-26 07:52:43 -0700836#if DEBUG_VALIDATE
caryclark1049f122015-04-20 08:31:59 -0700837 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700838 while (testBounded) {
csmartdaltonceeaa782016-08-10 10:07:57 -0700839 SkDEBUGCODE(const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded);
caryclark54359292015-03-26 07:52:43 -0700840 SkASSERT(!overlap->fDeleted);
caryclark643ede62016-08-08 14:27:45 -0700841#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -0700842 SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
843 SkASSERT(overlap->findOppSpan(this));
caryclark643ede62016-08-08 14:27:45 -0700844#endif
caryclark54359292015-03-26 07:52:43 -0700845 testBounded = testBounded->fNext;
846 }
847#endif
848}
849
caryclark1049f122015-04-20 08:31:59 -0700850template<typename TCurve, typename OppCurve>
851void SkTSpan<TCurve, OppCurve>::validatePerpT(double oppT) const {
852 const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
caryclark54359292015-03-26 07:52:43 -0700853 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -0700854 const SkTSpan<OppCurve, TCurve>* overlap = testBounded->fBounded;
caryclark26ad22a2015-10-16 09:03:38 -0700855 if (precisely_between(overlap->fStartT, oppT, overlap->fEndT)) {
caryclark54359292015-03-26 07:52:43 -0700856 return;
857 }
858 testBounded = testBounded->fNext;
859 }
860 SkASSERT(0);
caryclark54359292015-03-26 07:52:43 -0700861}
862
caryclark1049f122015-04-20 08:31:59 -0700863template<typename TCurve, typename OppCurve>
864void SkTSpan<TCurve, OppCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
865 SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt);
caryclark54359292015-03-26 07:52:43 -0700866}
867
868
caryclark1049f122015-04-20 08:31:59 -0700869template<typename TCurve, typename OppCurve>
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500870SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
caryclarke25a4f62016-07-26 09:26:29 -0700871 SkDEBUGPARAMS(SkOpGlobalState* debugGlobalState)
872 PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
caryclark45fa4472015-01-16 07:04:10 -0800873 : fCurve(c)
caryclark1049f122015-04-20 08:31:59 -0700874 , fHeap(sizeof(SkTSpan<TCurve, OppCurve>) * 4)
halcanary96fcdcc2015-08-27 07:41:13 -0700875 , fCoincident(nullptr)
876 , fDeleted(nullptr)
caryclark45fa4472015-01-16 07:04:10 -0800877 , fActiveCount(0)
caryclarke25a4f62016-07-26 09:26:29 -0700878 SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState))
caryclark54359292015-03-26 07:52:43 -0700879 PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
880 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
881 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
caryclark45fa4472015-01-16 07:04:10 -0800882{
caryclark34efb702016-10-24 08:19:06 -0700883 this->resetRemovedEnds();
884 fHead = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700885 SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState));
caryclark45fa4472015-01-16 07:04:10 -0800886 fHead->init(c);
887}
888
caryclark1049f122015-04-20 08:31:59 -0700889template<typename TCurve, typename OppCurve>
890SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
891 SkTSpan<TCurve, OppCurve>* result;
caryclark45fa4472015-01-16 07:04:10 -0800892 if (fDeleted) {
893 result = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800894 fDeleted = result->fNext;
895 } else {
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500896 result = fHeap.make<SkTSpan<TCurve, OppCurve>>();
caryclark45fa4472015-01-16 07:04:10 -0800897#if DEBUG_T_SECT
898 ++fDebugAllocatedCount;
899#endif
900 }
caryclarked0935a2015-10-22 07:23:52 -0700901 result->reset();
caryclark08b32492015-04-06 11:41:29 -0700902 result->fHasPerp = false;
903 result->fDeleted = false;
caryclark55888e42016-07-18 10:01:36 -0700904 ++fActiveCount;
caryclark54359292015-03-26 07:52:43 -0700905 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
caryclark1049f122015-04-20 08:31:59 -0700906 SkDEBUGCODE(result->fDebugSect = this);
caryclarked0935a2015-10-22 07:23:52 -0700907#ifdef SK_DEBUG
908 result->fPart.debugInit();
909 result->fCoinStart.debugInit();
910 result->fCoinEnd.debugInit();
911 result->fPrev = result->fNext = nullptr;
912 result->fBounds.debugInit();
913 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN;
914 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF;
915#endif
caryclark45fa4472015-01-16 07:04:10 -0800916 return result;
917}
918
caryclark1049f122015-04-20 08:31:59 -0700919template<typename TCurve, typename OppCurve>
920bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
Cary Clark74b42902018-03-09 07:38:47 -0500921 double tStep, double* resultT, double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst) {
caryclark1049f122015-04-20 08:31:59 -0700922 SkTSpan<TCurve, OppCurve> work;
caryclark45fa4472015-01-16 07:04:10 -0800923 double result = work.fStartT = work.fEndT = tStart;
caryclark1049f122015-04-20 08:31:59 -0700924 SkDEBUGCODE(work.fDebugSect = this);
caryclark45fa4472015-01-16 07:04:10 -0800925 SkDPoint last = fCurve.ptAtT(tStart);
926 SkDPoint oppPt;
927 bool flip = false;
caryclarkcdeff812016-07-22 03:34:19 -0700928 bool contained = false;
Cary Clark74b42902018-03-09 07:38:47 -0500929 bool down = tStep < 0;
caryclark1049f122015-04-20 08:31:59 -0700930 const OppCurve& opp = sect2->fCurve;
caryclark45fa4472015-01-16 07:04:10 -0800931 do {
932 tStep *= 0.5;
933 work.fStartT += tStep;
934 if (flip) {
935 tStep = -tStep;
936 flip = false;
937 }
938 work.initBounds(fCurve);
939 if (work.fCollapsed) {
940 return false;
941 }
942 if (last.approximatelyEqual(work.fPart[0])) {
943 break;
944 }
945 last = work.fPart[0];
946 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp);
caryclark6c3b9cd2016-09-26 05:36:58 -0700947 if (work.fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -0700948#if DEBUG_T_SECT
949 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt());
950#endif
caryclark45fa4472015-01-16 07:04:10 -0800951 double oppTTest = work.fCoinStart.perpT();
caryclark54359292015-03-26 07:52:43 -0700952 if (sect2->fHead->contains(oppTTest)) {
caryclark45fa4472015-01-16 07:04:10 -0800953 *oppT = oppTTest;
954 oppPt = work.fCoinStart.perpPt();
caryclarkcdeff812016-07-22 03:34:19 -0700955 contained = true;
Cary Clark74b42902018-03-09 07:38:47 -0500956 if (down ? result <= work.fStartT : result >= work.fStartT) {
957 *oppFirst = nullptr; // signal caller to fail
958 return false;
959 }
caryclark45fa4472015-01-16 07:04:10 -0800960 result = work.fStartT;
961 continue;
962 }
963 }
964 tStep = -tStep;
965 flip = true;
966 } while (true);
caryclarkcdeff812016-07-22 03:34:19 -0700967 if (!contained) {
968 return false;
969 }
caryclark45fa4472015-01-16 07:04:10 -0800970 if (last.approximatelyEqual(fCurve[0])) {
971 result = 0;
972 } else if (last.approximatelyEqual(fCurve[TCurve::kPointLast])) {
973 result = 1;
974 }
975 if (oppPt.approximatelyEqual(opp[0])) {
976 *oppT = 0;
caryclark1049f122015-04-20 08:31:59 -0700977 } else if (oppPt.approximatelyEqual(opp[OppCurve::kPointLast])) {
caryclark45fa4472015-01-16 07:04:10 -0800978 *oppT = 1;
979 }
980 *resultT = result;
981 return true;
982}
983
984// OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
985// so that each quad sect has a pointer to the largest, and can update it as spans
986// are split
caryclark1049f122015-04-20 08:31:59 -0700987template<typename TCurve, typename OppCurve>
988SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
989 SkTSpan<TCurve, OppCurve>* test = fHead;
990 SkTSpan<TCurve, OppCurve>* largest = fHead;
caryclark54359292015-03-26 07:52:43 -0700991 bool lCollapsed = largest->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800992 while ((test = test->fNext)) {
caryclark54359292015-03-26 07:52:43 -0700993 bool tCollapsed = test->fCollapsed;
994 if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
995 largest->fBoundsMax < test->fBoundsMax)) {
caryclark45fa4472015-01-16 07:04:10 -0800996 largest = test;
caryclark1049f122015-04-20 08:31:59 -0700997 lCollapsed = test->fCollapsed;
caryclark45fa4472015-01-16 07:04:10 -0800998 }
999 }
caryclark54359292015-03-26 07:52:43 -07001000 return largest;
caryclark45fa4472015-01-16 07:04:10 -08001001}
1002
caryclark1049f122015-04-20 08:31:59 -07001003template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001004bool SkTSect<TCurve, OppCurve>::coincidentCheck(SkTSect<OppCurve, TCurve>* sect2) {
caryclark1049f122015-04-20 08:31:59 -07001005 SkTSpan<TCurve, OppCurve>* first = fHead;
caryclark9feb6322016-10-25 08:58:26 -07001006 if (!first) {
1007 return false;
1008 }
caryclark1049f122015-04-20 08:31:59 -07001009 SkTSpan<TCurve, OppCurve>* last, * next;
caryclark45fa4472015-01-16 07:04:10 -08001010 do {
caryclark54359292015-03-26 07:52:43 -07001011 int consecutive = this->countConsecutiveSpans(first, &last);
1012 next = last->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001013 if (consecutive < COINCIDENT_SPAN_COUNT) {
1014 continue;
1015 }
caryclark54359292015-03-26 07:52:43 -07001016 this->validate();
1017 sect2->validate();
1018 this->computePerpendiculars(sect2, first, last);
1019 this->validate();
1020 sect2->validate();
caryclark45fa4472015-01-16 07:04:10 -08001021 // check to see if a range of points are on the curve
caryclark1049f122015-04-20 08:31:59 -07001022 SkTSpan<TCurve, OppCurve>* coinStart = first;
caryclark54359292015-03-26 07:52:43 -07001023 do {
caryclarkef7cee42016-09-06 09:05:54 -07001024 bool success = this->extractCoincident(sect2, coinStart, last, &coinStart);
1025 if (!success) {
1026 return false;
1027 }
caryclark54359292015-03-26 07:52:43 -07001028 } while (coinStart && !last->fDeleted);
caryclark55888e42016-07-18 10:01:36 -07001029 if (!fHead || !sect2->fHead) {
1030 break;
1031 }
caryclark643ede62016-08-08 14:27:45 -07001032 if (!next || next->fDeleted) {
1033 break;
1034 }
caryclark45fa4472015-01-16 07:04:10 -08001035 } while ((first = next));
caryclarkef7cee42016-09-06 09:05:54 -07001036 return true;
caryclark45fa4472015-01-16 07:04:10 -08001037}
1038
caryclark1049f122015-04-20 08:31:59 -07001039template<typename TCurve, typename OppCurve>
caryclark26ad22a2015-10-16 09:03:38 -07001040void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2,
1041 double start1s, double start1e) {
1042 SkTSpan<TCurve, OppCurve>* first = fHead;
1043 SkTSpan<TCurve, OppCurve>* last = this->tail();
1044 SkTSpan<OppCurve, TCurve>* oppFirst = sect2->fHead;
1045 SkTSpan<OppCurve, TCurve>* oppLast = sect2->tail();
1046 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1047 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
1048 this->removeSpanRange(first, last);
1049 sect2->removeSpanRange(oppFirst, oppLast);
1050 first->fStartT = start1s;
1051 first->fEndT = start1e;
1052 first->resetBounds(fCurve);
1053 first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve);
1054 first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->fCurve);
1055 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
caryclarkef784fb2015-10-30 12:03:06 -07001056 double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : SkTMax(0., first->fCoinStart.perpT());
1057 double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : SkTMin(1., first->fCoinEnd.perpT());
caryclark26ad22a2015-10-16 09:03:38 -07001058 if (!oppMatched) {
Ben Wagnerf08d1d02018-06-18 15:11:00 -04001059 using std::swap;
1060 swap(oppStartT, oppEndT);
caryclark26ad22a2015-10-16 09:03:38 -07001061 }
1062 oppFirst->fStartT = oppStartT;
1063 oppFirst->fEndT = oppEndT;
1064 oppFirst->resetBounds(sect2->fCurve);
1065 this->removeCoincident(first, false);
1066 sect2->removeCoincident(oppFirst, true);
1067 if (deleteEmptySpans) {
1068 this->deleteEmptySpans();
1069 sect2->deleteEmptySpans();
1070 }
1071}
1072
1073template<typename TCurve, typename OppCurve>
caryclark1049f122015-04-20 08:31:59 -07001074bool SkTSect<TCurve, OppCurve>::coincidentHasT(double t) {
1075 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001076 while (test) {
1077 if (between(test->fStartT, t, test->fEndT)) {
1078 return true;
1079 }
1080 test = test->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001081 }
caryclark54359292015-03-26 07:52:43 -07001082 return false;
caryclark45fa4472015-01-16 07:04:10 -08001083}
1084
caryclark1049f122015-04-20 08:31:59 -07001085template<typename TCurve, typename OppCurve>
1086int SkTSect<TCurve, OppCurve>::collapsed() const {
1087 int result = 0;
1088 const SkTSpan<TCurve, OppCurve>* test = fHead;
1089 while (test) {
1090 if (test->fCollapsed) {
1091 ++result;
1092 }
1093 test = test->next();
1094 }
1095 return result;
1096}
1097
1098template<typename TCurve, typename OppCurve>
1099void SkTSect<TCurve, OppCurve>::computePerpendiculars(SkTSect<OppCurve, TCurve>* sect2,
1100 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last) {
1101 const OppCurve& opp = sect2->fCurve;
1102 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001103 SkTSpan<TCurve, OppCurve>* prior = nullptr;
caryclark45fa4472015-01-16 07:04:10 -08001104 do {
caryclark54359292015-03-26 07:52:43 -07001105 if (!work->fHasPerp && !work->fCollapsed) {
1106 if (prior) {
1107 work->fCoinStart = prior->fCoinEnd;
1108 } else {
1109 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp);
caryclark45fa4472015-01-16 07:04:10 -08001110 }
caryclark6c3b9cd2016-09-26 05:36:58 -07001111 if (work->fCoinStart.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001112 double perpT = work->fCoinStart.perpT();
1113 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001114 work->fCoinStart.init();
caryclark54359292015-03-26 07:52:43 -07001115 } else {
1116 sect2->addForPerp(work, perpT);
1117 }
1118 }
1119 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPointLast], opp);
caryclark6c3b9cd2016-09-26 05:36:58 -07001120 if (work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001121 double perpT = work->fCoinEnd.perpT();
1122 if (sect2->coincidentHasT(perpT)) {
caryclarkdf386c52015-04-21 05:27:02 -07001123 work->fCoinEnd.init();
caryclark54359292015-03-26 07:52:43 -07001124 } else {
1125 sect2->addForPerp(work, perpT);
1126 }
1127 }
1128 work->fHasPerp = true;
caryclark45fa4472015-01-16 07:04:10 -08001129 }
1130 if (work == last) {
1131 break;
1132 }
caryclark54359292015-03-26 07:52:43 -07001133 prior = work;
caryclark45fa4472015-01-16 07:04:10 -08001134 work = work->fNext;
1135 SkASSERT(work);
1136 } while (true);
caryclark54359292015-03-26 07:52:43 -07001137}
1138
caryclark1049f122015-04-20 08:31:59 -07001139template<typename TCurve, typename OppCurve>
1140int SkTSect<TCurve, OppCurve>::countConsecutiveSpans(SkTSpan<TCurve, OppCurve>* first,
1141 SkTSpan<TCurve, OppCurve>** lastPtr) const {
caryclark54359292015-03-26 07:52:43 -07001142 int consecutive = 1;
caryclark1049f122015-04-20 08:31:59 -07001143 SkTSpan<TCurve, OppCurve>* last = first;
caryclark54359292015-03-26 07:52:43 -07001144 do {
caryclark1049f122015-04-20 08:31:59 -07001145 SkTSpan<TCurve, OppCurve>* next = last->fNext;
caryclark54359292015-03-26 07:52:43 -07001146 if (!next) {
1147 break;
1148 }
1149 if (next->fStartT > last->fEndT) {
1150 break;
1151 }
1152 ++consecutive;
1153 last = next;
1154 } while (true);
1155 *lastPtr = last;
1156 return consecutive;
1157}
1158
caryclark1049f122015-04-20 08:31:59 -07001159template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001160bool SkTSect<TCurve, OppCurve>::hasBounded(const SkTSpan<OppCurve, TCurve>* span) const {
caryclark1049f122015-04-20 08:31:59 -07001161 const SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001162 if (!test) {
1163 return false;
1164 }
1165 do {
1166 if (test->findOppSpan(span)) {
1167 return true;
1168 }
1169 } while ((test = test->next()));
1170 return false;
1171}
1172
caryclark1049f122015-04-20 08:31:59 -07001173template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001174bool SkTSect<TCurve, OppCurve>::deleteEmptySpans() {
caryclark1049f122015-04-20 08:31:59 -07001175 SkTSpan<TCurve, OppCurve>* test;
1176 SkTSpan<TCurve, OppCurve>* next = fHead;
Cary Clark59ed4822016-12-08 16:17:56 -05001177 int safetyHatch = 1000;
caryclark54359292015-03-26 07:52:43 -07001178 while ((test = next)) {
1179 next = test->fNext;
1180 if (!test->fBounded) {
caryclarkef7cee42016-09-06 09:05:54 -07001181 if (!this->removeSpan(test)) {
1182 return false;
1183 }
caryclark54359292015-03-26 07:52:43 -07001184 }
Cary Clark59ed4822016-12-08 16:17:56 -05001185 if (--safetyHatch < 0) {
1186 return false;
1187 }
caryclark54359292015-03-26 07:52:43 -07001188 }
caryclarkef7cee42016-09-06 09:05:54 -07001189 return true;
caryclark54359292015-03-26 07:52:43 -07001190}
1191
caryclark1049f122015-04-20 08:31:59 -07001192template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001193bool SkTSect<TCurve, OppCurve>::extractCoincident(
caryclark1049f122015-04-20 08:31:59 -07001194 SkTSect<OppCurve, TCurve>* sect2,
caryclarkef7cee42016-09-06 09:05:54 -07001195 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last,
1196 SkTSpan<TCurve, OppCurve>** result) {
caryclark1049f122015-04-20 08:31:59 -07001197 first = findCoincidentRun(first, &last);
caryclarka1b42d92016-08-16 10:25:29 -07001198 if (!first || !last) {
caryclarkef7cee42016-09-06 09:05:54 -07001199 *result = nullptr;
1200 return true;
caryclark45fa4472015-01-16 07:04:10 -08001201 }
1202 // march outwards to find limit of coincidence from here to previous and next spans
1203 double startT = first->fStartT;
caryclarkd8bc16b2015-03-26 09:05:12 -07001204 double oppStartT SK_INIT_TO_AVOID_WARNING;
caryclark54359292015-03-26 07:52:43 -07001205 double oppEndT SK_INIT_TO_AVOID_WARNING;
caryclark1049f122015-04-20 08:31:59 -07001206 SkTSpan<TCurve, OppCurve>* prev = first->fPrev;
caryclark6c3b9cd2016-09-26 05:36:58 -07001207 SkASSERT(first->fCoinStart.isMatch());
caryclark1049f122015-04-20 08:31:59 -07001208 SkTSpan<OppCurve, TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
caryclark6c3b9cd2016-09-26 05:36:58 -07001209 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001210 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
1211 double coinStart;
1212 SkDEBUGCODE(double coinEnd);
caryclark1049f122015-04-20 08:31:59 -07001213 SkTSpan<OppCurve, TCurve>* cutFirst;
caryclark54359292015-03-26 07:52:43 -07001214 if (prev && prev->fEndT == startT
1215 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
Cary Clark74b42902018-03-09 07:38:47 -05001216 &oppStartT, &oppFirst)
caryclark1049f122015-04-20 08:31:59 -07001217 && prev->fStartT < coinStart && coinStart < startT
1218 && (cutFirst = prev->oppT(oppStartT))) {
1219 oppFirst = cutFirst;
caryclark54359292015-03-26 07:52:43 -07001220 first = this->addSplitAt(prev, coinStart);
1221 first->markCoincident();
1222 prev->fCoinEnd.markCoincident();
1223 if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
caryclark1049f122015-04-20 08:31:59 -07001224 SkTSpan<OppCurve, TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
caryclark54359292015-03-26 07:52:43 -07001225 if (oppMatched) {
1226 oppFirst->fCoinEnd.markCoincident();
1227 oppHalf->markCoincident();
1228 oppFirst = oppHalf;
1229 } else {
1230 oppFirst->markCoincident();
1231 oppHalf->fCoinStart.markCoincident();
1232 }
1233 }
1234 } else {
Cary Clark74b42902018-03-09 07:38:47 -05001235 if (!oppFirst) {
1236 return false;
1237 }
caryclark54359292015-03-26 07:52:43 -07001238 SkDEBUGCODE(coinStart = first->fStartT);
1239 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
1240 }
caryclark1049f122015-04-20 08:31:59 -07001241 // FIXME: incomplete : if we're not at the end, find end of coin
1242 SkTSpan<OppCurve, TCurve>* oppLast;
caryclark6c3b9cd2016-09-26 05:36:58 -07001243 SkOPASSERT(last->fCoinEnd.isMatch());
caryclark54359292015-03-26 07:52:43 -07001244 oppLast = last->findOppT(last->fCoinEnd.perpT());
1245 SkDEBUGCODE(coinEnd = last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001246#ifdef SK_DEBUG
1247 if (!this->globalState() || !this->globalState()->debugSkipAssert()) {
1248 oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT;
1249 }
1250#endif
caryclark54359292015-03-26 07:52:43 -07001251 if (!oppMatched) {
Ben Wagnerf08d1d02018-06-18 15:11:00 -04001252 using std::swap;
1253 swap(oppFirst, oppLast);
1254 swap(oppStartT, oppEndT);
caryclark54359292015-03-26 07:52:43 -07001255 }
caryclarke25a4f62016-07-26 09:26:29 -07001256 SkOPASSERT(oppStartT < oppEndT);
caryclark54359292015-03-26 07:52:43 -07001257 SkASSERT(coinStart == first->fStartT);
1258 SkASSERT(coinEnd == last->fEndT);
caryclark643ede62016-08-08 14:27:45 -07001259 SkOPASSERT(oppStartT == oppFirst->fStartT);
1260 SkOPASSERT(oppEndT == oppLast->fEndT);
1261 if (!oppFirst) {
caryclarkef7cee42016-09-06 09:05:54 -07001262 *result = nullptr;
1263 return true;
caryclark643ede62016-08-08 14:27:45 -07001264 }
caryclark42942862016-08-19 07:01:33 -07001265 if (!oppLast) {
caryclarkef7cee42016-09-06 09:05:54 -07001266 *result = nullptr;
1267 return true;
caryclark42942862016-08-19 07:01:33 -07001268 }
caryclark54359292015-03-26 07:52:43 -07001269 // reduce coincident runs to single entries
1270 this->validate();
1271 sect2->validate();
caryclark1049f122015-04-20 08:31:59 -07001272 bool deleteEmptySpans = this->updateBounded(first, last, oppFirst);
1273 deleteEmptySpans |= sect2->updateBounded(oppFirst, oppLast, first);
caryclark54359292015-03-26 07:52:43 -07001274 this->removeSpanRange(first, last);
1275 sect2->removeSpanRange(oppFirst, oppLast);
1276 first->fEndT = last->fEndT;
1277 first->resetBounds(this->fCurve);
1278 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], sect2->fCurve);
1279 first->fCoinEnd.setPerp(fCurve, first->fEndT, first->fPart[TCurve::kPointLast], sect2->fCurve);
1280 oppStartT = first->fCoinStart.perpT();
1281 oppEndT = first->fCoinEnd.perpT();
1282 if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) {
1283 if (!oppMatched) {
Ben Wagnerf08d1d02018-06-18 15:11:00 -04001284 using std::swap;
1285 swap(oppStartT, oppEndT);
caryclark54359292015-03-26 07:52:43 -07001286 }
1287 oppFirst->fStartT = oppStartT;
1288 oppFirst->fEndT = oppEndT;
1289 oppFirst->resetBounds(sect2->fCurve);
1290 }
1291 this->validateBounded();
1292 sect2->validateBounded();
1293 last = first->fNext;
Cary Clark38702ab2017-09-05 18:11:55 -04001294 if (!this->removeCoincident(first, false)) {
1295 return false;
1296 }
1297 if (!sect2->removeCoincident(oppFirst, true)) {
1298 return false;
1299 }
caryclark1049f122015-04-20 08:31:59 -07001300 if (deleteEmptySpans) {
caryclarkef7cee42016-09-06 09:05:54 -07001301 if (!this->deleteEmptySpans() || !sect2->deleteEmptySpans()) {
1302 *result = nullptr;
1303 return false;
1304 }
caryclark54359292015-03-26 07:52:43 -07001305 }
1306 this->validate();
1307 sect2->validate();
caryclarkef7cee42016-09-06 09:05:54 -07001308 *result = last && !last->fDeleted && fHead && sect2->fHead ? last : nullptr;
1309 return true;
caryclark54359292015-03-26 07:52:43 -07001310}
1311
caryclark1049f122015-04-20 08:31:59 -07001312template<typename TCurve, typename OppCurve>
1313SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::findCoincidentRun(
1314 SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>** lastPtr) {
1315 SkTSpan<TCurve, OppCurve>* work = first;
halcanary96fcdcc2015-08-27 07:41:13 -07001316 SkTSpan<TCurve, OppCurve>* lastCandidate = nullptr;
1317 first = nullptr;
caryclark54359292015-03-26 07:52:43 -07001318 // find the first fully coincident span
1319 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07001320 if (work->fCoinStart.isMatch()) {
caryclark1049f122015-04-20 08:31:59 -07001321#if DEBUG_T_SECT
caryclark54359292015-03-26 07:52:43 -07001322 work->validatePerpT(work->fCoinStart.perpT());
1323 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt());
caryclark1049f122015-04-20 08:31:59 -07001324#endif
caryclarka35ab3e2016-10-20 08:32:18 -07001325 SkOPASSERT(work->hasOppT(work->fCoinStart.perpT()));
caryclark6c3b9cd2016-09-26 05:36:58 -07001326 if (!work->fCoinEnd.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001327 break;
1328 }
1329 lastCandidate = work;
1330 if (!first) {
1331 first = work;
1332 }
caryclark1049f122015-04-20 08:31:59 -07001333 } else if (first && work->fCollapsed) {
1334 *lastPtr = lastCandidate;
1335 return first;
caryclark54359292015-03-26 07:52:43 -07001336 } else {
halcanary96fcdcc2015-08-27 07:41:13 -07001337 lastCandidate = nullptr;
caryclark643ede62016-08-08 14:27:45 -07001338 SkOPASSERT(!first);
caryclark54359292015-03-26 07:52:43 -07001339 }
1340 if (work == *lastPtr) {
1341 return first;
1342 }
1343 work = work->fNext;
caryclarke25a4f62016-07-26 09:26:29 -07001344 if (!work) {
1345 return nullptr;
1346 }
caryclark54359292015-03-26 07:52:43 -07001347 } while (true);
1348 if (lastCandidate) {
1349 *lastPtr = lastCandidate;
1350 }
1351 return first;
1352}
1353
caryclark1049f122015-04-20 08:31:59 -07001354template<typename TCurve, typename OppCurve>
1355int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
1356 SkTSect<OppCurve, TCurve>* opp,
1357 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult) {
caryclark54359292015-03-26 07:52:43 -07001358 bool spanStart, oppStart;
1359 int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
1360 if (hullResult >= 0) {
1361 if (hullResult == 2) { // hulls have one point in common
1362 if (!span->fBounded || !span->fBounded->fNext) {
1363 SkASSERT(!span->fBounded || span->fBounded->fBounded == oppSpan);
1364 if (spanStart) {
1365 span->fEndT = span->fStartT;
caryclark45fa4472015-01-16 07:04:10 -08001366 } else {
caryclark54359292015-03-26 07:52:43 -07001367 span->fStartT = span->fEndT;
1368 }
1369 } else {
1370 hullResult = 1;
1371 }
1372 if (!oppSpan->fBounded || !oppSpan->fBounded->fNext) {
1373 SkASSERT(!oppSpan->fBounded || oppSpan->fBounded->fBounded == span);
1374 if (oppStart) {
1375 oppSpan->fEndT = oppSpan->fStartT;
1376 } else {
1377 oppSpan->fStartT = oppSpan->fEndT;
1378 }
1379 *oppResult = 2;
1380 } else {
1381 *oppResult = 1;
1382 }
1383 } else {
1384 *oppResult = 1;
1385 }
1386 return hullResult;
1387 }
1388 if (span->fIsLine && oppSpan->fIsLine) {
1389 SkIntersections i;
1390 int sects = this->linesIntersect(span, opp, oppSpan, &i);
caryclark26ad22a2015-10-16 09:03:38 -07001391 if (sects == 2) {
1392 return *oppResult = 1;
1393 }
caryclark54359292015-03-26 07:52:43 -07001394 if (!sects) {
1395 return -1;
1396 }
caryclark34efb702016-10-24 08:19:06 -07001397 this->removedEndCheck(span);
caryclark54359292015-03-26 07:52:43 -07001398 span->fStartT = span->fEndT = i[0][0];
caryclark34efb702016-10-24 08:19:06 -07001399 opp->removedEndCheck(oppSpan);
caryclark54359292015-03-26 07:52:43 -07001400 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1401 return *oppResult = 2;
1402 }
1403 if (span->fIsLinear || oppSpan->fIsLinear) {
1404 return *oppResult = (int) span->linearsIntersect(oppSpan);
1405 }
1406 return *oppResult = 1;
1407}
1408
caryclarked0935a2015-10-22 07:23:52 -07001409template<typename TCurve>
1410static bool is_parallel(const SkDLine& thisLine, const TCurve& opp) {
1411 if (!opp.IsConic()) {
1412 return false; // FIXME : breaks a lot of stuff now
1413 }
1414 int finds = 0;
1415 SkDLine thisPerp;
1416 thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1417 thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1418 thisPerp.fPts[1] = thisLine.fPts[1];
1419 SkIntersections perpRayI;
1420 perpRayI.intersectRay(opp, thisPerp);
1421 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1422 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]);
1423 }
1424 thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine.fPts[0].fY);
1425 thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine.fPts[1].fX);
1426 thisPerp.fPts[0] = thisLine.fPts[0];
1427 perpRayI.intersectRay(opp, thisPerp);
1428 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1429 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]);
1430 }
1431 return finds >= 2;
1432}
1433
caryclark54359292015-03-26 07:52:43 -07001434// while the intersection points are sufficiently far apart:
1435// construct the tangent lines from the intersections
1436// find the point where the tangent line intersects the opposite curve
caryclark1049f122015-04-20 08:31:59 -07001437template<typename TCurve, typename OppCurve>
1438int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
1439 SkTSect<OppCurve, TCurve>* opp,
1440 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
caryclarka35ab3e2016-10-20 08:32:18 -07001441 SkIntersections thisRayI SkDEBUGCODE((span->fDebugGlobalState));
1442 SkIntersections oppRayI SkDEBUGCODE((span->fDebugGlobalState));
caryclark54359292015-03-26 07:52:43 -07001443 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
caryclark1049f122015-04-20 08:31:59 -07001444 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
caryclark54359292015-03-26 07:52:43 -07001445 int loopCount = 0;
1446 double bestDistSq = DBL_MAX;
caryclark1049f122015-04-20 08:31:59 -07001447 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1448 return 0;
1449 }
1450 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1451 return 0;
1452 }
caryclark26ad22a2015-10-16 09:03:38 -07001453 // if the ends of each line intersect the opposite curve, the lines are coincident
1454 if (thisRayI.used() > 1) {
1455 int ptMatches = 0;
1456 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) {
1457 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); ++lIndex) {
1458 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPts[lIndex]);
1459 }
1460 }
caryclarked0935a2015-10-22 07:23:52 -07001461 if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001462 return 2;
1463 }
1464 }
1465 if (oppRayI.used() > 1) {
1466 int ptMatches = 0;
1467 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) {
Cary Clarkd80870f2017-10-17 11:57:26 -04001468 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(oppLine.fPts); ++lIndex) {
caryclark26ad22a2015-10-16 09:03:38 -07001469 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[lIndex]);
1470 }
1471 }
caryclarked0935a2015-10-22 07:23:52 -07001472 if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) {
caryclark26ad22a2015-10-16 09:03:38 -07001473 return 2;
1474 }
1475 }
caryclark54359292015-03-26 07:52:43 -07001476 do {
caryclark54359292015-03-26 07:52:43 -07001477 // pick the closest pair of points
1478 double closest = DBL_MAX;
1479 int closeIndex SK_INIT_TO_AVOID_WARNING;
1480 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1481 for (int index = 0; index < oppRayI.used(); ++index) {
1482 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
1483 continue;
1484 }
1485 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) {
1486 if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppSpan->fEndT)) {
1487 continue;
1488 }
1489 double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oIndex));
1490 if (closest > distSq) {
1491 closest = distSq;
1492 closeIndex = index;
1493 oppCloseIndex = oIndex;
caryclarkccec0f92015-03-24 07:28:17 -07001494 }
caryclarkccec0f92015-03-24 07:28:17 -07001495 }
reed0dc4dd62015-03-24 13:55:33 -07001496 }
caryclark54359292015-03-26 07:52:43 -07001497 if (closest == DBL_MAX) {
caryclark1049f122015-04-20 08:31:59 -07001498 break;
reed0dc4dd62015-03-24 13:55:33 -07001499 }
caryclark54359292015-03-26 07:52:43 -07001500 const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
1501 const SkDPoint& iPt = oppRayI.pt(closeIndex);
1502 if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT)
1503 && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan->fEndT)
1504 && oppIPt.approximatelyEqual(iPt)) {
1505 i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex);
1506 return i->used();
1507 }
1508 double distSq = oppIPt.distanceSquared(iPt);
1509 if (bestDistSq < distSq || ++loopCount > 5) {
caryclark1049f122015-04-20 08:31:59 -07001510 return 0;
caryclark54359292015-03-26 07:52:43 -07001511 }
1512 bestDistSq = distSq;
caryclark1049f122015-04-20 08:31:59 -07001513 double oppStart = oppRayI[0][closeIndex];
1514 thisLine[0] = fCurve.ptAtT(oppStart);
1515 thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppStart);
1516 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1517 break;
1518 }
1519 double start = thisRayI[0][oppCloseIndex];
1520 oppLine[0] = opp->fCurve.ptAtT(start);
1521 oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(start);
1522 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1523 break;
1524 }
caryclark54359292015-03-26 07:52:43 -07001525 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001526 // convergence may fail if the curves are nearly coincident
1527 SkTCoincident<OppCurve, TCurve> oCoinS, oCoinE;
1528 oCoinS.setPerp(opp->fCurve, oppSpan->fStartT, oppSpan->fPart[0], fCurve);
1529 oCoinE.setPerp(opp->fCurve, oppSpan->fEndT, oppSpan->fPart[OppCurve::kPointLast], fCurve);
1530 double tStart = oCoinS.perpT();
1531 double tEnd = oCoinE.perpT();
1532 bool swap = tStart > tEnd;
1533 if (swap) {
Ben Wagnerf08d1d02018-06-18 15:11:00 -04001534 using std::swap;
1535 swap(tStart, tEnd);
caryclark1049f122015-04-20 08:31:59 -07001536 }
1537 tStart = SkTMax(tStart, span->fStartT);
1538 tEnd = SkTMin(tEnd, span->fEndT);
1539 if (tStart > tEnd) {
1540 return 0;
1541 }
1542 SkDVector perpS, perpE;
1543 if (tStart == span->fStartT) {
1544 SkTCoincident<TCurve, OppCurve> coinS;
1545 coinS.setPerp(fCurve, span->fStartT, span->fPart[0], opp->fCurve);
1546 perpS = span->fPart[0] - coinS.perpPt();
1547 } else if (swap) {
1548 perpS = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1549 } else {
1550 perpS = oCoinS.perpPt() - oppSpan->fPart[0];
1551 }
1552 if (tEnd == span->fEndT) {
1553 SkTCoincident<TCurve, OppCurve> coinE;
1554 coinE.setPerp(fCurve, span->fEndT, span->fPart[TCurve::kPointLast], opp->fCurve);
1555 perpE = span->fPart[TCurve::kPointLast] - coinE.perpPt();
1556 } else if (swap) {
1557 perpE = oCoinS.perpPt() - oppSpan->fPart[0];
1558 } else {
1559 perpE = oCoinE.perpPt() - oppSpan->fPart[OppCurve::kPointLast];
1560 }
1561 if (perpS.dot(perpE) >= 0) {
1562 return 0;
1563 }
1564 SkTCoincident<TCurve, OppCurve> coinW;
1565 double workT = tStart;
1566 double tStep = tEnd - tStart;
1567 SkDPoint workPt;
1568 do {
1569 tStep *= 0.5;
1570 if (precisely_zero(tStep)) {
1571 return 0;
1572 }
1573 workT += tStep;
1574 workPt = fCurve.ptAtT(workT);
1575 coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
caryclark27c015d2016-09-23 05:47:20 -07001576 double perpT = coinW.perpT();
caryclark6c3b9cd2016-09-26 05:36:58 -07001577 if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) {
caryclarkb6693002015-12-16 12:28:35 -08001578 continue;
1579 }
caryclark1049f122015-04-20 08:31:59 -07001580 SkDVector perpW = workPt - coinW.perpPt();
1581 if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
1582 tStep = -tStep;
1583 }
caryclarkb6693002015-12-16 12:28:35 -08001584 if (workPt.approximatelyEqual(coinW.perpPt())) {
1585 break;
1586 }
1587 } while (true);
caryclark1049f122015-04-20 08:31:59 -07001588 double oppTTest = coinW.perpT();
1589 if (!opp->fHead->contains(oppTTest)) {
1590 return 0;
1591 }
1592 i->setMax(1);
1593 i->insert(workT, oppTTest, workPt);
1594 return 1;
caryclark54359292015-03-26 07:52:43 -07001595}
1596
1597
caryclark1049f122015-04-20 08:31:59 -07001598template<typename TCurve, typename OppCurve>
caryclarkef7cee42016-09-06 09:05:54 -07001599bool SkTSect<TCurve, OppCurve>::markSpanGone(SkTSpan<TCurve, OppCurve>* span) {
1600 if (--fActiveCount < 0) {
1601 return false;
1602 }
caryclark54359292015-03-26 07:52:43 -07001603 span->fNext = fDeleted;
1604 fDeleted = span;
caryclarke25a4f62016-07-26 09:26:29 -07001605 SkOPASSERT(!span->fDeleted);
caryclark54359292015-03-26 07:52:43 -07001606 span->fDeleted = true;
caryclarkef7cee42016-09-06 09:05:54 -07001607 return true;
caryclark54359292015-03-26 07:52:43 -07001608}
1609
caryclark1049f122015-04-20 08:31:59 -07001610template<typename TCurve, typename OppCurve>
1611bool SkTSect<TCurve, OppCurve>::matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2,
1612 double t2) const {
caryclark54359292015-03-26 07:52:43 -07001613 SkDVector dxdy = this->fCurve.dxdyAtT(t);
1614 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
1615 return dxdy.dot(dxdy2) >= 0;
1616}
1617
caryclark1049f122015-04-20 08:31:59 -07001618template<typename TCurve, typename OppCurve>
1619void SkTSect<TCurve, OppCurve>::matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2,
1620 double t2, bool* calcMatched, bool* oppMatched) const {
caryclark54359292015-03-26 07:52:43 -07001621 if (*calcMatched) {
caryclark55888e42016-07-18 10:01:36 -07001622 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
caryclark54359292015-03-26 07:52:43 -07001623 } else {
1624 *oppMatched = this->matchedDirection(t, sect2, t2);
1625 *calcMatched = true;
1626 }
1627}
1628
caryclark1049f122015-04-20 08:31:59 -07001629template<typename TCurve, typename OppCurve>
1630void SkTSect<TCurve, OppCurve>::mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2) {
caryclark54359292015-03-26 07:52:43 -07001631 double smallLimit = 0;
1632 do {
1633 // find the smallest unprocessed span
halcanary96fcdcc2015-08-27 07:41:13 -07001634 SkTSpan<TCurve, OppCurve>* smaller = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001635 SkTSpan<TCurve, OppCurve>* test = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001636 do {
caryclark221a4bb2016-10-07 11:15:15 -07001637 if (!test) {
1638 return;
1639 }
caryclark54359292015-03-26 07:52:43 -07001640 if (test->fStartT < smallLimit) {
1641 continue;
1642 }
1643 if (smaller && smaller->fEndT < test->fStartT) {
1644 continue;
1645 }
1646 smaller = test;
1647 } while ((test = test->fNext));
1648 if (!smaller) {
1649 return;
1650 }
1651 smallLimit = smaller->fEndT;
1652 // find next larger span
halcanary96fcdcc2015-08-27 07:41:13 -07001653 SkTSpan<TCurve, OppCurve>* prior = nullptr;
1654 SkTSpan<TCurve, OppCurve>* larger = nullptr;
1655 SkTSpan<TCurve, OppCurve>* largerPrior = nullptr;
caryclark54359292015-03-26 07:52:43 -07001656 test = fCoincident;
1657 do {
1658 if (test->fStartT < smaller->fEndT) {
1659 continue;
1660 }
caryclark221a4bb2016-10-07 11:15:15 -07001661 SkOPASSERT(test->fStartT != smaller->fEndT);
caryclark54359292015-03-26 07:52:43 -07001662 if (larger && larger->fStartT < test->fStartT) {
1663 continue;
1664 }
1665 largerPrior = prior;
1666 larger = test;
1667 } while ((prior = test), (test = test->fNext));
1668 if (!larger) {
1669 continue;
1670 }
1671 // check middle t value to see if it is coincident as well
1672 double midT = (smaller->fEndT + larger->fStartT) / 2;
1673 SkDPoint midPt = fCurve.ptAtT(midT);
caryclark1049f122015-04-20 08:31:59 -07001674 SkTCoincident<TCurve, OppCurve> coin;
caryclark54359292015-03-26 07:52:43 -07001675 coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07001676 if (coin.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07001677 smaller->fEndT = larger->fEndT;
1678 smaller->fCoinEnd = larger->fCoinEnd;
1679 if (largerPrior) {
1680 largerPrior->fNext = larger->fNext;
caryclark643ede62016-08-08 14:27:45 -07001681 largerPrior->validate();
caryclark54359292015-03-26 07:52:43 -07001682 } else {
1683 fCoincident = larger->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001684 }
1685 }
caryclark54359292015-03-26 07:52:43 -07001686 } while (true);
1687}
1688
caryclark1049f122015-04-20 08:31:59 -07001689template<typename TCurve, typename OppCurve>
1690SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::prev(
1691 SkTSpan<TCurve, OppCurve>* span) const {
halcanary96fcdcc2015-08-27 07:41:13 -07001692 SkTSpan<TCurve, OppCurve>* result = nullptr;
caryclark1049f122015-04-20 08:31:59 -07001693 SkTSpan<TCurve, OppCurve>* test = fHead;
caryclark54359292015-03-26 07:52:43 -07001694 while (span != test) {
1695 result = test;
1696 test = test->fNext;
1697 SkASSERT(test);
caryclarkccec0f92015-03-24 07:28:17 -07001698 }
caryclark55888e42016-07-18 10:01:36 -07001699 return result;
caryclarkccec0f92015-03-24 07:28:17 -07001700}
1701
caryclark1049f122015-04-20 08:31:59 -07001702template<typename TCurve, typename OppCurve>
1703void SkTSect<TCurve, OppCurve>::recoverCollapsed() {
1704 SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001705 while (deleted) {
caryclark1049f122015-04-20 08:31:59 -07001706 SkTSpan<TCurve, OppCurve>* delNext = deleted->fNext;
caryclark45fa4472015-01-16 07:04:10 -08001707 if (deleted->fCollapsed) {
caryclark1049f122015-04-20 08:31:59 -07001708 SkTSpan<TCurve, OppCurve>** spanPtr = &fHead;
caryclark45fa4472015-01-16 07:04:10 -08001709 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
1710 spanPtr = &(*spanPtr)->fNext;
1711 }
1712 deleted->fNext = *spanPtr;
1713 *spanPtr = deleted;
1714 }
1715 deleted = delNext;
1716 }
1717}
1718
caryclark1049f122015-04-20 08:31:59 -07001719template<typename TCurve, typename OppCurve>
1720void SkTSect<TCurve, OppCurve>::removeAllBut(const SkTSpan<OppCurve, TCurve>* keep,
1721 SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp) {
1722 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001723 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001724 SkTSpan<OppCurve, TCurve>* bounded = testBounded->fBounded;
1725 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001726 // may have been deleted when opp did 'remove all but'
1727 if (bounded != keep && !bounded->fDeleted) {
1728 SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
1729 if (bounded->removeBounded(span)) {
1730 opp->removeSpan(bounded);
1731 }
caryclarkccec0f92015-03-24 07:28:17 -07001732 }
caryclark54359292015-03-26 07:52:43 -07001733 testBounded = next;
caryclarkccec0f92015-03-24 07:28:17 -07001734 }
caryclark54359292015-03-26 07:52:43 -07001735 SkASSERT(!span->fDeleted);
1736 SkASSERT(span->findOppSpan(keep));
1737 SkASSERT(keep->findOppSpan(span));
caryclarkccec0f92015-03-24 07:28:17 -07001738}
1739
caryclark1049f122015-04-20 08:31:59 -07001740template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001741bool SkTSect<TCurve, OppCurve>::removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp) {
caryclark1049f122015-04-20 08:31:59 -07001742 SkTSpan<TCurve, OppCurve>* test = fHead;
1743 SkTSpan<TCurve, OppCurve>* next;
caryclark54359292015-03-26 07:52:43 -07001744 do {
1745 next = test->fNext;
1746 if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
1747 continue;
reed0dc4dd62015-03-24 13:55:33 -07001748 }
caryclark54359292015-03-26 07:52:43 -07001749 SkDVector startV = test->fCoinStart.perpPt() - test->fPart[0];
1750 SkDVector endV = test->fCoinEnd.perpPt() - test->fPart[TCurve::kPointLast];
1751#if DEBUG_T_SECT
1752 SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUNCTION__,
1753 startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV));
1754#endif
1755 if (startV.dot(endV) <= 0) {
1756 continue;
1757 }
Cary Clark0949bee2018-03-19 09:42:00 -04001758 if (!this->removeSpans(test, opp)) {
1759 return false;
1760 }
caryclark54359292015-03-26 07:52:43 -07001761 } while ((test = next));
Cary Clark0949bee2018-03-19 09:42:00 -04001762 return true;
caryclark54359292015-03-26 07:52:43 -07001763}
1764
caryclark1049f122015-04-20 08:31:59 -07001765template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001766bool SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span, bool isBetween) {
1767 if (!this->unlinkSpan(span)) {
1768 return false;
1769 }
caryclark54359292015-03-26 07:52:43 -07001770 if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
1771 --fActiveCount;
1772 span->fNext = fCoincident;
1773 fCoincident = span;
1774 } else {
1775 this->markSpanGone(span);
reed0dc4dd62015-03-24 13:55:33 -07001776 }
Cary Clark38702ab2017-09-05 18:11:55 -04001777 return true;
caryclarkccec0f92015-03-24 07:28:17 -07001778}
1779
caryclark1049f122015-04-20 08:31:59 -07001780template<typename TCurve, typename OppCurve>
caryclark34efb702016-10-24 08:19:06 -07001781void SkTSect<TCurve, OppCurve>::removedEndCheck(SkTSpan<TCurve, OppCurve>* span) {
caryclark6c3b9cd2016-09-26 05:36:58 -07001782 if (!span->fStartT) {
1783 fRemovedStartT = true;
1784 }
1785 if (1 == span->fEndT) {
1786 fRemovedEndT = true;
1787 }
caryclark34efb702016-10-24 08:19:06 -07001788}
1789
1790template<typename TCurve, typename OppCurve>
1791bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {\
1792 this->removedEndCheck(span);
Cary Clark38702ab2017-09-05 18:11:55 -04001793 if (!this->unlinkSpan(span)) {
1794 return false;
1795 }
caryclarkef7cee42016-09-06 09:05:54 -07001796 return this->markSpanGone(span);
caryclark54359292015-03-26 07:52:43 -07001797}
1798
caryclark1049f122015-04-20 08:31:59 -07001799template<typename TCurve, typename OppCurve>
1800void SkTSect<TCurve, OppCurve>::removeSpanRange(SkTSpan<TCurve, OppCurve>* first,
1801 SkTSpan<TCurve, OppCurve>* last) {
caryclark54359292015-03-26 07:52:43 -07001802 if (first == last) {
1803 return;
1804 }
caryclark1049f122015-04-20 08:31:59 -07001805 SkTSpan<TCurve, OppCurve>* span = first;
caryclark54359292015-03-26 07:52:43 -07001806 SkASSERT(span);
caryclark1049f122015-04-20 08:31:59 -07001807 SkTSpan<TCurve, OppCurve>* final = last->fNext;
1808 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001809 while ((span = next) && span != final) {
1810 next = span->fNext;
1811 this->markSpanGone(span);
1812 }
1813 if (final) {
1814 final->fPrev = first;
1815 }
1816 first->fNext = final;
Cary Clarkb8421ed2018-03-14 15:55:02 -04001817 // world may not be ready for validation here
caryclark643ede62016-08-08 14:27:45 -07001818 first->validate();
caryclark54359292015-03-26 07:52:43 -07001819}
1820
caryclark1049f122015-04-20 08:31:59 -07001821template<typename TCurve, typename OppCurve>
Cary Clark0949bee2018-03-19 09:42:00 -04001822bool SkTSect<TCurve, OppCurve>::removeSpans(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001823 SkTSect<OppCurve, TCurve>* opp) {
1824 SkTSpanBounded<OppCurve, TCurve>* bounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001825 while (bounded) {
caryclark1049f122015-04-20 08:31:59 -07001826 SkTSpan<OppCurve, TCurve>* spanBounded = bounded->fBounded;
1827 SkTSpanBounded<OppCurve, TCurve>* next = bounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001828 if (span->removeBounded(spanBounded)) { // shuffles last into position 0
1829 this->removeSpan(span);
1830 }
1831 if (spanBounded->removeBounded(span)) {
1832 opp->removeSpan(spanBounded);
1833 }
Cary Clark0949bee2018-03-19 09:42:00 -04001834 if (span->fDeleted && opp->hasBounded(span)) {
1835 return false;
1836 }
caryclark54359292015-03-26 07:52:43 -07001837 bounded = next;
reed0dc4dd62015-03-24 13:55:33 -07001838 }
Cary Clark0949bee2018-03-19 09:42:00 -04001839 return true;
reed0dc4dd62015-03-24 13:55:33 -07001840}
caryclarkccec0f92015-03-24 07:28:17 -07001841
caryclark1049f122015-04-20 08:31:59 -07001842template<typename TCurve, typename OppCurve>
1843SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::spanAtT(double t,
1844 SkTSpan<TCurve, OppCurve>** priorSpan) {
1845 SkTSpan<TCurve, OppCurve>* test = fHead;
halcanary96fcdcc2015-08-27 07:41:13 -07001846 SkTSpan<TCurve, OppCurve>* prev = nullptr;
caryclark54359292015-03-26 07:52:43 -07001847 while (test && test->fEndT < t) {
1848 prev = test;
1849 test = test->fNext;
reed0dc4dd62015-03-24 13:55:33 -07001850 }
caryclark54359292015-03-26 07:52:43 -07001851 *priorSpan = prev;
halcanary96fcdcc2015-08-27 07:41:13 -07001852 return test && test->fStartT <= t ? test : nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001853}
1854
caryclark1049f122015-04-20 08:31:59 -07001855template<typename TCurve, typename OppCurve>
1856SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::tail() {
1857 SkTSpan<TCurve, OppCurve>* result = fHead;
1858 SkTSpan<TCurve, OppCurve>* next = fHead;
reed0dc4dd62015-03-24 13:55:33 -07001859 while ((next = next->fNext)) {
1860 if (next->fEndT > result->fEndT) {
1861 result = next;
1862 }
1863 }
1864 return result;
1865}
1866
1867/* Each span has a range of opposite spans it intersects. After the span is split in two,
1868 adjust the range to its new size */
caryclark1049f122015-04-20 08:31:59 -07001869template<typename TCurve, typename OppCurve>
caryclarka35ab3e2016-10-20 08:32:18 -07001870bool SkTSect<TCurve, OppCurve>::trim(SkTSpan<TCurve, OppCurve>* span,
caryclark1049f122015-04-20 08:31:59 -07001871 SkTSect<OppCurve, TCurve>* opp) {
caryclarka35ab3e2016-10-20 08:32:18 -07001872 FAIL_IF(!span->initBounds(fCurve));
caryclark1049f122015-04-20 08:31:59 -07001873 const SkTSpanBounded<OppCurve, TCurve>* testBounded = span->fBounded;
caryclark54359292015-03-26 07:52:43 -07001874 while (testBounded) {
caryclark1049f122015-04-20 08:31:59 -07001875 SkTSpan<OppCurve, TCurve>* test = testBounded->fBounded;
1876 const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
caryclark54359292015-03-26 07:52:43 -07001877 int oppSects, sects = this->intersects(span, opp, test, &oppSects);
1878 if (sects >= 1) {
1879 if (oppSects == 2) {
1880 test->initBounds(opp->fCurve);
1881 opp->removeAllBut(span, test, this);
1882 }
1883 if (sects == 2) {
1884 span->initBounds(fCurve);
1885 this->removeAllBut(test, span, opp);
caryclarka35ab3e2016-10-20 08:32:18 -07001886 return true;
caryclark54359292015-03-26 07:52:43 -07001887 }
reed0dc4dd62015-03-24 13:55:33 -07001888 } else {
caryclark54359292015-03-26 07:52:43 -07001889 if (span->removeBounded(test)) {
1890 this->removeSpan(span);
1891 }
1892 if (test->removeBounded(span)) {
1893 opp->removeSpan(test);
1894 }
1895 }
1896 testBounded = next;
1897 }
caryclarka35ab3e2016-10-20 08:32:18 -07001898 return true;
caryclark54359292015-03-26 07:52:43 -07001899}
1900
caryclark1049f122015-04-20 08:31:59 -07001901template<typename TCurve, typename OppCurve>
Cary Clark38702ab2017-09-05 18:11:55 -04001902bool SkTSect<TCurve, OppCurve>::unlinkSpan(SkTSpan<TCurve, OppCurve>* span) {
caryclark1049f122015-04-20 08:31:59 -07001903 SkTSpan<TCurve, OppCurve>* prev = span->fPrev;
1904 SkTSpan<TCurve, OppCurve>* next = span->fNext;
caryclark54359292015-03-26 07:52:43 -07001905 if (prev) {
1906 prev->fNext = next;
1907 if (next) {
1908 next->fPrev = prev;
Cary Clark38702ab2017-09-05 18:11:55 -04001909 if (next->fStartT > next->fEndT) {
1910 return false;
1911 }
Cary Clarkb8421ed2018-03-14 15:55:02 -04001912 // world may not be ready for validate here
caryclark643ede62016-08-08 14:27:45 -07001913 next->validate();
caryclark54359292015-03-26 07:52:43 -07001914 }
1915 } else {
1916 fHead = next;
1917 if (next) {
halcanary96fcdcc2015-08-27 07:41:13 -07001918 next->fPrev = nullptr;
reed0dc4dd62015-03-24 13:55:33 -07001919 }
1920 }
Cary Clark38702ab2017-09-05 18:11:55 -04001921 return true;
reed0dc4dd62015-03-24 13:55:33 -07001922}
1923
caryclark1049f122015-04-20 08:31:59 -07001924template<typename TCurve, typename OppCurve>
1925bool SkTSect<TCurve, OppCurve>::updateBounded(SkTSpan<TCurve, OppCurve>* first,
1926 SkTSpan<TCurve, OppCurve>* last, SkTSpan<OppCurve, TCurve>* oppFirst) {
1927 SkTSpan<TCurve, OppCurve>* test = first;
1928 const SkTSpan<TCurve, OppCurve>* final = last->next();
caryclark54359292015-03-26 07:52:43 -07001929 bool deleteSpan = false;
1930 do {
1931 deleteSpan |= test->removeAllBounded();
caryclarke25a4f62016-07-26 09:26:29 -07001932 } while ((test = test->fNext) != final && test);
halcanary96fcdcc2015-08-27 07:41:13 -07001933 first->fBounded = nullptr;
caryclark54359292015-03-26 07:52:43 -07001934 first->addBounded(oppFirst, &fHeap);
1935 // cannot call validate until remove span range is called
1936 return deleteSpan;
1937}
1938
1939
caryclark1049f122015-04-20 08:31:59 -07001940template<typename TCurve, typename OppCurve>
1941void SkTSect<TCurve, OppCurve>::validate() const {
caryclark643ede62016-08-08 14:27:45 -07001942#if DEBUG_VALIDATE
caryclark45fa4472015-01-16 07:04:10 -08001943 int count = 0;
caryclark643ede62016-08-08 14:27:45 -07001944 double last = 0;
caryclark45fa4472015-01-16 07:04:10 -08001945 if (fHead) {
caryclark1049f122015-04-20 08:31:59 -07001946 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark45fa4472015-01-16 07:04:10 -08001947 SkASSERT(!span->fPrev);
caryclark643ede62016-08-08 14:27:45 -07001948 const SkTSpan<TCurve, OppCurve>* next;
caryclark45fa4472015-01-16 07:04:10 -08001949 do {
1950 span->validate();
1951 SkASSERT(span->fStartT >= last);
caryclark643ede62016-08-08 14:27:45 -07001952 last = span->fEndT;
caryclark45fa4472015-01-16 07:04:10 -08001953 ++count;
caryclark643ede62016-08-08 14:27:45 -07001954 next = span->fNext;
1955 SkASSERT(next != span);
1956 } while ((span = next) != nullptr);
caryclark45fa4472015-01-16 07:04:10 -08001957 }
1958 SkASSERT(count == fActiveCount);
caryclark643ede62016-08-08 14:27:45 -07001959#endif
1960#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -08001961 SkASSERT(fActiveCount <= fDebugAllocatedCount);
1962 int deletedCount = 0;
caryclark1049f122015-04-20 08:31:59 -07001963 const SkTSpan<TCurve, OppCurve>* deleted = fDeleted;
caryclark45fa4472015-01-16 07:04:10 -08001964 while (deleted) {
1965 ++deletedCount;
1966 deleted = deleted->fNext;
1967 }
caryclark1049f122015-04-20 08:31:59 -07001968 const SkTSpan<TCurve, OppCurve>* coincident = fCoincident;
caryclark54359292015-03-26 07:52:43 -07001969 while (coincident) {
1970 ++deletedCount;
1971 coincident = coincident->fNext;
1972 }
caryclark45fa4472015-01-16 07:04:10 -08001973 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount);
caryclarkccec0f92015-03-24 07:28:17 -07001974#endif
caryclark54359292015-03-26 07:52:43 -07001975}
1976
caryclark1049f122015-04-20 08:31:59 -07001977template<typename TCurve, typename OppCurve>
1978void SkTSect<TCurve, OppCurve>::validateBounded() const {
caryclark643ede62016-08-08 14:27:45 -07001979#if DEBUG_VALIDATE
caryclark54359292015-03-26 07:52:43 -07001980 if (!fHead) {
1981 return;
1982 }
caryclark1049f122015-04-20 08:31:59 -07001983 const SkTSpan<TCurve, OppCurve>* span = fHead;
caryclark54359292015-03-26 07:52:43 -07001984 do {
1985 span->validateBounded();
halcanary96fcdcc2015-08-27 07:41:13 -07001986 } while ((span = span->fNext) != nullptr);
caryclark54359292015-03-26 07:52:43 -07001987#endif
1988}
caryclark45fa4472015-01-16 07:04:10 -08001989
caryclark1049f122015-04-20 08:31:59 -07001990template<typename TCurve, typename OppCurve>
1991int SkTSect<TCurve, OppCurve>::EndsEqual(const SkTSect<TCurve, OppCurve>* sect1,
1992 const SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark45fa4472015-01-16 07:04:10 -08001993 int zeroOneSet = 0;
caryclark54359292015-03-26 07:52:43 -07001994 if (sect1->fCurve[0] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07001995 zeroOneSet |= kZeroS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07001996 intersections->insert(0, 0, sect1->fCurve[0]);
1997 }
caryclark1049f122015-04-20 08:31:59 -07001998 if (sect1->fCurve[0] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07001999 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark54359292015-03-26 07:52:43 -07002000 intersections->insert(0, 1, sect1->fCurve[0]);
2001 }
2002 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[0]) {
caryclarkccec0f92015-03-24 07:28:17 -07002003 zeroOneSet |= kOneS1Set | kZeroS2Set;
caryclark54359292015-03-26 07:52:43 -07002004 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
2005 }
caryclark1049f122015-04-20 08:31:59 -07002006 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[OppCurve::kPointLast]) {
caryclarkccec0f92015-03-24 07:28:17 -07002007 zeroOneSet |= kOneS1Set | kOneS2Set;
reed0dc4dd62015-03-24 13:55:33 -07002008 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07002009 }
2010 // check for zero
2011 if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set))
2012 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) {
2013 zeroOneSet |= kZeroS1Set | kZeroS2Set;
2014 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
2015 }
2016 if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
caryclark1049f122015-04-20 08:31:59 -07002017 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07002018 zeroOneSet |= kZeroS1Set | kOneS2Set;
caryclark1049f122015-04-20 08:31:59 -07002019 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[OppCurve::kPointLast]);
caryclark54359292015-03-26 07:52:43 -07002020 }
2021 // check for one
2022 if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
2023 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[0])) {
2024 zeroOneSet |= kOneS1Set | kZeroS2Set;
2025 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], sect2->fCurve[0]);
2026 }
2027 if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
2028 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[
caryclark1049f122015-04-20 08:31:59 -07002029 OppCurve::kPointLast])) {
caryclark54359292015-03-26 07:52:43 -07002030 zeroOneSet |= kOneS1Set | kOneS2Set;
2031 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
caryclark1049f122015-04-20 08:31:59 -07002032 sect2->fCurve[OppCurve::kPointLast]);
caryclark45fa4472015-01-16 07:04:10 -08002033 }
2034 return zeroOneSet;
2035}
2036
caryclark1049f122015-04-20 08:31:59 -07002037template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002038struct SkClosestRecord {
caryclark54359292015-03-26 07:52:43 -07002039 bool operator<(const SkClosestRecord& rh) const {
2040 return fClosest < rh.fClosest;
2041 }
2042
caryclark45fa4472015-01-16 07:04:10 -08002043 void addIntersection(SkIntersections* intersections) const {
2044 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT();
2045 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT();
2046 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
2047 }
2048
caryclark1049f122015-04-20 08:31:59 -07002049 void findEnd(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2,
caryclark45fa4472015-01-16 07:04:10 -08002050 int c1Index, int c2Index) {
2051 const TCurve& c1 = span1->part();
caryclark1049f122015-04-20 08:31:59 -07002052 const OppCurve& c2 = span2->part();
caryclark45fa4472015-01-16 07:04:10 -08002053 if (!c1[c1Index].approximatelyEqual(c2[c2Index])) {
2054 return;
2055 }
2056 double dist = c1[c1Index].distanceSquared(c2[c2Index]);
2057 if (fClosest < dist) {
2058 return;
2059 }
2060 fC1Span = span1;
2061 fC2Span = span2;
2062 fC1StartT = span1->startT();
2063 fC1EndT = span1->endT();
2064 fC2StartT = span2->startT();
2065 fC2EndT = span2->endT();
2066 fC1Index = c1Index;
2067 fC2Index = c2Index;
2068 fClosest = dist;
2069 }
2070
caryclarkcdeff812016-07-22 03:34:19 -07002071 bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const {
Cary Clark67116382017-01-03 16:25:18 -05002072 SkOPOBJASSERT(i, fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002073 || mate.fC1Span->endT() <= fC1Span->startT());
caryclarkcdeff812016-07-22 03:34:19 -07002074 SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT()
caryclark45fa4472015-01-16 07:04:10 -08002075 || mate.fC2Span->endT() <= fC2Span->startT());
2076 return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT()
2077 || fC1Span->startT() == mate.fC1Span->endT()
2078 || fC2Span == mate.fC2Span
2079 || fC2Span->endT() == mate.fC2Span->startT()
2080 || fC2Span->startT() == mate.fC2Span->endT();
2081 }
2082
2083 void merge(const SkClosestRecord& mate) {
2084 fC1Span = mate.fC1Span;
2085 fC2Span = mate.fC2Span;
2086 fClosest = mate.fClosest;
2087 fC1Index = mate.fC1Index;
2088 fC2Index = mate.fC2Index;
2089 }
caryclark55888e42016-07-18 10:01:36 -07002090
caryclark45fa4472015-01-16 07:04:10 -08002091 void reset() {
2092 fClosest = FLT_MAX;
halcanary96fcdcc2015-08-27 07:41:13 -07002093 SkDEBUGCODE(fC1Span = nullptr);
2094 SkDEBUGCODE(fC2Span = nullptr);
caryclark45fa4472015-01-16 07:04:10 -08002095 SkDEBUGCODE(fC1Index = fC2Index = -1);
2096 }
2097
2098 void update(const SkClosestRecord& mate) {
2099 fC1StartT = SkTMin(fC1StartT, mate.fC1StartT);
2100 fC1EndT = SkTMax(fC1EndT, mate.fC1EndT);
2101 fC2StartT = SkTMin(fC2StartT, mate.fC2StartT);
2102 fC2EndT = SkTMax(fC2EndT, mate.fC2EndT);
2103 }
2104
caryclark1049f122015-04-20 08:31:59 -07002105 const SkTSpan<TCurve, OppCurve>* fC1Span;
2106 const SkTSpan<OppCurve, TCurve>* fC2Span;
caryclark45fa4472015-01-16 07:04:10 -08002107 double fC1StartT;
2108 double fC1EndT;
2109 double fC2StartT;
2110 double fC2EndT;
2111 double fClosest;
2112 int fC1Index;
2113 int fC2Index;
2114};
2115
caryclark1049f122015-04-20 08:31:59 -07002116template<typename TCurve, typename OppCurve>
caryclark45fa4472015-01-16 07:04:10 -08002117struct SkClosestSect {
2118 SkClosestSect()
2119 : fUsed(0) {
2120 fClosest.push_back().reset();
2121 }
2122
caryclarkcdeff812016-07-22 03:34:19 -07002123 bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2
2124 SkDEBUGPARAMS(SkIntersections* i)) {
caryclark1049f122015-04-20 08:31:59 -07002125 SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed];
caryclark45fa4472015-01-16 07:04:10 -08002126 record->findEnd(span1, span2, 0, 0);
caryclark1049f122015-04-20 08:31:59 -07002127 record->findEnd(span1, span2, 0, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002128 record->findEnd(span1, span2, TCurve::kPointLast, 0);
caryclark1049f122015-04-20 08:31:59 -07002129 record->findEnd(span1, span2, TCurve::kPointLast, OppCurve::kPointLast);
caryclark45fa4472015-01-16 07:04:10 -08002130 if (record->fClosest == FLT_MAX) {
caryclark54359292015-03-26 07:52:43 -07002131 return false;
caryclark45fa4472015-01-16 07:04:10 -08002132 }
2133 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002134 SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index];
caryclarkcdeff812016-07-22 03:34:19 -07002135 if (test->matesWith(*record SkDEBUGPARAMS(i))) {
caryclark45fa4472015-01-16 07:04:10 -08002136 if (test->fClosest > record->fClosest) {
2137 test->merge(*record);
2138 }
2139 test->update(*record);
2140 record->reset();
caryclark54359292015-03-26 07:52:43 -07002141 return false;
caryclark45fa4472015-01-16 07:04:10 -08002142 }
2143 }
2144 ++fUsed;
2145 fClosest.push_back().reset();
caryclark54359292015-03-26 07:52:43 -07002146 return true;
caryclark45fa4472015-01-16 07:04:10 -08002147 }
2148
2149 void finish(SkIntersections* intersections) const {
caryclark1049f122015-04-20 08:31:59 -07002150 SkSTArray<TCurve::kMaxIntersections * 3,
2151 const SkClosestRecord<TCurve, OppCurve>*, true> closestPtrs;
caryclark45fa4472015-01-16 07:04:10 -08002152 for (int index = 0; index < fUsed; ++index) {
caryclark54359292015-03-26 07:52:43 -07002153 closestPtrs.push_back(&fClosest[index]);
2154 }
caryclark1049f122015-04-20 08:31:59 -07002155 SkTQSort<const SkClosestRecord<TCurve, OppCurve> >(closestPtrs.begin(), closestPtrs.end()
2156 - 1);
caryclark54359292015-03-26 07:52:43 -07002157 for (int index = 0; index < fUsed; ++index) {
caryclark1049f122015-04-20 08:31:59 -07002158 const SkClosestRecord<TCurve, OppCurve>* test = closestPtrs[index];
caryclark54359292015-03-26 07:52:43 -07002159 test->addIntersection(intersections);
caryclark45fa4472015-01-16 07:04:10 -08002160 }
2161 }
2162
caryclark54359292015-03-26 07:52:43 -07002163 // this is oversized so that an extra records can merge into final one
caryclark1049f122015-04-20 08:31:59 -07002164 SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve, OppCurve>, true> fClosest;
caryclark45fa4472015-01-16 07:04:10 -08002165 int fUsed;
2166};
2167
2168// returns true if the rect is too small to consider
caryclark1049f122015-04-20 08:31:59 -07002169template<typename TCurve, typename OppCurve>
2170void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
2171 SkTSect<OppCurve, TCurve>* sect2, SkIntersections* intersections) {
caryclark54359292015-03-26 07:52:43 -07002172#if DEBUG_T_SECT_DUMP > 1
2173 gDumpTSectNum = 0;
2174#endif
caryclark1049f122015-04-20 08:31:59 -07002175 SkDEBUGCODE(sect1->fOppSect = sect2);
2176 SkDEBUGCODE(sect2->fOppSect = sect1);
caryclark45fa4472015-01-16 07:04:10 -08002177 intersections->reset();
caryclarka35ab3e2016-10-20 08:32:18 -07002178 intersections->setMax(TCurve::kMaxIntersections + 4); // give extra for slop
caryclark1049f122015-04-20 08:31:59 -07002179 SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
2180 SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002181 int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
2182// SkASSERT(between(0, sect, 2));
2183 if (!sect) {
caryclark45fa4472015-01-16 07:04:10 -08002184 return;
2185 }
caryclark54359292015-03-26 07:52:43 -07002186 if (sect == 2 && oppSect == 2) {
caryclark45fa4472015-01-16 07:04:10 -08002187 (void) EndsEqual(sect1, sect2, intersections);
2188 return;
2189 }
caryclark54359292015-03-26 07:52:43 -07002190 span1->addBounded(span2, &sect1->fHeap);
2191 span2->addBounded(span1, &sect2->fHeap);
caryclark26ad22a2015-10-16 09:03:38 -07002192 const int kMaxCoinLoopCount = 8;
2193 int coinLoopCount = kMaxCoinLoopCount;
2194 double start1s SK_INIT_TO_AVOID_WARNING;
2195 double start1e SK_INIT_TO_AVOID_WARNING;
caryclark45fa4472015-01-16 07:04:10 -08002196 do {
2197 // find the largest bounds
caryclark1049f122015-04-20 08:31:59 -07002198 SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002199 if (!largest1) {
2200 break;
2201 }
caryclark1049f122015-04-20 08:31:59 -07002202 SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
caryclark45fa4472015-01-16 07:04:10 -08002203 // split it
caryclark1049f122015-04-20 08:31:59 -07002204 if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
2205 || (!largest1->fCollapsed && largest2->fCollapsed)))) {
2206 if (largest1->fCollapsed) {
2207 break;
2208 }
caryclark34efb702016-10-24 08:19:06 -07002209 sect1->resetRemovedEnds();
2210 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002211 // trim parts that don't intersect the opposite
2212 SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
caryclark643ede62016-08-08 14:27:45 -07002213 SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002214 if (!half1->split(largest1, &sect1->fHeap)) {
2215 break;
2216 }
caryclarka35ab3e2016-10-20 08:32:18 -07002217 if (!sect1->trim(largest1, sect2)) {
2218 SkOPOBJASSERT(intersections, 0);
2219 return;
2220 }
2221 if (!sect1->trim(half1, sect2)) {
2222 SkOPOBJASSERT(intersections, 0);
2223 return;
2224 }
caryclark1049f122015-04-20 08:31:59 -07002225 } else {
2226 if (largest2->fCollapsed) {
2227 break;
2228 }
caryclark34efb702016-10-24 08:19:06 -07002229 sect1->resetRemovedEnds();
2230 sect2->resetRemovedEnds();
caryclark1049f122015-04-20 08:31:59 -07002231 // trim parts that don't intersect the opposite
2232 SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
caryclark643ede62016-08-08 14:27:45 -07002233 SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState()));
caryclark1049f122015-04-20 08:31:59 -07002234 if (!half2->split(largest2, &sect2->fHeap)) {
2235 break;
2236 }
caryclarka35ab3e2016-10-20 08:32:18 -07002237 if (!sect2->trim(largest2, sect1)) {
2238 SkOPOBJASSERT(intersections, 0);
2239 return;
2240 }
2241 if (!sect2->trim(half2, sect1)) {
2242 SkOPOBJASSERT(intersections, 0);
2243 return;
2244 }
caryclark45fa4472015-01-16 07:04:10 -08002245 }
caryclark54359292015-03-26 07:52:43 -07002246 sect1->validate();
2247 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002248#if DEBUG_T_SECT_LOOP_COUNT
2249 intersections->debugBumpLoopCount(SkIntersections::kIterations_DebugLoop);
2250#endif
caryclark45fa4472015-01-16 07:04:10 -08002251 // if there are 9 or more continuous spans on both sects, suspect coincidence
2252 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2253 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
caryclark26ad22a2015-10-16 09:03:38 -07002254 if (coinLoopCount == kMaxCoinLoopCount) {
2255 start1s = sect1->fHead->fStartT;
2256 start1e = sect1->tail()->fEndT;
2257 }
caryclarkef7cee42016-09-06 09:05:54 -07002258 if (!sect1->coincidentCheck(sect2)) {
2259 return;
2260 }
caryclark54359292015-03-26 07:52:43 -07002261 sect1->validate();
2262 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002263#if DEBUG_T_SECT_LOOP_COUNT
2264 intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop);
2265#endif
caryclarkef784fb2015-10-30 12:03:06 -07002266 if (!--coinLoopCount && sect1->fHead && sect2->fHead) {
caryclark26ad22a2015-10-16 09:03:38 -07002267 /* All known working cases resolve in two tries. Sadly, cubicConicTests[0]
2268 gets stuck in a loop. It adds an extension to allow a coincident end
2269 perpendicular to track its intersection in the opposite curve. However,
2270 the bounding box of the extension does not intersect the original curve,
caryclark55888e42016-07-18 10:01:36 -07002271 so the extension is discarded, only to be added again the next time around. */
caryclark26ad22a2015-10-16 09:03:38 -07002272 sect1->coincidentForce(sect2, start1s, start1e);
2273 sect1->validate();
2274 sect2->validate();
2275 }
caryclark45fa4472015-01-16 07:04:10 -08002276 }
caryclark54359292015-03-26 07:52:43 -07002277 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
2278 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
Cary Clark59ed4822016-12-08 16:17:56 -05002279 if (!sect1->fHead) {
2280 return;
2281 }
caryclark54359292015-03-26 07:52:43 -07002282 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail());
Cary Clark59ed4822016-12-08 16:17:56 -05002283 if (!sect2->fHead) {
2284 return;
2285 }
caryclark54359292015-03-26 07:52:43 -07002286 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail());
Cary Clark0949bee2018-03-19 09:42:00 -04002287 if (!sect1->removeByPerpendicular(sect2)) {
2288 return;
2289 }
caryclark54359292015-03-26 07:52:43 -07002290 sect1->validate();
2291 sect2->validate();
caryclark26ad22a2015-10-16 09:03:38 -07002292#if DEBUG_T_SECT_LOOP_COUNT
2293 intersections->debugBumpLoopCount(SkIntersections::kComputePerp_DebugLoop);
2294#endif
caryclark1049f122015-04-20 08:31:59 -07002295 if (sect1->collapsed() > TCurve::kMaxIntersections) {
2296 break;
2297 }
caryclark54359292015-03-26 07:52:43 -07002298 }
2299#if DEBUG_T_SECT_DUMP
2300 sect1->dumpBoth(sect2);
caryclark45fa4472015-01-16 07:04:10 -08002301#endif
2302 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002303 break;
caryclark45fa4472015-01-16 07:04:10 -08002304 }
2305 } while (true);
caryclark1049f122015-04-20 08:31:59 -07002306 SkTSpan<TCurve, OppCurve>* coincident = sect1->fCoincident;
caryclark54359292015-03-26 07:52:43 -07002307 if (coincident) {
2308 // if there is more than one coincident span, check loosely to see if they should be joined
2309 if (coincident->fNext) {
2310 sect1->mergeCoincidence(sect2);
2311 coincident = sect1->fCoincident;
2312 }
2313 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1
caryclark45fa4472015-01-16 07:04:10 -08002314 do {
caryclark221a4bb2016-10-07 11:15:15 -07002315 if (!coincident) {
2316 return;
2317 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002318 if (!coincident->fCoinStart.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002319 continue;
2320 }
caryclark6c3b9cd2016-09-26 05:36:58 -07002321 if (!coincident->fCoinEnd.isMatch()) {
caryclarkef784fb2015-10-30 12:03:06 -07002322 continue;
2323 }
Cary Clark67116382017-01-03 16:25:18 -05002324 double perpT = coincident->fCoinStart.perpT();
2325 if (perpT < 0) {
2326 return;
2327 }
caryclark54359292015-03-26 07:52:43 -07002328 int index = intersections->insertCoincident(coincident->fStartT,
Cary Clark67116382017-01-03 16:25:18 -05002329 perpT, coincident->fPart[0]);
caryclark54359292015-03-26 07:52:43 -07002330 if ((intersections->insertCoincident(coincident->fEndT,
2331 coincident->fCoinEnd.perpT(),
2332 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) {
caryclark45fa4472015-01-16 07:04:10 -08002333 intersections->clearCoincidence(index);
2334 }
caryclark54359292015-03-26 07:52:43 -07002335 } while ((coincident = coincident->fNext));
2336 }
caryclark1049f122015-04-20 08:31:59 -07002337 int zeroOneSet = EndsEqual(sect1, sect2, intersections);
caryclark34efb702016-10-24 08:19:06 -07002338// if (!sect1->fHead || !sect2->fHead) {
caryclark6c3b9cd2016-09-26 05:36:58 -07002339 // if the final iteration contains an end (0 or 1),
2340 if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) {
2341 SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular with opposite curve
caryclarka35ab3e2016-10-20 08:32:18 -07002342 perp.setPerp(sect1->fCurve, 0, sect1->fCurve[0], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002343 if (perp.isMatch()) {
2344 intersections->insert(0, perp.perpT(), perp.perpPt());
2345 }
2346 }
2347 if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) {
2348 SkTCoincident<TCurve, OppCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002349 perp.setPerp(sect1->fCurve, 1, sect1->fCurve[TCurve::kPointLast], sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002350 if (perp.isMatch()) {
2351 intersections->insert(1, perp.perpT(), perp.perpPt());
2352 }
2353 }
2354 if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) {
2355 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002356 perp.setPerp(sect2->fCurve, 0, sect2->fCurve[0], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002357 if (perp.isMatch()) {
2358 intersections->insert(perp.perpT(), 0, perp.perpPt());
2359 }
2360 }
2361 if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) {
2362 SkTCoincident<OppCurve, TCurve> perp;
caryclarka35ab3e2016-10-20 08:32:18 -07002363 perp.setPerp(sect2->fCurve, 1, sect2->fCurve[OppCurve::kPointLast], sect1->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002364 if (perp.isMatch()) {
2365 intersections->insert(perp.perpT(), 1, perp.perpPt());
2366 }
2367 }
caryclark34efb702016-10-24 08:19:06 -07002368// }
2369 if (!sect1->fHead || !sect2->fHead) {
caryclark54359292015-03-26 07:52:43 -07002370 return;
caryclark45fa4472015-01-16 07:04:10 -08002371 }
caryclark45fa4472015-01-16 07:04:10 -08002372 sect1->recoverCollapsed();
2373 sect2->recoverCollapsed();
caryclark1049f122015-04-20 08:31:59 -07002374 SkTSpan<TCurve, OppCurve>* result1 = sect1->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002375 // check heads and tails for zero and ones and insert them if we haven't already done so
caryclark1049f122015-04-20 08:31:59 -07002376 const SkTSpan<TCurve, OppCurve>* head1 = result1;
caryclark45fa4472015-01-16 07:04:10 -08002377 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStartT)) {
2378 const SkDPoint& start1 = sect1->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002379 if (head1->isBounded()) {
2380 double t = head1->closestBoundedT(start1);
2381 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) {
2382 intersections->insert(0, t, start1);
2383 }
caryclark45fa4472015-01-16 07:04:10 -08002384 }
2385 }
caryclark1049f122015-04-20 08:31:59 -07002386 const SkTSpan<OppCurve, TCurve>* head2 = sect2->fHead;
caryclark45fa4472015-01-16 07:04:10 -08002387 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStartT)) {
2388 const SkDPoint& start2 = sect2->fCurve[0];
caryclark54359292015-03-26 07:52:43 -07002389 if (head2->isBounded()) {
2390 double t = head2->closestBoundedT(start2);
2391 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) {
2392 intersections->insert(t, 0, start2);
2393 }
caryclark45fa4472015-01-16 07:04:10 -08002394 }
2395 }
caryclark1049f122015-04-20 08:31:59 -07002396 const SkTSpan<TCurve, OppCurve>* tail1 = sect1->tail();
caryclark45fa4472015-01-16 07:04:10 -08002397 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT)) {
2398 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002399 if (tail1->isBounded()) {
2400 double t = tail1->closestBoundedT(end1);
2401 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) {
2402 intersections->insert(1, t, end1);
2403 }
caryclark45fa4472015-01-16 07:04:10 -08002404 }
2405 }
caryclark1049f122015-04-20 08:31:59 -07002406 const SkTSpan<OppCurve, TCurve>* tail2 = sect2->tail();
caryclark45fa4472015-01-16 07:04:10 -08002407 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT)) {
caryclark1049f122015-04-20 08:31:59 -07002408 const SkDPoint& end2 = sect2->fCurve[OppCurve::kPointLast];
caryclark54359292015-03-26 07:52:43 -07002409 if (tail2->isBounded()) {
2410 double t = tail2->closestBoundedT(end2);
2411 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
2412 intersections->insert(t, 1, end2);
2413 }
caryclark45fa4472015-01-16 07:04:10 -08002414 }
2415 }
caryclark1049f122015-04-20 08:31:59 -07002416 SkClosestSect<TCurve, OppCurve> closest;
caryclark45fa4472015-01-16 07:04:10 -08002417 do {
caryclark6c3b9cd2016-09-26 05:36:58 -07002418 while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) {
caryclark45fa4472015-01-16 07:04:10 -08002419 result1 = result1->fNext;
2420 }
2421 if (!result1) {
2422 break;
2423 }
caryclark1049f122015-04-20 08:31:59 -07002424 SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead;
caryclark54359292015-03-26 07:52:43 -07002425 bool found = false;
caryclark45fa4472015-01-16 07:04:10 -08002426 while (result2) {
caryclarkcdeff812016-07-22 03:34:19 -07002427 found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections));
caryclark45fa4472015-01-16 07:04:10 -08002428 result2 = result2->fNext;
2429 }
caryclark45fa4472015-01-16 07:04:10 -08002430 } while ((result1 = result1->fNext));
2431 closest.finish(intersections);
caryclark54359292015-03-26 07:52:43 -07002432 // if there is more than one intersection and it isn't already coincident, check
2433 int last = intersections->used() - 1;
2434 for (int index = 0; index < last; ) {
2435 if (intersections->isCoincident(index) && intersections->isCoincident(index + 1)) {
2436 ++index;
2437 continue;
2438 }
2439 double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
2440 SkDPoint midPt = sect1->fCurve.ptAtT(midT);
2441 // intersect perpendicular with opposite curve
caryclark1049f122015-04-20 08:31:59 -07002442 SkTCoincident<TCurve, OppCurve> perp;
caryclark54359292015-03-26 07:52:43 -07002443 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
caryclark6c3b9cd2016-09-26 05:36:58 -07002444 if (!perp.isMatch()) {
caryclark54359292015-03-26 07:52:43 -07002445 ++index;
2446 continue;
2447 }
2448 if (intersections->isCoincident(index)) {
2449 intersections->removeOne(index);
2450 --last;
2451 } else if (intersections->isCoincident(index + 1)) {
2452 intersections->removeOne(index + 1);
2453 --last;
2454 } else {
2455 intersections->setCoincident(index++);
2456 }
2457 intersections->setCoincident(index);
2458 }
caryclarka35ab3e2016-10-20 08:32:18 -07002459 SkOPOBJASSERT(intersections, intersections->used() <= TCurve::kMaxIntersections);
caryclark45fa4472015-01-16 07:04:10 -08002460}
deanm12670eb2016-04-26 14:09:01 -07002461
2462#endif