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

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

Issue 1111333002: compute initial winding from projected rays (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add missing test reference Created 5 years, 7 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/SkPathOpsCommon.h ('k') | src/pathops/SkPathOpsCubic.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 "SkAddIntersections.h" 7 #include "SkAddIntersections.h"
8 #include "SkOpCoincidence.h" 8 #include "SkOpCoincidence.h"
9 #include "SkOpEdgeBuilder.h" 9 #include "SkOpEdgeBuilder.h"
10 #include "SkPathOpsCommon.h" 10 #include "SkPathOpsCommon.h"
11 #include "SkPathWriter.h" 11 #include "SkPathWriter.h"
12 #include "SkTSort.h" 12 #include "SkTSort.h"
13 13
14 static int contourRangeCheckY(const SkTDArray<SkOpContour* >& contourList, 14 SkOpSegment* FindUndone(SkOpContourHead* contourList, SkOpSpanBase** startPtr,
15 SkOpSegment** currentPtr, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr ,
16 double* bestHit, SkScalar* bestDx, bool* tryAgain, double* midPtr, bool opp) {
17 SkOpSpanBase* start = *startPtr;
18 SkOpSpanBase* end = *endPtr;
19 const double mid = *midPtr;
20 const SkOpSegment* current = *currentPtr;
21 double tAtMid = SkOpSegment::TAtMid(start, end, mid);
22 SkPoint basePt = current->ptAtT(tAtMid);
23 int contourCount = contourList.count();
24 SkScalar bestY = SK_ScalarMin;
25 SkOpSegment* bestSeg = NULL;
26 SkOpSpan* bestTSpan = NULL;
27 bool bestOpp;
28 bool hitSomething = false;
29 for (int cTest = 0; cTest < contourCount; ++cTest) {
30 SkOpContour* contour = contourList[cTest];
31 bool testOpp = contour->operand() ^ current->operand() ^ opp;
32 if (basePt.fY < contour->bounds().fTop) {
33 continue;
34 }
35 if (bestY > contour->bounds().fBottom) {
36 continue;
37 }
38 SkOpSegment* testSeg = contour->first();
39 SkASSERT(testSeg);
40 do {
41 SkScalar testY = bestY;
42 double testHit;
43 bool vertical;
44 SkOpSpan* testTSpan = testSeg->crossedSpanY(basePt, tAtMid, testOpp,
45 testSeg == current, &testY, &testHit, &hitSomething, &vertic al);
46 if (!testTSpan) {
47 if (vertical) {
48 hitSomething = true;
49 bestSeg = NULL;
50 goto abortContours; // vertical encountered, return and try different point
51 }
52 continue;
53 }
54 if (testSeg == current && SkOpSegment::BetweenTs(start, testHit, end )) {
55 double baseT = start->t();
56 double endT = end->t();
57 double newMid = (testHit - baseT) / (endT - baseT);
58 #if DEBUG_WINDING
59 double midT = SkOpSegment::TAtMid(start, end, mid);
60 SkPoint midXY = current->ptAtT(midT);
61 double newMidT = SkOpSegment::TAtMid(start, end, newMid);
62 SkPoint newXY = current->ptAtT(newMidT);
63 SkDebugf("%s [%d] mid=%1.9g->%1.9g s=%1.9g (%1.9g,%1.9g) m=%1.9g (%1.9g,%1.9g)"
64 " n=%1.9g (%1.9g,%1.9g) e=%1.9g (%1.9g,%1.9g)\n", __FUNC TION__,
65 current->debugID(), mid, newMid,
66 baseT, start->pt().fX, start->pt().fY,
67 baseT + mid * (endT - baseT), midXY.fX, midXY.fY,
68 baseT + newMid * (endT - baseT), newXY.fX, newXY.fY,
69 endT, end->pt().fX, end->pt().fY);
70 #endif
71 *midPtr = newMid * 2; // calling loop with divide by 2 before c ontinuing
72 return SK_MinS32;
73 }
74 bestSeg = testSeg;
75 *bestHit = testHit;
76 bestOpp = testOpp;
77 bestTSpan = testTSpan;
78 bestY = testY;
79 } while ((testSeg = testSeg->next()));
80 }
81 abortContours:
82 int result;
83 if (!bestSeg) {
84 result = hitSomething ? SK_MinS32 : 0;
85 } else {
86 if (bestTSpan->windSum() == SK_MinS32) {
87 *currentPtr = bestSeg;
88 *startPtr = bestTSpan;
89 *endPtr = bestTSpan->next();
90 SkASSERT(*startPtr != *endPtr && *startPtr && *endPtr);
91 *tryAgain = true;
92 return 0;
93 }
94 result = bestSeg->windingAtT(*bestHit, bestTSpan, bestOpp, bestDx);
95 SkASSERT(result == SK_MinS32 || *bestDx);
96 }
97 double baseT = (*startPtr)->t();
98 double endT = (*endPtr)->t();
99 *bestHit = baseT + mid * (endT - baseT);
100 return result;
101 }
102
103 SkOpSegment* FindUndone(SkTDArray<SkOpContour* >& contourList, SkOpSpanBase** st artPtr,
104 SkOpSpanBase** endPtr) { 15 SkOpSpanBase** endPtr) {
105 int contourCount = contourList.count();
106 SkOpSegment* result; 16 SkOpSegment* result;
107 for (int cIndex = 0; cIndex < contourCount; ++cIndex) { 17 SkOpContour* contour = contourList;
108 SkOpContour* contour = contourList[cIndex]; 18 do {
109 result = contour->undoneSegment(startPtr, endPtr); 19 result = contour->undoneSegment(startPtr, endPtr);
110 if (result) { 20 if (result) {
111 return result; 21 return result;
112 } 22 }
113 } 23 } while ((contour = contour->next()));
114 return NULL; 24 return NULL;
115 } 25 }
116 26
117 SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr, 27 SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr,
118 SkOpSpanBase** endPtr) { 28 SkOpSpanBase** endPtr) {
119 while (chase->count()) { 29 while (chase->count()) {
120 SkOpSpanBase* span; 30 SkOpSpanBase* span;
121 chase->pop(&span); 31 chase->pop(&span);
122 SkOpSegment* segment = span->segment(); 32 SkOpSegment* segment = span->segment();
123 *startPtr = span->ptT()->next()->span(); 33 *startPtr = span->ptT()->next()->span();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 #else 99 #else
190 *chase->append() = span; 100 *chase->append() = span;
191 #endif 101 #endif
192 return first; 102 return first;
193 } 103 }
194 } 104 }
195 return NULL; 105 return NULL;
196 } 106 }
197 107
198 #if DEBUG_ACTIVE_SPANS 108 #if DEBUG_ACTIVE_SPANS
199 void DebugShowActiveSpans(SkTDArray<SkOpContour* >& contourList) { 109 void DebugShowActiveSpans(SkOpContourHead* contourList) {
200 int index; 110 SkOpContour* contour = contourList;
201 for (index = 0; index < contourList.count(); ++ index) { 111 do {
202 contourList[index]->debugShowActiveSpans(); 112 contour->debugShowActiveSpans();
203 } 113 } while ((contour = contour->next()));
204 } 114 }
205 #endif 115 #endif
206 116
207 static SkOpSegment* findTopSegment(const SkTDArray<SkOpContour* >& contourList, 117 bool SortContourList(SkOpContourHead** contourList, bool evenOdd, bool oppEvenOd d) {
208 bool firstPass, SkOpSpanBase** start, SkOpSpanBase** end, SkDPoint* topL eft, 118 SkTDArray<SkOpContour* > list;
209 bool* unsortable, bool* done, SkChunkAlloc* allocator) { 119 SkOpContour* contour = *contourList;
210 SkOpSegment* result;
211 const SkOpSegment* lastTopStart = NULL;
212 SkOpSpanBase* lastStart = NULL, * lastEnd = NULL;
213 do {
214 SkDPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
215 int contourCount = contourList.count();
216 SkOpSegment* topStart = NULL;
217 *done = true;
218 for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
219 SkOpContour* contour = contourList[cIndex];
220 if (contour->done()) {
221 continue;
222 }
223 const SkPathOpsBounds& bounds = contour->bounds();
224 if (bounds.fBottom < topLeft->fY) {
225 *done = false;
226 continue;
227 }
228 if (bounds.fBottom == topLeft->fY && bounds.fRight < topLeft->fX) {
229 *done = false;
230 continue;
231 }
232 contour->topSortableSegment(*topLeft, &bestXY, &topStart);
233 if (!contour->done()) {
234 *done = false;
235 }
236 }
237 if (!topStart) {
238 return NULL;
239 }
240 *topLeft = bestXY;
241 result = topStart->findTop(firstPass, start, end, unsortable, allocator) ;
242 if (!result) {
243 if (lastTopStart == topStart && lastStart == *start && lastEnd == *e nd) {
244 *done = true;
245 return NULL;
246 }
247 lastTopStart = topStart;
248 lastStart = *start;
249 lastEnd = *end;
250 }
251 } while (!result);
252 return result;
253 }
254
255 static int rightAngleWinding(const SkTDArray<SkOpContour* >& contourList,
256 SkOpSegment** currentPtr, SkOpSpanBase** start, SkOpSpanBase** end, doub le* tHit,
257 SkScalar* hitDx, bool* tryAgain, bool* onlyVertical, bool opp) {
258 double test = 0.9;
259 int contourWinding;
260 do {
261 contourWinding = contourRangeCheckY(contourList, currentPtr, start, end,
262 tHit, hitDx, tryAgain, &test, opp);
263 if (contourWinding != SK_MinS32 || *tryAgain) {
264 return contourWinding;
265 }
266 if (*currentPtr && (*currentPtr)->isVertical()) {
267 *onlyVertical = true;
268 return contourWinding;
269 }
270 test /= 2;
271 } while (!approximately_negative(test));
272 SkASSERT(0); // FIXME: incomplete functionality
273 return contourWinding;
274 }
275
276 static void skipVertical(const SkTDArray<SkOpContour* >& contourList,
277 SkOpSegment** current, SkOpSpanBase** start, SkOpSpanBase** end) {
278 if (!(*current)->isVertical(*start, *end)) {
279 return;
280 }
281 int contourCount = contourList.count();
282 for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
283 SkOpContour* contour = contourList[cIndex];
284 if (contour->done()) {
285 continue;
286 }
287 SkOpSegment* nonVertical = contour->nonVerticalSegment(start, end);
288 if (nonVertical) {
289 *current = nonVertical;
290 return;
291 }
292 }
293 return;
294 }
295
296 struct SortableTop2 { // error if local in pre-C++11
297 SkOpSpanBase* fStart;
298 SkOpSpanBase* fEnd;
299 };
300
301 SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour* >& contourList, bool f irstPass,
302 SkOpAngle::IncludeType angleIncludeType, bool* firstContour, SkOpSpanBas e** startPtr,
303 SkOpSpanBase** endPtr, SkDPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical,
304 SkChunkAlloc* allocator) {
305 SkOpSegment* current = findTopSegment(contourList, firstPass, startPtr, endP tr, topLeft,
306 unsortable, done, allocator);
307 if (!current) {
308 return NULL;
309 }
310 SkOpSpanBase* start = *startPtr;
311 SkOpSpanBase* end = *endPtr;
312 SkASSERT(current == start->segment());
313 if (*firstContour) {
314 current->initWinding(start, end, angleIncludeType);
315 *firstContour = false;
316 return current;
317 }
318 SkOpSpan* minSpan = start->starter(end);
319 int sumWinding = minSpan->windSum();
320 if (sumWinding == SK_MinS32) {
321 SkOpSpanBase* iSpan = end;
322 SkOpSpanBase* oSpan = start;
323 do {
324 bool checkFrom = oSpan->t() < iSpan->t();
325 if ((checkFrom ? iSpan->fromAngle() : iSpan->upCast()->toAngle()) == NULL) {
326 if (!iSpan->addSimpleAngle(checkFrom, allocator)) {
327 *unsortable = true;
328 return NULL;
329 }
330 }
331 sumWinding = current->computeSum(oSpan, iSpan, angleIncludeType);
332 SkTSwap(iSpan, oSpan);
333 } while (sumWinding == SK_MinS32 && iSpan == start);
334 }
335 if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) {
336 return current;
337 }
338 int contourWinding;
339 int oppContourWinding = 0;
340 // the simple upward projection of the unresolved points hit unsortable angl es
341 // shoot rays at right angles to the segment to find its winding, ignoring a ngle cases
342 bool tryAgain;
343 double tHit;
344 SkScalar hitDx = 0;
345 SkScalar hitOppDx = 0;
346 // keep track of subsequent returns to detect infinite loops
347 SkTDArray<SortableTop2> sortableTops;
348 do {
349 // if current is vertical, find another candidate which is not
350 // if only remaining candidates are vertical, then they can be marked do ne
351 SkASSERT(*startPtr != *endPtr && *startPtr && *endPtr);
352 SkASSERT(current == (*startPtr)->segment());
353 skipVertical(contourList, &current, startPtr, endPtr);
354 SkASSERT(current); // FIXME: if null, all remaining are vertical
355 SkASSERT(*startPtr != *endPtr && *startPtr && *endPtr);
356 SkASSERT(current == (*startPtr)->segment());
357 tryAgain = false;
358 contourWinding = rightAngleWinding(contourList, &current, startPtr, endP tr, &tHit,
359 &hitDx, &tryAgain, onlyVertical, false);
360 SkASSERT(current == (*startPtr)->segment());
361 if (tryAgain) {
362 bool giveUp = false;
363 int count = sortableTops.count();
364 for (int index = 0; index < count; ++index) {
365 const SortableTop2& prev = sortableTops[index];
366 if (giveUp) {
367 prev.fStart->segment()->markDone(prev.fStart->starter(prev.f End));
368 } else if (prev.fStart == *startPtr || prev.fEnd == *endPtr) {
369 // remaining edges are non-vertical and cannot have their wi nding computed
370 // mark them as done and return, and hope that assembly can fill the holes
371 giveUp = true;
372 index = -1;
373 }
374 }
375 if (giveUp) {
376 *done = true;
377 return NULL;
378 }
379 }
380 SortableTop2* sortableTop = sortableTops.append();
381 sortableTop->fStart = *startPtr;
382 sortableTop->fEnd = *endPtr;
383 #if DEBUG_SORT
384 SkDebugf("%s current=%d index=%d endIndex=%d tHit=%1.9g hitDx=%1.9g try= %d vert=%d\n",
385 __FUNCTION__, current->debugID(), (*startPtr)->debugID(), (*endP tr)->debugID(),
386 tHit, hitDx, tryAgain, *onlyVertical);
387 #endif
388 if (*onlyVertical) {
389 return current;
390 }
391 if (tryAgain) {
392 continue;
393 }
394 if (angleIncludeType < SkOpAngle::kBinarySingle) {
395 break;
396 }
397 oppContourWinding = rightAngleWinding(contourList, &current, startPtr, e ndPtr, &tHit,
398 &hitOppDx, &tryAgain, NULL, true);
399 SkASSERT(current == (*startPtr)->segment());
400 } while (tryAgain);
401 bool success = current->initWinding(*startPtr, *endPtr, tHit, contourWinding , hitDx,
402 oppContourWinding, hitOppDx);
403 if (current->done()) {
404 return NULL;
405 } else if (!success) { // check if the span has a valid winding
406 SkOpSpan* minSpan = (*startPtr)->t() < (*endPtr)->t() ? (*startPtr)->upC ast()
407 : (*endPtr)->upCast();
408 if (minSpan->windSum() == SK_MinS32) {
409 return NULL;
410 }
411 }
412 return current;
413 }
414
415 void MakeContourList(SkOpContour* contour, SkTDArray<SkOpContour* >& list,
416 bool evenOdd, bool oppEvenOdd) {
417 do { 120 do {
418 if (contour->count()) { 121 if (contour->count()) {
419 contour->setOppXor(contour->operand() ? evenOdd : oppEvenOdd); 122 contour->setOppXor(contour->operand() ? evenOdd : oppEvenOdd);
420 *list.append() = contour; 123 *list.append() = contour;
421 } 124 }
422 } while ((contour = contour->next())); 125 } while ((contour = contour->next()));
423 if (list.count() < 2) { 126 int count = list.count();
424 return; 127 if (!count) {
128 return false;
425 } 129 }
426 SkTQSort<SkOpContour>(list.begin(), list.end() - 1); 130 if (count > 1) {
131 SkTQSort<SkOpContour>(list.begin(), list.end() - 1);
132 }
133 contour = list[0];
134 SkOpContourHead* contourHead = static_cast<SkOpContourHead*>(contour);
135 contour->globalState()->setContourHead(contourHead);
136 *contourList = contourHead;
137 for (int index = 1; index < count; ++index) {
138 SkOpContour* next = list[index];
139 contour->setNext(next);
140 contour = next;
141 }
142 contour->setNext(NULL);
143 return true;
427 } 144 }
428 145
429 class DistanceLessThan { 146 class DistanceLessThan {
430 public: 147 public:
431 DistanceLessThan(double* distances) : fDistances(distances) { } 148 DistanceLessThan(double* distances) : fDistances(distances) { }
432 double* fDistances; 149 double* fDistances;
433 bool operator()(const int one, const int two) { 150 bool operator()(const int one, const int two) {
434 return fDistances[one] < fDistances[two]; 151 return fDistances[one] < fDistances[two];
435 } 152 }
436 }; 153 };
437 154
438 /* 155 /*
439 check start and end of each contour 156 check start and end of each contour
440 if not the same, record them 157 if not the same, record them
441 match them up 158 match them up
442 connect closest 159 connect closest
443 reassemble contour pieces into new path 160 reassemble contour pieces into new path
444 */ 161 */
445 void Assemble(const SkPathWriter& path, SkPathWriter* simple) { 162 void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
446 SkChunkAlloc allocator(4096); // FIXME: constant-ize, tune 163 SkChunkAlloc allocator(4096); // FIXME: constant-ize, tune
447 SkOpContour contour; 164 SkOpContourHead contour;
448 SkOpGlobalState globalState(NULL SkDEBUGPARAMS(&contour)); 165 SkOpGlobalState globalState(NULL, &contour);
449 #if DEBUG_SHOW_TEST_NAME 166 #if DEBUG_SHOW_TEST_NAME
450 SkDebugf("</div>\n"); 167 SkDebugf("</div>\n");
451 #endif 168 #endif
452 #if DEBUG_PATH_CONSTRUCTION 169 #if DEBUG_PATH_CONSTRUCTION
453 SkDebugf("%s\n", __FUNCTION__); 170 SkDebugf("%s\n", __FUNCTION__);
454 #endif 171 #endif
455 SkOpEdgeBuilder builder(path, &contour, &allocator, &globalState); 172 SkOpEdgeBuilder builder(path, &contour, &allocator, &globalState);
456 builder.finish(&allocator); 173 builder.finish(&allocator);
457 SkTDArray<const SkOpContour* > runs; // indices of partial contours 174 SkTDArray<const SkOpContour* > runs; // indices of partial contours
458 const SkOpContour* eContour = builder.head(); 175 const SkOpContour* eContour = builder.head();
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 } 344 }
628 } while (rIndex < count); 345 } while (rIndex < count);
629 #if DEBUG_ASSEMBLE 346 #if DEBUG_ASSEMBLE
630 for (rIndex = 0; rIndex < count; ++rIndex) { 347 for (rIndex = 0; rIndex < count; ++rIndex) {
631 SkASSERT(sLink[rIndex] == SK_MaxS32); 348 SkASSERT(sLink[rIndex] == SK_MaxS32);
632 SkASSERT(eLink[rIndex] == SK_MaxS32); 349 SkASSERT(eLink[rIndex] == SK_MaxS32);
633 } 350 }
634 #endif 351 #endif
635 } 352 }
636 353
637 static void align(SkTDArray<SkOpContour* >* contourList) { 354 static void align(SkOpContourHead* contourList) {
638 int contourCount = (*contourList).count(); 355 SkOpContour* contour = contourList;
639 for (int cTest = 0; cTest < contourCount; ++cTest) { 356 do {
640 SkOpContour* contour = (*contourList)[cTest];
641 contour->align(); 357 contour->align();
642 } 358 } while ((contour = contour->next()));
643 } 359 }
644 360
645 static void calcAngles(SkTDArray<SkOpContour* >* contourList, SkChunkAlloc* allo cator) { 361 static void calcAngles(SkOpContourHead* contourList, SkChunkAlloc* allocator) {
646 int contourCount = (*contourList).count(); 362 SkOpContour* contour = contourList;
647 for (int cTest = 0; cTest < contourCount; ++cTest) { 363 do {
648 SkOpContour* contour = (*contourList)[cTest];
649 contour->calcAngles(allocator); 364 contour->calcAngles(allocator);
650 } 365 } while ((contour = contour->next()));
651 } 366 }
652 367
653 static void missingCoincidence(SkTDArray<SkOpContour* >* contourList, 368 static void missingCoincidence(SkOpContourHead* contourList,
654 SkOpCoincidence* coincidence, SkChunkAlloc* allocator) { 369 SkOpCoincidence* coincidence, SkChunkAlloc* allocator) {
655 int contourCount = (*contourList).count(); 370 SkOpContour* contour = contourList;
656 for (int cTest = 0; cTest < contourCount; ++cTest) { 371 do {
657 SkOpContour* contour = (*contourList)[cTest];
658 contour->missingCoincidence(coincidence, allocator); 372 contour->missingCoincidence(coincidence, allocator);
659 } 373 } while ((contour = contour->next()));
660 } 374 }
661 375
662 static void moveMultiples(SkTDArray<SkOpContour* >* contourList) { 376 static void moveMultiples(SkOpContourHead* contourList) {
663 int contourCount = (*contourList).count(); 377 SkOpContour* contour = contourList;
664 for (int cTest = 0; cTest < contourCount; ++cTest) { 378 do {
665 SkOpContour* contour = (*contourList)[cTest];
666 contour->moveMultiples(); 379 contour->moveMultiples();
667 } 380 } while ((contour = contour->next()));
668 } 381 }
669 382
670 static void moveNearby(SkTDArray<SkOpContour* >* contourList) { 383 static void moveNearby(SkOpContourHead* contourList) {
671 int contourCount = (*contourList).count(); 384 SkOpContour* contour = contourList;
672 for (int cTest = 0; cTest < contourCount; ++cTest) { 385 do {
673 SkOpContour* contour = (*contourList)[cTest];
674 contour->moveNearby(); 386 contour->moveNearby();
675 } 387 } while ((contour = contour->next()));
676 } 388 }
677 389
678 static void sortAngles(SkTDArray<SkOpContour* >* contourList) { 390 static void sortAngles(SkOpContourHead* contourList) {
679 int contourCount = (*contourList).count(); 391 SkOpContour* contour = contourList;
680 for (int cTest = 0; cTest < contourCount; ++cTest) { 392 do {
681 SkOpContour* contour = (*contourList)[cTest];
682 contour->sortAngles(); 393 contour->sortAngles();
683 } 394 } while ((contour = contour->next()));
684 } 395 }
685 396
686 static void sortSegments(SkTDArray<SkOpContour* >* contourList) { 397 bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc e,
687 int contourCount = (*contourList).count(); 398 SkChunkAlloc* allocator) {
688 for (int cTest = 0; cTest < contourCount; ++cTest) { 399 SkOpGlobalState* globalState = contourList->globalState();
689 SkOpContour* contour = (*contourList)[cTest];
690 contour->sortSegments();
691 }
692 }
693
694 bool HandleCoincidence(SkTDArray<SkOpContour* >* contourList, SkOpCoincidence* c oincidence,
695 SkChunkAlloc* allocator, SkOpGlobalState* globalState) {
696 // combine t values when multiple intersections occur on some segments but n ot others 400 // combine t values when multiple intersections occur on some segments but n ot others
697 moveMultiples(contourList); 401 moveMultiples(contourList);
698 // move t values and points together to eliminate small/tiny gaps 402 // move t values and points together to eliminate small/tiny gaps
699 moveNearby(contourList); 403 moveNearby(contourList);
700 align(contourList); // give all span members common values 404 align(contourList); // give all span members common values
701 #if DEBUG_VALIDATE 405 #if DEBUG_VALIDATE
702 globalState->setPhase(SkOpGlobalState::kIntersecting); 406 globalState->setPhase(SkOpGlobalState::kIntersecting);
703 #endif 407 #endif
704 coincidence->addMissing(allocator); 408 coincidence->addMissing(allocator);
705 #if DEBUG_VALIDATE 409 #if DEBUG_VALIDATE
706 globalState->setPhase(SkOpGlobalState::kWalking); 410 globalState->setPhase(SkOpGlobalState::kWalking);
707 #endif 411 #endif
708 coincidence->expand(); // check to see if, loosely, coincident ranges may b e expanded 412 coincidence->expand(); // check to see if, loosely, coincident ranges may b e expanded
709 coincidence->mark(); // mark spans of coincident segments as coincident 413 coincidence->mark(); // mark spans of coincident segments as coincident
710 missingCoincidence(contourList, coincidence, allocator); // look for coinci dence missed earlier 414 missingCoincidence(contourList, coincidence, allocator); // look for coinci dence missed earlier
711 if (!coincidence->apply()) { // adjust the winding value to account for coi ncident edges 415 if (!coincidence->apply()) { // adjust the winding value to account for coi ncident edges
712 return false; 416 return false;
713 } 417 }
714 sortSegments(contourList);
715 calcAngles(contourList, allocator); 418 calcAngles(contourList, allocator);
716 sortAngles(contourList); 419 sortAngles(contourList);
717 if (globalState->angleCoincidence()) { 420 if (globalState->angleCoincidence()) {
718 missingCoincidence(contourList, coincidence, allocator); 421 missingCoincidence(contourList, coincidence, allocator);
719 if (!coincidence->apply()) { 422 if (!coincidence->apply()) {
720 return false; 423 return false;
721 } 424 }
722 } 425 }
723 #if DEBUG_ACTIVE_SPANS 426 #if DEBUG_ACTIVE_SPANS
724 DebugShowActiveSpans(*contourList); 427 coincidence->debugShowCoincidence();
428 DebugShowActiveSpans(contourList);
725 #endif 429 #endif
726 return true; 430 return true;
727 } 431 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsCommon.h ('k') | src/pathops/SkPathOpsCubic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698