blob: fea33095982b12ffb873444c219598ff7fb66af7 [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
2 * Copyright 2012 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 SkOpSpan_DEFINED
8#define SkOpSpan_DEFINED
9
caryclark54359292015-03-26 07:52:43 -070010#include "SkPathOpsDebug.h"
caryclark27c8eb82015-07-06 11:38:33 -070011#include "SkPathOpsTypes.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000012#include "SkPoint.h"
13
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050014class SkArenaAlloc;
caryclark55888e42016-07-18 10:01:36 -070015class SkOpAngle;
caryclark54359292015-03-26 07:52:43 -070016class SkOpContour;
17class SkOpGlobalState;
caryclark@google.com07393ca2013-04-08 11:47:37 +000018class SkOpSegment;
caryclark54359292015-03-26 07:52:43 -070019class SkOpSpanBase;
20class SkOpSpan;
caryclark55888e42016-07-18 10:01:36 -070021struct SkPathOpsBounds;
caryclark@google.com07393ca2013-04-08 11:47:37 +000022
caryclark54359292015-03-26 07:52:43 -070023// subset of op span used by terminal span (when t is equal to one)
24class SkOpPtT {
25public:
26 enum {
27 kIsAlias = 1,
28 kIsDuplicate = 1
29 };
30
caryclark30b9fdd2016-08-31 14:36:29 -070031 const SkOpPtT* active() const;
32
caryclark55888e42016-07-18 10:01:36 -070033 // please keep in sync with debugAddOpp()
caryclark29b25632016-08-25 11:27:17 -070034 void addOpp(SkOpPtT* opp, SkOpPtT* oppPrev) {
caryclark54359292015-03-26 07:52:43 -070035 SkOpPtT* oldNext = this->fNext;
36 SkASSERT(this != opp);
37 this->fNext = opp;
38 SkASSERT(oppPrev != oldNext);
39 oppPrev->fNext = oldNext;
40 }
41
42 bool alias() const;
caryclark55888e42016-07-18 10:01:36 -070043 bool coincident() const { return fCoincident; }
caryclark27c8eb82015-07-06 11:38:33 -070044 bool contains(const SkOpPtT* ) const;
caryclark55888e42016-07-18 10:01:36 -070045 bool contains(const SkOpSegment*, const SkPoint& ) const;
46 bool contains(const SkOpSegment*, double t) const;
47 const SkOpPtT* contains(const SkOpSegment* ) const;
caryclark54359292015-03-26 07:52:43 -070048 SkOpContour* contour() const;
49
50 int debugID() const {
caryclark1049f122015-04-20 08:31:59 -070051 return SkDEBUGRELEASE(fID, -1);
caryclark54359292015-03-26 07:52:43 -070052 }
53
caryclark29b25632016-08-25 11:27:17 -070054 void debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const;
caryclark54359292015-03-26 07:52:43 -070055 const SkOpAngle* debugAngle(int id) const;
caryclark55888e42016-07-18 10:01:36 -070056 const SkOpCoincidence* debugCoincidence() const;
caryclark26ad22a2015-10-16 09:03:38 -070057 bool debugContains(const SkOpPtT* ) const;
58 const SkOpPtT* debugContains(const SkOpSegment* check) const;
caryclark30b9fdd2016-08-31 14:36:29 -070059 SkOpContour* debugContour(int id) const;
caryclark8016b262016-09-06 05:59:47 -070060 const SkOpPtT* debugEnder(const SkOpPtT* end) const;
caryclark54359292015-03-26 07:52:43 -070061 int debugLoopLimit(bool report) const;
62 bool debugMatchID(int id) const;
caryclark29b25632016-08-25 11:27:17 -070063 const SkOpPtT* debugOppPrev(const SkOpPtT* opp) const;
caryclark54359292015-03-26 07:52:43 -070064 const SkOpPtT* debugPtT(int id) const;
caryclark025b11e2016-08-25 05:21:14 -070065 void debugResetCoinT() const;
caryclark54359292015-03-26 07:52:43 -070066 const SkOpSegment* debugSegment(int id) const;
caryclark025b11e2016-08-25 05:21:14 -070067 void debugSetCoinT(int ) const;
caryclark54359292015-03-26 07:52:43 -070068 const SkOpSpanBase* debugSpan(int id) const;
caryclark54359292015-03-26 07:52:43 -070069 void debugValidate() const;
70
71 bool deleted() const {
72 return fDeleted;
73 }
74
75 bool duplicate() const {
76 return fDuplicatePt;
77 }
78
79 void dump() const; // available to testing only
80 void dumpAll() const;
81 void dumpBase() const;
82
caryclark55888e42016-07-18 10:01:36 -070083 const SkOpPtT* find(const SkOpSegment* ) const;
caryclark26ad22a2015-10-16 09:03:38 -070084 SkOpGlobalState* globalState() const;
caryclark54359292015-03-26 07:52:43 -070085 void init(SkOpSpanBase* , double t, const SkPoint& , bool dup);
86
87 void insert(SkOpPtT* span) {
88 SkASSERT(span != this);
89 span->fNext = fNext;
90 fNext = span;
91 }
92
93 const SkOpPtT* next() const {
94 return fNext;
95 }
96
97 SkOpPtT* next() {
98 return fNext;
99 }
100
101 bool onEnd() const;
caryclark27c8eb82015-07-06 11:38:33 -0700102
caryclark30b9fdd2016-08-31 14:36:29 -0700103 // returns nullptr if this is already in the opp ptT loop
104 SkOpPtT* oppPrev(const SkOpPtT* opp) const {
caryclark29b25632016-08-25 11:27:17 -0700105 // find the fOpp ptr to opp
106 SkOpPtT* oppPrev = opp->fNext;
107 if (oppPrev == this) {
108 return nullptr;
109 }
110 while (oppPrev->fNext != opp) {
111 oppPrev = oppPrev->fNext;
112 if (oppPrev == this) {
113 return nullptr;
114 }
115 }
116 return oppPrev;
117 }
118
caryclark55888e42016-07-18 10:01:36 -0700119 static bool Overlaps(const SkOpPtT* s1, const SkOpPtT* e1, const SkOpPtT* s2,
120 const SkOpPtT* e2, const SkOpPtT** sOut, const SkOpPtT** eOut) {
121 const SkOpPtT* start1 = s1->fT < e1->fT ? s1 : e1;
122 const SkOpPtT* start2 = s2->fT < e2->fT ? s2 : e2;
caryclark27c8eb82015-07-06 11:38:33 -0700123 *sOut = between(s1->fT, start2->fT, e1->fT) ? start2
halcanary96fcdcc2015-08-27 07:41:13 -0700124 : between(s2->fT, start1->fT, e2->fT) ? start1 : nullptr;
caryclark55888e42016-07-18 10:01:36 -0700125 const SkOpPtT* end1 = s1->fT < e1->fT ? e1 : s1;
126 const SkOpPtT* end2 = s2->fT < e2->fT ? e2 : s2;
caryclark27c8eb82015-07-06 11:38:33 -0700127 *eOut = between(s1->fT, end2->fT, e1->fT) ? end2
halcanary96fcdcc2015-08-27 07:41:13 -0700128 : between(s2->fT, end1->fT, e2->fT) ? end1 : nullptr;
caryclark27c8eb82015-07-06 11:38:33 -0700129 if (*sOut == *eOut) {
130 SkASSERT(start1->fT >= end2->fT || start2->fT >= end1->fT);
131 return false;
132 }
133 SkASSERT(!*sOut || *sOut != *eOut);
134 return *sOut && *eOut;
135 }
136
caryclark55888e42016-07-18 10:01:36 -0700137 bool ptAlreadySeen(const SkOpPtT* head) const;
caryclark54359292015-03-26 07:52:43 -0700138 SkOpPtT* prev();
caryclark54359292015-03-26 07:52:43 -0700139
140 const SkOpSegment* segment() const;
141 SkOpSegment* segment();
142
caryclark55888e42016-07-18 10:01:36 -0700143 void setCoincident() const {
caryclarkfc560e02016-07-27 08:46:10 -0700144 SkOPASSERT(!fDeleted);
caryclark55888e42016-07-18 10:01:36 -0700145 fCoincident = true;
146 }
147
148 void setDeleted();
149
150 void setSpan(const SkOpSpanBase* span) {
151 fSpan = const_cast<SkOpSpanBase*>(span);
caryclark54359292015-03-26 07:52:43 -0700152 }
153
154 const SkOpSpanBase* span() const {
155 return fSpan;
156 }
157
158 SkOpSpanBase* span() {
159 return fSpan;
160 }
161
caryclark27c8eb82015-07-06 11:38:33 -0700162 const SkOpPtT* starter(const SkOpPtT* end) const {
163 return fT < end->fT ? this : end;
164 }
165
caryclark55888e42016-07-18 10:01:36 -0700166 double fT;
caryclark54359292015-03-26 07:52:43 -0700167 SkPoint fPt; // cache of point value at this t
168protected:
169 SkOpSpanBase* fSpan; // contains winding data
170 SkOpPtT* fNext; // intersection on opposite curve or alias on this curve
caryclark55888e42016-07-18 10:01:36 -0700171 bool fDeleted; // set if removed from span list
caryclark54359292015-03-26 07:52:43 -0700172 bool fDuplicatePt; // set if identical pt is somewhere in the next loop
caryclark55888e42016-07-18 10:01:36 -0700173 // below mutable since referrer is otherwise always const
174 mutable bool fCoincident; // set if at some point a coincident span pointed here
caryclark1049f122015-04-20 08:31:59 -0700175 SkDEBUGCODE(int fID);
caryclark54359292015-03-26 07:52:43 -0700176};
177
178class SkOpSpanBase {
179public:
caryclark30b9fdd2016-08-31 14:36:29 -0700180 SkOpSpanBase* active();
181 void addOpp(SkOpSpanBase* opp);
caryclark54359292015-03-26 07:52:43 -0700182
caryclark08bc8482015-04-24 09:08:57 -0700183 void bumpSpanAdds() {
184 ++fSpanAdds;
185 }
186
caryclark54359292015-03-26 07:52:43 -0700187 bool chased() const {
188 return fChased;
189 }
190
caryclark55888e42016-07-18 10:01:36 -0700191 void checkForCollapsedCoincidence();
caryclark54359292015-03-26 07:52:43 -0700192
193 const SkOpSpanBase* coinEnd() const {
194 return fCoinEnd;
195 }
196
caryclark30b9fdd2016-08-31 14:36:29 -0700197 bool collapsed(double s, double e) const;
caryclark54359292015-03-26 07:52:43 -0700198 bool contains(const SkOpSpanBase* ) const;
caryclark55888e42016-07-18 10:01:36 -0700199 const SkOpPtT* contains(const SkOpSegment* ) const;
caryclark54359292015-03-26 07:52:43 -0700200
201 bool containsCoinEnd(const SkOpSpanBase* coin) const {
202 SkASSERT(this != coin);
203 const SkOpSpanBase* next = this;
204 while ((next = next->fCoinEnd) != this) {
205 if (next == coin) {
206 return true;
207 }
208 }
209 return false;
210 }
211
212 bool containsCoinEnd(const SkOpSegment* ) const;
213 SkOpContour* contour() const;
214
215 int debugBumpCount() {
caryclark1049f122015-04-20 08:31:59 -0700216 return SkDEBUGRELEASE(++fCount, -1);
caryclark54359292015-03-26 07:52:43 -0700217 }
218
219 int debugID() const {
caryclark1049f122015-04-20 08:31:59 -0700220 return SkDEBUGRELEASE(fID, -1);
caryclark54359292015-03-26 07:52:43 -0700221 }
222
Cary Clarkab87d7a2016-10-04 10:01:04 -0400223#if DEBUG_COIN
224 void debugAddOpp(SkPathOpsDebug::GlitchLog* , const SkOpSpanBase* opp) const;
caryclark30b9fdd2016-08-31 14:36:29 -0700225#endif
caryclark26ad22a2015-10-16 09:03:38 -0700226 bool debugAlignedEnd(double t, const SkPoint& pt) const;
227 bool debugAlignedInner() const;
caryclark54359292015-03-26 07:52:43 -0700228 const SkOpAngle* debugAngle(int id) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400229#if DEBUG_COIN
230 void debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* ) const;
caryclark55888e42016-07-18 10:01:36 -0700231#endif
232 const SkOpCoincidence* debugCoincidence() const;
caryclark54359292015-03-26 07:52:43 -0700233 bool debugCoinEndLoopCheck() const;
caryclark30b9fdd2016-08-31 14:36:29 -0700234 SkOpContour* debugContour(int id) const;
caryclark55888e42016-07-18 10:01:36 -0700235#ifdef SK_DEBUG
caryclark30b9fdd2016-08-31 14:36:29 -0700236 bool debugDeleted() const { return fDebugDeleted; }
caryclark55888e42016-07-18 10:01:36 -0700237#endif
Cary Clarkab87d7a2016-10-04 10:01:04 -0400238#if DEBUG_COIN
239 void debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* ,
caryclark55888e42016-07-18 10:01:36 -0700240 const SkOpSpanBase* ) const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400241 void debugMergeMatches(SkPathOpsDebug::GlitchLog* log,
caryclark30b9fdd2016-08-31 14:36:29 -0700242 const SkOpSpanBase* opp) const;
caryclark55888e42016-07-18 10:01:36 -0700243#endif
caryclark54359292015-03-26 07:52:43 -0700244 const SkOpPtT* debugPtT(int id) const;
caryclark025b11e2016-08-25 05:21:14 -0700245 void debugResetCoinT() const;
caryclark54359292015-03-26 07:52:43 -0700246 const SkOpSegment* debugSegment(int id) const;
caryclark025b11e2016-08-25 05:21:14 -0700247 void debugSetCoinT(int ) const;
caryclark30b9fdd2016-08-31 14:36:29 -0700248#ifdef SK_DEBUG
249 void debugSetDeleted() { fDebugDeleted = true; }
250#endif
caryclark54359292015-03-26 07:52:43 -0700251 const SkOpSpanBase* debugSpan(int id) const;
caryclark26ad22a2015-10-16 09:03:38 -0700252 const SkOpSpan* debugStarter(SkOpSpanBase const** endPtr) const;
caryclark54359292015-03-26 07:52:43 -0700253 SkOpGlobalState* globalState() const;
254 void debugValidate() const;
255
256 bool deleted() const {
257 return fPtT.deleted();
258 }
259
260 void dump() const; // available to testing only
261 void dumpCoin() const;
262 void dumpAll() const;
263 void dumpBase() const;
caryclark55888e42016-07-18 10:01:36 -0700264 void dumpHead() const;
caryclark54359292015-03-26 07:52:43 -0700265
266 bool final() const {
267 return fPtT.fT == 1;
268 }
269
270 SkOpAngle* fromAngle() const {
271 return fFromAngle;
272 }
273
274 void initBase(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
275
caryclark55888e42016-07-18 10:01:36 -0700276 // Please keep this in sync with debugInsertCoinEnd()
caryclark54359292015-03-26 07:52:43 -0700277 void insertCoinEnd(SkOpSpanBase* coin) {
278 if (containsCoinEnd(coin)) {
279 SkASSERT(coin->containsCoinEnd(this));
280 return;
281 }
282 debugValidate();
283 SkASSERT(this != coin);
284 SkOpSpanBase* coinNext = coin->fCoinEnd;
285 coin->fCoinEnd = this->fCoinEnd;
286 this->fCoinEnd = coinNext;
287 debugValidate();
288 }
289
290 void merge(SkOpSpan* span);
caryclark30b9fdd2016-08-31 14:36:29 -0700291 void mergeMatches(SkOpSpanBase* opp);
caryclark54359292015-03-26 07:52:43 -0700292
caryclark55888e42016-07-18 10:01:36 -0700293 const SkOpSpan* prev() const {
294 return fPrev;
295 }
296
297 SkOpSpan* prev() {
caryclark54359292015-03-26 07:52:43 -0700298 return fPrev;
299 }
300
301 const SkPoint& pt() const {
302 return fPtT.fPt;
303 }
304
305 const SkOpPtT* ptT() const {
306 return &fPtT;
307 }
308
309 SkOpPtT* ptT() {
310 return &fPtT;
311 }
312
313 SkOpSegment* segment() const {
314 return fSegment;
315 }
316
caryclarkd4349722015-07-23 12:40:22 -0700317 void setAligned() {
318 fAligned = true;
319 }
320
caryclark54359292015-03-26 07:52:43 -0700321 void setChased(bool chased) {
322 fChased = chased;
323 }
324
caryclark54359292015-03-26 07:52:43 -0700325 void setFromAngle(SkOpAngle* angle) {
326 fFromAngle = angle;
327 }
328
329 void setPrev(SkOpSpan* prev) {
330 fPrev = prev;
331 }
332
333 bool simple() const {
334 fPtT.debugValidate();
caryclark55888e42016-07-18 10:01:36 -0700335 return fPtT.next()->next() == &fPtT;
caryclark54359292015-03-26 07:52:43 -0700336 }
337
caryclark08bc8482015-04-24 09:08:57 -0700338 int spanAddsCount() const {
339 return fSpanAdds;
340 }
341
caryclark54359292015-03-26 07:52:43 -0700342 const SkOpSpan* starter(const SkOpSpanBase* end) const {
343 const SkOpSpanBase* result = t() < end->t() ? this : end;
344 return result->upCast();
345 }
346
347 SkOpSpan* starter(SkOpSpanBase* end) {
348 SkASSERT(this->segment() == end->segment());
349 SkOpSpanBase* result = t() < end->t() ? this : end;
350 return result->upCast();
351 }
352
353 SkOpSpan* starter(SkOpSpanBase** endPtr) {
354 SkOpSpanBase* end = *endPtr;
355 SkASSERT(this->segment() == end->segment());
356 SkOpSpanBase* result;
357 if (t() < end->t()) {
358 result = this;
359 } else {
360 result = end;
361 *endPtr = this;
362 }
363 return result->upCast();
364 }
365
366 int step(const SkOpSpanBase* end) const {
367 return t() < end->t() ? 1 : -1;
368 }
369
370 double t() const {
371 return fPtT.fT;
372 }
373
374 void unaligned() {
375 fAligned = false;
376 }
377
378 SkOpSpan* upCast() {
379 SkASSERT(!final());
380 return (SkOpSpan*) this;
381 }
382
383 const SkOpSpan* upCast() const {
caryclarkef4f32a2016-08-24 09:24:18 -0700384 SkOPASSERT(!final());
caryclark54359292015-03-26 07:52:43 -0700385 return (const SkOpSpan*) this;
386 }
387
388 SkOpSpan* upCastable() {
halcanary96fcdcc2015-08-27 07:41:13 -0700389 return final() ? nullptr : upCast();
caryclark54359292015-03-26 07:52:43 -0700390 }
391
392 const SkOpSpan* upCastable() const {
halcanary96fcdcc2015-08-27 07:41:13 -0700393 return final() ? nullptr : upCast();
caryclark54359292015-03-26 07:52:43 -0700394 }
395
396private:
397 void alignInner();
398
399protected: // no direct access to internals to avoid treating a span base as a span
400 SkOpPtT fPtT; // list of points and t values associated with the start of this span
401 SkOpSegment* fSegment; // segment that contains this span
402 SkOpSpanBase* fCoinEnd; // linked list of coincident spans that end here (may point to itself)
403 SkOpAngle* fFromAngle; // points to next angle from span start to end
404 SkOpSpan* fPrev; // previous intersection point
caryclark08bc8482015-04-24 09:08:57 -0700405 int fSpanAdds; // number of times intersections have been added to span
caryclark54359292015-03-26 07:52:43 -0700406 bool fAligned;
407 bool fChased; // set after span has been added to chase array
caryclark1049f122015-04-20 08:31:59 -0700408 SkDEBUGCODE(int fCount); // number of pt/t pairs added
409 SkDEBUGCODE(int fID);
caryclark30b9fdd2016-08-31 14:36:29 -0700410 SkDEBUGCODE(bool fDebugDeleted); // set when span was merged with another span
caryclark54359292015-03-26 07:52:43 -0700411};
412
413class SkOpSpan : public SkOpSpanBase {
414public:
caryclarkef784fb2015-10-30 12:03:06 -0700415 bool alreadyAdded() const {
416 if (fAlreadyAdded) {
417 return true;
418 }
419 fAlreadyAdded = true;
420 return false;
421 }
422
caryclark54359292015-03-26 07:52:43 -0700423 bool clearCoincident() {
424 SkASSERT(!final());
425 if (fCoincident == this) {
426 return false;
427 }
428 fCoincident = this;
429 return true;
430 }
431
caryclarkbca19f72015-05-13 08:23:48 -0700432 int computeWindSum();
caryclark54359292015-03-26 07:52:43 -0700433 bool containsCoincidence(const SkOpSegment* ) const;
434
435 bool containsCoincidence(const SkOpSpan* coin) const {
436 SkASSERT(this != coin);
437 const SkOpSpan* next = this;
438 while ((next = next->fCoincident) != this) {
439 if (next == coin) {
440 return true;
441 }
442 }
443 return false;
444 }
445
446 bool debugCoinLoopCheck() const;
Cary Clarkab87d7a2016-10-04 10:01:04 -0400447#if DEBUG_COIN
448 void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* , const SkOpSpan* ) const;
449 void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* ,
450 const SkOpSegment* , bool flipped, bool ordered) const;
caryclark55888e42016-07-18 10:01:36 -0700451#endif
caryclark30b9fdd2016-08-31 14:36:29 -0700452 void dumpCoin() const;
453 bool dumpSpan() const;
caryclark54359292015-03-26 07:52:43 -0700454
455 bool done() const {
456 SkASSERT(!final());
457 return fDone;
458 }
459
caryclark54359292015-03-26 07:52:43 -0700460 void init(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
caryclark81a478c2016-09-09 09:37:57 -0700461 bool insertCoincidence(const SkOpSegment* , bool flipped, bool ordered);
caryclark54359292015-03-26 07:52:43 -0700462
caryclark55888e42016-07-18 10:01:36 -0700463 // Please keep this in sync with debugInsertCoincidence()
caryclark54359292015-03-26 07:52:43 -0700464 void insertCoincidence(SkOpSpan* coin) {
465 if (containsCoincidence(coin)) {
466 SkASSERT(coin->containsCoincidence(this));
467 return;
468 }
469 debugValidate();
470 SkASSERT(this != coin);
471 SkOpSpan* coinNext = coin->fCoincident;
472 coin->fCoincident = this->fCoincident;
473 this->fCoincident = coinNext;
474 debugValidate();
475 }
476
477 bool isCanceled() const {
478 SkASSERT(!final());
479 return fWindValue == 0 && fOppValue == 0;
480 }
481
482 bool isCoincident() const {
483 SkASSERT(!final());
484 return fCoincident != this;
485 }
486
487 SkOpSpanBase* next() const {
488 SkASSERT(!final());
489 return fNext;
490 }
491
492 int oppSum() const {
493 SkASSERT(!final());
494 return fOppSum;
495 }
496
497 int oppValue() const {
498 SkASSERT(!final());
499 return fOppValue;
500 }
501
caryclark30b9fdd2016-08-31 14:36:29 -0700502 void release(const SkOpPtT* );
503
caryclark54359292015-03-26 07:52:43 -0700504 SkOpPtT* setCoinStart(SkOpSpan* oldCoinStart, SkOpSegment* oppSegment);
505
506 void setDone(bool done) {
507 SkASSERT(!final());
508 fDone = done;
509 }
510
511 void setNext(SkOpSpanBase* nextT) {
512 SkASSERT(!final());
513 fNext = nextT;
514 }
515
516 void setOppSum(int oppSum);
517
518 void setOppValue(int oppValue) {
519 SkASSERT(!final());
520 SkASSERT(fOppSum == SK_MinS32);
caryclark595ac282016-10-24 08:41:45 -0700521 SkOPASSERT(!oppValue || !fDone);
caryclark54359292015-03-26 07:52:43 -0700522 fOppValue = oppValue;
523 }
524
525 void setToAngle(SkOpAngle* angle) {
526 SkASSERT(!final());
527 fToAngle = angle;
528 }
529
caryclark624637c2015-05-11 07:21:27 -0700530 void setWindSum(int windSum);
caryclark54359292015-03-26 07:52:43 -0700531
532 void setWindValue(int windValue) {
533 SkASSERT(!final());
534 SkASSERT(windValue >= 0);
535 SkASSERT(fWindSum == SK_MinS32);
caryclarkef4f32a2016-08-24 09:24:18 -0700536 SkOPASSERT(!windValue || !fDone);
caryclark54359292015-03-26 07:52:43 -0700537 fWindValue = windValue;
538 }
539
caryclark624637c2015-05-11 07:21:27 -0700540 bool sortableTop(SkOpContour* );
541
caryclark54359292015-03-26 07:52:43 -0700542 SkOpAngle* toAngle() const {
543 SkASSERT(!final());
544 return fToAngle;
545 }
546
547 int windSum() const {
548 SkASSERT(!final());
549 return fWindSum;
550 }
551
552 int windValue() const {
caryclarkef4f32a2016-08-24 09:24:18 -0700553 SkOPASSERT(!final());
caryclark54359292015-03-26 07:52:43 -0700554 return fWindValue;
555 }
556
557private: // no direct access to internals to avoid treating a span base as a span
558 SkOpSpan* fCoincident; // linked list of spans coincident with this one (may point to itself)
559 SkOpAngle* fToAngle; // points to next angle from span start to end
560 SkOpSpanBase* fNext; // next intersection point
caryclark@google.com07393ca2013-04-08 11:47:37 +0000561 int fWindSum; // accumulated from contours surrounding this one.
562 int fOppSum; // for binary operators: the opposite winding sum
563 int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident
564 int fOppValue; // normally 0 -- when binary coincident edges combine, opp value goes here
caryclark624637c2015-05-11 07:21:27 -0700565 int fTopTTry; // specifies direction and t value to try next
caryclark@google.com07393ca2013-04-08 11:47:37 +0000566 bool fDone; // if set, this span to next higher T has been processed
caryclarkef784fb2015-10-30 12:03:06 -0700567 mutable bool fAlreadyAdded;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000568};
569
570#endif