blob: 1eaef69847fdde200bb176255d69c016f4e1da05 [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
commit-bot@chromium.org0bcb8ca2014-04-25 13:42:21 +000017#if defined(SK_DEBUG) || !FORCE_RELEASE
18#include "SkThread.h"
19#endif
20
caryclark@google.com07393ca2013-04-08 11:47:37 +000021class SkPathWriter;
22
23class SkOpSegment {
24public:
25 SkOpSegment() {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000026#if defined(SK_DEBUG) || !FORCE_RELEASE
commit-bot@chromium.org0bcb8ca2014-04-25 13:42:21 +000027 fID = sk_atomic_inc(&SkPathOpsDebug::gSegmentID);
caryclark@google.com07393ca2013-04-08 11:47:37 +000028#endif
29 }
30
31 bool operator<(const SkOpSegment& rh) const {
32 return fBounds.fTop < rh.fBounds.fTop;
33 }
34
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000035 // FIXME: add some template or macro to avoid casting
36 SkOpAngle& angle(int index) {
37 const SkOpAngle& cAngle = (const_cast<const SkOpSegment*>(this))->angle(index);
38 return const_cast<SkOpAngle&>(cAngle);
39 }
40
caryclark@google.com07393ca2013-04-08 11:47:37 +000041 const SkPathOpsBounds& bounds() const {
42 return fBounds;
43 }
44
45 // OPTIMIZE
46 // when the edges are initially walked, they don't automatically get the prior and next
47 // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
48 // and would additionally remove the need for similar checks in condition edges. It would
49 // also allow intersection code to assume end of segment intersections (maybe?)
50 bool complete() const {
51 int count = fTs.count();
52 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
53 }
54
caryclark@google.comcffbcc32013-06-04 17:59:42 +000055 int count() const {
56 return fTs.count();
57 }
58
caryclark@google.com07393ca2013-04-08 11:47:37 +000059 bool done() const {
60 SkASSERT(fDoneSpans <= fTs.count());
61 return fDoneSpans == fTs.count();
62 }
63
64 bool done(int min) const {
65 return fTs[min].fDone;
66 }
67
68 bool done(const SkOpAngle* angle) const {
69 return done(SkMin32(angle->start(), angle->end()));
70 }
71
caryclark@google.com570863f2013-09-16 15:55:01 +000072 SkDPoint dPtAtT(double mid) const {
73 return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
74 }
75
caryclark@google.com07393ca2013-04-08 11:47:37 +000076 SkVector dxdy(int index) const {
reed@google.com277c3f82013-05-31 15:17:50 +000077 return (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs[index].fT);
caryclark@google.com07393ca2013-04-08 11:47:37 +000078 }
79
80 SkScalar dy(int index) const {
81 return dxdy(index).fY;
82 }
83
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000084 bool hasSmall() const {
85 return fSmall;
86 }
87
88 bool hasTiny() const {
89 return fTiny;
90 }
91
caryclark@google.com07393ca2013-04-08 11:47:37 +000092 bool intersected() const {
93 return fTs.count() > 0;
94 }
95
96 bool isCanceled(int tIndex) const {
97 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0;
98 }
99
100 bool isConnected(int startIndex, int endIndex) const {
101 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum != SK_MinS32;
102 }
103
104 bool isHorizontal() const {
105 return fBounds.fTop == fBounds.fBottom;
106 }
107
108 bool isVertical() const {
109 return fBounds.fLeft == fBounds.fRight;
110 }
111
112 bool isVertical(int start, int end) const {
reed@google.com277c3f82013-05-31 15:17:50 +0000113 return (*CurveIsVertical[SkPathOpsVerbToPoints(fVerb)])(fPts, start, end);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000114 }
115
116 bool operand() const {
117 return fOperand;
118 }
119
120 int oppSign(const SkOpAngle* angle) const {
121 SkASSERT(angle->segment() == this);
122 return oppSign(angle->start(), angle->end());
123 }
124
125 int oppSign(int startIndex, int endIndex) const {
126 int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[endIndex].fOppValue;
127#if DEBUG_WIND_BUMP
128 SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
129#endif
130 return result;
131 }
132
133 int oppSum(int tIndex) const {
134 return fTs[tIndex].fOppSum;
135 }
136
137 int oppSum(const SkOpAngle* angle) const {
138 int lesser = SkMin32(angle->start(), angle->end());
139 return fTs[lesser].fOppSum;
140 }
141
142 int oppValue(int tIndex) const {
143 return fTs[tIndex].fOppValue;
144 }
145
146 int oppValue(const SkOpAngle* angle) const {
147 int lesser = SkMin32(angle->start(), angle->end());
148 return fTs[lesser].fOppValue;
149 }
150
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000151#if DEBUG_VALIDATE
152 bool oppXor() const {
153 return fOppXor;
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000154 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000155#endif
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000156
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000157 SkPoint ptAtT(double mid) const {
158 return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
159 }
160
caryclark@google.com07393ca2013-04-08 11:47:37 +0000161 const SkPoint* pts() const {
162 return fPts;
163 }
164
165 void reset() {
166 init(NULL, (SkPath::Verb) -1, false, false);
167 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
168 fTs.reset();
169 }
170
171 void setOppXor(bool isOppXor) {
172 fOppXor = isOppXor;
173 }
174
caryclark@google.com07393ca2013-04-08 11:47:37 +0000175 void setUpWinding(int index, int endIndex, int* maxWinding, int* sumWinding) {
176 int deltaSum = spanSign(index, endIndex);
177 *maxWinding = *sumWinding;
178 *sumWinding -= deltaSum;
179 }
180
caryclark@google.com07393ca2013-04-08 11:47:37 +0000181 const SkOpSpan& span(int tIndex) const {
182 return fTs[tIndex];
183 }
184
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000185 const SkOpAngle* spanToAngle(int tStart, int tEnd) const {
186 SkASSERT(tStart != tEnd);
187 const SkOpSpan& span = fTs[tStart];
188 int index = tStart < tEnd ? span.fToAngleIndex : span.fFromAngleIndex;
189 return index >= 0 ? &angle(index) : NULL;
190 }
191
192 // FIXME: create some sort of macro or template that avoids casting
193 SkOpAngle* spanToAngle(int tStart, int tEnd) {
194 const SkOpAngle* cAngle = (const_cast<const SkOpSegment*>(this))->spanToAngle(tStart, tEnd);
195 return const_cast<SkOpAngle*>(cAngle);
196 }
197
caryclark@google.com07393ca2013-04-08 11:47:37 +0000198 int spanSign(const SkOpAngle* angle) const {
199 SkASSERT(angle->segment() == this);
200 return spanSign(angle->start(), angle->end());
201 }
202
203 int spanSign(int startIndex, int endIndex) const {
204 int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[endIndex].fWindValue;
205#if DEBUG_WIND_BUMP
206 SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
207#endif
208 return result;
209 }
210
caryclark@google.com07393ca2013-04-08 11:47:37 +0000211 double t(int tIndex) const {
212 return fTs[tIndex].fT;
213 }
214
215 double tAtMid(int start, int end, double mid) const {
216 return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
217 }
218
caryclark@google.com07393ca2013-04-08 11:47:37 +0000219 void updatePts(const SkPoint pts[]) {
220 fPts = pts;
221 }
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000222
caryclark@google.com07393ca2013-04-08 11:47:37 +0000223 SkPath::Verb verb() const {
224 return fVerb;
225 }
226
227 int windSum(int tIndex) const {
228 return fTs[tIndex].fWindSum;
229 }
230
231 int windValue(int tIndex) const {
232 return fTs[tIndex].fWindValue;
233 }
234
caryclark@google.com927b7022013-11-25 14:18:21 +0000235#if defined(SK_DEBUG) || DEBUG_WINDING
caryclark@google.com07393ca2013-04-08 11:47:37 +0000236 SkScalar xAtT(int index) const {
237 return xAtT(&fTs[index]);
238 }
caryclark@google.com927b7022013-11-25 14:18:21 +0000239#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000240
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000241#if DEBUG_VALIDATE
242 bool _xor() const { // FIXME: used only by SkOpAngle::debugValidateLoop()
243 return fXor;
244 }
245#endif
246
caryclark@google.com07393ca2013-04-08 11:47:37 +0000247 const SkPoint& xyAtT(const SkOpSpan* span) const {
248 return span->fPt;
249 }
250
caryclark@google.com07393ca2013-04-08 11:47:37 +0000251 const SkPoint& xyAtT(int index) const {
252 return xyAtT(&fTs[index]);
253 }
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000254
caryclark@google.com927b7022013-11-25 14:18:21 +0000255#if defined(SK_DEBUG) || DEBUG_WINDING
caryclark@google.com07393ca2013-04-08 11:47:37 +0000256 SkScalar yAtT(int index) const {
257 return yAtT(&fTs[index]);
258 }
caryclark@google.com927b7022013-11-25 14:18:21 +0000259#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000260
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000261 const SkOpAngle* activeAngle(int index, int* start, int* end, bool* done,
262 bool* sortable) const;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000263 SkPoint activeLeftTop(int* firstT) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000264 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000265 bool activeWinding(int index, int endIndex);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000266 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
267 void addCurveTo(int start, int end, SkPathWriter* path, bool active) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000268 void addEndSpan(int endIndex);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000269 void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
270 void addOtherT(int index, double otherT, int otherIndex);
271 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000272 void addSimpleAngle(int endIndex);
273 int addSelfT(const SkPoint& pt, double newT);
274 void addStartSpan(int endIndex);
commit-bot@chromium.org866f4e32013-11-21 17:04:29 +0000275 int addT(SkOpSegment* other, const SkPoint& pt, double newT);
caryclark@google.com570863f2013-09-16 15:55:01 +0000276 void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000277 void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000278 SkOpSegment* other);
279 const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
280 const SkPoint& pt);
281 bool alignSpan(int index, double thisT, const SkPoint& thisPt);
282 void alignSpanState(int start, int end);
283 const SkOpAngle& angle(int index) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000284 bool betweenTs(int lesser, double testT, int greater) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000285 bool calcAngles();
286 void checkDuplicates();
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000287 void checkEnds();
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000288 void checkMultiples();
289 void checkSmall();
caryclark@google.com570863f2013-09-16 15:55:01 +0000290 bool checkSmall(int index) const;
291 void checkTiny();
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000292 int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000293 bool containsPt(const SkPoint& , int index, int endIndex) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000294 int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool* hitSomething,
295 double mid, bool opp, bool current) const;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000296 bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, int oEnd,
297 int step, SkPoint* startPt, SkPoint* endPt, double* endT) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000298 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000299 bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000300 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
301 bool* unsortable);
302 SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000303 int findExactT(double t, const SkOpSegment* ) const;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000304 int findT(double t, const SkPoint& , const SkOpSegment* ) const;
305 SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool firstPass);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000306 void fixOtherTIndex();
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000307 void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000308 void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind,
caryclark@google.com570863f2013-09-16 15:55:01 +0000309 SkScalar hitOppDx);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000310 bool isMissing(double startT, const SkPoint& pt) const;
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000311 bool isTiny(const SkOpAngle* angle) const;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000312 bool joinCoincidence(SkOpSegment* other, double otherT, const SkPoint& otherPt, int step,
313 bool cancel);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000314 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
315 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
316 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding);
317 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding,
commit-bot@chromium.org866f4e32013-11-21 17:04:29 +0000318 const SkOpAngle* angle);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000319 void markDone(int index, int winding);
320 void markDoneBinary(int index);
321 void markDoneUnary(int index);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000322 bool nextCandidate(int* start, int* end) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000323 int nextSpan(int from, int step) const;
324 void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding,
325 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000326 void sortAngles();
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000327 bool subDivide(int start, int end, SkPoint edge[4]) const;
328 bool subDivide(int start, int end, SkDCubic* result) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000329 void undoneSpan(int* start, int* end);
330 int updateOppWindingReverse(const SkOpAngle* angle) const;
331 int updateWindingReverse(const SkOpAngle* angle) const;
332 static bool UseInnerWinding(int outerWinding, int innerWinding);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000333 static bool UseInnerWindingReverse(int outerWinding, int innerWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000334 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const;
335 int windSum(const SkOpAngle* angle) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000336// available for testing only
337#if DEBUG_VALIDATE
338 bool debugContains(const SkOpAngle* ) const;
339#endif
340#if defined(SK_DEBUG) || !FORCE_RELEASE
caryclark@google.com07393ca2013-04-08 11:47:37 +0000341 int debugID() const {
342 return fID;
343 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000344#else
345 int debugID() const {
346 return -1;
347 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000348#endif
caryclark@google.coma5e55922013-05-07 18:51:31 +0000349#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
caryclark@google.com07393ca2013-04-08 11:47:37 +0000350 void debugShowActiveSpans() const;
351#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000352#if DEBUG_CONCIDENT
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000353 void debugShowTs(const char* prefix) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000354#endif
355#if DEBUG_SHOW_WINDING
356 int debugShowWindingValues(int slotCount, int ofInterest) const;
357#endif
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000358 const SkTDArray<SkOpSpan>& debugSpans() const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000359 void debugValidate() const;
360 // available to testing only
361 void dumpAngles() const;
362 void dumpContour(int firstID, int lastID) const;
363 void dumpPts() const;
364 void dumpSpans() const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000365
366private:
caryclark@google.com570863f2013-09-16 15:55:01 +0000367 struct MissingSpan {
caryclark@google.com570863f2013-09-16 15:55:01 +0000368 double fT;
369 double fEndT;
370 SkOpSegment* fSegment;
371 SkOpSegment* fOther;
372 double fOtherT;
373 SkPoint fPt;
374 };
375
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000376 const SkOpAngle* activeAngleInner(int index, int* start, int* end, bool* done,
377 bool* sortable) const;
378 const SkOpAngle* activeAngleOther(int index, int* start, int* end, bool* done,
379 bool* sortable) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000380 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000381 int* sumMiWinding, int* sumSuWinding);
382 bool activeWinding(int index, int endIndex, int* sumWinding);
caryclark@google.com570863f2013-09-16 15:55:01 +0000383 void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
384 void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000385 int addSingletonAngleDown(int start, SkOpSegment** otherPtr);
386 int addSingletonAngleUp(int start, SkOpSegment** otherPtr);
387 SkOpAngle* addSingletonAngles(int start, int step);
caryclark@google.com570863f2013-09-16 15:55:01 +0000388 void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt,
389 const SkPoint& oPt);
caryclark@google.com570863f2013-09-16 15:55:01 +0000390 bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000391 void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
392 SkTArray<SkPoint, true>* outsideTs);
caryclark@google.com570863f2013-09-16 15:55:01 +0000393 void bumpCoincidentOther(const SkOpSpan& oTest, int* index,
394 SkTArray<SkPoint, true>* outsideTs);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000395 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000396 bool calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts);
397 void checkLinks(const SkOpSpan* ,
398 SkTArray<MissingSpan, true>* missingSpans) const;
399 static void CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
400 const SkOpSpan* oFirst, const SkOpSpan* oLast,
401 const SkOpSpan** missingPtr,
402 SkTArray<MissingSpan, true>* missingSpans);
403 int checkSetAngle(int tIndex) const;
404 void checkSmallCoincidence(const SkOpSpan& span, SkTArray<MissingSpan, true>* );
caryclark@google.com07393ca2013-04-08 11:47:37 +0000405 bool clockwise(int tStart, int tEnd) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000406 static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
407 SkOpAngle::IncludeType );
408 static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
409 SkOpAngle::IncludeType );
410 bool decrementSpan(SkOpSpan* span);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000411 int findEndSpan(int endIndex) const;
412 int findStartSpan(int startIndex) const;
413 int firstActive(int tIndex) const;
414 const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000415 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000416 bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000417 bool isSimple(int end) const;
418 bool isTiny(int index) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000419 const SkOpSpan& lastSpan(const SkOpSpan& thisSpan) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000420 void matchWindingValue(int tIndex, double t, bool borrowWind);
421 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
422 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000423 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding);
424 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000425 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding);
commit-bot@chromium.org866f4e32013-11-21 17:04:29 +0000426 SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000427 void markDoneBinary(int index, int winding, int oppWinding);
428 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding);
429 void markOneDone(const char* funName, int tIndex, int winding);
430 void markOneDoneBinary(const char* funName, int tIndex);
431 void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding);
432 void markOneDoneUnary(const char* funName, int tIndex);
caryclark@google.com570863f2013-09-16 15:55:01 +0000433 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding);
434 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding);
435 void markWinding(int index, int winding);
436 void markWinding(int index, int winding, int oppWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000437 bool monotonicInY(int tStart, int tEnd) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000438
439 bool multipleEnds() const {
440 return fTs[count() - 2].fT == 1;
441 }
442
443 bool multipleStarts() const {
444 return fTs[1].fT == 0;
445 }
446
caryclark@google.com07393ca2013-04-08 11:47:37 +0000447 bool multipleSpans(int end) const;
448 SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last);
caryclark@google.com570863f2013-09-16 15:55:01 +0000449 int nextExactSpan(int from, int step) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000450 bool serpentine(int tStart, int tEnd) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000451 void setFromAngleIndex(int endIndex, int angleIndex);
452 void setToAngleIndex(int endIndex, int angleIndex);
caryclark@google.com570863f2013-09-16 15:55:01 +0000453 void setUpWindings(int index, int endIndex, int* sumMiWinding,
454 int* maxWinding, int* sumWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000455 void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000456 static void TrackOutsidePair(SkTArray<SkPoint, true>* outsideTs, const SkPoint& endPt,
457 const SkPoint& startPt);
458 static void TrackOutside(SkTArray<SkPoint, true>* outsideTs, const SkPoint& startPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000459 int updateOppWinding(int index, int endIndex) const;
460 int updateOppWinding(const SkOpAngle* angle) const;
461 int updateWinding(int index, int endIndex) const;
462 int updateWinding(const SkOpAngle* angle) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000463 int updateWindingReverse(int index, int endIndex) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000464 SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
465 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
caryclark@google.com927b7022013-11-25 14:18:21 +0000466
467 SkScalar xAtT(const SkOpSpan* span) const {
468 return xyAtT(span).fX;
469 }
470
471 SkScalar yAtT(const SkOpSpan* span) const {
472 return xyAtT(span).fY;
473 }
474
caryclark@google.com07393ca2013-04-08 11:47:37 +0000475 void zeroSpan(SkOpSpan* span);
476
477#if DEBUG_SWAP_TOP
478 bool controlsContainedByEnds(int tStart, int tEnd) const;
479#endif
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000480 void debugAddAngle(int start, int end);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000481#if DEBUG_CONCIDENT
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000482 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
483#endif
484#if DEBUG_ANGLE
485 void debugCheckPointsEqualish(int tStart, int tEnd) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000486#endif
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000487#if DEBUG_SWAP_TOP
488 int debugInflections(int index, int endIndex) const;
489#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000490#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
491 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding);
492 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding, int oppWinding);
493#endif
494#if DEBUG_WINDING
495 static char as_digit(int value) {
496 return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
497 }
498#endif
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000499 // available to testing only
500 void debugConstruct();
501 void debugConstructCubic(SkPoint shortQuad[4]);
502 void debugConstructLine(SkPoint shortQuad[2]);
503 void debugConstructQuad(SkPoint shortQuad[3]);
504 void debugReset();
caryclark@google.com570863f2013-09-16 15:55:01 +0000505 void dumpDPts() const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000506 void dumpSpan(int index) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000507
508 const SkPoint* fPts;
509 SkPathOpsBounds fBounds;
caryclark@google.comd892bd82013-06-17 14:10:36 +0000510 // FIXME: can't convert to SkTArray because it uses insert
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000511 SkTDArray<SkOpSpan> fTs; // 2+ (always includes t=0 t=1) -- at least (number of spans) + 1
512// FIXME: replace both with bucket storage that allows direct immovable pointers to angles
513 SkTArray<SkOpAngle, true> fSingletonAngles; // 0 or 2 -- allocated for singletons
514 SkTArray<SkOpAngle, true> fAngles; // 0 or 2+ -- (number of non-zero spans) * 2
caryclark@google.com07393ca2013-04-08 11:47:37 +0000515 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
516 int fDoneSpans; // quick check that segment is finished
517 // OPTIMIZATION: force the following to be byte-sized
518 SkPath::Verb fVerb;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000519 bool fLoop; // set if cubic intersects itself
caryclark@google.com07393ca2013-04-08 11:47:37 +0000520 bool fOperand;
521 bool fXor; // set if original contour had even-odd fill
522 bool fOppXor; // set if opposite operand had even-odd fill
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000523 bool fSmall; // set if some span is small
524 bool fTiny; // set if some span is tiny
525#if defined(SK_DEBUG) || !FORCE_RELEASE
caryclark@google.com07393ca2013-04-08 11:47:37 +0000526 int fID;
527#endif
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000528
529 friend class PathOpsSegmentTester;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000530};
531
532#endif