blob: 4d84e3db6710e4da549c7a9ac913eb7913de1199 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/private/SkMacros.h"
Ben Wagner729a23f2019-05-17 16:29:34 -040011#include "src/core/SkArenaAlloc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/pathops/SkIntersections.h"
13#include "src/pathops/SkPathOpsBounds.h"
14#include "src/pathops/SkPathOpsRect.h"
15#include "src/pathops/SkPathOpsTCurve.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
caryclark45fa4472015-01-16 07:04:10 -080029class SkTCoincident {
30public:
caryclark697ac1c2015-04-13 09:36:01 -070031 SkTCoincident() {
caryclarkdf386c52015-04-21 05:27:02 -070032 this->init();
caryclark1049f122015-04-20 08:31:59 -070033 }
34
caryclarked0935a2015-10-22 07:23:52 -070035 void debugInit() {
36#ifdef SK_DEBUG
37 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
38 this->fPerpT = SK_ScalarNaN;
caryclark6c3b9cd2016-09-26 05:36:58 -070039 this->fMatch = 0xFF;
caryclarked0935a2015-10-22 07:23:52 -070040#endif
41 }
42
43 char dumpIsCoincidentStr() const;
caryclark1049f122015-04-20 08:31:59 -070044 void dump() const;
45
caryclark6c3b9cd2016-09-26 05:36:58 -070046 bool isMatch() const {
47 SkASSERT(!!fMatch == fMatch);
48 return SkToBool(fMatch);
caryclark45fa4472015-01-16 07:04:10 -080049 }
50
51 void init() {
caryclarkdf386c52015-04-21 05:27:02 -070052 fPerpT = -1;
caryclark6c3b9cd2016-09-26 05:36:58 -070053 fMatch = false;
caryclarkdf386c52015-04-21 05:27:02 -070054 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
caryclark45fa4472015-01-16 07:04:10 -080055 }
56
57 void markCoincident() {
caryclark6c3b9cd2016-09-26 05:36:58 -070058 if (!fMatch) {
caryclark45fa4472015-01-16 07:04:10 -080059 fPerpT = -1;
60 }
caryclark6c3b9cd2016-09-26 05:36:58 -070061 fMatch = true;
caryclark45fa4472015-01-16 07:04:10 -080062 }
63
64 const SkDPoint& perpPt() const {
65 return fPerpPt;
66 }
67
68 double perpT() const {
69 return fPerpT;
70 }
71
Cary Clark8762fb62018-10-16 16:06:24 -040072 void setPerp(const SkTCurve& c1, double t, const SkDPoint& cPt, const SkTCurve& );
caryclark45fa4472015-01-16 07:04:10 -080073
74private:
75 SkDPoint fPerpPt;
76 double fPerpT; // perpendicular intersection on opposite curve
caryclark6c3b9cd2016-09-26 05:36:58 -070077 SkOpDebugBool fMatch;
caryclark45fa4472015-01-16 07:04:10 -080078};
79
Cary Clark8762fb62018-10-16 16:06:24 -040080class SkTSect;
81class SkTSpan;
caryclark54359292015-03-26 07:52:43 -070082
caryclark54359292015-03-26 07:52:43 -070083struct SkTSpanBounded {
Cary Clark8762fb62018-10-16 16:06:24 -040084 SkTSpan* fBounded;
caryclark54359292015-03-26 07:52:43 -070085 SkTSpanBounded* fNext;
86};
caryclark45fa4472015-01-16 07:04:10 -080087
caryclark45fa4472015-01-16 07:04:10 -080088class SkTSpan {
89public:
Cary Clark8762fb62018-10-16 16:06:24 -040090 SkTSpan(const SkTCurve& curve, SkArenaAlloc& heap) {
Cary Clark0a671982018-10-11 12:16:49 -040091 fPart = curve.make(heap);
Cary Clark0a671982018-10-11 12:16:49 -040092 }
93
Cary Clark8762fb62018-10-16 16:06:24 -040094 void addBounded(SkTSpan* , SkArenaAlloc* );
reed0dc4dd62015-03-24 13:55:33 -070095 double closestBoundedT(const SkDPoint& pt) const;
caryclark54359292015-03-26 07:52:43 -070096 bool contains(double t) const;
reed0dc4dd62015-03-24 13:55:33 -070097
Cary Clark8762fb62018-10-16 16:06:24 -040098 void debugInit(const SkTCurve& curve, SkArenaAlloc& heap) {
99#ifdef SK_DEBUG
Leon Scroggins III577536a2020-07-31 13:47:50 -0400100 SkTCurve* fake = curve.make(heap);
101 fake->debugInit();
102 init(*fake);
103 initBounds(*fake);
caryclarkdf386c52015-04-21 05:27:02 -0700104 fCoinStart.init();
105 fCoinEnd.init();
Cary Clark0a671982018-10-11 12:16:49 -0400106#endif
caryclark1049f122015-04-20 08:31:59 -0700107 }
108
Cary Clark8762fb62018-10-16 16:06:24 -0400109 const SkTSect* debugOpp() const;
caryclark643ede62016-08-08 14:27:45 -0700110
111#ifdef SK_DEBUG
112 void debugSetGlobalState(SkOpGlobalState* state) {
113 fDebugGlobalState = state;
114 }
caryclark643ede62016-08-08 14:27:45 -0700115
caryclark54359292015-03-26 07:52:43 -0700116 const SkTSpan* debugSpan(int ) const;
117 const SkTSpan* debugT(double t) const;
caryclark54359292015-03-26 07:52:43 -0700118 bool debugIsBefore(const SkTSpan* span) const;
119#endif
120 void dump() const;
caryclark26ad22a2015-10-16 09:03:38 -0700121 void dumpAll() const;
caryclark1049f122015-04-20 08:31:59 -0700122 void dumpBounded(int id) const;
123 void dumpBounds() const;
124 void dumpCoin() const;
caryclark45fa4472015-01-16 07:04:10 -0800125
126 double endT() const {
127 return fEndT;
128 }
129
Cary Clark8762fb62018-10-16 16:06:24 -0400130 SkTSpan* findOppSpan(const SkTSpan* opp) const;
caryclark54359292015-03-26 07:52:43 -0700131
Cary Clark8762fb62018-10-16 16:06:24 -0400132 SkTSpan* findOppT(double t) const {
133 SkTSpan* result = oppT(t);
caryclark643ede62016-08-08 14:27:45 -0700134 SkOPASSERT(result);
caryclark45fa4472015-01-16 07:04:10 -0800135 return result;
136 }
137
caryclark643ede62016-08-08 14:27:45 -0700138 SkDEBUGCODE(SkOpGlobalState* globalState() const { return fDebugGlobalState; })
139
caryclark54359292015-03-26 07:52:43 -0700140 bool hasOppT(double t) const {
141 return SkToBool(oppT(t));
142 }
143
Cary Clark8762fb62018-10-16 16:06:24 -0400144 int hullsIntersect(SkTSpan* span, bool* start, bool* oppStart);
145 void init(const SkTCurve& );
146 bool initBounds(const SkTCurve& );
caryclark54359292015-03-26 07:52:43 -0700147
148 bool isBounded() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700149 return fBounded != nullptr;
caryclark54359292015-03-26 07:52:43 -0700150 }
151
Cary Clark8762fb62018-10-16 16:06:24 -0400152 bool linearsIntersect(SkTSpan* span);
caryclark54359292015-03-26 07:52:43 -0700153 double linearT(const SkDPoint& ) const;
154
155 void markCoincident() {
156 fCoinStart.markCoincident();
157 fCoinEnd.markCoincident();
158 }
caryclark45fa4472015-01-16 07:04:10 -0800159
160 const SkTSpan* next() const {
161 return fNext;
162 }
163
Cary Clark8762fb62018-10-16 16:06:24 -0400164 bool onlyEndPointsInCommon(const SkTSpan* opp, bool* start,
caryclark1049f122015-04-20 08:31:59 -0700165 bool* oppStart, bool* ptsInCommon);
caryclark54359292015-03-26 07:52:43 -0700166
Cary Clark8762fb62018-10-16 16:06:24 -0400167 const SkTCurve& part() const {
Cary Clark0a671982018-10-11 12:16:49 -0400168 return *fPart;
Cary Clark0a671982018-10-11 12:16:49 -0400169 }
170
Cary Clark8762fb62018-10-16 16:06:24 -0400171 int pointCount() const {
172 return fPart->pointCount();
173 }
174
175 const SkDPoint& pointFirst() const {
176 return (*fPart)[0];
177 }
178
179 const SkDPoint& pointLast() const {
180 return (*fPart)[fPart->pointLast()];
caryclark45fa4472015-01-16 07:04:10 -0800181 }
182
caryclark54359292015-03-26 07:52:43 -0700183 bool removeAllBounded();
Cary Clark8762fb62018-10-16 16:06:24 -0400184 bool removeBounded(const SkTSpan* opp);
caryclark54359292015-03-26 07:52:43 -0700185
caryclark45fa4472015-01-16 07:04:10 -0800186 void reset() {
halcanary96fcdcc2015-08-27 07:41:13 -0700187 fBounded = nullptr;
caryclark45fa4472015-01-16 07:04:10 -0800188 }
189
Cary Clark8762fb62018-10-16 16:06:24 -0400190 void resetBounds(const SkTCurve& curve) {
caryclark54359292015-03-26 07:52:43 -0700191 fIsLinear = fIsLine = false;
192 initBounds(curve);
caryclark45fa4472015-01-16 07:04:10 -0800193 }
194
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500195 bool split(SkTSpan* work, SkArenaAlloc* heap) {
caryclark54359292015-03-26 07:52:43 -0700196 return splitAt(work, (work->fStartT + work->fEndT) * 0.5, heap);
197 }
198
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500199 bool splitAt(SkTSpan* work, double t, SkArenaAlloc* heap);
caryclark45fa4472015-01-16 07:04:10 -0800200
201 double startT() const {
202 return fStartT;
203 }
204
caryclark54359292015-03-26 07:52:43 -0700205private:
caryclark45fa4472015-01-16 07:04:10 -0800206
207 // implementation is for testing only
caryclark54359292015-03-26 07:52:43 -0700208 int debugID() const {
209 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
caryclark45fa4472015-01-16 07:04:10 -0800210 }
211
caryclark54359292015-03-26 07:52:43 -0700212 void dumpID() const;
caryclark45fa4472015-01-16 07:04:10 -0800213
Cary Clark8762fb62018-10-16 16:06:24 -0400214 int hullCheck(const SkTSpan* opp, bool* start, bool* oppStart);
215 int linearIntersects(const SkTCurve& ) const;
216 SkTSpan* oppT(double t) const;
caryclark45fa4472015-01-16 07:04:10 -0800217
caryclark45fa4472015-01-16 07:04:10 -0800218 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700219 void validateBounded() const;
220 void validatePerpT(double oppT) const;
221 void validatePerpPt(double t, const SkDPoint& ) const;
caryclark45fa4472015-01-16 07:04:10 -0800222
Cary Clark8762fb62018-10-16 16:06:24 -0400223 SkTCurve* fPart;
224 SkTCoincident fCoinStart;
225 SkTCoincident fCoinEnd;
226 SkTSpanBounded* fBounded;
caryclark45fa4472015-01-16 07:04:10 -0800227 SkTSpan* fPrev;
228 SkTSpan* fNext;
229 SkDRect fBounds;
230 double fStartT;
231 double fEndT;
232 double fBoundsMax;
caryclarked0935a2015-10-22 07:23:52 -0700233 SkOpDebugBool fCollapsed;
234 SkOpDebugBool fHasPerp;
235 SkOpDebugBool fIsLinear;
236 SkOpDebugBool fIsLine;
237 SkOpDebugBool fDeleted;
caryclark643ede62016-08-08 14:27:45 -0700238 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
Cary Clark8762fb62018-10-16 16:06:24 -0400239 SkDEBUGCODE(SkTSect* fDebugSect);
caryclark54359292015-03-26 07:52:43 -0700240 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
Cary Clark8762fb62018-10-16 16:06:24 -0400241 friend class SkTSect;
caryclark45fa4472015-01-16 07:04:10 -0800242};
243
caryclark45fa4472015-01-16 07:04:10 -0800244class SkTSect {
245public:
Cary Clark8762fb62018-10-16 16:06:24 -0400246 SkTSect(const SkTCurve& c
247 SkDEBUGPARAMS(SkOpGlobalState* ) PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
248 static void BinarySearch(SkTSect* sect1, SkTSect* sect2,
caryclark1049f122015-04-20 08:31:59 -0700249 SkIntersections* intersections);
caryclark45fa4472015-01-16 07:04:10 -0800250
caryclarke25a4f62016-07-26 09:26:29 -0700251 SkDEBUGCODE(SkOpGlobalState* globalState() { return fDebugGlobalState; })
Cary Clark8762fb62018-10-16 16:06:24 -0400252 bool hasBounded(const SkTSpan* ) const;
caryclark54359292015-03-26 07:52:43 -0700253
Cary Clark8762fb62018-10-16 16:06:24 -0400254 const SkTSect* debugOpp() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700255 return SkDEBUGRELEASE(fOppSect, nullptr);
caryclark54359292015-03-26 07:52:43 -0700256 }
257
Cary Clark8762fb62018-10-16 16:06:24 -0400258#ifdef SK_DEBUG
259 const SkTSpan* debugSpan(int id) const;
260 const SkTSpan* debugT(double t) const;
261#endif
caryclark45fa4472015-01-16 07:04:10 -0800262 void dump() const;
Cary Clark8762fb62018-10-16 16:06:24 -0400263 void dumpBoth(SkTSect* ) const;
caryclark1049f122015-04-20 08:31:59 -0700264 void dumpBounded(int id) const;
265 void dumpBounds() const;
caryclark54359292015-03-26 07:52:43 -0700266 void dumpCoin() const;
267 void dumpCoinCurves() const;
caryclark45fa4472015-01-16 07:04:10 -0800268 void dumpCurves() const;
269
270private:
271 enum {
272 kZeroS1Set = 1,
273 kOneS1Set = 2,
274 kZeroS2Set = 4,
275 kOneS2Set = 8
276 };
277
Cary Clark8762fb62018-10-16 16:06:24 -0400278 SkTSpan* addFollowing(SkTSpan* prior);
279 void addForPerp(SkTSpan* span, double t);
280 SkTSpan* addOne();
caryclark55888e42016-07-18 10:01:36 -0700281
Cary Clark8762fb62018-10-16 16:06:24 -0400282 SkTSpan* addSplitAt(SkTSpan* span, double t) {
283 SkTSpan* result = this->addOne();
caryclark643ede62016-08-08 14:27:45 -0700284 SkDEBUGCODE(result->debugSetGlobalState(this->globalState()));
caryclark54359292015-03-26 07:52:43 -0700285 result->splitAt(span, t, &fHeap);
286 result->initBounds(fCurve);
287 span->initBounds(fCurve);
288 return result;
289 }
290
Cary Clark8762fb62018-10-16 16:06:24 -0400291 bool binarySearchCoin(SkTSect* , double tStart, double tStep, double* t,
292 double* oppT, SkTSpan** oppFirst);
293 SkTSpan* boundsMax();
294 bool coincidentCheck(SkTSect* sect2);
295 void coincidentForce(SkTSect* sect2, double start1s, double start1e);
caryclark54359292015-03-26 07:52:43 -0700296 bool coincidentHasT(double t);
caryclark1049f122015-04-20 08:31:59 -0700297 int collapsed() const;
Cary Clark8762fb62018-10-16 16:06:24 -0400298 void computePerpendiculars(SkTSect* sect2, SkTSpan* first,
299 SkTSpan* last);
300 int countConsecutiveSpans(SkTSpan* first,
301 SkTSpan** last) const;
caryclarkccec0f92015-03-24 07:28:17 -0700302
caryclark54359292015-03-26 07:52:43 -0700303 int debugID() const {
304 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
305 }
306
caryclarkef7cee42016-09-06 09:05:54 -0700307 bool deleteEmptySpans();
Cary Clark8762fb62018-10-16 16:06:24 -0400308 void dumpCommon(const SkTSpan* ) const;
309 void dumpCommonCurves(const SkTSpan* ) const;
310 static int EndsEqual(const SkTSect* sect1, const SkTSect* sect2,
caryclark1049f122015-04-20 08:31:59 -0700311 SkIntersections* );
Cary Clark8762fb62018-10-16 16:06:24 -0400312 bool extractCoincident(SkTSect* sect2, SkTSpan* first,
313 SkTSpan* last, SkTSpan** result);
314 SkTSpan* findCoincidentRun(SkTSpan* first, SkTSpan** lastPtr);
315 int intersects(SkTSpan* span, SkTSect* opp,
316 SkTSpan* oppSpan, int* oppResult);
317 bool isParallel(const SkDLine& thisLine, const SkTSect* opp) const;
318 int linesIntersect(SkTSpan* span, SkTSect* opp,
319 SkTSpan* oppSpan, SkIntersections* );
320 bool markSpanGone(SkTSpan* span);
321 bool matchedDirection(double t, const SkTSect* sect2, double t2) const;
322 void matchedDirCheck(double t, const SkTSect* sect2, double t2,
caryclark54359292015-03-26 07:52:43 -0700323 bool* calcMatched, bool* oppMatched) const;
Cary Clark8762fb62018-10-16 16:06:24 -0400324 void mergeCoincidence(SkTSect* sect2);
325
326 const SkDPoint& pointLast() const {
327 return fCurve[fCurve.pointLast()];
328 }
329
330 SkTSpan* prev(SkTSpan* ) const;
331 bool removeByPerpendicular(SkTSect* opp);
caryclark54359292015-03-26 07:52:43 -0700332 void recoverCollapsed();
Cary Clark8762fb62018-10-16 16:06:24 -0400333 bool removeCoincident(SkTSpan* span, bool isBetween);
334 void removeAllBut(const SkTSpan* keep, SkTSpan* span,
335 SkTSect* opp);
336 bool removeSpan(SkTSpan* span);
337 void removeSpanRange(SkTSpan* first, SkTSpan* last);
338 bool removeSpans(SkTSpan* span, SkTSect* opp);
339 void removedEndCheck(SkTSpan* span);
caryclark34efb702016-10-24 08:19:06 -0700340
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500341 void resetRemovedEnds() {
caryclark34efb702016-10-24 08:19:06 -0700342 fRemovedStartT = fRemovedEndT = false;
343 }
344
Cary Clark8762fb62018-10-16 16:06:24 -0400345 SkTSpan* spanAtT(double t, SkTSpan** priorSpan);
346 SkTSpan* tail();
347 bool trim(SkTSpan* span, SkTSect* opp);
348 bool unlinkSpan(SkTSpan* span);
349 bool updateBounded(SkTSpan* first, SkTSpan* last,
350 SkTSpan* oppFirst);
reed0dc4dd62015-03-24 13:55:33 -0700351 void validate() const;
caryclark54359292015-03-26 07:52:43 -0700352 void validateBounded() const;
353
Cary Clark8762fb62018-10-16 16:06:24 -0400354 const SkTCurve& fCurve;
Mike Reed534e7762018-11-05 07:46:38 -0500355 SkSTArenaAlloc<1024> fHeap;
Cary Clark8762fb62018-10-16 16:06:24 -0400356 SkTSpan* fHead;
357 SkTSpan* fCoincident;
358 SkTSpan* fDeleted;
caryclark45fa4472015-01-16 07:04:10 -0800359 int fActiveCount;
caryclark6c3b9cd2016-09-26 05:36:58 -0700360 bool fRemovedStartT;
361 bool fRemovedEndT;
Cary Clark5de52332018-08-30 12:58:23 -0400362 bool fHung;
caryclarke25a4f62016-07-26 09:26:29 -0700363 SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
Cary Clark8762fb62018-10-16 16:06:24 -0400364 SkDEBUGCODE(SkTSect* fOppSect);
caryclark54359292015-03-26 07:52:43 -0700365 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
366 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
caryclark45fa4472015-01-16 07:04:10 -0800367#if DEBUG_T_SECT
caryclark45fa4472015-01-16 07:04:10 -0800368 int fDebugAllocatedCount;
369#endif
Cary Clark8762fb62018-10-16 16:06:24 -0400370 friend class SkTSpan;
caryclark45fa4472015-01-16 07:04:10 -0800371};
372
deanm12670eb2016-04-26 14:09:01 -0700373#endif