blob: e2188bebbdcf43e2a74b391890537c1480a6143c [file] [log] [blame]
caryclark45fa4472015-01-16 07:04:10 -08001/*
2 * Copyright 2013 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 */
7#ifndef SkOpCoincidence_DEFINED
8#define SkOpCoincidence_DEFINED
9
caryclark55888e42016-07-18 10:01:36 -070010#include "SkTDArray.h"
caryclark45fa4472015-01-16 07:04:10 -080011#include "SkOpTAllocator.h"
12#include "SkOpSpan.h"
caryclark27c8eb82015-07-06 11:38:33 -070013#include "SkPathOpsTypes.h"
caryclark45fa4472015-01-16 07:04:10 -080014
15class SkOpPtT;
caryclark55888e42016-07-18 10:01:36 -070016class SkOpSpanBase;
caryclark45fa4472015-01-16 07:04:10 -080017
caryclark55888e42016-07-18 10:01:36 -070018class SkCoincidentSpans {
19public:
20 const SkOpPtT* coinPtTEnd() const { return fCoinPtTEnd; }
21 const SkOpPtT* coinPtTStart() const { return fCoinPtTStart; }
22
23 // These return non-const pointers so that, as copies, they can be added
24 // to a new span pair
25 SkOpPtT* coinPtTEndWritable() const { return const_cast<SkOpPtT*>(fCoinPtTEnd); }
26 SkOpPtT* coinPtTStartWritable() const { return const_cast<SkOpPtT*>(fCoinPtTStart); }
27
28 bool collapsed(const SkOpPtT* ) const;
29 bool contains(const SkOpPtT* s, const SkOpPtT* e) const;
30 void correctEnds();
31 void correctOneEnd(const SkOpPtT* (SkCoincidentSpans::* getEnd)() const,
32 void (SkCoincidentSpans::* setEnd)(const SkOpPtT* ptT) );
33
Cary Clarkab87d7a2016-10-04 10:01:04 -040034#if DEBUG_COIN
35 void debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const;
36 void debugCorrectOneEnd(SkPathOpsDebug::GlitchLog* log,
37 const SkOpPtT* (SkCoincidentSpans::* getEnd)() const,
38 void (SkCoincidentSpans::* setEnd)(const SkOpPtT* ptT) const) const;
39 bool debugExpand(SkPathOpsDebug::GlitchLog* log) const;
caryclark55888e42016-07-18 10:01:36 -070040#endif
caryclark26ad22a2015-10-16 09:03:38 -070041
Cary Clarkab87d7a2016-10-04 10:01:04 -040042 const char* debugID() const {
43#if DEBUG_COIN
44 return fGlobalState->debugCoinDictEntry().fFunctionName;
45#else
46 return nullptr;
47#endif
caryclark26ad22a2015-10-16 09:03:38 -070048 }
caryclark54359292015-03-26 07:52:43 -070049
caryclark55888e42016-07-18 10:01:36 -070050 void debugShow() const;
51#ifdef SK_DEBUG
52 void debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over,
53 const SkOpGlobalState* debugState) const;
54#endif
caryclark54359292015-03-26 07:52:43 -070055 void dump() const;
caryclark55888e42016-07-18 10:01:36 -070056 bool expand();
57 bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
58 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd);
59 bool flipped() const { return fOppPtTStart->fT > fOppPtTEnd->fT; }
caryclarkfc560e02016-07-27 08:46:10 -070060 SkDEBUGCODE(SkOpGlobalState* globalState() { return fGlobalState; })
61
62 void init(SkDEBUGCODE(SkOpGlobalState* globalState)) {
63 sk_bzero(this, sizeof(*this));
64 SkDEBUGCODE(fGlobalState = globalState);
65 }
66
caryclark81a478c2016-09-09 09:37:57 -070067 SkCoincidentSpans* next() { return fNext; }
68 const SkCoincidentSpans* next() const { return fNext; }
69 SkCoincidentSpans** nextPtr() { return &fNext; }
caryclark55888e42016-07-18 10:01:36 -070070 const SkOpPtT* oppPtTStart() const { return fOppPtTStart; }
71 const SkOpPtT* oppPtTEnd() const { return fOppPtTEnd; }
72 // These return non-const pointers so that, as copies, they can be added
73 // to a new span pair
74 SkOpPtT* oppPtTStartWritable() const { return const_cast<SkOpPtT*>(fOppPtTStart); }
75 SkOpPtT* oppPtTEndWritable() const { return const_cast<SkOpPtT*>(fOppPtTEnd); }
caryclark81a478c2016-09-09 09:37:57 -070076 bool ordered() const;
caryclark55888e42016-07-18 10:01:36 -070077
78 void set(SkCoincidentSpans* next, const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
Cary Clarkab87d7a2016-10-04 10:01:04 -040079 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd);
caryclark55888e42016-07-18 10:01:36 -070080
81 void setCoinPtTEnd(const SkOpPtT* ptT) {
caryclarkd6562002016-07-27 12:02:07 -070082 SkOPASSERT(ptT == ptT->span()->ptT());
caryclark55888e42016-07-18 10:01:36 -070083 SkASSERT(!fCoinPtTStart || ptT->fT != fCoinPtTStart->fT);
84 SkASSERT(!fCoinPtTStart || fCoinPtTStart->segment() == ptT->segment());
85 fCoinPtTEnd = ptT;
86 ptT->setCoincident();
87 }
88
89 void setCoinPtTStart(const SkOpPtT* ptT) {
caryclarkd6562002016-07-27 12:02:07 -070090 SkASSERT(ptT == ptT->span()->ptT());
caryclark42942862016-08-19 07:01:33 -070091 SkOPASSERT(!fCoinPtTEnd || ptT->fT != fCoinPtTEnd->fT);
caryclark55888e42016-07-18 10:01:36 -070092 SkASSERT(!fCoinPtTEnd || fCoinPtTEnd->segment() == ptT->segment());
93 fCoinPtTStart = ptT;
94 ptT->setCoincident();
95 }
96
97 void setEnds(const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTEnd) {
98 this->setCoinPtTEnd(coinPtTEnd);
99 this->setOppPtTEnd(oppPtTEnd);
100 }
101
102 void setOppPtTEnd(const SkOpPtT* ptT) {
caryclarkd6562002016-07-27 12:02:07 -0700103 SkOPASSERT(ptT == ptT->span()->ptT());
caryclarke7bb5b22016-09-22 05:20:07 -0700104 SkOPASSERT(!fOppPtTStart || ptT->fT != fOppPtTStart->fT);
caryclark55888e42016-07-18 10:01:36 -0700105 SkASSERT(!fOppPtTStart || fOppPtTStart->segment() == ptT->segment());
106 fOppPtTEnd = ptT;
107 ptT->setCoincident();
108 }
109
110 void setOppPtTStart(const SkOpPtT* ptT) {
caryclarkd6562002016-07-27 12:02:07 -0700111 SkASSERT(ptT == ptT->span()->ptT());
caryclark08714012016-10-07 12:57:47 -0700112 SkOPASSERT(!fOppPtTEnd || ptT->fT != fOppPtTEnd->fT);
caryclark55888e42016-07-18 10:01:36 -0700113 SkASSERT(!fOppPtTEnd || fOppPtTEnd->segment() == ptT->segment());
114 fOppPtTStart = ptT;
115 ptT->setCoincident();
116 }
117
118 void setStarts(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart) {
119 this->setCoinPtTStart(coinPtTStart);
120 this->setOppPtTStart(oppPtTStart);
121 }
122
123 void setNext(SkCoincidentSpans* next) { fNext = next; }
124
caryclark55888e42016-07-18 10:01:36 -0700125private:
126 SkCoincidentSpans* fNext;
127 const SkOpPtT* fCoinPtTStart;
128 const SkOpPtT* fCoinPtTEnd;
129 const SkOpPtT* fOppPtTStart;
130 const SkOpPtT* fOppPtTEnd;
caryclarkfc560e02016-07-27 08:46:10 -0700131 SkDEBUGCODE(SkOpGlobalState* fGlobalState);
caryclark45fa4472015-01-16 07:04:10 -0800132};
133
134class SkOpCoincidence {
135public:
caryclark55888e42016-07-18 10:01:36 -0700136 SkOpCoincidence(SkOpGlobalState* globalState)
halcanary96fcdcc2015-08-27 07:41:13 -0700137 : fHead(nullptr)
138 , fTop(nullptr)
caryclark55888e42016-07-18 10:01:36 -0700139 , fGlobalState(globalState)
140 , fContinue(false)
141 , fSpanDeleted(false)
142 , fPtAllocated(false)
143 , fCoinExtended(false)
144 , fSpanMerged(false) {
145 globalState->setCoincidence(this);
caryclark45fa4472015-01-16 07:04:10 -0800146 }
147
148 void add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart,
caryclark55888e42016-07-18 10:01:36 -0700149 SkOpPtT* oppPtTEnd);
Cary Clarkab87d7a2016-10-04 10:01:04 -0400150 bool addEndMovedSpans(DEBUG_COIN_DECLARE_ONLY_PARAMS());
151 bool addExpanded(DEBUG_COIN_DECLARE_ONLY_PARAMS());
152 bool addMissing(bool* added DEBUG_COIN_DECLARE_PARAMS());
Cary Clarke47ae292016-10-05 08:51:39 -0400153 void apply(DEBUG_COIN_DECLARE_ONLY_PARAMS());
caryclark26ad22a2015-10-16 09:03:38 -0700154 bool contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
caryclark55888e42016-07-18 10:01:36 -0700155 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400156 void correctEnds(DEBUG_COIN_DECLARE_ONLY_PARAMS());
caryclark26ad22a2015-10-16 09:03:38 -0700157
Cary Clarkab87d7a2016-10-04 10:01:04 -0400158#if DEBUG_COIN
159 void debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log) const;
160 void debugAddExpanded(SkPathOpsDebug::GlitchLog* ) const;
161 void debugAddMissing(SkPathOpsDebug::GlitchLog* , bool* added) const;
162 void debugAddOrOverlap(SkPathOpsDebug::GlitchLog* log,
caryclark30b9fdd2016-08-31 14:36:29 -0700163 const SkOpSegment* coinSeg, const SkOpSegment* oppSeg,
caryclark81a478c2016-09-09 09:37:57 -0700164 double coinTs, double coinTe, double oppTs, double oppTe,
165 bool* added) const;
caryclark55888e42016-07-18 10:01:36 -0700166#endif
caryclark27c8eb82015-07-06 11:38:33 -0700167
168 const SkOpAngle* debugAngle(int id) const {
caryclark55888e42016-07-18 10:01:36 -0700169 return SkDEBUGRELEASE(fGlobalState->debugAngle(id), nullptr);
caryclark27c8eb82015-07-06 11:38:33 -0700170 }
171
caryclark6c3b9cd2016-09-26 05:36:58 -0700172 void debugCheckBetween() const;
173
Cary Clarkab87d7a2016-10-04 10:01:04 -0400174#if DEBUG_COIN
175 void debugCheckValid(SkPathOpsDebug::GlitchLog* log) const;
caryclark55888e42016-07-18 10:01:36 -0700176#endif
177
caryclark30b9fdd2016-08-31 14:36:29 -0700178 SkOpContour* debugContour(int id) const {
caryclark55888e42016-07-18 10:01:36 -0700179 return SkDEBUGRELEASE(fGlobalState->debugContour(id), nullptr);
caryclark27c8eb82015-07-06 11:38:33 -0700180 }
181
Cary Clarkab87d7a2016-10-04 10:01:04 -0400182#if DEBUG_COIN
183 void debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const;
184 bool debugExpand(SkPathOpsDebug::GlitchLog* ) const;
185 void debugMark(SkPathOpsDebug::GlitchLog* ) const;
186 void debugMarkCollapsed(SkPathOpsDebug::GlitchLog* ,
caryclark55888e42016-07-18 10:01:36 -0700187 const SkCoincidentSpans* coin, const SkOpPtT* test) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400188 void debugMarkCollapsed(SkPathOpsDebug::GlitchLog* , const SkOpPtT* test) const;
caryclark55888e42016-07-18 10:01:36 -0700189#endif
caryclark26ad22a2015-10-16 09:03:38 -0700190
caryclark27c8eb82015-07-06 11:38:33 -0700191 const SkOpPtT* debugPtT(int id) const {
caryclark55888e42016-07-18 10:01:36 -0700192 return SkDEBUGRELEASE(fGlobalState->debugPtT(id), nullptr);
caryclark27c8eb82015-07-06 11:38:33 -0700193 }
194
195 const SkOpSegment* debugSegment(int id) const {
caryclark55888e42016-07-18 10:01:36 -0700196 return SkDEBUGRELEASE(fGlobalState->debugSegment(id), nullptr);
caryclark27c8eb82015-07-06 11:38:33 -0700197 }
198
Cary Clarkab87d7a2016-10-04 10:01:04 -0400199#if DEBUG_COIN
Cary Clarkab87d7a2016-10-04 10:01:04 -0400200 void debugRelease(SkPathOpsDebug::GlitchLog* , const SkCoincidentSpans* ,
caryclark30b9fdd2016-08-31 14:36:29 -0700201 const SkCoincidentSpans* ) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400202 void debugRelease(SkPathOpsDebug::GlitchLog* , const SkOpSegment* ) const;
caryclark55888e42016-07-18 10:01:36 -0700203#endif
caryclark624637c2015-05-11 07:21:27 -0700204 void debugShowCoincidence() const;
caryclark27c8eb82015-07-06 11:38:33 -0700205
206 const SkOpSpanBase* debugSpan(int id) const {
caryclark55888e42016-07-18 10:01:36 -0700207 return SkDEBUGRELEASE(fGlobalState->debugSpan(id), nullptr);
caryclark27c8eb82015-07-06 11:38:33 -0700208 }
209
caryclark55888e42016-07-18 10:01:36 -0700210 void debugValidate() const;
caryclark45fa4472015-01-16 07:04:10 -0800211 void dump() const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400212 bool expand(DEBUG_COIN_DECLARE_ONLY_PARAMS());
caryclark55888e42016-07-18 10:01:36 -0700213 bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart,
214 const SkOpPtT* oppPtTEnd);
Cary Clark40f23782016-10-06 12:04:16 -0400215 bool findOverlaps(SkOpCoincidence* DEBUG_COIN_DECLARE_PARAMS()) const;
caryclark55888e42016-07-18 10:01:36 -0700216 void fixUp(SkOpPtT* deleted, const SkOpPtT* kept);
217
218 SkOpGlobalState* globalState() {
219 return fGlobalState;
220 }
caryclark27c8eb82015-07-06 11:38:33 -0700221
caryclark81a478c2016-09-09 09:37:57 -0700222 const SkOpGlobalState* globalState() const {
223 return fGlobalState;
224 }
225
caryclark27c8eb82015-07-06 11:38:33 -0700226 bool isEmpty() const {
caryclark55888e42016-07-18 10:01:36 -0700227 return !fHead && !fTop;
caryclark27c8eb82015-07-06 11:38:33 -0700228 }
229
caryclarke6522ea2016-10-17 07:54:33 -0700230 bool mark(DEBUG_COIN_DECLARE_ONLY_PARAMS());
caryclark55888e42016-07-18 10:01:36 -0700231 void markCollapsed(SkOpPtT* );
232
233 static bool Ordered(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart) {
234 return Ordered(coinPtTStart->segment(), oppPtTStart->segment());
235 }
236
237 static bool Ordered(const SkOpSegment* coin, const SkOpSegment* opp);
238 void release(const SkOpSegment* );
caryclark30b9fdd2016-08-31 14:36:29 -0700239 void releaseDeleted();
caryclark45fa4472015-01-16 07:04:10 -0800240
caryclark54359292015-03-26 07:52:43 -0700241private:
caryclark55888e42016-07-18 10:01:36 -0700242 void add(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart,
243 const SkOpPtT* oppPtTEnd) {
244 this->add(const_cast<SkOpPtT*>(coinPtTStart), const_cast<SkOpPtT*>(coinPtTEnd),
245 const_cast<SkOpPtT*>(oppPtTStart), const_cast<SkOpPtT*>(oppPtTEnd));
246 }
247
caryclark15976282016-07-21 05:48:43 -0700248 bool addEndMovedSpans(const SkOpSpan* base, const SkOpSpanBase* testSpan);
caryclark55888e42016-07-18 10:01:36 -0700249 bool addEndMovedSpans(const SkOpPtT* ptT);
250
caryclark8016b262016-09-06 05:59:47 -0700251 bool addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over2s,
caryclark81a478c2016-09-09 09:37:57 -0700252 double tStart, double tEnd, SkOpSegment* coinSeg, SkOpSegment* oppSeg,
253 bool* added
caryclark8016b262016-09-06 05:59:47 -0700254 SkDEBUGPARAMS(const SkOpPtT* over1e) SkDEBUGPARAMS(const SkOpPtT* over2e));
caryclark55888e42016-07-18 10:01:36 -0700255 bool addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg,
caryclark81a478c2016-09-09 09:37:57 -0700256 double coinTs, double coinTe, double oppTs, double oppTe, bool* added);
caryclark55888e42016-07-18 10:01:36 -0700257 bool addOverlap(const SkOpSegment* seg1, const SkOpSegment* seg1o,
258 const SkOpSegment* seg2, const SkOpSegment* seg2o,
259 const SkOpPtT* overS, const SkOpPtT* overE);
caryclark55888e42016-07-18 10:01:36 -0700260 bool checkOverlap(SkCoincidentSpans* check,
261 const SkOpSegment* coinSeg, const SkOpSegment* oppSeg,
262 double coinTs, double coinTe, double oppTs, double oppTe,
263 SkTDArray<SkCoincidentSpans*>* overlaps) const;
264 bool contains(const SkOpSegment* seg, const SkOpSegment* opp, double oppT) const;
265 bool contains(const SkCoincidentSpans* coin, const SkOpSegment* seg,
266 const SkOpSegment* opp, double oppT) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400267#if DEBUG_COIN
268 void debugAddIfMissing(SkPathOpsDebug::GlitchLog* ,
caryclark8016b262016-09-06 05:59:47 -0700269 const SkCoincidentSpans* outer, const SkOpPtT* over1s,
270 const SkOpPtT* over1e) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400271 void debugAddIfMissing(SkPathOpsDebug::GlitchLog* ,
caryclark8016b262016-09-06 05:59:47 -0700272 const SkOpPtT* over1s, const SkOpPtT* over2s,
caryclark26ad22a2015-10-16 09:03:38 -0700273 double tStart, double tEnd,
caryclark81a478c2016-09-09 09:37:57 -0700274 const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, bool* added,
caryclark8016b262016-09-06 05:59:47 -0700275 const SkOpPtT* over1e, const SkOpPtT* over2e) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400276 void debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* ,
277 const SkOpSpan* base, const SkOpSpanBase* testSpan) const;
278 void debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* ,
279 const SkOpPtT* ptT) const;
caryclark55888e42016-07-18 10:01:36 -0700280#endif
281 void fixUp(SkCoincidentSpans* coin, SkOpPtT* deleted, const SkOpPtT* kept);
282 void markCollapsed(SkCoincidentSpans* head, SkOpPtT* test);
caryclark54359292015-03-26 07:52:43 -0700283 bool overlap(const SkOpPtT* coinStart1, const SkOpPtT* coinEnd1,
284 const SkOpPtT* coinStart2, const SkOpPtT* coinEnd2,
285 double* overS, double* overE) const;
caryclark55888e42016-07-18 10:01:36 -0700286 bool release(SkCoincidentSpans* coin, SkCoincidentSpans* );
caryclark30b9fdd2016-08-31 14:36:29 -0700287 void releaseDeleted(SkCoincidentSpans* );
caryclark55888e42016-07-18 10:01:36 -0700288 void restoreHead();
caryclark8016b262016-09-06 05:59:47 -0700289 // return coinPtT->segment()->t mapped from overS->fT <= t <= overE->fT
290 static double TRange(const SkOpPtT* overS, double t, const SkOpSegment* coinPtT
291 SkDEBUGPARAMS(const SkOpPtT* overE));
caryclark55888e42016-07-18 10:01:36 -0700292
caryclark45fa4472015-01-16 07:04:10 -0800293 SkCoincidentSpans* fHead;
caryclark27c8eb82015-07-06 11:38:33 -0700294 SkCoincidentSpans* fTop;
caryclark55888e42016-07-18 10:01:36 -0700295 SkOpGlobalState* fGlobalState;
296 bool fContinue;
297 bool fSpanDeleted;
298 bool fPtAllocated;
299 bool fCoinExtended;
300 bool fSpanMerged;
caryclark45fa4472015-01-16 07:04:10 -0800301};
302
303#endif