blob: d56ce8e206a50cc3ef0a6e6a3bf42ec48e86903e [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#ifndef SkOpSegment_DEFINE
8#define SkOpSegment_DEFINE
9
10#include "SkOpAngle.h"
caryclark@google.comcffbcc32013-06-04 17:59:42 +000011#include "SkOpSpan.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000012#include "SkPathOpsBounds.h"
13#include "SkPathOpsCurve.h"
caryclark@google.comd892bd82013-06-17 14:10:36 +000014#include "SkTArray.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000015#include "SkTDArray.h"
16
17class SkPathWriter;
18
19class SkOpSegment {
20public:
21 SkOpSegment() {
caryclark@google.com570863f2013-09-16 15:55:01 +000022#ifdef SK_DEBUG
23 fID = ++SkPathOpsDebug::gSegmentID;
caryclark@google.com07393ca2013-04-08 11:47:37 +000024#endif
25 }
26
27 bool operator<(const SkOpSegment& rh) const {
28 return fBounds.fTop < rh.fBounds.fTop;
29 }
30
31 const SkPathOpsBounds& bounds() const {
32 return fBounds;
33 }
34
35 // OPTIMIZE
36 // when the edges are initially walked, they don't automatically get the prior and next
37 // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
38 // and would additionally remove the need for similar checks in condition edges. It would
39 // also allow intersection code to assume end of segment intersections (maybe?)
40 bool complete() const {
41 int count = fTs.count();
42 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
43 }
44
caryclark@google.comcffbcc32013-06-04 17:59:42 +000045 int count() const {
46 return fTs.count();
47 }
48
caryclark@google.com07393ca2013-04-08 11:47:37 +000049 bool done() const {
50 SkASSERT(fDoneSpans <= fTs.count());
51 return fDoneSpans == fTs.count();
52 }
53
54 bool done(int min) const {
55 return fTs[min].fDone;
56 }
57
58 bool done(const SkOpAngle* angle) const {
59 return done(SkMin32(angle->start(), angle->end()));
60 }
61
caryclark@google.com570863f2013-09-16 15:55:01 +000062 // used only by partial coincidence detection
63 SkDPoint dPtAtT(double mid) const {
64 return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
65 }
66
caryclark@google.com07393ca2013-04-08 11:47:37 +000067 SkVector dxdy(int index) const {
reed@google.com277c3f82013-05-31 15:17:50 +000068 return (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs[index].fT);
caryclark@google.com07393ca2013-04-08 11:47:37 +000069 }
70
71 SkScalar dy(int index) const {
72 return dxdy(index).fY;
73 }
74
75 bool intersected() const {
76 return fTs.count() > 0;
77 }
78
79 bool isCanceled(int tIndex) const {
80 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0;
81 }
82
83 bool isConnected(int startIndex, int endIndex) const {
84 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum != SK_MinS32;
85 }
86
87 bool isHorizontal() const {
88 return fBounds.fTop == fBounds.fBottom;
89 }
90
91 bool isVertical() const {
92 return fBounds.fLeft == fBounds.fRight;
93 }
94
95 bool isVertical(int start, int end) const {
reed@google.com277c3f82013-05-31 15:17:50 +000096 return (*CurveIsVertical[SkPathOpsVerbToPoints(fVerb)])(fPts, start, end);
caryclark@google.com07393ca2013-04-08 11:47:37 +000097 }
98
99 bool operand() const {
100 return fOperand;
101 }
102
103 int oppSign(const SkOpAngle* angle) const {
104 SkASSERT(angle->segment() == this);
105 return oppSign(angle->start(), angle->end());
106 }
107
108 int oppSign(int startIndex, int endIndex) const {
109 int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[endIndex].fOppValue;
110#if DEBUG_WIND_BUMP
111 SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
112#endif
113 return result;
114 }
115
116 int oppSum(int tIndex) const {
117 return fTs[tIndex].fOppSum;
118 }
119
120 int oppSum(const SkOpAngle* angle) const {
121 int lesser = SkMin32(angle->start(), angle->end());
122 return fTs[lesser].fOppSum;
123 }
124
125 int oppValue(int tIndex) const {
126 return fTs[tIndex].fOppValue;
127 }
128
129 int oppValue(const SkOpAngle* angle) const {
130 int lesser = SkMin32(angle->start(), angle->end());
131 return fTs[lesser].fOppValue;
132 }
133
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000134 const SkOpSegment* other(int index) const {
135 return fTs[index].fOther;
136 }
137
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000138 // was used only by right angle winding finding
139 SkPoint ptAtT(double mid) const {
140 return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
141 }
142
caryclark@google.com07393ca2013-04-08 11:47:37 +0000143 const SkPoint* pts() const {
144 return fPts;
145 }
146
147 void reset() {
148 init(NULL, (SkPath::Verb) -1, false, false);
149 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
150 fTs.reset();
151 }
152
153 void setOppXor(bool isOppXor) {
154 fOppXor = isOppXor;
155 }
156
caryclark@google.com07393ca2013-04-08 11:47:37 +0000157 void setUpWinding(int index, int endIndex, int* maxWinding, int* sumWinding) {
158 int deltaSum = spanSign(index, endIndex);
159 *maxWinding = *sumWinding;
160 *sumWinding -= deltaSum;
161 }
162
163 // OPTIMIZATION: mark as debugging only if used solely by tests
164 const SkOpSpan& span(int tIndex) const {
165 return fTs[tIndex];
166 }
167
caryclark@google.comad65a3e2013-04-15 19:13:59 +0000168 // OPTIMIZATION: mark as debugging only if used solely by tests
169 const SkTDArray<SkOpSpan>& spans() const {
170 return fTs;
171 }
172
caryclark@google.com07393ca2013-04-08 11:47:37 +0000173 int spanSign(const SkOpAngle* angle) const {
174 SkASSERT(angle->segment() == this);
175 return spanSign(angle->start(), angle->end());
176 }
177
178 int spanSign(int startIndex, int endIndex) const {
179 int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[endIndex].fWindValue;
180#if DEBUG_WIND_BUMP
181 SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
182#endif
183 return result;
184 }
185
186 // OPTIMIZATION: mark as debugging only if used solely by tests
187 double t(int tIndex) const {
188 return fTs[tIndex].fT;
189 }
190
191 double tAtMid(int start, int end, double mid) const {
192 return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
193 }
194
195 bool unsortable(int index) const {
196 return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd;
197 }
198
199 void updatePts(const SkPoint pts[]) {
200 fPts = pts;
201 }
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000202
caryclark@google.com07393ca2013-04-08 11:47:37 +0000203 SkPath::Verb verb() const {
204 return fVerb;
205 }
206
207 int windSum(int tIndex) const {
208 return fTs[tIndex].fWindSum;
209 }
210
211 int windValue(int tIndex) const {
212 return fTs[tIndex].fWindValue;
213 }
214
215 SkScalar xAtT(int index) const {
216 return xAtT(&fTs[index]);
217 }
218
219 SkScalar xAtT(const SkOpSpan* span) const {
220 return xyAtT(span).fX;
221 }
222
223 const SkPoint& xyAtT(const SkOpSpan* span) const {
224 return span->fPt;
225 }
226
caryclark@google.com07393ca2013-04-08 11:47:37 +0000227 const SkPoint& xyAtT(int index) const {
228 return xyAtT(&fTs[index]);
229 }
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000230
caryclark@google.com07393ca2013-04-08 11:47:37 +0000231 SkScalar yAtT(int index) const {
232 return yAtT(&fTs[index]);
233 }
234
235 SkScalar yAtT(const SkOpSpan* span) const {
236 return xyAtT(span).fY;
237 }
238
caryclark@google.comd892bd82013-06-17 14:10:36 +0000239 bool activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* angles);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000240 SkPoint activeLeftTop(bool onlySortable, int* firstT) const;
241 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000242 bool activeWinding(int index, int endIndex);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000243 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
244 void addCurveTo(int start, int end, SkPathWriter* path, bool active) const;
245 void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
246 void addOtherT(int index, double otherT, int otherIndex);
247 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
248 int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT);
caryclark@google.com570863f2013-09-16 15:55:01 +0000249 int addT(SkOpSegment* other, const SkPoint& pt, double newT, bool isNear);
250 void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000251 void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT,
252 SkOpSegment* other);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000253 void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000254 bool betweenTs(int lesser, double testT, int greater) const;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000255 void checkEnds();
caryclark@google.com570863f2013-09-16 15:55:01 +0000256 bool checkSmall(int index) const;
257 void checkTiny();
258 int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType,
259 SkTArray<SkOpAngle, true>* angles, SkTArray<SkOpAngle*, true>* sorted);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000260 int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool* hitSomething,
261 double mid, bool opp, bool current) const;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000262 bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, int oEnd,
263 int step, SkPoint* startPt, SkPoint* endPt, double* endT) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000264 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
265 bool* unsortable, SkPathOp op, const int xorMiMask,
266 const int xorSuMask);
267 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
268 bool* unsortable);
269 SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000270 int findT(double t, const SkOpSegment* ) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000271 SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool onlySortable);
272 void fixOtherTIndex();
273 void initWinding(int start, int end);
274 void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind,
caryclark@google.com570863f2013-09-16 15:55:01 +0000275 SkScalar hitOppDx);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000276 bool isMissing(double startT, const SkPoint& pt) const;
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000277 bool isTiny(const SkOpAngle* angle) const;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000278 bool joinCoincidence(bool end, SkOpSegment* other, double otherT, int step, bool cancel);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000279 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
280 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
281 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding);
282 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding,
283 bool activeAngle, const SkOpAngle* angle);
284 void markDone(int index, int winding);
285 void markDoneBinary(int index);
286 void markDoneUnary(int index);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000287 bool nextCandidate(int* start, int* end) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000288 int nextSpan(int from, int step) const;
289 void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding,
290 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding);
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000291 enum SortAngleKind {
292 kMustBeOrdered_SortAngleKind, // required for winding calc
293 kMayBeUnordered_SortAngleKind // ok for find top
294 };
caryclark@google.com570863f2013-09-16 15:55:01 +0000295 static bool SortAngles(const SkTArray<SkOpAngle, true>& angles, // FIXME: replace with
296 SkTArray<SkOpAngle*, true>* angleList, // Sort Angles 2
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000297 SortAngleKind );
caryclark@google.com570863f2013-09-16 15:55:01 +0000298 static bool SortAngles2(const SkTArray<SkOpAngle, true>& angles,
299 SkTArray<SkOpAngle*, true>* angleList);
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000300 bool subDivide(int start, int end, SkPoint edge[4]) const;
301 bool subDivide(int start, int end, SkDCubic* result) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000302 void undoneSpan(int* start, int* end);
303 int updateOppWindingReverse(const SkOpAngle* angle) const;
304 int updateWindingReverse(const SkOpAngle* angle) const;
305 static bool UseInnerWinding(int outerWinding, int innerWinding);
306 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const;
307 int windSum(const SkOpAngle* angle) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000308
caryclark@google.com570863f2013-09-16 15:55:01 +0000309#ifdef SK_DEBUG
caryclark@google.com07393ca2013-04-08 11:47:37 +0000310 int debugID() const {
311 return fID;
312 }
313#endif
caryclark@google.coma5e55922013-05-07 18:51:31 +0000314#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
caryclark@google.com07393ca2013-04-08 11:47:37 +0000315 void debugShowActiveSpans() const;
316#endif
317#if DEBUG_SORT || DEBUG_SWAP_TOP
caryclark@google.comd892bd82013-06-17 14:10:36 +0000318 void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first,
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000319 const int contourWinding, const int oppContourWinding, bool sortable) const;
320 void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first,
321 bool sortable);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000322#endif
323#if DEBUG_CONCIDENT
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000324 void debugShowTs(const char* prefix) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000325#endif
326#if DEBUG_SHOW_WINDING
327 int debugShowWindingValues(int slotCount, int ofInterest) const;
328#endif
329
330private:
caryclark@google.com570863f2013-09-16 15:55:01 +0000331 struct MissingSpan {
332 enum Command {
333 kNoAction,
334 kAddMissing,
335 kRemoveNear,
336 kZeroSpan,
337 } fCommand;
338 double fT;
339 double fEndT;
340 SkOpSegment* fSegment;
341 SkOpSegment* fOther;
342 double fOtherT;
343 SkPoint fPt;
344 };
345
caryclark@google.comd892bd82013-06-17 14:10:36 +0000346 bool activeAngleOther(int index, int* done, SkTArray<SkOpAngle, true>* angles);
347 bool activeAngleInner(int index, int* done, SkTArray<SkOpAngle, true>* angles);
caryclark@google.com570863f2013-09-16 15:55:01 +0000348 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
349 int* sumMiWinding, int* sumSuWinding, int* maxWinding, int* sumWinding,
350 int* oppMaxWinding, int* oppSumWinding);
351 bool activeWinding(int index, int endIndex, int* maxWinding, int* sumWinding);
caryclark@google.comd892bd82013-06-17 14:10:36 +0000352 void addAngle(SkTArray<SkOpAngle, true>* angles, int start, int end) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000353 void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
354 void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
355 void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt,
356 const SkPoint& oPt);
caryclark@google.comd892bd82013-06-17 14:10:36 +0000357 void addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000358 void adjustMissingNear(const SkPoint& startPt, const SkPoint& endPt,
359 SkTArray<MissingSpan, true>* );
360 void adjustNear(double startT, const SkPoint& endPt, SkTArray<MissingSpan, true>* );
361 void adjustOtherNear(double startT, const SkPoint& startPt, const SkPoint& endPt,
362 SkTArray<MissingSpan, true>* );
363 MissingSpan::Command adjustThisNear(double startT, const SkPoint& startPt, const SkPoint& endPt,
364 SkTArray<MissingSpan, true>* );
365 int advanceCoincidentOther(double oEndT, int oIndex);
366 int advanceCoincidentThis(int index);
367 bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const;
368 bool buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool includeOpp) const;
caryclark@google.comd892bd82013-06-17 14:10:36 +0000369 void buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000370 void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
371 SkTArray<SkPoint, true>* outsideTs);
372 bool bumpCoincident(SkOpSpan* test, bool bigger, bool binary);
373 void bumpCoincidentOther(const SkOpSpan& oTest, int* index,
374 SkTArray<SkPoint, true>* outsideTs);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000375 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
376 bool clockwise(int tStart, int tEnd) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000377 static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
378 SkOpAngle::IncludeType );
379 static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
380 SkOpAngle::IncludeType );
381 bool decrementSpan(SkOpSpan* span);
caryclark@google.comd892bd82013-06-17 14:10:36 +0000382 int findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, int end);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000383 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd);
caryclark@google.com570863f2013-09-16 15:55:01 +0000384 bool isSimple(int end) const;
385 bool isTiny(int index) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000386 void matchWindingValue(int tIndex, double t, bool borrowWind);
387 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
388 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding);
389 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding);
390 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding);
391 SkOpSpan* markAngle(int maxWinding, int sumWinding, bool activeAngle, const SkOpAngle* angle);
392 void markDoneBinary(int index, int winding, int oppWinding);
393 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding);
394 void markOneDone(const char* funName, int tIndex, int winding);
395 void markOneDoneBinary(const char* funName, int tIndex);
396 void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding);
397 void markOneDoneUnary(const char* funName, int tIndex);
caryclark@google.com570863f2013-09-16 15:55:01 +0000398 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding);
399 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding);
400 void markWinding(int index, int winding);
401 void markWinding(int index, int winding, int oppWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000402 void markUnsortable(int start, int end);
403 bool monotonicInY(int tStart, int tEnd) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000404 double missingNear(double otherT, const SkOpSegment* other, const SkPoint& startPt,
405 const SkPoint& endPt) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000406 bool multipleSpans(int end) const;
407 SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last);
caryclark@google.com570863f2013-09-16 15:55:01 +0000408 int nextExactSpan(int from, int step) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000409 bool serpentine(int tStart, int tEnd) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000410 void setUpWindings(int index, int endIndex, int* sumMiWinding,
411 int* maxWinding, int* sumWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000412 void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000413 static void TrackOutsidePair(SkTArray<SkPoint, true>* outsideTs, const SkPoint& endPt,
414 const SkPoint& startPt);
415 static void TrackOutside(SkTArray<SkPoint, true>* outsideTs, const SkPoint& startPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000416 int updateOppWinding(int index, int endIndex) const;
417 int updateOppWinding(const SkOpAngle* angle) const;
418 int updateWinding(int index, int endIndex) const;
419 int updateWinding(const SkOpAngle* angle) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000420 int updateWindingReverse(int index, int endIndex) const;
421 static bool UseInnerWindingReverse(int outerWinding, int innerWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000422 SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
423 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
caryclark@google.com570863f2013-09-16 15:55:01 +0000424 int windValue(const SkOpAngle* angle) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000425 int windValueAt(double t) const;
426 void zeroSpan(SkOpSpan* span);
427
428#if DEBUG_SWAP_TOP
429 bool controlsContainedByEnds(int tStart, int tEnd) const;
430#endif
431#if DEBUG_CONCIDENT
432 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
433#endif
434#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
435 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding);
436 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding, int oppWinding);
437#endif
438#if DEBUG_WINDING
439 static char as_digit(int value) {
440 return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
441 }
442#endif
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000443 void debugValidate() const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000444#ifdef SK_DEBUG
445 void dumpPts() const;
446 void dumpDPts() const;
447 void dumpSpans() const;
448#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000449
450 const SkPoint* fPts;
451 SkPathOpsBounds fBounds;
caryclark@google.comd892bd82013-06-17 14:10:36 +0000452 // FIXME: can't convert to SkTArray because it uses insert
caryclark@google.com07393ca2013-04-08 11:47:37 +0000453 SkTDArray<SkOpSpan> fTs; // two or more (always includes t=0 t=1)
454 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
455 int fDoneSpans; // quick check that segment is finished
456 // OPTIMIZATION: force the following to be byte-sized
457 SkPath::Verb fVerb;
458 bool fOperand;
459 bool fXor; // set if original contour had even-odd fill
460 bool fOppXor; // set if opposite operand had even-odd fill
caryclark@google.com570863f2013-09-16 15:55:01 +0000461#ifdef SK_DEBUG
caryclark@google.com07393ca2013-04-08 11:47:37 +0000462 int fID;
463#endif
464};
465
466#endif