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

Side by Side Diff: src/pathops/SkOpSegment.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/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 "SkOpContour.h"
8 #include "SkOpSegment.h" 9 #include "SkOpSegment.h"
9 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
10 #include "SkTSort.h" 11 #include "SkTSort.h"
11 12
12 #define F (false) // discard the edge 13 #define F (false) // discard the edge
13 #define T (true) // keep the edge 14 #define T (true) // keep the edge
14 15
15 static const bool gUnaryActiveEdge[2][2] = { 16 static const bool gUnaryActiveEdge[2][2] = {
16 // from=0 from=1 17 // from=0 from=1
17 // to=0,1 to=0,1 18 // to=0,1 to=0,1
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 suFrom = (maxWinding & xorSuMask) != 0; 181 suFrom = (maxWinding & xorSuMask) != 0;
181 suTo = (sumWinding & xorSuMask) != 0; 182 suTo = (sumWinding & xorSuMask) != 0;
182 } else { 183 } else {
183 miFrom = (maxWinding & xorMiMask) != 0; 184 miFrom = (maxWinding & xorMiMask) != 0;
184 miTo = (sumWinding & xorMiMask) != 0; 185 miTo = (sumWinding & xorMiMask) != 0;
185 suFrom = (oppMaxWinding & xorSuMask) != 0; 186 suFrom = (oppMaxWinding & xorSuMask) != 0;
186 suTo = (oppSumWinding & xorSuMask) != 0; 187 suTo = (oppSumWinding & xorSuMask) != 0;
187 } 188 }
188 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; 189 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
189 #if DEBUG_ACTIVE_OP 190 #if DEBUG_ACTIVE_OP
190 SkDebugf("%s op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", __FUNCT ION__, 191 SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo =%d result=%d\n",
192 __FUNCTION__, debugID(), span(index).fT, span(endIndex).fT,
191 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); 193 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result);
192 #endif 194 #endif
193 return result; 195 return result;
194 } 196 }
195 197
196 bool SkOpSegment::activeWinding(int index, int endIndex) { 198 bool SkOpSegment::activeWinding(int index, int endIndex) {
197 int sumWinding = updateWinding(endIndex, index); 199 int sumWinding = updateWinding(endIndex, index);
198 return activeWinding(index, endIndex, &sumWinding); 200 return activeWinding(index, endIndex, &sumWinding);
199 } 201 }
200 202
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 default: 399 default:
398 SkASSERT(0); 400 SkASSERT(0);
399 } 401 }
400 } 402 }
401 } 403 }
402 // return ePtr[SkPathOpsVerbToPoints(fVerb)]; 404 // return ePtr[SkPathOpsVerbToPoints(fVerb)];
403 } 405 }
404 406
405 void SkOpSegment::addEndSpan(int endIndex) { 407 void SkOpSegment::addEndSpan(int endIndex) {
406 int spanCount = fTs.count(); 408 int spanCount = fTs.count();
407 int angleIndex = fAngles.count();
408 int startIndex = endIndex - 1; 409 int startIndex = endIndex - 1;
409 while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) { 410 while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) {
410 ++startIndex; 411 ++startIndex;
411 SkASSERT(startIndex < spanCount - 1); 412 SkASSERT(startIndex < spanCount - 1);
412 ++endIndex; 413 ++endIndex;
413 } 414 }
414 fAngles.push_back().set(this, spanCount - 1, startIndex); 415 SkOpAngle& angle = fAngles.push_back();
416 angle.set(this, spanCount - 1, startIndex);
415 #if DEBUG_ANGLE 417 #if DEBUG_ANGLE
416 fAngles.back().setID(angleIndex);
417 debugCheckPointsEqualish(endIndex, spanCount); 418 debugCheckPointsEqualish(endIndex, spanCount);
418 #endif 419 #endif
419 setFromAngleIndex(endIndex, angleIndex); 420 setFromAngle(endIndex, &angle);
420 } 421 }
421 422
422 void SkOpSegment::setFromAngleIndex(int endIndex, int angleIndex) { 423 void SkOpSegment::setFromAngle(int endIndex, SkOpAngle* angle) {
423 int spanCount = fTs.count(); 424 int spanCount = fTs.count();
424 do { 425 do {
425 fTs[endIndex].fFromAngleIndex = angleIndex; 426 fTs[endIndex].fFromAngle = angle;
426 } while (++endIndex < spanCount); 427 } while (++endIndex < spanCount);
427 } 428 }
428 429
429 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) { 430 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) {
430 init(pts, SkPath::kLine_Verb, operand, evenOdd); 431 init(pts, SkPath::kLine_Verb, operand, evenOdd);
431 fBounds.set(pts, 2); 432 fBounds.set(pts, 2);
432 } 433 }
433 434
434 // add 2 to edge or out of range values to get T extremes 435 // add 2 to edge or out of range values to get T extremes
435 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) { 436 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) {
436 SkOpSpan& span = fTs[index]; 437 SkOpSpan& span = fTs[index];
437 if (precisely_zero(otherT)) { 438 if (precisely_zero(otherT)) {
438 otherT = 0; 439 otherT = 0;
439 } else if (precisely_equal(otherT, 1)) { 440 } else if (precisely_equal(otherT, 1)) {
440 otherT = 1; 441 otherT = 1;
441 } 442 }
442 span.fOtherT = otherT; 443 span.fOtherT = otherT;
443 span.fOtherIndex = otherIndex; 444 span.fOtherIndex = otherIndex;
444 } 445 }
445 446
446 void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) { 447 void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) {
447 init(pts, SkPath::kQuad_Verb, operand, evenOdd); 448 init(pts, SkPath::kQuad_Verb, operand, evenOdd);
448 fBounds.setQuadBounds(pts); 449 fBounds.setQuadBounds(pts);
449 } 450 }
450 451
451 int SkOpSegment::addSingletonAngleDown(int endIndex, SkOpSegment** otherPtr) { 452 SkOpAngle* SkOpSegment::addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle* * anglePtr) {
452 int startIndex = findEndSpan(endIndex); 453 int spanIndex = count() - 1;
453 SkASSERT(startIndex > 0); 454 int startIndex = nextExactSpan(spanIndex, -1);
454 int spanIndex = endIndex - 1; 455 SkASSERT(startIndex >= 0);
455 fSingletonAngles.push_back().set(this, spanIndex, startIndex - 1); 456 SkOpAngle& angle = fAngles.push_back();
456 setFromAngleIndex(startIndex, fAngles.count() + fSingletonAngles.count() - 1 ); 457 *anglePtr = &angle;
458 angle.set(this, spanIndex, startIndex);
459 setFromAngle(spanIndex, &angle);
457 SkOpSegment* other; 460 SkOpSegment* other;
461 int oStartIndex, oEndIndex;
458 do { 462 do {
459 other = fTs[spanIndex].fOther; 463 const SkOpSpan& span = fTs[spanIndex];
460 if (other->fTs[0].fWindValue) { 464 SkASSERT(span.fT > 0);
465 other = span.fOther;
466 oStartIndex = span.fOtherIndex;
467 oEndIndex = other->nextExactSpan(oStartIndex, 1);
468 if (oEndIndex > 0 && other->span(oStartIndex).fWindValue) {
461 break; 469 break;
462 } 470 }
471 oEndIndex = oStartIndex;
472 oStartIndex = other->nextExactSpan(oEndIndex, -1);
463 --spanIndex; 473 --spanIndex;
464 SkASSERT(fTs[spanIndex].fT == 1); 474 } while (oStartIndex < 0 || !other->span(oStartIndex).fWindSum);
465 } while (true); 475 SkOpAngle& oAngle = other->fAngles.push_back();
466 int oEndIndex = other->findStartSpan(0); 476 oAngle.set(other, oStartIndex, oEndIndex);
467 SkASSERT(oEndIndex > 0); 477 other->setToAngle(oEndIndex, &oAngle);
468 int otherIndex = other->fSingletonAngles.count();
469 other->fSingletonAngles.push_back().set(other, 0, oEndIndex);
470 other->setToAngleIndex(oEndIndex, other->fAngles.count() + otherIndex);
471 *otherPtr = other; 478 *otherPtr = other;
472 return otherIndex; 479 return &oAngle;
473 } 480 }
474 481
475 int SkOpSegment::addSingletonAngleUp(int start, SkOpSegment** otherPtr) { 482 SkOpAngle* SkOpSegment::addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** anglePtr) {
476 int endIndex = findStartSpan(start); 483 int endIndex = nextExactSpan(0, 1);
477 SkASSERT(endIndex > 0); 484 SkASSERT(endIndex > 0);
478 int thisIndex = fSingletonAngles.count(); 485 SkOpAngle& angle = fAngles.push_back();
479 fSingletonAngles.push_back().set(this, start, endIndex); 486 *anglePtr = &angle;
480 setToAngleIndex(endIndex, fAngles.count() + thisIndex); 487 angle.set(this, 0, endIndex);
481 int spanIndex = start; 488 setToAngle(endIndex, &angle);
489 int spanIndex = 0;
482 SkOpSegment* other; 490 SkOpSegment* other;
483 int oCount, oStartIndex; 491 int oStartIndex, oEndIndex;
484 do { 492 do {
485 other = fTs[spanIndex].fOther; 493 const SkOpSpan& span = fTs[spanIndex];
486 oCount = other->count(); 494 SkASSERT(span.fT < 1);
487 oStartIndex = other->findEndSpan(oCount); 495 other = span.fOther;
488 SkASSERT(oStartIndex > 0); 496 oEndIndex = span.fOtherIndex;
489 if (other->fTs[oStartIndex - 1].fWindValue) { 497 oStartIndex = other->nextExactSpan(oEndIndex, -1);
498 if (oStartIndex >= 0 && other->span(oStartIndex).fWindValue) {
490 break; 499 break;
491 } 500 }
501 oStartIndex = oEndIndex;
502 oEndIndex = other->nextExactSpan(oStartIndex, 1);
492 ++spanIndex; 503 ++spanIndex;
493 SkASSERT(fTs[spanIndex].fT == 0); 504 } while (oEndIndex < 0 || !other->span(oStartIndex).fWindValue);
494 } while (true); 505 SkOpAngle& oAngle = other->fAngles.push_back();
495 int otherIndex = other->fSingletonAngles.count(); 506 oAngle.set(other, oEndIndex, oStartIndex);
496 other->fSingletonAngles.push_back().set(other, oCount - 1, oStartIndex - 1); 507 other->setFromAngle(oEndIndex, &oAngle);
497 other->setFromAngleIndex(oStartIndex, other->fAngles.count() + otherIndex);
498 *otherPtr = other; 508 *otherPtr = other;
499 return otherIndex; 509 return &oAngle;
500 } 510 }
501 511
502 SkOpAngle* SkOpSegment::addSingletonAngles(int start, int step) { 512 SkOpAngle* SkOpSegment::addSingletonAngles(int step) {
503 int thisIndex = fSingletonAngles.count();
504 SkOpSegment* other; 513 SkOpSegment* other;
505 int otherIndex; 514 SkOpAngle* angle, * otherAngle;
506 if (step > 0) { 515 if (step > 0) {
507 otherIndex = addSingletonAngleUp(start, &other); 516 otherAngle = addSingletonAngleUp(&other, &angle);
508 } else { 517 } else {
509 otherIndex = addSingletonAngleDown(start + 1, &other); 518 otherAngle = addSingletonAngleDown(&other, &angle);
510 } 519 }
511 fSingletonAngles[thisIndex].insert(&other->fSingletonAngles[otherIndex]); 520 angle->insert(otherAngle);
512 #if DEBUG_ANGLE 521 return angle;
513 fSingletonAngles[thisIndex].setID(fAngles.count() + thisIndex);
514 other->fSingletonAngles[otherIndex].setID(other->fAngles.count() + otherInde x);
515 #endif
516 return &fSingletonAngles[thisIndex];
517 } 522 }
518 523
519 void SkOpSegment::addStartSpan(int endIndex) { 524 void SkOpSegment::addStartSpan(int endIndex) {
520 int angleIndex = fAngles.count();
521 int index = 0; 525 int index = 0;
522 fAngles.push_back().set(this, index, endIndex); 526 SkOpAngle& angle = fAngles.push_back();
527 angle.set(this, index, endIndex);
523 #if DEBUG_ANGLE 528 #if DEBUG_ANGLE
524 fAngles.back().setID(angleIndex);
525 debugCheckPointsEqualish(index, endIndex); 529 debugCheckPointsEqualish(index, endIndex);
526 #endif 530 #endif
527 setToAngleIndex(endIndex, angleIndex); 531 setToAngle(endIndex, &angle);
528 } 532 }
529 533
530 void SkOpSegment::setToAngleIndex(int endIndex, int angleIndex) { 534 void SkOpSegment::setToAngle(int endIndex, SkOpAngle* angle) {
531 int index = 0; 535 int index = 0;
532 do { 536 do {
533 fTs[index].fToAngleIndex = angleIndex; 537 fTs[index].fToAngle = angle;
534 } while (++index < endIndex); 538 } while (++index < endIndex);
535 } 539 }
536 540
537 // Defer all coincident edge processing until 541 // Defer all coincident edge processing until
538 // after normal intersections have been computed 542 // after normal intersections have been computed
539 543
540 // no need to be tricky; insert in normal T order 544 // no need to be tricky; insert in normal T order
541 // resolve overlapping ts when considering coincidence later 545 // resolve overlapping ts when considering coincidence later
542 546
543 // add non-coincident intersection. Resulting edges are sorted in T. 547 // add non-coincident intersection. Resulting edges are sorted in T.
544 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { 548 int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) {
545 SkASSERT(this != other || fVerb == SkPath::kCubic_Verb); 549 SkASSERT(this != other || fVerb == SkPath::kCubic_Verb);
546 #if 0 // this needs an even rougher association to be useful 550 #if 0 // this needs an even rougher association to be useful
547 SkASSERT(SkDPoint::RoughlyEqual(ptAtT(newT), pt)); 551 SkASSERT(SkDPoint::RoughlyEqual(ptAtT(newT), pt));
548 #endif 552 #endif
549 if (precisely_zero(newT)) { 553 const SkPoint& firstPt = fPts[0];
550 newT = 0; 554 const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)];
551 } else if (precisely_equal(newT, 1)) { 555 SkASSERT(newT == 0 || !precisely_zero(newT));
552 newT = 1; 556 SkASSERT(newT == 1 || !precisely_equal(newT, 1));
553 }
554 // FIXME: in the pathological case where there is a ton of intercepts, 557 // FIXME: in the pathological case where there is a ton of intercepts,
555 // binary search? 558 // binary search?
556 int insertedAt = -1; 559 int insertedAt = -1;
557 int tCount = fTs.count(); 560 int tCount = fTs.count();
558 const SkPoint& firstPt = fPts[0];
559 const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)];
560 for (int index = 0; index < tCount; ++index) { 561 for (int index = 0; index < tCount; ++index) {
561 // OPTIMIZATION: if there are three or more identical Ts, then 562 // OPTIMIZATION: if there are three or more identical Ts, then
562 // the fourth and following could be further insertion-sorted so 563 // the fourth and following could be further insertion-sorted so
563 // that all the edges are clockwise or counterclockwise. 564 // that all the edges are clockwise or counterclockwise.
564 // This could later limit segment tests to the two adjacent 565 // This could later limit segment tests to the two adjacent
565 // neighbors, although it doesn't help with determining which 566 // neighbors, although it doesn't help with determining which
566 // circular direction to go in. 567 // circular direction to go in.
567 const SkOpSpan& span = fTs[index]; 568 const SkOpSpan& span = fTs[index];
568 if (newT < span.fT) { 569 if (newT < span.fT) {
569 insertedAt = index; 570 insertedAt = index;
(...skipping 11 matching lines...) Expand all
581 } 582 }
582 } 583 }
583 SkOpSpan* span; 584 SkOpSpan* span;
584 if (insertedAt >= 0) { 585 if (insertedAt >= 0) {
585 span = fTs.insert(insertedAt); 586 span = fTs.insert(insertedAt);
586 } else { 587 } else {
587 insertedAt = tCount; 588 insertedAt = tCount;
588 span = fTs.append(); 589 span = fTs.append();
589 } 590 }
590 span->fT = newT; 591 span->fT = newT;
592 #if SK_DEBUG
593 span->fOtherT = -1;
594 #endif
591 span->fOther = other; 595 span->fOther = other;
592 span->fPt = pt; 596 span->fPt = pt;
593 #if 0 597 #if 0
594 // cubics, for instance, may not be exact enough to satisfy this check (e.g. , cubicOp69d) 598 // cubics, for instance, may not be exact enough to satisfy this check (e.g. , cubicOp69d)
595 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) 599 SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX)
596 && approximately_equal(xyAtT(newT).fY, pt.fY)); 600 && approximately_equal(xyAtT(newT).fY, pt.fY));
597 #endif 601 #endif
598 span->fFromAngleIndex = -1; 602 span->fFromAngle = NULL;
599 span->fToAngleIndex = -1; 603 span->fToAngle = NULL;
600 span->fWindSum = SK_MinS32; 604 span->fWindSum = SK_MinS32;
601 span->fOppSum = SK_MinS32; 605 span->fOppSum = SK_MinS32;
602 span->fWindValue = 1; 606 span->fWindValue = 1;
603 span->fOppValue = 0; 607 span->fOppValue = 0;
604 span->fChased = false; 608 span->fChased = false;
609 span->fCoincident = false;
610 span->fLoop = false;
611 span->fNear = false;
612 span->fMultiple = false;
613 span->fSmall = false;
614 span->fTiny = false;
605 if ((span->fDone = newT == 1)) { 615 if ((span->fDone = newT == 1)) {
606 ++fDoneSpans; 616 ++fDoneSpans;
607 } 617 }
608 span->fLoop = false;
609 span->fSmall = false;
610 span->fTiny = false;
611 int less = -1; 618 int less = -1;
619 // FIXME: note that this relies on spans being a continguous array
612 // find range of spans with nearly the same point as this one 620 // find range of spans with nearly the same point as this one
613 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) { 621 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) {
614 if (fVerb == SkPath::kCubic_Verb) { 622 if (fVerb == SkPath::kCubic_Verb) {
615 double tInterval = newT - span[less].fT; 623 double tInterval = newT - span[less].fT;
616 double tMid = newT - tInterval / 2; 624 double tMid = newT - tInterval / 2;
617 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); 625 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid);
618 if (!midPt.approximatelyEqual(xyAtT(span))) { 626 if (!midPt.approximatelyEqual(xyAtT(span))) {
619 break; 627 break;
620 } 628 }
621 } 629 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS egment* other) { 688 void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS egment* other) {
681 bool binary = fOperand != other->fOperand; 689 bool binary = fOperand != other->fOperand;
682 int index = 0; 690 int index = 0;
683 while (startPt != fTs[index].fPt) { 691 while (startPt != fTs[index].fPt) {
684 SkASSERT(index < fTs.count()); 692 SkASSERT(index < fTs.count());
685 ++index; 693 ++index;
686 } 694 }
687 while (index > 0 && precisely_equal(fTs[index].fT, fTs[index - 1].fT)) { 695 while (index > 0 && precisely_equal(fTs[index].fT, fTs[index - 1].fT)) {
688 --index; 696 --index;
689 } 697 }
698 bool oFoundEnd = false;
690 int oIndex = other->fTs.count(); 699 int oIndex = other->fTs.count();
691 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match 700 while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match
692 SkASSERT(oIndex > 0); 701 SkASSERT(oIndex > 0);
693 } 702 }
694 double oStartT = other->fTs[oIndex].fT; 703 double oStartT = other->fTs[oIndex].fT;
695 // look for first point beyond match 704 // look for first point beyond match
696 while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other ->fTs[oIndex].fT)) { 705 while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other ->fTs[oIndex].fT)) {
697 SkASSERT(oIndex > 0); 706 SkASSERT(oIndex > 0);
698 } 707 }
699 SkOpSpan* test = &fTs[index]; 708 SkOpSpan* test = &fTs[index];
700 SkOpSpan* oTest = &other->fTs[oIndex]; 709 SkOpSpan* oTest = &other->fTs[oIndex];
701 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; 710 SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts;
702 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 711 SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts;
712 bool decrement, track, bigger;
713 int originalWindValue;
714 const SkPoint* testPt;
715 const SkPoint* oTestPt;
703 do { 716 do {
704 SkASSERT(test->fT < 1); 717 SkASSERT(test->fT < 1);
705 SkASSERT(oTest->fT < 1); 718 SkASSERT(oTest->fT < 1);
706 bool decrement = test->fWindValue && oTest->fWindValue; 719 decrement = test->fWindValue && oTest->fWindValue;
707 bool track = test->fWindValue || oTest->fWindValue; 720 track = test->fWindValue || oTest->fWindValue;
708 bool bigger = test->fWindValue >= oTest->fWindValue; 721 bigger = test->fWindValue >= oTest->fWindValue;
709 const SkPoint& testPt = test->fPt; 722 testPt = &test->fPt;
710 double testT = test->fT; 723 double testT = test->fT;
711 const SkPoint& oTestPt = oTest->fPt; 724 oTestPt = &oTest->fPt;
712 double oTestT = oTest->fT; 725 double oTestT = oTest->fT;
713 do { 726 do {
714 if (decrement) { 727 if (decrement) {
715 if (binary && bigger) { 728 if (binary && bigger) {
716 test->fOppValue--; 729 test->fOppValue--;
717 } else { 730 } else {
718 decrementSpan(test); 731 decrementSpan(test);
719 } 732 }
720 } else if (track) { 733 } else if (track) {
721 TrackOutsidePair(&outsidePts, testPt, oTestPt); 734 TrackOutsidePair(&outsidePts, *testPt, *oTestPt);
722 } 735 }
723 SkASSERT(index < fTs.count() - 1); 736 SkASSERT(index < fTs.count() - 1);
724 test = &fTs[++index]; 737 test = &fTs[++index];
725 } while (testPt == test->fPt || precisely_equal(testT, test->fT)); 738 } while (*testPt == test->fPt || precisely_equal(testT, test->fT));
726 SkDEBUGCODE(int originalWindValue = oTest->fWindValue); 739 originalWindValue = oTest->fWindValue;
727 do { 740 do {
728 SkASSERT(oTest->fT < 1); 741 SkASSERT(oTest->fT < 1);
729 SkASSERT(originalWindValue == oTest->fWindValue); 742 SkASSERT(originalWindValue == oTest->fWindValue);
730 if (decrement) { 743 if (decrement) {
731 if (binary && !bigger) { 744 if (binary && !bigger) {
732 oTest->fOppValue--; 745 oTest->fOppValue--;
733 } else { 746 } else {
734 other->decrementSpan(oTest); 747 other->decrementSpan(oTest);
735 } 748 }
736 } else if (track) { 749 } else if (track) {
737 TrackOutsidePair(&oOutsidePts, oTestPt, testPt); 750 TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt);
751 }
752 if (!oIndex) {
753 break;
754 }
755 oFoundEnd |= endPt == oTest->fPt;
756 oTest = &other->fTs[--oIndex];
757 } while (*oTestPt == oTest->fPt || precisely_equal(oTestT, oTest->fT));
758 } while (endPt != test->fPt && test->fT < 1);
759 // FIXME: determine if canceled edges need outside ts added
760 if (!oFoundEnd) {
761 for (int oIdx2 = oIndex; oIdx2 >= 0; --oIdx2) {
762 SkOpSpan* oTst2 = &other->fTs[oIdx2];
763 if (originalWindValue != oTst2->fWindValue) {
764 goto skipAdvanceOtherCancel;
765 }
766 if (!oTst2->fWindValue) {
767 goto skipAdvanceOtherCancel;
768 }
769 if (endPt == other->fTs[oIdx2].fPt) {
770 break;
771 }
772 }
773 do {
774 SkASSERT(originalWindValue == oTest->fWindValue);
775 if (decrement) {
776 if (binary && !bigger) {
777 oTest->fOppValue--;
778 } else {
779 other->decrementSpan(oTest);
780 }
781 } else if (track) {
782 TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt);
738 } 783 }
739 if (!oIndex) { 784 if (!oIndex) {
740 break; 785 break;
741 } 786 }
742 oTest = &other->fTs[--oIndex]; 787 oTest = &other->fTs[--oIndex];
743 } while (oTestPt == oTest->fPt || precisely_equal(oTestT, oTest->fT)); 788 oFoundEnd |= endPt == oTest->fPt;
744 } while (endPt != test->fPt && test->fT < 1); 789 } while (!oFoundEnd || endPt == oTest->fPt);
745 // FIXME: determine if canceled edges need outside ts added 790 }
791 skipAdvanceOtherCancel:
746 int outCount = outsidePts.count(); 792 int outCount = outsidePts.count();
747 if (!done() && outCount) { 793 if (!done() && outCount) {
748 addCancelOutsides(outsidePts[0], outsidePts[1], other); 794 addCancelOutsides(outsidePts[0], outsidePts[1], other);
749 if (outCount > 2) { 795 if (outCount > 2) {
750 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other); 796 addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1] , other);
751 } 797 }
752 } 798 }
753 if (!other->done() && oOutsidePts.count()) { 799 if (!other->done() && oOutsidePts.count()) {
754 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this); 800 other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this);
755 } 801 }
802 setCoincidentRange(startPt, endPt, other);
803 other->setCoincidentRange(startPt, endPt, this);
756 } 804 }
757 805
758 int SkOpSegment::addSelfT(const SkPoint& pt, double newT) { 806 int SkOpSegment::addSelfT(const SkPoint& pt, double newT) {
759 // if the tail nearly intersects itself but not quite, the caller records th is separately 807 // if the tail nearly intersects itself but not quite, the caller records th is separately
760 int result = addT(this, pt, newT); 808 int result = addT(this, pt, newT);
761 SkOpSpan* span = &fTs[result]; 809 SkOpSpan* span = &fTs[result];
762 fLoop = span->fLoop = true; 810 fLoop = span->fLoop = true;
763 return result; 811 return result;
764 } 812 }
765 813
814 // find the starting or ending span with an existing loop of angles
815 // FIXME? replicate for all identical starting/ending spans?
816 // OPTIMIZE? remove the spans pointing to windValue==0 here or earlier?
817 // FIXME? assert that only one other span has a valid windValue or oppValue
766 void SkOpSegment::addSimpleAngle(int index) { 818 void SkOpSegment::addSimpleAngle(int index) {
819 SkOpSpan* span = &fTs[index];
767 if (index == 0) { 820 if (index == 0) {
768 SkASSERT(!fTs[index].fTiny && fTs[index + 1].fT > 0); 821 do {
822 if (span->fToAngle) {
823 SkASSERT(span->fToAngle->loopCount() == 2);
824 SkASSERT(!span->fFromAngle);
825 span->fFromAngle = span->fToAngle->next();
826 return;
827 }
828 span = &fTs[++index];
829 } while (span->fT == 0);
830 SkASSERT(index == 1);
831 index = 0;
832 SkASSERT(!fTs[0].fTiny && fTs[1].fT > 0);
769 addStartSpan(1); 833 addStartSpan(1);
770 } else { 834 } else {
835 do {
836 if (span->fFromAngle) {
837 SkASSERT(span->fFromAngle->loopCount() == 2);
838 SkASSERT(!span->fToAngle);
839 span->fToAngle = span->fFromAngle->next();
840 return;
841 }
842 span = &fTs[--index];
843 } while (span->fT == 1);
844 SkASSERT(index == count() - 2);
845 index = count() - 1;
771 SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1); 846 SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1);
772 addEndSpan(index); 847 addEndSpan(index);
773 } 848 }
774 SkOpSpan& span = fTs[index]; 849 span = &fTs[index];
775 SkOpSegment* other = span.fOther; 850 SkOpSegment* other = span->fOther;
776 SkOpSpan& oSpan = other->fTs[span.fOtherIndex]; 851 SkOpSpan& oSpan = other->fTs[span->fOtherIndex];
777 SkOpAngle* angle, * oAngle; 852 SkOpAngle* angle, * oAngle;
778 if (index == 0) { 853 if (index == 0) {
779 SkASSERT(span.fOtherIndex - 1 >= 0); 854 SkASSERT(span->fOtherIndex - 1 >= 0);
780 SkASSERT(span.fOtherT == 1); 855 SkASSERT(span->fOtherT == 1);
781 SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span.fOtherIndex - 1]); 856 SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span->fOtherIndex - 1]);
782 SkASSERT(!oPrior.fTiny && oPrior.fT < 1); 857 SkASSERT(!oPrior.fTiny && oPrior.fT < 1);
783 other->addEndSpan(span.fOtherIndex); 858 other->addEndSpan(span->fOtherIndex);
784 angle = &this->angle(span.fToAngleIndex); 859 angle = span->fToAngle;
785 oAngle = &other->angle(oSpan.fFromAngleIndex); 860 oAngle = oSpan.fFromAngle;
786 } else { 861 } else {
787 SkASSERT(span.fOtherIndex + 1 < other->count()); 862 SkASSERT(span->fOtherIndex + 1 < other->count());
788 SkASSERT(span.fOtherT == 0); 863 SkASSERT(span->fOtherT == 0);
789 SkASSERT(!oSpan.fTiny && (other->fTs[span.fOtherIndex + 1].fT > 0 864 SkASSERT(!oSpan.fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0
790 || (other->fTs[span.fOtherIndex + 1].fFromAngleIndex < 0 865 || (other->fTs[span->fOtherIndex + 1].fFromAngle == NULL
791 && other->fTs[span.fOtherIndex + 1].fToAngleIndex < 0))); 866 && other->fTs[span->fOtherIndex + 1].fToAngle == NULL)));
792 int oIndex = 1; 867 int oIndex = 1;
793 do { 868 do {
794 const SkOpSpan& osSpan = other->span(oIndex); 869 const SkOpSpan& osSpan = other->span(oIndex);
795 if (osSpan.fFromAngleIndex >= 0 || osSpan.fT > 0) { 870 if (osSpan.fFromAngle || osSpan.fT > 0) {
796 break; 871 break;
797 } 872 }
798 ++oIndex; 873 ++oIndex;
799 SkASSERT(oIndex < other->count()); 874 SkASSERT(oIndex < other->count());
800 } while (true); 875 } while (true);
801 other->addStartSpan(oIndex); 876 other->addStartSpan(oIndex);
802 angle = &this->angle(span.fFromAngleIndex); 877 angle = span->fFromAngle;
803 oAngle = &other->angle(oSpan.fToAngleIndex); 878 oAngle = oSpan.fToAngle;
804 } 879 }
805 angle->insert(oAngle); 880 angle->insert(oAngle);
806 } 881 }
807 882
883 void SkOpSegment::alignMultiples(SkTDArray<AlignedSpan>* alignedArray) {
884 debugValidate();
885 int count = this->count();
886 for (int index = 0; index < count; ++index) {
887 SkOpSpan& span = fTs[index];
888 if (!span.fMultiple) {
889 continue;
890 }
891 int end = nextExactSpan(index, 1);
892 SkASSERT(end > index + 1);
893 const SkPoint& thisPt = span.fPt;
894 while (index < end - 1) {
895 SkOpSegment* other1 = span.fOther;
896 int oCnt = other1->count();
897 for (int idx2 = index + 1; idx2 < end; ++idx2) {
898 SkOpSpan& span2 = fTs[idx2];
899 SkOpSegment* other2 = span2.fOther;
900 for (int oIdx = 0; oIdx < oCnt; ++oIdx) {
901 SkOpSpan& oSpan = other1->fTs[oIdx];
902 if (oSpan.fOther != other2) {
903 continue;
904 }
905 if (oSpan.fPt == thisPt) {
906 goto skipExactMatches;
907 }
908 }
909 for (int oIdx = 0; oIdx < oCnt; ++oIdx) {
910 SkOpSpan& oSpan = other1->fTs[oIdx];
911 if (oSpan.fOther != other2) {
912 continue;
913 }
914 if (SkDPoint::RoughlyEqual(oSpan.fPt, thisPt)) {
915 SkOpSpan& oSpan2 = other2->fTs[oSpan.fOtherIndex];
916 if (zero_or_one(span.fOtherT) || zero_or_one(oSpan.fT)
917 || zero_or_one(span2.fOtherT) || zero_or_one(oSp an2.fT)) {
918 return;
919 }
920 if (!way_roughly_equal(span.fOtherT, oSpan.fT)
921 || !way_roughly_equal(span2.fOtherT, oSpan2.fT)
922 || !way_roughly_equal(span2.fOtherT, oSpan.fOthe rT)
923 || !way_roughly_equal(span.fOtherT, oSpan2.fOthe rT)) {
924 return;
925 }
926 alignSpan(thisPt, span.fOtherT, other1, span2.fOtherT,
927 other2, &oSpan, alignedArray);
928 alignSpan(thisPt, span2.fOtherT, other2, span.fOtherT,
929 other1, &oSpan2, alignedArray);
930 break;
931 }
932 }
933 skipExactMatches:
934 ;
935 }
936 ++index;
937 }
938 }
939 debugValidate();
940 }
941
942 void SkOpSegment::alignSpan(const SkPoint& newPt, double newT, const SkOpSegment * other,
943 double otherT, const SkOpSegment* other2, SkOpSpan* oSpan,
944 SkTDArray<AlignedSpan>* alignedArray) {
945 AlignedSpan* aligned = alignedArray->append();
946 aligned->fOldPt = oSpan->fPt;
947 aligned->fPt = newPt;
948 aligned->fOldT = oSpan->fT;
949 aligned->fT = newT;
950 aligned->fSegment = this; // OPTIMIZE: may be unused, can remove
951 aligned->fOther1 = other;
952 aligned->fOther2 = other2;
953 SkASSERT(SkDPoint::RoughlyEqual(oSpan->fPt, newPt));
954 oSpan->fPt = newPt;
955 // SkASSERT(way_roughly_equal(oSpan->fT, newT));
956 oSpan->fT = newT;
957 // SkASSERT(way_roughly_equal(oSpan->fOtherT, otherT));
958 oSpan->fOtherT = otherT;
959 }
960
808 bool SkOpSegment::alignSpan(int index, double thisT, const SkPoint& thisPt) { 961 bool SkOpSegment::alignSpan(int index, double thisT, const SkPoint& thisPt) {
809 bool aligned = false; 962 bool aligned = false;
810 SkOpSpan* span = &fTs[index]; 963 SkOpSpan* span = &fTs[index];
811 SkOpSegment* other = span->fOther; 964 SkOpSegment* other = span->fOther;
812 int oIndex = span->fOtherIndex; 965 int oIndex = span->fOtherIndex;
813 SkOpSpan* oSpan = &other->fTs[oIndex]; 966 SkOpSpan* oSpan = &other->fTs[oIndex];
814 if (span->fT != thisT) { 967 if (span->fT != thisT) {
815 span->fT = thisT; 968 span->fT = thisT;
816 oSpan->fOtherT = thisT; 969 oSpan->fOtherT = thisT;
817 aligned = true; 970 aligned = true;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 if (span->fDone != allDone) { 1023 if (span->fDone != allDone) {
871 span->fDone = allDone; 1024 span->fDone = allDone;
872 fDoneSpans += allDone ? 1 : -1; 1025 fDoneSpans += allDone ? 1 : -1;
873 } 1026 }
874 SkASSERT(span->fWindValue == winding); 1027 SkASSERT(span->fWindValue == winding);
875 SkASSERT(span->fOppValue == oppWinding); 1028 SkASSERT(span->fOppValue == oppWinding);
876 ++index; 1029 ++index;
877 } 1030 }
878 } 1031 }
879 1032
1033 void SkOpSegment::blindCancel(const SkCoincidence& coincidence, SkOpSegment* oth er) {
1034 bool binary = fOperand != other->fOperand;
1035 int index = 0;
1036 int last = this->count();
1037 do {
1038 SkOpSpan& span = this->fTs[--last];
1039 if (span.fT != 1 && !span.fSmall) {
1040 break;
1041 }
1042 span.fCoincident = true;
1043 } while (true);
1044 int oIndex = other->count();
1045 do {
1046 SkOpSpan& oSpan = other->fTs[--oIndex];
1047 if (oSpan.fT != 1 && !oSpan.fSmall) {
1048 break;
1049 }
1050 oSpan.fCoincident = true;
1051 } while (true);
1052 do {
1053 SkOpSpan* test = &this->fTs[index];
1054 int baseWind = test->fWindValue;
1055 int baseOpp = test->fOppValue;
1056 int endIndex = index;
1057 while (++endIndex <= last) {
1058 SkOpSpan* endSpan = &this->fTs[endIndex];
1059 SkASSERT(endSpan->fT < 1);
1060 if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp ) {
1061 break;
1062 }
1063 endSpan->fCoincident = true;
1064 }
1065 SkOpSpan* oTest = &other->fTs[oIndex];
1066 int oBaseWind = oTest->fWindValue;
1067 int oBaseOpp = oTest->fOppValue;
1068 int oStartIndex = oIndex;
1069 while (--oStartIndex >= 0) {
1070 SkOpSpan* oStartSpan = &other->fTs[oStartIndex];
1071 if (oStartSpan->fWindValue != oBaseWind || oStartSpan->fOppValue != oBaseOpp) {
1072 break;
1073 }
1074 oStartSpan->fCoincident = true;
1075 }
1076 bool decrement = baseWind && oBaseWind;
1077 bool bigger = baseWind >= oBaseWind;
1078 do {
1079 SkASSERT(test->fT < 1);
1080 if (decrement) {
1081 if (binary && bigger) {
1082 test->fOppValue--;
1083 } else {
1084 decrementSpan(test);
1085 }
1086 }
1087 test->fCoincident = true;
1088 test = &fTs[++index];
1089 } while (index < endIndex);
1090 do {
1091 SkASSERT(oTest->fT < 1);
1092 if (decrement) {
1093 if (binary && !bigger) {
1094 oTest->fOppValue--;
1095 } else {
1096 other->decrementSpan(oTest);
1097 }
1098 }
1099 oTest->fCoincident = true;
1100 oTest = &other->fTs[--oIndex];
1101 } while (oIndex > oStartIndex);
1102 } while (index <= last && oIndex >= 0);
1103 SkASSERT(index > last);
1104 SkASSERT(oIndex < 0);
1105 }
1106
1107 void SkOpSegment::blindCoincident(const SkCoincidence& coincidence, SkOpSegment* other) {
1108 bool binary = fOperand != other->fOperand;
1109 int index = 0;
1110 int last = this->count();
1111 do {
1112 SkOpSpan& span = this->fTs[--last];
1113 if (span.fT != 1 && !span.fSmall) {
1114 break;
1115 }
1116 span.fCoincident = true;
1117 } while (true);
1118 int oIndex = 0;
1119 int oLast = other->count();
1120 do {
1121 SkOpSpan& oSpan = other->fTs[--oLast];
1122 if (oSpan.fT != 1 && !oSpan.fSmall) {
1123 break;
1124 }
1125 oSpan.fCoincident = true;
1126 } while (true);
1127 do {
1128 SkOpSpan* test = &this->fTs[index];
1129 int baseWind = test->fWindValue;
1130 int baseOpp = test->fOppValue;
1131 int endIndex = index;
1132 SkOpSpan* endSpan;
1133 while (++endIndex <= last) {
1134 endSpan = &this->fTs[endIndex];
1135 SkASSERT(endSpan->fT < 1);
1136 if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp ) {
1137 break;
1138 }
1139 endSpan->fCoincident = true;
1140 }
1141 SkOpSpan* oTest = &other->fTs[oIndex];
1142 int oBaseWind = oTest->fWindValue;
1143 int oBaseOpp = oTest->fOppValue;
1144 int oEndIndex = oIndex;
1145 SkOpSpan* oEndSpan;
1146 while (++oEndIndex <= oLast) {
1147 oEndSpan = &this->fTs[oEndIndex];
1148 SkASSERT(oEndSpan->fT < 1);
1149 if (oEndSpan->fWindValue != oBaseWind || oEndSpan->fOppValue != oBas eOpp) {
1150 break;
1151 }
1152 oEndSpan->fCoincident = true;
1153 }
1154 // consolidate the winding count even if done
1155 if ((test->fWindValue || test->fOppValue) && (oTest->fWindValue || oTest ->fOppValue)) {
1156 if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
1157 bumpCoincidentBlind(binary, index, endIndex);
1158 other->bumpCoincidentOBlind(oIndex, oEndIndex);
1159 } else {
1160 other->bumpCoincidentBlind(binary, oIndex, oEndIndex);
1161 bumpCoincidentOBlind(index, endIndex);
1162 }
1163 }
1164 index = endIndex;
1165 oIndex = oEndIndex;
1166 } while (index <= last && oIndex <= oLast);
1167 SkASSERT(index > last);
1168 SkASSERT(oIndex > oLast);
1169 }
1170
1171 void SkOpSegment::bumpCoincidentBlind(bool binary, int index, int endIndex) {
1172 const SkOpSpan& oTest = fTs[index];
1173 int oWindValue = oTest.fWindValue;
1174 int oOppValue = oTest.fOppValue;
1175 if (binary) {
1176 SkTSwap<int>(oWindValue, oOppValue);
1177 }
1178 do {
1179 (void) bumpSpan(&fTs[index], oWindValue, oOppValue);
1180 } while (++index < endIndex);
1181 }
1182
880 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in dexPtr, 1183 void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in dexPtr,
881 SkTArray<SkPoint, true>* outsideTs) { 1184 SkTArray<SkPoint, true>* outsideTs) {
882 int index = *indexPtr; 1185 int index = *indexPtr;
883 int oWindValue = oTest.fWindValue; 1186 int oWindValue = oTest.fWindValue;
884 int oOppValue = oTest.fOppValue; 1187 int oOppValue = oTest.fOppValue;
885 if (binary) { 1188 if (binary) {
886 SkTSwap<int>(oWindValue, oOppValue); 1189 SkTSwap<int>(oWindValue, oOppValue);
887 } 1190 }
888 SkOpSpan* const test = &fTs[index]; 1191 SkOpSpan* const test = &fTs[index];
889 SkOpSpan* end = test; 1192 SkOpSpan* end = test;
890 const SkPoint& oStartPt = oTest.fPt; 1193 const SkPoint& oStartPt = oTest.fPt;
891 do { 1194 do {
892 if (bumpSpan(end, oWindValue, oOppValue)) { 1195 if (bumpSpan(end, oWindValue, oOppValue)) {
893 TrackOutside(outsideTs, oStartPt); 1196 TrackOutside(outsideTs, oStartPt);
894 } 1197 }
895 end = &fTs[++index]; 1198 end = &fTs[++index];
896 } while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && en d->fT < 1); 1199 } while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && en d->fT < 1);
897 *indexPtr = index; 1200 *indexPtr = index;
898 } 1201 }
899 1202
1203 void SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) {
1204 do {
1205 zeroSpan(&fTs[index]);
1206 } while (++index < endIndex);
1207 }
1208
900 // because of the order in which coincidences are resolved, this and other 1209 // because of the order in which coincidences are resolved, this and other
901 // may not have the same intermediate points. Compute the corresponding 1210 // may not have the same intermediate points. Compute the corresponding
902 // intermediate T values (using this as the master, other as the follower) 1211 // intermediate T values (using this as the master, other as the follower)
903 // and walk other conditionally -- hoping that it catches up in the end 1212 // and walk other conditionally -- hoping that it catches up in the end
904 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, 1213 void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr,
905 SkTArray<SkPoint, true>* oOutsidePts) { 1214 SkTArray<SkPoint, true>* oOutsidePts) {
906 int oIndex = *oIndexPtr; 1215 int oIndex = *oIndexPtr;
907 SkOpSpan* const oTest = &fTs[oIndex]; 1216 SkOpSpan* const oTest = &fTs[oIndex];
908 SkOpSpan* oEnd = oTest; 1217 SkOpSpan* oEnd = oTest;
909 const SkPoint& oStartPt = oTest->fPt; 1218 const SkPoint& oStartPt = oTest->fPt;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 } 1327 }
1019 test = &fTs[++index]; 1328 test = &fTs[++index];
1020 testPt = &test->fPt; 1329 testPt = &test->fPt;
1021 } while (endPt != *testPt); 1330 } while (endPt != *testPt);
1022 } 1331 }
1023 if (endPt != *oTestPt) { 1332 if (endPt != *oTestPt) {
1024 // look ahead to see if zeroing more spans will allows us to catch up 1333 // look ahead to see if zeroing more spans will allows us to catch up
1025 int oPeekIndex = oIndex; 1334 int oPeekIndex = oIndex;
1026 bool success = true; 1335 bool success = true;
1027 SkOpSpan* oPeek; 1336 SkOpSpan* oPeek;
1337 int oCount = other->count();
1028 do { 1338 do {
1029 oPeek = &other->fTs[oPeekIndex]; 1339 oPeek = &other->fTs[oPeekIndex];
1030 if (oPeek->fT == 1) { 1340 if (++oPeekIndex == oCount) {
1031 success = false; 1341 success = false;
1032 break; 1342 break;
1033 } 1343 }
1034 ++oPeekIndex;
1035 } while (endPt != oPeek->fPt); 1344 } while (endPt != oPeek->fPt);
1036 if (success) { 1345 if (success) {
1037 // make sure the matching point completes the coincidence span 1346 // make sure the matching point completes the coincidence span
1038 success = false; 1347 success = false;
1039 do { 1348 do {
1040 if (oPeek->fOther == this) { 1349 if (oPeek->fOther == this) {
1041 success = true; 1350 success = true;
1042 break; 1351 break;
1043 } 1352 }
1044 oPeek = &other->fTs[++oPeekIndex]; 1353 oPeek = &other->fTs[++oPeekIndex];
(...skipping 11 matching lines...) Expand all
1056 } while (endPt != *oTestPt); 1365 } while (endPt != *oTestPt);
1057 } 1366 }
1058 } 1367 }
1059 int outCount = outsidePts.count(); 1368 int outCount = outsidePts.count();
1060 if (!done() && outCount) { 1369 if (!done() && outCount) {
1061 addCoinOutsides(outsidePts[0], endPt, other); 1370 addCoinOutsides(outsidePts[0], endPt, other);
1062 } 1371 }
1063 if (!other->done() && oOutsidePts.count()) { 1372 if (!other->done() && oOutsidePts.count()) {
1064 other->addCoinOutsides(oOutsidePts[0], endPt, this); 1373 other->addCoinOutsides(oOutsidePts[0], endPt, this);
1065 } 1374 }
1375 setCoincidentRange(startPt, endPt, other);
1376 other->setCoincidentRange(startPt, endPt, this);
1066 } 1377 }
1067 1378
1068 // FIXME: this doesn't prevent the same span from being added twice 1379 // FIXME: this doesn't prevent the same span from being added twice
1069 // fix in caller, SkASSERT here? 1380 // fix in caller, SkASSERT here?
1070 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind, 1381 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind,
1071 const SkPoint& pt) { 1382 const SkPoint& pt, const SkPoint& pt2) {
1072 int tCount = fTs.count(); 1383 int tCount = fTs.count();
1073 for (int tIndex = 0; tIndex < tCount; ++tIndex) { 1384 for (int tIndex = 0; tIndex < tCount; ++tIndex) {
1074 const SkOpSpan& span = fTs[tIndex]; 1385 const SkOpSpan& span = fTs[tIndex];
1075 if (!approximately_negative(span.fT - t)) { 1386 if (!approximately_negative(span.fT - t)) {
1076 break; 1387 break;
1077 } 1388 }
1078 if (approximately_negative(span.fT - t) && span.fOther == other 1389 if (approximately_negative(span.fT - t) && span.fOther == other
1079 && approximately_equal(span.fOtherT, otherT)) { 1390 && approximately_equal(span.fOtherT, otherT)) {
1080 #if DEBUG_ADD_T_PAIR 1391 #if DEBUG_ADD_T_PAIR
1081 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", 1392 SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n",
1082 __FUNCTION__, fID, t, other->fID, otherT); 1393 __FUNCTION__, fID, t, other->fID, otherT);
1083 #endif 1394 #endif
1084 return NULL; 1395 return NULL;
1085 } 1396 }
1086 } 1397 }
1087 #if DEBUG_ADD_T_PAIR 1398 #if DEBUG_ADD_T_PAIR
1088 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", 1399 SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
1089 __FUNCTION__, fID, t, other->fID, otherT); 1400 __FUNCTION__, fID, t, other->fID, otherT);
1090 #endif 1401 #endif
1091 int insertedAt = addT(other, pt, t); 1402 int insertedAt = addT(other, pt, t);
1092 int otherInsertedAt = other->addT(this, pt, otherT); 1403 int otherInsertedAt = other->addT(this, pt2, otherT);
1093 addOtherT(insertedAt, otherT, otherInsertedAt); 1404 addOtherT(insertedAt, otherT, otherInsertedAt);
1094 other->addOtherT(otherInsertedAt, t, insertedAt); 1405 other->addOtherT(otherInsertedAt, t, insertedAt);
1095 matchWindingValue(insertedAt, t, borrowWind); 1406 matchWindingValue(insertedAt, t, borrowWind);
1096 other->matchWindingValue(otherInsertedAt, otherT, borrowWind); 1407 other->matchWindingValue(otherInsertedAt, otherT, borrowWind);
1097 return &span(insertedAt); 1408 SkOpSpan& span = this->fTs[insertedAt];
1409 if (pt != pt2) {
1410 span.fNear = true;
1411 SkOpSpan& oSpan = other->fTs[otherInsertedAt];
1412 oSpan.fNear = true;
1413 }
1414 return &span;
1098 } 1415 }
1099 1416
1100 const SkOpAngle& SkOpSegment::angle(int index) const { 1417 const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other T, bool borrowWind,
1101 SkASSERT(index >= 0); 1418 const SkPoint& pt) {
1102 int count = fAngles.count(); 1419 return addTPair(t, other, otherT, borrowWind, pt, pt);
1103 if (index < count) {
1104 return fAngles[index];
1105 }
1106 index -= count;
1107 count = fSingletonAngles.count();
1108 SkASSERT(index < count);
1109 return fSingletonAngles[index];
1110 } 1420 }
1111 1421
1112 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const { 1422 bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const {
1113 const SkPoint midPt = ptAtT(midT); 1423 const SkPoint midPt = ptAtT(midT);
1114 SkPathOpsBounds bounds; 1424 SkPathOpsBounds bounds;
1115 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY); 1425 bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY);
1116 bounds.sort(); 1426 bounds.sort();
1117 return bounds.almostContains(midPt); 1427 return bounds.almostContains(midPt);
1118 } 1428 }
1119 1429
(...skipping 11 matching lines...) Expand all
1131 int spanCount = fTs.count(); 1441 int spanCount = fTs.count();
1132 if (spanCount <= 2) { 1442 if (spanCount <= 2) {
1133 return spanCount == 2; 1443 return spanCount == 2;
1134 } 1444 }
1135 int index = 1; 1445 int index = 1;
1136 const SkOpSpan* firstSpan = &fTs[index]; 1446 const SkOpSpan* firstSpan = &fTs[index];
1137 int activePrior = checkSetAngle(0); 1447 int activePrior = checkSetAngle(0);
1138 const SkOpSpan* span = &fTs[0]; 1448 const SkOpSpan* span = &fTs[0];
1139 if (firstSpan->fT == 0 || span->fTiny || span->fOtherT != 1 || span->fOther- >multipleEnds()) { 1449 if (firstSpan->fT == 0 || span->fTiny || span->fOtherT != 1 || span->fOther- >multipleEnds()) {
1140 index = findStartSpan(0); // curve start intersects 1450 index = findStartSpan(0); // curve start intersects
1141 if (index < 0) { 1451 SkASSERT(index > 0);
1142 return false;
1143 }
1144 if (activePrior >= 0) { 1452 if (activePrior >= 0) {
1145 addStartSpan(index); 1453 addStartSpan(index);
1146 } 1454 }
1147 } 1455 }
1148 bool addEnd; 1456 bool addEnd;
1149 int endIndex = spanCount - 1; 1457 int endIndex = spanCount - 1;
1150 span = &fTs[endIndex - 1]; 1458 span = &fTs[endIndex - 1];
1151 if ((addEnd = span->fT == 1 || span->fTiny)) { // if curve end intersects 1459 if ((addEnd = span->fT == 1 || span->fTiny)) { // if curve end intersects
1152 endIndex = findEndSpan(endIndex); 1460 endIndex = findEndSpan(endIndex);
1153 if (endIndex < 0) { 1461 SkASSERT(endIndex > 0);
1154 return false;
1155 }
1156 } else { 1462 } else {
1157 addEnd = fTs[endIndex].fOtherT != 0 || fTs[endIndex].fOther->multipleSta rts(); 1463 addEnd = fTs[endIndex].fOtherT != 0 || fTs[endIndex].fOther->multipleSta rts();
1158 } 1464 }
1159 SkASSERT(endIndex >= index); 1465 SkASSERT(endIndex >= index);
1160 int prior = 0; 1466 int prior = 0;
1161 while (index < endIndex) { 1467 while (index < endIndex) {
1162 const SkOpSpan& fromSpan = fTs[index]; // for each intermediate interse ction 1468 const SkOpSpan& fromSpan = fTs[index]; // for each intermediate interse ction
1163 const SkOpSpan* lastSpan; 1469 const SkOpSpan* lastSpan;
1164 span = &fromSpan; 1470 span = &fromSpan;
1165 int start = index; 1471 int start = index;
1166 do { 1472 do {
1167 lastSpan = span; 1473 lastSpan = span;
1168 span = &fTs[++index]; 1474 span = &fTs[++index];
1169 SkASSERT(index < spanCount); 1475 SkASSERT(index < spanCount);
1170 if (!precisely_negative(span->fT - lastSpan->fT) && !lastSpan->fTiny ) { 1476 if (!precisely_negative(span->fT - lastSpan->fT) && !lastSpan->fTiny ) {
1171 break; 1477 break;
1172 } 1478 }
1173 if (!SkDPoint::ApproximatelyEqual(lastSpan->fPt, span->fPt)) { 1479 if (!SkDPoint::ApproximatelyEqual(lastSpan->fPt, span->fPt)) {
1174 return false; 1480 return false;
1175 } 1481 }
1176 } while (true); 1482 } while (true);
1177 int angleIndex = fAngles.count(); 1483 SkOpAngle* angle = NULL;
1178 int priorAngleIndex; 1484 SkOpAngle* priorAngle;
1179 if (activePrior >= 0) { 1485 if (activePrior >= 0) {
1180 int pActive = firstActive(prior); 1486 int pActive = firstActive(prior);
1181 SkASSERT(pActive < start); 1487 SkASSERT(pActive < start);
1182 fAngles.push_back().set(this, start, pActive); 1488 priorAngle = &fAngles.push_back();
1183 priorAngleIndex = angleIndex++; 1489 priorAngle->set(this, start, pActive);
1184 #if DEBUG_ANGLE
1185 fAngles.back().setID(priorAngleIndex);
1186 #endif
1187 } 1490 }
1188 int active = checkSetAngle(start); 1491 int active = checkSetAngle(start);
1189 if (active >= 0) { 1492 if (active >= 0) {
1190 SkASSERT(active < index); 1493 SkASSERT(active < index);
1191 fAngles.push_back().set(this, active, index); 1494 angle = &fAngles.push_back();
1192 #if DEBUG_ANGLE 1495 angle->set(this, active, index);
1193 fAngles.back().setID(angleIndex);
1194 #endif
1195 } 1496 }
1196 #if DEBUG_ANGLE 1497 #if DEBUG_ANGLE
1197 debugCheckPointsEqualish(start, index); 1498 debugCheckPointsEqualish(start, index);
1198 #endif 1499 #endif
1199 prior = start; 1500 prior = start;
1200 do { 1501 do {
1201 const SkOpSpan* startSpan = &fTs[start - 1]; 1502 const SkOpSpan* startSpan = &fTs[start - 1];
1202 if (!startSpan->fSmall || startSpan->fFromAngleIndex >= 0 1503 if (!startSpan->fSmall || isCanceled(start - 1) || startSpan->fFromA ngle
1203 || startSpan->fToAngleIndex >= 0) { 1504 || startSpan->fToAngle) {
1204 break; 1505 break;
1205 } 1506 }
1206 --start; 1507 --start;
1207 } while (start > 0); 1508 } while (start > 0);
1208 do { 1509 do {
1209 if (activePrior >= 0) { 1510 if (activePrior >= 0) {
1210 SkASSERT(fTs[start].fFromAngleIndex == -1); 1511 SkASSERT(fTs[start].fFromAngle == NULL);
1211 fTs[start].fFromAngleIndex = priorAngleIndex; 1512 fTs[start].fFromAngle = priorAngle;
1212 } 1513 }
1213 if (active >= 0) { 1514 if (active >= 0) {
1214 SkASSERT(fTs[start].fToAngleIndex == -1); 1515 SkASSERT(fTs[start].fToAngle == NULL);
1215 fTs[start].fToAngleIndex = angleIndex; 1516 fTs[start].fToAngle = angle;
1216 } 1517 }
1217 } while (++start < index); 1518 } while (++start < index);
1218 activePrior = active; 1519 activePrior = active;
1219 } 1520 }
1220 if (addEnd && activePrior >= 0) { 1521 if (addEnd && activePrior >= 0) {
1221 addEndSpan(endIndex); 1522 addEndSpan(endIndex);
1222 } 1523 }
1223 return true; 1524 return true;
1224 } 1525 }
1225 1526
1226 int SkOpSegment::checkSetAngle(int tIndex) const { 1527 int SkOpSegment::checkSetAngle(int tIndex) const {
1227 const SkOpSpan* span = &fTs[tIndex]; 1528 const SkOpSpan* span = &fTs[tIndex];
1228 while (span->fTiny /* || span->fSmall */) { 1529 while (span->fTiny /* || span->fSmall */) {
1229 span = &fTs[++tIndex]; 1530 span = &fTs[++tIndex];
1230 } 1531 }
1231 return isCanceled(tIndex) ? -1 : tIndex; 1532 return isCanceled(tIndex) ? -1 : tIndex;
1232 } 1533 }
1233 1534
1234 // at this point, the span is already ordered, or unorderable, or unsortable 1535 // at this point, the span is already ordered, or unorderable
1235 int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType) { 1536 int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType) {
1236 SkASSERT(includeType != SkOpAngle::kUnaryXor); 1537 SkASSERT(includeType != SkOpAngle::kUnaryXor);
1237 SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex); 1538 SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex);
1238 if (NULL == firstAngle) { 1539 if (NULL == firstAngle) {
1239 return SK_NaN32; 1540 return SK_NaN32;
1240 } 1541 }
1241 // if all angles have a computed winding, 1542 // if all angles have a computed winding,
1242 // or if no adjacent angles are orderable, 1543 // or if no adjacent angles are orderable,
1243 // or if adjacent orderable angles have no computed winding, 1544 // or if adjacent orderable angles have no computed winding,
1244 // there's nothing to do 1545 // there's nothing to do
1245 // if two orderable angles are adjacent, and one has winding computed, trans fer to the other 1546 // if two orderable angles are adjacent, and both are next to orderable angl es,
1547 // and one has winding computed, transfer to the other
1246 SkOpAngle* baseAngle = NULL; 1548 SkOpAngle* baseAngle = NULL;
1247 bool tryReverse = false; 1549 bool tryReverse = false;
1248 // look for counterclockwise transfers 1550 // look for counterclockwise transfers
1249 SkOpAngle* angle = firstAngle; 1551 SkOpAngle* angle = firstAngle->previous();
1552 SkOpAngle* next = angle->next();
1553 firstAngle = next;
1250 do { 1554 do {
1251 int testWinding = angle->segment()->windSum(angle); 1555 SkOpAngle* prior = angle;
1252 if (SK_MinS32 != testWinding && !angle->unorderable()) { 1556 angle = next;
1253 baseAngle = angle; 1557 next = angle->next();
1558 SkASSERT(prior->next() == angle);
1559 SkASSERT(angle->next() == next);
1560 if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
1561 baseAngle = NULL;
1254 continue; 1562 continue;
1255 } 1563 }
1256 if (angle->unorderable()) { 1564 int testWinding = angle->segment()->windSum(angle);
1257 baseAngle = NULL; 1565 if (SK_MinS32 != testWinding) {
1566 baseAngle = angle;
1258 tryReverse = true; 1567 tryReverse = true;
1259 continue; 1568 continue;
1260 } 1569 }
1261 if (baseAngle) { 1570 if (baseAngle) {
1262 ComputeOneSum(baseAngle, angle, includeType); 1571 ComputeOneSum(baseAngle, angle, includeType);
1263 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle : NULL; 1572 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle : NULL;
1264 tryReverse |= !baseAngle;
1265 } 1573 }
1266 } while ((angle = angle->next()) != firstAngle); 1574 } while (next != firstAngle);
1267 if (baseAngle && SK_MinS32 == firstAngle->segment()->windSum(angle)) { 1575 if (baseAngle && SK_MinS32 == firstAngle->segment()->windSum(firstAngle)) {
1268 firstAngle = baseAngle; 1576 firstAngle = baseAngle;
1269 tryReverse = true; 1577 tryReverse = true;
1270 } 1578 }
1271 if (tryReverse) { 1579 if (tryReverse) {
1272 baseAngle = NULL; 1580 baseAngle = NULL;
1273 angle = firstAngle; 1581 SkOpAngle* prior = firstAngle;
1274 do { 1582 do {
1583 angle = prior;
1584 prior = angle->previous();
1585 SkASSERT(prior->next() == angle);
1586 next = angle->next();
1587 if (prior->unorderable() || angle->unorderable() || next->unorderabl e()) {
1588 baseAngle = NULL;
1589 continue;
1590 }
1275 int testWinding = angle->segment()->windSum(angle); 1591 int testWinding = angle->segment()->windSum(angle);
1276 if (SK_MinS32 != testWinding) { 1592 if (SK_MinS32 != testWinding) {
1277 baseAngle = angle; 1593 baseAngle = angle;
1278 continue; 1594 continue;
1279 } 1595 }
1280 if (angle->unorderable()) {
1281 baseAngle = NULL;
1282 continue;
1283 }
1284 if (baseAngle) { 1596 if (baseAngle) {
1285 ComputeOneSumReverse(baseAngle, angle, includeType); 1597 ComputeOneSumReverse(baseAngle, angle, includeType);
1286 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angl e : NULL; 1598 baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angl e : NULL;
1287 } 1599 }
1288 } while ((angle = angle->previous()) != firstAngle); 1600 } while (prior != firstAngle);
1289 } 1601 }
1290 int minIndex = SkMin32(startIndex, endIndex); 1602 int minIndex = SkMin32(startIndex, endIndex);
1291 return windSum(minIndex); 1603 return windSum(minIndex);
1292 } 1604 }
1293 1605
1294 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle , 1606 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle ,
1295 SkOpAngle::IncludeType includeType) { 1607 SkOpAngle::IncludeType includeType) {
1296 const SkOpSegment* baseSegment = baseAngle->segment(); 1608 const SkOpSegment* baseSegment = baseAngle->segment();
1297 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 1609 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle);
1298 int sumSuWinding; 1610 int sumSuWinding;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 const SkOpSpan& span = this->span(index); 1667 const SkOpSpan& span = this->span(index);
1356 if (span.fPt == pt) { 1668 if (span.fPt == pt) {
1357 const SkOpSpan& endSpan = this->span(endIndex); 1669 const SkOpSpan& endSpan = this->span(endIndex);
1358 return span.fT == endSpan.fT && pt != endSpan.fPt; 1670 return span.fT == endSpan.fT && pt != endSpan.fPt;
1359 } 1671 }
1360 index += step; 1672 index += step;
1361 } while (index != endIndex); 1673 } while (index != endIndex);
1362 return false; 1674 return false;
1363 } 1675 }
1364 1676
1677 bool SkOpSegment::containsT(double t, const SkOpSegment* other, double otherT) c onst {
1678 int count = this->count();
1679 for (int index = 0; index < count; ++index) {
1680 const SkOpSpan& span = fTs[index];
1681 if (t < span.fT) {
1682 return false;
1683 }
1684 if (t == span.fT) {
1685 if (other != span.fOther) {
1686 continue;
1687 }
1688 if (other->fVerb != SkPath::kCubic_Verb) {
1689 return true;
1690 }
1691 if (!other->fLoop) {
1692 return true;
1693 }
1694 double otherMidT = (otherT + span.fOtherT) / 2;
1695 SkPoint otherPt = other->ptAtT(otherMidT);
1696 return SkDPoint::ApproximatelyEqual(span.fPt, otherPt);
1697 }
1698 }
1699 return false;
1700 }
1701
1365 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT, 1702 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT,
1366 bool* hitSomething, double mid, bool opp, bool cur rent) const { 1703 bool* hitSomething, double mid, bool opp, bool cur rent) const {
1367 SkScalar bottom = fBounds.fBottom; 1704 SkScalar bottom = fBounds.fBottom;
1368 int bestTIndex = -1; 1705 int bestTIndex = -1;
1369 if (bottom <= *bestY) { 1706 if (bottom <= *bestY) {
1370 return bestTIndex; 1707 return bestTIndex;
1371 } 1708 }
1372 SkScalar top = fBounds.fTop; 1709 SkScalar top = fBounds.fTop;
1373 if (top >= basePt.fY) { 1710 if (top >= basePt.fY) {
1374 return bestTIndex; 1711 return bestTIndex;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1535 testSpan = &firstSpan - 1; 1872 testSpan = &firstSpan - 1;
1536 smallCounts[0] = smallCounts[1] = 0; 1873 smallCounts[0] = smallCounts[1] = 0;
1537 while (++testSpan <= &lastSpan) { 1874 while (++testSpan <= &lastSpan) {
1538 SkASSERT(approximately_equal(testSpan->fT, firstLoopT) + 1875 SkASSERT(approximately_equal(testSpan->fT, firstLoopT) +
1539 approximately_equal(testSpan->fT, lastLoopT) == 1); 1876 approximately_equal(testSpan->fT, lastLoopT) == 1);
1540 smallCounts[approximately_equal(testSpan->fT, lastLoopT)]++; 1877 smallCounts[approximately_equal(testSpan->fT, lastLoopT)]++;
1541 } 1878 }
1542 return true; 1879 return true;
1543 } 1880 }
1544 1881
1882 double SkOpSegment::calcMissingTEnd(const SkOpSegment* ref, double loEnd, double min, double max,
1883 double hiEnd, const SkOpSegment* other, int thisStart) {
1884 if (max >= hiEnd) {
1885 return -1;
1886 }
1887 int end = findOtherT(hiEnd, ref);
1888 if (end < 0) {
1889 return -1;
1890 }
1891 double tHi = span(end).fT;
1892 double tLo, refLo;
1893 if (thisStart >= 0) {
1894 tLo = span(thisStart).fT;
1895 refLo = min;
1896 } else {
1897 int start1 = findOtherT(loEnd, ref);
1898 SkASSERT(start1 >= 0);
1899 tLo = span(start1).fT;
1900 refLo = loEnd;
1901 }
1902 double missingT = (max - refLo) / (hiEnd - refLo);
1903 missingT = tLo + missingT * (tHi - tLo);
1904 return missingT;
1905 }
1906
1907 double SkOpSegment::calcMissingTStart(const SkOpSegment* ref, double loEnd, doub le min, double max,
1908 double hiEnd, const SkOpSegment* other, int thisEnd) {
1909 if (min <= loEnd) {
1910 return -1;
1911 }
1912 int start = findOtherT(loEnd, ref);
1913 if (start < 0) {
1914 return -1;
1915 }
1916 double tLo = span(start).fT;
1917 double tHi, refHi;
1918 if (thisEnd >= 0) {
1919 tHi = span(thisEnd).fT;
1920 refHi = max;
1921 } else {
1922 int end1 = findOtherT(hiEnd, ref);
1923 if (end1 < 0) {
1924 return -1;
1925 }
1926 tHi = span(end1).fT;
1927 refHi = hiEnd;
1928 }
1929 double missingT = (min - loEnd) / (refHi - loEnd);
1930 missingT = tLo + missingT * (tHi - tLo);
1931 return missingT;
1932 }
1933
1545 // see if spans with two or more intersections have the same number on the other end 1934 // see if spans with two or more intersections have the same number on the other end
1546 void SkOpSegment::checkDuplicates() { 1935 void SkOpSegment::checkDuplicates() {
1547 debugValidate(); 1936 debugValidate();
1548 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 1937 SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
1549 int index; 1938 int index;
1550 int endIndex = 0; 1939 int endIndex = 0;
1551 bool endFound; 1940 bool endFound;
1552 do { 1941 do {
1553 index = endIndex; 1942 index = endIndex;
1554 endIndex = nextExactSpan(index, 1); 1943 endIndex = nextExactSpan(index, 1);
1555 if ((endFound = endIndex < 0)) { 1944 if ((endFound = endIndex < 0)) {
1556 endIndex = count(); 1945 endIndex = count();
1557 } 1946 }
1558 int dupCount = endIndex - index; 1947 int dupCount = endIndex - index;
1559 if (dupCount < 2) { 1948 if (dupCount < 2) {
1560 continue; 1949 continue;
1561 } 1950 }
1562 do { 1951 do {
1563 const SkOpSpan* thisSpan = &fTs[index]; 1952 const SkOpSpan* thisSpan = &fTs[index];
1953 if (thisSpan->fNear) {
1954 continue;
1955 }
1564 SkOpSegment* other = thisSpan->fOther; 1956 SkOpSegment* other = thisSpan->fOther;
1565 int oIndex = thisSpan->fOtherIndex; 1957 int oIndex = thisSpan->fOtherIndex;
1566 int oStart = other->nextExactSpan(oIndex, -1) + 1; 1958 int oStart = other->nextExactSpan(oIndex, -1) + 1;
1567 int oEnd = other->nextExactSpan(oIndex, 1); 1959 int oEnd = other->nextExactSpan(oIndex, 1);
1568 if (oEnd < 0) { 1960 if (oEnd < 0) {
1569 oEnd = other->count(); 1961 oEnd = other->count();
1570 } 1962 }
1571 int oCount = oEnd - oStart; 1963 int oCount = oEnd - oStart;
1572 // force the other to match its t and this pt if not on an end point 1964 // force the other to match its t and this pt if not on an end point
1573 if (oCount != dupCount) { 1965 if (oCount != dupCount) {
(...skipping 21 matching lines...) Expand all
1595 if (missingCount == 0) { 1987 if (missingCount == 0) {
1596 return; 1988 return;
1597 } 1989 }
1598 SkSTArray<kMissingSpanCount, MissingSpan, true> missingCoincidence; 1990 SkSTArray<kMissingSpanCount, MissingSpan, true> missingCoincidence;
1599 for (index = 0; index < missingCount; ++index) { 1991 for (index = 0; index < missingCount; ++index) {
1600 MissingSpan& missing = missingSpans[index]; 1992 MissingSpan& missing = missingSpans[index];
1601 SkOpSegment* missingOther = missing.fOther; 1993 SkOpSegment* missingOther = missing.fOther;
1602 if (missing.fSegment == missing.fOther) { 1994 if (missing.fSegment == missing.fOther) {
1603 continue; 1995 continue;
1604 } 1996 }
1997 #if 0 // FIXME: this eliminates spurious data from skpwww_argus_presse_fr_41 bu t breaks
1998 // skpwww_fashionscandal_com_94 -- calcAngles complains, but I don't unde rstand why
1999 if (missing.fSegment->containsT(missing.fT, missing.fOther, missing.fOth erT)) {
2000 #if DEBUG_DUPLICATES
2001 SkDebugf("skip 1 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fSe gment->fID,
2002 missing.fT, missing.fOther->fID, missing.fOtherT);
2003 #endif
2004 continue;
2005 }
2006 if (missing.fOther->containsT(missing.fOtherT, missing.fSegment, missing .fT)) {
2007 #if DEBUG_DUPLICATES
2008 SkDebugf("skip 2 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fOt her->fID,
2009 missing.fOtherT, missing.fSegment->fID, missing.fT);
2010 #endif
2011 continue;
2012 }
2013 #endif
2014 // skip if adding would insert point into an existing coincindent span
2015 if (missing.fSegment->inCoincidentSpan(missing.fT, missingOther)
2016 && missingOther->inCoincidentSpan(missing.fOtherT, this)) {
2017 continue;
2018 }
2019 // skip if the created coincident spans are small
2020 if (missing.fSegment->coincidentSmall(missing.fPt, missing.fT, missingOt her)
2021 && missingOther->coincidentSmall(missing.fPt, missing.fOtherT, m issing.fSegment)) {
2022 continue;
2023 }
1605 const SkOpSpan* added = missing.fSegment->addTPair(missing.fT, missingOt her, 2024 const SkOpSpan* added = missing.fSegment->addTPair(missing.fT, missingOt her,
1606 missing.fOtherT, false, missing.fPt); 2025 missing.fOtherT, false, missing.fPt);
1607 if (added && added->fSmall) { 2026 if (added && added->fSmall) {
1608 missing.fSegment->checkSmallCoincidence(*added, &missingCoincidence) ; 2027 missing.fSegment->checkSmallCoincidence(*added, &missingCoincidence) ;
1609 } 2028 }
1610 } 2029 }
1611 for (index = 0; index < missingCount; ++index) { 2030 for (index = 0; index < missingCount; ++index) {
1612 MissingSpan& missing = missingSpans[index]; 2031 MissingSpan& missing = missingSpans[index];
1613 missing.fSegment->fixOtherTIndex(); 2032 missing.fSegment->fixOtherTIndex();
1614 missing.fOther->fixOtherTIndex(); 2033 missing.fOther->fixOtherTIndex();
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1770 while (fTs[end].fT < 1) { 2189 while (fTs[end].fT < 1) {
1771 int start = index = end; 2190 int start = index = end;
1772 end = nextExactSpan(index, 1); 2191 end = nextExactSpan(index, 1);
1773 if (end <= index) { 2192 if (end <= index) {
1774 return; // buffer overflow example triggers this 2193 return; // buffer overflow example triggers this
1775 } 2194 }
1776 if (index + 1 == end) { 2195 if (index + 1 == end) {
1777 continue; 2196 continue;
1778 } 2197 }
1779 // force the duplicates to agree on t and pt if not on the end 2198 // force the duplicates to agree on t and pt if not on the end
1780 double thisT = fTs[index].fT; 2199 SkOpSpan& span = fTs[index];
1781 const SkPoint& thisPt = fTs[index].fPt; 2200 double thisT = span.fT;
2201 const SkPoint& thisPt = span.fPt;
2202 span.fMultiple = true;
1782 bool aligned = false; 2203 bool aligned = false;
1783 while (++index < end) { 2204 while (++index < end) {
1784 aligned |= alignSpan(index, thisT, thisPt); 2205 aligned |= alignSpan(index, thisT, thisPt);
1785 } 2206 }
1786 if (aligned) { 2207 if (aligned) {
1787 alignSpanState(start, end); 2208 alignSpanState(start, end);
1788 } 2209 }
2210 fMultiples = true;
1789 } 2211 }
1790 debugValidate(); 2212 debugValidate();
1791 } 2213 }
1792 2214
1793 void SkOpSegment::CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan, 2215 void SkOpSegment::CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
1794 const SkOpSpan* oFirst, const SkOpSpan* oLast, const SkOpSpan** missingP tr, 2216 const SkOpSpan* oFirst, const SkOpSpan* oLast, const SkOpSpan** missingP tr,
1795 SkTArray<MissingSpan, true>* missingSpans) { 2217 SkTArray<MissingSpan, true>* missingSpans) {
1796 SkASSERT(oSpan->fPt == test->fPt); 2218 SkASSERT(oSpan->fPt == test->fPt);
1797 const SkOpSpan* oTest = oSpan; 2219 const SkOpSpan* oTest = oSpan;
1798 while (oTest > oFirst && (--oTest)->fPt == test->fPt) { 2220 while (oTest > oFirst && (--oTest)->fPt == test->fPt) {
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
2139 } 2561 }
2140 } 2562 }
2141 // OPTIMIZE: consolidate to avoid multiple calls to fix index 2563 // OPTIMIZE: consolidate to avoid multiple calls to fix index
2142 for (int index = 0; index < missingCount; ++index) { 2564 for (int index = 0; index < missingCount; ++index) {
2143 MissingSpan& missing = missingSpans[index]; 2565 MissingSpan& missing = missingSpans[index];
2144 missing.fSegment->fixOtherTIndex(); 2566 missing.fSegment->fixOtherTIndex();
2145 missing.fOther->fixOtherTIndex(); 2567 missing.fOther->fixOtherTIndex();
2146 } 2568 }
2147 } 2569 }
2148 2570
2571 bool SkOpSegment::coincidentSmall(const SkPoint& pt, double t, const SkOpSegment * other) const {
2572 int count = this->count();
2573 for (int index = 0; index < count; ++index) {
2574 const SkOpSpan& span = this->span(index);
2575 if (span.fOther != other) {
2576 continue;
2577 }
2578 if (span.fPt == pt) {
2579 continue;
2580 }
2581 if (!AlmostEqualUlps(span.fPt, pt)) {
2582 continue;
2583 }
2584 if (fVerb != SkPath::kCubic_Verb) {
2585 return true;
2586 }
2587 double tInterval = t - span.fT;
2588 double tMid = t - tInterval / 2;
2589 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid);
2590 return midPt.approximatelyEqual(xyAtT(t));
2591 }
2592 return false;
2593 }
2594
2149 bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* o ther, int oStart, 2595 bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* o ther, int oStart,
2150 int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) cons t { 2596 int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) cons t {
2151 SkASSERT(span->fT == 0 || span->fT == 1); 2597 SkASSERT(span->fT == 0 || span->fT == 1);
2152 SkASSERT(span->fOtherT == 0 || span->fOtherT == 1); 2598 SkASSERT(span->fOtherT == 0 || span->fOtherT == 1);
2153 const SkOpSpan* otherSpan = &other->span(oEnd); 2599 const SkOpSpan* otherSpan = &other->span(oEnd);
2154 double refT = otherSpan->fT; 2600 double refT = otherSpan->fT;
2155 const SkPoint& refPt = otherSpan->fPt; 2601 const SkPoint& refPt = otherSpan->fPt;
2156 const SkOpSpan* lastSpan = &other->span(step > 0 ? other->count() - 1 : 0); 2602 const SkOpSpan* lastSpan = &other->span(step > 0 ? other->count() - 1 : 0);
2157 do { 2603 do {
2158 const SkOpSegment* match = span->fOther; 2604 const SkOpSegment* match = span->fOther;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 Opposite values result from combining coincident spans. 2674 Opposite values result from combining coincident spans.
2229 */ 2675 */
2230 SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart , int* nextEnd, 2676 SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart , int* nextEnd,
2231 bool* unsortable, SkPathOp op, const int xo rMiMask, 2677 bool* unsortable, SkPathOp op, const int xo rMiMask,
2232 const int xorSuMask) { 2678 const int xorSuMask) {
2233 const int startIndex = *nextStart; 2679 const int startIndex = *nextStart;
2234 const int endIndex = *nextEnd; 2680 const int endIndex = *nextEnd;
2235 SkASSERT(startIndex != endIndex); 2681 SkASSERT(startIndex != endIndex);
2236 SkDEBUGCODE(const int count = fTs.count()); 2682 SkDEBUGCODE(const int count = fTs.count());
2237 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); 2683 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
2238 const int step = SkSign32(endIndex - startIndex); 2684 int step = SkSign32(endIndex - startIndex);
2239 const int end = nextExactSpan(startIndex, step); 2685 *nextStart = startIndex;
2240 SkASSERT(end >= 0); 2686 SkOpSegment* other = isSimple(nextStart, &step);
2241 SkOpSpan* endSpan = &fTs[end]; 2687 if (other)
2242 SkOpSegment* other; 2688 {
2243 if (isSimple(end)) {
2244 // mark the smaller of startIndex, endIndex done, and all adjacent 2689 // mark the smaller of startIndex, endIndex done, and all adjacent
2245 // spans with the same T value (but not 'other' spans) 2690 // spans with the same T value (but not 'other' spans)
2246 #if DEBUG_WINDING 2691 #if DEBUG_WINDING
2247 SkDebugf("%s simple\n", __FUNCTION__); 2692 SkDebugf("%s simple\n", __FUNCTION__);
2248 #endif 2693 #endif
2249 int min = SkMin32(startIndex, endIndex); 2694 int min = SkMin32(startIndex, endIndex);
2250 if (fTs[min].fDone) { 2695 if (fTs[min].fDone) {
2251 return NULL; 2696 return NULL;
2252 } 2697 }
2253 markDoneBinary(min); 2698 markDoneBinary(min);
2254 other = endSpan->fOther;
2255 *nextStart = endSpan->fOtherIndex;
2256 double startT = other->fTs[*nextStart].fT; 2699 double startT = other->fTs[*nextStart].fT;
2257 *nextEnd = *nextStart; 2700 *nextEnd = *nextStart;
2258 do { 2701 do {
2259 *nextEnd += step; 2702 *nextEnd += step;
2260 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 2703 } while (precisely_zero(startT - other->fTs[*nextEnd].fT));
2261 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2704 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
2262 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { 2705 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) {
2263 *unsortable = true; 2706 *unsortable = true;
2264 return NULL; 2707 return NULL;
2265 } 2708 }
2266 return other; 2709 return other;
2267 } 2710 }
2711 const int end = nextExactSpan(startIndex, step);
2712 SkASSERT(end >= 0);
2268 SkASSERT(startIndex - endIndex != 0); 2713 SkASSERT(startIndex - endIndex != 0);
2269 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2714 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2270 // more than one viable candidate -- measure angles to find best 2715 // more than one viable candidate -- measure angles to find best
2271 2716
2272 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp); 2717 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp);
2273 bool sortable = calcWinding != SK_NaN32; 2718 bool sortable = calcWinding != SK_NaN32;
2274 if (!sortable) { 2719 if (!sortable) {
2275 *unsortable = true; 2720 *unsortable = true;
2276 markDoneBinary(SkMin32(startIndex, endIndex)); 2721 markDoneBinary(SkMin32(startIndex, endIndex));
2277 return NULL; 2722 return NULL;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2318 foundDone = nextSegment->done(nextAngle); 2763 foundDone = nextSegment->done(nextAngle);
2319 } 2764 }
2320 } 2765 }
2321 if (nextSegment->done()) { 2766 if (nextSegment->done()) {
2322 continue; 2767 continue;
2323 } 2768 }
2324 if (nextSegment->isTiny(nextAngle)) { 2769 if (nextSegment->isTiny(nextAngle)) {
2325 continue; 2770 continue;
2326 } 2771 }
2327 if (!activeAngle) { 2772 if (!activeAngle) {
2328 nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextAngle->e nd()); 2773 (void) nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextA ngle->end());
2329 } 2774 }
2330 SkOpSpan* last = nextAngle->lastMarked(); 2775 SkOpSpan* last = nextAngle->lastMarked();
2331 if (last) { 2776 if (last) {
2332 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 2777 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
2333 *chase->append() = last; 2778 *chase->append() = last;
2334 #if DEBUG_WINDING 2779 #if DEBUG_WINDING
2335 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ , 2780 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ ,
2336 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum, 2781 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum,
2337 last->fSmall); 2782 last->fSmall);
2338 #endif 2783 #endif
(...skipping 19 matching lines...) Expand all
2358 return nextSegment; 2803 return nextSegment;
2359 } 2804 }
2360 2805
2361 SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next Start, 2806 SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next Start,
2362 int* nextEnd, bool* unsortable) { 2807 int* nextEnd, bool* unsortable) {
2363 const int startIndex = *nextStart; 2808 const int startIndex = *nextStart;
2364 const int endIndex = *nextEnd; 2809 const int endIndex = *nextEnd;
2365 SkASSERT(startIndex != endIndex); 2810 SkASSERT(startIndex != endIndex);
2366 SkDEBUGCODE(const int count = fTs.count()); 2811 SkDEBUGCODE(const int count = fTs.count());
2367 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); 2812 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
2368 const int step = SkSign32(endIndex - startIndex); 2813 int step = SkSign32(endIndex - startIndex);
2369 const int end = nextExactSpan(startIndex, step); 2814 *nextStart = startIndex;
2370 SkASSERT(end >= 0); 2815 SkOpSegment* other = isSimple(nextStart, &step);
2371 SkOpSpan* endSpan = &fTs[end]; 2816 if (other)
2372 SkOpSegment* other; 2817 {
2373 if (isSimple(end)) {
2374 // mark the smaller of startIndex, endIndex done, and all adjacent 2818 // mark the smaller of startIndex, endIndex done, and all adjacent
2375 // spans with the same T value (but not 'other' spans) 2819 // spans with the same T value (but not 'other' spans)
2376 #if DEBUG_WINDING 2820 #if DEBUG_WINDING
2377 SkDebugf("%s simple\n", __FUNCTION__); 2821 SkDebugf("%s simple\n", __FUNCTION__);
2378 #endif 2822 #endif
2379 int min = SkMin32(startIndex, endIndex); 2823 int min = SkMin32(startIndex, endIndex);
2380 if (fTs[min].fDone) { 2824 if (fTs[min].fDone) {
2381 return NULL; 2825 return NULL;
2382 } 2826 }
2383 markDoneUnary(min); 2827 markDoneUnary(min);
2384 other = endSpan->fOther;
2385 *nextStart = endSpan->fOtherIndex;
2386 double startT = other->fTs[*nextStart].fT; 2828 double startT = other->fTs[*nextStart].fT;
2387 *nextEnd = *nextStart; 2829 *nextEnd = *nextStart;
2388 do { 2830 do {
2389 *nextEnd += step; 2831 *nextEnd += step;
2390 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 2832 } while (precisely_zero(startT - other->fTs[*nextEnd].fT));
2391 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2833 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
2392 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { 2834 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) {
2393 *unsortable = true; 2835 *unsortable = true;
2394 return NULL; 2836 return NULL;
2395 } 2837 }
2396 return other; 2838 return other;
2397 } 2839 }
2840 const int end = nextExactSpan(startIndex, step);
2841 SkASSERT(end >= 0);
2398 SkASSERT(startIndex - endIndex != 0); 2842 SkASSERT(startIndex - endIndex != 0);
2399 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2843 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2400 // more than one viable candidate -- measure angles to find best 2844 // more than one viable candidate -- measure angles to find best
2401 2845
2402 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding); 2846 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding);
2403 bool sortable = calcWinding != SK_NaN32; 2847 bool sortable = calcWinding != SK_NaN32;
2404 if (!sortable) { 2848 if (!sortable) {
2405 *unsortable = true; 2849 *unsortable = true;
2406 markDoneUnary(SkMin32(startIndex, endIndex)); 2850 markDoneUnary(SkMin32(startIndex, endIndex));
2407 return NULL; 2851 return NULL;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2467 return nextSegment; 2911 return nextSegment;
2468 } 2912 }
2469 2913
2470 SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort able) { 2914 SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort able) {
2471 const int startIndex = *nextStart; 2915 const int startIndex = *nextStart;
2472 const int endIndex = *nextEnd; 2916 const int endIndex = *nextEnd;
2473 SkASSERT(startIndex != endIndex); 2917 SkASSERT(startIndex != endIndex);
2474 SkDEBUGCODE(int count = fTs.count()); 2918 SkDEBUGCODE(int count = fTs.count());
2475 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); 2919 SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
2476 int step = SkSign32(endIndex - startIndex); 2920 int step = SkSign32(endIndex - startIndex);
2477 int end = nextExactSpan(startIndex, step);
2478 SkASSERT(end >= 0);
2479 SkOpSpan* endSpan = &fTs[end];
2480 SkOpSegment* other;
2481 // Detect cases where all the ends canceled out (e.g., 2921 // Detect cases where all the ends canceled out (e.g.,
2482 // there is no angle) and therefore there's only one valid connection 2922 // there is no angle) and therefore there's only one valid connection
2483 if (isSimple(end) || !spanToAngle(end, startIndex)) { 2923 *nextStart = startIndex;
2924 SkOpSegment* other = isSimple(nextStart, &step);
2925 if (other)
2926 {
2484 #if DEBUG_WINDING 2927 #if DEBUG_WINDING
2485 SkDebugf("%s simple\n", __FUNCTION__); 2928 SkDebugf("%s simple\n", __FUNCTION__);
2486 #endif 2929 #endif
2487 int min = SkMin32(startIndex, endIndex); 2930 int min = SkMin32(startIndex, endIndex);
2488 if (fTs[min].fDone) { 2931 if (fTs[min].fDone) {
2489 return NULL; 2932 return NULL;
2490 } 2933 }
2491 markDone(min, 1); 2934 markDone(min, 1);
2492 other = endSpan->fOther;
2493 *nextStart = endSpan->fOtherIndex;
2494 double startT = other->fTs[*nextStart].fT; 2935 double startT = other->fTs[*nextStart].fT;
2495 // FIXME: I don't know why the logic here is difference from the winding case 2936 // FIXME: I don't know why the logic here is difference from the winding case
2496 SkDEBUGCODE(bool firstLoop = true;) 2937 SkDEBUGCODE(bool firstLoop = true;)
2497 if ((approximately_less_than_zero(startT) && step < 0) 2938 if ((approximately_less_than_zero(startT) && step < 0)
2498 || (approximately_greater_than_one(startT) && step > 0)) { 2939 || (approximately_greater_than_one(startT) && step > 0)) {
2499 step = -step; 2940 step = -step;
2500 SkDEBUGCODE(firstLoop = false;) 2941 SkDEBUGCODE(firstLoop = false;)
2501 } 2942 }
2502 do { 2943 do {
2503 *nextEnd = *nextStart; 2944 *nextEnd = *nextStart;
2504 do { 2945 do {
2505 *nextEnd += step; 2946 *nextEnd += step;
2506 } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 2947 } while (precisely_zero(startT - other->fTs[*nextEnd].fT));
2507 if (other->fTs[SkMin32(*nextStart, *nextEnd)].fWindValue) { 2948 if (other->fTs[SkMin32(*nextStart, *nextEnd)].fWindValue) {
2508 break; 2949 break;
2509 } 2950 }
2510 SkASSERT(firstLoop); 2951 SkASSERT(firstLoop);
2511 SkDEBUGCODE(firstLoop = false;) 2952 SkDEBUGCODE(firstLoop = false;)
2512 step = -step; 2953 step = -step;
2513 } while (true); 2954 } while (true);
2514 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2955 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
2515 return other; 2956 return other;
2516 } 2957 }
2517 SkASSERT(startIndex - endIndex != 0); 2958 SkASSERT(startIndex - endIndex != 0);
2518 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2959 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2519 // parallel block above with presorted version 2960 // parallel block above with presorted version
2961 int end = nextExactSpan(startIndex, step);
2962 SkASSERT(end >= 0);
2520 SkOpAngle* angle = spanToAngle(end, startIndex); 2963 SkOpAngle* angle = spanToAngle(end, startIndex);
2521 SkASSERT(angle); 2964 SkASSERT(angle);
2522 #if DEBUG_SORT 2965 #if DEBUG_SORT
2523 SkDebugf("%s\n", __FUNCTION__); 2966 SkDebugf("%s\n", __FUNCTION__);
2524 angle->debugLoop(); 2967 angle->debugLoop();
2525 #endif 2968 #endif
2526 SkOpAngle* nextAngle = angle->next(); 2969 SkOpAngle* nextAngle = angle->next();
2527 const SkOpAngle* foundAngle = NULL; 2970 const SkOpAngle* foundAngle = NULL;
2528 bool foundDone = false; 2971 bool foundDone = false;
2529 SkOpSegment* nextSegment; 2972 SkOpSegment* nextSegment;
(...skipping 25 matching lines...) Expand all
2555 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d); 2998 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEn d);
2556 #endif 2999 #endif
2557 return nextSegment; 3000 return nextSegment;
2558 } 3001 }
2559 3002
2560 int SkOpSegment::findStartSpan(int startIndex) const { 3003 int SkOpSegment::findStartSpan(int startIndex) const {
2561 int index = startIndex; 3004 int index = startIndex;
2562 const SkOpSpan* span = &fTs[index]; 3005 const SkOpSpan* span = &fTs[index];
2563 const SkPoint& firstPt = span->fPt; 3006 const SkPoint& firstPt = span->fPt;
2564 double firstT = span->fT; 3007 double firstT = span->fT;
3008 const SkOpSpan* prior;
2565 do { 3009 do {
2566 if (index > 0) { 3010 prior = span;
2567 if (span->fT != firstT) { 3011 span = &fTs[++index];
2568 break; 3012 } while (SkDPoint::ApproximatelyEqual(span->fPt, firstPt)
2569 } 3013 && (span->fT == firstT || prior->fTiny));
2570 if (!SkDPoint::ApproximatelyEqual(firstPt, fTs[index].fPt)) {
2571 return -1;
2572 }
2573 }
2574 ++index;
2575 if (span->fTiny) {
2576 if (!SkDPoint::ApproximatelyEqual(firstPt, fTs[index].fPt)) {
2577 return -1;
2578 }
2579 firstT = fTs[index++].fT;
2580 }
2581 span = &fTs[index];
2582 } while (true);
2583 return index; 3014 return index;
2584 } 3015 }
2585 3016
2586 int SkOpSegment::findExactT(double t, const SkOpSegment* match) const { 3017 int SkOpSegment::findExactT(double t, const SkOpSegment* match) const {
2587 int count = this->count(); 3018 int count = this->count();
2588 for (int index = 0; index < count; ++index) { 3019 for (int index = 0; index < count; ++index) {
2589 const SkOpSpan& span = fTs[index]; 3020 const SkOpSpan& span = fTs[index];
2590 if (span.fT == t && span.fOther == match) { 3021 if (span.fT == t && span.fOther == match) {
2591 return index; 3022 return index;
2592 } 3023 }
2593 } 3024 }
2594 SkASSERT(0); 3025 SkASSERT(0);
2595 return -1; 3026 return -1;
2596 } 3027 }
2597 3028
3029 int SkOpSegment::findOtherT(double t, const SkOpSegment* match) const {
3030 int count = this->count();
3031 for (int index = 0; index < count; ++index) {
3032 const SkOpSpan& span = fTs[index];
3033 if (span.fOtherT == t && span.fOther == match) {
3034 return index;
3035 }
3036 }
3037 return -1;
3038 }
3039
2598 int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) co nst { 3040 int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) co nst {
2599 int count = this->count(); 3041 int count = this->count();
2600 for (int index = 0; index < count; ++index) { 3042 for (int index = 0; index < count; ++index) {
2601 const SkOpSpan& span = fTs[index]; 3043 const SkOpSpan& span = fTs[index];
2602 if (approximately_equal_orderable(span.fT, t) && span.fOther == match) { 3044 if (approximately_equal_orderable(span.fT, t) && span.fOther == match) {
2603 return index; 3045 return index;
2604 } 3046 }
2605 } 3047 }
2606 // Usually, the pair of ts are an exact match. It's possible that the t valu es have 3048 // Usually, the pair of ts are an exact match. It's possible that the t valu es have
2607 // been adjusted to make multiple intersections align. In this rare case, lo ok for a 3049 // been adjusted to make multiple intersections align. In this rare case, lo ok for a
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2640 if (span(firstT).fDone || (end = nextSpan(firstT, step)) == -1) { 3082 if (span(firstT).fDone || (end = nextSpan(firstT, step)) == -1) {
2641 step = -1; 3083 step = -1;
2642 end = nextSpan(firstT, step); 3084 end = nextSpan(firstT, step);
2643 SkASSERT(end != -1); 3085 SkASSERT(end != -1);
2644 } 3086 }
2645 // if the topmost T is not on end, or is three-way or more, find left 3087 // if the topmost T is not on end, or is three-way or more, find left
2646 // look for left-ness from tLeft to firstT (matching y of other) 3088 // look for left-ness from tLeft to firstT (matching y of other)
2647 SkASSERT(firstT - end != 0); 3089 SkASSERT(firstT - end != 0);
2648 SkOpAngle* markAngle = spanToAngle(firstT, end); 3090 SkOpAngle* markAngle = spanToAngle(firstT, end);
2649 if (!markAngle) { 3091 if (!markAngle) {
2650 markAngle = addSingletonAngles(firstT, step); 3092 markAngle = addSingletonAngles(step);
2651 } 3093 }
2652 markAngle->markStops(); 3094 markAngle->markStops();
2653 const SkOpAngle* baseAngle = markAngle->findFirst(); 3095 const SkOpAngle* baseAngle = markAngle->findFirst();
2654 if (!baseAngle) { 3096 if (!baseAngle) {
2655 return NULL; // nothing to do 3097 return NULL; // nothing to do
2656 } 3098 }
2657 SkScalar top = SK_ScalarMax; 3099 SkScalar top = SK_ScalarMax;
2658 const SkOpAngle* firstAngle = NULL; 3100 const SkOpAngle* firstAngle = NULL;
2659 const SkOpAngle* angle = baseAngle; 3101 const SkOpAngle* angle = baseAngle;
2660 do { 3102 do {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2747 if (oT == oSpan.fT && this == oSpan.fOther && oSpan.fOtherT == iSpan .fT) { 3189 if (oT == oSpan.fT && this == oSpan.fOther && oSpan.fOtherT == iSpan .fT) {
2748 iSpan.fOtherIndex = o; 3190 iSpan.fOtherIndex = o;
2749 oSpan.fOtherIndex = i; 3191 oSpan.fOtherIndex = i;
2750 break; 3192 break;
2751 } 3193 }
2752 } 3194 }
2753 SkASSERT(iSpan.fOtherIndex >= 0); 3195 SkASSERT(iSpan.fOtherIndex >= 0);
2754 } 3196 }
2755 } 3197 }
2756 3198
3199 bool SkOpSegment::inCoincidentSpan(double t, const SkOpSegment* other) const {
3200 int foundEnds = 0;
3201 int count = this->count();
3202 for (int index = 0; index < count; ++index) {
3203 const SkOpSpan& span = this->span(index);
3204 if (span.fCoincident) {
3205 foundEnds |= (span.fOther == other) << ((t > span.fT) + (t >= span.f T));
3206 }
3207 }
3208 SkASSERT(foundEnds != 7);
3209 return foundEnds == 0x3 || foundEnds == 0x5 || foundEnds == 0x6; // two bit s set
3210 }
3211
2757 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo l evenOdd) { 3212 void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo l evenOdd) {
2758 fDoneSpans = 0; 3213 fDoneSpans = 0;
2759 fOperand = operand; 3214 fOperand = operand;
2760 fXor = evenOdd; 3215 fXor = evenOdd;
2761 fPts = pts; 3216 fPts = pts;
2762 fVerb = verb; 3217 fVerb = verb;
2763 fLoop = fSmall = fTiny = false; 3218 fLoop = fMultiples = fSmall = fTiny = false;
2764 } 3219 }
2765 3220
2766 void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIn cludeType) { 3221 void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIn cludeType) {
2767 int local = spanSign(start, end); 3222 int local = spanSign(start, end);
2768 if (angleIncludeType == SkOpAngle::kBinarySingle) { 3223 if (angleIncludeType == SkOpAngle::kBinarySingle) {
2769 int oppLocal = oppSign(start, end); 3224 int oppLocal = oppSign(start, end);
2770 (void) markAndChaseWinding(start, end, local, oppLocal); 3225 (void) markAndChaseWinding(start, end, local, oppLocal);
2771 // OPTIMIZATION: the reverse mark and chase could skip the first marking 3226 // OPTIMIZATION: the reverse mark and chase could skip the first marking
2772 (void) markAndChaseWinding(end, start, local, oppLocal); 3227 (void) markAndChaseWinding(end, start, local, oppLocal);
2773 } else { 3228 } else {
(...skipping 12 matching lines...) Expand all
2786 from has the same x direction as this span, the winding should change. If the dx is opposite, then 3241 from has the same x direction as this span, the winding should change. If the dx is opposite, then
2787 the same winding is shared by both. 3242 the same winding is shared by both.
2788 */ 3243 */
2789 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc alar hitDx, 3244 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc alar hitDx,
2790 int oppWind, SkScalar hitOppDx) { 3245 int oppWind, SkScalar hitOppDx) {
2791 SkASSERT(hitDx || !winding); 3246 SkASSERT(hitDx || !winding);
2792 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 3247 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX;
2793 SkASSERT(dx); 3248 SkASSERT(dx);
2794 int windVal = windValue(SkMin32(start, end)); 3249 int windVal = windValue(SkMin32(start, end));
2795 #if DEBUG_WINDING_AT_T 3250 #if DEBUG_WINDING_AT_T
2796 SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding , 3251 SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, d ebugID(), winding,
2797 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); 3252 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal);
2798 #endif 3253 #endif
2799 int sideWind = winding + (dx < 0 ? windVal : -windVal); 3254 int sideWind = winding + (dx < 0 ? windVal : -windVal);
2800 if (abs(winding) < abs(sideWind)) { 3255 if (abs(winding) < abs(sideWind)) {
2801 winding = sideWind; 3256 winding = sideWind;
2802 } 3257 }
2803 #if DEBUG_WINDING_AT_T
2804 SkDebugf(" winding=%d\n", winding);
2805 #endif
2806 SkDEBUGCODE(int oppLocal = oppSign(start, end)); 3258 SkDEBUGCODE(int oppLocal = oppSign(start, end));
2807 SkASSERT(hitOppDx || !oppWind || !oppLocal); 3259 SkASSERT(hitOppDx || !oppWind || !oppLocal);
2808 int oppWindVal = oppValue(SkMin32(start, end)); 3260 int oppWindVal = oppValue(SkMin32(start, end));
2809 if (!oppWind) { 3261 if (!oppWind) {
2810 oppWind = dx < 0 ? oppWindVal : -oppWindVal; 3262 oppWind = dx < 0 ? oppWindVal : -oppWindVal;
2811 } else if (hitOppDx * dx >= 0) { 3263 } else if (hitOppDx * dx >= 0) {
2812 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); 3264 int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal);
2813 if (abs(oppWind) < abs(oppSideWind)) { 3265 if (abs(oppWind) < abs(oppSideWind)) {
2814 oppWind = oppSideWind; 3266 oppWind = oppSideWind;
2815 } 3267 }
2816 } 3268 }
3269 #if DEBUG_WINDING_AT_T
3270 SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind);
3271 #endif
2817 (void) markAndChaseWinding(start, end, winding, oppWind); 3272 (void) markAndChaseWinding(start, end, winding, oppWind);
2818 // OPTIMIZATION: the reverse mark and chase could skip the first marking 3273 // OPTIMIZATION: the reverse mark and chase could skip the first marking
2819 (void) markAndChaseWinding(end, start, winding, oppWind); 3274 (void) markAndChaseWinding(end, start, winding, oppWind);
2820 } 3275 }
2821 3276
2822 bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPt r) const { 3277 bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPt r) const {
2823 if (!baseAngle->inLoop()) { 3278 if (!baseAngle->inLoop()) {
2824 return false; 3279 return false;
2825 } 3280 }
2826 int index = *indexPtr; 3281 int index = *indexPtr;
2827 int froIndex = fTs[index].fFromAngleIndex; 3282 SkOpAngle* from = fTs[index].fFromAngle;
2828 int toIndex = fTs[index].fToAngleIndex; 3283 SkOpAngle* to = fTs[index].fToAngle;
2829 while (++index < spanCount) { 3284 while (++index < spanCount) {
2830 int nextFro = fTs[index].fFromAngleIndex; 3285 SkOpAngle* nextFrom = fTs[index].fFromAngle;
2831 int nextTo = fTs[index].fToAngleIndex; 3286 SkOpAngle* nextTo = fTs[index].fToAngle;
2832 if (froIndex != nextFro || toIndex != nextTo) { 3287 if (from != nextFrom || to != nextTo) {
2833 break; 3288 break;
2834 } 3289 }
2835 } 3290 }
2836 *indexPtr = index; 3291 *indexPtr = index;
2837 return true; 3292 return true;
2838 } 3293 }
2839 3294
2840 // OPTIMIZE: successive calls could start were the last leaves off 3295 // OPTIMIZE: successive calls could start were the last leaves off
2841 // or calls could specialize to walk forwards or backwards 3296 // or calls could specialize to walk forwards or backwards
2842 bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const { 3297 bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const {
2843 int tCount = fTs.count(); 3298 int tCount = fTs.count();
2844 for (int index = 0; index < tCount; ++index) { 3299 for (int index = 0; index < tCount; ++index) {
2845 const SkOpSpan& span = fTs[index]; 3300 const SkOpSpan& span = fTs[index];
2846 if (approximately_zero(startT - span.fT) && pt == span.fPt) { 3301 if (approximately_zero(startT - span.fT) && pt == span.fPt) {
2847 return false; 3302 return false;
2848 } 3303 }
2849 } 3304 }
2850 return true; 3305 return true;
2851 } 3306 }
2852 3307
2853 bool SkOpSegment::isSimple(int end) const { 3308
2854 #if 1 3309 SkOpSegment* SkOpSegment::isSimple(int* end, int* step) {
2855 int count = fTs.count(); 3310 return nextChase(end, step, NULL, NULL);
2856 if (count == 2) {
2857 return true;
2858 }
2859 double t = fTs[end].fT;
2860 if (approximately_less_than_zero(t)) {
2861 return !approximately_less_than_zero(fTs[1].fT);
2862 }
2863 if (approximately_greater_than_one(t)) {
2864 return !approximately_greater_than_one(fTs[count - 2].fT);
2865 }
2866 return false;
2867 #else
2868 // OPTIMIZE: code could be rejiggered to use this simpler test. To make this work, a little
2869 // more logic is required to ignore the dangling canceled out spans
2870 const SkOpSpan& span = fTs[end];
2871 return span.fFromAngleIndex < 0 && span.fToAngleIndex < 0;
2872 #endif
2873 } 3311 }
2874 3312
2875 bool SkOpSegment::isTiny(const SkOpAngle* angle) const { 3313 bool SkOpSegment::isTiny(const SkOpAngle* angle) const {
2876 int start = angle->start(); 3314 int start = angle->start();
2877 int end = angle->end(); 3315 int end = angle->end();
2878 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; 3316 const SkOpSpan& mSpan = fTs[SkMin32(start, end)];
2879 return mSpan.fTiny; 3317 return mSpan.fTiny;
2880 } 3318 }
2881 3319
2882 bool SkOpSegment::isTiny(int index) const { 3320 bool SkOpSegment::isTiny(int index) const {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2921 } 3359 }
2922 3360
2923 // this span is excluded by the winding rule -- chase the ends 3361 // this span is excluded by the winding rule -- chase the ends
2924 // as long as they are unambiguous to mark connections as done 3362 // as long as they are unambiguous to mark connections as done
2925 // and give them the same winding value 3363 // and give them the same winding value
2926 3364
2927 SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) { 3365 SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) {
2928 int step = SkSign32(endIndex - index); 3366 int step = SkSign32(endIndex - index);
2929 int min = SkMin32(index, endIndex); 3367 int min = SkMin32(index, endIndex);
2930 markDoneBinary(min); 3368 markDoneBinary(min);
2931 SkOpSpan* last; 3369 SkOpSpan* last = NULL;
2932 SkOpSegment* other = this; 3370 SkOpSegment* other = this;
2933 while ((other = other->nextChase(&index, step, &min, &last))) { 3371 while ((other = other->nextChase(&index, &step, &min, &last))) {
2934 if (other->done()) { 3372 if (other->done()) {
2935 return NULL; 3373 SkASSERT(!last);
3374 break;
2936 } 3375 }
2937 other->markDoneBinary(min); 3376 other->markDoneBinary(min);
2938 } 3377 }
2939 return last; 3378 return last;
2940 } 3379 }
2941 3380
2942 SkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) { 3381 SkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) {
2943 int step = SkSign32(endIndex - index); 3382 int step = SkSign32(endIndex - index);
2944 int min = SkMin32(index, endIndex); 3383 int min = SkMin32(index, endIndex);
2945 markDoneUnary(min); 3384 markDoneUnary(min);
2946 SkOpSpan* last; 3385 SkOpSpan* last = NULL;
2947 SkOpSegment* other = this; 3386 SkOpSegment* other = this;
2948 while ((other = other->nextChase(&index, step, &min, &last))) { 3387 while ((other = other->nextChase(&index, &step, &min, &last))) {
2949 if (other->done()) { 3388 if (other->done()) {
2950 return NULL; 3389 SkASSERT(!last);
3390 break;
2951 } 3391 }
2952 other->markDoneUnary(min); 3392 other->markDoneUnary(min);
2953 } 3393 }
2954 return last; 3394 return last;
2955 } 3395 }
2956 3396
2957 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) { 3397 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) {
2958 int index = angle->start(); 3398 int index = angle->start();
2959 int endIndex = angle->end(); 3399 int endIndex = angle->end();
2960 int step = SkSign32(endIndex - index); 3400 int step = SkSign32(endIndex - index);
2961 int min = SkMin32(index, endIndex); 3401 int min = SkMin32(index, endIndex);
2962 markWinding(min, winding); 3402 markWinding(min, winding);
2963 SkOpSpan* last; 3403 SkOpSpan* last = NULL;
2964 SkOpSegment* other = this; 3404 SkOpSegment* other = this;
2965 while ((other = other->nextChase(&index, step, &min, &last))) { 3405 while ((other = other->nextChase(&index, &step, &min, &last))) {
2966 if (other->fTs[min].fWindSum != SK_MinS32) { 3406 if (other->fTs[min].fWindSum != SK_MinS32) {
2967 SkASSERT(other->fTs[min].fWindSum == winding); 3407 SkASSERT(other->fTs[min].fWindSum == winding);
2968 return NULL; 3408 SkASSERT(!last);
3409 break;
2969 } 3410 }
2970 other->markWinding(min, winding); 3411 other->markWinding(min, winding);
2971 } 3412 }
2972 return last; 3413 return last;
2973 } 3414 }
2974 3415
2975 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding) { 3416 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding) {
2976 int min = SkMin32(index, endIndex); 3417 int min = SkMin32(index, endIndex);
2977 int step = SkSign32(endIndex - index); 3418 int step = SkSign32(endIndex - index);
2978 markWinding(min, winding); 3419 markWinding(min, winding);
2979 SkOpSpan* last; 3420 SkOpSpan* last = NULL;
2980 SkOpSegment* other = this; 3421 SkOpSegment* other = this;
2981 while ((other = other->nextChase(&index, step, &min, &last))) { 3422 while ((other = other->nextChase(&index, &step, &min, &last))) {
2982 if (other->fTs[min].fWindSum != SK_MinS32) { 3423 if (other->fTs[min].fWindSum != SK_MinS32) {
2983 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p); 3424 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p);
2984 return NULL; 3425 SkASSERT(!last);
3426 break;
2985 } 3427 }
2986 other->markWinding(min, winding); 3428 other->markWinding(min, winding);
2987 } 3429 }
2988 return last; 3430 return last;
2989 } 3431 }
2990 3432
2991 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) { 3433 SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) {
2992 int min = SkMin32(index, endIndex); 3434 int min = SkMin32(index, endIndex);
2993 int step = SkSign32(endIndex - index); 3435 int step = SkSign32(endIndex - index);
2994 markWinding(min, winding, oppWinding); 3436 markWinding(min, winding, oppWinding);
2995 SkOpSpan* last; 3437 SkOpSpan* last = NULL;
2996 SkOpSegment* other = this; 3438 SkOpSegment* other = this;
2997 while ((other = other->nextChase(&index, step, &min, &last))) { 3439 while ((other = other->nextChase(&index, &step, &min, &last))) {
2998 if (other->fTs[min].fWindSum != SK_MinS32) { 3440 if (other->fTs[min].fWindSum != SK_MinS32) {
2999 SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoo p); 3441 #if SK_DEBUG
3000 return NULL; 3442 if (!other->fTs[min].fLoop) {
3443 if (fOperand == other->fOperand) {
3444 // FIXME: this is probably a bug -- rects4 asserts here
3445 // SkASSERT(other->fTs[min].fWindSum == winding);
3446 // FIXME: this is probably a bug -- rects3 asserts here
3447 // SkASSERT(other->fTs[min].fOppSum == oppWinding);
3448 } else {
3449 SkASSERT(other->fTs[min].fWindSum == oppWinding);
3450 // FIXME: this is probably a bug -- skpwww_joomla_org_23 asserts here
3451 // SkASSERT(other->fTs[min].fOppSum == winding);
3452 }
3453 }
3454 SkASSERT(!last);
3455 #endif
3456 break;
3001 } 3457 }
3002 other->markWinding(min, winding, oppWinding); 3458 if (fOperand == other->fOperand) {
3459 other->markWinding(min, winding, oppWinding);
3460 } else {
3461 other->markWinding(min, oppWinding, winding);
3462 }
3003 } 3463 }
3004 return last; 3464 return last;
3005 } 3465 }
3006 3466
3007 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding) { 3467 SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding) {
3008 int start = angle->start(); 3468 int start = angle->start();
3009 int end = angle->end(); 3469 int end = angle->end();
3010 return markAndChaseWinding(start, end, winding, oppWinding); 3470 return markAndChaseWinding(start, end, winding, oppWinding);
3011 } 3471 }
3012 3472
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
3309 SkOpSpan& newSpan = fTs[tIndex]; 3769 SkOpSpan& newSpan = fTs[tIndex];
3310 newSpan.fWindValue = nextDoorWind; 3770 newSpan.fWindValue = nextDoorWind;
3311 newSpan.fOppValue = nextOppWind; 3771 newSpan.fOppValue = nextOppWind;
3312 if (!nextDoorWind && !nextOppWind && !newSpan.fDone) { 3772 if (!nextDoorWind && !nextOppWind && !newSpan.fDone) {
3313 newSpan.fDone = true; 3773 newSpan.fDone = true;
3314 ++fDoneSpans; 3774 ++fDoneSpans;
3315 } 3775 }
3316 } 3776 }
3317 } 3777 }
3318 3778
3319 // return span if when chasing, two or more radiating spans are not done
3320 // OPTIMIZATION: ? multiple spans is detected when there is only one valid
3321 // candidate and the remaining spans have windValue == 0 (canceled by
3322 // coincidence). The coincident edges could either be removed altogether,
3323 // or this code could be more complicated in detecting this case. Worth it?
3324 bool SkOpSegment::multipleSpans(int end) const {
3325 return end > 0 && end < fTs.count() - 1;
3326 }
3327
3328 bool SkOpSegment::nextCandidate(int* start, int* end) const { 3779 bool SkOpSegment::nextCandidate(int* start, int* end) const {
3329 while (fTs[*end].fDone) { 3780 while (fTs[*end].fDone) {
3330 if (fTs[*end].fT == 1) { 3781 if (fTs[*end].fT == 1) {
3331 return false; 3782 return false;
3332 } 3783 }
3333 ++(*end); 3784 ++(*end);
3334 } 3785 }
3335 *start = *end; 3786 *start = *end;
3336 *end = nextExactSpan(*start, 1); 3787 *end = nextExactSpan(*start, 1);
3337 return true; 3788 return true;
3338 } 3789 }
3339 3790
3340 SkOpSegment* SkOpSegment::nextChase(int* index, const int step, int* min, SkOpSp an** last) { 3791 static SkOpSegment* set_last(SkOpSpan** last, SkOpSpan* endSpan) {
3341 int end = nextExactSpan(*index, step); 3792 if (last && !endSpan->fSmall) {
3793 *last = endSpan;
3794 }
3795 return NULL;
3796 }
3797
3798 SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, Sk OpSpan** last) {
3799 int origIndex = *indexPtr;
3800 int step = *stepPtr;
3801 int end = nextExactSpan(origIndex, step);
3342 SkASSERT(end >= 0); 3802 SkASSERT(end >= 0);
3343 if (fTs[end].fSmall) { 3803 SkOpSpan& endSpan = fTs[end];
3344 *last = NULL; 3804 SkOpAngle* angle = step > 0 ? endSpan.fFromAngle : endSpan.fToAngle;
3345 return NULL; 3805 int foundIndex;
3806 int otherEnd;
3807 SkOpSegment* other;
3808 if (angle == NULL) {
3809 if (endSpan.fT != 0 && endSpan.fT != 1) {
3810 return NULL;
3811 }
3812 other = endSpan.fOther;
3813 foundIndex = endSpan.fOtherIndex;
3814 otherEnd = other->nextExactSpan(foundIndex, step);
3815 } else {
3816 int loopCount = angle->loopCount();
3817 if (loopCount > 2) {
3818 return set_last(last, &endSpan);
3819 }
3820 const SkOpAngle* next = angle->next();
3821 if (angle->sign() != next->sign()) {
3822 #if DEBUG_WINDING
3823 SkDebugf("%s mismatched signs\n", __FUNCTION__);
3824 #endif
3825 // return set_last(last, &endSpan);
3826 }
3827 other = next->segment();
3828 foundIndex = end = next->start();
3829 otherEnd = next->end();
3346 } 3830 }
3347 if (multipleSpans(end)) { 3831 int foundStep = foundIndex < otherEnd ? 1 : -1;
3348 *last = &fTs[end]; 3832 if (*stepPtr != foundStep) {
3349 return NULL; 3833 return set_last(last, &endSpan);
3350 } 3834 }
3351 const SkOpSpan& endSpan = fTs[end]; 3835 SkASSERT(*indexPtr >= 0);
3352 SkOpSegment* other = endSpan.fOther;
3353 *index = endSpan.fOtherIndex;
3354 SkASSERT(*index >= 0);
3355 int otherEnd = other->nextExactSpan(*index, step);
3356 SkASSERT(otherEnd >= 0); 3836 SkASSERT(otherEnd >= 0);
3357 *min = SkMin32(*index, otherEnd); 3837 #if 1
3358 if (other->fTs[*min].fSmall) { 3838 int origMin = origIndex + (step < 0 ? step : 0);
3359 *last = NULL; 3839 const SkOpSpan& orig = this->span(origMin);
3360 return NULL; 3840 #endif
3841 int foundMin = SkMin32(foundIndex, otherEnd);
3842 #if 1
3843 const SkOpSpan& found = other->span(foundMin);
3844 if (found.fWindValue != orig.fWindValue || found.fOppValue != orig.fOppValue ) {
3845 return set_last(last, &endSpan);
3846 }
3847 #endif
3848 *indexPtr = foundIndex;
3849 *stepPtr = foundStep;
3850 if (minPtr) {
3851 *minPtr = foundMin;
3361 } 3852 }
3362 return other; 3853 return other;
3363 } 3854 }
3364 3855
3365 // This has callers for two different situations: one establishes the end 3856 // This has callers for two different situations: one establishes the end
3366 // of the current span, and one establishes the beginning of the next span 3857 // of the current span, and one establishes the beginning of the next span
3367 // (thus the name). When this is looking for the end of the current span, 3858 // (thus the name). When this is looking for the end of the current span,
3368 // coincidence is found when the beginning Ts contain -step and the end 3859 // coincidence is found when the beginning Ts contain -step and the end
3369 // contains step. When it is looking for the beginning of the next, the 3860 // contains step. When it is looking for the beginning of the next, the
3370 // first Ts found can be ignored and the last Ts should contain -step. 3861 // first Ts found can be ignored and the last Ts should contain -step.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3407 const SkOpSpan& span = fTs[to]; 3898 const SkOpSpan& span = fTs[to];
3408 if (precisely_negative(span.fT - fromSpan.fT)) { 3899 if (precisely_negative(span.fT - fromSpan.fT)) {
3409 continue; 3900 continue;
3410 } 3901 }
3411 return to; 3902 return to;
3412 } 3903 }
3413 } 3904 }
3414 return -1; 3905 return -1;
3415 } 3906 }
3416 3907
3908 void SkOpSegment::pinT(const SkPoint& pt, double* t) {
3909 if (pt == fPts[0]) {
3910 *t = 0;
3911 }
3912 int count = SkPathOpsVerbToPoints(fVerb);
3913 if (pt == fPts[count]) {
3914 *t = 1;
3915 }
3916 }
3917
3918 void SkOpSegment::setCoincidentRange(const SkPoint& startPt, const SkPoint& endP t,
3919 SkOpSegment* other) {
3920 int count = this->count();
3921 for (int index = 0; index < count; ++index) {
3922 SkOpSpan &span = fTs[index];
3923 if ((startPt == span.fPt || endPt == span.fPt) && other == span.fOther) {
3924 span.fCoincident = true;
3925 }
3926 }
3927 }
3928
3417 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding, 3929 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding,
3418 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding ) { 3930 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding ) {
3419 int deltaSum = spanSign(index, endIndex); 3931 int deltaSum = spanSign(index, endIndex);
3420 int oppDeltaSum = oppSign(index, endIndex); 3932 int oppDeltaSum = oppSign(index, endIndex);
3421 if (operand()) { 3933 if (operand()) {
3422 *maxWinding = *sumSuWinding; 3934 *maxWinding = *sumSuWinding;
3423 *sumWinding = *sumSuWinding -= deltaSum; 3935 *sumWinding = *sumSuWinding -= deltaSum;
3424 *oppMaxWinding = *sumMiWinding; 3936 *oppMaxWinding = *sumMiWinding;
3425 *oppSumWinding = *sumMiWinding -= oppDeltaSum; 3937 *oppSumWinding = *sumMiWinding -= oppDeltaSum;
3426 } else { 3938 } else {
(...skipping 18 matching lines...) Expand all
3445 #endif 3957 #endif
3446 } 3958 }
3447 3959
3448 void SkOpSegment::sortAngles() { 3960 void SkOpSegment::sortAngles() {
3449 int spanCount = fTs.count(); 3961 int spanCount = fTs.count();
3450 if (spanCount <= 2) { 3962 if (spanCount <= 2) {
3451 return; 3963 return;
3452 } 3964 }
3453 int index = 0; 3965 int index = 0;
3454 do { 3966 do {
3455 int fromIndex = fTs[index].fFromAngleIndex; 3967 SkOpAngle* fromAngle = fTs[index].fFromAngle;
3456 int toIndex = fTs[index].fToAngleIndex; 3968 SkOpAngle* toAngle = fTs[index].fToAngle;
3457 if (fromIndex < 0 && toIndex < 0) { 3969 if (!fromAngle && !toAngle) {
3458 index += 1; 3970 index += 1;
3459 continue; 3971 continue;
3460 } 3972 }
3461 SkOpAngle* baseAngle = NULL; 3973 SkOpAngle* baseAngle = NULL;
3462 if (fromIndex >= 0) { 3974 if (fromAngle) {
3463 baseAngle = &this->angle(fromIndex); 3975 baseAngle = fromAngle;
3464 if (inLoop(baseAngle, spanCount, &index)) { 3976 if (inLoop(baseAngle, spanCount, &index)) {
3465 continue; 3977 continue;
3466 } 3978 }
3467 } 3979 }
3468 #if DEBUG_ANGLE 3980 #if DEBUG_ANGLE
3469 bool wroteAfterHeader = false; 3981 bool wroteAfterHeader = false;
3470 #endif 3982 #endif
3471 if (toIndex >= 0) { 3983 if (toAngle) {
3472 SkOpAngle* toAngle = &this->angle(toIndex);
3473 if (!baseAngle) { 3984 if (!baseAngle) {
3474 baseAngle = toAngle; 3985 baseAngle = toAngle;
3475 if (inLoop(baseAngle, spanCount, &index)) { 3986 if (inLoop(baseAngle, spanCount, &index)) {
3476 continue; 3987 continue;
3477 } 3988 }
3478 } else { 3989 } else {
3479 SkDEBUGCODE(int newIndex = index); 3990 SkDEBUGCODE(int newIndex = index);
3480 SkASSERT(!inLoop(baseAngle, spanCount, &newIndex) && newIndex == index); 3991 SkASSERT(!inLoop(baseAngle, spanCount, &newIndex) && newIndex == index);
3481 #if DEBUG_ANGLE 3992 #if DEBUG_ANGLE
3482 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT, 3993 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT,
3483 index); 3994 index);
3484 wroteAfterHeader = true; 3995 wroteAfterHeader = true;
3485 #endif 3996 #endif
3486 baseAngle->insert(toAngle); 3997 baseAngle->insert(toAngle);
3487 } 3998 }
3488 } 3999 }
3489 int nextFrom, nextTo; 4000 SkOpAngle* nextFrom, * nextTo;
3490 int firstIndex = index; 4001 int firstIndex = index;
3491 do { 4002 do {
3492 SkOpSpan& span = fTs[index]; 4003 SkOpSpan& span = fTs[index];
3493 SkOpSegment* other = span.fOther; 4004 SkOpSegment* other = span.fOther;
3494 SkOpSpan& oSpan = other->fTs[span.fOtherIndex]; 4005 SkOpSpan& oSpan = other->fTs[span.fOtherIndex];
3495 int otherAngleIndex = oSpan.fFromAngleIndex; 4006 SkOpAngle* oAngle = oSpan.fFromAngle;
3496 if (otherAngleIndex >= 0) { 4007 if (oAngle) {
3497 #if DEBUG_ANGLE 4008 #if DEBUG_ANGLE
3498 if (!wroteAfterHeader) { 4009 if (!wroteAfterHeader) {
3499 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT, 4010 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT,
3500 index); 4011 index);
3501 wroteAfterHeader = true; 4012 wroteAfterHeader = true;
3502 } 4013 }
3503 #endif 4014 #endif
3504 SkOpAngle* oAngle = &other->angle(otherAngleIndex);
3505 if (!oAngle->loopContains(*baseAngle)) { 4015 if (!oAngle->loopContains(*baseAngle)) {
3506 baseAngle->insert(oAngle); 4016 baseAngle->insert(oAngle);
3507 } 4017 }
3508 } 4018 }
3509 otherAngleIndex = oSpan.fToAngleIndex; 4019 oAngle = oSpan.fToAngle;
3510 if (otherAngleIndex >= 0) { 4020 if (oAngle) {
3511 #if DEBUG_ANGLE 4021 #if DEBUG_ANGLE
3512 if (!wroteAfterHeader) { 4022 if (!wroteAfterHeader) {
3513 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT, 4023 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT,
3514 index); 4024 index);
3515 wroteAfterHeader = true; 4025 wroteAfterHeader = true;
3516 } 4026 }
3517 #endif 4027 #endif
3518 SkOpAngle* oAngle = &other->angle(otherAngleIndex);
3519 if (!oAngle->loopContains(*baseAngle)) { 4028 if (!oAngle->loopContains(*baseAngle)) {
3520 baseAngle->insert(oAngle); 4029 baseAngle->insert(oAngle);
3521 } 4030 }
3522 } 4031 }
3523 if (++index == spanCount) { 4032 if (++index == spanCount) {
3524 break; 4033 break;
3525 } 4034 }
3526 nextFrom = fTs[index].fFromAngleIndex; 4035 nextFrom = fTs[index].fFromAngle;
3527 nextTo = fTs[index].fToAngleIndex; 4036 nextTo = fTs[index].fToAngle;
3528 } while (fromIndex == nextFrom && toIndex == nextTo); 4037 } while (fromAngle == nextFrom && toAngle == nextTo);
3529 if (baseAngle && baseAngle->loopCount() == 1) { 4038 if (baseAngle && baseAngle->loopCount() == 1) {
3530 index = firstIndex; 4039 index = firstIndex;
3531 do { 4040 do {
3532 SkOpSpan& span = fTs[index]; 4041 SkOpSpan& span = fTs[index];
3533 span.fFromAngleIndex = span.fToAngleIndex = -1; 4042 span.fFromAngle = span.fToAngle = NULL;
3534 if (++index == spanCount) { 4043 if (++index == spanCount) {
3535 break; 4044 break;
3536 } 4045 }
3537 nextFrom = fTs[index].fFromAngleIndex; 4046 nextFrom = fTs[index].fFromAngle;
3538 nextTo = fTs[index].fToAngleIndex; 4047 nextTo = fTs[index].fToAngle;
3539 } while (fromIndex == nextFrom && toIndex == nextTo); 4048 } while (fromAngle == nextFrom && toAngle == nextTo);
3540 baseAngle = NULL; 4049 baseAngle = NULL;
3541 } 4050 }
3542 #if DEBUG_SORT 4051 #if DEBUG_SORT
3543 SkASSERT(!baseAngle || baseAngle->loopCount() > 1); 4052 SkASSERT(!baseAngle || baseAngle->loopCount() > 1);
3544 #endif 4053 #endif
3545 } while (index < spanCount); 4054 } while (index < spanCount);
3546 } 4055 }
3547 4056
3548 // return true if midpoints were computed 4057 // return true if midpoints were computed
3549 bool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { 4058 bool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const {
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
3742 } 4251 }
3743 4252
3744 int SkOpSegment::windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx ) const { 4253 int SkOpSegment::windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx ) const {
3745 if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span, disregard 4254 if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span, disregard
3746 return SK_MinS32; 4255 return SK_MinS32;
3747 } 4256 }
3748 int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex); 4257 int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex);
3749 SkASSERT(winding != SK_MinS32); 4258 SkASSERT(winding != SK_MinS32);
3750 int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex); 4259 int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex);
3751 #if DEBUG_WINDING_AT_T 4260 #if DEBUG_WINDING_AT_T
3752 SkDebugf("%s oldWinding=%d windValue=%d", __FUNCTION__, winding, windVal); 4261 SkDebugf("%s id=%d opp=%d tHit=%1.9g t=%1.9g oldWinding=%d windValue=%d", __ FUNCTION__,
4262 debugID(), crossOpp, tHit, t(tIndex), winding, windVal);
3753 #endif 4263 #endif
3754 // see if a + change in T results in a +/- change in X (compute x'(T)) 4264 // see if a + change in T results in a +/- change in X (compute x'(T))
3755 *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 4265 *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX;
3756 if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { 4266 if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) {
3757 *dx = fPts[2].fX - fPts[1].fX - *dx; 4267 *dx = fPts[2].fX - fPts[1].fX - *dx;
3758 } 4268 }
3759 if (*dx == 0) { 4269 if (*dx == 0) {
3760 #if DEBUG_WINDING_AT_T 4270 #if DEBUG_WINDING_AT_T
3761 SkDebugf(" dx=0 winding=SK_MinS32\n"); 4271 SkDebugf(" dx=0 winding=SK_MinS32\n");
3762 #endif 4272 #endif
(...skipping 22 matching lines...) Expand all
3785 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 4295 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
3786 span->fWindValue = 0; 4296 span->fWindValue = 0;
3787 span->fOppValue = 0; 4297 span->fOppValue = 0;
3788 if (span->fTiny || span->fSmall) { 4298 if (span->fTiny || span->fSmall) {
3789 return; 4299 return;
3790 } 4300 }
3791 SkASSERT(!span->fDone); 4301 SkASSERT(!span->fDone);
3792 span->fDone = true; 4302 span->fDone = true;
3793 ++fDoneSpans; 4303 ++fDoneSpans;
3794 } 4304 }
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