blob: 6b7a2f9ea0cf7bd3018326c687fa54d1dab8c5eb [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"
Cary Clark8762fb62018-10-16 16:06:24 -040015#include "SkPathOpsTCurve.h"
caryclark54359292015-03-26 07:52:43 -070016#include "SkTSort.h"
caryclark45fa4472015-01-16 07:04:10 -080017
Ben Wagnerf08d1d02018-06-18 15:11:00 -040018#include <utility>
19
caryclarked0935a2015-10-22 07:23:52 -070020#ifdef SK_DEBUG
21typedef uint8_t SkOpDebugBool;
22#else
23typedef bool SkOpDebugBool;
24#endif
25
Cary Clark0949bee2018-03-19 09:42:00 -040026static inline bool SkDoubleIsNaN(double x) {
27 return x != x;
28}
29
caryclark45fa4472015-01-16 07:04:10 -080030class SkTCoincident {
31public:
caryclark697ac1c2015-04-13 09:36:01 -070032 SkTCoincident() {
caryclarkdf386c52015-04-21 05:27:02 -070033 this->init();
caryclark1049f122015-04-20 08:31:59 -070034 }
35
caryclarked0935a2015-10-22 07:23:52 -070036 void debugInit() {
37#ifdef SK_DEBUG
38 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
39 this->fPerpT = SK_ScalarNaN;
caryclark6c3b9cd2016-09-26 05:36:58 -070040 this->fMatch = 0xFF;
caryclarked0935a2015-10-22 07:23:52 -070041#endif
42 }
43
44 char dumpIsCoincidentStr() const;
caryclark1049f122015-04-20 08:31:59 -070045 void dump() const;
46
caryclark6c3b9cd2016-09-26 05:36:58 -070047 bool isMatch() const {
48 SkASSERT(!!fMatch == fMatch);
49 return SkToBool(fMatch);
caryclark45fa4472015-01-16 07:04:10 -080050 }
51
52 void init() {
caryclarkdf386c52015-04-21 05:27:02 -070053 fPerpT = -1;
caryclark6c3b9cd2016-09-26 05:36:58 -070054 fMatch = false;
caryclarkdf386c52015-04-21 05:27:02 -070055 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
caryclark45fa4472015-01-16 07:04:10 -080056 }
57
58 void markCoincident() {
caryclark6c3b9cd2016-09-26 05:36:58 -070059 if (!fMatch) {
caryclark45fa4472015-01-16 07:04:10 -080060 fPerpT = -1;
61 }
caryclark6c3b9cd2016-09-26 05:36:58 -070062 fMatch = true;
caryclark45fa4472015-01-16 07:04:10 -080063 }
64
65 const SkDPoint& perpPt() const {
66 return fPerpPt;
67 }
68
69 double perpT() const {
70 return fPerpT;
71 }
72
Cary Clark8762fb62018-10-16 16:06:24 -040073 void setPerp(const SkTCurve& c1, double t, const SkDPoint& cPt, const SkTCurve& );
caryclark45fa4472015-01-16 07:04:10 -080074
75private:
76 SkDPoint fPerpPt;
77 double fPerpT; // perpendicular intersection on opposite curve
caryclark6c3b9cd2016-09-26 05:36:58 -070078 SkOpDebugBool fMatch;
caryclark45fa4472015-01-16 07:04:10 -080079};
80
Cary Clark8762fb62018-10-16 16:06:24 -040081class SkTSect;
82class SkTSpan;
caryclark54359292015-03-26 07:52:43 -070083
caryclark54359292015-03-26 07:52:43 -070084struct SkTSpanBounded {
Cary Clark8762fb62018-10-16 16:06:24 -040085 SkTSpan* fBounded;
caryclark54359292015-03-26 07:52:43 -070086 SkTSpanBounded* fNext;
87};
caryclark45fa4472015-01-16 07:04:10 -080088
caryclark45fa4472015-01-16 07:04:10 -080089class SkTSpan {
90public:
Cary Clark8762fb62018-10-16 16:06:24 -040091 SkTSpan(const SkTCurve& curve, SkArenaAlloc& heap) {
Cary Clark0a671982018-10-11 12:16:49 -040092 fPart = curve.make(heap);
Cary Clark0a671982018-10-11 12:16:49 -040093 }
94
Cary Clark8762fb62018-10-16 16:06:24 -040095 void addBounded(SkTSpan* , 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
Cary Clark8762fb62018-10-16 16:06:24 -040099 void debugInit(const SkTCurve& curve, SkArenaAlloc& heap) {
100#ifdef SK_DEBUG
101 SkTCurve* dummy = curve.make(heap);
102 dummy->debugInit();
103 init(*dummy);
104 initBounds(*dummy);
caryclarkdf386c52015-04-21 05:27:02 -0700105 fCoinStart.init();
106 fCoinEnd.init();
Cary Clark0a671982018-10-11 12:16:49 -0400107#endif
caryclark1049f122015-04-20 08:31:59 -0700108 }
109
Cary Clark8762fb62018-10-16 16:06:24 -0400110 const SkTSect* debugOpp() const;
caryclark643ede62016-08-08 14:27:45 -0700111
112#ifdef SK_DEBUG
113 void debugSetGlobalState(SkOpGlobalState* state) {
114 fDebugGlobalState = state;
115 }
caryclark643ede62016-08-08 14:27:45 -0700116
caryclark54359292015-03-26 07:52:43 -0700117 const SkTSpan* debugSpan(int ) const;
118 const SkTSpan* debugT(double t) const;
caryclark54359292015-03-26 07:52:43 -0700119 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
Cary Clark8762fb62018-10-16 16:06:24 -0400131 SkTSpan* findOppSpan(const SkTSpan* opp) const;
caryclark54359292015-03-26 07:52:43 -0700132
Cary Clark8762fb62018-10-16 16:06:24 -0400133 SkTSpan* findOppT(double t) const {
134 SkTSpan* 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
Cary Clark8762fb62018-10-16 16:06:24 -0400145 int hullsIntersect(SkTSpan* span, bool* start, bool* oppStart);
146 void init(const SkTCurve& );
147 bool initBounds(const SkTCurve& );
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
Cary Clark8762fb62018-10-16 16:06:24 -0400153 bool linearsIntersect(SkTSpan* 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
Cary Clark8762fb62018-10-16 16:06:24 -0400165 bool onlyEndPointsInCommon(const SkTSpan* opp, bool* start,
caryclark1049f122015-04-20 08:31:59 -0700166 bool* oppStart, bool* ptsInCommon);
caryclark54359292015-03-26 07:52:43 -0700167
Cary Clark8762fb62018-10-16 16:06:24 -0400168 const SkTCurve& part() const {
Cary Clark0a671982018-10-11 12:16:49 -0400169 return *fPart;
Cary Clark0a671982018-10-11 12:16:49 -0400170 }
171
Cary Clark8762fb62018-10-16 16:06:24 -0400172 int pointCount() const {
173 return fPart->pointCount();
174 }
175
176 const SkDPoint& pointFirst() const {
177 return (*fPart)[0];
178 }
179
180 const SkDPoint& pointLast() const {
181 return (*fPart)[fPart->pointLast()];
caryclark45fa4472015-01-16 07:04:10 -0800182 }
183
caryclark54359292015-03-26 07:52:43 -0700184 bool removeAllBounded();
Cary Clark8762fb62018-10-16 16:06:24 -0400185 bool removeBounded(const SkTSpan* opp);
caryclark54359292015-03-26 07:52:43 -0700186
caryclark45fa4472015-01-16 07:04:10 -0800187 void reset() {
halcanary96fcdcc2015-08-27 07:41:13 -0700188 fBounded = nullptr;
caryclark45fa4472015-01-16 07:04:10 -0800189 }
190
Cary Clark8762fb62018-10-16 16:06:24 -0400191 void resetBounds(const SkTCurve& curve) {
caryclark54359292015-03-26 07:52:43 -0700192 fIsLinear = fIsLine = false;
193 initBounds(curve);
caryclark45fa4472015-01-16 07:04:10 -0800194 }
195
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500196 bool split(SkTSpan* work, SkArenaAlloc* heap) {
caryclark54359292015-03-26 07:52:43 -0700197 return splitAt(work, (work->fStartT + work->fEndT) * 0.5, heap);
198 }
199
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500200 bool splitAt(SkTSpan* work, double t, SkArenaAlloc* heap);
caryclark45fa4472015-01-16 07:04:10 -0800201
202 double startT() const {
203 return fStartT;
204 }
205
caryclark54359292015-03-26 07:52:43 -0700206private:
caryclark45fa4472015-01-16 07:04:10 -0800207
208 // implementation is for testing only
caryclark54359292015-03-26 07:52:43 -0700209 int debugID() const {
210 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
caryclark45fa4472015-01-16 07:04:10 -0800211 }
212
caryclark54359292015-03-26 07:52:43 -0700213 void dumpID() const;
caryclark45fa4472015-01-16 07:04:10 -0800214
Cary Clark8762fb62018-10-16 16:06:24 -0400215 int hullCheck(const SkTSpan* opp, bool* start, bool* oppStart);
216 int linearIntersects(const SkTCurve& ) const;
217 SkTSpan* oppT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800218
caryclark45fa4472015-01-16 07:04:10 -0800219 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700220 void validateBounded() const;
221 void validatePerpT(double oppT) const;
222 void validatePerpPt(double t, const SkDPoint& ) const;
caryclark45fa4472015-01-16 07:04:10 -0800223
Cary Clark8762fb62018-10-16 16:06:24 -0400224 SkTCurve* fPart;
225 SkTCoincident fCoinStart;
226 SkTCoincident fCoinEnd;
227 SkTSpanBounded* fBounded;
caryclark45fa4472015-01-16 07:04:10 -0800228 SkTSpan* fPrev;
229 SkTSpan* fNext;
230 SkDRect fBounds;
231 double fStartT;
232 double fEndT;
233 double fBoundsMax;
caryclarked0935a2015-10-22 07:23:52 -0700234 SkOpDebugBool fCollapsed;
235 SkOpDebugBool fHasPerp;
236 SkOpDebugBool fIsLinear;
237 SkOpDebugBool fIsLine;
238 SkOpDebugBool fDeleted;
caryclark643ede62016-08-08 14:27:45 -0700239 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
Cary Clark8762fb62018-10-16 16:06:24 -0400240 SkDEBUGCODE(SkTSect* fDebugSect);
caryclark54359292015-03-26 07:52:43 -0700241 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
Cary Clark8762fb62018-10-16 16:06:24 -0400242 friend class SkTSect;
caryclark45fa4472015-01-16 07:04:10 -0800243};
244
caryclark45fa4472015-01-16 07:04:10 -0800245class SkTSect {
246public:
Cary Clark8762fb62018-10-16 16:06:24 -0400247 SkTSect(const SkTCurve& c
248 SkDEBUGPARAMS(SkOpGlobalState* ) PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
249 static void BinarySearch(SkTSect* sect1, SkTSect* sect2,
caryclark1049f122015-04-20 08:31:59 -0700250 SkIntersections* intersections);
caryclark45fa4472015-01-16 07:04:10 -0800251
caryclarke25a4f62016-07-26 09:26:29 -0700252 SkDEBUGCODE(SkOpGlobalState* globalState() { return fDebugGlobalState; })
Cary Clark8762fb62018-10-16 16:06:24 -0400253 bool hasBounded(const SkTSpan* ) const;
caryclark54359292015-03-26 07:52:43 -0700254
Cary Clark8762fb62018-10-16 16:06:24 -0400255 const SkTSect* debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700256 return SkDEBUGRELEASE(fOppSect, nullptr);
caryclark54359292015-03-26 07:52:43 -0700257 }
258
Cary Clark8762fb62018-10-16 16:06:24 -0400259#ifdef SK_DEBUG
260 const SkTSpan* debugSpan(int id) const;
261 const SkTSpan* debugT(double t) const;
262#endif
caryclark45fa4472015-01-16 07:04:10 -0800263 void dump() const;
Cary Clark8762fb62018-10-16 16:06:24 -0400264 void dumpBoth(SkTSect* ) const;
caryclark1049f122015-04-20 08:31:59 -0700265 void dumpBounded(int id) const;
266 void dumpBounds() const;
caryclark54359292015-03-26 07:52:43 -0700267 void dumpCoin() const;
268 void dumpCoinCurves() const;
caryclark45fa4472015-01-16 07:04:10 -0800269 void dumpCurves() const;
270
271private:
272 enum {
273 kZeroS1Set = 1,
274 kOneS1Set = 2,
275 kZeroS2Set = 4,
276 kOneS2Set = 8
277 };
278
Cary Clark8762fb62018-10-16 16:06:24 -0400279 SkTSpan* addFollowing(SkTSpan* prior);
280 void addForPerp(SkTSpan* span, double t);
281 SkTSpan* addOne();
caryclark55888e42016-07-18 10:01:36 -0700282
Cary Clark8762fb62018-10-16 16:06:24 -0400283 SkTSpan* addSplitAt(SkTSpan* span, double t) {
284 SkTSpan* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700285 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700286 result->splitAt(span, t, &fHeap);
287 result->initBounds(fCurve);
288 span->initBounds(fCurve);
289 return result;
290 }
291
Cary Clark8762fb62018-10-16 16:06:24 -0400292 bool binarySearchCoin(SkTSect* , double tStart, double tStep, double* t,
293 double* oppT, SkTSpan** oppFirst);
294 SkTSpan* boundsMax();
295 bool coincidentCheck(SkTSect* sect2);
296 void coincidentForce(SkTSect* sect2, double start1s, double start1e);
caryclark54359292015-03-26 07:52:43 -0700297 bool coincidentHasT(double t);
caryclark1049f122015-04-20 08:31:59 -0700298 int collapsed() const;
Cary Clark8762fb62018-10-16 16:06:24 -0400299 void computePerpendiculars(SkTSect* sect2, SkTSpan* first,
300 SkTSpan* last);
301 int countConsecutiveSpans(SkTSpan* first,
302 SkTSpan** last) const;
caryclarkccec0f92015-03-24 07:28:17 -0700303
caryclark54359292015-03-26 07:52:43 -0700304 int debugID() const {
305 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
306 }
307
caryclarkef7cee42016-09-06 09:05:54 -0700308 bool deleteEmptySpans();
Cary Clark8762fb62018-10-16 16:06:24 -0400309 void dumpCommon(const SkTSpan* ) const;
310 void dumpCommonCurves(const SkTSpan* ) const;
311 static int EndsEqual(const SkTSect* sect1, const SkTSect* sect2,
caryclark1049f122015-04-20 08:31:59 -0700312 SkIntersections* );
Cary Clark8762fb62018-10-16 16:06:24 -0400313 bool extractCoincident(SkTSect* sect2, SkTSpan* first,
314 SkTSpan* last, SkTSpan** result);
315 SkTSpan* findCoincidentRun(SkTSpan* first, SkTSpan** lastPtr);
316 int intersects(SkTSpan* span, SkTSect* opp,
317 SkTSpan* oppSpan, int* oppResult);
318 bool isParallel(const SkDLine& thisLine, const SkTSect* opp) const;
319 int linesIntersect(SkTSpan* span, SkTSect* opp,
320 SkTSpan* oppSpan, SkIntersections* );
321 bool markSpanGone(SkTSpan* span);
322 bool matchedDirection(double t, const SkTSect* sect2, double t2) const;
323 void matchedDirCheck(double t, const SkTSect* sect2, double t2,
caryclark54359292015-03-26 07:52:43 -0700324 bool* calcMatched, bool* oppMatched) const;
Cary Clark8762fb62018-10-16 16:06:24 -0400325 void mergeCoincidence(SkTSect* sect2);
326
327 const SkDPoint& pointLast() const {
328 return fCurve[fCurve.pointLast()];
329 }
330
331 SkTSpan* prev(SkTSpan* ) const;
332 bool removeByPerpendicular(SkTSect* opp);
caryclark54359292015-03-26 07:52:43 -0700333 void recoverCollapsed();
Cary Clark8762fb62018-10-16 16:06:24 -0400334 bool removeCoincident(SkTSpan* span, bool isBetween);
335 void removeAllBut(const SkTSpan* keep, SkTSpan* span,
336 SkTSect* opp);
337 bool removeSpan(SkTSpan* span);
338 void removeSpanRange(SkTSpan* first, SkTSpan* last);
339 bool removeSpans(SkTSpan* span, SkTSect* opp);
340 void removedEndCheck(SkTSpan* span);
caryclark34efb702016-10-24 08:19:06 -0700341
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500342 void resetRemovedEnds() {
caryclark34efb702016-10-24 08:19:06 -0700343 fRemovedStartT = fRemovedEndT = false;
344 }
345
Cary Clark8762fb62018-10-16 16:06:24 -0400346 SkTSpan* spanAtT(double t, SkTSpan** priorSpan);
347 SkTSpan* tail();
348 bool trim(SkTSpan* span, SkTSect* opp);
349 bool unlinkSpan(SkTSpan* span);
350 bool updateBounded(SkTSpan* first, SkTSpan* last,
351 SkTSpan* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700352 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700353 void validateBounded() const;
354
Cary Clark8762fb62018-10-16 16:06:24 -0400355 const SkTCurve& fCurve;
Mike Reed534e7762018-11-05 07:46:38 -0500356 SkSTArenaAlloc<1024> fHeap;
Cary Clark8762fb62018-10-16 16:06:24 -0400357 SkTSpan* fHead;
358 SkTSpan* fCoincident;
359 SkTSpan* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800360 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700361 bool fRemovedStartT;
362 bool fRemovedEndT;
Cary Clark5de52332018-08-30 12:58:23 -0400363 bool fHung;
caryclarke25a4f62016-07-26 09:26:29 -0700364 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
Cary Clark8762fb62018-10-16 16:06:24 -0400365 SkDEBUGCODE(SkTSect* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700366 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
367 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800368#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800369 int fDebugAllocatedCount;
370#endif
Cary Clark8762fb62018-10-16 16:06:24 -0400371 friend class SkTSpan;
caryclark45fa4472015-01-16 07:04:10 -0800372};
373
deanm12670eb2016-04-26 14:09:01 -0700374#endif