1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 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 SkOpContour_DEFINED 8*c8dee2aaSAndroid Build Coastguard Worker #define SkOpContour_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/pathops/SkPathOps.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkOpSegment.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkOpSpan.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsBounds.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTypes.h" 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker class SkOpAngle; 23*c8dee2aaSAndroid Build Coastguard Worker class SkOpCoincidence; 24*c8dee2aaSAndroid Build Coastguard Worker class SkPathWriter; 25*c8dee2aaSAndroid Build Coastguard Worker enum class SkOpRayDir; 26*c8dee2aaSAndroid Build Coastguard Worker struct SkOpRayHit; 27*c8dee2aaSAndroid Build Coastguard Worker 28*c8dee2aaSAndroid Build Coastguard Worker class SkOpContour { 29*c8dee2aaSAndroid Build Coastguard Worker public: SkOpContour()30*c8dee2aaSAndroid Build Coastguard Worker SkOpContour() { 31*c8dee2aaSAndroid Build Coastguard Worker reset(); 32*c8dee2aaSAndroid Build Coastguard Worker } 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker bool operator<(const SkOpContour& rh) const { 35*c8dee2aaSAndroid Build Coastguard Worker return fBounds.fTop == rh.fBounds.fTop 36*c8dee2aaSAndroid Build Coastguard Worker ? fBounds.fLeft < rh.fBounds.fLeft 37*c8dee2aaSAndroid Build Coastguard Worker : fBounds.fTop < rh.fBounds.fTop; 38*c8dee2aaSAndroid Build Coastguard Worker } 39*c8dee2aaSAndroid Build Coastguard Worker addConic(SkPoint pts[3],SkScalar weight)40*c8dee2aaSAndroid Build Coastguard Worker void addConic(SkPoint pts[3], SkScalar weight) { 41*c8dee2aaSAndroid Build Coastguard Worker appendSegment().addConic(pts, weight, this); 42*c8dee2aaSAndroid Build Coastguard Worker } 43*c8dee2aaSAndroid Build Coastguard Worker addCubic(SkPoint pts[4])44*c8dee2aaSAndroid Build Coastguard Worker void addCubic(SkPoint pts[4]) { 45*c8dee2aaSAndroid Build Coastguard Worker appendSegment().addCubic(pts, this); 46*c8dee2aaSAndroid Build Coastguard Worker } 47*c8dee2aaSAndroid Build Coastguard Worker addLine(SkPoint pts[2])48*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* addLine(SkPoint pts[2]) { 49*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(pts[0] != pts[1]); 50*c8dee2aaSAndroid Build Coastguard Worker return appendSegment().addLine(pts, this); 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker addQuad(SkPoint pts[3])53*c8dee2aaSAndroid Build Coastguard Worker void addQuad(SkPoint pts[3]) { 54*c8dee2aaSAndroid Build Coastguard Worker appendSegment().addQuad(pts, this); 55*c8dee2aaSAndroid Build Coastguard Worker } 56*c8dee2aaSAndroid Build Coastguard Worker appendSegment()57*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment& appendSegment() { 58*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* result = fCount++ ? this->globalState()->allocator()->make<SkOpSegment>() 59*c8dee2aaSAndroid Build Coastguard Worker : &fHead; 60*c8dee2aaSAndroid Build Coastguard Worker result->setPrev(fTail); 61*c8dee2aaSAndroid Build Coastguard Worker if (fTail) { 62*c8dee2aaSAndroid Build Coastguard Worker fTail->setNext(result); 63*c8dee2aaSAndroid Build Coastguard Worker } 64*c8dee2aaSAndroid Build Coastguard Worker fTail = result; 65*c8dee2aaSAndroid Build Coastguard Worker return *result; 66*c8dee2aaSAndroid Build Coastguard Worker } 67*c8dee2aaSAndroid Build Coastguard Worker bounds()68*c8dee2aaSAndroid Build Coastguard Worker const SkPathOpsBounds& bounds() const { 69*c8dee2aaSAndroid Build Coastguard Worker return fBounds; 70*c8dee2aaSAndroid Build Coastguard Worker } 71*c8dee2aaSAndroid Build Coastguard Worker calcAngles()72*c8dee2aaSAndroid Build Coastguard Worker void calcAngles() { 73*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 74*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 75*c8dee2aaSAndroid Build Coastguard Worker do { 76*c8dee2aaSAndroid Build Coastguard Worker segment->calcAngles(); 77*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 78*c8dee2aaSAndroid Build Coastguard Worker } 79*c8dee2aaSAndroid Build Coastguard Worker complete()80*c8dee2aaSAndroid Build Coastguard Worker void complete() { 81*c8dee2aaSAndroid Build Coastguard Worker setBounds(); 82*c8dee2aaSAndroid Build Coastguard Worker } 83*c8dee2aaSAndroid Build Coastguard Worker count()84*c8dee2aaSAndroid Build Coastguard Worker int count() const { 85*c8dee2aaSAndroid Build Coastguard Worker return fCount; 86*c8dee2aaSAndroid Build Coastguard Worker } 87*c8dee2aaSAndroid Build Coastguard Worker debugID()88*c8dee2aaSAndroid Build Coastguard Worker int debugID() const { 89*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(fID, -1); 90*c8dee2aaSAndroid Build Coastguard Worker } 91*c8dee2aaSAndroid Build Coastguard Worker debugIndent()92*c8dee2aaSAndroid Build Coastguard Worker int debugIndent() const { 93*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(fDebugIndent, 0); 94*c8dee2aaSAndroid Build Coastguard Worker } 95*c8dee2aaSAndroid Build Coastguard Worker debugAngle(int id)96*c8dee2aaSAndroid Build Coastguard Worker const SkOpAngle* debugAngle(int id) const { 97*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(this->globalState()->debugAngle(id), nullptr); 98*c8dee2aaSAndroid Build Coastguard Worker } 99*c8dee2aaSAndroid Build Coastguard Worker debugCoincidence()100*c8dee2aaSAndroid Build Coastguard Worker const SkOpCoincidence* debugCoincidence() const { 101*c8dee2aaSAndroid Build Coastguard Worker return this->globalState()->coincidence(); 102*c8dee2aaSAndroid Build Coastguard Worker } 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN 105*c8dee2aaSAndroid Build Coastguard Worker void debugCheckHealth(SkPathOpsDebug::GlitchLog* ) const; 106*c8dee2aaSAndroid Build Coastguard Worker #endif 107*c8dee2aaSAndroid Build Coastguard Worker debugContour(int id)108*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* debugContour(int id) const { 109*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(this->globalState()->debugContour(id), nullptr); 110*c8dee2aaSAndroid Build Coastguard Worker } 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN 113*c8dee2aaSAndroid Build Coastguard Worker void debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const; 114*c8dee2aaSAndroid Build Coastguard Worker void debugMoveMultiples(SkPathOpsDebug::GlitchLog* ) const; 115*c8dee2aaSAndroid Build Coastguard Worker void debugMoveNearby(SkPathOpsDebug::GlitchLog* log) const; 116*c8dee2aaSAndroid Build Coastguard Worker #endif 117*c8dee2aaSAndroid Build Coastguard Worker debugPtT(int id)118*c8dee2aaSAndroid Build Coastguard Worker const SkOpPtT* debugPtT(int id) const { 119*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(this->globalState()->debugPtT(id), nullptr); 120*c8dee2aaSAndroid Build Coastguard Worker } 121*c8dee2aaSAndroid Build Coastguard Worker debugSegment(int id)122*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* debugSegment(int id) const { 123*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(this->globalState()->debugSegment(id), nullptr); 124*c8dee2aaSAndroid Build Coastguard Worker } 125*c8dee2aaSAndroid Build Coastguard Worker 126*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_ACTIVE_SPANS debugShowActiveSpans(SkString * str)127*c8dee2aaSAndroid Build Coastguard Worker void debugShowActiveSpans(SkString* str) { 128*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 129*c8dee2aaSAndroid Build Coastguard Worker do { 130*c8dee2aaSAndroid Build Coastguard Worker segment->debugShowActiveSpans(str); 131*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 132*c8dee2aaSAndroid Build Coastguard Worker } 133*c8dee2aaSAndroid Build Coastguard Worker #endif 134*c8dee2aaSAndroid Build Coastguard Worker debugSpan(int id)135*c8dee2aaSAndroid Build Coastguard Worker const SkOpSpanBase* debugSpan(int id) const { 136*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(this->globalState()->debugSpan(id), nullptr); 137*c8dee2aaSAndroid Build Coastguard Worker } 138*c8dee2aaSAndroid Build Coastguard Worker globalState()139*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* globalState() const { 140*c8dee2aaSAndroid Build Coastguard Worker return fState; 141*c8dee2aaSAndroid Build Coastguard Worker } 142*c8dee2aaSAndroid Build Coastguard Worker debugValidate()143*c8dee2aaSAndroid Build Coastguard Worker void debugValidate() const { 144*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_VALIDATE 145*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* segment = &fHead; 146*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* prior = nullptr; 147*c8dee2aaSAndroid Build Coastguard Worker do { 148*c8dee2aaSAndroid Build Coastguard Worker segment->debugValidate(); 149*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(segment->prev() == prior); 150*c8dee2aaSAndroid Build Coastguard Worker prior = segment; 151*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 152*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(prior == fTail); 153*c8dee2aaSAndroid Build Coastguard Worker #endif 154*c8dee2aaSAndroid Build Coastguard Worker } 155*c8dee2aaSAndroid Build Coastguard Worker done()156*c8dee2aaSAndroid Build Coastguard Worker bool done() const { 157*c8dee2aaSAndroid Build Coastguard Worker return fDone; 158*c8dee2aaSAndroid Build Coastguard Worker } 159*c8dee2aaSAndroid Build Coastguard Worker 160*c8dee2aaSAndroid Build Coastguard Worker void dump() const; 161*c8dee2aaSAndroid Build Coastguard Worker void dumpAll() const; 162*c8dee2aaSAndroid Build Coastguard Worker void dumpAngles() const; 163*c8dee2aaSAndroid Build Coastguard Worker void dumpContours() const; 164*c8dee2aaSAndroid Build Coastguard Worker void dumpContoursAll() const; 165*c8dee2aaSAndroid Build Coastguard Worker void dumpContoursAngles() const; 166*c8dee2aaSAndroid Build Coastguard Worker void dumpContoursPts() const; 167*c8dee2aaSAndroid Build Coastguard Worker void dumpContoursPt(int segmentID) const; 168*c8dee2aaSAndroid Build Coastguard Worker void dumpContoursSegment(int segmentID) const; 169*c8dee2aaSAndroid Build Coastguard Worker void dumpContoursSpan(int segmentID) const; 170*c8dee2aaSAndroid Build Coastguard Worker void dumpContoursSpans() const; 171*c8dee2aaSAndroid Build Coastguard Worker void dumpPt(int ) const; 172*c8dee2aaSAndroid Build Coastguard Worker void dumpPts(const char* prefix = "seg") const; 173*c8dee2aaSAndroid Build Coastguard Worker void dumpPtsX(const char* prefix) const; 174*c8dee2aaSAndroid Build Coastguard Worker void dumpSegment(int ) const; 175*c8dee2aaSAndroid Build Coastguard Worker void dumpSegments(const char* prefix = "seg", SkPathOp op = (SkPathOp) -1) const; 176*c8dee2aaSAndroid Build Coastguard Worker void dumpSpan(int ) const; 177*c8dee2aaSAndroid Build Coastguard Worker void dumpSpans() const; 178*c8dee2aaSAndroid Build Coastguard Worker end()179*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& end() const { 180*c8dee2aaSAndroid Build Coastguard Worker return fTail->pts()[SkPathOpsVerbToPoints(fTail->verb())]; 181*c8dee2aaSAndroid Build Coastguard Worker } 182*c8dee2aaSAndroid Build Coastguard Worker 183*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* findSortableTop(SkOpContour* ); 184*c8dee2aaSAndroid Build Coastguard Worker first()185*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* first() { 186*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 187*c8dee2aaSAndroid Build Coastguard Worker return &fHead; 188*c8dee2aaSAndroid Build Coastguard Worker } 189*c8dee2aaSAndroid Build Coastguard Worker first()190*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* first() const { 191*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 192*c8dee2aaSAndroid Build Coastguard Worker return &fHead; 193*c8dee2aaSAndroid Build Coastguard Worker } 194*c8dee2aaSAndroid Build Coastguard Worker indentDump()195*c8dee2aaSAndroid Build Coastguard Worker void indentDump() const { 196*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fDebugIndent += 2); 197*c8dee2aaSAndroid Build Coastguard Worker } 198*c8dee2aaSAndroid Build Coastguard Worker init(SkOpGlobalState * globalState,bool operand,bool isXor)199*c8dee2aaSAndroid Build Coastguard Worker void init(SkOpGlobalState* globalState, bool operand, bool isXor) { 200*c8dee2aaSAndroid Build Coastguard Worker fState = globalState; 201*c8dee2aaSAndroid Build Coastguard Worker fOperand = operand; 202*c8dee2aaSAndroid Build Coastguard Worker fXor = isXor; 203*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fID = globalState->nextContourID()); 204*c8dee2aaSAndroid Build Coastguard Worker } 205*c8dee2aaSAndroid Build Coastguard Worker isCcw()206*c8dee2aaSAndroid Build Coastguard Worker int isCcw() const { 207*c8dee2aaSAndroid Build Coastguard Worker return fCcw; 208*c8dee2aaSAndroid Build Coastguard Worker } 209*c8dee2aaSAndroid Build Coastguard Worker isXor()210*c8dee2aaSAndroid Build Coastguard Worker bool isXor() const { 211*c8dee2aaSAndroid Build Coastguard Worker return fXor; 212*c8dee2aaSAndroid Build Coastguard Worker } 213*c8dee2aaSAndroid Build Coastguard Worker joinSegments()214*c8dee2aaSAndroid Build Coastguard Worker void joinSegments() { 215*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 216*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* next; 217*c8dee2aaSAndroid Build Coastguard Worker do { 218*c8dee2aaSAndroid Build Coastguard Worker next = segment->next(); 219*c8dee2aaSAndroid Build Coastguard Worker segment->joinEnds(next ? next : &fHead); 220*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = next)); 221*c8dee2aaSAndroid Build Coastguard Worker } 222*c8dee2aaSAndroid Build Coastguard Worker markAllDone()223*c8dee2aaSAndroid Build Coastguard Worker void markAllDone() { 224*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 225*c8dee2aaSAndroid Build Coastguard Worker do { 226*c8dee2aaSAndroid Build Coastguard Worker segment->markAllDone(); 227*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 228*c8dee2aaSAndroid Build Coastguard Worker } 229*c8dee2aaSAndroid Build Coastguard Worker 230*c8dee2aaSAndroid Build Coastguard Worker // Please keep this aligned with debugMissingCoincidence() missingCoincidence()231*c8dee2aaSAndroid Build Coastguard Worker bool missingCoincidence() { 232*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 233*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 234*c8dee2aaSAndroid Build Coastguard Worker bool result = false; 235*c8dee2aaSAndroid Build Coastguard Worker do { 236*c8dee2aaSAndroid Build Coastguard Worker if (segment->missingCoincidence()) { 237*c8dee2aaSAndroid Build Coastguard Worker result = true; 238*c8dee2aaSAndroid Build Coastguard Worker } 239*c8dee2aaSAndroid Build Coastguard Worker segment = segment->next(); 240*c8dee2aaSAndroid Build Coastguard Worker } while (segment); 241*c8dee2aaSAndroid Build Coastguard Worker return result; 242*c8dee2aaSAndroid Build Coastguard Worker } 243*c8dee2aaSAndroid Build Coastguard Worker moveMultiples()244*c8dee2aaSAndroid Build Coastguard Worker bool moveMultiples() { 245*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 246*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 247*c8dee2aaSAndroid Build Coastguard Worker do { 248*c8dee2aaSAndroid Build Coastguard Worker if (!segment->moveMultiples()) { 249*c8dee2aaSAndroid Build Coastguard Worker return false; 250*c8dee2aaSAndroid Build Coastguard Worker } 251*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 252*c8dee2aaSAndroid Build Coastguard Worker return true; 253*c8dee2aaSAndroid Build Coastguard Worker } 254*c8dee2aaSAndroid Build Coastguard Worker moveNearby()255*c8dee2aaSAndroid Build Coastguard Worker bool moveNearby() { 256*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 257*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 258*c8dee2aaSAndroid Build Coastguard Worker do { 259*c8dee2aaSAndroid Build Coastguard Worker if (!segment->moveNearby()) { 260*c8dee2aaSAndroid Build Coastguard Worker return false; 261*c8dee2aaSAndroid Build Coastguard Worker } 262*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 263*c8dee2aaSAndroid Build Coastguard Worker return true; 264*c8dee2aaSAndroid Build Coastguard Worker } 265*c8dee2aaSAndroid Build Coastguard Worker next()266*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* next() { 267*c8dee2aaSAndroid Build Coastguard Worker return fNext; 268*c8dee2aaSAndroid Build Coastguard Worker } 269*c8dee2aaSAndroid Build Coastguard Worker next()270*c8dee2aaSAndroid Build Coastguard Worker const SkOpContour* next() const { 271*c8dee2aaSAndroid Build Coastguard Worker return fNext; 272*c8dee2aaSAndroid Build Coastguard Worker } 273*c8dee2aaSAndroid Build Coastguard Worker operand()274*c8dee2aaSAndroid Build Coastguard Worker bool operand() const { 275*c8dee2aaSAndroid Build Coastguard Worker return fOperand; 276*c8dee2aaSAndroid Build Coastguard Worker } 277*c8dee2aaSAndroid Build Coastguard Worker oppXor()278*c8dee2aaSAndroid Build Coastguard Worker bool oppXor() const { 279*c8dee2aaSAndroid Build Coastguard Worker return fOppXor; 280*c8dee2aaSAndroid Build Coastguard Worker } 281*c8dee2aaSAndroid Build Coastguard Worker outdentDump()282*c8dee2aaSAndroid Build Coastguard Worker void outdentDump() const { 283*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fDebugIndent -= 2); 284*c8dee2aaSAndroid Build Coastguard Worker } 285*c8dee2aaSAndroid Build Coastguard Worker 286*c8dee2aaSAndroid Build Coastguard Worker void rayCheck(const SkOpRayHit& base, SkOpRayDir dir, SkOpRayHit** hits, SkArenaAlloc*); 287*c8dee2aaSAndroid Build Coastguard Worker reset()288*c8dee2aaSAndroid Build Coastguard Worker void reset() { 289*c8dee2aaSAndroid Build Coastguard Worker fTail = nullptr; 290*c8dee2aaSAndroid Build Coastguard Worker fNext = nullptr; 291*c8dee2aaSAndroid Build Coastguard Worker fCount = 0; 292*c8dee2aaSAndroid Build Coastguard Worker fDone = false; 293*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fBounds.setLTRB(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin)); 294*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fFirstSorted = -1); 295*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fDebugIndent = 0); 296*c8dee2aaSAndroid Build Coastguard Worker } 297*c8dee2aaSAndroid Build Coastguard Worker resetReverse()298*c8dee2aaSAndroid Build Coastguard Worker void resetReverse() { 299*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* next = this; 300*c8dee2aaSAndroid Build Coastguard Worker do { 301*c8dee2aaSAndroid Build Coastguard Worker if (!next->count()) { 302*c8dee2aaSAndroid Build Coastguard Worker continue; 303*c8dee2aaSAndroid Build Coastguard Worker } 304*c8dee2aaSAndroid Build Coastguard Worker next->fCcw = -1; 305*c8dee2aaSAndroid Build Coastguard Worker next->fReverse = false; 306*c8dee2aaSAndroid Build Coastguard Worker } while ((next = next->next())); 307*c8dee2aaSAndroid Build Coastguard Worker } 308*c8dee2aaSAndroid Build Coastguard Worker reversed()309*c8dee2aaSAndroid Build Coastguard Worker bool reversed() const { 310*c8dee2aaSAndroid Build Coastguard Worker return fReverse; 311*c8dee2aaSAndroid Build Coastguard Worker } 312*c8dee2aaSAndroid Build Coastguard Worker setBounds()313*c8dee2aaSAndroid Build Coastguard Worker void setBounds() { 314*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 315*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* segment = &fHead; 316*c8dee2aaSAndroid Build Coastguard Worker fBounds = segment->bounds(); 317*c8dee2aaSAndroid Build Coastguard Worker while ((segment = segment->next())) { 318*c8dee2aaSAndroid Build Coastguard Worker fBounds.add(segment->bounds()); 319*c8dee2aaSAndroid Build Coastguard Worker } 320*c8dee2aaSAndroid Build Coastguard Worker } 321*c8dee2aaSAndroid Build Coastguard Worker setCcw(int ccw)322*c8dee2aaSAndroid Build Coastguard Worker void setCcw(int ccw) { 323*c8dee2aaSAndroid Build Coastguard Worker fCcw = ccw; 324*c8dee2aaSAndroid Build Coastguard Worker } 325*c8dee2aaSAndroid Build Coastguard Worker setGlobalState(SkOpGlobalState * state)326*c8dee2aaSAndroid Build Coastguard Worker void setGlobalState(SkOpGlobalState* state) { 327*c8dee2aaSAndroid Build Coastguard Worker fState = state; 328*c8dee2aaSAndroid Build Coastguard Worker } 329*c8dee2aaSAndroid Build Coastguard Worker setNext(SkOpContour * contour)330*c8dee2aaSAndroid Build Coastguard Worker void setNext(SkOpContour* contour) { 331*c8dee2aaSAndroid Build Coastguard Worker // SkASSERT(!fNext == !!contour); 332*c8dee2aaSAndroid Build Coastguard Worker fNext = contour; 333*c8dee2aaSAndroid Build Coastguard Worker } 334*c8dee2aaSAndroid Build Coastguard Worker setOperand(bool isOp)335*c8dee2aaSAndroid Build Coastguard Worker void setOperand(bool isOp) { 336*c8dee2aaSAndroid Build Coastguard Worker fOperand = isOp; 337*c8dee2aaSAndroid Build Coastguard Worker } 338*c8dee2aaSAndroid Build Coastguard Worker setOppXor(bool isOppXor)339*c8dee2aaSAndroid Build Coastguard Worker void setOppXor(bool isOppXor) { 340*c8dee2aaSAndroid Build Coastguard Worker fOppXor = isOppXor; 341*c8dee2aaSAndroid Build Coastguard Worker } 342*c8dee2aaSAndroid Build Coastguard Worker setReverse()343*c8dee2aaSAndroid Build Coastguard Worker void setReverse() { 344*c8dee2aaSAndroid Build Coastguard Worker fReverse = true; 345*c8dee2aaSAndroid Build Coastguard Worker } 346*c8dee2aaSAndroid Build Coastguard Worker setXor(bool isXor)347*c8dee2aaSAndroid Build Coastguard Worker void setXor(bool isXor) { 348*c8dee2aaSAndroid Build Coastguard Worker fXor = isXor; 349*c8dee2aaSAndroid Build Coastguard Worker } 350*c8dee2aaSAndroid Build Coastguard Worker sortAngles()351*c8dee2aaSAndroid Build Coastguard Worker bool sortAngles() { 352*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCount > 0); 353*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* segment = &fHead; 354*c8dee2aaSAndroid Build Coastguard Worker do { 355*c8dee2aaSAndroid Build Coastguard Worker FAIL_IF(!segment->sortAngles()); 356*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 357*c8dee2aaSAndroid Build Coastguard Worker return true; 358*c8dee2aaSAndroid Build Coastguard Worker } 359*c8dee2aaSAndroid Build Coastguard Worker start()360*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& start() const { 361*c8dee2aaSAndroid Build Coastguard Worker return fHead.pts()[0]; 362*c8dee2aaSAndroid Build Coastguard Worker } 363*c8dee2aaSAndroid Build Coastguard Worker toPartialBackward(SkPathWriter * path)364*c8dee2aaSAndroid Build Coastguard Worker void toPartialBackward(SkPathWriter* path) const { 365*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* segment = fTail; 366*c8dee2aaSAndroid Build Coastguard Worker do { 367*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path)); 368*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->prev())); 369*c8dee2aaSAndroid Build Coastguard Worker } 370*c8dee2aaSAndroid Build Coastguard Worker toPartialForward(SkPathWriter * path)371*c8dee2aaSAndroid Build Coastguard Worker void toPartialForward(SkPathWriter* path) const { 372*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* segment = &fHead; 373*c8dee2aaSAndroid Build Coastguard Worker do { 374*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path)); 375*c8dee2aaSAndroid Build Coastguard Worker } while ((segment = segment->next())); 376*c8dee2aaSAndroid Build Coastguard Worker } 377*c8dee2aaSAndroid Build Coastguard Worker 378*c8dee2aaSAndroid Build Coastguard Worker void toReversePath(SkPathWriter* path) const; 379*c8dee2aaSAndroid Build Coastguard Worker void toPath(SkPathWriter* path) const; 380*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* undoneSpan(); 381*c8dee2aaSAndroid Build Coastguard Worker 382*c8dee2aaSAndroid Build Coastguard Worker protected: 383*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* fState; 384*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment fHead; 385*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* fTail; 386*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* fNext; 387*c8dee2aaSAndroid Build Coastguard Worker SkPathOpsBounds fBounds; 388*c8dee2aaSAndroid Build Coastguard Worker int fCcw; 389*c8dee2aaSAndroid Build Coastguard Worker int fCount; 390*c8dee2aaSAndroid Build Coastguard Worker int fFirstSorted; 391*c8dee2aaSAndroid Build Coastguard Worker bool fDone; // set by find top segment 392*c8dee2aaSAndroid Build Coastguard Worker bool fOperand; // true for the second argument to a binary operator 393*c8dee2aaSAndroid Build Coastguard Worker bool fReverse; // true if contour should be reverse written to path (used only by fix winding) 394*c8dee2aaSAndroid Build Coastguard Worker bool fXor; // set if original path had even-odd fill 395*c8dee2aaSAndroid Build Coastguard Worker bool fOppXor; // set if opposite path had even-odd fill 396*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(int fID;) 397*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(mutable int fDebugIndent;) 398*c8dee2aaSAndroid Build Coastguard Worker }; 399*c8dee2aaSAndroid Build Coastguard Worker 400*c8dee2aaSAndroid Build Coastguard Worker class SkOpContourHead : public SkOpContour { 401*c8dee2aaSAndroid Build Coastguard Worker public: appendContour()402*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* appendContour() { 403*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* contour = this->globalState()->allocator()->make<SkOpContour>(); 404*c8dee2aaSAndroid Build Coastguard Worker contour->setNext(nullptr); 405*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* prev = this; 406*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* next; 407*c8dee2aaSAndroid Build Coastguard Worker while ((next = prev->next())) { 408*c8dee2aaSAndroid Build Coastguard Worker prev = next; 409*c8dee2aaSAndroid Build Coastguard Worker } 410*c8dee2aaSAndroid Build Coastguard Worker prev->setNext(contour); 411*c8dee2aaSAndroid Build Coastguard Worker return contour; 412*c8dee2aaSAndroid Build Coastguard Worker } 413*c8dee2aaSAndroid Build Coastguard Worker joinAllSegments()414*c8dee2aaSAndroid Build Coastguard Worker void joinAllSegments() { 415*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* next = this; 416*c8dee2aaSAndroid Build Coastguard Worker do { 417*c8dee2aaSAndroid Build Coastguard Worker if (!next->count()) { 418*c8dee2aaSAndroid Build Coastguard Worker continue; 419*c8dee2aaSAndroid Build Coastguard Worker } 420*c8dee2aaSAndroid Build Coastguard Worker next->joinSegments(); 421*c8dee2aaSAndroid Build Coastguard Worker } while ((next = next->next())); 422*c8dee2aaSAndroid Build Coastguard Worker } 423*c8dee2aaSAndroid Build Coastguard Worker remove(SkOpContour * contour)424*c8dee2aaSAndroid Build Coastguard Worker void remove(SkOpContour* contour) { 425*c8dee2aaSAndroid Build Coastguard Worker if (contour == this) { 426*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this->count() == 0); 427*c8dee2aaSAndroid Build Coastguard Worker return; 428*c8dee2aaSAndroid Build Coastguard Worker } 429*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(contour->next() == nullptr); 430*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* prev = this; 431*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* next; 432*c8dee2aaSAndroid Build Coastguard Worker while ((next = prev->next()) != contour) { 433*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(next); 434*c8dee2aaSAndroid Build Coastguard Worker prev = next; 435*c8dee2aaSAndroid Build Coastguard Worker } 436*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(prev); 437*c8dee2aaSAndroid Build Coastguard Worker prev->setNext(nullptr); 438*c8dee2aaSAndroid Build Coastguard Worker } 439*c8dee2aaSAndroid Build Coastguard Worker }; 440*c8dee2aaSAndroid Build Coastguard Worker 441*c8dee2aaSAndroid Build Coastguard Worker class SkOpContourBuilder { 442*c8dee2aaSAndroid Build Coastguard Worker public: SkOpContourBuilder(SkOpContour * contour)443*c8dee2aaSAndroid Build Coastguard Worker SkOpContourBuilder(SkOpContour* contour) 444*c8dee2aaSAndroid Build Coastguard Worker : fContour(contour) 445*c8dee2aaSAndroid Build Coastguard Worker , fLastIsLine(false) { 446*c8dee2aaSAndroid Build Coastguard Worker } 447*c8dee2aaSAndroid Build Coastguard Worker 448*c8dee2aaSAndroid Build Coastguard Worker void addConic(SkPoint pts[3], SkScalar weight); 449*c8dee2aaSAndroid Build Coastguard Worker void addCubic(SkPoint pts[4]); 450*c8dee2aaSAndroid Build Coastguard Worker void addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight = 1); 451*c8dee2aaSAndroid Build Coastguard Worker void addLine(const SkPoint pts[2]); 452*c8dee2aaSAndroid Build Coastguard Worker void addQuad(SkPoint pts[3]); 453*c8dee2aaSAndroid Build Coastguard Worker void flush(); contour()454*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* contour() { return fContour; } setContour(SkOpContour * contour)455*c8dee2aaSAndroid Build Coastguard Worker void setContour(SkOpContour* contour) { flush(); fContour = contour; } 456*c8dee2aaSAndroid Build Coastguard Worker protected: 457*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* fContour; 458*c8dee2aaSAndroid Build Coastguard Worker SkPoint fLastLine[2]; 459*c8dee2aaSAndroid Build Coastguard Worker bool fLastIsLine; 460*c8dee2aaSAndroid Build Coastguard Worker }; 461*c8dee2aaSAndroid Build Coastguard Worker 462*c8dee2aaSAndroid Build Coastguard Worker #endif 463