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 SkOpSegment_DEFINE 8*c8dee2aaSAndroid Build Coastguard Worker #define SkOpSegment_DEFINE 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 "include/private/base/SkMath.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkOpAngle.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkOpSpan.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsBounds.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsConic.h" 22*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsCubic.h" 23*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsCurve.h" 24*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsPoint.h" 25*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsQuad.h" 26*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTypes.h" 27*c8dee2aaSAndroid Build Coastguard Worker 28*c8dee2aaSAndroid Build Coastguard Worker enum class SkOpRayDir; 29*c8dee2aaSAndroid Build Coastguard Worker class SkOpCoincidence; 30*c8dee2aaSAndroid Build Coastguard Worker class SkOpContour; 31*c8dee2aaSAndroid Build Coastguard Worker class SkPathWriter; 32*c8dee2aaSAndroid Build Coastguard Worker struct SkOpRayHit; 33*c8dee2aaSAndroid Build Coastguard Worker template <typename T> class SkTDArray; 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker class SkOpSegment { 36*c8dee2aaSAndroid Build Coastguard Worker public: 37*c8dee2aaSAndroid Build Coastguard Worker bool operator<(const SkOpSegment& rh) const { 38*c8dee2aaSAndroid Build Coastguard Worker return fBounds.fTop < rh.fBounds.fTop; 39*c8dee2aaSAndroid Build Coastguard Worker } 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr, 42*c8dee2aaSAndroid Build Coastguard Worker bool* done); 43*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr, 44*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase** endPtr, bool* done); 45*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr, 46*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase** endPtr, bool* done); 47*c8dee2aaSAndroid Build Coastguard Worker bool activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask, 48*c8dee2aaSAndroid Build Coastguard Worker SkPathOp op); 49*c8dee2aaSAndroid Build Coastguard Worker bool activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end, SkPathOp op, 50*c8dee2aaSAndroid Build Coastguard Worker int* sumMiWinding, int* sumSuWinding); 51*c8dee2aaSAndroid Build Coastguard Worker 52*c8dee2aaSAndroid Build Coastguard Worker bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end); 53*c8dee2aaSAndroid Build Coastguard Worker bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding); 54*c8dee2aaSAndroid Build Coastguard Worker addConic(SkPoint pts[3],SkScalar weight,SkOpContour * parent)55*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* addConic(SkPoint pts[3], SkScalar weight, SkOpContour* parent) { 56*c8dee2aaSAndroid Build Coastguard Worker init(pts, weight, parent, SkPath::kConic_Verb); 57*c8dee2aaSAndroid Build Coastguard Worker SkDCurve curve; 58*c8dee2aaSAndroid Build Coastguard Worker curve.fConic.set(pts, weight); 59*c8dee2aaSAndroid Build Coastguard Worker curve.setConicBounds(pts, weight, 0, 1, &fBounds); 60*c8dee2aaSAndroid Build Coastguard Worker return this; 61*c8dee2aaSAndroid Build Coastguard Worker } 62*c8dee2aaSAndroid Build Coastguard Worker addCubic(SkPoint pts[4],SkOpContour * parent)63*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* addCubic(SkPoint pts[4], SkOpContour* parent) { 64*c8dee2aaSAndroid Build Coastguard Worker init(pts, 1, parent, SkPath::kCubic_Verb); 65*c8dee2aaSAndroid Build Coastguard Worker SkDCurve curve; 66*c8dee2aaSAndroid Build Coastguard Worker curve.fCubic.set(pts); 67*c8dee2aaSAndroid Build Coastguard Worker curve.setCubicBounds(pts, 1, 0, 1, &fBounds); 68*c8dee2aaSAndroid Build Coastguard Worker return this; 69*c8dee2aaSAndroid Build Coastguard Worker } 70*c8dee2aaSAndroid Build Coastguard Worker 71*c8dee2aaSAndroid Build Coastguard Worker bool addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end, SkPathWriter* path) const; 72*c8dee2aaSAndroid Build Coastguard Worker addEndSpan()73*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* addEndSpan() { 74*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* angle = this->globalState()->allocator()->make<SkOpAngle>(); 75*c8dee2aaSAndroid Build Coastguard Worker angle->set(&fTail, fTail.prev()); 76*c8dee2aaSAndroid Build Coastguard Worker fTail.setFromAngle(angle); 77*c8dee2aaSAndroid Build Coastguard Worker return angle; 78*c8dee2aaSAndroid Build Coastguard Worker } 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker bool addExpanded(double newT, const SkOpSpanBase* test, bool* startOver); 81*c8dee2aaSAndroid Build Coastguard Worker addLine(SkPoint pts[2],SkOpContour * parent)82*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* addLine(SkPoint pts[2], SkOpContour* parent) { 83*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(pts[0] != pts[1]); 84*c8dee2aaSAndroid Build Coastguard Worker init(pts, 1, parent, SkPath::kLine_Verb); 85*c8dee2aaSAndroid Build Coastguard Worker fBounds.setBounds(pts, 2); 86*c8dee2aaSAndroid Build Coastguard Worker return this; 87*c8dee2aaSAndroid Build Coastguard Worker } 88*c8dee2aaSAndroid Build Coastguard Worker 89*c8dee2aaSAndroid Build Coastguard Worker SkOpPtT* addMissing(double t, SkOpSegment* opp, bool* allExist); 90*c8dee2aaSAndroid Build Coastguard Worker addStartSpan()91*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* addStartSpan() { 92*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* angle = this->globalState()->allocator()->make<SkOpAngle>(); 93*c8dee2aaSAndroid Build Coastguard Worker angle->set(&fHead, fHead.next()); 94*c8dee2aaSAndroid Build Coastguard Worker fHead.setToAngle(angle); 95*c8dee2aaSAndroid Build Coastguard Worker return angle; 96*c8dee2aaSAndroid Build Coastguard Worker } 97*c8dee2aaSAndroid Build Coastguard Worker addQuad(SkPoint pts[3],SkOpContour * parent)98*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* addQuad(SkPoint pts[3], SkOpContour* parent) { 99*c8dee2aaSAndroid Build Coastguard Worker init(pts, 1, parent, SkPath::kQuad_Verb); 100*c8dee2aaSAndroid Build Coastguard Worker SkDCurve curve; 101*c8dee2aaSAndroid Build Coastguard Worker curve.fQuad.set(pts); 102*c8dee2aaSAndroid Build Coastguard Worker curve.setQuadBounds(pts, 1, 0, 1, &fBounds); 103*c8dee2aaSAndroid Build Coastguard Worker return this; 104*c8dee2aaSAndroid Build Coastguard Worker } 105*c8dee2aaSAndroid Build Coastguard Worker 106*c8dee2aaSAndroid Build Coastguard Worker SkOpPtT* addT(double t); 107*c8dee2aaSAndroid Build Coastguard Worker SkOpPtT* addT(double t, const SkPoint& pt); 108*c8dee2aaSAndroid Build Coastguard Worker bounds()109*c8dee2aaSAndroid Build Coastguard Worker const SkPathOpsBounds& bounds() const { 110*c8dee2aaSAndroid Build Coastguard Worker return fBounds; 111*c8dee2aaSAndroid Build Coastguard Worker } 112*c8dee2aaSAndroid Build Coastguard Worker bumpCount()113*c8dee2aaSAndroid Build Coastguard Worker void bumpCount() { 114*c8dee2aaSAndroid Build Coastguard Worker ++fCount; 115*c8dee2aaSAndroid Build Coastguard Worker } 116*c8dee2aaSAndroid Build Coastguard Worker 117*c8dee2aaSAndroid Build Coastguard Worker void calcAngles(); 118*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase::Collapsed collapsed(double startT, double endT) const; 119*c8dee2aaSAndroid Build Coastguard Worker static bool ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, 120*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle::IncludeType ); 121*c8dee2aaSAndroid Build Coastguard Worker static bool ComputeOneSumReverse(SkOpAngle* baseAngle, SkOpAngle* nextAngle, 122*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle::IncludeType ); 123*c8dee2aaSAndroid Build Coastguard Worker int computeSum(SkOpSpanBase* start, SkOpSpanBase* end, SkOpAngle::IncludeType includeType); 124*c8dee2aaSAndroid Build Coastguard Worker 125*c8dee2aaSAndroid Build Coastguard Worker void clearAll(); 126*c8dee2aaSAndroid Build Coastguard Worker void clearOne(SkOpSpan* span); 127*c8dee2aaSAndroid Build Coastguard Worker static void ClearVisited(SkOpSpanBase* span); 128*c8dee2aaSAndroid Build Coastguard Worker bool contains(double t) const; 129*c8dee2aaSAndroid Build Coastguard Worker contour()130*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* contour() const { 131*c8dee2aaSAndroid Build Coastguard Worker return fContour; 132*c8dee2aaSAndroid Build Coastguard Worker } 133*c8dee2aaSAndroid Build Coastguard Worker count()134*c8dee2aaSAndroid Build Coastguard Worker int count() const { 135*c8dee2aaSAndroid Build Coastguard Worker return fCount; 136*c8dee2aaSAndroid Build Coastguard Worker } 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker void debugAddAngle(double startT, double endT); 139*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN 140*c8dee2aaSAndroid Build Coastguard Worker const SkOpPtT* debugAddT(double t, SkPathOpsDebug::GlitchLog* ) const; 141*c8dee2aaSAndroid Build Coastguard Worker #endif 142*c8dee2aaSAndroid Build Coastguard Worker const SkOpAngle* debugAngle(int id) const; 143*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_ANGLE 144*c8dee2aaSAndroid Build Coastguard Worker void debugCheckAngleCoin() const; 145*c8dee2aaSAndroid Build Coastguard Worker #endif 146*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN 147*c8dee2aaSAndroid Build Coastguard Worker void debugCheckHealth(SkPathOpsDebug::GlitchLog* ) const; 148*c8dee2aaSAndroid Build Coastguard Worker void debugClearAll(SkPathOpsDebug::GlitchLog* glitches) const; 149*c8dee2aaSAndroid Build Coastguard Worker void debugClearOne(const SkOpSpan* span, SkPathOpsDebug::GlitchLog* glitches) const; 150*c8dee2aaSAndroid Build Coastguard Worker #endif 151*c8dee2aaSAndroid Build Coastguard Worker const SkOpCoincidence* debugCoincidence() const; 152*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* debugContour(int id) const; 153*c8dee2aaSAndroid Build Coastguard Worker debugID()154*c8dee2aaSAndroid Build Coastguard Worker int debugID() const { 155*c8dee2aaSAndroid Build Coastguard Worker return SkDEBUGRELEASE(fID, -1); 156*c8dee2aaSAndroid Build Coastguard Worker } 157*c8dee2aaSAndroid Build Coastguard Worker 158*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* debugLastAngle(); 159*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN 160*c8dee2aaSAndroid Build Coastguard Worker void debugMissingCoincidence(SkPathOpsDebug::GlitchLog* glitches) const; 161*c8dee2aaSAndroid Build Coastguard Worker void debugMoveMultiples(SkPathOpsDebug::GlitchLog* glitches) const; 162*c8dee2aaSAndroid Build Coastguard Worker void debugMoveNearby(SkPathOpsDebug::GlitchLog* glitches) const; 163*c8dee2aaSAndroid Build Coastguard Worker #endif 164*c8dee2aaSAndroid Build Coastguard Worker const SkOpPtT* debugPtT(int id) const; 165*c8dee2aaSAndroid Build Coastguard Worker void debugReset(); 166*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* debugSegment(int id) const; 167*c8dee2aaSAndroid Build Coastguard Worker 168*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_ACTIVE_SPANS 169*c8dee2aaSAndroid Build Coastguard Worker void debugShowActiveSpans(SkString* str) const; 170*c8dee2aaSAndroid Build Coastguard Worker #endif 171*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_MARK_DONE 172*c8dee2aaSAndroid Build Coastguard Worker void debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding); 173*c8dee2aaSAndroid Build Coastguard Worker void debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, int oppWinding); 174*c8dee2aaSAndroid Build Coastguard Worker #endif 175*c8dee2aaSAndroid Build Coastguard Worker 176*c8dee2aaSAndroid Build Coastguard Worker const SkOpSpanBase* debugSpan(int id) const; 177*c8dee2aaSAndroid Build Coastguard Worker void debugValidate() const; 178*c8dee2aaSAndroid Build Coastguard Worker 179*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COINCIDENCE_ORDER 180*c8dee2aaSAndroid Build Coastguard Worker void debugResetCoinT() const; 181*c8dee2aaSAndroid Build Coastguard Worker void debugSetCoinT(int, SkScalar ) const; 182*c8dee2aaSAndroid Build Coastguard Worker #endif 183*c8dee2aaSAndroid Build Coastguard Worker 184*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN 185*c8dee2aaSAndroid Build Coastguard Worker static void DebugClearVisited(const SkOpSpanBase* span); 186*c8dee2aaSAndroid Build Coastguard Worker debugVisited()187*c8dee2aaSAndroid Build Coastguard Worker bool debugVisited() const { 188*c8dee2aaSAndroid Build Coastguard Worker if (!fDebugVisited) { 189*c8dee2aaSAndroid Build Coastguard Worker fDebugVisited = true; 190*c8dee2aaSAndroid Build Coastguard Worker return false; 191*c8dee2aaSAndroid Build Coastguard Worker } 192*c8dee2aaSAndroid Build Coastguard Worker return true; 193*c8dee2aaSAndroid Build Coastguard Worker } 194*c8dee2aaSAndroid Build Coastguard Worker #endif 195*c8dee2aaSAndroid Build Coastguard Worker 196*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_ANGLE 197*c8dee2aaSAndroid Build Coastguard Worker double distSq(double t, const SkOpAngle* opp) const; 198*c8dee2aaSAndroid Build Coastguard Worker #endif 199*c8dee2aaSAndroid Build Coastguard Worker done()200*c8dee2aaSAndroid Build Coastguard Worker bool done() const { 201*c8dee2aaSAndroid Build Coastguard Worker SkOPASSERT(fDoneCount <= fCount); 202*c8dee2aaSAndroid Build Coastguard Worker return fDoneCount == fCount; 203*c8dee2aaSAndroid Build Coastguard Worker } 204*c8dee2aaSAndroid Build Coastguard Worker done(const SkOpAngle * angle)205*c8dee2aaSAndroid Build Coastguard Worker bool done(const SkOpAngle* angle) const { 206*c8dee2aaSAndroid Build Coastguard Worker return angle->start()->starter(angle->end())->done(); 207*c8dee2aaSAndroid Build Coastguard Worker } 208*c8dee2aaSAndroid Build Coastguard Worker dPtAtT(double mid)209*c8dee2aaSAndroid Build Coastguard Worker SkDPoint dPtAtT(double mid) const { 210*c8dee2aaSAndroid Build Coastguard Worker return (*CurveDPointAtT[fVerb])(fPts, fWeight, mid); 211*c8dee2aaSAndroid Build Coastguard Worker } 212*c8dee2aaSAndroid Build Coastguard Worker dSlopeAtT(double mid)213*c8dee2aaSAndroid Build Coastguard Worker SkDVector dSlopeAtT(double mid) const { 214*c8dee2aaSAndroid Build Coastguard Worker return (*CurveDSlopeAtT[fVerb])(fPts, fWeight, mid); 215*c8dee2aaSAndroid Build Coastguard Worker } 216*c8dee2aaSAndroid Build Coastguard Worker 217*c8dee2aaSAndroid Build Coastguard Worker void dump() const; 218*c8dee2aaSAndroid Build Coastguard Worker void dumpAll() const; 219*c8dee2aaSAndroid Build Coastguard Worker void dumpAngles() const; 220*c8dee2aaSAndroid Build Coastguard Worker void dumpCoin() const; 221*c8dee2aaSAndroid Build Coastguard Worker void dumpPts(const char* prefix = "seg") const; 222*c8dee2aaSAndroid Build Coastguard Worker void dumpPtsInner(const char* prefix = "seg") const; 223*c8dee2aaSAndroid Build Coastguard Worker 224*c8dee2aaSAndroid Build Coastguard Worker const SkOpPtT* existing(double t, const SkOpSegment* opp) const; 225*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, 226*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase** nextEnd, bool* unsortable, bool* simple, 227*c8dee2aaSAndroid Build Coastguard Worker SkPathOp op, int xorMiMask, int xorSuMask); 228*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* findNextWinding(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, 229*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase** nextEnd, bool* unsortable); 230*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable); 231*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* findSortableTop(SkOpContour* ); 232*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* globalState() const; 233*c8dee2aaSAndroid Build Coastguard Worker head()234*c8dee2aaSAndroid Build Coastguard Worker const SkOpSpan* head() const { 235*c8dee2aaSAndroid Build Coastguard Worker return &fHead; 236*c8dee2aaSAndroid Build Coastguard Worker } 237*c8dee2aaSAndroid Build Coastguard Worker head()238*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* head() { 239*c8dee2aaSAndroid Build Coastguard Worker return &fHead; 240*c8dee2aaSAndroid Build Coastguard Worker } 241*c8dee2aaSAndroid Build Coastguard Worker 242*c8dee2aaSAndroid Build Coastguard Worker void init(SkPoint pts[], SkScalar weight, SkOpContour* parent, SkPath::Verb verb); 243*c8dee2aaSAndroid Build Coastguard Worker insert(SkOpSpan * prev)244*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* insert(SkOpSpan* prev) { 245*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* globalState = this->globalState(); 246*c8dee2aaSAndroid Build Coastguard Worker globalState->setAllocatedOpSpan(); 247*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* result = globalState->allocator()->make<SkOpSpan>(); 248*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase* next = prev->next(); 249*c8dee2aaSAndroid Build Coastguard Worker result->setPrev(prev); 250*c8dee2aaSAndroid Build Coastguard Worker prev->setNext(result); 251*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(result->ptT()->fT = 0); 252*c8dee2aaSAndroid Build Coastguard Worker result->setNext(next); 253*c8dee2aaSAndroid Build Coastguard Worker if (next) { 254*c8dee2aaSAndroid Build Coastguard Worker next->setPrev(result); 255*c8dee2aaSAndroid Build Coastguard Worker } 256*c8dee2aaSAndroid Build Coastguard Worker return result; 257*c8dee2aaSAndroid Build Coastguard Worker } 258*c8dee2aaSAndroid Build Coastguard Worker 259*c8dee2aaSAndroid Build Coastguard Worker bool isClose(double t, const SkOpSegment* opp) const; 260*c8dee2aaSAndroid Build Coastguard Worker isHorizontal()261*c8dee2aaSAndroid Build Coastguard Worker bool isHorizontal() const { 262*c8dee2aaSAndroid Build Coastguard Worker return fBounds.fTop == fBounds.fBottom; 263*c8dee2aaSAndroid Build Coastguard Worker } 264*c8dee2aaSAndroid Build Coastguard Worker isSimple(SkOpSpanBase ** end,int * step)265*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* isSimple(SkOpSpanBase** end, int* step) const { 266*c8dee2aaSAndroid Build Coastguard Worker return nextChase(end, step, nullptr, nullptr); 267*c8dee2aaSAndroid Build Coastguard Worker } 268*c8dee2aaSAndroid Build Coastguard Worker isVertical()269*c8dee2aaSAndroid Build Coastguard Worker bool isVertical() const { 270*c8dee2aaSAndroid Build Coastguard Worker return fBounds.fLeft == fBounds.fRight; 271*c8dee2aaSAndroid Build Coastguard Worker } 272*c8dee2aaSAndroid Build Coastguard Worker isVertical(SkOpSpanBase * start,SkOpSpanBase * end)273*c8dee2aaSAndroid Build Coastguard Worker bool isVertical(SkOpSpanBase* start, SkOpSpanBase* end) const { 274*c8dee2aaSAndroid Build Coastguard Worker return (*CurveIsVertical[fVerb])(fPts, fWeight, start->t(), end->t()); 275*c8dee2aaSAndroid Build Coastguard Worker } 276*c8dee2aaSAndroid Build Coastguard Worker 277*c8dee2aaSAndroid Build Coastguard Worker bool isXor() const; 278*c8dee2aaSAndroid Build Coastguard Worker joinEnds(SkOpSegment * start)279*c8dee2aaSAndroid Build Coastguard Worker void joinEnds(SkOpSegment* start) { 280*c8dee2aaSAndroid Build Coastguard Worker fTail.ptT()->addOpp(start->fHead.ptT(), start->fHead.ptT()); 281*c8dee2aaSAndroid Build Coastguard Worker } 282*c8dee2aaSAndroid Build Coastguard Worker lastPt()283*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& lastPt() const { 284*c8dee2aaSAndroid Build Coastguard Worker return fPts[SkPathOpsVerbToPoints(fVerb)]; 285*c8dee2aaSAndroid Build Coastguard Worker } 286*c8dee2aaSAndroid Build Coastguard Worker 287*c8dee2aaSAndroid Build Coastguard Worker void markAllDone(); 288*c8dee2aaSAndroid Build Coastguard Worker bool markAndChaseDone(SkOpSpanBase* start, SkOpSpanBase* end, SkOpSpanBase** found); 289*c8dee2aaSAndroid Build Coastguard Worker bool markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding, 290*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase** lastPtr); 291*c8dee2aaSAndroid Build Coastguard Worker bool markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding, 292*c8dee2aaSAndroid Build Coastguard Worker int oppWinding, SkOpSpanBase** lastPtr); 293*c8dee2aaSAndroid Build Coastguard Worker bool markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle, SkOpSpanBase** result); 294*c8dee2aaSAndroid Build Coastguard Worker bool markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding, 295*c8dee2aaSAndroid Build Coastguard Worker const SkOpAngle* angle, SkOpSpanBase** result); 296*c8dee2aaSAndroid Build Coastguard Worker void markDone(SkOpSpan* ); 297*c8dee2aaSAndroid Build Coastguard Worker bool markWinding(SkOpSpan* , int winding); 298*c8dee2aaSAndroid Build Coastguard Worker bool markWinding(SkOpSpan* , int winding, int oppWinding); 299*c8dee2aaSAndroid Build Coastguard Worker bool match(const SkOpPtT* span, const SkOpSegment* parent, double t, const SkPoint& pt) const; 300*c8dee2aaSAndroid Build Coastguard Worker bool missingCoincidence(); 301*c8dee2aaSAndroid Build Coastguard Worker bool moveMultiples(); 302*c8dee2aaSAndroid Build Coastguard Worker bool moveNearby(); 303*c8dee2aaSAndroid Build Coastguard Worker next()304*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* next() const { 305*c8dee2aaSAndroid Build Coastguard Worker return fNext; 306*c8dee2aaSAndroid Build Coastguard Worker } 307*c8dee2aaSAndroid Build Coastguard Worker 308*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* nextChase(SkOpSpanBase** , int* step, SkOpSpan** , SkOpSpanBase** last) const; 309*c8dee2aaSAndroid Build Coastguard Worker bool operand() const; 310*c8dee2aaSAndroid Build Coastguard Worker OppSign(const SkOpSpanBase * start,const SkOpSpanBase * end)311*c8dee2aaSAndroid Build Coastguard Worker static int OppSign(const SkOpSpanBase* start, const SkOpSpanBase* end) { 312*c8dee2aaSAndroid Build Coastguard Worker int result = start->t() < end->t() ? -start->upCast()->oppValue() 313*c8dee2aaSAndroid Build Coastguard Worker : end->upCast()->oppValue(); 314*c8dee2aaSAndroid Build Coastguard Worker return result; 315*c8dee2aaSAndroid Build Coastguard Worker } 316*c8dee2aaSAndroid Build Coastguard Worker 317*c8dee2aaSAndroid Build Coastguard Worker bool oppXor() const; 318*c8dee2aaSAndroid Build Coastguard Worker prev()319*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* prev() const { 320*c8dee2aaSAndroid Build Coastguard Worker return fPrev; 321*c8dee2aaSAndroid Build Coastguard Worker } 322*c8dee2aaSAndroid Build Coastguard Worker ptAtT(double mid)323*c8dee2aaSAndroid Build Coastguard Worker SkPoint ptAtT(double mid) const { 324*c8dee2aaSAndroid Build Coastguard Worker return (*CurvePointAtT[fVerb])(fPts, fWeight, mid); 325*c8dee2aaSAndroid Build Coastguard Worker } 326*c8dee2aaSAndroid Build Coastguard Worker pts()327*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* pts() const { 328*c8dee2aaSAndroid Build Coastguard Worker return fPts; 329*c8dee2aaSAndroid Build Coastguard Worker } 330*c8dee2aaSAndroid Build Coastguard Worker ptsDisjoint(const SkOpPtT & span,const SkOpPtT & test)331*c8dee2aaSAndroid Build Coastguard Worker bool ptsDisjoint(const SkOpPtT& span, const SkOpPtT& test) const { 332*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this == span.segment()); 333*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this == test.segment()); 334*c8dee2aaSAndroid Build Coastguard Worker return ptsDisjoint(span.fT, span.fPt, test.fT, test.fPt); 335*c8dee2aaSAndroid Build Coastguard Worker } 336*c8dee2aaSAndroid Build Coastguard Worker ptsDisjoint(const SkOpPtT & span,double t,const SkPoint & pt)337*c8dee2aaSAndroid Build Coastguard Worker bool ptsDisjoint(const SkOpPtT& span, double t, const SkPoint& pt) const { 338*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this == span.segment()); 339*c8dee2aaSAndroid Build Coastguard Worker return ptsDisjoint(span.fT, span.fPt, t, pt); 340*c8dee2aaSAndroid Build Coastguard Worker } 341*c8dee2aaSAndroid Build Coastguard Worker 342*c8dee2aaSAndroid Build Coastguard Worker bool ptsDisjoint(double t1, const SkPoint& pt1, double t2, const SkPoint& pt2) const; 343*c8dee2aaSAndroid Build Coastguard Worker 344*c8dee2aaSAndroid Build Coastguard Worker void rayCheck(const SkOpRayHit& base, SkOpRayDir dir, SkOpRayHit** hits, SkArenaAlloc*); 345*c8dee2aaSAndroid Build Coastguard Worker void release(const SkOpSpan* ); 346*c8dee2aaSAndroid Build Coastguard Worker 347*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN resetDebugVisited()348*c8dee2aaSAndroid Build Coastguard Worker void resetDebugVisited() const { 349*c8dee2aaSAndroid Build Coastguard Worker fDebugVisited = false; 350*c8dee2aaSAndroid Build Coastguard Worker } 351*c8dee2aaSAndroid Build Coastguard Worker #endif 352*c8dee2aaSAndroid Build Coastguard Worker resetVisited()353*c8dee2aaSAndroid Build Coastguard Worker void resetVisited() { 354*c8dee2aaSAndroid Build Coastguard Worker fVisited = false; 355*c8dee2aaSAndroid Build Coastguard Worker } 356*c8dee2aaSAndroid Build Coastguard Worker setContour(SkOpContour * contour)357*c8dee2aaSAndroid Build Coastguard Worker void setContour(SkOpContour* contour) { 358*c8dee2aaSAndroid Build Coastguard Worker fContour = contour; 359*c8dee2aaSAndroid Build Coastguard Worker } 360*c8dee2aaSAndroid Build Coastguard Worker setNext(SkOpSegment * next)361*c8dee2aaSAndroid Build Coastguard Worker void setNext(SkOpSegment* next) { 362*c8dee2aaSAndroid Build Coastguard Worker fNext = next; 363*c8dee2aaSAndroid Build Coastguard Worker } 364*c8dee2aaSAndroid Build Coastguard Worker setPrev(SkOpSegment * prev)365*c8dee2aaSAndroid Build Coastguard Worker void setPrev(SkOpSegment* prev) { 366*c8dee2aaSAndroid Build Coastguard Worker fPrev = prev; 367*c8dee2aaSAndroid Build Coastguard Worker } 368*c8dee2aaSAndroid Build Coastguard Worker setUpWinding(SkOpSpanBase * start,SkOpSpanBase * end,int * maxWinding,int * sumWinding)369*c8dee2aaSAndroid Build Coastguard Worker void setUpWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* maxWinding, int* sumWinding) { 370*c8dee2aaSAndroid Build Coastguard Worker int deltaSum = SpanSign(start, end); 371*c8dee2aaSAndroid Build Coastguard Worker *maxWinding = *sumWinding; 372*c8dee2aaSAndroid Build Coastguard Worker if (*sumWinding == SK_MinS32) { 373*c8dee2aaSAndroid Build Coastguard Worker return; 374*c8dee2aaSAndroid Build Coastguard Worker } 375*c8dee2aaSAndroid Build Coastguard Worker *sumWinding -= deltaSum; 376*c8dee2aaSAndroid Build Coastguard Worker } 377*c8dee2aaSAndroid Build Coastguard Worker 378*c8dee2aaSAndroid Build Coastguard Worker void setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, 379*c8dee2aaSAndroid Build Coastguard Worker int* maxWinding, int* sumWinding); 380*c8dee2aaSAndroid Build Coastguard Worker void setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, int* sumSuWinding, 381*c8dee2aaSAndroid Build Coastguard Worker int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding); 382*c8dee2aaSAndroid Build Coastguard Worker bool sortAngles(); 383*c8dee2aaSAndroid Build Coastguard Worker bool spansNearby(const SkOpSpanBase* ref, const SkOpSpanBase* check, bool* found) const; 384*c8dee2aaSAndroid Build Coastguard Worker SpanSign(const SkOpSpanBase * start,const SkOpSpanBase * end)385*c8dee2aaSAndroid Build Coastguard Worker static int SpanSign(const SkOpSpanBase* start, const SkOpSpanBase* end) { 386*c8dee2aaSAndroid Build Coastguard Worker int result = start->t() < end->t() ? -start->upCast()->windValue() 387*c8dee2aaSAndroid Build Coastguard Worker : end->upCast()->windValue(); 388*c8dee2aaSAndroid Build Coastguard Worker return result; 389*c8dee2aaSAndroid Build Coastguard Worker } 390*c8dee2aaSAndroid Build Coastguard Worker spanToAngle(SkOpSpanBase * start,SkOpSpanBase * end)391*c8dee2aaSAndroid Build Coastguard Worker SkOpAngle* spanToAngle(SkOpSpanBase* start, SkOpSpanBase* end) { 392*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(start != end); 393*c8dee2aaSAndroid Build Coastguard Worker return start->t() < end->t() ? start->upCast()->toAngle() : start->fromAngle(); 394*c8dee2aaSAndroid Build Coastguard Worker } 395*c8dee2aaSAndroid Build Coastguard Worker 396*c8dee2aaSAndroid Build Coastguard Worker bool subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, SkDCurve* result) const; 397*c8dee2aaSAndroid Build Coastguard Worker tail()398*c8dee2aaSAndroid Build Coastguard Worker const SkOpSpanBase* tail() const { 399*c8dee2aaSAndroid Build Coastguard Worker return &fTail; 400*c8dee2aaSAndroid Build Coastguard Worker } 401*c8dee2aaSAndroid Build Coastguard Worker tail()402*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase* tail() { 403*c8dee2aaSAndroid Build Coastguard Worker return &fTail; 404*c8dee2aaSAndroid Build Coastguard Worker } 405*c8dee2aaSAndroid Build Coastguard Worker 406*c8dee2aaSAndroid Build Coastguard Worker bool testForCoincidence(const SkOpPtT* priorPtT, const SkOpPtT* ptT, const SkOpSpanBase* prior, 407*c8dee2aaSAndroid Build Coastguard Worker const SkOpSpanBase* spanBase, const SkOpSegment* opp) const; 408*c8dee2aaSAndroid Build Coastguard Worker 409*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* undoneSpan(); 410*c8dee2aaSAndroid Build Coastguard Worker int updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const; 411*c8dee2aaSAndroid Build Coastguard Worker int updateOppWinding(const SkOpAngle* angle) const; 412*c8dee2aaSAndroid Build Coastguard Worker int updateOppWindingReverse(const SkOpAngle* angle) const; 413*c8dee2aaSAndroid Build Coastguard Worker int updateWinding(SkOpSpanBase* start, SkOpSpanBase* end); 414*c8dee2aaSAndroid Build Coastguard Worker int updateWinding(SkOpAngle* angle); 415*c8dee2aaSAndroid Build Coastguard Worker int updateWindingReverse(const SkOpAngle* angle); 416*c8dee2aaSAndroid Build Coastguard Worker 417*c8dee2aaSAndroid Build Coastguard Worker static bool UseInnerWinding(int outerWinding, int innerWinding); 418*c8dee2aaSAndroid Build Coastguard Worker verb()419*c8dee2aaSAndroid Build Coastguard Worker SkPath::Verb verb() const { 420*c8dee2aaSAndroid Build Coastguard Worker return fVerb; 421*c8dee2aaSAndroid Build Coastguard Worker } 422*c8dee2aaSAndroid Build Coastguard Worker 423*c8dee2aaSAndroid Build Coastguard Worker // look for two different spans that point to the same opposite segment visited()424*c8dee2aaSAndroid Build Coastguard Worker bool visited() { 425*c8dee2aaSAndroid Build Coastguard Worker if (!fVisited) { 426*c8dee2aaSAndroid Build Coastguard Worker fVisited = true; 427*c8dee2aaSAndroid Build Coastguard Worker return false; 428*c8dee2aaSAndroid Build Coastguard Worker } 429*c8dee2aaSAndroid Build Coastguard Worker return true; 430*c8dee2aaSAndroid Build Coastguard Worker } 431*c8dee2aaSAndroid Build Coastguard Worker weight()432*c8dee2aaSAndroid Build Coastguard Worker SkScalar weight() const { 433*c8dee2aaSAndroid Build Coastguard Worker return fWeight; 434*c8dee2aaSAndroid Build Coastguard Worker } 435*c8dee2aaSAndroid Build Coastguard Worker 436*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan* windingSpanAtT(double tHit); 437*c8dee2aaSAndroid Build Coastguard Worker int windSum(const SkOpAngle* angle) const; 438*c8dee2aaSAndroid Build Coastguard Worker 439*c8dee2aaSAndroid Build Coastguard Worker private: 440*c8dee2aaSAndroid Build Coastguard Worker SkOpSpan fHead; // the head span always has its t set to zero 441*c8dee2aaSAndroid Build Coastguard Worker SkOpSpanBase fTail; // the tail span always has its t set to one 442*c8dee2aaSAndroid Build Coastguard Worker SkOpContour* fContour; 443*c8dee2aaSAndroid Build Coastguard Worker SkOpSegment* fNext; // forward-only linked list used by contour to walk the segments 444*c8dee2aaSAndroid Build Coastguard Worker const SkOpSegment* fPrev; 445*c8dee2aaSAndroid Build Coastguard Worker SkPoint* fPts; // pointer into array of points owned by edge builder that may be tweaked 446*c8dee2aaSAndroid Build Coastguard Worker SkPathOpsBounds fBounds; // tight bounds 447*c8dee2aaSAndroid Build Coastguard Worker SkScalar fWeight; 448*c8dee2aaSAndroid Build Coastguard Worker int fCount; // number of spans (one for a non-intersecting segment) 449*c8dee2aaSAndroid Build Coastguard Worker int fDoneCount; // number of processed spans (zero initially) 450*c8dee2aaSAndroid Build Coastguard Worker SkPath::Verb fVerb; 451*c8dee2aaSAndroid Build Coastguard Worker bool fVisited; // used by missing coincidence check 452*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COIN 453*c8dee2aaSAndroid Build Coastguard Worker mutable bool fDebugVisited; // used by debug missing coincidence check 454*c8dee2aaSAndroid Build Coastguard Worker #endif 455*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_COINCIDENCE_ORDER 456*c8dee2aaSAndroid Build Coastguard Worker mutable int fDebugBaseIndex; 457*c8dee2aaSAndroid Build Coastguard Worker mutable SkScalar fDebugBaseMin; // if > 0, the 1st t value in this seg vis-a-vis the ref seg 458*c8dee2aaSAndroid Build Coastguard Worker mutable SkScalar fDebugBaseMax; 459*c8dee2aaSAndroid Build Coastguard Worker mutable int fDebugLastIndex; 460*c8dee2aaSAndroid Build Coastguard Worker mutable SkScalar fDebugLastMin; // if > 0, the last t -- next t val - base has same sign 461*c8dee2aaSAndroid Build Coastguard Worker mutable SkScalar fDebugLastMax; 462*c8dee2aaSAndroid Build Coastguard Worker #endif 463*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(int fID;) 464*c8dee2aaSAndroid Build Coastguard Worker }; 465*c8dee2aaSAndroid Build Coastguard Worker 466*c8dee2aaSAndroid Build Coastguard Worker #endif 467