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