xref: /aosp_15_r20/external/skia/src/pathops/SkOpSegment.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker #ifndef 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