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

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

Issue 272153002: fix bugs found by computing flat clips in 800K skps (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix maybe-uninitialized error in unbuntu Created 6 years, 6 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/SkPathOpsDebug.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 "SkOpEdgeBuilder.h" 8 #include "SkOpEdgeBuilder.h"
9 #include "SkPathOpsCommon.h" 9 #include "SkPathOpsCommon.h"
10 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
11 #include "SkTSort.h" 11 #include "SkTSort.h"
12 12
13 static void alignMultiples(SkTArray<SkOpContour*, true>* contourList,
14 SkTDArray<SkOpSegment::AlignedSpan>* aligned) {
15 int contourCount = (*contourList).count();
16 for (int cTest = 0; cTest < contourCount; ++cTest) {
17 SkOpContour* contour = (*contourList)[cTest];
18 if (contour->hasMultiples()) {
19 contour->alignMultiples(aligned);
20 }
21 }
22 }
23
24 static void alignCoincidence(SkTArray<SkOpContour*, true>* contourList,
25 const SkTDArray<SkOpSegment::AlignedSpan>& aligned) {
26 int contourCount = (*contourList).count();
27 for (int cTest = 0; cTest < contourCount; ++cTest) {
28 SkOpContour* contour = (*contourList)[cTest];
29 int count = aligned.count();
30 for (int index = 0; index < count; ++index) {
31 contour->alignCoincidence(aligned[index]);
32 }
33 }
34 }
35
13 static int contourRangeCheckY(const SkTArray<SkOpContour*, true>& contourList, S kOpSegment** currentPtr, 36 static int contourRangeCheckY(const SkTArray<SkOpContour*, true>& contourList, S kOpSegment** currentPtr,
14 int* indexPtr, int* endIndexPtr, double* bestHit, SkScalar* bestDx, 37 int* indexPtr, int* endIndexPtr, double* bestHit, SkScalar* bestDx,
15 bool* tryAgain, double* midPtr, bool opp) { 38 bool* tryAgain, double* midPtr, bool opp) {
16 const int index = *indexPtr; 39 const int index = *indexPtr;
17 const int endIndex = *endIndexPtr; 40 const int endIndex = *endIndexPtr;
18 const double mid = *midPtr; 41 const double mid = *midPtr;
19 const SkOpSegment* current = *currentPtr; 42 const SkOpSegment* current = *currentPtr;
20 double tAtMid = current->tAtMid(index, endIndex, mid); 43 double tAtMid = current->tAtMid(index, endIndex, mid);
21 SkPoint basePt = current->ptAtT(tAtMid); 44 SkPoint basePt = current->ptAtT(tAtMid);
22 int contourCount = contourList.count(); 45 int contourCount = contourList.count();
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 *endIndex = angle->end(); 201 *endIndex = angle->end();
179 int lesser = SkMin32(*tIndex, *endIndex); 202 int lesser = SkMin32(*tIndex, *endIndex);
180 const SkOpSpan& nextSpan = segment->span(lesser); 203 const SkOpSpan& nextSpan = segment->span(lesser);
181 if (!nextSpan.fDone) { 204 if (!nextSpan.fDone) {
182 // FIXME: this be wrong? assign startWinding if edge is in 205 // FIXME: this be wrong? assign startWinding if edge is in
183 // same direction. If the direction is opposite, winding to 206 // same direction. If the direction is opposite, winding to
184 // assign is flipped sign or +/- 1? 207 // assign is flipped sign or +/- 1?
185 if (SkOpSegment::UseInnerWinding(maxWinding, winding)) { 208 if (SkOpSegment::UseInnerWinding(maxWinding, winding)) {
186 maxWinding = winding; 209 maxWinding = winding;
187 } 210 }
188 segment->markAndChaseWinding(angle, maxWinding, 0); 211 (void) segment->markAndChaseWinding(angle, maxWinding, 0);
189 break; 212 break;
190 } 213 }
191 } 214 }
192 *chase->insert(0) = span; 215 *chase->insert(0) = span;
193 return segment; 216 return segment;
194 } 217 }
195 return NULL; 218 return NULL;
196 } 219 }
197 220
198 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY 221 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
199 void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList) { 222 void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList) {
200 int index; 223 int index;
201 for (index = 0; index < contourList.count(); ++ index) { 224 for (index = 0; index < contourList.count(); ++ index) {
202 contourList[index]->debugShowActiveSpans(); 225 contourList[index]->debugShowActiveSpans();
203 } 226 }
204 } 227 }
205 #endif 228 #endif
206 229
207 static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourL ist, 230 static SkOpSegment* findTopSegment(const SkTArray<SkOpContour*, true>& contourLi st, int* index,
208 int* index, int* endIndex, SkPoint* topLeft, bool* unsortable, 231 int* endIndex, SkPoint* topLeft, bool* unsortable, bool* done, bool firs tPass) {
209 bool* done, bool firstPass) {
210 SkOpSegment* result; 232 SkOpSegment* result;
211 const SkOpSegment* lastTopStart = NULL; 233 const SkOpSegment* lastTopStart = NULL;
212 int lastIndex = -1, lastEndIndex = -1; 234 int lastIndex = -1, lastEndIndex = -1;
213 do { 235 do {
214 SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax}; 236 SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
215 int contourCount = contourList.count(); 237 int contourCount = contourList.count();
216 SkOpSegment* topStart = NULL; 238 SkOpSegment* topStart = NULL;
217 *done = true; 239 *done = true;
218 for (int cIndex = 0; cIndex < contourCount; ++cIndex) { 240 for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
219 SkOpContour* contour = contourList[cIndex]; 241 SkOpContour* contour = contourList[cIndex];
(...skipping 22 matching lines...) Expand all
242 if (!result) { 264 if (!result) {
243 if (lastTopStart == topStart && lastIndex == *index && lastEndIndex == *endIndex) { 265 if (lastTopStart == topStart && lastIndex == *index && lastEndIndex == *endIndex) {
244 *done = true; 266 *done = true;
245 return NULL; 267 return NULL;
246 } 268 }
247 lastTopStart = topStart; 269 lastTopStart = topStart;
248 lastIndex = *index; 270 lastIndex = *index;
249 lastEndIndex = *endIndex; 271 lastEndIndex = *endIndex;
250 } 272 }
251 } while (!result); 273 } while (!result);
252 #if 0
253 if (result) {
254 *unsortable = false;
255 }
256 #endif
257 return result; 274 return result;
258 } 275 }
259 276
260 static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList, 277 static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList,
261 SkOpSegment** current, int* index, int* endIndex, d ouble* tHit, 278 SkOpSegment** currentPtr, int* indexPtr, int* endIndexPtr, double* tHit,
262 SkScalar* hitDx, bool* tryAgain, bool opp) { 279 SkScalar* hitDx, bool* tryAgain, bool* onlyVertical, bool opp) {
263 double test = 0.9; 280 double test = 0.9;
264 int contourWinding; 281 int contourWinding;
265 do { 282 do {
266 contourWinding = contourRangeCheckY(contourList, current, index, endInde x, tHit, hitDx, 283 contourWinding = contourRangeCheckY(contourList, currentPtr, indexPtr, e ndIndexPtr,
267 tryAgain, &test, opp); 284 tHit, hitDx, tryAgain, &test, opp);
268 if (contourWinding != SK_MinS32 || *tryAgain) { 285 if (contourWinding != SK_MinS32 || *tryAgain) {
269 return contourWinding; 286 return contourWinding;
270 } 287 }
288 if (*currentPtr && (*currentPtr)->isVertical()) {
289 *onlyVertical = true;
290 return contourWinding;
291 }
271 test /= 2; 292 test /= 2;
272 } while (!approximately_negative(test)); 293 } while (!approximately_negative(test));
273 SkASSERT(0); // should be OK to comment out, but interested when this hits 294 SkASSERT(0); // FIXME: incomplete functionality
274 return contourWinding; 295 return contourWinding;
275 } 296 }
276 297
277 static void skipVertical(const SkTArray<SkOpContour*, true>& contourList, 298 static void skipVertical(const SkTArray<SkOpContour*, true>& contourList,
278 SkOpSegment** current, int* index, int* endIndex) { 299 SkOpSegment** current, int* index, int* endIndex) {
279 if (!(*current)->isVertical(*index, *endIndex)) { 300 if (!(*current)->isVertical(*index, *endIndex)) {
280 return; 301 return;
281 } 302 }
282 int contourCount = contourList.count(); 303 int contourCount = contourList.count();
283 for (int cIndex = 0; cIndex < contourCount; ++cIndex) { 304 for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
284 SkOpContour* contour = contourList[cIndex]; 305 SkOpContour* contour = contourList[cIndex];
285 if (contour->done()) { 306 if (contour->done()) {
286 continue; 307 continue;
287 } 308 }
288 SkOpSegment* nonVertical = contour->nonVerticalSegment(index, endIndex); 309 SkOpSegment* nonVertical = contour->nonVerticalSegment(index, endIndex);
289 if (nonVertical) { 310 if (nonVertical) {
290 *current = nonVertical; 311 *current = nonVertical;
291 return; 312 return;
292 } 313 }
293 } 314 }
294 return; 315 return;
295 } 316 }
296 317
297 SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, 318 SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
298 SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexP tr, 319 SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexP tr,
299 int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done, bool f irstPass) { 320 int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical,
300 SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, t opLeft, unsortable, 321 bool firstPass) {
322 SkOpSegment* current = findTopSegment(contourList, indexPtr, endIndexPtr, to pLeft, unsortable,
301 done, firstPass); 323 done, firstPass);
302 if (!current) { 324 if (!current) {
303 return NULL; 325 return NULL;
304 } 326 }
305 const int index = *indexPtr; 327 const int startIndex = *indexPtr;
306 const int endIndex = *endIndexPtr; 328 const int endIndex = *endIndexPtr;
307 if (*firstContour) { 329 if (*firstContour) {
308 current->initWinding(index, endIndex, angleIncludeType); 330 current->initWinding(startIndex, endIndex, angleIncludeType);
309 *firstContour = false; 331 *firstContour = false;
310 return current; 332 return current;
311 } 333 }
312 int minIndex = SkMin32(index, endIndex); 334 int minIndex = SkMin32(startIndex, endIndex);
313 int sumWinding = current->windSum(minIndex); 335 int sumWinding = current->windSum(minIndex);
314 if (sumWinding != SK_MinS32) { 336 if (sumWinding == SK_MinS32) {
315 return current; 337 int index = endIndex;
338 int oIndex = startIndex;
339 do {
340 const SkOpSpan& span = current->span(index);
341 if ((oIndex < index ? span.fFromAngle : span.fToAngle) == NULL) {
342 current->addSimpleAngle(index);
343 }
344 sumWinding = current->computeSum(oIndex, index, angleIncludeType);
345 SkTSwap(index, oIndex);
346 } while (sumWinding == SK_MinS32 && index == startIndex);
316 } 347 }
317 SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32);
318 const SkOpSpan& span = current->span(endIndex);
319 if ((index < endIndex ? span.fFromAngleIndex : span.fToAngleIndex) < 0) {
320 current->addSimpleAngle(endIndex);
321 }
322 sumWinding = current->computeSum(index, endIndex, angleIncludeType);
323 if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) { 348 if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) {
324 return current; 349 return current;
325 } 350 }
326 int contourWinding; 351 int contourWinding;
327 int oppContourWinding = 0; 352 int oppContourWinding = 0;
328 // the simple upward projection of the unresolved points hit unsortable angl es 353 // the simple upward projection of the unresolved points hit unsortable angl es
329 // shoot rays at right angles to the segment to find its winding, ignoring a ngle cases 354 // shoot rays at right angles to the segment to find its winding, ignoring a ngle cases
330 bool tryAgain; 355 bool tryAgain;
331 double tHit; 356 double tHit;
332 SkScalar hitDx = 0; 357 SkScalar hitDx = 0;
333 SkScalar hitOppDx = 0; 358 SkScalar hitOppDx = 0;
334 do { 359 do {
335 // if current is vertical, find another candidate which is not 360 // if current is vertical, find another candidate which is not
336 // if only remaining candidates are vertical, then they can be marked do ne 361 // if only remaining candidates are vertical, then they can be marked do ne
337 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0); 362 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
338 skipVertical(contourList, &current, indexPtr, endIndexPtr); 363 skipVertical(contourList, &current, indexPtr, endIndexPtr);
339 SkASSERT(current); // FIXME: if null, all remaining are vertical 364 SkASSERT(current); // FIXME: if null, all remaining are vertical
340 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0); 365 SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
341 tryAgain = false; 366 tryAgain = false;
342 contourWinding = rightAngleWinding(contourList, &current, indexPtr, endI ndexPtr, &tHit, 367 contourWinding = rightAngleWinding(contourList, &current, indexPtr, endI ndexPtr, &tHit,
343 &hitDx, &tryAgain, false); 368 &hitDx, &tryAgain, onlyVertical, false);
369 if (*onlyVertical) {
370 return current;
371 }
344 if (tryAgain) { 372 if (tryAgain) {
345 continue; 373 continue;
346 } 374 }
347 if (angleIncludeType < SkOpAngle::kBinarySingle) { 375 if (angleIncludeType < SkOpAngle::kBinarySingle) {
348 break; 376 break;
349 } 377 }
350 oppContourWinding = rightAngleWinding(contourList, &current, indexPtr, e ndIndexPtr, &tHit, 378 oppContourWinding = rightAngleWinding(contourList, &current, indexPtr, e ndIndexPtr, &tHit,
351 &hitOppDx, &tryAgain, true); 379 &hitOppDx, &tryAgain, NULL, true);
352 } while (tryAgain); 380 } while (tryAgain);
353 current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, o ppContourWinding, 381 current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, o ppContourWinding,
354 hitOppDx); 382 hitOppDx);
355 if (current->done()) { 383 if (current->done()) {
356 return NULL; 384 return NULL;
357 } 385 }
358 return current; 386 return current;
359 } 387 }
360 388
361 static bool calcAngles(SkTArray<SkOpContour*, true>* contourList) { 389 static bool calcAngles(SkTArray<SkOpContour*, true>* contourList) {
(...skipping 18 matching lines...) Expand all
380 static void checkEnds(SkTArray<SkOpContour*, true>* contourList) { 408 static void checkEnds(SkTArray<SkOpContour*, true>* contourList) {
381 // it's hard to determine if the end of a cubic or conic nearly intersects a nother curve. 409 // it's hard to determine if the end of a cubic or conic nearly intersects a nother curve.
382 // instead, look to see if the connecting curve intersected at that same end . 410 // instead, look to see if the connecting curve intersected at that same end .
383 int contourCount = (*contourList).count(); 411 int contourCount = (*contourList).count();
384 for (int cTest = 0; cTest < contourCount; ++cTest) { 412 for (int cTest = 0; cTest < contourCount; ++cTest) {
385 SkOpContour* contour = (*contourList)[cTest]; 413 SkOpContour* contour = (*contourList)[cTest];
386 contour->checkEnds(); 414 contour->checkEnds();
387 } 415 }
388 } 416 }
389 417
390 static void checkMultiples(SkTArray<SkOpContour*, true>* contourList) { 418 static bool checkMultiples(SkTArray<SkOpContour*, true>* contourList) {
391 // it's hard to determine if the end of a cubic or conic nearly intersects a nother curve. 419 bool hasMultiples = false;
392 // instead, look to see if the connecting curve intersected at that same end .
393 int contourCount = (*contourList).count(); 420 int contourCount = (*contourList).count();
394 for (int cTest = 0; cTest < contourCount; ++cTest) { 421 for (int cTest = 0; cTest < contourCount; ++cTest) {
395 SkOpContour* contour = (*contourList)[cTest]; 422 SkOpContour* contour = (*contourList)[cTest];
396 contour->checkMultiples(); 423 contour->checkMultiples();
424 hasMultiples |= contour->hasMultiples();
397 } 425 }
426 return hasMultiples;
398 } 427 }
399 428
400 // A small interval of a pair of curves may collapse to lines for each, triggeri ng coincidence 429 // A small interval of a pair of curves may collapse to lines for each, triggeri ng coincidence
401 static void checkSmall(SkTArray<SkOpContour*, true>* contourList) { 430 static void checkSmall(SkTArray<SkOpContour*, true>* contourList) {
402 int contourCount = (*contourList).count(); 431 int contourCount = (*contourList).count();
403 for (int cTest = 0; cTest < contourCount; ++cTest) { 432 for (int cTest = 0; cTest < contourCount; ++cTest) {
404 SkOpContour* contour = (*contourList)[cTest]; 433 SkOpContour* contour = (*contourList)[cTest];
405 contour->checkSmall(); 434 contour->checkSmall();
406 } 435 }
407 } 436 }
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 697
669 bool HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) { 698 bool HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
670 #if DEBUG_SHOW_WINDING 699 #if DEBUG_SHOW_WINDING
671 SkOpContour::debugShowWindingValues(contourList); 700 SkOpContour::debugShowWindingValues(contourList);
672 #endif 701 #endif
673 CoincidenceCheck(contourList, total); 702 CoincidenceCheck(contourList, total);
674 #if DEBUG_SHOW_WINDING 703 #if DEBUG_SHOW_WINDING
675 SkOpContour::debugShowWindingValues(contourList); 704 SkOpContour::debugShowWindingValues(contourList);
676 #endif 705 #endif
677 fixOtherTIndex(contourList); 706 fixOtherTIndex(contourList);
678 checkEnds(contourList); 707 checkEnds(contourList); // check if connecting curve intersected at the sam e end
679 checkMultiples(contourList); 708 bool hasM = checkMultiples(contourList); // check if intersections agree on t and point values
680 checkDuplicates(contourList); 709 SkTDArray<SkOpSegment::AlignedSpan> aligned;
681 checkTiny(contourList); 710 if (hasM) {
682 checkSmall(contourList); 711 alignMultiples(contourList, &aligned); // align pairs of identical poin ts
683 joinCoincidence(contourList); 712 alignCoincidence(contourList, aligned);
713 }
714 checkDuplicates(contourList); // check if spans have the same number on the other end
715 checkTiny(contourList); // if pair have the same end points, mark them as p arallel
716 checkSmall(contourList); // a pair of curves with a small span may turn int o coincident lines
717 joinCoincidence(contourList); // join curves that connect to a coincident p air
684 sortSegments(contourList); 718 sortSegments(contourList);
685 if (!calcAngles(contourList)) { 719 if (!calcAngles(contourList)) {
686 return false; 720 return false;
687 } 721 }
688 sortAngles(contourList); 722 sortAngles(contourList);
689 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY 723 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
690 DebugShowActiveSpans(*contourList); 724 DebugShowActiveSpans(*contourList);
691 #endif 725 #endif
692 return true; 726 return true;
693 } 727 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsCommon.h ('k') | src/pathops/SkPathOpsDebug.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698