blob: b6eab86a7fbfa39cdc668c60ea1cb46eb3a68c38 [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() {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000022#if defined(SK_DEBUG) || !FORCE_RELEASE
caryclark@google.com570863f2013-09-16 15:55:01 +000023 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
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000031 // FIXME: add some template or macro to avoid casting
32 SkOpAngle& angle(int index) {
33 const SkOpAngle& cAngle = (const_cast<const SkOpSegment*>(this))->angle(index);
34 return const_cast<SkOpAngle&>(cAngle);
35 }
36
caryclark@google.com07393ca2013-04-08 11:47:37 +000037 const SkPathOpsBounds& bounds() const {
38 return fBounds;
39 }
40
41 // OPTIMIZE
42 // when the edges are initially walked, they don't automatically get the prior and next
43 // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
44 // and would additionally remove the need for similar checks in condition edges. It would
45 // also allow intersection code to assume end of segment intersections (maybe?)
46 bool complete() const {
47 int count = fTs.count();
48 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
49 }
50
caryclark@google.comcffbcc32013-06-04 17:59:42 +000051 int count() const {
52 return fTs.count();
53 }
54
caryclark@google.com07393ca2013-04-08 11:47:37 +000055 bool done() const {
56 SkASSERT(fDoneSpans <= fTs.count());
57 return fDoneSpans == fTs.count();
58 }
59
60 bool done(int min) const {
61 return fTs[min].fDone;
62 }
63
64 bool done(const SkOpAngle* angle) const {
65 return done(SkMin32(angle->start(), angle->end()));
66 }
67
caryclark@google.com570863f2013-09-16 15:55:01 +000068 SkDPoint dPtAtT(double mid) const {
69 return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
70 }
71
caryclark@google.com07393ca2013-04-08 11:47:37 +000072 SkVector dxdy(int index) const {
reed@google.com277c3f82013-05-31 15:17:50 +000073 return (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs[index].fT);
caryclark@google.com07393ca2013-04-08 11:47:37 +000074 }
75
76 SkScalar dy(int index) const {
77 return dxdy(index).fY;
78 }
79
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000080 bool hasSmall() const {
81 return fSmall;
82 }
83
84 bool hasTiny() const {
85 return fTiny;
86 }
87
caryclark@google.com07393ca2013-04-08 11:47:37 +000088 bool intersected() const {
89 return fTs.count() > 0;
90 }
91
92 bool isCanceled(int tIndex) const {
93 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0;
94 }
95
96 bool isConnected(int startIndex, int endIndex) const {
97 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum != SK_MinS32;
98 }
99
100 bool isHorizontal() const {
101 return fBounds.fTop == fBounds.fBottom;
102 }
103
104 bool isVertical() const {
105 return fBounds.fLeft == fBounds.fRight;
106 }
107
108 bool isVertical(int start, int end) const {
reed@google.com277c3f82013-05-31 15:17:50 +0000109 return (*CurveIsVertical[SkPathOpsVerbToPoints(fVerb)])(fPts, start, end);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000110 }
111
112 bool operand() const {
113 return fOperand;
114 }
115
116 int oppSign(const SkOpAngle* angle) const {
117 SkASSERT(angle->segment() == this);
118 return oppSign(angle->start(), angle->end());
119 }
120
121 int oppSign(int startIndex, int endIndex) const {
122 int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[endIndex].fOppValue;
123#if DEBUG_WIND_BUMP
124 SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
125#endif
126 return result;
127 }
128
129 int oppSum(int tIndex) const {
130 return fTs[tIndex].fOppSum;
131 }
132
133 int oppSum(const SkOpAngle* angle) const {
134 int lesser = SkMin32(angle->start(), angle->end());
135 return fTs[lesser].fOppSum;
136 }
137
138 int oppValue(int tIndex) const {
139 return fTs[tIndex].fOppValue;
140 }
141
142 int oppValue(const SkOpAngle* angle) const {
143 int lesser = SkMin32(angle->start(), angle->end());
144 return fTs[lesser].fOppValue;
145 }
146
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000147#if DEBUG_VALIDATE
148 bool oppXor() const {
149 return fOppXor;
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000150 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000151#endif
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000152
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000153 SkPoint ptAtT(double mid) const {
154 return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
155 }
156
caryclark@google.com07393ca2013-04-08 11:47:37 +0000157 const SkPoint* pts() const {
158 return fPts;
159 }
160
161 void reset() {
162 init(NULL, (SkPath::Verb) -1, false, false);
163 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
164 fTs.reset();
165 }
166
167 void setOppXor(bool isOppXor) {
168 fOppXor = isOppXor;
169 }
170
caryclark@google.com07393ca2013-04-08 11:47:37 +0000171 void setUpWinding(int index, int endIndex, int* maxWinding, int* sumWinding) {
172 int deltaSum = spanSign(index, endIndex);
173 *maxWinding = *sumWinding;
174 *sumWinding -= deltaSum;
175 }
176
caryclark@google.com07393ca2013-04-08 11:47:37 +0000177 const SkOpSpan& span(int tIndex) const {
178 return fTs[tIndex];
179 }
180
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000181 const SkOpAngle* spanToAngle(int tStart, int tEnd) const {
182 SkASSERT(tStart != tEnd);
183 const SkOpSpan& span = fTs[tStart];
184 int index = tStart < tEnd ? span.fToAngleIndex : span.fFromAngleIndex;
185 return index >= 0 ? &angle(index) : NULL;
186 }
187
188 // FIXME: create some sort of macro or template that avoids casting
189 SkOpAngle* spanToAngle(int tStart, int tEnd) {
190 const SkOpAngle* cAngle = (const_cast<const SkOpSegment*>(this))->spanToAngle(tStart, tEnd);
191 return const_cast<SkOpAngle*>(cAngle);
192 }
193
caryclark@google.com07393ca2013-04-08 11:47:37 +0000194 int spanSign(const SkOpAngle* angle) const {
195 SkASSERT(angle->segment() == this);
196 return spanSign(angle->start(), angle->end());
197 }
198
199 int spanSign(int startIndex, int endIndex) const {
200 int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[endIndex].fWindValue;
201#if DEBUG_WIND_BUMP
202 SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
203#endif
204 return result;
205 }
206
caryclark@google.com07393ca2013-04-08 11:47:37 +0000207 double t(int tIndex) const {
208 return fTs[tIndex].fT;
209 }
210
211 double tAtMid(int start, int end, double mid) const {
212 return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
213 }
214
caryclark@google.com07393ca2013-04-08 11:47:37 +0000215 void updatePts(const SkPoint pts[]) {
216 fPts = pts;
217 }
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000218
caryclark@google.com07393ca2013-04-08 11:47:37 +0000219 SkPath::Verb verb() const {
220 return fVerb;
221 }
222
223 int windSum(int tIndex) const {
224 return fTs[tIndex].fWindSum;
225 }
226
227 int windValue(int tIndex) const {
228 return fTs[tIndex].fWindValue;
229 }
230
caryclark@google.com927b7022013-11-25 14:18:21 +0000231#if defined(SK_DEBUG) || DEBUG_WINDING
caryclark@google.com07393ca2013-04-08 11:47:37 +0000232 SkScalar xAtT(int index) const {
233 return xAtT(&fTs[index]);
234 }
caryclark@google.com927b7022013-11-25 14:18:21 +0000235#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000236
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000237#if DEBUG_VALIDATE
238 bool _xor() const { // FIXME: used only by SkOpAngle::debugValidateLoop()
239 return fXor;
240 }
241#endif
242
caryclark@google.com07393ca2013-04-08 11:47:37 +0000243 const SkPoint& xyAtT(const SkOpSpan* span) const {
244 return span->fPt;
245 }
246
caryclark@google.com07393ca2013-04-08 11:47:37 +0000247 const SkPoint& xyAtT(int index) const {
248 return xyAtT(&fTs[index]);
249 }
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000250
caryclark@google.com927b7022013-11-25 14:18:21 +0000251#if defined(SK_DEBUG) || DEBUG_WINDING
caryclark@google.com07393ca2013-04-08 11:47:37 +0000252 SkScalar yAtT(int index) const {
253 return yAtT(&fTs[index]);
254 }
caryclark@google.com927b7022013-11-25 14:18:21 +0000255#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000256
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000257 const SkOpAngle* activeAngle(int index, int* start, int* end, bool* done,
258 bool* sortable) const;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000259 SkPoint activeLeftTop(int* firstT) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000260 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000261 bool activeWinding(int index, int endIndex);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000262 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
263 void addCurveTo(int start, int end, SkPathWriter* path, bool active) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000264 void addEndSpan(int endIndex);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000265 void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
266 void addOtherT(int index, double otherT, int otherIndex);
267 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000268 void addSimpleAngle(int endIndex);
269 int addSelfT(const SkPoint& pt, double newT);
270 void addStartSpan(int endIndex);
commit-bot@chromium.org866f4e32013-11-21 17:04:29 +0000271 int addT(SkOpSegment* other, const SkPoint& pt, double newT);
caryclark@google.com570863f2013-09-16 15:55:01 +0000272 void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000273 void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000274 SkOpSegment* other);
275 const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
276 const SkPoint& pt);
277 bool alignSpan(int index, double thisT, const SkPoint& thisPt);
278 void alignSpanState(int start, int end);
279 const SkOpAngle& angle(int index) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000280 bool betweenTs(int lesser, double testT, int greater) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000281 bool calcAngles();
282 void checkDuplicates();
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000283 void checkEnds();
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000284 void checkMultiples();
285 void checkSmall();
caryclark@google.com570863f2013-09-16 15:55:01 +0000286 bool checkSmall(int index) const;
287 void checkTiny();
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000288 int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000289 bool containsPt(const SkPoint& , int index, int endIndex) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000290 int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool* hitSomething,
291 double mid, bool opp, bool current) const;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000292 bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, int oEnd,
293 int step, SkPoint* startPt, SkPoint* endPt, double* endT) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000294 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000295 bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000296 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
297 bool* unsortable);
298 SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000299 int findExactT(double t, const SkOpSegment* ) const;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000300 int findT(double t, const SkPoint& , const SkOpSegment* ) const;
301 SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool firstPass);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000302 void fixOtherTIndex();
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000303 void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000304 void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind,
caryclark@google.com570863f2013-09-16 15:55:01 +0000305 SkScalar hitOppDx);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000306 bool isMissing(double startT, const SkPoint& pt) const;
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000307 bool isTiny(const SkOpAngle* angle) const;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000308 bool joinCoincidence(SkOpSegment* other, double otherT, const SkPoint& otherPt, int step,
309 bool cancel);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000310 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
311 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
312 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding);
313 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding,
commit-bot@chromium.org866f4e32013-11-21 17:04:29 +0000314 const SkOpAngle* angle);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000315 void markDone(int index, int winding);
316 void markDoneBinary(int index);
317 void markDoneUnary(int index);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000318 bool nextCandidate(int* start, int* end) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000319 int nextSpan(int from, int step) const;
320 void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding,
321 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000322 void sortAngles();
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000323 bool subDivide(int start, int end, SkPoint edge[4]) const;
324 bool subDivide(int start, int end, SkDCubic* result) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000325 void undoneSpan(int* start, int* end);
326 int updateOppWindingReverse(const SkOpAngle* angle) const;
327 int updateWindingReverse(const SkOpAngle* angle) const;
328 static bool UseInnerWinding(int outerWinding, int innerWinding);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000329 static bool UseInnerWindingReverse(int outerWinding, int innerWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000330 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const;
331 int windSum(const SkOpAngle* angle) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000332// available for testing only
333#if DEBUG_VALIDATE
334 bool debugContains(const SkOpAngle* ) const;
335#endif
336#if defined(SK_DEBUG) || !FORCE_RELEASE
caryclark@google.com07393ca2013-04-08 11:47:37 +0000337 int debugID() const {
338 return fID;
339 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000340#else
341 int debugID() const {
342 return -1;
343 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000344#endif
caryclark@google.coma5e55922013-05-07 18:51:31 +0000345#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
caryclark@google.com07393ca2013-04-08 11:47:37 +0000346 void debugShowActiveSpans() const;
347#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000348#if DEBUG_CONCIDENT
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000349 void debugShowTs(const char* prefix) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000350#endif
351#if DEBUG_SHOW_WINDING
352 int debugShowWindingValues(int slotCount, int ofInterest) const;
353#endif
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000354 const SkTDArray<SkOpSpan>& debugSpans() const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000355 void debugValidate() const;
356 // available to testing only
357 void dumpAngles() const;
358 void dumpContour(int firstID, int lastID) const;
359 void dumpPts() const;
360 void dumpSpans() const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000361
362private:
caryclark@google.com570863f2013-09-16 15:55:01 +0000363 struct MissingSpan {
caryclark@google.com570863f2013-09-16 15:55:01 +0000364 double fT;
365 double fEndT;
366 SkOpSegment* fSegment;
367 SkOpSegment* fOther;
368 double fOtherT;
369 SkPoint fPt;
370 };
371
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000372 const SkOpAngle* activeAngleInner(int index, int* start, int* end, bool* done,
373 bool* sortable) const;
374 const SkOpAngle* activeAngleOther(int index, int* start, int* end, bool* done,
375 bool* sortable) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000376 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000377 int* sumMiWinding, int* sumSuWinding);
378 bool activeWinding(int index, int endIndex, int* sumWinding);
caryclark@google.com570863f2013-09-16 15:55:01 +0000379 void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
380 void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000381 int addSingletonAngleDown(int start, SkOpSegment** otherPtr);
382 int addSingletonAngleUp(int start, SkOpSegment** otherPtr);
383 SkOpAngle* addSingletonAngles(int start, int step);
caryclark@google.com570863f2013-09-16 15:55:01 +0000384 void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt,
385 const SkPoint& oPt);
caryclark@google.com570863f2013-09-16 15:55:01 +0000386 bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000387 void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
388 SkTArray<SkPoint, true>* outsideTs);
caryclark@google.com570863f2013-09-16 15:55:01 +0000389 void bumpCoincidentOther(const SkOpSpan& oTest, int* index,
390 SkTArray<SkPoint, true>* outsideTs);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000391 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000392 bool calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts);
393 void checkLinks(const SkOpSpan* ,
394 SkTArray<MissingSpan, true>* missingSpans) const;
395 static void CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
396 const SkOpSpan* oFirst, const SkOpSpan* oLast,
397 const SkOpSpan** missingPtr,
398 SkTArray<MissingSpan, true>* missingSpans);
399 int checkSetAngle(int tIndex) const;
400 void checkSmallCoincidence(const SkOpSpan& span, SkTArray<MissingSpan, true>* );
caryclark@google.com07393ca2013-04-08 11:47:37 +0000401 bool clockwise(int tStart, int tEnd) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000402 static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
403 SkOpAngle::IncludeType );
404 static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
405 SkOpAngle::IncludeType );
406 bool decrementSpan(SkOpSpan* span);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000407 int findEndSpan(int endIndex) const;
408 int findStartSpan(int startIndex) const;
409 int firstActive(int tIndex) const;
410 const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000411 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000412 bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000413 bool isSimple(int end) const;
414 bool isTiny(int index) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000415 const SkOpSpan& lastSpan(const SkOpSpan& thisSpan) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000416 void matchWindingValue(int tIndex, double t, bool borrowWind);
417 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
418 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000419 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding);
420 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000421 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding);
commit-bot@chromium.org866f4e32013-11-21 17:04:29 +0000422 SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000423 void markDoneBinary(int index, int winding, int oppWinding);
424 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding);
425 void markOneDone(const char* funName, int tIndex, int winding);
426 void markOneDoneBinary(const char* funName, int tIndex);
427 void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding);
428 void markOneDoneUnary(const char* funName, int tIndex);
caryclark@google.com570863f2013-09-16 15:55:01 +0000429 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding);
430 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding);
431 void markWinding(int index, int winding);
432 void markWinding(int index, int winding, int oppWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000433 bool monotonicInY(int tStart, int tEnd) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000434
435 bool multipleEnds() const {
436 return fTs[count() - 2].fT == 1;
437 }
438
439 bool multipleStarts() const {
440 return fTs[1].fT == 0;
441 }
442
caryclark@google.com07393ca2013-04-08 11:47:37 +0000443 bool multipleSpans(int end) const;
444 SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last);
caryclark@google.com570863f2013-09-16 15:55:01 +0000445 int nextExactSpan(int from, int step) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000446 bool serpentine(int tStart, int tEnd) const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000447 void setFromAngleIndex(int endIndex, int angleIndex);
448 void setToAngleIndex(int endIndex, int angleIndex);
caryclark@google.com570863f2013-09-16 15:55:01 +0000449 void setUpWindings(int index, int endIndex, int* sumMiWinding,
450 int* maxWinding, int* sumWinding);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000451 void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000452 static void TrackOutsidePair(SkTArray<SkPoint, true>* outsideTs, const SkPoint& endPt,
453 const SkPoint& startPt);
454 static void TrackOutside(SkTArray<SkPoint, true>* outsideTs, const SkPoint& startPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000455 int updateOppWinding(int index, int endIndex) const;
456 int updateOppWinding(const SkOpAngle* angle) const;
457 int updateWinding(int index, int endIndex) const;
458 int updateWinding(const SkOpAngle* angle) const;
caryclark@google.com570863f2013-09-16 15:55:01 +0000459 int updateWindingReverse(int index, int endIndex) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000460 SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
461 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
caryclark@google.com927b7022013-11-25 14:18:21 +0000462
463 SkScalar xAtT(const SkOpSpan* span) const {
464 return xyAtT(span).fX;
465 }
466
467 SkScalar yAtT(const SkOpSpan* span) const {
468 return xyAtT(span).fY;
469 }
470
caryclark@google.com07393ca2013-04-08 11:47:37 +0000471 void zeroSpan(SkOpSpan* span);
472
473#if DEBUG_SWAP_TOP
474 bool controlsContainedByEnds(int tStart, int tEnd) const;
475#endif
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000476 void debugAddAngle(int start, int end);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000477#if DEBUG_CONCIDENT
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000478 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
479#endif
480#if DEBUG_ANGLE
481 void debugCheckPointsEqualish(int tStart, int tEnd) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000482#endif
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000483#if DEBUG_SWAP_TOP
484 int debugInflections(int index, int endIndex) const;
485#endif
caryclark@google.com07393ca2013-04-08 11:47:37 +0000486#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
487 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding);
488 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding, int oppWinding);
489#endif
490#if DEBUG_WINDING
491 static char as_digit(int value) {
492 return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
493 }
494#endif
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000495 // available to testing only
496 void debugConstruct();
497 void debugConstructCubic(SkPoint shortQuad[4]);
498 void debugConstructLine(SkPoint shortQuad[2]);
499 void debugConstructQuad(SkPoint shortQuad[3]);
500 void debugReset();
caryclark@google.com570863f2013-09-16 15:55:01 +0000501 void dumpDPts() const;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000502 void dumpSpan(int index) const;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000503
504 const SkPoint* fPts;
505 SkPathOpsBounds fBounds;
caryclark@google.comd892bd82013-06-17 14:10:36 +0000506 // FIXME: can't convert to SkTArray because it uses insert
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000507 SkTDArray<SkOpSpan> fTs; // 2+ (always includes t=0 t=1) -- at least (number of spans) + 1
508// FIXME: replace both with bucket storage that allows direct immovable pointers to angles
509 SkTArray<SkOpAngle, true> fSingletonAngles; // 0 or 2 -- allocated for singletons
510 SkTArray<SkOpAngle, true> fAngles; // 0 or 2+ -- (number of non-zero spans) * 2
caryclark@google.com07393ca2013-04-08 11:47:37 +0000511 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
512 int fDoneSpans; // quick check that segment is finished
513 // OPTIMIZATION: force the following to be byte-sized
514 SkPath::Verb fVerb;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000515 bool fLoop; // set if cubic intersects itself
caryclark@google.com07393ca2013-04-08 11:47:37 +0000516 bool fOperand;
517 bool fXor; // set if original contour had even-odd fill
518 bool fOppXor; // set if opposite operand had even-odd fill
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000519 bool fSmall; // set if some span is small
520 bool fTiny; // set if some span is tiny
521#if defined(SK_DEBUG) || !FORCE_RELEASE
caryclark@google.com07393ca2013-04-08 11:47:37 +0000522 int fID;
523#endif
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000524
525 friend class PathOpsSegmentTester;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000526};
527
528#endif