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

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

Issue 1111333002: compute initial winding from projected rays (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add missing test reference Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpCoincidence.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 "SkOpAngle.h" 7 #include "SkOpAngle.h"
8 #include "SkOpSegment.h" 8 #include "SkOpSegment.h"
9 #include "SkPathOpsCurve.h" 9 #include "SkPathOpsCurve.h"
10 #include "SkTSort.h" 10 #include "SkTSort.h"
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 ? checkEnd->upCast()->next() : NULL 353 ? checkEnd->upCast()->next() : NULL
354 : checkEnd->prev(); 354 : checkEnd->prev();
355 } while (checkEnd); 355 } while (checkEnd);
356 recomputeSector: 356 recomputeSector:
357 SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->seg ment()->head() 357 SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->seg ment()->head()
358 : checkEnd ? checkEnd->upCast()->next() : fEnd->segment()->tail(); 358 : checkEnd ? checkEnd->upCast()->next() : fEnd->segment()->tail();
359 if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) { 359 if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) {
360 fUnorderable = true; 360 fUnorderable = true;
361 return false; 361 return false;
362 } 362 }
363 if (stepUp != (fStart->t() < computedEnd->t())) {
364 fUnorderable = true;
365 return false;
366 }
363 SkOpSpanBase* saveEnd = fEnd; 367 SkOpSpanBase* saveEnd = fEnd;
364 fComputedEnd = fEnd = computedEnd; 368 fComputedEnd = fEnd = computedEnd;
365 setSpans(); 369 setSpans();
366 setSector(); 370 setSector();
367 fEnd = saveEnd; 371 fEnd = saveEnd;
368 return !fUnorderable; 372 return !fUnorderable;
369 } 373 }
370 374
371 int SkOpAngle::convexHullOverlaps(const SkOpAngle* rh) const { 375 int SkOpAngle::convexHullOverlaps(const SkOpAngle* rh) const {
372 const SkDVector* sweep = this->fSweep; 376 const SkDVector* sweep = this->fSweep;
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 SkDVector vLeft = *endPt - start; 594 SkDVector vLeft = *endPt - start;
591 SkDVector vRight = oppPt - start; 595 SkDVector vRight = oppPt - start;
592 double dir = vLeft.crossCheck(vRight); 596 double dir = vLeft.crossCheck(vRight);
593 if (!dir) { 597 if (!dir) {
594 return false; 598 return false;
595 } 599 }
596 *inside = dir < 0; 600 *inside = dir < 0;
597 return true; 601 return true;
598 } 602 }
599 603
600 // Most of the time, the first one can be found trivially by detecting the small est sector value.
601 // If all angles have the same sector value, actual sorting is required.
602 SkOpAngle* SkOpAngle::findFirst() {
603 SkOpAngle* best = this;
604 int bestStart = SkTMin(fSectorStart, fSectorEnd);
605 SkOpAngle* angle = this;
606 while ((angle = angle->fNext) != this) {
607 int angleEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
608 if (angleEnd < bestStart) {
609 return angle; // we wrapped around
610 }
611 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
612 if (bestStart > angleStart) {
613 best = angle;
614 bestStart = angleStart;
615 }
616 }
617 // back up to the first possible angle
618 SkOpAngle* firstBest = best;
619 angle = best;
620 int bestEnd = SkTMax(best->fSectorStart, best->fSectorEnd);
621 while ((angle = angle->previous()) != firstBest) {
622 if (angle->fStop) {
623 break;
624 }
625 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
626 // angles that are smaller by one aren't necessary better, since the lar ger may be a line
627 // and the smaller may be a curve that curls to the other side of the li ne.
628 if (bestEnd + 1 < angleStart) {
629 return best;
630 }
631 best = angle;
632 bestEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
633 }
634 // in the case where all angles are nearly in the same sector, check the ord er to find the best
635 firstBest = best;
636 angle = best;
637 do {
638 angle = angle->fNext;
639 if (angle->fStop) {
640 return firstBest;
641 }
642 bool orderable = best->orderable(angle); // note: may return an unorder able angle
643 if (orderable == 0) {
644 return angle;
645 }
646 best = angle;
647 } while (angle != firstBest);
648 // if the angles are equally ordered, fall back on the initial tangent
649 bool foundBelow = false;
650 while ((angle = angle->fNext)) {
651 SkDVector scratch[2];
652 const SkDVector* sweep;
653 if (!angle->fUnorderedSweep) {
654 sweep = angle->fSweep;
655 } else {
656 scratch[0] = angle->fCurvePart[1] - angle->fCurvePart[0];
657 sweep = &scratch[0];
658 }
659 bool isAbove = sweep->fY <= 0;
660 if (isAbove && foundBelow) {
661 return angle;
662 }
663 foundBelow |= !isAbove;
664 if (angle == firstBest) {
665 return NULL; // should not loop around
666 }
667 }
668 SkASSERT(0); // should never get here
669 return NULL;
670 }
671
672 /* y<0 y==0 y>0 x<0 x==0 x>0 xy<0 xy==0 xy>0 604 /* y<0 y==0 y>0 x<0 x==0 x>0 xy<0 xy==0 xy>0
673 0 x x x 605 0 x x x
674 1 x x x 606 1 x x x
675 2 x x x 607 2 x x x
676 3 x x x 608 3 x x x
677 4 x x x 609 4 x x x
678 5 x x x 610 5 x x x
679 6 x x x 611 6 x x x
680 7 x x x 612 7 x x x
681 8 x x x 613 8 x x x
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 int count = 0; 741 int count = 0;
810 const SkOpAngle* first = this; 742 const SkOpAngle* first = this;
811 const SkOpAngle* next = this; 743 const SkOpAngle* next = this;
812 do { 744 do {
813 next = next->fNext; 745 next = next->fNext;
814 ++count; 746 ++count;
815 } while (next && next != first); 747 } while (next && next != first);
816 return count; 748 return count;
817 } 749 }
818 750
819 // OPTIMIZATION: can this be done better in after when angles are sorted?
820 bool SkOpAngle::markStops() {
821 SkOpAngle* angle = this;
822 int lastEnd = SkTMax(fSectorStart, fSectorEnd);
823 do {
824 angle = angle->fNext;
825 if (!angle) {
826 return false;
827 }
828 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
829 // angles that are smaller by one aren't necessary better, since the lar ger may be a line
830 // and the smaller may be a curve that curls to the other side of the li ne.
831 if (lastEnd + 1 < angleStart) {
832 angle->fStop = true;
833 }
834 lastEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
835 } while (angle != this);
836 return true;
837 }
838
839 bool SkOpAngle::merge(SkOpAngle* angle) { 751 bool SkOpAngle::merge(SkOpAngle* angle) {
840 SkASSERT(fNext); 752 SkASSERT(fNext);
841 SkASSERT(angle->fNext); 753 SkASSERT(angle->fNext);
842 SkOpAngle* working = angle; 754 SkOpAngle* working = angle;
843 do { 755 do {
844 if (this == working) { 756 if (this == working) {
845 return false; 757 return false;
846 } 758 }
847 working = working->fNext; 759 working = working->fNext;
848 } while (working != angle); 760 } while (working != angle);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 SkOpSegment* SkOpAngle::segment() const { 873 SkOpSegment* SkOpAngle::segment() const {
962 return fStart->segment(); 874 return fStart->segment();
963 } 875 }
964 876
965 void SkOpAngle::set(SkOpSpanBase* start, SkOpSpanBase* end) { 877 void SkOpAngle::set(SkOpSpanBase* start, SkOpSpanBase* end) {
966 fStart = start; 878 fStart = start;
967 fComputedEnd = fEnd = end; 879 fComputedEnd = fEnd = end;
968 SkASSERT(start != end); 880 SkASSERT(start != end);
969 fNext = NULL; 881 fNext = NULL;
970 fComputeSector = fComputedSector = fCheckCoincidence = false; 882 fComputeSector = fComputedSector = fCheckCoincidence = false;
971 fStop = false;
972 setSpans(); 883 setSpans();
973 setSector(); 884 setSector();
974 SkDEBUGCODE(fID = start ? start->globalState()->nextAngleID() : -1); 885 SkDEBUGCODE(fID = start ? start->globalState()->nextAngleID() : -1);
975 } 886 }
976 887
977 void SkOpAngle::setCurveHullSweep() { 888 void SkOpAngle::setCurveHullSweep() {
978 fUnorderedSweep = false; 889 fUnorderedSweep = false;
979 fSweep[0] = fCurvePart[1] - fCurvePart[0]; 890 fSweep[0] = fCurvePart[1] - fCurvePart[0];
980 const SkOpSegment* segment = fStart->segment(); 891 const SkOpSegment* segment = fStart->segment();
981 if (SkPath::kLine_Verb == segment->verb()) { 892 if (SkPath::kLine_Verb == segment->verb()) {
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 crossesZero = this->checkCrossesZero(); 1061 crossesZero = this->checkCrossesZero();
1151 start = SkTMin(fSectorStart, fSectorEnd); 1062 start = SkTMin(fSectorStart, fSectorEnd);
1152 int end = SkTMax(fSectorStart, fSectorEnd); 1063 int end = SkTMax(fSectorStart, fSectorEnd);
1153 if (!crossesZero) { 1064 if (!crossesZero) {
1154 fSectorMask = (unsigned) -1 >> (31 - end + start) << start; 1065 fSectorMask = (unsigned) -1 >> (31 - end + start) << start;
1155 } else { 1066 } else {
1156 fSectorMask = (unsigned) -1 >> (31 - start) | (-1 << end); 1067 fSectorMask = (unsigned) -1 >> (31 - start) | (-1 << end);
1157 } 1068 }
1158 } 1069 }
1159 1070
1160 int SkOpAngle::sign() const {
1161 SkASSERT(fStart->t() != fEnd->t());
1162 return fStart->t() < fEnd->t() ? -1 : 1;
1163 }
1164
1165 SkOpSpan* SkOpAngle::starter() { 1071 SkOpSpan* SkOpAngle::starter() {
1166 return fStart->starter(fEnd); 1072 return fStart->starter(fEnd);
1167 } 1073 }
1168 1074
1169 bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) const { 1075 bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) const {
1170 if (s0xt0 == 0) { 1076 if (s0xt0 == 0) {
1171 return false; 1077 return false;
1172 } 1078 }
1173 // if the ctrl tangents are not nearly parallel, use them 1079 // if the ctrl tangents are not nearly parallel, use them
1174 // solve for opposite direction displacement scale factor == m 1080 // solve for opposite direction displacement scale factor == m
(...skipping 11 matching lines...) Expand all
1186 return true; 1092 return true;
1187 } 1093 }
1188 SkASSERT(s0dt0 != 0); 1094 SkASSERT(s0dt0 != 0);
1189 double m = s0xt0 / s0dt0; 1095 double m = s0xt0 / s0dt0;
1190 double sDist = sweep[0].length() * m; 1096 double sDist = sweep[0].length() * m;
1191 double tDist = tweep[0].length() * m; 1097 double tDist = tweep[0].length() * m;
1192 bool useS = fabs(sDist) < fabs(tDist); 1098 bool useS = fabs(sDist) < fabs(tDist);
1193 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD ist)); 1099 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD ist));
1194 return mFactor < 2400; // empirically found limit 1100 return mFactor < 2400; // empirically found limit
1195 } 1101 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpCoincidence.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698