xref: /aosp_15_r20/external/skia/src/pathops/SkOpSpan.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkOpSpan_DEFINED
8*c8dee2aaSAndroid Build Coastguard Worker #define SkOpSpan_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMath.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker 
16*c8dee2aaSAndroid Build Coastguard Worker class SkOpAngle;
17*c8dee2aaSAndroid Build Coastguard Worker class SkOpCoincidence;
18*c8dee2aaSAndroid Build Coastguard Worker class SkOpContour;
19*c8dee2aaSAndroid Build Coastguard Worker class SkOpSegment;
20*c8dee2aaSAndroid Build Coastguard Worker class SkOpSpan;
21*c8dee2aaSAndroid Build Coastguard Worker class SkOpSpanBase;
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker // subset of op span used by terminal span (when t is equal to one)
24*c8dee2aaSAndroid Build Coastguard Worker class SkOpPtT {
25*c8dee2aaSAndroid Build Coastguard Worker public:
26*c8dee2aaSAndroid Build Coastguard Worker     enum {
27*c8dee2aaSAndroid Build Coastguard Worker         kIsAlias = 1,
28*c8dee2aaSAndroid Build Coastguard Worker         kIsDuplicate = 1
29*c8dee2aaSAndroid Build Coastguard Worker     };
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* active() const;
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker     // please keep in sync with debugAddOpp()
addOpp(SkOpPtT * opp,SkOpPtT * oppPrev)34*c8dee2aaSAndroid Build Coastguard Worker     void addOpp(SkOpPtT* opp, SkOpPtT* oppPrev) {
35*c8dee2aaSAndroid Build Coastguard Worker         SkOpPtT* oldNext = this->fNext;
36*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this != opp);
37*c8dee2aaSAndroid Build Coastguard Worker         this->fNext = opp;
38*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(oppPrev != oldNext);
39*c8dee2aaSAndroid Build Coastguard Worker         oppPrev->fNext = oldNext;
40*c8dee2aaSAndroid Build Coastguard Worker     }
41*c8dee2aaSAndroid Build Coastguard Worker 
42*c8dee2aaSAndroid Build Coastguard Worker     bool alias() const;
coincident()43*c8dee2aaSAndroid Build Coastguard Worker     bool coincident() const { return fCoincident; }
44*c8dee2aaSAndroid Build Coastguard Worker     bool contains(const SkOpPtT* ) const;
45*c8dee2aaSAndroid Build Coastguard Worker     bool contains(const SkOpSegment*, const SkPoint& ) const;
46*c8dee2aaSAndroid Build Coastguard Worker     bool contains(const SkOpSegment*, double t) const;
47*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* contains(const SkOpSegment* ) const;
48*c8dee2aaSAndroid Build Coastguard Worker     SkOpContour* contour() const;
49*c8dee2aaSAndroid Build Coastguard Worker 
debugID()50*c8dee2aaSAndroid Build Coastguard Worker     int debugID() const {
51*c8dee2aaSAndroid Build Coastguard Worker         return SkDEBUGRELEASE(fID, -1);
52*c8dee2aaSAndroid Build Coastguard Worker     }
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker     void debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const;
55*c8dee2aaSAndroid Build Coastguard Worker     const SkOpAngle* debugAngle(int id) const;
56*c8dee2aaSAndroid Build Coastguard Worker     const SkOpCoincidence* debugCoincidence() const;
57*c8dee2aaSAndroid Build Coastguard Worker     bool debugContains(const SkOpPtT* ) const;
58*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* debugContains(const SkOpSegment* check) const;
59*c8dee2aaSAndroid Build Coastguard Worker     SkOpContour* debugContour(int id) const;
60*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* debugEnder(const SkOpPtT* end) const;
61*c8dee2aaSAndroid Build Coastguard Worker     int debugLoopLimit(bool report) const;
62*c8dee2aaSAndroid Build Coastguard Worker     bool debugMatchID(int id) const;
63*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* debugOppPrev(const SkOpPtT* opp) const;
64*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* debugPtT(int id) const;
65*c8dee2aaSAndroid Build Coastguard Worker     void debugResetCoinT() const;
66*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSegment* debugSegment(int id) const;
67*c8dee2aaSAndroid Build Coastguard Worker     void debugSetCoinT(int ) const;
68*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpanBase* debugSpan(int id) const;
69*c8dee2aaSAndroid Build Coastguard Worker     void debugValidate() const;
70*c8dee2aaSAndroid Build Coastguard Worker 
deleted()71*c8dee2aaSAndroid Build Coastguard Worker     bool deleted() const {
72*c8dee2aaSAndroid Build Coastguard Worker         return fDeleted;
73*c8dee2aaSAndroid Build Coastguard Worker     }
74*c8dee2aaSAndroid Build Coastguard Worker 
duplicate()75*c8dee2aaSAndroid Build Coastguard Worker     bool duplicate() const {
76*c8dee2aaSAndroid Build Coastguard Worker         return fDuplicatePt;
77*c8dee2aaSAndroid Build Coastguard Worker     }
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker     void dump() const;  // available to testing only
80*c8dee2aaSAndroid Build Coastguard Worker     void dumpAll() const;
81*c8dee2aaSAndroid Build Coastguard Worker     void dumpBase() const;
82*c8dee2aaSAndroid Build Coastguard Worker 
83*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* find(const SkOpSegment* ) const;
84*c8dee2aaSAndroid Build Coastguard Worker     SkOpGlobalState* globalState() const;
85*c8dee2aaSAndroid Build Coastguard Worker     void init(SkOpSpanBase* , double t, const SkPoint& , bool dup);
86*c8dee2aaSAndroid Build Coastguard Worker 
insert(SkOpPtT * span)87*c8dee2aaSAndroid Build Coastguard Worker     void insert(SkOpPtT* span) {
88*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(span != this);
89*c8dee2aaSAndroid Build Coastguard Worker         span->fNext = fNext;
90*c8dee2aaSAndroid Build Coastguard Worker         fNext = span;
91*c8dee2aaSAndroid Build Coastguard Worker     }
92*c8dee2aaSAndroid Build Coastguard Worker 
next()93*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* next() const {
94*c8dee2aaSAndroid Build Coastguard Worker         return fNext;
95*c8dee2aaSAndroid Build Coastguard Worker     }
96*c8dee2aaSAndroid Build Coastguard Worker 
next()97*c8dee2aaSAndroid Build Coastguard Worker     SkOpPtT* next() {
98*c8dee2aaSAndroid Build Coastguard Worker         return fNext;
99*c8dee2aaSAndroid Build Coastguard Worker     }
100*c8dee2aaSAndroid Build Coastguard Worker 
101*c8dee2aaSAndroid Build Coastguard Worker     bool onEnd() const;
102*c8dee2aaSAndroid Build Coastguard Worker 
103*c8dee2aaSAndroid Build Coastguard Worker     // returns nullptr if this is already in the opp ptT loop
oppPrev(const SkOpPtT * opp)104*c8dee2aaSAndroid Build Coastguard Worker     SkOpPtT* oppPrev(const SkOpPtT* opp) const {
105*c8dee2aaSAndroid Build Coastguard Worker         // find the fOpp ptr to opp
106*c8dee2aaSAndroid Build Coastguard Worker         SkOpPtT* oppPrev = opp->fNext;
107*c8dee2aaSAndroid Build Coastguard Worker         if (oppPrev == this) {
108*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
109*c8dee2aaSAndroid Build Coastguard Worker         }
110*c8dee2aaSAndroid Build Coastguard Worker         while (oppPrev->fNext != opp) {
111*c8dee2aaSAndroid Build Coastguard Worker             oppPrev = oppPrev->fNext;
112*c8dee2aaSAndroid Build Coastguard Worker             if (oppPrev == this) {
113*c8dee2aaSAndroid Build Coastguard Worker                 return nullptr;
114*c8dee2aaSAndroid Build Coastguard Worker             }
115*c8dee2aaSAndroid Build Coastguard Worker         }
116*c8dee2aaSAndroid Build Coastguard Worker         return oppPrev;
117*c8dee2aaSAndroid Build Coastguard Worker     }
118*c8dee2aaSAndroid Build Coastguard Worker 
Overlaps(const SkOpPtT * s1,const SkOpPtT * e1,const SkOpPtT * s2,const SkOpPtT * e2,const SkOpPtT ** sOut,const SkOpPtT ** eOut)119*c8dee2aaSAndroid Build Coastguard Worker     static bool Overlaps(const SkOpPtT* s1, const SkOpPtT* e1, const SkOpPtT* s2,
120*c8dee2aaSAndroid Build Coastguard Worker             const SkOpPtT* e2, const SkOpPtT** sOut, const SkOpPtT** eOut) {
121*c8dee2aaSAndroid Build Coastguard Worker         const SkOpPtT* start1 = s1->fT < e1->fT ? s1 : e1;
122*c8dee2aaSAndroid Build Coastguard Worker         const SkOpPtT* start2 = s2->fT < e2->fT ? s2 : e2;
123*c8dee2aaSAndroid Build Coastguard Worker         *sOut = between(s1->fT, start2->fT, e1->fT) ? start2
124*c8dee2aaSAndroid Build Coastguard Worker                 : between(s2->fT, start1->fT, e2->fT) ? start1 : nullptr;
125*c8dee2aaSAndroid Build Coastguard Worker         const SkOpPtT* end1 = s1->fT < e1->fT ? e1 : s1;
126*c8dee2aaSAndroid Build Coastguard Worker         const SkOpPtT* end2 = s2->fT < e2->fT ? e2 : s2;
127*c8dee2aaSAndroid Build Coastguard Worker         *eOut = between(s1->fT, end2->fT, e1->fT) ? end2
128*c8dee2aaSAndroid Build Coastguard Worker                 : between(s2->fT, end1->fT, e2->fT) ? end1 : nullptr;
129*c8dee2aaSAndroid Build Coastguard Worker         if (*sOut == *eOut) {
130*c8dee2aaSAndroid Build Coastguard Worker             SkOPOBJASSERT(s1, start1->fT >= end2->fT || start2->fT >= end1->fT);
131*c8dee2aaSAndroid Build Coastguard Worker             return false;
132*c8dee2aaSAndroid Build Coastguard Worker         }
133*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!*sOut || *sOut != *eOut);
134*c8dee2aaSAndroid Build Coastguard Worker         return *sOut && *eOut;
135*c8dee2aaSAndroid Build Coastguard Worker     }
136*c8dee2aaSAndroid Build Coastguard Worker 
137*c8dee2aaSAndroid Build Coastguard Worker     bool ptAlreadySeen(const SkOpPtT* head) const;
138*c8dee2aaSAndroid Build Coastguard Worker     SkOpPtT* prev();
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSegment* segment() const;
141*c8dee2aaSAndroid Build Coastguard Worker     SkOpSegment* segment();
142*c8dee2aaSAndroid Build Coastguard Worker 
setCoincident()143*c8dee2aaSAndroid Build Coastguard Worker     void setCoincident() const {
144*c8dee2aaSAndroid Build Coastguard Worker         SkOPASSERT(!fDeleted);
145*c8dee2aaSAndroid Build Coastguard Worker         fCoincident = true;
146*c8dee2aaSAndroid Build Coastguard Worker     }
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker     void setDeleted();
149*c8dee2aaSAndroid Build Coastguard Worker 
setSpan(const SkOpSpanBase * span)150*c8dee2aaSAndroid Build Coastguard Worker     void setSpan(const SkOpSpanBase* span) {
151*c8dee2aaSAndroid Build Coastguard Worker         fSpan = const_cast<SkOpSpanBase*>(span);
152*c8dee2aaSAndroid Build Coastguard Worker     }
153*c8dee2aaSAndroid Build Coastguard Worker 
span()154*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpanBase* span() const {
155*c8dee2aaSAndroid Build Coastguard Worker         return fSpan;
156*c8dee2aaSAndroid Build Coastguard Worker     }
157*c8dee2aaSAndroid Build Coastguard Worker 
span()158*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpanBase* span() {
159*c8dee2aaSAndroid Build Coastguard Worker         return fSpan;
160*c8dee2aaSAndroid Build Coastguard Worker     }
161*c8dee2aaSAndroid Build Coastguard Worker 
starter(const SkOpPtT * end)162*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* starter(const SkOpPtT* end) const {
163*c8dee2aaSAndroid Build Coastguard Worker         return fT < end->fT ? this : end;
164*c8dee2aaSAndroid Build Coastguard Worker     }
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker     double fT;
167*c8dee2aaSAndroid Build Coastguard Worker     SkPoint fPt;   // cache of point value at this t
168*c8dee2aaSAndroid Build Coastguard Worker protected:
169*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpanBase* fSpan;  // contains winding data
170*c8dee2aaSAndroid Build Coastguard Worker     SkOpPtT* fNext;  // intersection on opposite curve or alias on this curve
171*c8dee2aaSAndroid Build Coastguard Worker     bool fDeleted;  // set if removed from span list
172*c8dee2aaSAndroid Build Coastguard Worker     bool fDuplicatePt;  // set if identical pt is somewhere in the next loop
173*c8dee2aaSAndroid Build Coastguard Worker     // below mutable since referrer is otherwise always const
174*c8dee2aaSAndroid Build Coastguard Worker     mutable bool fCoincident;  // set if at some point a coincident span pointed here
175*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(int fID;)
176*c8dee2aaSAndroid Build Coastguard Worker };
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker class SkOpSpanBase {
179*c8dee2aaSAndroid Build Coastguard Worker public:
180*c8dee2aaSAndroid Build Coastguard Worker     enum class Collapsed {
181*c8dee2aaSAndroid Build Coastguard Worker         kNo,
182*c8dee2aaSAndroid Build Coastguard Worker         kYes,
183*c8dee2aaSAndroid Build Coastguard Worker         kError,
184*c8dee2aaSAndroid Build Coastguard Worker     };
185*c8dee2aaSAndroid Build Coastguard Worker 
186*c8dee2aaSAndroid Build Coastguard Worker     bool addOpp(SkOpSpanBase* opp);
187*c8dee2aaSAndroid Build Coastguard Worker 
bumpSpanAdds()188*c8dee2aaSAndroid Build Coastguard Worker     void bumpSpanAdds() {
189*c8dee2aaSAndroid Build Coastguard Worker         ++fSpanAdds;
190*c8dee2aaSAndroid Build Coastguard Worker     }
191*c8dee2aaSAndroid Build Coastguard Worker 
chased()192*c8dee2aaSAndroid Build Coastguard Worker     bool chased() const {
193*c8dee2aaSAndroid Build Coastguard Worker         return fChased;
194*c8dee2aaSAndroid Build Coastguard Worker     }
195*c8dee2aaSAndroid Build Coastguard Worker 
196*c8dee2aaSAndroid Build Coastguard Worker     void checkForCollapsedCoincidence();
197*c8dee2aaSAndroid Build Coastguard Worker 
coinEnd()198*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpanBase* coinEnd() const {
199*c8dee2aaSAndroid Build Coastguard Worker         return fCoinEnd;
200*c8dee2aaSAndroid Build Coastguard Worker     }
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker     Collapsed collapsed(double s, double e) const;
203*c8dee2aaSAndroid Build Coastguard Worker     bool contains(const SkOpSpanBase* ) const;
204*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* contains(const SkOpSegment* ) const;
205*c8dee2aaSAndroid Build Coastguard Worker 
containsCoinEnd(const SkOpSpanBase * coin)206*c8dee2aaSAndroid Build Coastguard Worker     bool containsCoinEnd(const SkOpSpanBase* coin) const {
207*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this != coin);
208*c8dee2aaSAndroid Build Coastguard Worker         const SkOpSpanBase* next = this;
209*c8dee2aaSAndroid Build Coastguard Worker         while ((next = next->fCoinEnd) != this) {
210*c8dee2aaSAndroid Build Coastguard Worker             if (next == coin) {
211*c8dee2aaSAndroid Build Coastguard Worker                 return true;
212*c8dee2aaSAndroid Build Coastguard Worker             }
213*c8dee2aaSAndroid Build Coastguard Worker         }
214*c8dee2aaSAndroid Build Coastguard Worker         return false;
215*c8dee2aaSAndroid Build Coastguard Worker     }
216*c8dee2aaSAndroid Build Coastguard Worker 
217*c8dee2aaSAndroid Build Coastguard Worker     bool containsCoinEnd(const SkOpSegment* ) const;
218*c8dee2aaSAndroid Build Coastguard Worker     SkOpContour* contour() const;
219*c8dee2aaSAndroid Build Coastguard Worker 
debugBumpCount()220*c8dee2aaSAndroid Build Coastguard Worker     int debugBumpCount() {
221*c8dee2aaSAndroid Build Coastguard Worker         return SkDEBUGRELEASE(++fCount, -1);
222*c8dee2aaSAndroid Build Coastguard Worker     }
223*c8dee2aaSAndroid Build Coastguard Worker 
debugID()224*c8dee2aaSAndroid Build Coastguard Worker     int debugID() const {
225*c8dee2aaSAndroid Build Coastguard Worker         return SkDEBUGRELEASE(fID, -1);
226*c8dee2aaSAndroid Build Coastguard Worker     }
227*c8dee2aaSAndroid Build Coastguard Worker 
228*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN
229*c8dee2aaSAndroid Build Coastguard Worker     void debugAddOpp(SkPathOpsDebug::GlitchLog* , const SkOpSpanBase* opp) const;
230*c8dee2aaSAndroid Build Coastguard Worker #endif
231*c8dee2aaSAndroid Build Coastguard Worker     bool debugAlignedEnd(double t, const SkPoint& pt) const;
232*c8dee2aaSAndroid Build Coastguard Worker     bool debugAlignedInner() const;
233*c8dee2aaSAndroid Build Coastguard Worker     const SkOpAngle* debugAngle(int id) const;
234*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN
235*c8dee2aaSAndroid Build Coastguard Worker     void debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* ) const;
236*c8dee2aaSAndroid Build Coastguard Worker #endif
237*c8dee2aaSAndroid Build Coastguard Worker     const SkOpCoincidence* debugCoincidence() const;
238*c8dee2aaSAndroid Build Coastguard Worker     bool debugCoinEndLoopCheck() const;
239*c8dee2aaSAndroid Build Coastguard Worker     SkOpContour* debugContour(int id) const;
240*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
debugDeleted()241*c8dee2aaSAndroid Build Coastguard Worker     bool debugDeleted() const { return fDebugDeleted; }
242*c8dee2aaSAndroid Build Coastguard Worker #endif
243*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN
244*c8dee2aaSAndroid Build Coastguard Worker     void debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* ,
245*c8dee2aaSAndroid Build Coastguard Worker                             const SkOpSpanBase* ) const;
246*c8dee2aaSAndroid Build Coastguard Worker     void debugMergeMatches(SkPathOpsDebug::GlitchLog* log,
247*c8dee2aaSAndroid Build Coastguard Worker                            const SkOpSpanBase* opp) const;
248*c8dee2aaSAndroid Build Coastguard Worker #endif
249*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* debugPtT(int id) const;
250*c8dee2aaSAndroid Build Coastguard Worker     void debugResetCoinT() const;
251*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSegment* debugSegment(int id) const;
252*c8dee2aaSAndroid Build Coastguard Worker     void debugSetCoinT(int ) const;
253*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
debugSetDeleted()254*c8dee2aaSAndroid Build Coastguard Worker     void debugSetDeleted() { fDebugDeleted = true; }
255*c8dee2aaSAndroid Build Coastguard Worker #endif
256*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpanBase* debugSpan(int id) const;
257*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpan* debugStarter(SkOpSpanBase const** endPtr) const;
258*c8dee2aaSAndroid Build Coastguard Worker     SkOpGlobalState* globalState() const;
259*c8dee2aaSAndroid Build Coastguard Worker     void debugValidate() const;
260*c8dee2aaSAndroid Build Coastguard Worker 
deleted()261*c8dee2aaSAndroid Build Coastguard Worker     bool deleted() const {
262*c8dee2aaSAndroid Build Coastguard Worker         return fPtT.deleted();
263*c8dee2aaSAndroid Build Coastguard Worker     }
264*c8dee2aaSAndroid Build Coastguard Worker 
265*c8dee2aaSAndroid Build Coastguard Worker     void dump() const;  // available to testing only
266*c8dee2aaSAndroid Build Coastguard Worker     void dumpCoin() const;
267*c8dee2aaSAndroid Build Coastguard Worker     void dumpAll() const;
268*c8dee2aaSAndroid Build Coastguard Worker     void dumpBase() const;
269*c8dee2aaSAndroid Build Coastguard Worker     void dumpHead() const;
270*c8dee2aaSAndroid Build Coastguard Worker 
final()271*c8dee2aaSAndroid Build Coastguard Worker     bool final() const {
272*c8dee2aaSAndroid Build Coastguard Worker         return fPtT.fT == 1;
273*c8dee2aaSAndroid Build Coastguard Worker     }
274*c8dee2aaSAndroid Build Coastguard Worker 
fromAngle()275*c8dee2aaSAndroid Build Coastguard Worker     SkOpAngle* fromAngle() const {
276*c8dee2aaSAndroid Build Coastguard Worker         return fFromAngle;
277*c8dee2aaSAndroid Build Coastguard Worker     }
278*c8dee2aaSAndroid Build Coastguard Worker 
279*c8dee2aaSAndroid Build Coastguard Worker     void initBase(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
280*c8dee2aaSAndroid Build Coastguard Worker 
281*c8dee2aaSAndroid Build Coastguard Worker     // Please keep this in sync with debugInsertCoinEnd()
insertCoinEnd(SkOpSpanBase * coin)282*c8dee2aaSAndroid Build Coastguard Worker     void insertCoinEnd(SkOpSpanBase* coin) {
283*c8dee2aaSAndroid Build Coastguard Worker         if (containsCoinEnd(coin)) {
284*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(coin->containsCoinEnd(this));
285*c8dee2aaSAndroid Build Coastguard Worker             return;
286*c8dee2aaSAndroid Build Coastguard Worker         }
287*c8dee2aaSAndroid Build Coastguard Worker         debugValidate();
288*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this != coin);
289*c8dee2aaSAndroid Build Coastguard Worker         SkOpSpanBase* coinNext = coin->fCoinEnd;
290*c8dee2aaSAndroid Build Coastguard Worker         coin->fCoinEnd = this->fCoinEnd;
291*c8dee2aaSAndroid Build Coastguard Worker         this->fCoinEnd = coinNext;
292*c8dee2aaSAndroid Build Coastguard Worker         debugValidate();
293*c8dee2aaSAndroid Build Coastguard Worker     }
294*c8dee2aaSAndroid Build Coastguard Worker 
295*c8dee2aaSAndroid Build Coastguard Worker     void merge(SkOpSpan* span);
296*c8dee2aaSAndroid Build Coastguard Worker     bool mergeMatches(SkOpSpanBase* opp);
297*c8dee2aaSAndroid Build Coastguard Worker 
prev()298*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpan* prev() const {
299*c8dee2aaSAndroid Build Coastguard Worker         return fPrev;
300*c8dee2aaSAndroid Build Coastguard Worker     }
301*c8dee2aaSAndroid Build Coastguard Worker 
prev()302*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpan* prev() {
303*c8dee2aaSAndroid Build Coastguard Worker         return fPrev;
304*c8dee2aaSAndroid Build Coastguard Worker     }
305*c8dee2aaSAndroid Build Coastguard Worker 
pt()306*c8dee2aaSAndroid Build Coastguard Worker     const SkPoint& pt() const {
307*c8dee2aaSAndroid Build Coastguard Worker         return fPtT.fPt;
308*c8dee2aaSAndroid Build Coastguard Worker     }
309*c8dee2aaSAndroid Build Coastguard Worker 
ptT()310*c8dee2aaSAndroid Build Coastguard Worker     const SkOpPtT* ptT() const {
311*c8dee2aaSAndroid Build Coastguard Worker         return &fPtT;
312*c8dee2aaSAndroid Build Coastguard Worker     }
313*c8dee2aaSAndroid Build Coastguard Worker 
ptT()314*c8dee2aaSAndroid Build Coastguard Worker     SkOpPtT* ptT() {
315*c8dee2aaSAndroid Build Coastguard Worker         return &fPtT;
316*c8dee2aaSAndroid Build Coastguard Worker     }
317*c8dee2aaSAndroid Build Coastguard Worker 
segment()318*c8dee2aaSAndroid Build Coastguard Worker     SkOpSegment* segment() const {
319*c8dee2aaSAndroid Build Coastguard Worker         return fSegment;
320*c8dee2aaSAndroid Build Coastguard Worker     }
321*c8dee2aaSAndroid Build Coastguard Worker 
setAligned()322*c8dee2aaSAndroid Build Coastguard Worker     void setAligned() {
323*c8dee2aaSAndroid Build Coastguard Worker         fAligned = true;
324*c8dee2aaSAndroid Build Coastguard Worker     }
325*c8dee2aaSAndroid Build Coastguard Worker 
setChased(bool chased)326*c8dee2aaSAndroid Build Coastguard Worker     void setChased(bool chased) {
327*c8dee2aaSAndroid Build Coastguard Worker         fChased = chased;
328*c8dee2aaSAndroid Build Coastguard Worker     }
329*c8dee2aaSAndroid Build Coastguard Worker 
setFromAngle(SkOpAngle * angle)330*c8dee2aaSAndroid Build Coastguard Worker     void setFromAngle(SkOpAngle* angle) {
331*c8dee2aaSAndroid Build Coastguard Worker         fFromAngle = angle;
332*c8dee2aaSAndroid Build Coastguard Worker     }
333*c8dee2aaSAndroid Build Coastguard Worker 
setPrev(SkOpSpan * prev)334*c8dee2aaSAndroid Build Coastguard Worker     void setPrev(SkOpSpan* prev) {
335*c8dee2aaSAndroid Build Coastguard Worker         fPrev = prev;
336*c8dee2aaSAndroid Build Coastguard Worker     }
337*c8dee2aaSAndroid Build Coastguard Worker 
simple()338*c8dee2aaSAndroid Build Coastguard Worker     bool simple() const {
339*c8dee2aaSAndroid Build Coastguard Worker         fPtT.debugValidate();
340*c8dee2aaSAndroid Build Coastguard Worker         return fPtT.next()->next() == &fPtT;
341*c8dee2aaSAndroid Build Coastguard Worker     }
342*c8dee2aaSAndroid Build Coastguard Worker 
spanAddsCount()343*c8dee2aaSAndroid Build Coastguard Worker     int spanAddsCount() const {
344*c8dee2aaSAndroid Build Coastguard Worker         return fSpanAdds;
345*c8dee2aaSAndroid Build Coastguard Worker     }
346*c8dee2aaSAndroid Build Coastguard Worker 
starter(const SkOpSpanBase * end)347*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpan* starter(const SkOpSpanBase* end) const {
348*c8dee2aaSAndroid Build Coastguard Worker         const SkOpSpanBase* result = t() < end->t() ? this : end;
349*c8dee2aaSAndroid Build Coastguard Worker         return result->upCast();
350*c8dee2aaSAndroid Build Coastguard Worker     }
351*c8dee2aaSAndroid Build Coastguard Worker 
starter(SkOpSpanBase * end)352*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpan* starter(SkOpSpanBase* end) {
353*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->segment() == end->segment());
354*c8dee2aaSAndroid Build Coastguard Worker         SkOpSpanBase* result = t() < end->t() ? this : end;
355*c8dee2aaSAndroid Build Coastguard Worker         return result->upCast();
356*c8dee2aaSAndroid Build Coastguard Worker     }
357*c8dee2aaSAndroid Build Coastguard Worker 
starter(SkOpSpanBase ** endPtr)358*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpan* starter(SkOpSpanBase** endPtr) {
359*c8dee2aaSAndroid Build Coastguard Worker         SkOpSpanBase* end = *endPtr;
360*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->segment() == end->segment());
361*c8dee2aaSAndroid Build Coastguard Worker         SkOpSpanBase* result;
362*c8dee2aaSAndroid Build Coastguard Worker         if (t() < end->t()) {
363*c8dee2aaSAndroid Build Coastguard Worker             result = this;
364*c8dee2aaSAndroid Build Coastguard Worker         } else {
365*c8dee2aaSAndroid Build Coastguard Worker             result = end;
366*c8dee2aaSAndroid Build Coastguard Worker             *endPtr = this;
367*c8dee2aaSAndroid Build Coastguard Worker         }
368*c8dee2aaSAndroid Build Coastguard Worker         return result->upCast();
369*c8dee2aaSAndroid Build Coastguard Worker     }
370*c8dee2aaSAndroid Build Coastguard Worker 
step(const SkOpSpanBase * end)371*c8dee2aaSAndroid Build Coastguard Worker     int step(const SkOpSpanBase* end) const {
372*c8dee2aaSAndroid Build Coastguard Worker         return t() < end->t() ? 1 : -1;
373*c8dee2aaSAndroid Build Coastguard Worker     }
374*c8dee2aaSAndroid Build Coastguard Worker 
t()375*c8dee2aaSAndroid Build Coastguard Worker     double t() const {
376*c8dee2aaSAndroid Build Coastguard Worker         return fPtT.fT;
377*c8dee2aaSAndroid Build Coastguard Worker     }
378*c8dee2aaSAndroid Build Coastguard Worker 
unaligned()379*c8dee2aaSAndroid Build Coastguard Worker     void unaligned() {
380*c8dee2aaSAndroid Build Coastguard Worker         fAligned = false;
381*c8dee2aaSAndroid Build Coastguard Worker     }
382*c8dee2aaSAndroid Build Coastguard Worker 
upCast()383*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpan* upCast() {
384*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
385*c8dee2aaSAndroid Build Coastguard Worker         return (SkOpSpan*) this;
386*c8dee2aaSAndroid Build Coastguard Worker     }
387*c8dee2aaSAndroid Build Coastguard Worker 
upCast()388*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpan* upCast() const {
389*c8dee2aaSAndroid Build Coastguard Worker         SkOPASSERT(!final());
390*c8dee2aaSAndroid Build Coastguard Worker         return (const SkOpSpan*) this;
391*c8dee2aaSAndroid Build Coastguard Worker     }
392*c8dee2aaSAndroid Build Coastguard Worker 
upCastable()393*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpan* upCastable() {
394*c8dee2aaSAndroid Build Coastguard Worker         return final() ? nullptr : upCast();
395*c8dee2aaSAndroid Build Coastguard Worker     }
396*c8dee2aaSAndroid Build Coastguard Worker 
upCastable()397*c8dee2aaSAndroid Build Coastguard Worker     const SkOpSpan* upCastable() const {
398*c8dee2aaSAndroid Build Coastguard Worker         return final() ? nullptr : upCast();
399*c8dee2aaSAndroid Build Coastguard Worker     }
400*c8dee2aaSAndroid Build Coastguard Worker 
401*c8dee2aaSAndroid Build Coastguard Worker private:
402*c8dee2aaSAndroid Build Coastguard Worker     void alignInner();
403*c8dee2aaSAndroid Build Coastguard Worker 
404*c8dee2aaSAndroid Build Coastguard Worker protected:  // no direct access to internals to avoid treating a span base as a span
405*c8dee2aaSAndroid Build Coastguard Worker     SkOpPtT fPtT;  // list of points and t values associated with the start of this span
406*c8dee2aaSAndroid Build Coastguard Worker     SkOpSegment* fSegment;  // segment that contains this span
407*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpanBase* fCoinEnd;  // linked list of coincident spans that end here (may point to itself)
408*c8dee2aaSAndroid Build Coastguard Worker     SkOpAngle* fFromAngle;  // points to next angle from span start to end
409*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpan* fPrev;  // previous intersection point
410*c8dee2aaSAndroid Build Coastguard Worker     int fSpanAdds;  // number of times intersections have been added to span
411*c8dee2aaSAndroid Build Coastguard Worker     bool fAligned;
412*c8dee2aaSAndroid Build Coastguard Worker     bool fChased;  // set after span has been added to chase array
413*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(int fCount;)  // number of pt/t pairs added
414*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(int fID;)
415*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(bool fDebugDeleted;)  // set when span was merged with another span
416*c8dee2aaSAndroid Build Coastguard Worker };
417*c8dee2aaSAndroid Build Coastguard Worker 
418*c8dee2aaSAndroid Build Coastguard Worker class SkOpSpan : public SkOpSpanBase {
419*c8dee2aaSAndroid Build Coastguard Worker public:
alreadyAdded()420*c8dee2aaSAndroid Build Coastguard Worker     bool alreadyAdded() const {
421*c8dee2aaSAndroid Build Coastguard Worker         if (fAlreadyAdded) {
422*c8dee2aaSAndroid Build Coastguard Worker             return true;
423*c8dee2aaSAndroid Build Coastguard Worker         }
424*c8dee2aaSAndroid Build Coastguard Worker         return false;
425*c8dee2aaSAndroid Build Coastguard Worker     }
426*c8dee2aaSAndroid Build Coastguard Worker 
clearCoincident()427*c8dee2aaSAndroid Build Coastguard Worker     bool clearCoincident() {
428*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
429*c8dee2aaSAndroid Build Coastguard Worker         if (fCoincident == this) {
430*c8dee2aaSAndroid Build Coastguard Worker             return false;
431*c8dee2aaSAndroid Build Coastguard Worker         }
432*c8dee2aaSAndroid Build Coastguard Worker         fCoincident = this;
433*c8dee2aaSAndroid Build Coastguard Worker         return true;
434*c8dee2aaSAndroid Build Coastguard Worker     }
435*c8dee2aaSAndroid Build Coastguard Worker 
436*c8dee2aaSAndroid Build Coastguard Worker     int computeWindSum();
437*c8dee2aaSAndroid Build Coastguard Worker     bool containsCoincidence(const SkOpSegment* ) const;
438*c8dee2aaSAndroid Build Coastguard Worker 
containsCoincidence(const SkOpSpan * coin)439*c8dee2aaSAndroid Build Coastguard Worker     bool containsCoincidence(const SkOpSpan* coin) const {
440*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this != coin);
441*c8dee2aaSAndroid Build Coastguard Worker         const SkOpSpan* next = this;
442*c8dee2aaSAndroid Build Coastguard Worker         while ((next = next->fCoincident) != this) {
443*c8dee2aaSAndroid Build Coastguard Worker             if (next == coin) {
444*c8dee2aaSAndroid Build Coastguard Worker                 return true;
445*c8dee2aaSAndroid Build Coastguard Worker             }
446*c8dee2aaSAndroid Build Coastguard Worker         }
447*c8dee2aaSAndroid Build Coastguard Worker         return false;
448*c8dee2aaSAndroid Build Coastguard Worker     }
449*c8dee2aaSAndroid Build Coastguard Worker 
450*c8dee2aaSAndroid Build Coastguard Worker     bool debugCoinLoopCheck() const;
451*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN
452*c8dee2aaSAndroid Build Coastguard Worker     void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* , const SkOpSpan* ) const;
453*c8dee2aaSAndroid Build Coastguard Worker     void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* ,
454*c8dee2aaSAndroid Build Coastguard Worker                                 const SkOpSegment* , bool flipped, bool ordered) const;
455*c8dee2aaSAndroid Build Coastguard Worker #endif
456*c8dee2aaSAndroid Build Coastguard Worker     void dumpCoin() const;
457*c8dee2aaSAndroid Build Coastguard Worker     bool dumpSpan() const;
458*c8dee2aaSAndroid Build Coastguard Worker 
done()459*c8dee2aaSAndroid Build Coastguard Worker     bool done() const {
460*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
461*c8dee2aaSAndroid Build Coastguard Worker         return fDone;
462*c8dee2aaSAndroid Build Coastguard Worker     }
463*c8dee2aaSAndroid Build Coastguard Worker 
464*c8dee2aaSAndroid Build Coastguard Worker     void init(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
465*c8dee2aaSAndroid Build Coastguard Worker     bool insertCoincidence(const SkOpSegment* , bool flipped, bool ordered);
466*c8dee2aaSAndroid Build Coastguard Worker 
467*c8dee2aaSAndroid Build Coastguard Worker     // Please keep this in sync with debugInsertCoincidence()
insertCoincidence(SkOpSpan * coin)468*c8dee2aaSAndroid Build Coastguard Worker     void insertCoincidence(SkOpSpan* coin) {
469*c8dee2aaSAndroid Build Coastguard Worker         if (containsCoincidence(coin)) {
470*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(coin->containsCoincidence(this));
471*c8dee2aaSAndroid Build Coastguard Worker             return;
472*c8dee2aaSAndroid Build Coastguard Worker         }
473*c8dee2aaSAndroid Build Coastguard Worker         debugValidate();
474*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this != coin);
475*c8dee2aaSAndroid Build Coastguard Worker         SkOpSpan* coinNext = coin->fCoincident;
476*c8dee2aaSAndroid Build Coastguard Worker         coin->fCoincident = this->fCoincident;
477*c8dee2aaSAndroid Build Coastguard Worker         this->fCoincident = coinNext;
478*c8dee2aaSAndroid Build Coastguard Worker         debugValidate();
479*c8dee2aaSAndroid Build Coastguard Worker     }
480*c8dee2aaSAndroid Build Coastguard Worker 
isCanceled()481*c8dee2aaSAndroid Build Coastguard Worker     bool isCanceled() const {
482*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
483*c8dee2aaSAndroid Build Coastguard Worker         return fWindValue == 0 && fOppValue == 0;
484*c8dee2aaSAndroid Build Coastguard Worker     }
485*c8dee2aaSAndroid Build Coastguard Worker 
isCoincident()486*c8dee2aaSAndroid Build Coastguard Worker     bool isCoincident() const {
487*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
488*c8dee2aaSAndroid Build Coastguard Worker         return fCoincident != this;
489*c8dee2aaSAndroid Build Coastguard Worker     }
490*c8dee2aaSAndroid Build Coastguard Worker 
markAdded()491*c8dee2aaSAndroid Build Coastguard Worker     void markAdded() {
492*c8dee2aaSAndroid Build Coastguard Worker         fAlreadyAdded = true;
493*c8dee2aaSAndroid Build Coastguard Worker     }
494*c8dee2aaSAndroid Build Coastguard Worker 
next()495*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpanBase* next() const {
496*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
497*c8dee2aaSAndroid Build Coastguard Worker         return fNext;
498*c8dee2aaSAndroid Build Coastguard Worker     }
499*c8dee2aaSAndroid Build Coastguard Worker 
oppSum()500*c8dee2aaSAndroid Build Coastguard Worker     int oppSum() const {
501*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
502*c8dee2aaSAndroid Build Coastguard Worker         return fOppSum;
503*c8dee2aaSAndroid Build Coastguard Worker     }
504*c8dee2aaSAndroid Build Coastguard Worker 
oppValue()505*c8dee2aaSAndroid Build Coastguard Worker     int oppValue() const {
506*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
507*c8dee2aaSAndroid Build Coastguard Worker         return fOppValue;
508*c8dee2aaSAndroid Build Coastguard Worker     }
509*c8dee2aaSAndroid Build Coastguard Worker 
510*c8dee2aaSAndroid Build Coastguard Worker     void release(const SkOpPtT* );
511*c8dee2aaSAndroid Build Coastguard Worker 
512*c8dee2aaSAndroid Build Coastguard Worker     SkOpPtT* setCoinStart(SkOpSpan* oldCoinStart, SkOpSegment* oppSegment);
513*c8dee2aaSAndroid Build Coastguard Worker 
setDone(bool done)514*c8dee2aaSAndroid Build Coastguard Worker     void setDone(bool done) {
515*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
516*c8dee2aaSAndroid Build Coastguard Worker         fDone = done;
517*c8dee2aaSAndroid Build Coastguard Worker     }
518*c8dee2aaSAndroid Build Coastguard Worker 
setNext(SkOpSpanBase * nextT)519*c8dee2aaSAndroid Build Coastguard Worker     void setNext(SkOpSpanBase* nextT) {
520*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
521*c8dee2aaSAndroid Build Coastguard Worker         fNext = nextT;
522*c8dee2aaSAndroid Build Coastguard Worker     }
523*c8dee2aaSAndroid Build Coastguard Worker 
524*c8dee2aaSAndroid Build Coastguard Worker     void setOppSum(int oppSum);
525*c8dee2aaSAndroid Build Coastguard Worker 
setOppValue(int oppValue)526*c8dee2aaSAndroid Build Coastguard Worker     void setOppValue(int oppValue) {
527*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
528*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fOppSum == SK_MinS32);
529*c8dee2aaSAndroid Build Coastguard Worker         SkOPASSERT(!oppValue || !fDone);
530*c8dee2aaSAndroid Build Coastguard Worker         fOppValue = oppValue;
531*c8dee2aaSAndroid Build Coastguard Worker     }
532*c8dee2aaSAndroid Build Coastguard Worker 
setToAngle(SkOpAngle * angle)533*c8dee2aaSAndroid Build Coastguard Worker     void setToAngle(SkOpAngle* angle) {
534*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
535*c8dee2aaSAndroid Build Coastguard Worker         fToAngle = angle;
536*c8dee2aaSAndroid Build Coastguard Worker     }
537*c8dee2aaSAndroid Build Coastguard Worker 
538*c8dee2aaSAndroid Build Coastguard Worker     void setWindSum(int windSum);
539*c8dee2aaSAndroid Build Coastguard Worker 
setWindValue(int windValue)540*c8dee2aaSAndroid Build Coastguard Worker     void setWindValue(int windValue) {
541*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
542*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(windValue >= 0);
543*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fWindSum == SK_MinS32);
544*c8dee2aaSAndroid Build Coastguard Worker         SkOPASSERT(!windValue || !fDone);
545*c8dee2aaSAndroid Build Coastguard Worker         fWindValue = windValue;
546*c8dee2aaSAndroid Build Coastguard Worker     }
547*c8dee2aaSAndroid Build Coastguard Worker 
548*c8dee2aaSAndroid Build Coastguard Worker     bool sortableTop(SkOpContour* );
549*c8dee2aaSAndroid Build Coastguard Worker 
toAngle()550*c8dee2aaSAndroid Build Coastguard Worker     SkOpAngle* toAngle() const {
551*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
552*c8dee2aaSAndroid Build Coastguard Worker         return fToAngle;
553*c8dee2aaSAndroid Build Coastguard Worker     }
554*c8dee2aaSAndroid Build Coastguard Worker 
windSum()555*c8dee2aaSAndroid Build Coastguard Worker     int windSum() const {
556*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!final());
557*c8dee2aaSAndroid Build Coastguard Worker         return fWindSum;
558*c8dee2aaSAndroid Build Coastguard Worker     }
559*c8dee2aaSAndroid Build Coastguard Worker 
windValue()560*c8dee2aaSAndroid Build Coastguard Worker     int windValue() const {
561*c8dee2aaSAndroid Build Coastguard Worker         SkOPASSERT(!final());
562*c8dee2aaSAndroid Build Coastguard Worker         return fWindValue;
563*c8dee2aaSAndroid Build Coastguard Worker     }
564*c8dee2aaSAndroid Build Coastguard Worker 
565*c8dee2aaSAndroid Build Coastguard Worker private:  // no direct access to internals to avoid treating a span base as a span
566*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpan* fCoincident;  // linked list of spans coincident with this one (may point to itself)
567*c8dee2aaSAndroid Build Coastguard Worker     SkOpAngle* fToAngle;  // points to next angle from span start to end
568*c8dee2aaSAndroid Build Coastguard Worker     SkOpSpanBase* fNext;  // next intersection point
569*c8dee2aaSAndroid Build Coastguard Worker     int fWindSum;  // accumulated from contours surrounding this one.
570*c8dee2aaSAndroid Build Coastguard Worker     int fOppSum;  // for binary operators: the opposite winding sum
571*c8dee2aaSAndroid Build Coastguard Worker     int fWindValue;  // 0 == canceled; 1 == normal; >1 == coincident
572*c8dee2aaSAndroid Build Coastguard Worker     int fOppValue;  // normally 0 -- when binary coincident edges combine, opp value goes here
573*c8dee2aaSAndroid Build Coastguard Worker     int fTopTTry; // specifies direction and t value to try next
574*c8dee2aaSAndroid Build Coastguard Worker     bool fDone;  // if set, this span to next higher T has been processed
575*c8dee2aaSAndroid Build Coastguard Worker     bool fAlreadyAdded;
576*c8dee2aaSAndroid Build Coastguard Worker };
577*c8dee2aaSAndroid Build Coastguard Worker 
578*c8dee2aaSAndroid Build Coastguard Worker #endif
579