Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: src/pathops/SkOpSegment.cpp

Issue 131103009: update pathops to circle sort (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: disable old test that still fails on linux 32 release Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkOpSpan.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "SkIntersections.h" 7 #include "SkIntersections.h"
8 #include "SkOpSegment.h" 8 #include "SkOpSegment.h"
9 #include "SkPathWriter.h" 9 #include "SkPathWriter.h"
10 #include "SkTSort.h" 10 #include "SkTSort.h"
11 11
12 #define F (false) // discard the edge 12 #define F (false) // discard the edge
13 #define T (true) // keep the edge 13 #define T (true) // keep the edge
14 14
15 static const bool gUnaryActiveEdge[2][2] = { 15 static const bool gUnaryActiveEdge[2][2] = {
16 // from=0 from=1 16 // from=0 from=1
17 // to=0,1 to=0,1 17 // to=0,1 to=0,1
18 {F, T}, {T, F}, 18 {F, T}, {T, F},
19 }; 19 };
20 20
21 static const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = { 21 static const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = {
22 // miFrom=0 miFrom=1 22 // miFrom=0 miFrom=1
23 // miTo=0 miTo=1 miTo=0 miTo=1 23 // miTo=0 miTo=1 miTo=0 miTo=1
24 // suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1 24 // suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1
25 // suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 25 // suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1
26 {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}} , // mi - su 26 {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}} , // mi - su
27 {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}} , // mi & su 27 {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}} , // mi & su
28 {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}} , // mi | su 28 {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}} , // mi | su
29 {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}} , // mi ^ su 29 {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}} , // mi ^ su
30 }; 30 };
31 31
32 #undef F 32 #undef F
33 #undef T 33 #undef T
34 34
35 enum { 35 enum {
36 kOutsideTrackedTCount = 16, // FIXME: determine what this should be 36 kOutsideTrackedTCount = 16, // FIXME: determine what this should be
37 kMissingSpanCount = 4, // FIXME: determine what this should be 37 kMissingSpanCount = 4, // FIXME: determine what this should be
38 }; 38 };
39 39
40 // note that this follows the same logic flow as build angles 40 const SkOpAngle* SkOpSegment::activeAngle(int index, int* start, int* end, bool* done,
41 bool SkOpSegment::activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* a ngles) { 41 bool* sortable) const {
42 if (activeAngleInner(index, done, angles)) { 42 if (const SkOpAngle* result = activeAngleInner(index, start, end, done, sort able)) {
43 return true; 43 return result;
44 } 44 }
45 double referenceT = fTs[index].fT; 45 double referenceT = fTs[index].fT;
46 int lesser = index; 46 int lesser = index;
47 while (--lesser >= 0 47 while (--lesser >= 0
48 && (precisely_negative(referenceT - fTs[lesser].fT) || fTs[lesser].f Tiny)) { 48 && (precisely_negative(referenceT - fTs[lesser].fT) || fTs[lesser].f Tiny)) {
49 if (activeAngleOther(lesser, done, angles)) { 49 if (const SkOpAngle* result = activeAngleOther(lesser, start, end, done, sortable)) {
50 return true; 50 return result;
51 } 51 }
52 } 52 }
53 do { 53 do {
54 if (activeAngleOther(index, done, angles)) { 54 if (const SkOpAngle* result = activeAngleOther(index, start, end, done, sortable)) {
55 return true; 55 return result;
56 } 56 }
57 if (++index == fTs.count()) { 57 if (++index == fTs.count()) {
58 break; 58 break;
59 } 59 }
60 if (fTs[index - 1].fTiny) { 60 if (fTs[index - 1].fTiny) {
61 referenceT = fTs[index].fT; 61 referenceT = fTs[index].fT;
62 continue; 62 continue;
63 } 63 }
64 } while (precisely_negative(fTs[index].fT - referenceT)); 64 } while (precisely_negative(fTs[index].fT - referenceT));
65 return false; 65 return NULL;
66 } 66 }
67 67
68 bool SkOpSegment::activeAngleOther(int index, int* done, SkTArray<SkOpAngle, tru e>* angles) { 68 const SkOpAngle* SkOpSegment::activeAngleInner(int index, int* start, int* end, bool* done,
69 SkOpSpan* span = &fTs[index]; 69 bool* sortable) const {
70 SkOpSegment* other = span->fOther;
71 int oIndex = span->fOtherIndex;
72 return other->activeAngleInner(oIndex, done, angles);
73 }
74
75 bool SkOpSegment::activeAngleInner(int index, int* done, SkTArray<SkOpAngle, tru e>* angles) {
76 int next = nextExactSpan(index, 1); 70 int next = nextExactSpan(index, 1);
77 if (next > 0) { 71 if (next > 0) {
78 SkOpSpan& upSpan = fTs[index]; 72 const SkOpSpan& upSpan = fTs[index];
73 if (upSpan.fUnsortableStart) {
74 *sortable = false;
75 return NULL;
76 }
79 if (upSpan.fWindValue || upSpan.fOppValue) { 77 if (upSpan.fWindValue || upSpan.fOppValue) {
80 addAngle(angles, index, next); 78 if (*end < 0) {
81 if (upSpan.fDone || upSpan.fUnsortableEnd) { 79 *start = index;
82 (*done)++; 80 *end = next;
83 } else if (upSpan.fWindSum != SK_MinS32) {
84 return true;
85 } 81 }
86 } else if (!upSpan.fDone) { 82 if (!upSpan.fDone && !upSpan.fUnsortableEnd) {
87 upSpan.fDone = true; 83 if (upSpan.fWindSum != SK_MinS32) {
88 fDoneSpans++; 84 return spanToAngle(index, next);
85 }
86 *done = false;
87 }
88 } else {
89 SkASSERT(upSpan.fDone);
89 } 90 }
90 } 91 }
91 int prev = nextExactSpan(index, -1); 92 int prev = nextExactSpan(index, -1);
92 // edge leading into junction 93 // edge leading into junction
93 if (prev >= 0) { 94 if (prev >= 0) {
94 SkOpSpan& downSpan = fTs[prev]; 95 const SkOpSpan& downSpan = fTs[prev];
96 if (downSpan.fUnsortableEnd) {
97 *sortable = false;
98 return NULL;
99 }
95 if (downSpan.fWindValue || downSpan.fOppValue) { 100 if (downSpan.fWindValue || downSpan.fOppValue) {
96 addAngle(angles, index, prev); 101 if (*end < 0) {
97 if (downSpan.fDone) { 102 *start = index;
98 (*done)++; 103 *end = prev;
99 } else if (downSpan.fWindSum != SK_MinS32) {
100 return true;
101 } 104 }
102 } else if (!downSpan.fDone) { 105 if (!downSpan.fDone) {
103 downSpan.fDone = true; 106 if (downSpan.fWindSum != SK_MinS32) {
104 fDoneSpans++; 107 return spanToAngle(index, prev);
108 }
109 *done = false;
110 }
111 } else {
112 SkASSERT(downSpan.fDone);
105 } 113 }
106 } 114 }
107 return false; 115 return NULL;
116 }
117
118 const SkOpAngle* SkOpSegment::activeAngleOther(int index, int* start, int* end, bool* done,
119 bool* sortable) const {
120 const SkOpSpan* span = &fTs[index];
121 SkOpSegment* other = span->fOther;
122 int oIndex = span->fOtherIndex;
123 return other->activeAngleInner(oIndex, start, end, done, sortable);
108 } 124 }
109 125
110 SkPoint SkOpSegment::activeLeftTop(bool onlySortable, int* firstT) const { 126 SkPoint SkOpSegment::activeLeftTop(bool onlySortable, int* firstT) const {
111 SkASSERT(!done()); 127 SkASSERT(!done());
112 SkPoint topPt = {SK_ScalarMax, SK_ScalarMax}; 128 SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
113 int count = fTs.count(); 129 int count = fTs.count();
114 // see if either end is not done since we want smaller Y of the pair 130 // see if either end is not done since we want smaller Y of the pair
115 bool lastDone = true; 131 bool lastDone = true;
116 bool lastUnsortable = false; 132 bool lastUnsortable = false;
117 double lastT = -1; 133 double lastT = -1;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 } 168 }
153 return topPt; 169 return topPt;
154 } 170 }
155 171
156 bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask , SkPathOp op) { 172 bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask , SkPathOp op) {
157 int sumMiWinding = updateWinding(endIndex, index); 173 int sumMiWinding = updateWinding(endIndex, index);
158 int sumSuWinding = updateOppWinding(endIndex, index); 174 int sumSuWinding = updateOppWinding(endIndex, index);
159 if (fOperand) { 175 if (fOperand) {
160 SkTSwap<int>(sumMiWinding, sumSuWinding); 176 SkTSwap<int>(sumMiWinding, sumSuWinding);
161 } 177 }
162 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; 178 return activeOp(xorMiMask, xorSuMask, index, endIndex, op, &sumMiWinding, &s umSuWinding);
163 return activeOp(xorMiMask, xorSuMask, index, endIndex, op, &sumMiWinding, &s umSuWinding,
164 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
165 } 179 }
166 180
167 bool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, int index, int endIndex , SkPathOp op, 181 bool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, int index, int endIndex , SkPathOp op,
168 int* sumMiWinding, int* sumSuWinding, 182 int* sumMiWinding, int* sumSuWinding) {
169 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding ) { 183 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
170 setUpWindings(index, endIndex, sumMiWinding, sumSuWinding, 184 setUpWindings(index, endIndex, sumMiWinding, sumSuWinding,
171 maxWinding, sumWinding, oppMaxWinding, oppSumWinding); 185 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
172 bool miFrom; 186 bool miFrom;
173 bool miTo; 187 bool miTo;
174 bool suFrom; 188 bool suFrom;
175 bool suTo; 189 bool suTo;
176 if (operand()) { 190 if (operand()) {
177 miFrom = (*oppMaxWinding & xorMiMask) != 0; 191 miFrom = (oppMaxWinding & xorMiMask) != 0;
178 miTo = (*oppSumWinding & xorMiMask) != 0; 192 miTo = (oppSumWinding & xorMiMask) != 0;
179 suFrom = (*maxWinding & xorSuMask) != 0; 193 suFrom = (maxWinding & xorSuMask) != 0;
180 suTo = (*sumWinding & xorSuMask) != 0; 194 suTo = (sumWinding & xorSuMask) != 0;
181 } else { 195 } else {
182 miFrom = (*maxWinding & xorMiMask) != 0; 196 miFrom = (maxWinding & xorMiMask) != 0;
183 miTo = (*sumWinding & xorMiMask) != 0; 197 miTo = (sumWinding & xorMiMask) != 0;
184 suFrom = (*oppMaxWinding & xorSuMask) != 0; 198 suFrom = (oppMaxWinding & xorSuMask) != 0;
185 suTo = (*oppSumWinding & xorSuMask) != 0; 199 suTo = (oppSumWinding & xorSuMask) != 0;
186 } 200 }
187 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; 201 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
188 #if DEBUG_ACTIVE_OP 202 #if DEBUG_ACTIVE_OP
189 SkDebugf("%s op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", __FUNCT ION__, 203 SkDebugf("%s op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", __FUNCT ION__,
190 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); 204 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result);
191 #endif 205 #endif
192 return result; 206 return result;
193 } 207 }
194 208
195 bool SkOpSegment::activeWinding(int index, int endIndex) { 209 bool SkOpSegment::activeWinding(int index, int endIndex) {
196 int sumWinding = updateWinding(endIndex, index); 210 int sumWinding = updateWinding(endIndex, index);
197 int maxWinding; 211 return activeWinding(index, endIndex, &sumWinding);
198 return activeWinding(index, endIndex, &maxWinding, &sumWinding);
199 } 212 }
200 213
201 bool SkOpSegment::activeWinding(int index, int endIndex, int* maxWinding, int* s umWinding) { 214 bool SkOpSegment::activeWinding(int index, int endIndex, int* sumWinding) {
202 setUpWinding(index, endIndex, maxWinding, sumWinding); 215 int maxWinding;
203 bool from = *maxWinding != 0; 216 setUpWinding(index, endIndex, &maxWinding, sumWinding);
217 bool from = maxWinding != 0;
204 bool to = *sumWinding != 0; 218 bool to = *sumWinding != 0;
205 bool result = gUnaryActiveEdge[from][to]; 219 bool result = gUnaryActiveEdge[from][to];
206 return result; 220 return result;
207 } 221 }
208 222
209 void SkOpSegment::addAngle(SkTArray<SkOpAngle, true>* anglesPtr, int start, int end) const {
210 SkASSERT(start != end);
211 SkOpAngle& angle = anglesPtr->push_back();
212 angle.set(this, start, end);
213 }
214
215 void SkOpSegment::addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt , 223 void SkOpSegment::addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt ,
216 SkOpSegment* other) { 224 SkOpSegment* other) {
217 int tIndex = -1; 225 int tIndex = -1;
218 int tCount = fTs.count(); 226 int tCount = fTs.count();
219 int oIndex = -1; 227 int oIndex = -1;
220 int oCount = other->fTs.count(); 228 int oCount = other->fTs.count();
221 do { 229 do {
222 ++tIndex; 230 ++tIndex;
223 } while (startPt != fTs[tIndex].fPt && tIndex < tCount); 231 } while (startPt != fTs[tIndex].fPt && tIndex < tCount);
224 int tIndexStart = tIndex; 232 int tIndexStart = tIndex;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 void SkOpSegment::addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, 300 void SkOpSegment::addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt,
293 SkOpSegment* other) { 301 SkOpSegment* other) {
294 // walk this to startPt 302 // walk this to startPt
295 // walk other to startPt 303 // walk other to startPt
296 // if either is > 0, add a pointer to the other, copying adjacent winding 304 // if either is > 0, add a pointer to the other, copying adjacent winding
297 int tIndex = -1; 305 int tIndex = -1;
298 int oIndex = -1; 306 int oIndex = -1;
299 do { 307 do {
300 ++tIndex; 308 ++tIndex;
301 } while (startPt != fTs[tIndex].fPt); 309 } while (startPt != fTs[tIndex].fPt);
310 int ttIndex = tIndex;
311 bool checkOtherTMatch = false;
312 do {
313 const SkOpSpan& span = fTs[ttIndex];
314 if (startPt != span.fPt) {
315 break;
316 }
317 if (span.fOther == other && span.fPt == startPt) {
318 checkOtherTMatch = true;
319 break;
320 }
321 } while (++ttIndex < count());
302 do { 322 do {
303 ++oIndex; 323 ++oIndex;
304 } while (startPt != other->fTs[oIndex].fPt); 324 } while (startPt != other->fTs[oIndex].fPt);
305 if (tIndex > 0 || oIndex > 0 || fOperand != other->fOperand) { 325 bool skipAdd = false;
326 if (checkOtherTMatch) {
327 int ooIndex = oIndex;
328 do {
329 const SkOpSpan& oSpan = other->fTs[ooIndex];
330 if (startPt != oSpan.fPt) {
331 break;
332 }
333 if (oSpan.fT == fTs[ttIndex].fOtherT) {
334 skipAdd = true;
335 break;
336 }
337 } while (++ooIndex < other->count());
338 }
339 if ((tIndex > 0 || oIndex > 0 || fOperand != other->fOperand) && !skipAdd) {
306 addTPair(fTs[tIndex].fT, other, other->fTs[oIndex].fT, false, startPt); 340 addTPair(fTs[tIndex].fT, other, other->fTs[oIndex].fT, false, startPt);
307 } 341 }
308 SkPoint nextPt = startPt; 342 SkPoint nextPt = startPt;
309 do { 343 do {
310 const SkPoint* workPt; 344 const SkPoint* workPt;
311 do { 345 do {
312 workPt = &fTs[++tIndex].fPt; 346 workPt = &fTs[++tIndex].fPt;
313 } while (nextPt == *workPt); 347 } while (nextPt == *workPt);
314 do { 348 do {
315 workPt = &other->fTs[++oIndex].fPt; 349 workPt = &other->fTs[++oIndex].fPt;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 path->cubicTo(ePtr[1], ePtr[2], ePtr[3]); 405 path->cubicTo(ePtr[1], ePtr[2], ePtr[3]);
372 break; 406 break;
373 default: 407 default:
374 SkASSERT(0); 408 SkASSERT(0);
375 } 409 }
376 } 410 }
377 } 411 }
378 // return ePtr[SkPathOpsVerbToPoints(fVerb)]; 412 // return ePtr[SkPathOpsVerbToPoints(fVerb)];
379 } 413 }
380 414
415 void SkOpSegment::addEndSpan(int endIndex) {
416 int spanCount = fTs.count();
417 int angleIndex = fAngles.count();
418 int startIndex = endIndex - 1;
419 while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) {
420 ++startIndex;
421 SkASSERT(startIndex < spanCount - 1);
422 ++endIndex;
423 }
424 fAngles.push_back().set(this, spanCount - 1, startIndex);
425 #if DEBUG_ANGLE
426 fAngles.back().setID(angleIndex);
427 debugCheckPointsEqualish(endIndex, spanCount);
428 #endif
429 setFromAngleIndex(endIndex, angleIndex);
430 }
431
432 void SkOpSegment::setFromAngleIndex(int endIndex, int angleIndex) {
433 int spanCount = fTs.count();
434 do {
435 fTs[endIndex].fFromAngleIndex = angleIndex;
436 } while (++endIndex < spanCount);
437 }
438
381 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) { 439 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) {
382 init(pts, SkPath::kLine_Verb, operand, evenOdd); 440 init(pts, SkPath::kLine_Verb, operand, evenOdd);
383 fBounds.set(pts, 2); 441 fBounds.set(pts, 2);
384 } 442 }
385 443
386 // add 2 to edge or out of range values to get T extremes 444 // add 2 to edge or out of range values to get T extremes
387 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) { 445 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) {
388 SkOpSpan& span = fTs[index]; 446 SkOpSpan& span = fTs[index];
389 if (precisely_zero(otherT)) { 447 if (precisely_zero(otherT)) {
390 otherT = 0; 448 otherT = 0;
391 } else if (precisely_equal(otherT, 1)) { 449 } else if (precisely_equal(otherT, 1)) {
392 otherT = 1; 450 otherT = 1;
393 } 451 }
394 span.fOtherT = otherT; 452 span.fOtherT = otherT;
395 span.fOtherIndex = otherIndex; 453 span.fOtherIndex = otherIndex;
396 } 454 }
397 455
398 void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) { 456 void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) {
399 init(pts, SkPath::kQuad_Verb, operand, evenOdd); 457 init(pts, SkPath::kQuad_Verb, operand, evenOdd);
400 fBounds.setQuadBounds(pts); 458 fBounds.setQuadBounds(pts);
401 } 459 }
402 460
461 int SkOpSegment::addSingletonAngleDown(int endIndex, SkOpSegment** otherPtr) {
462 int startIndex = findEndSpan(endIndex);
463 SkASSERT(startIndex > 0);
464 int spanIndex = endIndex - 1;
465 fSingletonAngles.push_back().set(this, spanIndex, startIndex - 1);
466 setFromAngleIndex(startIndex, fAngles.count() + fSingletonAngles.count() - 1 );
467 SkOpSegment* other;
468 do {
469 other = fTs[spanIndex].fOther;
470 if (other->fTs[0].fWindValue) {
471 break;
472 }
473 --spanIndex;
474 SkASSERT(fTs[spanIndex].fT == 1);
475 } while (true);
476 int oEndIndex = other->findStartSpan(0);
477 SkASSERT(oEndIndex > 0);
478 int otherIndex = other->fSingletonAngles.count();
479 other->fSingletonAngles.push_back().set(other, 0, oEndIndex);
480 other->setToAngleIndex(oEndIndex, other->fAngles.count() + otherIndex);
481 *otherPtr = other;
482 return otherIndex;
483 }
484
485 int SkOpSegment::addSingletonAngleUp(int start, SkOpSegment** otherPtr) {
486 int endIndex = findStartSpan(start);
487 SkASSERT(endIndex > 0);
488 int thisIndex = fSingletonAngles.count();
489 fSingletonAngles.push_back().set(this, start, endIndex);
490 setToAngleIndex(endIndex, fAngles.count() + thisIndex);
491 int spanIndex = start;
492 SkOpSegment* other;
493 int oCount, oStartIndex;
494 do {
495 other = fTs[spanIndex].fOther;
496 oCount = other->count();
497 oStartIndex = other->findEndSpan(oCount);
498 SkASSERT(oStartIndex > 0);
499 if (other->fTs[oStartIndex - 1].fWindValue) {
500 break;
501 }
502 ++spanIndex;
503 SkASSERT(fTs[spanIndex].fT == 0);
504 } while (true);
505 int otherIndex = other->fSingletonAngles.count();
506 other->fSingletonAngles.push_back().set(other, oCount - 1, oStartIndex - 1);
507 other->setFromAngleIndex(oStartIndex, other->fAngles.count() + otherIndex);
508 *otherPtr = other;
509 return otherIndex;
510 }
511
512 SkOpAngle* SkOpSegment::addSingletonAngles(int start, int step) {
513 int thisIndex = fSingletonAngles.count();
514 SkOpSegment* other;
515 int otherIndex;
516 if (step > 0) {
517 otherIndex = addSingletonAngleUp(start, &other);
518 } else {
519 otherIndex = addSingletonAngleDown(start + 1, &other);
520 }
521 fSingletonAngles[thisIndex].insert(&other->fSingletonAngles[otherIndex]);
522 #if DEBUG_ANGLE
523 fSingletonAngles[thisIndex].setID(fAngles.count() + thisIndex);
524 other->fSingletonAngles[otherIndex].setID(other->fAngles.count() + otherInde x);
525 #endif
526 return &fSingletonAngles[thisIndex];
527 }
528
529 void SkOpSegment::addStartSpan(int endIndex) {
530 int angleIndex = fAngles.count();
531 int index = 0;
532 fAngles.push_back().set(this, index, endIndex);
533 #if DEBUG_ANGLE
534 fAngles.back().setID(angleIndex);
535 debugCheckPointsEqualish(index, endIndex);
536 #endif
537 setToAngleIndex(endIndex, angleIndex);
538 }
539
540 void SkOpSegment::setToAngleIndex(int endIndex, int angleIndex) {
541 int index = 0;
542 do {
543 fTs[index].fToAngleIndex = angleIndex;
544 } while (++index < endIndex);
545 }
546
403 // Defer all coincident edge processing until 547 // Defer all coincident edge processing until
404 // after normal intersections have been computed 548 // after normal intersections have been computed
405 549
406 // no need to be tricky; insert in normal T order 550 // no need to be tricky; insert in normal T order
407 // resolve overlapping ts when considering coincidence later 551 // resolve overlapping ts when considering coincidence later
408 552
409 // add non-coincident intersection. Resulting edges are sorted in T. 553 // add non-coincident intersection. Resulting edges are sorted in T.
410 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { 554 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) {
555 SkASSERT(this != other || fVerb == SkPath::kCubic_Verb);
556 #if 0 // this needs an even rougher association to be useful
557 SkASSERT(SkDPoint::RoughlyEqual(ptAtT(newT), pt));
558 #endif
411 if (precisely_zero(newT)) { 559 if (precisely_zero(newT)) {
412 newT = 0; 560 newT = 0;
413 } else if (precisely_equal(newT, 1)) { 561 } else if (precisely_equal(newT, 1)) {
414 newT = 1; 562 newT = 1;
415 } 563 }
416 // FIXME: in the pathological case where there is a ton of intercepts, 564 // FIXME: in the pathological case where there is a ton of intercepts,
417 // binary search? 565 // binary search?
418 int insertedAt = -1; 566 int insertedAt = -1;
419 size_t tCount = fTs.count(); 567 int tCount = fTs.count();
420 const SkPoint& firstPt = fPts[0]; 568 const SkPoint& firstPt = fPts[0];
421 const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)]; 569 const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)];
422 for (size_t index = 0; index < tCount; ++index) { 570 for (int index = 0; index < tCount; ++index) {
423 // OPTIMIZATION: if there are three or more identical Ts, then 571 // OPTIMIZATION: if there are three or more identical Ts, then
424 // the fourth and following could be further insertion-sorted so 572 // the fourth and following could be further insertion-sorted so
425 // that all the edges are clockwise or counterclockwise. 573 // that all the edges are clockwise or counterclockwise.
426 // This could later limit segment tests to the two adjacent 574 // This could later limit segment tests to the two adjacent
427 // neighbors, although it doesn't help with determining which 575 // neighbors, although it doesn't help with determining which
428 // circular direction to go in. 576 // circular direction to go in.
429 const SkOpSpan& span = fTs[index]; 577 const SkOpSpan& span = fTs[index];
430 if (newT < span.fT) { 578 if (newT < span.fT) {
431 insertedAt = index; 579 insertedAt = index;
432 break; 580 break;
(...skipping 17 matching lines...) Expand all
450 span = fTs.append(); 598 span = fTs.append();
451 } 599 }
452 span->fT = newT; 600 span->fT = newT;
453 span->fOther = other; 601 span->fOther = other;
454 span->fPt = pt; 602 span->fPt = pt;
455 #if 0 603 #if 0
456 // cubics, for instance, may not be exact enough to satisfy this check (e.g. , cubicOp69d) 604 // cubics, for instance, may not be exact enough to satisfy this check (e.g. , cubicOp69d)
457 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) 605 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX)
458 && approximately_equal(xyAtT(newT).fY, pt.fY)); 606 && approximately_equal(xyAtT(newT).fY, pt.fY));
459 #endif 607 #endif
608 span->fFromAngleIndex = -1;
609 span->fToAngleIndex = -1;
460 span->fWindSum = SK_MinS32; 610 span->fWindSum = SK_MinS32;
461 span->fOppSum = SK_MinS32; 611 span->fOppSum = SK_MinS32;
462 span->fWindValue = 1; 612 span->fWindValue = 1;
463 span->fOppValue = 0; 613 span->fOppValue = 0;
464 span->fSmall = false; 614 span->fChased = false;
465 span->fTiny = false;
466 span->fLoop = false;
467 if ((span->fDone = newT == 1)) { 615 if ((span->fDone = newT == 1)) {
468 ++fDoneSpans; 616 ++fDoneSpans;
469 } 617 }
618 span->fLoop = false;
619 span->fSmall = false;
620 span->fTiny = false;
470 span->fUnsortableStart = false; 621 span->fUnsortableStart = false;
471 span->fUnsortableEnd = false; 622 span->fUnsortableEnd = false;
472 int less = -1; 623 int less = -1;
473 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, span->fPt)) { 624 // find range of spans with nearly the same point as this one
474 if (span[less].fDone) { 625 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) {
475 break;
476 }
477 double tInterval = newT - span[less].fT;
478 if (precisely_negative(tInterval)) {
479 break;
480 }
481 if (fVerb == SkPath::kCubic_Verb) { 626 if (fVerb == SkPath::kCubic_Verb) {
627 double tInterval = newT - span[less].fT;
482 double tMid = newT - tInterval / 2; 628 double tMid = newT - tInterval / 2;
483 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); 629 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid);
484 if (!midPt.approximatelyEqual(xyAtT(span))) { 630 if (!midPt.approximatelyEqual(xyAtT(span))) {
485 break; 631 break;
486 } 632 }
487 } 633 }
488 span[less].fSmall = true;
489 bool tiny = span[less].fPt == span->fPt;
490 span[less].fTiny = tiny;
491 span[less].fDone = true;
492 if (approximately_negative(newT - span[less].fT) && tiny) {
493 if (approximately_greater_than_one(newT)) {
494 SkASSERT(&span[less] - fTs.begin() < fTs.count());
495 span[less].fUnsortableStart = true;
496 if (&span[less - 1] - fTs.begin() >= 0) {
497 span[less - 1].fUnsortableEnd = true;
498 }
499 }
500 if (approximately_less_than_zero(span[less].fT)) {
501 SkASSERT(&span[less + 1] - fTs.begin() < fTs.count());
502 SkASSERT(&span[less] - fTs.begin() >= 0);
503 span[less + 1].fUnsortableStart = true;
504 span[less].fUnsortableEnd = true;
505 }
506 }
507 ++fDoneSpans;
508 --less; 634 --less;
509 } 635 }
510 int more = 1; 636 int more = 1;
511 while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, sp an->fPt)) { 637 while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, pt )) {
512 if (span[more - 1].fDone) {
513 break;
514 }
515 double tEndInterval = span[more].fT - newT;
516 if (precisely_negative(tEndInterval)) {
517 if ((span->fTiny = span[more].fTiny)) {
518 span->fDone = true;
519 ++fDoneSpans;
520 }
521 break;
522 }
523 if (fVerb == SkPath::kCubic_Verb) { 638 if (fVerb == SkPath::kCubic_Verb) {
639 double tEndInterval = span[more].fT - newT;
524 double tMid = newT - tEndInterval / 2; 640 double tMid = newT - tEndInterval / 2;
525 SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid); 641 SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid);
526 if (!midEndPt.approximatelyEqual(xyAtT(span))) { 642 if (!midEndPt.approximatelyEqual(xyAtT(span))) {
527 break; 643 break;
528 } 644 }
529 } 645 }
530 span[more - 1].fSmall = true;
531 bool tiny = span[more].fPt == span->fPt;
532 span[more - 1].fTiny = tiny;
533 span[more - 1].fDone = true;
534 if (approximately_negative(span[more].fT - newT) && tiny) {
535 if (approximately_greater_than_one(span[more].fT)) {
536 span[more + 1].fUnsortableStart = true;
537 span[more].fUnsortableEnd = true;
538 }
539 if (approximately_less_than_zero(newT)) {
540 span[more].fUnsortableStart = true;
541 span[more - 1].fUnsortableEnd = true;
542 }
543 }
544 ++fDoneSpans;
545 ++more; 646 ++more;
546 } 647 }
648 ++less;
649 --more;
650 while (more - 1 > less && span[more].fPt == span[more - 1].fPt
651 && span[more].fT == span[more - 1].fT) {
652 --more;
653 }
654 if (less == more) {
655 return insertedAt;
656 }
657 if (precisely_negative(span[more].fT - span[less].fT)) {
658 return insertedAt;
659 }
660 // if the total range of t values is big enough, mark all tiny
661 bool tiny = span[less].fPt == span[more].fPt;
662 int index = less;
663 do {
664 fSmall = span[index].fSmall = true;
665 fTiny |= span[index].fTiny = tiny;
666 if (!span[index].fDone) {
667 span[index].fDone = true;
668 ++fDoneSpans;
669 }
670 } while (++index < more);
547 return insertedAt; 671 return insertedAt;
548 } 672 }
549 673
550 // set spans from start to end to decrement by one 674 // set spans from start to end to decrement by one
551 // note this walks other backwards 675 // note this walks other backwards
552 // FIXME: there's probably an edge case that can be constructed where 676 // FIXME: there's probably an edge case that can be constructed where
553 // two span in one segment are separated by float epsilon on one span but 677 // two span in one segment are separated by float epsilon on one span but
554 // not the other, if one segment is very small. For this 678 // not the other, if one segment is very small. For this
555 // case the counts asserted below may or may not be enough to separate the 679 // case the counts asserted below may or may not be enough to separate the
556 // spans. Even if the counts work out, what if the spans aren't correctly 680 // spans. Even if the counts work out, what if the spans aren't correctly
557 // sorted? It feels better in such a case to match the span's other span 681 // sorted? It feels better in such a case to match the span's other span
558 // pointer since both coincident segments must contain the same spans. 682 // pointer since both coincident segments must contain the same spans.
559 // FIXME? It seems that decrementing by one will fail for complex paths that 683 // FIXME? It seems that decrementing by one will fail for complex paths that
560 // have three or more coincident edges. Shouldn't this subtract the difference 684 // have three or more coincident edges. Shouldn't this subtract the difference
561 // between the winding values? 685 // between the winding values?
562 /* |--> |--> 686 /* |--> |-->
563 this 0>>>>1>>>>2>>>>3>>>4 0>>>>1>>>>2>>>>3>>>4 0>>>>1>>>>2>>>>3>>> 4 687 this 0>>>>1>>>>2>>>>3>>>4 0>>>>1>>>>2>>>>3>>>4 0>>>>1>>>>2>>>>3>>> 4
564 other 2<<<<1<<<<0 2<<<<1<<<<0 2<<<<1<<<<0 688 other 2<<<<1<<<<0 2<<<<1<<<<0 2<<<<1<<<<0
565 ^ ^ <--| <--| 689 ^ ^ <--| <--|
566 startPt endPt test/oTest first pos test/oTest final po s 690 startPt endPt test/oTest first pos test/oTest final po s
567 */ 691 */
568 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS egment* other) { 692 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS egment* other) {
569 bool binary = fOperand != other->fOperand; 693 bool binary = fOperand != other->fOperand;
570 int index = 0; 694 int index = 0;
571 while (startPt != fTs[index].fPt) { 695 while (startPt != fTs[index].fPt) {
572 SkASSERT(index < fTs.count()); 696 SkASSERT(index < fTs.count());
573 ++index; 697 ++index;
574 } 698 }
575 while (index > 0 && fTs[index].fT == fTs[index - 1].fT) { 699 while (index > 0 && precisely_equal(fTs[index].fT, fTs[index - 1].fT)) {
576 --index; 700 --index;
577 } 701 }
578 int oIndex = other->fTs.count(); 702 int oIndex = other->fTs.count();
579 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match 703 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match
580 SkASSERT(oIndex > 0); 704 SkASSERT(oIndex > 0);
581 } 705 }
582 double oStartT = other->fTs[oIndex].fT; 706 double oStartT = other->fTs[oIndex].fT;
583 // look for first point beyond match 707 // look for first point beyond match
584 while (startPt == other->fTs[--oIndex].fPt || oStartT == other->fTs[oIndex]. fT) { 708 while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other ->fTs[oIndex].fT)) {
585 SkASSERT(oIndex > 0); 709 SkASSERT(oIndex > 0);
586 } 710 }
587 SkOpSpan* test = &fTs[index]; 711 SkOpSpan* test = &fTs[index];
588 SkOpSpan* oTest = &other->fTs[oIndex]; 712 SkOpSpan* oTest = &other->fTs[oIndex];
589 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; 713 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts;
590 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 714 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts;
591 do { 715 do {
592 SkASSERT(test->fT < 1); 716 SkASSERT(test->fT < 1);
593 SkASSERT(oTest->fT < 1); 717 SkASSERT(oTest->fT < 1);
594 bool decrement = test->fWindValue && oTest->fWindValue; 718 bool decrement = test->fWindValue && oTest->fWindValue;
595 bool track = test->fWindValue || oTest->fWindValue; 719 bool track = test->fWindValue || oTest->fWindValue;
596 bool bigger = test->fWindValue >= oTest->fWindValue; 720 bool bigger = test->fWindValue >= oTest->fWindValue;
597 const SkPoint& testPt = test->fPt; 721 const SkPoint& testPt = test->fPt;
598 double testT = test->fT; 722 double testT = test->fT;
599 const SkPoint& oTestPt = oTest->fPt; 723 const SkPoint& oTestPt = oTest->fPt;
600 double oTestT = oTest->fT; 724 double oTestT = oTest->fT;
601 do { 725 do {
602 if (decrement) { 726 if (decrement) {
603 if (binary && bigger) { 727 if (binary && bigger) {
604 test->fOppValue--; 728 test->fOppValue--;
605 } else { 729 } else {
606 decrementSpan(test); 730 decrementSpan(test);
607 } 731 }
608 } else if (track) { 732 } else if (track) {
609 TrackOutsidePair(&outsidePts, testPt, oTestPt); 733 TrackOutsidePair(&outsidePts, testPt, oTestPt);
610 } 734 }
611 SkASSERT(index < fTs.count() - 1); 735 SkASSERT(index < fTs.count() - 1);
612 test = &fTs[++index]; 736 test = &fTs[++index];
613 } while (testPt == test->fPt || testT == test->fT); 737 } while (testPt == test->fPt || precisely_equal(testT, test->fT));
614 SkDEBUGCODE(int originalWindValue = oTest->fWindValue); 738 SkDEBUGCODE(int originalWindValue = oTest->fWindValue);
615 do { 739 do {
616 SkASSERT(oTest->fT < 1); 740 SkASSERT(oTest->fT < 1);
617 SkASSERT(originalWindValue == oTest->fWindValue); 741 SkASSERT(originalWindValue == oTest->fWindValue);
618 if (decrement) { 742 if (decrement) {
619 if (binary && !bigger) { 743 if (binary && !bigger) {
620 oTest->fOppValue--; 744 oTest->fOppValue--;
621 } else { 745 } else {
622 other->decrementSpan(oTest); 746 other->decrementSpan(oTest);
623 } 747 }
624 } else if (track) { 748 } else if (track) {
625 TrackOutsidePair(&oOutsidePts, oTestPt, testPt); 749 TrackOutsidePair(&oOutsidePts, oTestPt, testPt);
626 } 750 }
627 if (!oIndex) { 751 if (!oIndex) {
628 break; 752 break;
629 } 753 }
630 oTest = &other->fTs[--oIndex]; 754 oTest = &other->fTs[--oIndex];
631 } while (oTestPt == oTest->fPt || oTestT == oTest->fT); 755 } while (oTestPt == oTest->fPt || precisely_equal(oTestT, oTest->fT));
632 } while (endPt != test->fPt && test->fT < 1); 756 } while (endPt != test->fPt && test->fT < 1);
633 // FIXME: determine if canceled edges need outside ts added 757 // FIXME: determine if canceled edges need outside ts added
634 int outCount = outsidePts.count(); 758 int outCount = outsidePts.count();
635 if (!done() && outCount) { 759 if (!done() && outCount) {
636 addCancelOutsides(outsidePts[0], outsidePts[1], other); 760 addCancelOutsides(outsidePts[0], outsidePts[1], other);
637 if (outCount > 2) { 761 if (outCount > 2) {
638 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other); 762 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other);
639 } 763 }
640 } 764 }
641 if (!other->done() && oOutsidePts.count()) { 765 if (!other->done() && oOutsidePts.count()) {
642 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this); 766 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this);
643 } 767 }
644 } 768 }
645 769
646 int SkOpSegment::addSelfT(SkOpSegment* other, const SkPoint& pt, double newT) { 770 int SkOpSegment::addSelfT(const SkPoint& pt, double newT) {
647 // if the tail nearly intersects itself but not quite, the caller records th is separately 771 // if the tail nearly intersects itself but not quite, the caller records th is separately
648 int result = addT(other, pt, newT); 772 int result = addT(this, pt, newT);
649 SkOpSpan* span = &fTs[result]; 773 SkOpSpan* span = &fTs[result];
650 span->fLoop = true; 774 fLoop = span->fLoop = true;
651 return result; 775 return result;
652 } 776 }
653 777
778 void SkOpSegment::addSimpleAngle(int index) {
779 if (index == 0) {
780 SkASSERT(!fTs[index].fTiny && fTs[index + 1].fT > 0);
781 addStartSpan(1);
782 } else {
783 SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1);
784 addEndSpan(index);
785 }
786 SkOpSpan& span = fTs[index];
787 SkOpSegment* other = span.fOther;
788 SkOpSpan& oSpan = other->fTs[span.fOtherIndex];
789 SkOpAngle* angle, * oAngle;
790 if (index == 0) {
791 SkASSERT(span.fOtherIndex - 1 >= 0);
792 SkASSERT(span.fOtherT == 1);
793 SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span.fOtherIndex - 1]);
794 SkASSERT(!oPrior.fTiny && oPrior.fT < 1);
795 other->addEndSpan(span.fOtherIndex);
796 angle = &this->angle(span.fToAngleIndex);
797 oAngle = &other->angle(oSpan.fFromAngleIndex);
798 } else {
799 SkASSERT(span.fOtherIndex + 1 < other->count());
800 SkASSERT(span.fOtherT == 0);
801 SkASSERT(!oSpan.fTiny && (other->fTs[span.fOtherIndex + 1].fT > 0
802 || (other->fTs[span.fOtherIndex + 1].fFromAngleIndex < 0
803 && other->fTs[span.fOtherIndex + 1].fToAngleIndex < 0)));
804 int oIndex = 1;
805 do {
806 const SkOpSpan& osSpan = other->span(oIndex);
807 if (osSpan.fFromAngleIndex >= 0 || osSpan.fT > 0) {
808 break;
809 }
810 ++oIndex;
811 SkASSERT(oIndex < other->count());
812 } while (true);
813 other->addStartSpan(oIndex);
814 angle = &this->angle(span.fFromAngleIndex);
815 oAngle = &other->angle(oSpan.fToAngleIndex);
816 }
817 angle->insert(oAngle);
818 }
819
820 bool SkOpSegment::alignSpan(int index, double thisT, const SkPoint& thisPt) {
821 bool aligned = false;
822 SkOpSpan* span = &fTs[index];
823 SkOpSegment* other = span->fOther;
824 int oIndex = span->fOtherIndex;
825 SkOpSpan* oSpan = &other->fTs[oIndex];
826 if (span->fT != thisT) {
827 span->fT = thisT;
828 oSpan->fOtherT = thisT;
829 aligned = true;
830 }
831 if (span->fPt != thisPt) {
832 span->fPt = thisPt;
833 oSpan->fPt = thisPt;
834 aligned = true;
835 }
836 double oT = oSpan->fT;
837 if (oT == 0 || oT == 1) {
838 return aligned;
839 }
840 int oStart = other->nextSpan(oIndex, -1) + 1;
841 int oEnd = other->nextSpan(oIndex, 1);
842 oSpan = &other->fTs[oStart];
843 oT = oSpan->fT;
844 bool oAligned = false;
845 if (oSpan->fPt != thisPt) {
846 oAligned |= other->alignSpan(oStart, oT, thisPt);
847 }
848 int otherIndex = oStart;
849 while (++otherIndex < oEnd) {
850 SkOpSpan* oNextSpan = &other->fTs[otherIndex];
851 if (oNextSpan->fT != oT || oNextSpan->fPt != thisPt) {
852 oAligned |= other->alignSpan(otherIndex, oT, thisPt);
853 }
854 }
855 if (oAligned) {
856 other->alignSpanState(oStart, oEnd);
857 }
858 return aligned;
859 }
860
861 void SkOpSegment::alignSpanState(int start, int end) {
862 SkOpSpan* lastSpan = &fTs[--end];
863 bool allSmall = lastSpan->fSmall;
864 bool allTiny = lastSpan->fTiny;
865 bool allDone = lastSpan->fDone;
866 SkDEBUGCODE(int winding = lastSpan->fWindValue);
867 SkDEBUGCODE(int oppWinding = lastSpan->fOppValue);
868 int index = start;
869 while (index < end) {
870 SkOpSpan* span = &fTs[index];
871 span->fSmall = allSmall;
872 span->fTiny = allTiny;
873 if (span->fDone != allDone) {
874 span->fDone = allDone;
875 fDoneSpans += allDone ? 1 : -1;
876 }
877 SkASSERT(span->fWindValue == winding);
878 SkASSERT(span->fOppValue == oppWinding);
879 ++index;
880 }
881 }
882
654 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in dexPtr, 883 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in dexPtr,
655 SkTArray<SkPoint, true>* outsideTs) { 884 SkTArray<SkPoint, true>* outsideTs) {
656 int index = *indexPtr; 885 int index = *indexPtr;
657 int oWindValue = oTest.fWindValue; 886 int oWindValue = oTest.fWindValue;
658 int oOppValue = oTest.fOppValue; 887 int oOppValue = oTest.fOppValue;
659 if (binary) { 888 if (binary) {
660 SkTSwap<int>(oWindValue, oOppValue); 889 SkTSwap<int>(oWindValue, oOppValue);
661 } 890 }
662 SkOpSpan* const test = &fTs[index]; 891 SkOpSpan* const test = &fTs[index];
663 SkOpSpan* end = test; 892 SkOpSpan* end = test;
664 const SkPoint& oStartPt = oTest.fPt; 893 const SkPoint& oStartPt = oTest.fPt;
665 do { 894 do {
666 if (bumpSpan(end, oWindValue, oOppValue)) { 895 if (bumpSpan(end, oWindValue, oOppValue)) {
667 TrackOutside(outsideTs, oStartPt); 896 TrackOutside(outsideTs, oStartPt);
668 } 897 }
669 end = &fTs[++index]; 898 end = &fTs[++index];
670 } while ((end->fPt == test->fPt || end->fT == test->fT) && end->fT < 1); 899 } while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && en d->fT < 1);
671 *indexPtr = index; 900 *indexPtr = index;
672 } 901 }
673 902
674 // because of the order in which coincidences are resolved, this and other 903 // because of the order in which coincidences are resolved, this and other
675 // may not have the same intermediate points. Compute the corresponding 904 // may not have the same intermediate points. Compute the corresponding
676 // intermediate T values (using this as the master, other as the follower) 905 // intermediate T values (using this as the master, other as the follower)
677 // and walk other conditionally -- hoping that it catches up in the end 906 // and walk other conditionally -- hoping that it catches up in the end
678 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, 907 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr,
679 SkTArray<SkPoint, true>* oOutsidePts) { 908 SkTArray<SkPoint, true>* oOutsidePts) {
680 int oIndex = *oIndexPtr; 909 int oIndex = *oIndexPtr;
681 SkOpSpan* const oTest = &fTs[oIndex]; 910 SkOpSpan* const oTest = &fTs[oIndex];
682 SkOpSpan* oEnd = oTest; 911 SkOpSpan* oEnd = oTest;
683 const SkPoint& startPt = test.fPt;
684 const SkPoint& oStartPt = oTest->fPt; 912 const SkPoint& oStartPt = oTest->fPt;
685 double oStartT = oTest->fT; 913 double oStartT = oTest->fT;
686 if (oStartPt == oEnd->fPt || oStartT == oEnd->fT) { 914 #if 0 // FIXME : figure out what disabling this breaks
915 const SkPoint& startPt = test.fPt;
916 // this is always true since oEnd == oTest && oStartPt == oTest->fPt -- find proper condition
917 if (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) {
687 TrackOutside(oOutsidePts, startPt); 918 TrackOutside(oOutsidePts, startPt);
688 } 919 }
689 while (oStartPt == oEnd->fPt || oStartT == oEnd->fT) { 920 #endif
921 while (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) {
690 zeroSpan(oEnd); 922 zeroSpan(oEnd);
691 oEnd = &fTs[++oIndex]; 923 oEnd = &fTs[++oIndex];
692 } 924 }
693 *oIndexPtr = oIndex; 925 *oIndexPtr = oIndex;
694 } 926 }
695 927
696 // FIXME: need to test this case: 928 // FIXME: need to test this case:
697 // contourA has two segments that are coincident 929 // contourA has two segments that are coincident
698 // contourB has two segments that are coincident in the same place 930 // contourB has two segments that are coincident in the same place
699 // each ends up with +2/0 pairs for winding count 931 // each ends up with +2/0 pairs for winding count
700 // since logic below doesn't transfer count (only increments/decrements) can thi s be 932 // since logic below doesn't transfer count (only increments/decrements) can thi s be
701 // resolved to +4/0 ? 933 // resolved to +4/0 ?
702 934
703 // set spans from start to end to increment the greater by one and decrement 935 // set spans from start to end to increment the greater by one and decrement
704 // the lesser 936 // the lesser
705 void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d ouble endT, 937 void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d ouble endT,
706 SkOpSegment* other) { 938 SkOpSegment* other) {
707 bool binary = fOperand != other->fOperand; 939 bool binary = fOperand != other->fOperand;
708 int index = 0; 940 int index = 0;
709 while (startPt != fTs[index].fPt) { 941 while (startPt != fTs[index].fPt) {
710 SkASSERT(index < fTs.count()); 942 SkASSERT(index < fTs.count());
711 ++index; 943 ++index;
712 } 944 }
713 double startT = fTs[index].fT; 945 double startT = fTs[index].fT;
714 while (index > 0 && fTs[index - 1].fT == startT) { 946 while (index > 0 && precisely_equal(fTs[index - 1].fT, startT)) {
715 --index; 947 --index;
716 } 948 }
717 int oIndex = 0; 949 int oIndex = 0;
718 while (startPt != other->fTs[oIndex].fPt) { 950 while (startPt != other->fTs[oIndex].fPt) {
719 SkASSERT(oIndex < other->fTs.count()); 951 SkASSERT(oIndex < other->fTs.count());
720 ++oIndex; 952 ++oIndex;
721 } 953 }
722 double oStartT = other->fTs[oIndex].fT; 954 double oStartT = other->fTs[oIndex].fT;
723 while (oIndex > 0 && other->fTs[oIndex - 1].fT == oStartT) { 955 while (oIndex > 0 && precisely_equal(other->fTs[oIndex - 1].fT, oStartT)) {
724 --oIndex; 956 --oIndex;
725 } 957 }
726 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; 958 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts;
727 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 959 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts;
728 SkOpSpan* test = &fTs[index]; 960 SkOpSpan* test = &fTs[index];
729 const SkPoint* testPt = &test->fPt; 961 const SkPoint* testPt = &test->fPt;
730 double testT = test->fT; 962 double testT = test->fT;
731 SkOpSpan* oTest = &other->fTs[oIndex]; 963 SkOpSpan* oTest = &other->fTs[oIndex];
732 const SkPoint* oTestPt = &oTest->fPt; 964 const SkPoint* oTestPt = &oTest->fPt;
733 SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 965 SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
734 do { 966 do {
735 SkASSERT(test->fT < 1); 967 SkASSERT(test->fT < 1);
736 SkASSERT(oTest->fT < 1); 968 SkASSERT(oTest->fT < 1);
737 #if 0 969
738 if (test->fDone || oTest->fDone) { 970 // consolidate the winding count even if done
739 #else // consolidate the winding count even if done
740 if ((test->fWindValue == 0 && test->fOppValue == 0) 971 if ((test->fWindValue == 0 && test->fOppValue == 0)
741 || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) { 972 || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) {
742 #endif
743 SkDEBUGCODE(int firstWind = test->fWindValue); 973 SkDEBUGCODE(int firstWind = test->fWindValue);
744 SkDEBUGCODE(int firstOpp = test->fOppValue); 974 SkDEBUGCODE(int firstOpp = test->fOppValue);
745 do { 975 do {
746 SkASSERT(firstWind == fTs[index].fWindValue); 976 SkASSERT(firstWind == fTs[index].fWindValue);
747 SkASSERT(firstOpp == fTs[index].fOppValue); 977 SkASSERT(firstOpp == fTs[index].fOppValue);
748 ++index; 978 ++index;
749 SkASSERT(index < fTs.count()); 979 SkASSERT(index < fTs.count());
750 } while (*testPt == fTs[index].fPt); 980 } while (*testPt == fTs[index].fPt);
751 SkDEBUGCODE(firstWind = oTest->fWindValue); 981 SkDEBUGCODE(firstWind = oTest->fWindValue);
752 SkDEBUGCODE(firstOpp = oTest->fOppValue); 982 SkDEBUGCODE(firstOpp = oTest->fOppValue);
753 do { 983 do {
754 SkASSERT(firstWind == other->fTs[oIndex].fWindValue); 984 SkASSERT(firstWind == other->fTs[oIndex].fWindValue);
755 SkASSERT(firstOpp == other->fTs[oIndex].fOppValue); 985 SkASSERT(firstOpp == other->fTs[oIndex].fOppValue);
756 ++oIndex; 986 ++oIndex;
757 SkASSERT(oIndex < other->fTs.count()); 987 SkASSERT(oIndex < other->fTs.count());
758 } while (*oTestPt == other->fTs[oIndex].fPt); 988 } while (*oTestPt == other->fTs[oIndex].fPt);
759 } else { 989 } else {
760 if (!binary || test->fWindValue + oTest->fOppValue >= 0) { 990 if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
761 bumpCoincidentThis(*oTest, binary, &index, &outsidePts); 991 bumpCoincidentThis(*oTest, binary, &index, &outsidePts);
762 other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); 992 other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts);
763 } else { 993 } else {
764 other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts); 994 other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts);
765 bumpCoincidentOther(*oTest, &index, &outsidePts); 995 bumpCoincidentOther(*oTest, &index, &outsidePts);
766 } 996 }
767 } 997 }
768 test = &fTs[index]; 998 test = &fTs[index];
769 testPt = &test->fPt; 999 testPt = &test->fPt;
770 testT = test->fT; 1000 testT = test->fT;
771 if (endPt == *testPt || endT == testT) { 1001 oTest = &other->fTs[oIndex];
1002 oTestPt = &oTest->fPt;
1003 if (endPt == *testPt || precisely_equal(endT, testT)) {
772 break; 1004 break;
773 } 1005 }
774 oTest = &other->fTs[oIndex]; 1006 // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
775 oTestPt = &oTest->fPt;
776 SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
777 } while (endPt != *oTestPt); 1007 } while (endPt != *oTestPt);
778 if (endPt != *testPt && endT != testT) { // in rare cases, one may have end ed before the other 1008 // in rare cases, one may have ended before the other
1009 if (endPt != *testPt && !precisely_equal(endT, testT)) {
779 int lastWind = test[-1].fWindValue; 1010 int lastWind = test[-1].fWindValue;
780 int lastOpp = test[-1].fOppValue; 1011 int lastOpp = test[-1].fOppValue;
781 bool zero = lastWind == 0 && lastOpp == 0; 1012 bool zero = lastWind == 0 && lastOpp == 0;
782 do { 1013 do {
783 if (test->fWindValue || test->fOppValue) { 1014 if (test->fWindValue || test->fOppValue) {
784 test->fWindValue = lastWind; 1015 test->fWindValue = lastWind;
785 test->fOppValue = lastOpp; 1016 test->fOppValue = lastOpp;
786 if (zero) { 1017 if (zero) {
787 test->fDone = true; 1018 test->fDone = true;
788 ++fDoneSpans; 1019 ++fDoneSpans;
789 } 1020 }
790 } 1021 }
791 test = &fTs[++index]; 1022 test = &fTs[++index];
792 testPt = &test->fPt; 1023 testPt = &test->fPt;
793 } while (endPt != *testPt); 1024 } while (endPt != *testPt);
794 } 1025 }
1026 if (endPt != *oTestPt) {
1027 // look ahead to see if zeroing more spans will allows us to catch up
1028 int oPeekIndex = oIndex;
1029 bool success = true;
1030 SkOpSpan* oPeek;
1031 do {
1032 oPeek = &other->fTs[oPeekIndex];
1033 if (oPeek->fT == 1) {
1034 success = false;
1035 break;
1036 }
1037 ++oPeekIndex;
1038 } while (endPt != oPeek->fPt);
1039 if (success) {
1040 // make sure the matching point completes the coincidence span
1041 success = false;
1042 do {
1043 if (oPeek->fOther == this) {
1044 success = true;
1045 break;
1046 }
1047 oPeek = &other->fTs[++oPeekIndex];
1048 } while (endPt == oPeek->fPt);
1049 }
1050 if (success) {
1051 do {
1052 if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
1053 other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts);
1054 } else {
1055 other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsideP ts);
1056 }
1057 oTest = &other->fTs[oIndex];
1058 oTestPt = &oTest->fPt;
1059 } while (endPt != *oTestPt);
1060 }
1061 }
795 int outCount = outsidePts.count(); 1062 int outCount = outsidePts.count();
796 if (!done() && outCount) { 1063 if (!done() && outCount) {
797 addCoinOutsides(outsidePts[0], endPt, other); 1064 addCoinOutsides(outsidePts[0], endPt, other);
798 } 1065 }
799 if (!other->done() && oOutsidePts.count()) { 1066 if (!other->done() && oOutsidePts.count()) {
800 other->addCoinOutsides(oOutsidePts[0], endPt, this); 1067 other->addCoinOutsides(oOutsidePts[0], endPt, this);
801 } 1068 }
802 } 1069 }
803 1070
804 // FIXME: this doesn't prevent the same span from being added twice 1071 // FIXME: this doesn't prevent the same span from being added twice
805 // fix in caller, SkASSERT here? 1072 // fix in caller, SkASSERT here?
806 void SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool bor rowWind, 1073 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind,
807 const SkPoint& pt) { 1074 const SkPoint& pt) {
808 int tCount = fTs.count(); 1075 int tCount = fTs.count();
809 for (int tIndex = 0; tIndex < tCount; ++tIndex) { 1076 for (int tIndex = 0; tIndex < tCount; ++tIndex) {
810 const SkOpSpan& span = fTs[tIndex]; 1077 const SkOpSpan& span = fTs[tIndex];
811 if (!approximately_negative(span.fT - t)) { 1078 if (!approximately_negative(span.fT - t)) {
812 break; 1079 break;
813 } 1080 }
814 if (approximately_negative(span.fT - t) && span.fOther == other 1081 if (approximately_negative(span.fT - t) && span.fOther == other
815 && approximately_equal(span.fOtherT, otherT)) { 1082 && approximately_equal(span.fOtherT, otherT)) {
816 #if DEBUG_ADD_T_PAIR 1083 #if DEBUG_ADD_T_PAIR
817 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", 1084 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n",
818 __FUNCTION__, fID, t, other->fID, otherT); 1085 __FUNCTION__, fID, t, other->fID, otherT);
819 #endif 1086 #endif
820 return; 1087 return NULL;
821 } 1088 }
822 } 1089 }
823 #if DEBUG_ADD_T_PAIR 1090 #if DEBUG_ADD_T_PAIR
824 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", 1091 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
825 __FUNCTION__, fID, t, other->fID, otherT); 1092 __FUNCTION__, fID, t, other->fID, otherT);
826 #endif 1093 #endif
827 int insertedAt = addT(other, pt, t); 1094 int insertedAt = addT(other, pt, t);
828 int otherInsertedAt = other->addT(this, pt, otherT); 1095 int otherInsertedAt = other->addT(this, pt, otherT);
829 addOtherT(insertedAt, otherT, otherInsertedAt); 1096 addOtherT(insertedAt, otherT, otherInsertedAt);
830 other->addOtherT(otherInsertedAt, t, insertedAt); 1097 other->addOtherT(otherInsertedAt, t, insertedAt);
831 matchWindingValue(insertedAt, t, borrowWind); 1098 matchWindingValue(insertedAt, t, borrowWind);
832 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); 1099 other->matchWindingValue(otherInsertedAt, otherT, borrowWind);
1100 return &span(insertedAt);
833 } 1101 }
834 1102
835 void SkOpSegment::addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* an gles) const { 1103 const SkOpAngle& SkOpSegment::angle(int index) const {
836 // add edge leading into junction 1104 SkASSERT(index >= 0);
837 int min = SkMin32(end, start); 1105 int count = fAngles.count();
838 if (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0) { 1106 if (index < count) {
839 addAngle(angles, end, start); 1107 return fAngles[index];
840 } 1108 }
841 // add edge leading away from junction 1109 index -= count;
842 int step = SkSign32(end - start); 1110 count = fSingletonAngles.count();
843 int tIndex = nextExactSpan(end, step); 1111 SkASSERT(index < count);
844 min = SkMin32(end, tIndex); 1112 return fSingletonAngles[index];
845 if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0)) {
846 addAngle(angles, end, tIndex);
847 }
848 } 1113 }
849 1114
850 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const { 1115 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const {
851 const SkPoint midPt = ptAtT(midT); 1116 const SkPoint midPt = ptAtT(midT);
852 SkPathOpsBounds bounds; 1117 SkPathOpsBounds bounds;
853 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY); 1118 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY);
854 bounds.sort(); 1119 bounds.sort();
855 return bounds.almostContains(midPt); 1120 return bounds.almostContains(midPt);
856 } 1121 }
857 1122
858 bool SkOpSegment::betweenTs(int lesser, double testT, int greater) const { 1123 bool SkOpSegment::betweenTs(int lesser, double testT, int greater) const {
859 if (lesser > greater) { 1124 if (lesser > greater) {
860 SkTSwap<int>(lesser, greater); 1125 SkTSwap<int>(lesser, greater);
861 } 1126 }
862 return approximately_between(fTs[lesser].fT, testT, fTs[greater].fT); 1127 return approximately_between(fTs[lesser].fT, testT, fTs[greater].fT);
863 } 1128 }
864 1129
865 // note that this follows the same logic flow as active angle 1130 // in extreme cases (like the buffer overflow test) return false to abort
866 bool SkOpSegment::buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool allowOpp) const { 1131 // for now, if one t value represents two different points, then the values are too extreme
867 double referenceT = fTs[index].fT; 1132 // to generate meaningful results
868 const SkPoint& referencePt = fTs[index].fPt; 1133 bool SkOpSegment::calcAngles() {
869 int lesser = index; 1134 int spanCount = fTs.count();
870 while (--lesser >= 0 && (allowOpp || fTs[lesser].fOther->fOperand == fOperan d) 1135 if (spanCount <= 2) {
871 && (precisely_negative(referenceT - fTs[lesser].fT) || fTs[lesser].f Tiny)) { 1136 return spanCount == 2;
872 buildAnglesInner(lesser, angles);
873 } 1137 }
874 do { 1138 int index = 1;
875 buildAnglesInner(index, angles); 1139 const SkOpSpan* firstSpan = &fTs[index];
876 if (++index == fTs.count()) { 1140 int activePrior = checkSetAngle(0);
877 break; 1141 const SkOpSpan* span = &fTs[0];
878 } 1142 if (firstSpan->fT == 0 || span->fTiny || span->fOtherT != 1 || span->fOther- >multipleEnds()) {
879 if (!allowOpp && fTs[index].fOther->fOperand != fOperand) { 1143 index = findStartSpan(0); // curve start intersects
880 break; 1144 if (index < 0) {
881 }
882 if (fTs[index - 1].fTiny) {
883 referenceT = fTs[index].fT;
884 continue;
885 }
886 if (!precisely_negative(fTs[index].fT - referenceT) && fTs[index].fPt == referencePt) {
887 // FIXME
888 // testQuad8 generates the wrong output unless false is returned her e. Other tests will
889 // take this path although they aren't required to. This means that many go much slower
890 // because of this sort fail.
891 // SkDebugf("!!!\n");
892 return false; 1145 return false;
893 } 1146 }
894 } while (precisely_negative(fTs[index].fT - referenceT)); 1147 if (activePrior >= 0) {
1148 addStartSpan(index);
1149 }
1150 }
1151 bool addEnd;
1152 int endIndex = spanCount - 1;
1153 span = &fTs[endIndex - 1];
1154 if ((addEnd = span->fT == 1 || span->fTiny)) { // if curve end intersects
1155 endIndex = findEndSpan(endIndex);
1156 if (endIndex < 0) {
1157 return false;
1158 }
1159 } else {
1160 addEnd = fTs[endIndex].fOtherT != 0 || fTs[endIndex].fOther->multipleSta rts();
1161 }
1162 SkASSERT(endIndex >= index);
1163 int prior = 0;
1164 while (index < endIndex) {
1165 const SkOpSpan& fromSpan = fTs[index]; // for each intermediate interse ction
1166 const SkOpSpan* lastSpan;
1167 span = &fromSpan;
1168 int start = index;
1169 do {
1170 lastSpan = span;
1171 span = &fTs[++index];
1172 SkASSERT(index < spanCount);
1173 if (!precisely_negative(span->fT - lastSpan->fT) && !lastSpan->fTiny ) {
1174 break;
1175 }
1176 if (!SkDPoint::ApproximatelyEqual(lastSpan->fPt, span->fPt)) {
1177 return false;
1178 }
1179 } while (true);
1180 int angleIndex = fAngles.count();
1181 int priorAngleIndex;
1182 if (activePrior >= 0) {
1183 int pActive = firstActive(prior);
1184 SkASSERT(pActive < start);
1185 fAngles.push_back().set(this, start, pActive);
1186 priorAngleIndex = angleIndex++;
1187 #if DEBUG_ANGLE
1188 fAngles.back().setID(priorAngleIndex);
1189 #endif
1190 }
1191 int active = checkSetAngle(start);
1192 if (active >= 0) {
1193 SkASSERT(active < index);
1194 fAngles.push_back().set(this, active, index);
1195 #if DEBUG_ANGLE
1196 fAngles.back().setID(angleIndex);
1197 #endif
1198 }
1199 #if DEBUG_ANGLE
1200 debugCheckPointsEqualish(start, index);
1201 #endif
1202 prior = start;
1203 do {
1204 const SkOpSpan* startSpan = &fTs[start - 1];
1205 if (!startSpan->fSmall || startSpan->fFromAngleIndex >= 0
1206 || startSpan->fToAngleIndex >= 0) {
1207 break;
1208 }
1209 --start;
1210 } while (start > 0);
1211 do {
1212 if (activePrior >= 0) {
1213 SkASSERT(fTs[start].fFromAngleIndex == -1);
1214 fTs[start].fFromAngleIndex = priorAngleIndex;
1215 }
1216 if (active >= 0) {
1217 SkASSERT(fTs[start].fToAngleIndex == -1);
1218 fTs[start].fToAngleIndex = angleIndex;
1219 }
1220 } while (++start < index);
1221 activePrior = active;
1222 }
1223 if (addEnd && activePrior >= 0) {
1224 addEndSpan(endIndex);
1225 }
895 return true; 1226 return true;
896 } 1227 }
897 1228
898 void SkOpSegment::buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const { 1229 int SkOpSegment::checkSetAngle(int tIndex) const {
899 const SkOpSpan* span = &fTs[index]; 1230 const SkOpSpan* span = &fTs[tIndex];
900 SkOpSegment* other = span->fOther; 1231 while (span->fTiny /* || span->fSmall */) {
901 // if there is only one live crossing, and no coincidence, continue 1232 span = &fTs[++tIndex];
902 // in the same direction
903 // if there is coincidence, the only choice may be to reverse direction
904 // find edge on either side of intersection
905 int oIndex = span->fOtherIndex;
906 // if done == -1, prior span has already been processed
907 int step = 1;
908 int next = other->nextExactSpan(oIndex, step);
909 if (next < 0) {
910 step = -step;
911 next = other->nextExactSpan(oIndex, step);
912 } 1233 }
913 // add candidate into and away from junction 1234 return isCanceled(tIndex) ? -1 : tIndex;
914 other->addTwoAngles(next, oIndex, angles);
915 } 1235 }
916 1236
917 int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType, 1237 // at this point, the span is already ordered, or unorderable, or unsortable
918 SkTArray<SkOpAngle, true>* angles, SkTArray<SkOpAngle*, true>* sorted) { 1238 int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType) {
919 addTwoAngles(startIndex, endIndex, angles); 1239 SkASSERT(includeType != SkOpAngle::kUnaryXor);
920 if (!buildAngles(endIndex, angles, includeType == SkOpAngle::kBinaryOpp)) { 1240 SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex);
1241 if (NULL == firstAngle) {
921 return SK_NaN32; 1242 return SK_NaN32;
922 } 1243 }
923 int angleCount = angles->count();
924 // abort early before sorting if an unsortable (not an unorderable) angle is found
925 if (includeType != SkOpAngle::kUnaryXor) {
926 int firstIndex = -1;
927 while (++firstIndex < angleCount) {
928 const SkOpAngle& angle = (*angles)[firstIndex];
929 if (angle.segment()->windSum(&angle) != SK_MinS32) {
930 break;
931 }
932 }
933 if (firstIndex == angleCount) {
934 return SK_MinS32;
935 }
936 }
937 bool sortable = SortAngles2(*angles, sorted);
938 #if DEBUG_SORT_RAW
939 if (sorted->count() > 0) {
940 (*sorted)[0]->segment()->debugShowSort(__FUNCTION__, *sorted, 0, 0, 0, s ortable);
941 }
942 #endif
943 if (!sortable) {
944 return SK_NaN32;
945 }
946 if (includeType == SkOpAngle::kUnaryXor) {
947 return SK_MinS32;
948 }
949 // if all angles have a computed winding, 1244 // if all angles have a computed winding,
950 // or if no adjacent angles are orderable, 1245 // or if no adjacent angles are orderable,
951 // or if adjacent orderable angles have no computed winding, 1246 // or if adjacent orderable angles have no computed winding,
952 // there's nothing to do 1247 // there's nothing to do
953 // if two orderable angles are adjacent, and one has winding computed, trans fer to the other 1248 // if two orderable angles are adjacent, and one has winding computed, trans fer to the other
954 const SkOpAngle* baseAngle = NULL; 1249 SkOpAngle* baseAngle = NULL;
955 int last = angleCount;
956 int finalInitialOrderable = -1;
957 bool tryReverse = false; 1250 bool tryReverse = false;
958 // look for counterclockwise transfers 1251 // look for counterclockwise transfers
1252 SkOpAngle* angle = firstAngle;
959 do { 1253 do {
960 int index = 0; 1254 int testWinding = angle->segment()->windSum(angle);
1255 if (SK_MinS32 != testWinding && !angle->unorderable()) {
1256 baseAngle = angle;
1257 continue;
1258 }
1259 if (angle->unorderable()) {
1260 baseAngle = NULL;
1261 tryReverse = true;
1262 continue;
1263 }
1264 if (baseAngle) {
1265 ComputeOneSum(baseAngle, angle, includeType);
1266 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle : NULL;
1267 tryReverse |= !baseAngle;
1268 }
1269 } while ((angle = angle->next()) != firstAngle);
1270 if (baseAngle && SK_MinS32 == firstAngle->segment()->windSum(angle)) {
1271 firstAngle = baseAngle;
1272 tryReverse = true;
1273 }
1274 if (tryReverse) {
1275 baseAngle = NULL;
1276 angle = firstAngle;
961 do { 1277 do {
962 SkOpAngle* testAngle = (*sorted)[index]; 1278 int testWinding = angle->segment()->windSum(angle);
963 int testWinding = testAngle->segment()->windSum(testAngle); 1279 if (SK_MinS32 != testWinding) {
964 if (SK_MinS32 != testWinding && !testAngle->unorderable()) { 1280 baseAngle = angle;
965 baseAngle = testAngle;
966 continue; 1281 continue;
967 } 1282 }
968 if (testAngle->unorderable()) { 1283 if (angle->unorderable()) {
969 baseAngle = NULL; 1284 baseAngle = NULL;
970 tryReverse = true;
971 continue; 1285 continue;
972 } 1286 }
973 if (baseAngle) { 1287 if (baseAngle) {
974 ComputeOneSum(baseAngle, testAngle, includeType); 1288 ComputeOneSumReverse(baseAngle, angle, includeType);
975 baseAngle = SK_MinS32 != testAngle->segment()->windSum(testAngle ) ? testAngle 1289 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angl e : NULL;
976 : NULL;
977 tryReverse |= !baseAngle;
978 continue;
979 } 1290 }
980 if (finalInitialOrderable + 1 == index) { 1291 } while ((angle = angle->previous()) != firstAngle);
981 finalInitialOrderable = index;
982 }
983 } while (++index != last);
984 if (finalInitialOrderable < 0) {
985 break;
986 }
987 last = finalInitialOrderable + 1;
988 finalInitialOrderable = -2; // make this always negative the second tim e through
989 } while (baseAngle);
990 if (tryReverse) {
991 baseAngle = NULL;
992 last = 0;
993 finalInitialOrderable = angleCount;
994 do {
995 int index = angleCount;
996 while (--index >= last) {
997 SkOpAngle* testAngle = (*sorted)[index];
998 int testWinding = testAngle->segment()->windSum(testAngle);
999 if (SK_MinS32 != testWinding) {
1000 baseAngle = testAngle;
1001 continue;
1002 }
1003 if (testAngle->unorderable()) {
1004 baseAngle = NULL;
1005 continue;
1006 }
1007 if (baseAngle) {
1008 ComputeOneSumReverse(baseAngle, testAngle, includeType);
1009 baseAngle = SK_MinS32 != testAngle->segment()->windSum(testA ngle) ? testAngle
1010 : NULL;
1011 continue;
1012 }
1013 if (finalInitialOrderable - 1 == index) {
1014 finalInitialOrderable = index;
1015 }
1016 }
1017 if (finalInitialOrderable >= angleCount) {
1018 break;
1019 }
1020 last = finalInitialOrderable;
1021 finalInitialOrderable = angleCount + 1; // make this inactive 2nd t ime through
1022 } while (baseAngle);
1023 } 1292 }
1024 int minIndex = SkMin32(startIndex, endIndex); 1293 int minIndex = SkMin32(startIndex, endIndex);
1025 return windSum(minIndex); 1294 return windSum(minIndex);
1026 } 1295 }
1027 1296
1028 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle , 1297 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle ,
1029 SkOpAngle::IncludeType includeType) { 1298 SkOpAngle::IncludeType includeType) {
1030 const SkOpSegment* baseSegment = baseAngle->segment(); 1299 const SkOpSegment* baseSegment = baseAngle->segment();
1031 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 1300 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle);
1032 int sumSuWinding; 1301 int sumSuWinding;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding, 1345 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding,
1077 nextAngle); 1346 nextAngle);
1078 } else { 1347 } else {
1079 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding, 1348 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding,
1080 &maxWinding, &sumWinding); 1349 &maxWinding, &sumWinding);
1081 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 1350 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
1082 } 1351 }
1083 nextAngle->setLastMarked(last); 1352 nextAngle->setLastMarked(last);
1084 } 1353 }
1085 1354
1355 void SkOpSegment::constructLine(SkPoint shortLine[2]) {
1356 addLine(shortLine, false, false);
1357 addT(NULL, shortLine[0], 0);
1358 addT(NULL, shortLine[1], 1);
1359 addStartSpan(1);
1360 addEndSpan(1);
1361 SkOpAngle& angle = fAngles.push_back();
1362 angle.set(this, 0, 1);
1363 }
1364
1086 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT, 1365 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT,
1087 bool* hitSomething, double mid, bool opp, bool cur rent) const { 1366 bool* hitSomething, double mid, bool opp, bool cur rent) const {
1088 SkScalar bottom = fBounds.fBottom; 1367 SkScalar bottom = fBounds.fBottom;
1089 int bestTIndex = -1; 1368 int bestTIndex = -1;
1090 if (bottom <= *bestY) { 1369 if (bottom <= *bestY) {
1091 return bestTIndex; 1370 return bestTIndex;
1092 } 1371 }
1093 SkScalar top = fBounds.fTop; 1372 SkScalar top = fBounds.fTop;
1094 if (top >= basePt.fY) { 1373 if (top >= basePt.fY) {
1095 return bestTIndex; 1374 return bestTIndex;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 span->fOppValue &= 1; 1478 span->fOppValue &= 1;
1200 } 1479 }
1201 if (!span->fWindValue && !span->fOppValue) { 1480 if (!span->fWindValue && !span->fOppValue) {
1202 span->fDone = true; 1481 span->fDone = true;
1203 ++fDoneSpans; 1482 ++fDoneSpans;
1204 return true; 1483 return true;
1205 } 1484 }
1206 return false; 1485 return false;
1207 } 1486 }
1208 1487
1488 const SkOpSpan& SkOpSegment::firstSpan(const SkOpSpan& thisSpan) const {
1489 const SkOpSpan* firstSpan = &thisSpan; // rewind to the start
1490 const SkOpSpan* beginSpan = fTs.begin();
1491 const SkPoint& testPt = thisSpan.fPt;
1492 while (firstSpan > beginSpan && firstSpan[-1].fPt == testPt) {
1493 --firstSpan;
1494 }
1495 return *firstSpan;
1496 }
1497
1498 const SkOpSpan& SkOpSegment::lastSpan(const SkOpSpan& thisSpan) const {
1499 const SkOpSpan* endSpan = fTs.end() - 1; // last can't be small
1500 const SkOpSpan* lastSpan = &thisSpan; // find the end
1501 const SkPoint& testPt = thisSpan.fPt;
1502 while (lastSpan < endSpan && lastSpan[1].fPt == testPt) {
1503 ++lastSpan;
1504 }
1505 return *lastSpan;
1506 }
1507
1508 // with a loop, the comparison is move involved
1509 // scan backwards and forwards to count all matching points
1510 // (verify that there are twp scans marked as loops)
1511 // compare that against 2 matching scans for loop plus other results
1512 bool SkOpSegment::calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts) {
1513 const SkOpSpan& firstSpan = this->firstSpan(thisSpan); // rewind to the star t
1514 const SkOpSpan& lastSpan = this->lastSpan(thisSpan); // find the end
1515 double firstLoopT = -1, lastLoopT = -1;
1516 const SkOpSpan* testSpan = &firstSpan - 1;
1517 while (++testSpan <= &lastSpan) {
1518 if (testSpan->fLoop) {
1519 firstLoopT = testSpan->fT;
1520 break;
1521 }
1522 }
1523 testSpan = &lastSpan + 1;
1524 while (--testSpan >= &firstSpan) {
1525 if (testSpan->fLoop) {
1526 lastLoopT = testSpan->fT;
1527 break;
1528 }
1529 }
1530 SkASSERT((firstLoopT == -1) == (lastLoopT == -1));
1531 if (firstLoopT == -1) {
1532 return false;
1533 }
1534 SkASSERT(firstLoopT < lastLoopT);
1535 testSpan = &firstSpan - 1;
1536 smallCounts[0] = smallCounts[1] = 0;
1537 while (++testSpan <= &lastSpan) {
1538 SkASSERT(approximately_equal(testSpan->fT, firstLoopT) +
1539 approximately_equal(testSpan->fT, lastLoopT) == 1);
1540 smallCounts[approximately_equal(testSpan->fT, lastLoopT)]++;
1541 }
1542 return true;
1543 }
1544
1545 // see if spans with two or more intersections have the same number on the other end
1546 void SkOpSegment::checkDuplicates() {
1547 debugValidate();
1548 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
1549 int index;
1550 int endIndex = 0;
1551 bool endFound;
1552 do {
1553 index = endIndex;
1554 endIndex = nextExactSpan(index, 1);
1555 if ((endFound = endIndex < 0)) {
1556 endIndex = count();
1557 }
1558 int dupCount = endIndex - index;
1559 if (dupCount < 2) {
1560 continue;
1561 }
1562 do {
1563 const SkOpSpan* thisSpan = &fTs[index];
1564 SkOpSegment* other = thisSpan->fOther;
1565 int oIndex = thisSpan->fOtherIndex;
1566 int oStart = other->nextExactSpan(oIndex, -1) + 1;
1567 int oEnd = other->nextExactSpan(oIndex, 1);
1568 if (oEnd < 0) {
1569 oEnd = other->count();
1570 }
1571 int oCount = oEnd - oStart;
1572 // force the other to match its t and this pt if not on an end point
1573 if (oCount != dupCount) {
1574 MissingSpan& missing = missingSpans.push_back();
1575 missing.fOther = NULL;
1576 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
1577 missing.fPt = thisSpan->fPt;
1578 const SkOpSpan& oSpan = other->span(oIndex);
1579 if (oCount > dupCount) {
1580 missing.fSegment = this;
1581 missing.fT = thisSpan->fT;
1582 other->checkLinks(&oSpan, &missingSpans);
1583 } else {
1584 missing.fSegment = other;
1585 missing.fT = oSpan.fT;
1586 checkLinks(thisSpan, &missingSpans);
1587 }
1588 if (!missingSpans.back().fOther) {
1589 missingSpans.pop_back();
1590 }
1591 }
1592 } while (++index < endIndex);
1593 } while (!endFound);
1594 int missingCount = missingSpans.count();
1595 if (missingCount == 0) {
1596 return;
1597 }
1598 SkSTArray<kMissingSpanCount, MissingSpan, true> missingCoincidence;
1599 for (index = 0; index < missingCount; ++index) {
1600 MissingSpan& missing = missingSpans[index];
1601 SkOpSegment* missingOther = missing.fOther;
1602 if (missing.fSegment == missing.fOther) {
1603 continue;
1604 }
1605 const SkOpSpan* added = missing.fSegment->addTPair(missing.fT, missingOt her,
1606 missing.fOtherT, false, missing.fPt);
1607 if (added && added->fSmall) {
1608 missing.fSegment->checkSmallCoincidence(*added, &missingCoincidence) ;
1609 }
1610 }
1611 for (index = 0; index < missingCount; ++index) {
1612 MissingSpan& missing = missingSpans[index];
1613 missing.fSegment->fixOtherTIndex();
1614 missing.fOther->fixOtherTIndex();
1615 }
1616 for (index = 0; index < missingCoincidence.count(); ++index) {
1617 MissingSpan& missing = missingCoincidence[index];
1618 missing.fSegment->fixOtherTIndex();
1619 }
1620 debugValidate();
1621 }
1622
1209 // look to see if the curve end intersects an intermediary that intersects the o ther 1623 // look to see if the curve end intersects an intermediary that intersects the o ther
1210 void SkOpSegment::checkEnds() { 1624 void SkOpSegment::checkEnds() {
1211 debugValidate(); 1625 debugValidate();
1212 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 1626 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
1213 int count = fTs.count(); 1627 int count = fTs.count();
1214 for (int index = 0; index < count; ++index) { 1628 for (int index = 0; index < count; ++index) {
1215 const SkOpSpan& span = fTs[index]; 1629 const SkOpSpan& span = fTs[index];
1216 double otherT = span.fOtherT; 1630 double otherT = span.fOtherT;
1217 if (otherT != 0 && otherT != 1) { // only check ends 1631 if (otherT != 0 && otherT != 1) { // only check ends
1218 continue; 1632 continue;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 } 1720 }
1307 } 1721 }
1308 if (missingSpans.count() == 0) { 1722 if (missingSpans.count() == 0) {
1309 debugValidate(); 1723 debugValidate();
1310 return; 1724 return;
1311 } 1725 }
1312 debugValidate(); 1726 debugValidate();
1313 int missingCount = missingSpans.count(); 1727 int missingCount = missingSpans.count();
1314 for (int index = 0; index < missingCount; ++index) { 1728 for (int index = 0; index < missingCount; ++index) {
1315 MissingSpan& missing = missingSpans[index]; 1729 MissingSpan& missing = missingSpans[index];
1316 addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt ); 1730 if (this != missing.fOther) {
1731 addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing .fPt);
1732 }
1317 } 1733 }
1318 fixOtherTIndex(); 1734 fixOtherTIndex();
1319 // OPTIMIZATION: this may fix indices more than once. Build an array of uniq ue segments to 1735 // OPTIMIZATION: this may fix indices more than once. Build an array of uniq ue segments to
1320 // avoid this 1736 // avoid this
1321 for (int index = 0; index < missingCount; ++index) { 1737 for (int index = 0; index < missingCount; ++index) {
1322 missingSpans[index].fOther->fixOtherTIndex(); 1738 missingSpans[index].fOther->fixOtherTIndex();
1323 } 1739 }
1324 debugValidate(); 1740 debugValidate();
1325 } 1741 }
1326 1742
1743 void SkOpSegment::checkLinks(const SkOpSpan* base,
1744 SkTArray<MissingSpan, true>* missingSpans) const {
1745 const SkOpSpan* first = fTs.begin();
1746 const SkOpSpan* last = fTs.end() - 1;
1747 SkASSERT(base >= first && last >= base);
1748 const SkOpSegment* other = base->fOther;
1749 const SkOpSpan* oFirst = other->fTs.begin();
1750 const SkOpSpan* oLast = other->fTs.end() - 1;
1751 const SkOpSpan* oSpan = &other->fTs[base->fOtherIndex];
1752 const SkOpSpan* test = base;
1753 const SkOpSpan* missing = NULL;
1754 while (test > first && (--test)->fPt == base->fPt) {
1755 CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans);
1756 }
1757 test = base;
1758 while (test < last && (++test)->fPt == base->fPt) {
1759 CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans);
1760 }
1761 }
1762
1763 // see if spans with two or more intersections all agree on common t and point v alues
1764 void SkOpSegment::checkMultiples() {
1765 debugValidate();
1766 int index;
1767 int end = 0;
1768 while (fTs[++end].fT == 0)
1769 ;
1770 while (fTs[end].fT < 1) {
1771 int start = index = end;
1772 end = nextExactSpan(index, 1);
1773 if (end <= index) {
1774 return; // buffer overflow example triggers this
1775 }
1776 if (index + 1 == end) {
1777 continue;
1778 }
1779 // force the duplicates to agree on t and pt if not on the end
1780 double thisT = fTs[index].fT;
1781 const SkPoint& thisPt = fTs[index].fPt;
1782 bool aligned = false;
1783 while (++index < end) {
1784 aligned |= alignSpan(index, thisT, thisPt);
1785 }
1786 if (aligned) {
1787 alignSpanState(start, end);
1788 }
1789 }
1790 debugValidate();
1791 }
1792
1793 void SkOpSegment::CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
1794 const SkOpSpan* oFirst, const SkOpSpan* oLast, const SkOpSpan** missingP tr,
1795 SkTArray<MissingSpan, true>* missingSpans) {
1796 SkASSERT(oSpan->fPt == test->fPt);
1797 const SkOpSpan* oTest = oSpan;
1798 while (oTest > oFirst && (--oTest)->fPt == test->fPt) {
1799 if (oTest->fOther == test->fOther && oTest->fOtherT == test->fOtherT) {
1800 return;
1801 }
1802 }
1803 oTest = oSpan;
1804 while (oTest < oLast && (++oTest)->fPt == test->fPt) {
1805 if (oTest->fOther == test->fOther && oTest->fOtherT == test->fOtherT) {
1806 return;
1807 }
1808 }
1809 if (*missingPtr) {
1810 missingSpans->push_back();
1811 }
1812 MissingSpan& lastMissing = missingSpans->back();
1813 if (*missingPtr) {
1814 lastMissing = missingSpans->end()[-2];
1815 }
1816 *missingPtr = test;
1817 lastMissing.fOther = test->fOther;
1818 lastMissing.fOtherT = test->fOtherT;
1819 }
1820
1327 bool SkOpSegment::checkSmall(int index) const { 1821 bool SkOpSegment::checkSmall(int index) const {
1328 if (fTs[index].fSmall) { 1822 if (fTs[index].fSmall) {
1329 return true; 1823 return true;
1330 } 1824 }
1331 double tBase = fTs[index].fT; 1825 double tBase = fTs[index].fT;
1332 while (index > 0 && precisely_negative(tBase - fTs[--index].fT)) 1826 while (index > 0 && precisely_negative(tBase - fTs[--index].fT))
1333 ; 1827 ;
1334 return fTs[index].fSmall; 1828 return fTs[index].fSmall;
1335 } 1829 }
1336 1830
1831 // a pair of curves may turn into coincident lines -- small may be a hint that t hat happened
1832 // if a cubic contains a loop, the counts must be adjusted
1833 void SkOpSegment::checkSmall() {
1834 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
1835 const SkOpSpan* beginSpan = fTs.begin();
1836 const SkOpSpan* thisSpan = beginSpan - 1;
1837 const SkOpSpan* endSpan = fTs.end() - 1; // last can't be small
1838 while (++thisSpan < endSpan) {
1839 if (!thisSpan->fSmall) {
1840 continue;
1841 }
1842 if (!thisSpan->fWindValue) {
1843 continue;
1844 }
1845 const SkOpSpan& firstSpan = this->firstSpan(*thisSpan);
1846 const SkOpSpan& lastSpan = this->lastSpan(*thisSpan);
1847 ptrdiff_t smallCount = &lastSpan - &firstSpan + 1;
1848 SkASSERT(1 <= smallCount && smallCount < count());
1849 if (smallCount <= 1) {
1850 SkASSERT(1 == smallCount);
1851 checkSmallCoincidence(firstSpan, NULL);
1852 continue;
1853 }
1854 // at this point, check for missing computed intersections
1855 const SkPoint& testPt = firstSpan.fPt;
1856 thisSpan = &firstSpan - 1;
1857 SkOpSegment* other = NULL;
1858 while (++thisSpan <= &lastSpan) {
1859 other = thisSpan->fOther;
1860 if (other != this) {
1861 break;
1862 }
1863 }
1864 SkASSERT(other != this);
1865 int oIndex = thisSpan->fOtherIndex;
1866 const SkOpSpan& oSpan = other->span(oIndex);
1867 const SkOpSpan& oFirstSpan = other->firstSpan(oSpan);
1868 const SkOpSpan& oLastSpan = other->lastSpan(oSpan);
1869 ptrdiff_t oCount = &oLastSpan - &oFirstSpan + 1;
1870 if (fLoop) {
1871 int smallCounts[2];
1872 SkASSERT(!other->fLoop); // FIXME: we need more complicated logic f or pair of loops
1873 if (calcLoopSpanCount(*thisSpan, smallCounts)) {
1874 if (smallCounts[0] && oCount != smallCounts[0]) {
1875 SkASSERT(0); // FIXME: need a working test case to properly code & debug
1876 }
1877 if (smallCounts[1] && oCount != smallCounts[1]) {
1878 SkASSERT(0); // FIXME: need a working test case to properly code & debug
1879 }
1880 goto nextSmallCheck;
1881 }
1882 }
1883 if (other->fLoop) {
1884 int otherCounts[2];
1885 if (other->calcLoopSpanCount(other->span(oIndex), otherCounts)) {
1886 if (otherCounts[0] && otherCounts[0] != smallCount) {
1887 SkASSERT(0); // FIXME: need a working test case to properly code & debug
1888 }
1889 if (otherCounts[1] && otherCounts[1] != smallCount) {
1890 SkASSERT(0); // FIXME: need a working test case to properly code & debug
1891 }
1892 goto nextSmallCheck;
1893 }
1894 }
1895 if (oCount != smallCount) { // check if number of pts in this match oth er
1896 MissingSpan& missing = missingSpans.push_back();
1897 missing.fOther = NULL;
1898 SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
1899 missing.fPt = testPt;
1900 const SkOpSpan& oSpan = other->span(oIndex);
1901 if (oCount > smallCount) {
1902 missing.fSegment = this;
1903 missing.fT = thisSpan->fT;
1904 other->checkLinks(&oSpan, &missingSpans);
1905 } else {
1906 missing.fSegment = other;
1907 missing.fT = oSpan.fT;
1908 checkLinks(thisSpan, &missingSpans);
1909 }
1910 if (!missingSpans.back().fOther || missing.fSegment->done()) {
1911 missingSpans.pop_back();
1912 }
1913 }
1914 nextSmallCheck:
1915 thisSpan = &lastSpan;
1916 }
1917 int missingCount = missingSpans.count();
1918 for (int index = 0; index < missingCount; ++index) {
1919 MissingSpan& missing = missingSpans[index];
1920 SkOpSegment* missingOther = missing.fOther;
1921 // note that add t pair may edit span arrays, so prior pointers to spans are no longer valid
1922 if (!missing.fSegment->addTPair(missing.fT, missingOther, missing.fOther T, false,
1923 missing.fPt)) {
1924 continue;
1925 }
1926 int otherTIndex = missingOther->findT(missing.fOtherT, missing.fSegment) ;
1927 const SkOpSpan& otherSpan = missingOther->span(otherTIndex);
1928 if (otherSpan.fSmall) {
1929 const SkOpSpan* nextSpan = &otherSpan;
1930 do {
1931 ++nextSpan;
1932 } while (nextSpan->fSmall);
1933 missing.fSegment->addTCoincident(missing.fPt, nextSpan->fPt, nextSpa n->fT,
1934 missingOther);
1935 } else if (otherSpan.fT > 0) {
1936 const SkOpSpan* priorSpan = &otherSpan;
1937 do {
1938 --priorSpan;
1939 } while (priorSpan->fT == otherSpan.fT);
1940 if (priorSpan->fSmall) {
1941 missing.fSegment->addTCancel(missing.fPt, priorSpan->fPt, missin gOther);
1942 }
1943 }
1944 }
1945 // OPTIMIZATION: this may fix indices more than once. Build an array of uniq ue segments to
1946 // avoid this
1947 for (int index = 0; index < missingCount; ++index) {
1948 MissingSpan& missing = missingSpans[index];
1949 missing.fSegment->fixOtherTIndex();
1950 missing.fOther->fixOtherTIndex();
1951 }
1952 debugValidate();
1953 }
1954
1955 void SkOpSegment::checkSmallCoincidence(const SkOpSpan& span,
1956 SkTArray<MissingSpan, true>* checkMultiple) {
1957 SkASSERT(span.fSmall);
1958 SkASSERT(span.fWindValue);
1959 SkASSERT(&span < fTs.end() - 1);
1960 const SkOpSpan* next = &span + 1;
1961 SkASSERT(!next->fSmall || checkMultiple);
1962 if (checkMultiple) {
1963 while (next->fSmall) {
1964 ++next;
1965 SkASSERT(next < fTs.end());
1966 }
1967 }
1968 SkOpSegment* other = span.fOther;
1969 while (other != next->fOther) {
1970 if (!checkMultiple) {
1971 return;
1972 }
1973 const SkOpSpan* test = next + 1;
1974 if (test == fTs.end()) {
1975 return;
1976 }
1977 if (test->fPt != next->fPt || !precisely_equal(test->fT, next->fT)) {
1978 return;
1979 }
1980 next = test;
1981 }
1982 SkASSERT(span.fT < next->fT);
1983 int oStartIndex = other->findExactT(span.fOtherT, this);
1984 int oEndIndex = other->findExactT(next->fOtherT, this);
1985 // FIXME: be overly conservative by limiting this to the caller that allows multiple smalls
1986 if (!checkMultiple || fVerb != SkPath::kLine_Verb || other->fVerb != SkPath: :kLine_Verb) {
1987 SkPoint mid = ptAtT((span.fT + next->fT) / 2);
1988 const SkOpSpan& oSpanStart = other->fTs[oStartIndex];
1989 const SkOpSpan& oSpanEnd = other->fTs[oEndIndex];
1990 SkPoint oMid = other->ptAtT((oSpanStart.fT + oSpanEnd.fT) / 2);
1991 if (!SkDPoint::ApproximatelyEqual(mid, oMid)) {
1992 return;
1993 }
1994 }
1995 // FIXME: again, be overly conservative to avoid breaking existing tests
1996 const SkOpSpan& oSpan = oStartIndex < oEndIndex ? other->fTs[oStartIndex]
1997 : other->fTs[oEndIndex];
1998 if (checkMultiple && !oSpan.fSmall) {
1999 return;
2000 }
2001 SkASSERT(oSpan.fSmall);
2002 if (oStartIndex < oEndIndex) {
2003 addTCoincident(span.fPt, next->fPt, next->fT, other);
2004 } else {
2005 addTCancel(span.fPt, next->fPt, other);
2006 }
2007 if (!checkMultiple) {
2008 return;
2009 }
2010 // check to see if either segment is coincident with a third segment -- if i t is, and if
2011 // the opposite segment is not already coincident with the third, make it so
2012 // OPTIMIZE: to make this check easier, add coincident and cancel could set a coincident bit
2013 if (span.fWindValue != 1 || span.fOppValue != 0) {
2014 // start here;
2015 // iterate through the spans, looking for the third coincident case
2016 // if we find one, we need to return state to the caller so that the ind ices can be fixed
2017 // this also suggests that all of this function is fragile since it reli es on a valid index
2018 }
2019 // probably should make this a common function rather than copy/paste code
2020 if (oSpan.fWindValue != 1 || oSpan.fOppValue != 0) {
2021 const SkOpSpan* oTest = &oSpan;
2022 while (--oTest >= other->fTs.begin()) {
2023 if (oTest->fPt != oSpan.fPt || !precisely_equal(oTest->fT, oSpan.fT) ) {
2024 break;
2025 }
2026 SkOpSegment* testOther = oTest->fOther;
2027 SkASSERT(testOther != this);
2028 // look in both directions to see if there is a coincident span
2029 const SkOpSpan* tTest = testOther->fTs.begin();
2030 for (int testIndex = 0; testIndex < testOther->count(); ++testIndex) {
2031 if (tTest->fPt != span.fPt) {
2032 ++tTest;
2033 continue;
2034 }
2035 if (testOther->verb() != SkPath::kLine_Verb
2036 || other->verb() != SkPath::kLine_Verb) {
2037 SkPoint mid = ptAtT((span.fT + next->fT) / 2);
2038 SkPoint oMid = other->ptAtT((oTest->fOtherT + tTest->fT) / 2 );
2039 if (!SkDPoint::ApproximatelyEqual(mid, oMid)) {
2040 continue;
2041 }
2042 }
2043 #if DEBUG_CONCIDENT
2044 SkDebugf("%s coincident found=%d %1.9g %1.9g\n", __FUNCTION__, t estOther->fID,
2045 oTest->fOtherT, tTest->fT);
2046 #endif
2047 if (tTest->fT < oTest->fOtherT) {
2048 addTCoincident(span.fPt, next->fPt, next->fT, testOther);
2049 } else {
2050 addTCancel(span.fPt, next->fPt, testOther);
2051 }
2052 MissingSpan missing;
2053 missing.fSegment = testOther;
2054 checkMultiple->push_back(missing);
2055 break;
2056 }
2057 }
2058 oTest = &oSpan;
2059 while (++oTest < other->fTs.end()) {
2060 if (oTest->fPt != oSpan.fPt || !precisely_equal(oTest->fT, oSpan.fT) ) {
2061 break;
2062 }
2063
2064 }
2065 }
2066 }
2067
1337 // if pair of spans on either side of tiny have the same end point and mid point , mark 2068 // if pair of spans on either side of tiny have the same end point and mid point , mark
1338 // them as parallel 2069 // them as parallel
1339 // OPTIMIZATION : mark the segment to note that some span is tiny
1340 void SkOpSegment::checkTiny() { 2070 void SkOpSegment::checkTiny() {
1341 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 2071 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
1342 SkOpSpan* thisSpan = fTs.begin() - 1; 2072 SkOpSpan* thisSpan = fTs.begin() - 1;
1343 const SkOpSpan* endSpan = fTs.end() - 1; // last can't be tiny 2073 const SkOpSpan* endSpan = fTs.end() - 1; // last can't be tiny
1344 while (++thisSpan < endSpan) { 2074 while (++thisSpan < endSpan) {
1345 if (!thisSpan->fTiny) { 2075 if (!thisSpan->fTiny) {
1346 continue; 2076 continue;
1347 } 2077 }
1348 SkOpSpan* nextSpan = thisSpan + 1; 2078 SkOpSpan* nextSpan = thisSpan + 1;
1349 double thisT = thisSpan->fT; 2079 double thisT = thisSpan->fT;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 missing.fPt = thisSpan->fPt; 2124 missing.fPt = thisSpan->fPt;
1395 } 2125 }
1396 } 2126 }
1397 } 2127 }
1398 int missingCount = missingSpans.count(); 2128 int missingCount = missingSpans.count();
1399 if (!missingCount) { 2129 if (!missingCount) {
1400 return; 2130 return;
1401 } 2131 }
1402 for (int index = 0; index < missingCount; ++index) { 2132 for (int index = 0; index < missingCount; ++index) {
1403 MissingSpan& missing = missingSpans[index]; 2133 MissingSpan& missing = missingSpans[index];
1404 missing.fSegment->addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt); 2134 if (missing.fSegment != missing.fOther) {
2135 missing.fSegment->addTPair(missing.fT, missing.fOther, missing.fOthe rT, false,
2136 missing.fPt);
2137 }
1405 } 2138 }
2139 // OPTIMIZE: consolidate to avoid multiple calls to fix index
1406 for (int index = 0; index < missingCount; ++index) { 2140 for (int index = 0; index < missingCount; ++index) {
1407 MissingSpan& missing = missingSpans[index]; 2141 MissingSpan& missing = missingSpans[index];
1408 missing.fSegment->fixOtherTIndex(); 2142 missing.fSegment->fixOtherTIndex();
1409 missing.fOther->fixOtherTIndex(); 2143 missing.fOther->fixOtherTIndex();
1410 } 2144 }
1411 } 2145 }
1412 2146
1413 bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* o ther, int oStart, 2147 bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* o ther, int oStart,
1414 int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) cons t { 2148 int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) cons t {
1415 SkASSERT(span->fT == 0 || span->fT == 1); 2149 SkASSERT(span->fT == 0 || span->fT == 1);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 return false; 2201 return false;
1468 } 2202 }
1469 if (otherSpan == lastSpan) { 2203 if (otherSpan == lastSpan) {
1470 break; 2204 break;
1471 } 2205 }
1472 otherSpan += step; 2206 otherSpan += step;
1473 } while (otherSpan->fT == refT || otherSpan->fPt == refPt); 2207 } while (otherSpan->fT == refT || otherSpan->fPt == refPt);
1474 return false; 2208 return false;
1475 } 2209 }
1476 2210
2211 int SkOpSegment::findEndSpan(int endIndex) const {
2212 const SkOpSpan* span = &fTs[--endIndex];
2213 const SkPoint& lastPt = span->fPt;
2214 double endT = span->fT;
2215 do {
2216 span = &fTs[--endIndex];
2217 } while (SkDPoint::ApproximatelyEqual(span->fPt, lastPt) && (span->fT == end T || span->fTiny));
2218 return endIndex + 1;
2219 }
2220
1477 /* 2221 /*
1478 The M and S variable name parts stand for the operators. 2222 The M and S variable name parts stand for the operators.
1479 Mi stands for Minuend (see wiki subtraction, analogous to difference) 2223 Mi stands for Minuend (see wiki subtraction, analogous to difference)
1480 Su stands for Subtrahend 2224 Su stands for Subtrahend
1481 The Opp variable name part designates that the value is for the Opposite operat or. 2225 The Opp variable name part designates that the value is for the Opposite operat or.
1482 Opposite values result from combining coincident spans. 2226 Opposite values result from combining coincident spans.
1483 */ 2227 */
1484 SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart , int* nextEnd, 2228 SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart , int* nextEnd,
1485 bool* unsortable, SkPathOp op, const int xo rMiMask, 2229 bool* unsortable, SkPathOp op, const int xo rMiMask,
1486 const int xorSuMask) { 2230 const int xorSuMask) {
(...skipping 25 matching lines...) Expand all
1512 do { 2256 do {
1513 *nextEnd += step; 2257 *nextEnd += step;
1514 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 2258 } while (precisely_zero(startT - other->fTs[*nextEnd].fT));
1515 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2259 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
1516 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { 2260 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) {
1517 *unsortable = true; 2261 *unsortable = true;
1518 return NULL; 2262 return NULL;
1519 } 2263 }
1520 return other; 2264 return other;
1521 } 2265 }
1522 // more than one viable candidate -- measure angles to find best
1523 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
1524 SkASSERT(startIndex - endIndex != 0); 2266 SkASSERT(startIndex - endIndex != 0);
1525 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2267 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
1526 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; 2268 // more than one viable candidate -- measure angles to find best
1527 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp, &angles , &sorted); 2269
2270 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp);
1528 bool sortable = calcWinding != SK_NaN32; 2271 bool sortable = calcWinding != SK_NaN32;
1529 if (sortable && sorted.count() == 0) {
1530 // if no edge has a computed winding sum, we can go no further
1531 *unsortable = true;
1532 return NULL;
1533 }
1534 int angleCount = angles.count();
1535 int firstIndex = findStartingEdge(sorted, startIndex, end);
1536 SkASSERT(!sortable || firstIndex >= 0);
1537 #if DEBUG_SORT
1538 debugShowSort(__FUNCTION__, sorted, firstIndex, sortable);
1539 #endif
1540 if (!sortable) { 2272 if (!sortable) {
1541 *unsortable = true; 2273 *unsortable = true;
1542 return NULL; 2274 return NULL;
1543 } 2275 }
1544 SkASSERT(sorted[firstIndex]->segment() == this); 2276 SkOpAngle* angle = spanToAngle(end, startIndex);
1545 #if DEBUG_WINDING 2277 if (angle->unorderable()) {
1546 SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex, 2278 *unsortable = true;
1547 sorted[firstIndex]->sign()); 2279 return NULL;
2280 }
2281 #if DEBUG_SORT
2282 SkDebugf("%s\n", __FUNCTION__);
2283 angle->debugLoop();
1548 #endif 2284 #endif
1549 int sumMiWinding = updateWinding(endIndex, startIndex); 2285 int sumMiWinding = updateWinding(endIndex, startIndex);
1550 int sumSuWinding = updateOppWinding(endIndex, startIndex); 2286 int sumSuWinding = updateOppWinding(endIndex, startIndex);
1551 if (operand()) { 2287 if (operand()) {
1552 SkTSwap<int>(sumMiWinding, sumSuWinding); 2288 SkTSwap<int>(sumMiWinding, sumSuWinding);
1553 } 2289 }
1554 int nextIndex = firstIndex + 1; 2290 SkOpAngle* nextAngle = angle->next();
1555 int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
1556 const SkOpAngle* foundAngle = NULL; 2291 const SkOpAngle* foundAngle = NULL;
1557 bool foundDone = false; 2292 bool foundDone = false;
1558 // iterate through the angle, and compute everyone's winding 2293 // iterate through the angle, and compute everyone's winding
1559 SkOpSegment* nextSegment; 2294 SkOpSegment* nextSegment;
1560 int activeCount = 0; 2295 int activeCount = 0;
1561 do { 2296 do {
1562 SkASSERT(nextIndex != firstIndex);
1563 if (nextIndex == angleCount) {
1564 nextIndex = 0;
1565 }
1566 const SkOpAngle* nextAngle = sorted[nextIndex];
1567 nextSegment = nextAngle->segment(); 2297 nextSegment = nextAngle->segment();
1568 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
1569 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle ->start(), 2298 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle ->start(),
1570 nextAngle->end(), op, &sumMiWinding, &sumSuWinding, 2299 nextAngle->end(), op, &sumMiWinding, &sumSuWinding);
1571 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
1572 if (activeAngle) { 2300 if (activeAngle) {
1573 ++activeCount; 2301 ++activeCount;
1574 if (!foundAngle || (foundDone && activeCount & 1)) { 2302 if (!foundAngle || (foundDone && activeCount & 1)) {
1575 if (nextSegment->isTiny(nextAngle)) { 2303 if (nextSegment->isTiny(nextAngle)) {
1576 *unsortable = true; 2304 *unsortable = true;
1577 return NULL; 2305 return NULL;
1578 } 2306 }
1579 foundAngle = nextAngle; 2307 foundAngle = nextAngle;
1580 foundDone = nextSegment->done(nextAngle); 2308 foundDone = nextSegment->done(nextAngle);
1581 } 2309 }
1582 } 2310 }
1583 if (nextSegment->done()) { 2311 if (nextSegment->done()) {
1584 continue; 2312 continue;
1585 } 2313 }
1586 if (nextSegment->isTiny(nextAngle)) { 2314 if (nextSegment->isTiny(nextAngle)) {
1587 continue; 2315 continue;
1588 } 2316 }
1589 if (!activeAngle) { 2317 if (!activeAngle) {
1590 nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextAngle->e nd()); 2318 nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextAngle->e nd());
1591 } 2319 }
1592 SkOpSpan* last = nextAngle->lastMarked(); 2320 SkOpSpan* last = nextAngle->lastMarked();
1593 if (last) { 2321 if (last) {
2322 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
1594 *chase->append() = last; 2323 *chase->append() = last;
1595 #if DEBUG_WINDING 2324 #if DEBUG_WINDING
1596 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ , 2325 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ ,
1597 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum, 2326 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum,
1598 last->fSmall); 2327 last->fSmall);
1599 #endif 2328 #endif
1600 } 2329 }
1601 } while (++nextIndex != lastIndex); 2330 } while ((nextAngle = nextAngle->next()) != angle);
2331 #if DEBUG_ANGLE
2332 if (foundAngle) {
2333 foundAngle->debugSameAs(foundAngle);
2334 }
2335 #endif
2336
1602 markDoneBinary(SkMin32(startIndex, endIndex)); 2337 markDoneBinary(SkMin32(startIndex, endIndex));
1603 if (!foundAngle) { 2338 if (!foundAngle) {
1604 return NULL; 2339 return NULL;
1605 } 2340 }
1606 *nextStart = foundAngle->start(); 2341 *nextStart = foundAngle->start();
1607 *nextEnd = foundAngle->end(); 2342 *nextEnd = foundAngle->end();
1608 nextSegment = foundAngle->segment(); 2343 nextSegment = foundAngle->segment();
1609 #if DEBUG_WINDING 2344 #if DEBUG_WINDING
1610 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 2345 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
1611 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d); 2346 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1643 do { 2378 do {
1644 *nextEnd += step; 2379 *nextEnd += step;
1645 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 2380 } while (precisely_zero(startT - other->fTs[*nextEnd].fT));
1646 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2381 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
1647 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { 2382 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) {
1648 *unsortable = true; 2383 *unsortable = true;
1649 return NULL; 2384 return NULL;
1650 } 2385 }
1651 return other; 2386 return other;
1652 } 2387 }
1653 // more than one viable candidate -- measure angles to find best
1654 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
1655 SkASSERT(startIndex - endIndex != 0); 2388 SkASSERT(startIndex - endIndex != 0);
1656 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2389 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
1657 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; 2390 // more than one viable candidate -- measure angles to find best
1658 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding, &ang les, &sorted); 2391
2392 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding);
1659 bool sortable = calcWinding != SK_NaN32; 2393 bool sortable = calcWinding != SK_NaN32;
1660 int angleCount = angles.count();
1661 int firstIndex = findStartingEdge(sorted, startIndex, end);
1662 SkASSERT(!sortable || firstIndex >= 0);
1663 #if DEBUG_SORT
1664 debugShowSort(__FUNCTION__, sorted, firstIndex, sortable);
1665 #endif
1666 if (!sortable) { 2394 if (!sortable) {
1667 *unsortable = true; 2395 *unsortable = true;
1668 return NULL; 2396 return NULL;
1669 } 2397 }
1670 SkASSERT(sorted[firstIndex]->segment() == this); 2398 SkOpAngle* angle = spanToAngle(end, startIndex);
1671 #if DEBUG_WINDING 2399 #if DEBUG_SORT
1672 SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex, 2400 SkDebugf("%s\n", __FUNCTION__);
1673 sorted[firstIndex]->sign()); 2401 angle->debugLoop();
1674 #endif 2402 #endif
1675 int sumWinding = updateWinding(endIndex, startIndex); 2403 int sumWinding = updateWinding(endIndex, startIndex);
1676 int nextIndex = firstIndex + 1; 2404 SkOpAngle* nextAngle = angle->next();
1677 int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
1678 const SkOpAngle* foundAngle = NULL; 2405 const SkOpAngle* foundAngle = NULL;
1679 bool foundDone = false; 2406 bool foundDone = false;
1680 // iterate through the angle, and compute everyone's winding
1681 SkOpSegment* nextSegment; 2407 SkOpSegment* nextSegment;
1682 int activeCount = 0; 2408 int activeCount = 0;
1683 do { 2409 do {
1684 SkASSERT(nextIndex != firstIndex);
1685 if (nextIndex == angleCount) {
1686 nextIndex = 0;
1687 }
1688 const SkOpAngle* nextAngle = sorted[nextIndex];
1689 nextSegment = nextAngle->segment(); 2410 nextSegment = nextAngle->segment();
1690 int maxWinding;
1691 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn gle->end(), 2411 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn gle->end(),
1692 &maxWinding, &sumWinding); 2412 &sumWinding);
1693 if (activeAngle) { 2413 if (activeAngle) {
1694 ++activeCount; 2414 ++activeCount;
1695 if (!foundAngle || (foundDone && activeCount & 1)) { 2415 if (!foundAngle || (foundDone && activeCount & 1)) {
1696 if (nextSegment->isTiny(nextAngle)) { 2416 if (nextSegment->isTiny(nextAngle)) {
1697 *unsortable = true; 2417 *unsortable = true;
1698 return NULL; 2418 return NULL;
1699 } 2419 }
1700 foundAngle = nextAngle; 2420 foundAngle = nextAngle;
1701 foundDone = nextSegment->done(nextAngle); 2421 foundDone = nextSegment->done(nextAngle);
1702 } 2422 }
1703 } 2423 }
1704 if (nextSegment->done()) { 2424 if (nextSegment->done()) {
1705 continue; 2425 continue;
1706 } 2426 }
1707 if (nextSegment->isTiny(nextAngle)) { 2427 if (nextSegment->isTiny(nextAngle)) {
1708 continue; 2428 continue;
1709 } 2429 }
1710 if (!activeAngle) { 2430 if (!activeAngle) {
1711 nextSegment->markAndChaseDoneUnary(nextAngle->start(), nextAngle->en d()); 2431 nextSegment->markAndChaseDoneUnary(nextAngle->start(), nextAngle->en d());
1712 } 2432 }
1713 SkOpSpan* last = nextAngle->lastMarked(); 2433 SkOpSpan* last = nextAngle->lastMarked();
1714 if (last) { 2434 if (last) {
2435 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
2436 // assert here that span isn't already in array
1715 *chase->append() = last; 2437 *chase->append() = last;
1716 #if DEBUG_WINDING 2438 #if DEBUG_WINDING
1717 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ , 2439 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ ,
1718 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum, 2440 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum,
1719 last->fSmall); 2441 last->fSmall);
1720 #endif 2442 #endif
1721 } 2443 }
1722 } while (++nextIndex != lastIndex); 2444 } while ((nextAngle = nextAngle->next()) != angle);
1723 markDoneUnary(SkMin32(startIndex, endIndex)); 2445 markDoneUnary(SkMin32(startIndex, endIndex));
1724 if (!foundAngle) { 2446 if (!foundAngle) {
1725 return NULL; 2447 return NULL;
1726 } 2448 }
1727 *nextStart = foundAngle->start(); 2449 *nextStart = foundAngle->start();
1728 *nextEnd = foundAngle->end(); 2450 *nextEnd = foundAngle->end();
1729 nextSegment = foundAngle->segment(); 2451 nextSegment = foundAngle->segment();
1730 #if DEBUG_WINDING 2452 #if DEBUG_WINDING
1731 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 2453 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
1732 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d); 2454 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d);
1733 #endif 2455 #endif
1734 return nextSegment; 2456 return nextSegment;
1735 } 2457 }
1736 2458
1737 SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort able) { 2459 SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort able) {
1738 const int startIndex = *nextStart; 2460 const int startIndex = *nextStart;
1739 const int endIndex = *nextEnd; 2461 const int endIndex = *nextEnd;
1740 SkASSERT(startIndex != endIndex); 2462 SkASSERT(startIndex != endIndex);
1741 SkDEBUGCODE(int count = fTs.count()); 2463 SkDEBUGCODE(int count = fTs.count());
1742 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); 2464 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
1743 int step = SkSign32(endIndex - startIndex); 2465 int step = SkSign32(endIndex - startIndex);
1744 int end = nextExactSpan(startIndex, step); 2466 int end = nextExactSpan(startIndex, step);
1745 SkASSERT(end >= 0); 2467 SkASSERT(end >= 0);
1746 SkOpSpan* endSpan = &fTs[end]; 2468 SkOpSpan* endSpan = &fTs[end];
1747 SkOpSegment* other; 2469 SkOpSegment* other;
1748 if (isSimple(end)) { 2470 // Detect cases where all the ends canceled out (e.g.,
2471 // there is no angle) and therefore there's only one valid connection
2472 if (isSimple(end) || !spanToAngle(end, startIndex)) {
1749 #if DEBUG_WINDING 2473 #if DEBUG_WINDING
1750 SkDebugf("%s simple\n", __FUNCTION__); 2474 SkDebugf("%s simple\n", __FUNCTION__);
1751 #endif 2475 #endif
1752 int min = SkMin32(startIndex, endIndex); 2476 int min = SkMin32(startIndex, endIndex);
1753 if (fTs[min].fDone) { 2477 if (fTs[min].fDone) {
1754 return NULL; 2478 return NULL;
1755 } 2479 }
1756 markDone(min, 1); 2480 markDone(min, 1);
1757 other = endSpan->fOther; 2481 other = endSpan->fOther;
1758 *nextStart = endSpan->fOtherIndex; 2482 *nextStart = endSpan->fOtherIndex;
(...skipping 13 matching lines...) Expand all
1772 if (other->fTs[SkMin32(*nextStart, *nextEnd)].fWindValue) { 2496 if (other->fTs[SkMin32(*nextStart, *nextEnd)].fWindValue) {
1773 break; 2497 break;
1774 } 2498 }
1775 SkASSERT(firstLoop); 2499 SkASSERT(firstLoop);
1776 SkDEBUGCODE(firstLoop = false;) 2500 SkDEBUGCODE(firstLoop = false;)
1777 step = -step; 2501 step = -step;
1778 } while (true); 2502 } while (true);
1779 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2503 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
1780 return other; 2504 return other;
1781 } 2505 }
1782 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
1783 SkASSERT(startIndex - endIndex != 0); 2506 SkASSERT(startIndex - endIndex != 0);
1784 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2507 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
1785 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; 2508 // parallel block above with presorted version
1786 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryXor, &angles, &sorted); 2509 SkOpAngle* angle = spanToAngle(end, startIndex);
1787 bool sortable = calcWinding != SK_NaN32; 2510 SkASSERT(angle);
1788 int angleCount = angles.count();
1789 int firstIndex = findStartingEdge(sorted, startIndex, end);
1790 SkASSERT(!sortable || firstIndex >= 0);
1791 #if DEBUG_SORT 2511 #if DEBUG_SORT
1792 debugShowSort(__FUNCTION__, sorted, firstIndex, 0, 0, sortable); 2512 SkDebugf("%s\n", __FUNCTION__);
2513 angle->debugLoop();
1793 #endif 2514 #endif
1794 if (!sortable) { 2515 SkOpAngle* nextAngle = angle->next();
1795 *unsortable = true;
1796 return NULL;
1797 }
1798 SkASSERT(sorted[firstIndex]->segment() == this);
1799 #if DEBUG_WINDING
1800 SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
1801 sorted[firstIndex]->sign());
1802 #endif
1803 int nextIndex = firstIndex + 1;
1804 int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
1805 const SkOpAngle* foundAngle = NULL; 2516 const SkOpAngle* foundAngle = NULL;
1806 bool foundDone = false; 2517 bool foundDone = false;
1807 SkOpSegment* nextSegment; 2518 SkOpSegment* nextSegment;
1808 int activeCount = 0; 2519 int activeCount = 0;
1809 do { 2520 do {
1810 SkASSERT(nextIndex != firstIndex);
1811 if (nextIndex == angleCount) {
1812 nextIndex = 0;
1813 }
1814 const SkOpAngle* nextAngle = sorted[nextIndex];
1815 nextSegment = nextAngle->segment(); 2521 nextSegment = nextAngle->segment();
1816 ++activeCount; 2522 ++activeCount;
1817 if (!foundAngle || (foundDone && activeCount & 1)) { 2523 if (!foundAngle || (foundDone && activeCount & 1)) {
1818 if (nextSegment->isTiny(nextAngle)) { 2524 if (nextSegment->isTiny(nextAngle)) {
1819 *unsortable = true; 2525 *unsortable = true;
1820 return NULL; 2526 return NULL;
1821 } 2527 }
1822 foundAngle = nextAngle; 2528 foundAngle = nextAngle;
1823 foundDone = nextSegment->done(nextAngle); 2529 if (!(foundDone = nextSegment->done(nextAngle))) {
2530 break;
2531 }
1824 } 2532 }
1825 if (nextSegment->done()) { 2533 nextAngle = nextAngle->next();
1826 continue; 2534 } while (nextAngle != angle);
1827 }
1828 } while (++nextIndex != lastIndex);
1829 markDone(SkMin32(startIndex, endIndex), 1); 2535 markDone(SkMin32(startIndex, endIndex), 1);
1830 if (!foundAngle) { 2536 if (!foundAngle) {
1831 return NULL; 2537 return NULL;
1832 } 2538 }
1833 *nextStart = foundAngle->start(); 2539 *nextStart = foundAngle->start();
1834 *nextEnd = foundAngle->end(); 2540 *nextEnd = foundAngle->end();
1835 nextSegment = foundAngle->segment(); 2541 nextSegment = foundAngle->segment();
1836 #if DEBUG_WINDING 2542 #if DEBUG_WINDING
1837 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 2543 SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
1838 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d); 2544 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d);
1839 #endif 2545 #endif
1840 return nextSegment; 2546 return nextSegment;
1841 } 2547 }
1842 2548
1843 int SkOpSegment::findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, int end) { 2549 int SkOpSegment::findStartSpan(int startIndex) const {
1844 int angleCount = sorted.count(); 2550 int index = startIndex;
1845 int firstIndex = -1; 2551 const SkOpSpan* span = &fTs[index];
1846 for (int angleIndex = 0; angleIndex < angleCount; ++angleIndex) { 2552 const SkPoint& firstPt = span->fPt;
1847 const SkOpAngle* angle = sorted[angleIndex]; 2553 double firstT = span->fT;
1848 if (angle->segment() == this && angle->start() == end && 2554 do {
1849 angle->end() == start) { 2555 if (index > 0) {
1850 firstIndex = angleIndex; 2556 if (span->fT != firstT) {
1851 break; 2557 break;
2558 }
2559 if (!SkDPoint::ApproximatelyEqual(firstPt, fTs[index].fPt)) {
2560 return -1;
2561 }
1852 } 2562 }
1853 } 2563 ++index;
1854 return firstIndex; 2564 if (span->fTiny) {
2565 if (!SkDPoint::ApproximatelyEqual(firstPt, fTs[index].fPt)) {
2566 return -1;
2567 }
2568 firstT = fTs[index++].fT;
2569 }
2570 span = &fTs[index];
2571 } while (true);
2572 return index;
1855 } 2573 }
1856 2574
1857 int SkOpSegment::findT(double t, const SkOpSegment* match) const { 2575 int SkOpSegment::findExactT(double t, const SkOpSegment* match) const {
1858 int count = this->count(); 2576 int count = this->count();
1859 for (int index = 0; index < count; ++index) { 2577 for (int index = 0; index < count; ++index) {
1860 const SkOpSpan& span = fTs[index]; 2578 const SkOpSpan& span = fTs[index];
1861 if (span.fT == t && span.fOther == match) { 2579 if (span.fT == t && span.fOther == match) {
1862 return index; 2580 return index;
1863 } 2581 }
1864 } 2582 }
1865 SkASSERT(0); 2583 SkASSERT(0);
1866 return -1; 2584 return -1;
1867 } 2585 }
1868 2586
1869 // FIXME: either: 2587 int SkOpSegment::findT(double t, const SkOpSegment* match) const {
1870 // a) mark spans with either end unsortable as done, or 2588 int count = this->count();
1871 // b) rewrite findTop / findTopSegment / findTopContour to iterate further 2589 for (int index = 0; index < count; ++index) {
1872 // when encountering an unsortable span 2590 const SkOpSpan& span = fTs[index];
2591 if (approximately_equal_orderable(span.fT, t) && span.fOther == match) {
2592 return index;
2593 }
2594 }
2595 SkASSERT(0);
2596 return -1;
2597 }
1873 2598
1874 // OPTIMIZATION : for a pair of lines, can we compute points at T (cached) 2599 SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort able) {
1875 // and use more concise logic like the old edge walker code?
1876 // FIXME: this needs to deal with coincident edges
1877 SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort able,
1878 bool onlySortable) {
1879 // iterate through T intersections and return topmost 2600 // iterate through T intersections and return topmost
1880 // topmost tangent from y-min to first pt is closer to horizontal 2601 // topmost tangent from y-min to first pt is closer to horizontal
1881 SkASSERT(!done()); 2602 SkASSERT(!done());
1882 int firstT = -1; 2603 int firstT = -1;
1883 /* SkPoint topPt = */ activeLeftTop(onlySortable, &firstT); 2604 /* SkPoint topPt = */ activeLeftTop(true, &firstT);
1884 if (firstT < 0) { 2605 if (firstT < 0) {
1885 *unsortable = true; 2606 *unsortable = true;
1886 firstT = 0; 2607 firstT = 0;
1887 while (fTs[firstT].fDone) { 2608 while (fTs[firstT].fDone) {
1888 SkASSERT(firstT < fTs.count()); 2609 SkASSERT(firstT < fTs.count());
1889 ++firstT; 2610 ++firstT;
1890 } 2611 }
1891 *tIndexPtr = firstT; 2612 *tIndexPtr = firstT;
1892 *endIndexPtr = nextExactSpan(firstT, 1); 2613 *endIndexPtr = nextExactSpan(firstT, 1);
1893 return this; 2614 return this;
1894 } 2615 }
1895 // sort the edges to find the leftmost 2616 // sort the edges to find the leftmost
1896 int step = 1; 2617 int step = 1;
1897 int end = nextSpan(firstT, step); 2618 int end;
1898 if (end == -1) { 2619 if (span(firstT).fDone || (end = nextSpan(firstT, step)) == -1) {
1899 step = -1; 2620 step = -1;
1900 end = nextSpan(firstT, step); 2621 end = nextSpan(firstT, step);
1901 SkASSERT(end != -1); 2622 SkASSERT(end != -1);
1902 } 2623 }
1903 // if the topmost T is not on end, or is three-way or more, find left 2624 // if the topmost T is not on end, or is three-way or more, find left
1904 // look for left-ness from tLeft to firstT (matching y of other) 2625 // look for left-ness from tLeft to firstT (matching y of other)
1905 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
1906 SkASSERT(firstT - end != 0); 2626 SkASSERT(firstT - end != 0);
1907 addTwoAngles(end, firstT, &angles); 2627 SkOpAngle* markAngle = spanToAngle(firstT, end);
1908 if (!buildAngles(firstT, &angles, true) && onlySortable) { 2628 if (!markAngle) {
1909 // *unsortable = true; 2629 markAngle = addSingletonAngles(firstT, step);
1910 // return NULL;
1911 } 2630 }
1912 SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; 2631 markAngle->markStops();
1913 bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMayBeUnordered_Sor tAngleKind); 2632 const SkOpAngle* baseAngle = markAngle->findFirst();
1914 if (onlySortable && !sortable) { 2633 if (!baseAngle) {
1915 *unsortable = true; 2634 return NULL; // nothing to do
1916 return NULL;
1917 } 2635 }
1918 int first = SK_MaxS32;
1919 SkScalar top = SK_ScalarMax; 2636 SkScalar top = SK_ScalarMax;
1920 int count = sorted.count(); 2637 const SkOpAngle* firstAngle = NULL;
1921 for (int index = 0; index < count; ++index) { 2638 const SkOpAngle* angle = baseAngle;
1922 const SkOpAngle* angle = sorted[index]; 2639 do {
1923 if (onlySortable && angle->unorderable()) { 2640 if (!angle->unorderable()) {
1924 continue; 2641 SkOpSegment* next = angle->segment();
2642 SkPathOpsBounds bounds;
2643 next->subDivideBounds(angle->end(), angle->start(), &bounds);
2644 if (approximately_greater(top, bounds.fTop)) {
2645 top = bounds.fTop;
2646 firstAngle = angle;
2647 }
1925 } 2648 }
1926 SkOpSegment* next = angle->segment(); 2649 angle = angle->next();
1927 SkPathOpsBounds bounds; 2650 } while (angle != baseAngle);
1928 next->subDivideBounds(angle->end(), angle->start(), &bounds); 2651 SkASSERT(firstAngle);
1929 if (approximately_greater(top, bounds.fTop)) { 2652 #if DEBUG_SORT
1930 top = bounds.fTop; 2653 SkDebugf("%s\n", __FUNCTION__);
1931 first = index; 2654 firstAngle->debugLoop();
1932 }
1933 }
1934 SkASSERT(first < SK_MaxS32);
1935 #if DEBUG_SORT // || DEBUG_SWAP_TOP
1936 sorted[first]->segment()->debugShowSort(__FUNCTION__, sorted, first, 0, 0, s ortable);
1937 #endif 2655 #endif
1938 // skip edges that have already been processed 2656 // skip edges that have already been processed
1939 firstT = first - 1; 2657 angle = firstAngle;
1940 SkOpSegment* leftSegment; 2658 SkOpSegment* leftSegment;
1941 do { 2659 do {
1942 if (++firstT == count) { 2660 // SkASSERT(!angle->unsortable());
1943 firstT = 0;
1944 }
1945 const SkOpAngle* angle = sorted[firstT];
1946 SkASSERT(!onlySortable || !angle->unsortable());
1947 leftSegment = angle->segment(); 2661 leftSegment = angle->segment();
1948 *tIndexPtr = angle->end(); 2662 *tIndexPtr = angle->end();
1949 *endIndexPtr = angle->start(); 2663 *endIndexPtr = angle->start();
2664 angle = angle->next();
1950 } while (leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fDone); 2665 } while (leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fDone);
1951 if (leftSegment->verb() >= SkPath::kQuad_Verb) { 2666 if (leftSegment->verb() >= SkPath::kQuad_Verb) {
1952 const int tIndex = *tIndexPtr; 2667 const int tIndex = *tIndexPtr;
1953 const int endIndex = *endIndexPtr; 2668 const int endIndex = *endIndexPtr;
1954 if (!leftSegment->clockwise(tIndex, endIndex)) { 2669 if (!leftSegment->clockwise(tIndex, endIndex)) {
1955 bool swap = !leftSegment->monotonicInY(tIndex, endIndex) 2670 bool swap = !leftSegment->monotonicInY(tIndex, endIndex)
1956 && !leftSegment->serpentine(tIndex, endIndex); 2671 && !leftSegment->serpentine(tIndex, endIndex);
1957 #if DEBUG_SWAP_TOP 2672 #if DEBUG_SWAP_TOP
1958 SkDebugf("%s swap=%d serpentine=%d containedByEnds=%d monotonic=%d\n ", __FUNCTION__, 2673 SkDebugf("%s swap=%d serpentine=%d containedByEnds=%d monotonic=%d\n ", __FUNCTION__,
1959 swap, 2674 swap,
1960 leftSegment->serpentine(tIndex, endIndex), 2675 leftSegment->serpentine(tIndex, endIndex),
1961 leftSegment->controlsContainedByEnds(tIndex, endIndex), 2676 leftSegment->controlsContainedByEnds(tIndex, endIndex),
1962 leftSegment->monotonicInY(tIndex, endIndex)); 2677 leftSegment->monotonicInY(tIndex, endIndex));
1963 #endif 2678 #endif
1964 if (swap) { 2679 if (swap) {
1965 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first 2680 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first
1966 // sorted but merely the first not already processed (i.e., not done) 2681 // sorted but merely the first not already processed (i.e., not done)
1967 SkTSwap(*tIndexPtr, *endIndexPtr); 2682 SkTSwap(*tIndexPtr, *endIndexPtr);
1968 } 2683 }
1969 } 2684 }
1970 } 2685 }
1971 SkASSERT(!leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fTiny); 2686 SkASSERT(!leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fTiny);
1972 return leftSegment; 2687 return leftSegment;
1973 } 2688 }
1974 2689
2690 int SkOpSegment::firstActive(int tIndex) const {
2691 while (fTs[tIndex].fTiny) {
2692 SkASSERT(!isCanceled(tIndex));
2693 ++tIndex;
2694 }
2695 return tIndex;
2696 }
2697
1975 // FIXME: not crazy about this 2698 // FIXME: not crazy about this
1976 // when the intersections are performed, the other index is into an 2699 // when the intersections are performed, the other index is into an
1977 // incomplete array. As the array grows, the indices become incorrect 2700 // incomplete array. As the array grows, the indices become incorrect
1978 // while the following fixes the indices up again, it isn't smart about 2701 // while the following fixes the indices up again, it isn't smart about
1979 // skipping segments whose indices are already correct 2702 // skipping segments whose indices are already correct
1980 // assuming we leave the code that wrote the index in the first place 2703 // assuming we leave the code that wrote the index in the first place
1981 // FIXME: if called after remove, this needs to correct tiny 2704 // FIXME: if called after remove, this needs to correct tiny
1982 void SkOpSegment::fixOtherTIndex() { 2705 void SkOpSegment::fixOtherTIndex() {
1983 int iCount = fTs.count(); 2706 int iCount = fTs.count();
1984 for (int i = 0; i < iCount; ++i) { 2707 for (int i = 0; i < iCount; ++i) {
(...skipping 13 matching lines...) Expand all
1998 SkASSERT(iSpan.fOtherIndex >= 0); 2721 SkASSERT(iSpan.fOtherIndex >= 0);
1999 } 2722 }
2000 } 2723 }
2001 2724
2002 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo l evenOdd) { 2725 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo l evenOdd) {
2003 fDoneSpans = 0; 2726 fDoneSpans = 0;
2004 fOperand = operand; 2727 fOperand = operand;
2005 fXor = evenOdd; 2728 fXor = evenOdd;
2006 fPts = pts; 2729 fPts = pts;
2007 fVerb = verb; 2730 fVerb = verb;
2731 fLoop = fSmall = fTiny = false;
2008 } 2732 }
2009 2733
2010 void SkOpSegment::initWinding(int start, int end) { 2734 void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIn cludeType) {
2011 int local = spanSign(start, end); 2735 int local = spanSign(start, end);
2012 int oppLocal = oppSign(start, end); 2736 if (angleIncludeType == SkOpAngle::kBinarySingle) {
2013 (void) markAndChaseWinding(start, end, local, oppLocal); 2737 int oppLocal = oppSign(start, end);
2738 (void) markAndChaseWinding(start, end, local, oppLocal);
2014 // OPTIMIZATION: the reverse mark and chase could skip the first marking 2739 // OPTIMIZATION: the reverse mark and chase could skip the first marking
2015 (void) markAndChaseWinding(end, start, local, oppLocal); 2740 (void) markAndChaseWinding(end, start, local, oppLocal);
2741 } else {
2742 (void) markAndChaseWinding(start, end, local);
2743 // OPTIMIZATION: the reverse mark and chase could skip the first marking
2744 (void) markAndChaseWinding(end, start, local);
2745 }
2016 } 2746 }
2017 2747
2018 /* 2748 /*
2019 when we start with a vertical intersect, we try to use the dx to determine if th e edge is to 2749 when we start with a vertical intersect, we try to use the dx to determine if th e edge is to
2020 the left or the right of vertical. This determines if we need to add the span's 2750 the left or the right of vertical. This determines if we need to add the span's
2021 sign or not. However, this isn't enough. 2751 sign or not. However, this isn't enough.
2022 If the supplied sign (winding) is zero, then we didn't hit another vertical span , so dx is needed. 2752 If the supplied sign (winding) is zero, then we didn't hit another vertical span , so dx is needed.
2023 If there was a winding, then it may or may not need adjusting. If the span the w inding was borrowed 2753 If there was a winding, then it may or may not need adjusting. If the span the w inding was borrowed
2024 from has the same x direction as this span, the winding should change. If the dx is opposite, then 2754 from has the same x direction as this span, the winding should change. If the dx is opposite, then
2025 the same winding is shared by both. 2755 the same winding is shared by both.
2026 */ 2756 */
2027 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc alar hitDx, 2757 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc alar hitDx,
2028 int oppWind, SkScalar hitOppDx) { 2758 int oppWind, SkScalar hitOppDx) {
2029 SkASSERT(hitDx || !winding); 2759 SkASSERT(hitDx || !winding);
2030 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 2760 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX;
2031 SkASSERT(dx); 2761 SkASSERT(dx);
2032 int windVal = windValue(SkMin32(start, end)); 2762 int windVal = windValue(SkMin32(start, end));
2033 #if DEBUG_WINDING_AT_T 2763 #if DEBUG_WINDING_AT_T
2034 SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding , 2764 SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding ,
2035 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); 2765 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal);
2036 #endif 2766 #endif
2037 if (!winding) { 2767 int sideWind = winding + (dx < 0 ? windVal : -windVal);
2038 winding = dx < 0 ? windVal : -windVal; 2768 if (abs(winding) < abs(sideWind)) {
2039 } else if (winding * dx < 0) { 2769 winding = sideWind;
2040 int sideWind = winding + (dx < 0 ? windVal : -windVal);
2041 if (abs(winding) < abs(sideWind)) {
2042 winding = sideWind;
2043 }
2044 } 2770 }
2045 #if DEBUG_WINDING_AT_T 2771 #if DEBUG_WINDING_AT_T
2046 SkDebugf(" winding=%d\n", winding); 2772 SkDebugf(" winding=%d\n", winding);
2047 #endif 2773 #endif
2048 SkDEBUGCODE(int oppLocal = oppSign(start, end)); 2774 SkDEBUGCODE(int oppLocal = oppSign(start, end));
2049 SkASSERT(hitOppDx || !oppWind || !oppLocal); 2775 SkASSERT(hitOppDx || !oppWind || !oppLocal);
2050 int oppWindVal = oppValue(SkMin32(start, end)); 2776 int oppWindVal = oppValue(SkMin32(start, end));
2051 if (!oppWind) { 2777 if (!oppWind) {
2052 oppWind = dx < 0 ? oppWindVal : -oppWindVal; 2778 oppWind = dx < 0 ? oppWindVal : -oppWindVal;
2053 } else if (hitOppDx * dx >= 0) { 2779 } else if (hitOppDx * dx >= 0) {
2054 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); 2780 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal);
2055 if (abs(oppWind) < abs(oppSideWind)) { 2781 if (abs(oppWind) < abs(oppSideWind)) {
2056 oppWind = oppSideWind; 2782 oppWind = oppSideWind;
2057 } 2783 }
2058 } 2784 }
2059 (void) markAndChaseWinding(start, end, winding, oppWind); 2785 (void) markAndChaseWinding(start, end, winding, oppWind);
2060 // OPTIMIZATION: the reverse mark and chase could skip the first marking 2786 // OPTIMIZATION: the reverse mark and chase could skip the first marking
2061 (void) markAndChaseWinding(end, start, winding, oppWind); 2787 (void) markAndChaseWinding(end, start, winding, oppWind);
2062 } 2788 }
2063 2789
2790 bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPt r) const {
2791 if (!baseAngle->inLoop()) {
2792 return false;
2793 }
2794 int index = *indexPtr;
2795 int froIndex = fTs[index].fFromAngleIndex;
2796 int toIndex = fTs[index].fToAngleIndex;
2797 while (++index < spanCount) {
2798 int nextFro = fTs[index].fFromAngleIndex;
2799 int nextTo = fTs[index].fToAngleIndex;
2800 if (froIndex != nextFro || toIndex != nextTo) {
2801 break;
2802 }
2803 }
2804 *indexPtr = index;
2805 return true;
2806 }
2807
2064 // OPTIMIZE: successive calls could start were the last leaves off 2808 // OPTIMIZE: successive calls could start were the last leaves off
2065 // or calls could specialize to walk forwards or backwards 2809 // or calls could specialize to walk forwards or backwards
2066 bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const { 2810 bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const {
2067 size_t tCount = fTs.count(); 2811 int tCount = fTs.count();
2068 for (size_t index = 0; index < tCount; ++index) { 2812 for (int index = 0; index < tCount; ++index) {
2069 const SkOpSpan& span = fTs[index]; 2813 const SkOpSpan& span = fTs[index];
2070 if (approximately_zero(startT - span.fT) && pt == span.fPt) { 2814 if (approximately_zero(startT - span.fT) && pt == span.fPt) {
2071 return false; 2815 return false;
2072 } 2816 }
2073 } 2817 }
2074 return true; 2818 return true;
2075 } 2819 }
2076 2820
2077 bool SkOpSegment::isSimple(int end) const { 2821 bool SkOpSegment::isSimple(int end) const {
2822 #if 1
2078 int count = fTs.count(); 2823 int count = fTs.count();
2079 if (count == 2) { 2824 if (count == 2) {
2080 return true; 2825 return true;
2081 } 2826 }
2082 double t = fTs[end].fT; 2827 double t = fTs[end].fT;
2083 if (approximately_less_than_zero(t)) { 2828 if (approximately_less_than_zero(t)) {
2084 return !approximately_less_than_zero(fTs[1].fT); 2829 return !approximately_less_than_zero(fTs[1].fT);
2085 } 2830 }
2086 if (approximately_greater_than_one(t)) { 2831 if (approximately_greater_than_one(t)) {
2087 return !approximately_greater_than_one(fTs[count - 2].fT); 2832 return !approximately_greater_than_one(fTs[count - 2].fT);
2088 } 2833 }
2089 return false; 2834 return false;
2835 #else
2836 // OPTIMIZE: code could be rejiggered to use this simpler test. To make this work, a little
2837 // more logic is required to ignore the dangling canceled out spans
2838 const SkOpSpan& span = fTs[end];
2839 return span.fFromAngleIndex < 0 && span.fToAngleIndex < 0;
2840 #endif
2841 }
2842
2843 bool SkOpSegment::isSmall(const SkOpAngle* angle) const {
2844 int start = angle->start();
2845 int end = angle->end();
2846 const SkOpSpan& mSpan = fTs[SkMin32(start, end)];
2847 return mSpan.fSmall;
2090 } 2848 }
2091 2849
2092 bool SkOpSegment::isTiny(const SkOpAngle* angle) const { 2850 bool SkOpSegment::isTiny(const SkOpAngle* angle) const {
2093 int start = angle->start(); 2851 int start = angle->start();
2094 int end = angle->end(); 2852 int end = angle->end();
2095 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; 2853 const SkOpSpan& mSpan = fTs[SkMin32(start, end)];
2096 return mSpan.fTiny; 2854 return mSpan.fTiny;
2097 } 2855 }
2098 2856
2099 bool SkOpSegment::isTiny(int index) const { 2857 bool SkOpSegment::isTiny(int index) const {
2100 return fTs[index].fTiny; 2858 return fTs[index].fTiny;
2101 } 2859 }
2102 2860
2103 // look pair of active edges going away from coincident edge 2861 // look pair of active edges going away from coincident edge
2104 // one of them should be the continuation of other 2862 // one of them should be the continuation of other
2105 // if both are active, look to see if they both the connect to another coinciden t pair 2863 // if both are active, look to see if they both the connect to another coinciden t pair
2106 // if one at least one is a line, then make the pair coincident 2864 // if at least one is a line, then make the pair coincident
2107 // if neither is a line, test for coincidence 2865 // if neither is a line, test for coincidence
2108 bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, int step, 2866 bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, int step, b ool cancel) {
2109 bool cancel) {
2110 int otherTIndex = other->findT(otherT, this); 2867 int otherTIndex = other->findT(otherT, this);
2111 int next = other->nextExactSpan(otherTIndex, step); 2868 int next = other->nextExactSpan(otherTIndex, step);
2112 int otherMin = SkTMin(otherTIndex, next); 2869 int otherMin = SkMin32(otherTIndex, next);
2113 int otherWind = other->span(otherMin).fWindValue; 2870 int otherWind = other->span(otherMin).fWindValue;
2114 if (otherWind == 0) { 2871 if (otherWind == 0) {
2115 return false; 2872 return false;
2116 } 2873 }
2117 SkASSERT(next >= 0); 2874 SkASSERT(next >= 0);
2118 int tIndex = 0; 2875 int tIndex = 0;
2119 do { 2876 do {
2120 SkOpSpan* test = &fTs[tIndex]; 2877 SkOpSpan* test = &fTs[tIndex];
2121 SkASSERT(test->fT == 0); 2878 SkASSERT(test->fT == 0);
2122 if (test->fOther == other || test->fOtherT != 1) { 2879 if (test->fOther == other || test->fOtherT != 1) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2164 SkOpSegment* other = this; 2921 SkOpSegment* other = this;
2165 while ((other = other->nextChase(&index, step, &min, &last))) { 2922 while ((other = other->nextChase(&index, step, &min, &last))) {
2166 if (other->done()) { 2923 if (other->done()) {
2167 return NULL; 2924 return NULL;
2168 } 2925 }
2169 other->markDoneUnary(min); 2926 other->markDoneUnary(min);
2170 } 2927 }
2171 return last; 2928 return last;
2172 } 2929 }
2173 2930
2174 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, const int win ding) { 2931 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) {
2175 int index = angle->start(); 2932 int index = angle->start();
2176 int endIndex = angle->end(); 2933 int endIndex = angle->end();
2177 int step = SkSign32(endIndex - index); 2934 int step = SkSign32(endIndex - index);
2178 int min = SkMin32(index, endIndex); 2935 int min = SkMin32(index, endIndex);
2179 markWinding(min, winding); 2936 markWinding(min, winding);
2180 SkOpSpan* last; 2937 SkOpSpan* last;
2181 SkOpSegment* other = this; 2938 SkOpSegment* other = this;
2182 while ((other = other->nextChase(&index, step, &min, &last))) { 2939 while ((other = other->nextChase(&index, step, &min, &last))) {
2183 if (other->fTs[min].fWindSum != SK_MinS32) { 2940 if (other->fTs[min].fWindSum != SK_MinS32) {
2184 SkASSERT(other->fTs[min].fWindSum == winding); 2941 SkASSERT(other->fTs[min].fWindSum == winding);
2185 return NULL; 2942 return NULL;
2186 } 2943 }
2187 other->markWinding(min, winding); 2944 other->markWinding(min, winding);
2188 } 2945 }
2189 return last; 2946 return last;
2190 } 2947 }
2191 2948
2949 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding) {
2950 int min = SkMin32(index, endIndex);
2951 int step = SkSign32(endIndex - index);
2952 markWinding(min, winding);
2953 SkOpSpan* last;
2954 SkOpSegment* other = this;
2955 while ((other = other->nextChase(&index, step, &min, &last))) {
2956 if (other->fTs[min].fWindSum != SK_MinS32) {
2957 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p);
2958 return NULL;
2959 }
2960 other->markWinding(min, winding);
2961 }
2962 return last;
2963 }
2964
2192 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) { 2965 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) {
2193 int min = SkMin32(index, endIndex); 2966 int min = SkMin32(index, endIndex);
2194 int step = SkSign32(endIndex - index); 2967 int step = SkSign32(endIndex - index);
2195 markWinding(min, winding, oppWinding); 2968 markWinding(min, winding, oppWinding);
2196 SkOpSpan* last; 2969 SkOpSpan* last;
2197 SkOpSegment* other = this; 2970 SkOpSegment* other = this;
2198 while ((other = other->nextChase(&index, step, &min, &last))) { 2971 while ((other = other->nextChase(&index, step, &min, &last))) {
2199 if (other->fTs[min].fWindSum != SK_MinS32) { 2972 if (other->fTs[min].fWindSum != SK_MinS32) {
2200 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p); 2973 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p);
2201 return NULL; 2974 return NULL;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2258 // SkASSERT(!done()); 3031 // SkASSERT(!done());
2259 SkASSERT(winding); 3032 SkASSERT(winding);
2260 double referenceT = fTs[index].fT; 3033 double referenceT = fTs[index].fT;
2261 int lesser = index; 3034 int lesser = index;
2262 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 3035 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2263 markOneDone(__FUNCTION__, lesser, winding); 3036 markOneDone(__FUNCTION__, lesser, winding);
2264 } 3037 }
2265 do { 3038 do {
2266 markOneDone(__FUNCTION__, index, winding); 3039 markOneDone(__FUNCTION__, index, winding);
2267 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT)); 3040 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
3041 debugValidate();
2268 } 3042 }
2269 3043
2270 void SkOpSegment::markDoneBinary(int index) { 3044 void SkOpSegment::markDoneBinary(int index) {
2271 double referenceT = fTs[index].fT; 3045 double referenceT = fTs[index].fT;
2272 int lesser = index; 3046 int lesser = index;
2273 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 3047 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2274 markOneDoneBinary(__FUNCTION__, lesser); 3048 markOneDoneBinary(__FUNCTION__, lesser);
2275 } 3049 }
2276 do { 3050 do {
2277 markOneDoneBinary(__FUNCTION__, index); 3051 markOneDoneBinary(__FUNCTION__, index);
2278 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT)); 3052 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
3053 debugValidate();
2279 } 3054 }
2280 3055
2281 void SkOpSegment::markDoneUnary(int index) { 3056 void SkOpSegment::markDoneUnary(int index) {
2282 double referenceT = fTs[index].fT; 3057 double referenceT = fTs[index].fT;
2283 int lesser = index; 3058 int lesser = index;
2284 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 3059 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2285 markOneDoneUnary(__FUNCTION__, lesser); 3060 markOneDoneUnary(__FUNCTION__, lesser);
2286 } 3061 }
2287 do { 3062 do {
2288 markOneDoneUnary(__FUNCTION__, index); 3063 markOneDoneUnary(__FUNCTION__, index);
2289 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT)); 3064 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referen ceT));
3065 debugValidate();
2290 } 3066 }
2291 3067
2292 void SkOpSegment::markOneDone(const char* funName, int tIndex, int winding) { 3068 void SkOpSegment::markOneDone(const char* funName, int tIndex, int winding) {
2293 SkOpSpan* span = markOneWinding(funName, tIndex, winding); 3069 SkOpSpan* span = markOneWinding(funName, tIndex, winding);
2294 if (!span) { 3070 if (!span || span->fDone) {
2295 return; 3071 return;
2296 } 3072 }
2297 span->fDone = true; 3073 span->fDone = true;
2298 fDoneSpans++; 3074 fDoneSpans++;
2299 } 3075 }
2300 3076
2301 void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) { 3077 void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) {
2302 SkOpSpan* span = verifyOneWinding(funName, tIndex); 3078 SkOpSpan* span = verifyOneWinding(funName, tIndex);
2303 if (!span) { 3079 if (!span) {
2304 return; 3080 return;
2305 } 3081 }
3082 SkASSERT(!span->fDone);
2306 span->fDone = true; 3083 span->fDone = true;
2307 fDoneSpans++; 3084 fDoneSpans++;
2308 } 3085 }
2309 3086
2310 void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) { 3087 void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) {
2311 SkOpSpan* span = verifyOneWindingU(funName, tIndex); 3088 SkOpSpan* span = verifyOneWindingU(funName, tIndex);
2312 if (!span) { 3089 if (!span) {
2313 return; 3090 return;
2314 } 3091 }
3092 if (span->fWindSum == SK_MinS32) {
3093 SkDebugf("%s uncomputed\n", __FUNCTION__);
3094 }
3095 SkASSERT(!span->fDone);
2315 span->fDone = true; 3096 span->fDone = true;
2316 fDoneSpans++; 3097 fDoneSpans++;
2317 } 3098 }
2318 3099
2319 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng) { 3100 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng) {
2320 SkOpSpan& span = fTs[tIndex]; 3101 SkOpSpan& span = fTs[tIndex];
2321 if (span.fDone) { 3102 if (span.fDone && !span.fSmall) {
2322 return NULL; 3103 return NULL;
2323 } 3104 }
2324 #if DEBUG_MARK_DONE 3105 #if DEBUG_MARK_DONE
2325 debugShowNewWinding(funName, span, winding); 3106 debugShowNewWinding(funName, span, winding);
2326 #endif 3107 #endif
2327 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 3108 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
2328 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum); 3109 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum);
2329 span.fWindSum = winding; 3110 span.fWindSum = winding;
2330 return &span; 3111 return &span;
2331 } 3112 }
2332 3113
2333 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng, 3114 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng,
2334 int oppWinding) { 3115 int oppWinding) {
2335 SkOpSpan& span = fTs[tIndex]; 3116 SkOpSpan& span = fTs[tIndex];
2336 if (span.fDone && !span.fSmall) { 3117 if (span.fDone && !span.fSmall) {
2337 return NULL; 3118 return NULL;
2338 } 3119 }
2339 #if DEBUG_MARK_DONE 3120 #if DEBUG_MARK_DONE
2340 debugShowNewWinding(funName, span, winding, oppWinding); 3121 debugShowNewWinding(funName, span, winding, oppWinding);
2341 #endif 3122 #endif
2342 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 3123 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
2343 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum); 3124 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum);
2344 span.fWindSum = winding; 3125 span.fWindSum = winding;
2345 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding); 3126 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding);
2346 SkASSERT(abs(oppWinding) <= SkPathOpsDebug::gMaxWindSum); 3127 SkASSERT(abs(oppWinding) <= SkPathOpsDebug::gMaxWindSum);
2347 span.fOppSum = oppWinding; 3128 span.fOppSum = oppWinding;
3129 debugValidate();
2348 return &span; 3130 return &span;
2349 } 3131 }
2350 3132
2351 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order 3133 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order
2352 bool SkOpSegment::clockwise(int tStart, int tEnd) const { 3134 bool SkOpSegment::clockwise(int tStart, int tEnd) const {
2353 SkASSERT(fVerb != SkPath::kLine_Verb); 3135 SkASSERT(fVerb != SkPath::kLine_Verb);
2354 SkPoint edge[4]; 3136 SkPoint edge[4];
2355 subDivide(tStart, tEnd, edge); 3137 subDivide(tStart, tEnd, edge);
2356 int points = SkPathOpsVerbToPoints(fVerb); 3138 int points = SkPathOpsVerbToPoints(fVerb);
2357 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY) ; 3139 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY) ;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2440 #endif 3222 #endif
2441 span->fUnsortableStart = true; 3223 span->fUnsortableStart = true;
2442 } else { 3224 } else {
2443 --span; 3225 --span;
2444 #if DEBUG_UNSORTABLE 3226 #if DEBUG_UNSORTABLE
2445 debugShowNewWinding(__FUNCTION__, *span, 0); 3227 debugShowNewWinding(__FUNCTION__, *span, 0);
2446 #endif 3228 #endif
2447 span->fUnsortableEnd = true; 3229 span->fUnsortableEnd = true;
2448 } 3230 }
2449 if (!span->fUnsortableStart || !span->fUnsortableEnd || span->fDone) { 3231 if (!span->fUnsortableStart || !span->fUnsortableEnd || span->fDone) {
3232 debugValidate();
2450 return; 3233 return;
2451 } 3234 }
2452 span->fDone = true; 3235 span->fDone = true;
2453 fDoneSpans++; 3236 fDoneSpans++;
3237 debugValidate();
2454 } 3238 }
2455 3239
2456 void SkOpSegment::markWinding(int index, int winding) { 3240 void SkOpSegment::markWinding(int index, int winding) {
2457 // SkASSERT(!done()); 3241 // SkASSERT(!done());
2458 SkASSERT(winding); 3242 SkASSERT(winding);
2459 double referenceT = fTs[index].fT; 3243 double referenceT = fTs[index].fT;
2460 int lesser = index; 3244 int lesser = index;
2461 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 3245 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2462 markOneWinding(__FUNCTION__, lesser, winding); 3246 markOneWinding(__FUNCTION__, lesser, winding);
2463 } 3247 }
2464 do { 3248 do {
2465 markOneWinding(__FUNCTION__, index, winding); 3249 markOneWinding(__FUNCTION__, index, winding);
2466 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT)); 3250 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT));
3251 debugValidate();
2467 } 3252 }
2468 3253
2469 void SkOpSegment::markWinding(int index, int winding, int oppWinding) { 3254 void SkOpSegment::markWinding(int index, int winding, int oppWinding) {
2470 // SkASSERT(!done()); 3255 // SkASSERT(!done());
2471 SkASSERT(winding || oppWinding); 3256 SkASSERT(winding || oppWinding);
2472 double referenceT = fTs[index].fT; 3257 double referenceT = fTs[index].fT;
2473 int lesser = index; 3258 int lesser = index;
2474 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 3259 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2475 markOneWinding(__FUNCTION__, lesser, winding, oppWinding); 3260 markOneWinding(__FUNCTION__, lesser, winding, oppWinding);
2476 } 3261 }
2477 do { 3262 do {
2478 markOneWinding(__FUNCTION__, index, winding, oppWinding); 3263 markOneWinding(__FUNCTION__, index, winding, oppWinding);
2479 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT)); 3264 } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenc eT));
3265 debugValidate();
2480 } 3266 }
2481 3267
2482 void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) { 3268 void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) {
2483 int nextDoorWind = SK_MaxS32; 3269 int nextDoorWind = SK_MaxS32;
2484 int nextOppWind = SK_MaxS32; 3270 int nextOppWind = SK_MaxS32;
3271 // prefer exact matches
2485 if (tIndex > 0) { 3272 if (tIndex > 0) {
2486 const SkOpSpan& below = fTs[tIndex - 1]; 3273 const SkOpSpan& below = fTs[tIndex - 1];
3274 if (below.fT == t) {
3275 nextDoorWind = below.fWindValue;
3276 nextOppWind = below.fOppValue;
3277 }
3278 }
3279 if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) {
3280 const SkOpSpan& above = fTs[tIndex + 1];
3281 if (above.fT == t) {
3282 nextDoorWind = above.fWindValue;
3283 nextOppWind = above.fOppValue;
3284 }
3285 }
3286 if (nextDoorWind == SK_MaxS32 && tIndex > 0) {
3287 const SkOpSpan& below = fTs[tIndex - 1];
2487 if (approximately_negative(t - below.fT)) { 3288 if (approximately_negative(t - below.fT)) {
2488 nextDoorWind = below.fWindValue; 3289 nextDoorWind = below.fWindValue;
2489 nextOppWind = below.fOppValue; 3290 nextOppWind = below.fOppValue;
2490 } 3291 }
2491 } 3292 }
2492 if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) { 3293 if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) {
2493 const SkOpSpan& above = fTs[tIndex + 1]; 3294 const SkOpSpan& above = fTs[tIndex + 1];
2494 if (approximately_negative(above.fT - t)) { 3295 if (approximately_negative(above.fT - t)) {
2495 nextDoorWind = above.fWindValue; 3296 nextDoorWind = above.fWindValue;
2496 nextOppWind = above.fOppValue; 3297 nextOppWind = above.fOppValue;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2630 } 3431 }
2631 3432
2632 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, 3433 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding,
2633 int* maxWinding, int* sumWinding) { 3434 int* maxWinding, int* sumWinding) {
2634 int deltaSum = spanSign(index, endIndex); 3435 int deltaSum = spanSign(index, endIndex);
2635 *maxWinding = *sumMiWinding; 3436 *maxWinding = *sumMiWinding;
2636 *sumWinding = *sumMiWinding -= deltaSum; 3437 *sumWinding = *sumMiWinding -= deltaSum;
2637 SkASSERT(abs(*sumWinding) <= SkPathOpsDebug::gMaxWindSum); 3438 SkASSERT(abs(*sumWinding) <= SkPathOpsDebug::gMaxWindSum);
2638 } 3439 }
2639 3440
2640 // This marks all spans unsortable so that this info is available for early 3441 void SkOpSegment::sortAngles() {
2641 // exclusion in find top and others. This could be optimized to only mark 3442 int spanCount = fTs.count();
2642 // adjacent spans that unsortable. However, this makes it difficult to later 3443 if (spanCount <= 2) {
2643 // determine starting points for edge detection in find top and the like. 3444 return;
2644 bool SkOpSegment::SortAngles(const SkTArray<SkOpAngle, true>& angles, 3445 }
2645 SkTArray<SkOpAngle*, true>* angleList, 3446 int index = 0;
2646 SortAngleKind orderKind) { 3447 do {
2647 bool sortable = true; 3448 int fromIndex = fTs[index].fFromAngleIndex;
2648 int angleCount = angles.count(); 3449 int toIndex = fTs[index].fToAngleIndex;
2649 int angleIndex; 3450 if (fromIndex < 0 && toIndex < 0) {
2650 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { 3451 index += 1;
2651 const SkOpAngle& angle = angles[angleIndex]; 3452 continue;
2652 angleList->push_back(const_cast<SkOpAngle*>(&angle)); 3453 }
3454 SkOpAngle* baseAngle = NULL;
3455 if (fromIndex >= 0) {
3456 baseAngle = &this->angle(fromIndex);
3457 if (inLoop(baseAngle, spanCount, &index)) {
3458 continue;
3459 }
3460 }
2653 #if DEBUG_ANGLE 3461 #if DEBUG_ANGLE
2654 (*(angleList->end() - 1))->setID(angleIndex); 3462 bool wroteAfterHeader = false;
2655 #endif 3463 #endif
2656 sortable &= !(angle.unsortable() || (orderKind == kMustBeOrdered_SortAng leKind 3464 if (toIndex >= 0) {
2657 && angle.unorderable())); 3465 SkOpAngle* toAngle = &this->angle(toIndex);
2658 } 3466 if (!baseAngle) {
2659 if (sortable) { 3467 baseAngle = toAngle;
2660 SkTQSort<SkOpAngle>(angleList->begin(), angleList->end() - 1); 3468 if (inLoop(baseAngle, spanCount, &index)) {
2661 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { 3469 continue;
2662 if (angles[angleIndex].unsortable() || (orderKind == kMustBeOrdered_ SortAngleKind 3470 }
2663 && angles[angleIndex].unorderable())) { 3471 } else {
2664 sortable = false; 3472 SkDEBUGCODE(int newIndex = index);
3473 SkASSERT(!inLoop(baseAngle, spanCount, &newIndex) && newIndex == index);
3474 #if DEBUG_ANGLE
3475 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT,
3476 index);
3477 wroteAfterHeader = true;
3478 #endif
3479 baseAngle->insert(toAngle);
3480 }
3481 }
3482 int nextFrom, nextTo;
3483 int firstIndex = index;
3484 do {
3485 SkOpSpan& span = fTs[index];
3486 SkOpSegment* other = span.fOther;
3487 SkOpSpan& oSpan = other->fTs[span.fOtherIndex];
3488 int otherAngleIndex = oSpan.fFromAngleIndex;
3489 if (otherAngleIndex >= 0) {
3490 #if DEBUG_ANGLE
3491 if (!wroteAfterHeader) {
3492 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT,
3493 index);
3494 wroteAfterHeader = true;
3495 }
3496 #endif
3497 baseAngle->insert(&other->angle(otherAngleIndex));
3498 }
3499 otherAngleIndex = oSpan.fToAngleIndex;
3500 if (otherAngleIndex >= 0) {
3501 #if DEBUG_ANGLE
3502 if (!wroteAfterHeader) {
3503 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT,
3504 index);
3505 wroteAfterHeader = true;
3506 }
3507 #endif
3508 baseAngle->insert(&other->angle(otherAngleIndex));
3509 }
3510 if (++index == spanCount) {
2665 break; 3511 break;
2666 } 3512 }
3513 nextFrom = fTs[index].fFromAngleIndex;
3514 nextTo = fTs[index].fToAngleIndex;
3515 } while (fromIndex == nextFrom && toIndex == nextTo);
3516 if (baseAngle && baseAngle->loopCount() == 1) {
3517 index = firstIndex;
3518 do {
3519 SkOpSpan& span = fTs[index];
3520 span.fFromAngleIndex = span.fToAngleIndex = -1;
3521 if (++index == spanCount) {
3522 break;
3523 }
3524 nextFrom = fTs[index].fFromAngleIndex;
3525 nextTo = fTs[index].fToAngleIndex;
3526 } while (fromIndex == nextFrom && toIndex == nextTo);
3527 baseAngle = NULL;
2667 } 3528 }
2668 } 3529 #if DEBUG_SORT
2669 if (!sortable) { 3530 SkASSERT(!baseAngle || baseAngle->loopCount() > 1);
2670 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
2671 const SkOpAngle& angle = angles[angleIndex];
2672 angle.segment()->markUnsortable(angle.start(), angle.end());
2673 }
2674 }
2675 return sortable;
2676 }
2677
2678 // set segments to unsortable if angle is unsortable, but do not set all angles
2679 // note that for a simple 4 way crossing, two of the edges may be orderable even though
2680 // two edges are too short to be orderable.
2681 // perhaps some classes of unsortable angles should make all shared angles unsor table, but
2682 // simple lines that have tiny crossings are always sortable on the large ends
2683 // OPTIMIZATION: check earlier when angles are added to input if any are unsorta ble
2684 // may make sense then to mark all segments in angle sweep as unsortableStart/un sortableEnd
2685 // solely for the purpose of short-circuiting future angle building around this center
2686 bool SkOpSegment::SortAngles2(const SkTArray<SkOpAngle, true>& angles,
2687 SkTArray<SkOpAngle*, true>* angleList) {
2688 int angleCount = angles.count();
2689 int angleIndex;
2690 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
2691 const SkOpAngle& angle = angles[angleIndex];
2692 if (angle.unsortable()) {
2693 return false;
2694 }
2695 angleList->push_back(const_cast<SkOpAngle*>(&angle));
2696 #if DEBUG_ANGLE
2697 (*(angleList->end() - 1))->setID(angleIndex);
2698 #endif 3531 #endif
2699 } 3532 } while (index < spanCount);
2700 SkTQSort<SkOpAngle>(angleList->begin(), angleList->end() - 1);
2701 // at this point angles are sorted but individually may not be orderable
2702 // this means that only adjcent orderable segments may transfer winding
2703 return true;
2704 } 3533 }
2705 3534
2706 // return true if midpoints were computed 3535 // return true if midpoints were computed
2707 bool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { 3536 bool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const {
2708 SkASSERT(start != end); 3537 SkASSERT(start != end);
2709 edge[0] = fTs[start].fPt; 3538 edge[0] = fTs[start].fPt;
2710 int points = SkPathOpsVerbToPoints(fVerb); 3539 int points = SkPathOpsVerbToPoints(fVerb);
2711 edge[points] = fTs[end].fPt; 3540 edge[points] = fTs[end].fPt;
2712 if (fVerb == SkPath::kLine_Verb) { 3541 if (fVerb == SkPath::kLine_Verb) {
2713 return false; 3542 return false;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2795 } 3624 }
2796 3625
2797 void SkOpSegment::TrackOutside(SkTArray<SkPoint, true>* outsidePts, const SkPoin t& startPt) { 3626 void SkOpSegment::TrackOutside(SkTArray<SkPoint, true>* outsidePts, const SkPoin t& startPt) {
2798 int outCount = outsidePts->count(); 3627 int outCount = outsidePts->count();
2799 if (outCount == 0 || startPt != (*outsidePts)[outCount - 1]) { 3628 if (outCount == 0 || startPt != (*outsidePts)[outCount - 1]) {
2800 outsidePts->push_back(startPt); 3629 outsidePts->push_back(startPt);
2801 } 3630 }
2802 } 3631 }
2803 3632
2804 void SkOpSegment::undoneSpan(int* start, int* end) { 3633 void SkOpSegment::undoneSpan(int* start, int* end) {
2805 size_t tCount = fTs.count(); 3634 int tCount = fTs.count();
2806 size_t index; 3635 int index;
2807 for (index = 0; index < tCount; ++index) { 3636 for (index = 0; index < tCount; ++index) {
2808 if (!fTs[index].fDone) { 3637 if (!fTs[index].fDone) {
2809 break; 3638 break;
2810 } 3639 }
2811 } 3640 }
2812 SkASSERT(index < tCount - 1); 3641 SkASSERT(index < tCount - 1);
2813 *start = index; 3642 *start = index;
2814 double startT = fTs[index].fT; 3643 double startT = fTs[index].fT;
2815 while (approximately_negative(fTs[++index].fT - startT)) 3644 while (approximately_negative(fTs[++index].fT - startT))
2816 SkASSERT(index < tCount); 3645 SkASSERT(index < tCount);
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
2940 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 3769 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
2941 span->fWindValue = 0; 3770 span->fWindValue = 0;
2942 span->fOppValue = 0; 3771 span->fOppValue = 0;
2943 if (span->fTiny || span->fSmall) { 3772 if (span->fTiny || span->fSmall) {
2944 return; 3773 return;
2945 } 3774 }
2946 SkASSERT(!span->fDone); 3775 SkASSERT(!span->fDone);
2947 span->fDone = true; 3776 span->fDone = true;
2948 ++fDoneSpans; 3777 ++fDoneSpans;
2949 } 3778 }
2950
2951 #if DEBUG_SWAP_TOP
2952 bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const {
2953 if (fVerb != SkPath::kCubic_Verb) {
2954 return false;
2955 }
2956 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
2957 return dst.controlsContainedByEnds();
2958 }
2959 #endif
2960
2961 #if DEBUG_CONCIDENT
2962 // SkASSERT if pair has not already been added
2963 void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double other T) const {
2964 for (int i = 0; i < fTs.count(); ++i) {
2965 if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == other T) {
2966 return;
2967 }
2968 }
2969 SkASSERT(0);
2970 }
2971 #endif
2972
2973 #if DEBUG_CONCIDENT
2974 void SkOpSegment::debugShowTs(const char* prefix) const {
2975 SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID);
2976 int lastWind = -1;
2977 int lastOpp = -1;
2978 double lastT = -1;
2979 int i;
2980 for (i = 0; i < fTs.count(); ++i) {
2981 bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
2982 || lastOpp != fTs[i].fOppValue;
2983 if (change && lastWind >= 0) {
2984 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
2985 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
2986 }
2987 if (change) {
2988 SkDebugf(" [o=%d", fTs[i].fOther->fID);
2989 lastWind = fTs[i].fWindValue;
2990 lastOpp = fTs[i].fOppValue;
2991 lastT = fTs[i].fT;
2992 } else {
2993 SkDebugf(",%d", fTs[i].fOther->fID);
2994 }
2995 }
2996 if (i <= 0) {
2997 return;
2998 }
2999 SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
3000 lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
3001 if (fOperand) {
3002 SkDebugf(" operand");
3003 }
3004 if (done()) {
3005 SkDebugf(" done");
3006 }
3007 SkDebugf("\n");
3008 }
3009 #endif
3010
3011 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
3012 void SkOpSegment::debugShowActiveSpans() const {
3013 debugValidate();
3014 if (done()) {
3015 return;
3016 }
3017 #if DEBUG_ACTIVE_SPANS_SHORT_FORM
3018 int lastId = -1;
3019 double lastT = -1;
3020 #endif
3021 for (int i = 0; i < fTs.count(); ++i) {
3022 if (fTs[i].fDone) {
3023 continue;
3024 }
3025 SkASSERT(i < fTs.count() - 1);
3026 #if DEBUG_ACTIVE_SPANS_SHORT_FORM
3027 if (lastId == fID && lastT == fTs[i].fT) {
3028 continue;
3029 }
3030 lastId = fID;
3031 lastT = fTs[i].fT;
3032 #endif
3033 SkDebugf("%s id=%d", __FUNCTION__, fID);
3034 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
3035 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
3036 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
3037 }
3038 const SkOpSpan* span = &fTs[i];
3039 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span));
3040 int iEnd = i + 1;
3041 while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
3042 ++iEnd;
3043 }
3044 SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
3045 const SkOpSegment* other = fTs[i].fOther;
3046 SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
3047 other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
3048 if (fTs[i].fWindSum == SK_MinS32) {
3049 SkDebugf("?");
3050 } else {
3051 SkDebugf("%d", fTs[i].fWindSum);
3052 }
3053 SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppVa lue);
3054 }
3055 }
3056 #endif
3057
3058
3059 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
3060 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) {
3061 const SkPoint& pt = xyAtT(&span);
3062 SkDebugf("%s id=%d", fun, fID);
3063 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
3064 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
3065 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
3066 }
3067 SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
3068 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
3069 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=",
3070 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f Y,
3071 (&span)[1].fT, winding);
3072 if (span.fWindSum == SK_MinS32) {
3073 SkDebugf("?");
3074 } else {
3075 SkDebugf("%d", span.fWindSum);
3076 }
3077 SkDebugf(" windValue=%d\n", span.fWindValue);
3078 }
3079
3080 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
3081 int oppWinding) {
3082 const SkPoint& pt = xyAtT(&span);
3083 SkDebugf("%s id=%d", fun, fID);
3084 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
3085 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
3086 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
3087 }
3088 SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
3089 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
3090 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
3091 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f Y,
3092 (&span)[1].fT, winding, oppWinding);
3093 if (span.fOppSum == SK_MinS32) {
3094 SkDebugf("?");
3095 } else {
3096 SkDebugf("%d", span.fOppSum);
3097 }
3098 SkDebugf(" windSum=");
3099 if (span.fWindSum == SK_MinS32) {
3100 SkDebugf("?");
3101 } else {
3102 SkDebugf("%d", span.fWindSum);
3103 }
3104 SkDebugf(" windValue=%d\n", span.fWindValue);
3105 }
3106 #endif
3107
3108 #if DEBUG_SORT || DEBUG_SWAP_TOP
3109 void SkOpSegment::debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true >& angles,
3110 int first, const int contourWinding,
3111 const int oppContourWinding, bool sortable) cons t {
3112 if (--SkPathOpsDebug::gSortCount < 0) {
3113 return;
3114 }
3115 if (!sortable) {
3116 if (angles.count() == 0) {
3117 return;
3118 }
3119 if (first < 0) {
3120 first = 0;
3121 }
3122 }
3123 SkASSERT(angles[first]->segment() == this);
3124 SkASSERT(!sortable || angles.count() > 1);
3125 int lastSum = contourWinding;
3126 int oppLastSum = oppContourWinding;
3127 const SkOpAngle* firstAngle = angles[first];
3128 int windSum = lastSum - spanSign(firstAngle);
3129 int oppoSign = oppSign(firstAngle);
3130 int oppWindSum = oppLastSum - oppoSign;
3131 #define WIND_AS_STRING(x) char x##Str[12]; \
3132 if (!SkPathOpsDebug::ValidWind(x)) strcpy(x##Str, "?"); \
3133 else SK_SNPRINTF(x##Str, sizeof(x##Str), "%d", x)
3134 WIND_AS_STRING(contourWinding);
3135 WIND_AS_STRING(oppContourWinding);
3136 SkDebugf("%s %s contourWinding=%s oppContourWinding=%s sign=%d\n", fun, __FU NCTION__,
3137 contourWindingStr, oppContourWindingStr, spanSign(angles[first]));
3138 int index = first;
3139 bool firstTime = true;
3140 do {
3141 const SkOpAngle& angle = *angles[index];
3142 const SkOpSegment& segment = *angle.segment();
3143 int start = angle.start();
3144 int end = angle.end();
3145 const SkOpSpan& sSpan = segment.fTs[start];
3146 const SkOpSpan& eSpan = segment.fTs[end];
3147 const SkOpSpan& mSpan = segment.fTs[SkMin32(start, end)];
3148 bool opp = segment.fOperand ^ fOperand;
3149 if (!firstTime) {
3150 oppoSign = segment.oppSign(&angle);
3151 if (opp) {
3152 oppLastSum = oppWindSum;
3153 oppWindSum -= segment.spanSign(&angle);
3154 if (oppoSign) {
3155 lastSum = windSum;
3156 windSum -= oppoSign;
3157 }
3158 } else {
3159 lastSum = windSum;
3160 windSum -= segment.spanSign(&angle);
3161 if (oppoSign) {
3162 oppLastSum = oppWindSum;
3163 oppWindSum -= oppoSign;
3164 }
3165 }
3166 }
3167 SkDebugf("%s [%d] %s", __FUNCTION__, index,
3168 angle.unsortable() ? "*** UNSORTABLE *** " : "");
3169 #if DEBUG_SORT_COMPACT
3170 SkDebugf("id=%d %s start=%d (%1.9g,%1.9g) end=%d (%1.9g,%1.9g)",
3171 segment.fID, kLVerbStr[SkPathOpsVerbToPoints(segment.fVerb)],
3172 start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end,
3173 segment.xAtT(&eSpan), segment.yAtT(&eSpan));
3174 #else
3175 switch (segment.fVerb) {
3176 case SkPath::kLine_Verb:
3177 SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts));
3178 break;
3179 case SkPath::kQuad_Verb:
3180 SkDebugf(QUAD_DEBUG_STR, QUAD_DEBUG_DATA(segment.fPts));
3181 break;
3182 case SkPath::kCubic_Verb:
3183 SkDebugf(CUBIC_DEBUG_STR, CUBIC_DEBUG_DATA(segment.fPts));
3184 break;
3185 default:
3186 SkASSERT(0);
3187 }
3188 SkDebugf(" tStart=%1.9g tEnd=%1.9g", sSpan.fT, eSpan.fT);
3189 #endif
3190 SkDebugf(" sign=%d windValue=%d windSum=", angle.sign(), mSpan.fWindValu e);
3191 SkPathOpsDebug::WindingPrintf(mSpan.fWindSum);
3192 int last, wind;
3193 if (opp) {
3194 last = oppLastSum;
3195 wind = oppWindSum;
3196 } else {
3197 last = lastSum;
3198 wind = windSum;
3199 }
3200 bool useInner = SkPathOpsDebug::ValidWind(last) && SkPathOpsDebug::Valid Wind(wind)
3201 && UseInnerWinding(last, wind);
3202 WIND_AS_STRING(last);
3203 WIND_AS_STRING(wind);
3204 WIND_AS_STRING(lastSum);
3205 WIND_AS_STRING(oppLastSum);
3206 WIND_AS_STRING(windSum);
3207 WIND_AS_STRING(oppWindSum);
3208 #undef WIND_AS_STRING
3209 if (!oppoSign) {
3210 SkDebugf(" %s->%s (max=%s)", lastStr, windStr, useInner ? windStr : lastStr);
3211 } else {
3212 SkDebugf(" %s->%s (%s->%s)", lastStr, windStr, opp ? lastSumStr : op pLastSumStr,
3213 opp ? windSumStr : oppWindSumStr);
3214 }
3215 SkDebugf(" done=%d unord=%d small=%d tiny=%d opp=%d\n",
3216 mSpan.fDone, angle.unorderable(), mSpan.fSmall, mSpan.fTiny, opp );
3217 ++index;
3218 if (index == angles.count()) {
3219 index = 0;
3220 }
3221 if (firstTime) {
3222 firstTime = false;
3223 }
3224 } while (index != first);
3225 }
3226
3227 void SkOpSegment::debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true >& angles,
3228 int first, bool sortable) {
3229 if (!sortable) {
3230 if (angles.count() == 0) {
3231 return;
3232 }
3233 if (first < 0) {
3234 first = 0;
3235 }
3236 }
3237 const SkOpAngle* firstAngle = angles[first];
3238 const SkOpSegment* segment = firstAngle->segment();
3239 int winding = segment->updateWinding(firstAngle);
3240 int oppWinding = segment->updateOppWinding(firstAngle);
3241 debugShowSort(fun, angles, first, winding, oppWinding, sortable);
3242 }
3243
3244 #endif
3245
3246 #if DEBUG_SHOW_WINDING
3247 int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const {
3248 if (!(1 << fID & ofInterest)) {
3249 return 0;
3250 }
3251 int sum = 0;
3252 SkTArray<char, true> slots(slotCount * 2);
3253 memset(slots.begin(), ' ', slotCount * 2);
3254 for (int i = 0; i < fTs.count(); ++i) {
3255 // if (!(1 << fTs[i].fOther->fID & ofInterest)) {
3256 // continue;
3257 // }
3258 sum += fTs[i].fWindValue;
3259 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
3260 sum += fTs[i].fOppValue;
3261 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
3262 }
3263 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi n(), slotCount,
3264 slots.begin() + slotCount);
3265 return sum;
3266 }
3267 #endif
3268
3269 void SkOpSegment::debugValidate() const {
3270 #if DEBUG_VALIDATE
3271 int count = fTs.count();
3272 SkASSERT(count >= 2);
3273 SkASSERT(fTs[0].fT == 0);
3274 SkASSERT(fTs[count - 1].fT == 1);
3275 int done = 0;
3276 double t = -1;
3277 for (int i = 0; i < count; ++i) {
3278 const SkOpSpan& span = fTs[i];
3279 SkASSERT(t <= span.fT);
3280 t = span.fT;
3281 int otherIndex = span.fOtherIndex;
3282 const SkOpSegment* other = span.fOther;
3283 const SkOpSpan& otherSpan = other->fTs[otherIndex];
3284 SkASSERT(otherSpan.fPt == span.fPt);
3285 SkASSERT(otherSpan.fOtherT == t);
3286 SkASSERT(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
3287 done += span.fDone;
3288 }
3289 SkASSERT(done == fDoneSpans);
3290 #endif
3291 }
3292
3293 #ifdef SK_DEBUG
3294 void SkOpSegment::dumpPts() const {
3295 int last = SkPathOpsVerbToPoints(fVerb);
3296 SkDebugf("{{");
3297 int index = 0;
3298 do {
3299 SkDPoint::dump(fPts[index]);
3300 SkDebugf(", ");
3301 } while (++index < last);
3302 SkDPoint::dump(fPts[index]);
3303 SkDebugf("}}\n");
3304 }
3305
3306 void SkOpSegment::dumpDPts() const {
3307 int count = SkPathOpsVerbToPoints(fVerb);
3308 SkDebugf("{{");
3309 int index = 0;
3310 do {
3311 SkDPoint dPt = {fPts[index].fX, fPts[index].fY};
3312 dPt.dump();
3313 if (index != count) {
3314 SkDebugf(", ");
3315 }
3316 } while (++index <= count);
3317 SkDebugf("}}\n");
3318 }
3319
3320 void SkOpSegment::dumpSpans() const {
3321 int count = this->count();
3322 for (int index = 0; index < count; ++index) {
3323 const SkOpSpan& span = this->span(index);
3324 SkDebugf("[%d] ", index);
3325 span.dump();
3326 }
3327 }
3328 #endif
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkOpSpan.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698