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

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

Issue 239563004: fix minor skp-found bugs (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix mac-detected errors Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkOpSpan.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "SkIntersections.h" 7 #include "SkIntersections.h"
8 #include "SkOpSegment.h" 8 #include "SkOpSegment.h"
9 #include "SkPathWriter.h" 9 #include "SkPathWriter.h"
10 #include "SkTSort.h" 10 #include "SkTSort.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 } 63 }
64 } while (precisely_negative(fTs[index].fT - referenceT)); 64 } while (precisely_negative(fTs[index].fT - referenceT));
65 return NULL; 65 return NULL;
66 } 66 }
67 67
68 const SkOpAngle* SkOpSegment::activeAngleInner(int index, int* start, int* end, bool* done, 68 const SkOpAngle* SkOpSegment::activeAngleInner(int index, int* start, int* end, bool* done,
69 bool* sortable) const { 69 bool* sortable) const {
70 int next = nextExactSpan(index, 1); 70 int next = nextExactSpan(index, 1);
71 if (next > 0) { 71 if (next > 0) {
72 const SkOpSpan& upSpan = fTs[index]; 72 const SkOpSpan& upSpan = fTs[index];
73 if (upSpan.fUnsortableStart) {
74 *sortable = false;
75 return NULL;
76 }
77 if (upSpan.fWindValue || upSpan.fOppValue) { 73 if (upSpan.fWindValue || upSpan.fOppValue) {
78 if (*end < 0) { 74 if (*end < 0) {
79 *start = index; 75 *start = index;
80 *end = next; 76 *end = next;
81 } 77 }
82 if (!upSpan.fDone && !upSpan.fUnsortableEnd) { 78 if (!upSpan.fDone) {
83 if (upSpan.fWindSum != SK_MinS32) { 79 if (upSpan.fWindSum != SK_MinS32) {
84 return spanToAngle(index, next); 80 return spanToAngle(index, next);
85 } 81 }
86 *done = false; 82 *done = false;
87 } 83 }
88 } else { 84 } else {
89 SkASSERT(upSpan.fDone); 85 SkASSERT(upSpan.fDone);
90 } 86 }
91 } 87 }
92 int prev = nextExactSpan(index, -1); 88 int prev = nextExactSpan(index, -1);
93 // edge leading into junction 89 // edge leading into junction
94 if (prev >= 0) { 90 if (prev >= 0) {
95 const SkOpSpan& downSpan = fTs[prev]; 91 const SkOpSpan& downSpan = fTs[prev];
96 if (downSpan.fUnsortableEnd) {
97 *sortable = false;
98 return NULL;
99 }
100 if (downSpan.fWindValue || downSpan.fOppValue) { 92 if (downSpan.fWindValue || downSpan.fOppValue) {
101 if (*end < 0) { 93 if (*end < 0) {
102 *start = index; 94 *start = index;
103 *end = prev; 95 *end = prev;
104 } 96 }
105 if (!downSpan.fDone) { 97 if (!downSpan.fDone) {
106 if (downSpan.fWindSum != SK_MinS32) { 98 if (downSpan.fWindSum != SK_MinS32) {
107 return spanToAngle(index, prev); 99 return spanToAngle(index, prev);
108 } 100 }
109 *done = false; 101 *done = false;
110 } 102 }
111 } else { 103 } else {
112 SkASSERT(downSpan.fDone); 104 SkASSERT(downSpan.fDone);
113 } 105 }
114 } 106 }
115 return NULL; 107 return NULL;
116 } 108 }
117 109
118 const SkOpAngle* SkOpSegment::activeAngleOther(int index, int* start, int* end, bool* done, 110 const SkOpAngle* SkOpSegment::activeAngleOther(int index, int* start, int* end, bool* done,
119 bool* sortable) const { 111 bool* sortable) const {
120 const SkOpSpan* span = &fTs[index]; 112 const SkOpSpan* span = &fTs[index];
121 SkOpSegment* other = span->fOther; 113 SkOpSegment* other = span->fOther;
122 int oIndex = span->fOtherIndex; 114 int oIndex = span->fOtherIndex;
123 return other->activeAngleInner(oIndex, start, end, done, sortable); 115 return other->activeAngleInner(oIndex, start, end, done, sortable);
124 } 116 }
125 117
126 SkPoint SkOpSegment::activeLeftTop(bool onlySortable, int* firstT) const { 118 SkPoint SkOpSegment::activeLeftTop(int* firstT) const {
127 SkASSERT(!done()); 119 SkASSERT(!done());
128 SkPoint topPt = {SK_ScalarMax, SK_ScalarMax}; 120 SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
129 int count = fTs.count(); 121 int count = fTs.count();
130 // see if either end is not done since we want smaller Y of the pair 122 // see if either end is not done since we want smaller Y of the pair
131 bool lastDone = true; 123 bool lastDone = true;
132 bool lastUnsortable = false;
133 double lastT = -1; 124 double lastT = -1;
134 for (int index = 0; index < count; ++index) { 125 for (int index = 0; index < count; ++index) {
135 const SkOpSpan& span = fTs[index]; 126 const SkOpSpan& span = fTs[index];
136 if (onlySortable && (span.fUnsortableStart || lastUnsortable)) {
137 goto next;
138 }
139 if (span.fDone && lastDone) { 127 if (span.fDone && lastDone) {
140 goto next; 128 goto next;
141 } 129 }
142 if (approximately_negative(span.fT - lastT)) { 130 if (approximately_negative(span.fT - lastT)) {
143 goto next; 131 goto next;
144 } 132 }
145 { 133 {
146 const SkPoint& xy = xyAtT(&span); 134 const SkPoint& xy = xyAtT(&span);
147 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { 135 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) {
148 topPt = xy; 136 topPt = xy;
149 if (firstT) { 137 if (firstT) {
150 *firstT = index; 138 *firstT = index;
151 } 139 }
152 } 140 }
153 if (fVerb != SkPath::kLine_Verb && !lastDone) { 141 if (fVerb != SkPath::kLine_Verb && !lastDone) {
154 SkPoint curveTop = (*CurveTop[SkPathOpsVerbToPoints(fVerb)])(fPt s, lastT, span.fT); 142 SkPoint curveTop = (*CurveTop[SkPathOpsVerbToPoints(fVerb)])(fPt s, lastT, span.fT);
155 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY 143 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY
156 && topPt.fX > curveTop.fX)) { 144 && topPt.fX > curveTop.fX)) {
157 topPt = curveTop; 145 topPt = curveTop;
158 if (firstT) { 146 if (firstT) {
159 *firstT = index; 147 *firstT = index;
160 } 148 }
161 } 149 }
162 } 150 }
163 lastT = span.fT; 151 lastT = span.fT;
164 } 152 }
165 next: 153 next:
166 lastDone = span.fDone; 154 lastDone = span.fDone;
167 lastUnsortable = span.fUnsortableEnd;
168 } 155 }
169 return topPt; 156 return topPt;
170 } 157 }
171 158
172 bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask , SkPathOp op) { 159 bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask , SkPathOp op) {
173 int sumMiWinding = updateWinding(endIndex, index); 160 int sumMiWinding = updateWinding(endIndex, index);
174 int sumSuWinding = updateOppWinding(endIndex, index); 161 int sumSuWinding = updateOppWinding(endIndex, index);
175 if (fOperand) { 162 if (fOperand) {
176 SkTSwap<int>(sumMiWinding, sumSuWinding); 163 SkTSwap<int>(sumMiWinding, sumSuWinding);
177 } 164 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 } 325 }
339 if ((tIndex > 0 || oIndex > 0 || fOperand != other->fOperand) && !skipAdd) { 326 if ((tIndex > 0 || oIndex > 0 || fOperand != other->fOperand) && !skipAdd) {
340 addTPair(fTs[tIndex].fT, other, other->fTs[oIndex].fT, false, startPt); 327 addTPair(fTs[tIndex].fT, other, other->fTs[oIndex].fT, false, startPt);
341 } 328 }
342 SkPoint nextPt = startPt; 329 SkPoint nextPt = startPt;
343 do { 330 do {
344 const SkPoint* workPt; 331 const SkPoint* workPt;
345 do { 332 do {
346 workPt = &fTs[++tIndex].fPt; 333 workPt = &fTs[++tIndex].fPt;
347 } while (nextPt == *workPt); 334 } while (nextPt == *workPt);
335 const SkPoint* oWorkPt;
348 do { 336 do {
349 workPt = &other->fTs[++oIndex].fPt; 337 oWorkPt = &other->fTs[++oIndex].fPt;
350 } while (nextPt == *workPt); 338 } while (nextPt == *oWorkPt);
351 nextPt = *workPt; 339 nextPt = *workPt;
352 double tStart = fTs[tIndex].fT; 340 double tStart = fTs[tIndex].fT;
353 double oStart = other->fTs[oIndex].fT; 341 double oStart = other->fTs[oIndex].fT;
354 if (tStart == 1 && oStart == 1 && fOperand == other->fOperand) { 342 if (tStart == 1 && oStart == 1 && fOperand == other->fOperand) {
355 break; 343 break;
356 } 344 }
357 addTPair(tStart, other, oStart, false, nextPt); 345 if (*workPt == *oWorkPt) {
346 addTPair(tStart, other, oStart, false, nextPt);
347 }
358 } while (endPt != nextPt); 348 } while (endPt != nextPt);
359 } 349 }
360 350
361 void SkOpSegment::addCubic(const SkPoint pts[4], bool operand, bool evenOdd) { 351 void SkOpSegment::addCubic(const SkPoint pts[4], bool operand, bool evenOdd) {
362 init(pts, SkPath::kCubic_Verb, operand, evenOdd); 352 init(pts, SkPath::kCubic_Verb, operand, evenOdd);
363 fBounds.setCubicBounds(pts); 353 fBounds.setCubicBounds(pts);
364 } 354 }
365 355
366 void SkOpSegment::addCurveTo(int start, int end, SkPathWriter* path, bool active ) const { 356 void SkOpSegment::addCurveTo(int start, int end, SkPathWriter* path, bool active ) const {
367 SkPoint edge[4]; 357 SkPoint edge[4];
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 span->fOppSum = SK_MinS32; 601 span->fOppSum = SK_MinS32;
612 span->fWindValue = 1; 602 span->fWindValue = 1;
613 span->fOppValue = 0; 603 span->fOppValue = 0;
614 span->fChased = false; 604 span->fChased = false;
615 if ((span->fDone = newT == 1)) { 605 if ((span->fDone = newT == 1)) {
616 ++fDoneSpans; 606 ++fDoneSpans;
617 } 607 }
618 span->fLoop = false; 608 span->fLoop = false;
619 span->fSmall = false; 609 span->fSmall = false;
620 span->fTiny = false; 610 span->fTiny = false;
621 span->fUnsortableStart = false;
622 span->fUnsortableEnd = false;
623 int less = -1; 611 int less = -1;
624 // find range of spans with nearly the same point as this one 612 // find range of spans with nearly the same point as this one
625 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) { 613 while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) {
626 if (fVerb == SkPath::kCubic_Verb) { 614 if (fVerb == SkPath::kCubic_Verb) {
627 double tInterval = newT - span[less].fT; 615 double tInterval = newT - span[less].fT;
628 double tMid = newT - tInterval / 2; 616 double tMid = newT - tInterval / 2;
629 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); 617 SkDPoint midPt = dcubic_xy_at_t(fPts, tMid);
630 if (!midPt.approximatelyEqual(xyAtT(span))) { 618 if (!midPt.approximatelyEqual(xyAtT(span))) {
631 break; 619 break;
632 } 620 }
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 span->fT = thisT; 815 span->fT = thisT;
828 oSpan->fOtherT = thisT; 816 oSpan->fOtherT = thisT;
829 aligned = true; 817 aligned = true;
830 } 818 }
831 if (span->fPt != thisPt) { 819 if (span->fPt != thisPt) {
832 span->fPt = thisPt; 820 span->fPt = thisPt;
833 oSpan->fPt = thisPt; 821 oSpan->fPt = thisPt;
834 aligned = true; 822 aligned = true;
835 } 823 }
836 double oT = oSpan->fT; 824 double oT = oSpan->fT;
837 if (oT == 0 || oT == 1) { 825 if (oT == 0) {
838 return aligned; 826 return aligned;
839 } 827 }
840 int oStart = other->nextSpan(oIndex, -1) + 1; 828 int oStart = other->nextSpan(oIndex, -1) + 1;
829 oSpan = &other->fTs[oStart];
830 int otherIndex = oStart;
831 if (oT == 1) {
832 if (aligned) {
833 while (oSpan->fPt == thisPt && oSpan->fT != 1) {
834 oSpan->fTiny = true;
835 ++oSpan;
836 }
837 }
838 return aligned;
839 }
840 oT = oSpan->fT;
841 int oEnd = other->nextSpan(oIndex, 1); 841 int oEnd = other->nextSpan(oIndex, 1);
842 oSpan = &other->fTs[oStart];
843 oT = oSpan->fT;
844 bool oAligned = false; 842 bool oAligned = false;
845 if (oSpan->fPt != thisPt) { 843 if (oSpan->fPt != thisPt) {
846 oAligned |= other->alignSpan(oStart, oT, thisPt); 844 oAligned |= other->alignSpan(oStart, oT, thisPt);
847 } 845 }
848 int otherIndex = oStart;
849 while (++otherIndex < oEnd) { 846 while (++otherIndex < oEnd) {
850 SkOpSpan* oNextSpan = &other->fTs[otherIndex]; 847 SkOpSpan* oNextSpan = &other->fTs[otherIndex];
851 if (oNextSpan->fT != oT || oNextSpan->fPt != thisPt) { 848 if (oNextSpan->fT != oT || oNextSpan->fPt != thisPt) {
852 oAligned |= other->alignSpan(otherIndex, oT, thisPt); 849 oAligned |= other->alignSpan(otherIndex, oT, thisPt);
853 } 850 }
854 } 851 }
855 if (oAligned) { 852 if (oAligned) {
856 other->alignSpanState(oStart, oEnd); 853 other->alignSpanState(oStart, oEnd);
857 } 854 }
858 return aligned; 855 return aligned;
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
1345 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding, 1342 last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, opp SumWinding,
1346 nextAngle); 1343 nextAngle);
1347 } else { 1344 } else {
1348 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding, 1345 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiW inding,
1349 &maxWinding, &sumWinding); 1346 &maxWinding, &sumWinding);
1350 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 1347 last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
1351 } 1348 }
1352 nextAngle->setLastMarked(last); 1349 nextAngle->setLastMarked(last);
1353 } 1350 }
1354 1351
1355 void SkOpSegment::constructLine(SkPoint shortLine[2]) { 1352 bool SkOpSegment::containsPt(const SkPoint& pt, int index, int endIndex) const {
1356 addLine(shortLine, false, false); 1353 int step = index < endIndex ? 1 : -1;
1357 addT(NULL, shortLine[0], 0); 1354 do {
1358 addT(NULL, shortLine[1], 1); 1355 const SkOpSpan& span = this->span(index);
1359 addStartSpan(1); 1356 if (span.fPt == pt) {
1360 addEndSpan(1); 1357 const SkOpSpan& endSpan = this->span(endIndex);
1361 SkOpAngle& angle = fAngles.push_back(); 1358 return span.fT == endSpan.fT && pt != endSpan.fPt;
1362 angle.set(this, 0, 1); 1359 }
1360 index += step;
1361 } while (index != endIndex);
1362 return false;
1363 } 1363 }
1364 1364
1365 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT, 1365 int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hi tT,
1366 bool* hitSomething, double mid, bool opp, bool cur rent) const { 1366 bool* hitSomething, double mid, bool opp, bool cur rent) const {
1367 SkScalar bottom = fBounds.fBottom; 1367 SkScalar bottom = fBounds.fBottom;
1368 int bestTIndex = -1; 1368 int bestTIndex = -1;
1369 if (bottom <= *bestY) { 1369 if (bottom <= *bestY) {
1370 return bestTIndex; 1370 return bestTIndex;
1371 } 1371 }
1372 SkScalar top = fBounds.fTop; 1372 SkScalar top = fBounds.fTop;
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
1916 } 1916 }
1917 int missingCount = missingSpans.count(); 1917 int missingCount = missingSpans.count();
1918 for (int index = 0; index < missingCount; ++index) { 1918 for (int index = 0; index < missingCount; ++index) {
1919 MissingSpan& missing = missingSpans[index]; 1919 MissingSpan& missing = missingSpans[index];
1920 SkOpSegment* missingOther = missing.fOther; 1920 SkOpSegment* missingOther = missing.fOther;
1921 // note that add t pair may edit span arrays, so prior pointers to spans are no longer valid 1921 // note that add t pair may edit span arrays, so prior pointers to spans are no longer valid
1922 if (!missing.fSegment->addTPair(missing.fT, missingOther, missing.fOther T, false, 1922 if (!missing.fSegment->addTPair(missing.fT, missingOther, missing.fOther T, false,
1923 missing.fPt)) { 1923 missing.fPt)) {
1924 continue; 1924 continue;
1925 } 1925 }
1926 int otherTIndex = missingOther->findT(missing.fOtherT, missing.fSegment) ; 1926 int otherTIndex = missingOther->findT(missing.fOtherT, missing.fPt, miss ing.fSegment);
1927 const SkOpSpan& otherSpan = missingOther->span(otherTIndex); 1927 const SkOpSpan& otherSpan = missingOther->span(otherTIndex);
1928 if (otherSpan.fSmall) { 1928 if (otherSpan.fSmall) {
1929 const SkOpSpan* nextSpan = &otherSpan; 1929 const SkOpSpan* nextSpan = &otherSpan;
1930 do { 1930 do {
1931 ++nextSpan; 1931 ++nextSpan;
1932 } while (nextSpan->fSmall); 1932 } while (nextSpan->fSmall);
1933 missing.fSegment->addTCoincident(missing.fPt, nextSpan->fPt, nextSpa n->fT, 1933 missing.fSegment->addTCoincident(missing.fPt, nextSpan->fPt, nextSpa n->fT,
1934 missingOther); 1934 missingOther);
1935 } else if (otherSpan.fT > 0) { 1935 } else if (otherSpan.fT > 0) {
1936 const SkOpSpan* priorSpan = &otherSpan; 1936 const SkOpSpan* priorSpan = &otherSpan;
(...skipping 11 matching lines...) Expand all
1948 MissingSpan& missing = missingSpans[index]; 1948 MissingSpan& missing = missingSpans[index];
1949 missing.fSegment->fixOtherTIndex(); 1949 missing.fSegment->fixOtherTIndex();
1950 missing.fOther->fixOtherTIndex(); 1950 missing.fOther->fixOtherTIndex();
1951 } 1951 }
1952 debugValidate(); 1952 debugValidate();
1953 } 1953 }
1954 1954
1955 void SkOpSegment::checkSmallCoincidence(const SkOpSpan& span, 1955 void SkOpSegment::checkSmallCoincidence(const SkOpSpan& span,
1956 SkTArray<MissingSpan, true>* checkMultiple) { 1956 SkTArray<MissingSpan, true>* checkMultiple) {
1957 SkASSERT(span.fSmall); 1957 SkASSERT(span.fSmall);
1958 SkASSERT(span.fWindValue); 1958 if (0 && !span.fWindValue) {
1959 return;
1960 }
1959 SkASSERT(&span < fTs.end() - 1); 1961 SkASSERT(&span < fTs.end() - 1);
1960 const SkOpSpan* next = &span + 1; 1962 const SkOpSpan* next = &span + 1;
1961 SkASSERT(!next->fSmall || checkMultiple); 1963 SkASSERT(!next->fSmall || checkMultiple);
1962 if (checkMultiple) { 1964 if (checkMultiple) {
1963 while (next->fSmall) { 1965 while (next->fSmall) {
1964 ++next; 1966 ++next;
1965 SkASSERT(next < fTs.end()); 1967 SkASSERT(next < fTs.end());
1966 } 1968 }
1967 } 1969 }
1968 SkOpSegment* other = span.fOther; 1970 SkOpSegment* other = span.fOther;
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
2264 return other; 2266 return other;
2265 } 2267 }
2266 SkASSERT(startIndex - endIndex != 0); 2268 SkASSERT(startIndex - endIndex != 0);
2267 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2269 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2268 // more than one viable candidate -- measure angles to find best 2270 // more than one viable candidate -- measure angles to find best
2269 2271
2270 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp); 2272 int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp);
2271 bool sortable = calcWinding != SK_NaN32; 2273 bool sortable = calcWinding != SK_NaN32;
2272 if (!sortable) { 2274 if (!sortable) {
2273 *unsortable = true; 2275 *unsortable = true;
2276 markDoneBinary(SkMin32(startIndex, endIndex));
2274 return NULL; 2277 return NULL;
2275 } 2278 }
2276 SkOpAngle* angle = spanToAngle(end, startIndex); 2279 SkOpAngle* angle = spanToAngle(end, startIndex);
2277 if (angle->unorderable()) { 2280 if (angle->unorderable()) {
2278 *unsortable = true; 2281 *unsortable = true;
2282 markDoneBinary(SkMin32(startIndex, endIndex));
2279 return NULL; 2283 return NULL;
2280 } 2284 }
2281 #if DEBUG_SORT 2285 #if DEBUG_SORT
2282 SkDebugf("%s\n", __FUNCTION__); 2286 SkDebugf("%s\n", __FUNCTION__);
2283 angle->debugLoop(); 2287 angle->debugLoop();
2284 #endif 2288 #endif
2285 int sumMiWinding = updateWinding(endIndex, startIndex); 2289 int sumMiWinding = updateWinding(endIndex, startIndex);
2290 if (sumMiWinding == SK_MinS32) {
2291 *unsortable = true;
2292 markDoneBinary(SkMin32(startIndex, endIndex));
2293 return NULL;
2294 }
2286 int sumSuWinding = updateOppWinding(endIndex, startIndex); 2295 int sumSuWinding = updateOppWinding(endIndex, startIndex);
2287 if (operand()) { 2296 if (operand()) {
2288 SkTSwap<int>(sumMiWinding, sumSuWinding); 2297 SkTSwap<int>(sumMiWinding, sumSuWinding);
2289 } 2298 }
2290 SkOpAngle* nextAngle = angle->next(); 2299 SkOpAngle* nextAngle = angle->next();
2291 const SkOpAngle* foundAngle = NULL; 2300 const SkOpAngle* foundAngle = NULL;
2292 bool foundDone = false; 2301 bool foundDone = false;
2293 // iterate through the angle, and compute everyone's winding 2302 // iterate through the angle, and compute everyone's winding
2294 SkOpSegment* nextSegment; 2303 SkOpSegment* nextSegment;
2295 int activeCount = 0; 2304 int activeCount = 0;
2296 do { 2305 do {
2297 nextSegment = nextAngle->segment(); 2306 nextSegment = nextAngle->segment();
2298 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle ->start(), 2307 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle ->start(),
2299 nextAngle->end(), op, &sumMiWinding, &sumSuWinding); 2308 nextAngle->end(), op, &sumMiWinding, &sumSuWinding);
2300 if (activeAngle) { 2309 if (activeAngle) {
2301 ++activeCount; 2310 ++activeCount;
2302 if (!foundAngle || (foundDone && activeCount & 1)) { 2311 if (!foundAngle || (foundDone && activeCount & 1)) {
2303 if (nextSegment->isTiny(nextAngle)) { 2312 if (nextSegment->isTiny(nextAngle)) {
2304 *unsortable = true; 2313 *unsortable = true;
2314 markDoneBinary(SkMin32(startIndex, endIndex));
2305 return NULL; 2315 return NULL;
2306 } 2316 }
2307 foundAngle = nextAngle; 2317 foundAngle = nextAngle;
2308 foundDone = nextSegment->done(nextAngle); 2318 foundDone = nextSegment->done(nextAngle);
2309 } 2319 }
2310 } 2320 }
2311 if (nextSegment->done()) { 2321 if (nextSegment->done()) {
2312 continue; 2322 continue;
2313 } 2323 }
2314 if (nextSegment->isTiny(nextAngle)) { 2324 if (nextSegment->isTiny(nextAngle)) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2386 return other; 2396 return other;
2387 } 2397 }
2388 SkASSERT(startIndex - endIndex != 0); 2398 SkASSERT(startIndex - endIndex != 0);
2389 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 2399 SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2390 // more than one viable candidate -- measure angles to find best 2400 // more than one viable candidate -- measure angles to find best
2391 2401
2392 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding); 2402 int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding);
2393 bool sortable = calcWinding != SK_NaN32; 2403 bool sortable = calcWinding != SK_NaN32;
2394 if (!sortable) { 2404 if (!sortable) {
2395 *unsortable = true; 2405 *unsortable = true;
2406 markDoneUnary(SkMin32(startIndex, endIndex));
2396 return NULL; 2407 return NULL;
2397 } 2408 }
2398 SkOpAngle* angle = spanToAngle(end, startIndex); 2409 SkOpAngle* angle = spanToAngle(end, startIndex);
2399 #if DEBUG_SORT 2410 #if DEBUG_SORT
2400 SkDebugf("%s\n", __FUNCTION__); 2411 SkDebugf("%s\n", __FUNCTION__);
2401 angle->debugLoop(); 2412 angle->debugLoop();
2402 #endif 2413 #endif
2403 int sumWinding = updateWinding(endIndex, startIndex); 2414 int sumWinding = updateWinding(endIndex, startIndex);
2404 SkOpAngle* nextAngle = angle->next(); 2415 SkOpAngle* nextAngle = angle->next();
2405 const SkOpAngle* foundAngle = NULL; 2416 const SkOpAngle* foundAngle = NULL;
2406 bool foundDone = false; 2417 bool foundDone = false;
2407 SkOpSegment* nextSegment; 2418 SkOpSegment* nextSegment;
2408 int activeCount = 0; 2419 int activeCount = 0;
2409 do { 2420 do {
2410 nextSegment = nextAngle->segment(); 2421 nextSegment = nextAngle->segment();
2411 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn gle->end(), 2422 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn gle->end(),
2412 &sumWinding); 2423 &sumWinding);
2413 if (activeAngle) { 2424 if (activeAngle) {
2414 ++activeCount; 2425 ++activeCount;
2415 if (!foundAngle || (foundDone && activeCount & 1)) { 2426 if (!foundAngle || (foundDone && activeCount & 1)) {
2416 if (nextSegment->isTiny(nextAngle)) { 2427 if (nextSegment->isTiny(nextAngle)) {
2417 *unsortable = true; 2428 *unsortable = true;
2429 markDoneUnary(SkMin32(startIndex, endIndex));
2418 return NULL; 2430 return NULL;
2419 } 2431 }
2420 foundAngle = nextAngle; 2432 foundAngle = nextAngle;
2421 foundDone = nextSegment->done(nextAngle); 2433 foundDone = nextSegment->done(nextAngle);
2422 } 2434 }
2423 } 2435 }
2424 if (nextSegment->done()) { 2436 if (nextSegment->done()) {
2425 continue; 2437 continue;
2426 } 2438 }
2427 if (nextSegment->isTiny(nextAngle)) { 2439 if (nextSegment->isTiny(nextAngle)) {
2428 continue; 2440 continue;
2429 } 2441 }
2430 if (!activeAngle) { 2442 if (!activeAngle) {
2431 nextSegment->markAndChaseDoneUnary(nextAngle->start(), nextAngle->en d()); 2443 nextSegment->markAndChaseDoneUnary(nextAngle->start(), nextAngle->en d());
2432 } 2444 }
2433 SkOpSpan* last = nextAngle->lastMarked(); 2445 SkOpSpan* last = nextAngle->lastMarked();
2434 if (last) { 2446 if (last) {
2435 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 2447 SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
2436 // assert here that span isn't already in array
2437 *chase->append() = last; 2448 *chase->append() = last;
2438 #if DEBUG_WINDING 2449 #if DEBUG_WINDING
2439 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ , 2450 SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__ ,
2440 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum, 2451 last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last ->fWindSum,
2441 last->fSmall); 2452 last->fSmall);
2442 #endif 2453 #endif
2443 } 2454 }
2444 } while ((nextAngle = nextAngle->next()) != angle); 2455 } while ((nextAngle = nextAngle->next()) != angle);
2445 markDoneUnary(SkMin32(startIndex, endIndex)); 2456 markDoneUnary(SkMin32(startIndex, endIndex));
2446 if (!foundAngle) { 2457 if (!foundAngle) {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2577 for (int index = 0; index < count; ++index) { 2588 for (int index = 0; index < count; ++index) {
2578 const SkOpSpan& span = fTs[index]; 2589 const SkOpSpan& span = fTs[index];
2579 if (span.fT == t && span.fOther == match) { 2590 if (span.fT == t && span.fOther == match) {
2580 return index; 2591 return index;
2581 } 2592 }
2582 } 2593 }
2583 SkASSERT(0); 2594 SkASSERT(0);
2584 return -1; 2595 return -1;
2585 } 2596 }
2586 2597
2587 int SkOpSegment::findT(double t, const SkOpSegment* match) const { 2598 int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) co nst {
2588 int count = this->count(); 2599 int count = this->count();
2589 for (int index = 0; index < count; ++index) { 2600 for (int index = 0; index < count; ++index) {
2590 const SkOpSpan& span = fTs[index]; 2601 const SkOpSpan& span = fTs[index];
2591 if (approximately_equal_orderable(span.fT, t) && span.fOther == match) { 2602 if (approximately_equal_orderable(span.fT, t) && span.fOther == match) {
2592 return index; 2603 return index;
2593 } 2604 }
2594 } 2605 }
2606 // 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
2608 // matching point / match pair instead.
2609 for (int index = 0; index < count; ++index) {
2610 const SkOpSpan& span = fTs[index];
2611 if (span.fPt == pt && span.fOther == match) {
2612 return index;
2613 }
2614 }
2595 SkASSERT(0); 2615 SkASSERT(0);
2596 return -1; 2616 return -1;
2597 } 2617 }
2598 2618
2599 SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort able) { 2619 SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort able,
2620 bool firstPass) {
2600 // iterate through T intersections and return topmost 2621 // iterate through T intersections and return topmost
2601 // topmost tangent from y-min to first pt is closer to horizontal 2622 // topmost tangent from y-min to first pt is closer to horizontal
2602 SkASSERT(!done()); 2623 SkASSERT(!done());
2603 int firstT = -1; 2624 int firstT = -1;
2604 /* SkPoint topPt = */ activeLeftTop(true, &firstT); 2625 /* SkPoint topPt = */ activeLeftTop(&firstT);
2605 if (firstT < 0) { 2626 if (firstT < 0) {
2606 *unsortable = true; 2627 *unsortable = !firstPass;
2607 firstT = 0; 2628 firstT = 0;
2608 while (fTs[firstT].fDone) { 2629 while (fTs[firstT].fDone) {
2609 SkASSERT(firstT < fTs.count()); 2630 SkASSERT(firstT < fTs.count());
2610 ++firstT; 2631 ++firstT;
2611 } 2632 }
2612 *tIndexPtr = firstT; 2633 *tIndexPtr = firstT;
2613 *endIndexPtr = nextExactSpan(firstT, 1); 2634 *endIndexPtr = nextExactSpan(firstT, 1);
2614 return this; 2635 return this;
2615 } 2636 }
2616 // sort the edges to find the leftmost 2637 // sort the edges to find the leftmost
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2648 } 2669 }
2649 angle = angle->next(); 2670 angle = angle->next();
2650 } while (angle != baseAngle); 2671 } while (angle != baseAngle);
2651 SkASSERT(firstAngle); 2672 SkASSERT(firstAngle);
2652 #if DEBUG_SORT 2673 #if DEBUG_SORT
2653 SkDebugf("%s\n", __FUNCTION__); 2674 SkDebugf("%s\n", __FUNCTION__);
2654 firstAngle->debugLoop(); 2675 firstAngle->debugLoop();
2655 #endif 2676 #endif
2656 // skip edges that have already been processed 2677 // skip edges that have already been processed
2657 angle = firstAngle; 2678 angle = firstAngle;
2658 SkOpSegment* leftSegment; 2679 SkOpSegment* leftSegment = NULL;
2680 bool looped = false;
2659 do { 2681 do {
2660 // SkASSERT(!angle->unsortable()); 2682 *unsortable = angle->unorderable();
2661 leftSegment = angle->segment(); 2683 if (firstPass || !*unsortable) {
2662 *tIndexPtr = angle->end(); 2684 leftSegment = angle->segment();
2663 *endIndexPtr = angle->start(); 2685 *tIndexPtr = angle->end();
2686 *endIndexPtr = angle->start();
2687 if (!leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fDone) {
2688 break;
2689 }
2690 }
2664 angle = angle->next(); 2691 angle = angle->next();
2665 } while (leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fDone); 2692 looped = true;
2693 } while (angle != firstAngle);
2694 if (angle == firstAngle && looped) {
2695 return NULL;
2696 }
2666 if (leftSegment->verb() >= SkPath::kQuad_Verb) { 2697 if (leftSegment->verb() >= SkPath::kQuad_Verb) {
2667 const int tIndex = *tIndexPtr; 2698 const int tIndex = *tIndexPtr;
2668 const int endIndex = *endIndexPtr; 2699 const int endIndex = *endIndexPtr;
2669 if (!leftSegment->clockwise(tIndex, endIndex)) { 2700 if (!leftSegment->clockwise(tIndex, endIndex)) {
2670 bool swap = !leftSegment->monotonicInY(tIndex, endIndex) 2701 bool swap = !leftSegment->monotonicInY(tIndex, endIndex)
2671 && !leftSegment->serpentine(tIndex, endIndex); 2702 && !leftSegment->serpentine(tIndex, endIndex);
2672 #if DEBUG_SWAP_TOP 2703 #if DEBUG_SWAP_TOP
2673 SkDebugf("%s swap=%d serpentine=%d containedByEnds=%d monotonic=%d\n ", __FUNCTION__, 2704 SkDebugf("%s swap=%d inflections=%d serpentine=%d controlledbyends=% d monotonic=%d\n",
2674 swap, 2705 __FUNCTION__,
2706 swap, leftSegment->debugInflections(tIndex, endIndex),
2675 leftSegment->serpentine(tIndex, endIndex), 2707 leftSegment->serpentine(tIndex, endIndex),
2676 leftSegment->controlsContainedByEnds(tIndex, endIndex), 2708 leftSegment->controlsContainedByEnds(tIndex, endIndex),
2677 leftSegment->monotonicInY(tIndex, endIndex)); 2709 leftSegment->monotonicInY(tIndex, endIndex));
2678 #endif 2710 #endif
2679 if (swap) { 2711 if (swap) {
2680 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first 2712 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first
2681 // sorted but merely the first not already processed (i.e., not done) 2713 // sorted but merely the first not already processed (i.e., not done)
2682 SkTSwap(*tIndexPtr, *endIndexPtr); 2714 SkTSwap(*tIndexPtr, *endIndexPtr);
2683 } 2715 }
2684 } 2716 }
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2833 } 2865 }
2834 return false; 2866 return false;
2835 #else 2867 #else
2836 // OPTIMIZE: code could be rejiggered to use this simpler test. To make this work, a little 2868 // OPTIMIZE: code could be rejiggered to use this simpler test. To make this work, a little
2837 // more logic is required to ignore the dangling canceled out spans 2869 // more logic is required to ignore the dangling canceled out spans
2838 const SkOpSpan& span = fTs[end]; 2870 const SkOpSpan& span = fTs[end];
2839 return span.fFromAngleIndex < 0 && span.fToAngleIndex < 0; 2871 return span.fFromAngleIndex < 0 && span.fToAngleIndex < 0;
2840 #endif 2872 #endif
2841 } 2873 }
2842 2874
2843 bool SkOpSegment::isSmall(const SkOpAngle* angle) const {
2844 int start = angle->start();
2845 int end = angle->end();
2846 const SkOpSpan& mSpan = fTs[SkMin32(start, end)];
2847 return mSpan.fSmall;
2848 }
2849
2850 bool SkOpSegment::isTiny(const SkOpAngle* angle) const { 2875 bool SkOpSegment::isTiny(const SkOpAngle* angle) const {
2851 int start = angle->start(); 2876 int start = angle->start();
2852 int end = angle->end(); 2877 int end = angle->end();
2853 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; 2878 const SkOpSpan& mSpan = fTs[SkMin32(start, end)];
2854 return mSpan.fTiny; 2879 return mSpan.fTiny;
2855 } 2880 }
2856 2881
2857 bool SkOpSegment::isTiny(int index) const { 2882 bool SkOpSegment::isTiny(int index) const {
2858 return fTs[index].fTiny; 2883 return fTs[index].fTiny;
2859 } 2884 }
2860 2885
2861 // look pair of active edges going away from coincident edge 2886 // look pair of active edges going away from coincident edge
2862 // one of them should be the continuation of other 2887 // one of them should be the continuation of other
2863 // if both are active, look to see if they both the connect to another coinciden t pair 2888 // if both are active, look to see if they both the connect to another coinciden t pair
2864 // if at least one is a line, then make the pair coincident 2889 // if at least one is a line, then make the pair coincident
2865 // if neither is a line, test for coincidence 2890 // if neither is a line, test for coincidence
2866 bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, int step, b ool cancel) { 2891 bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, const SkPoi nt& otherPt,
2867 int otherTIndex = other->findT(otherT, this); 2892 int step, bool cancel) {
2893 int otherTIndex = other->findT(otherT, otherPt, this);
2868 int next = other->nextExactSpan(otherTIndex, step); 2894 int next = other->nextExactSpan(otherTIndex, step);
2869 int otherMin = SkMin32(otherTIndex, next); 2895 int otherMin = SkMin32(otherTIndex, next);
2870 int otherWind = other->span(otherMin).fWindValue; 2896 int otherWind = other->span(otherMin).fWindValue;
2871 if (otherWind == 0) { 2897 if (otherWind == 0) {
2872 return false; 2898 return false;
2873 } 2899 }
2874 SkASSERT(next >= 0); 2900 SkASSERT(next >= 0);
2875 int tIndex = 0; 2901 int tIndex = 0;
2876 do { 2902 do {
2877 SkOpSpan* test = &fTs[tIndex]; 2903 SkOpSpan* test = &fTs[tIndex];
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
3099 3125
3100 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng) { 3126 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng) {
3101 SkOpSpan& span = fTs[tIndex]; 3127 SkOpSpan& span = fTs[tIndex];
3102 if (span.fDone && !span.fSmall) { 3128 if (span.fDone && !span.fSmall) {
3103 return NULL; 3129 return NULL;
3104 } 3130 }
3105 #if DEBUG_MARK_DONE 3131 #if DEBUG_MARK_DONE
3106 debugShowNewWinding(funName, span, winding); 3132 debugShowNewWinding(funName, span, winding);
3107 #endif 3133 #endif
3108 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 3134 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
3109 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum); 3135 #if DEBUG_LIMIT_WIND_SUM
3136 SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM);
3137 #endif
3110 span.fWindSum = winding; 3138 span.fWindSum = winding;
3111 return &span; 3139 return &span;
3112 } 3140 }
3113 3141
3114 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng, 3142 SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi ng,
3115 int oppWinding) { 3143 int oppWinding) {
3116 SkOpSpan& span = fTs[tIndex]; 3144 SkOpSpan& span = fTs[tIndex];
3117 if (span.fDone && !span.fSmall) { 3145 if (span.fDone && !span.fSmall) {
3118 return NULL; 3146 return NULL;
3119 } 3147 }
3120 #if DEBUG_MARK_DONE 3148 #if DEBUG_MARK_DONE
3121 debugShowNewWinding(funName, span, winding, oppWinding); 3149 debugShowNewWinding(funName, span, winding, oppWinding);
3122 #endif 3150 #endif
3123 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 3151 SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
3124 SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum); 3152 #if DEBUG_LIMIT_WIND_SUM
3153 SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM);
3154 #endif
3125 span.fWindSum = winding; 3155 span.fWindSum = winding;
3126 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding); 3156 SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding);
3127 SkASSERT(abs(oppWinding) <= SkPathOpsDebug::gMaxWindSum); 3157 #if DEBUG_LIMIT_WIND_SUM
3158 SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM);
3159 #endif
3128 span.fOppSum = oppWinding; 3160 span.fOppSum = oppWinding;
3129 debugValidate(); 3161 debugValidate();
3130 return &span; 3162 return &span;
3131 } 3163 }
3132 3164
3133 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order 3165 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order
3134 bool SkOpSegment::clockwise(int tStart, int tEnd) const { 3166 bool SkOpSegment::clockwise(int tStart, int tEnd) const {
3135 SkASSERT(fVerb != SkPath::kLine_Verb); 3167 SkASSERT(fVerb != SkPath::kLine_Verb);
3136 SkPoint edge[4]; 3168 SkPoint edge[4];
3137 subDivide(tStart, tEnd, edge); 3169 subDivide(tStart, tEnd, edge);
(...skipping 12 matching lines...) Expand all
3150 } 3182 }
3151 } 3183 }
3152 } 3184 }
3153 for (int idx = 0; idx < points; ++idx){ 3185 for (int idx = 0; idx < points; ++idx){
3154 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx] .fY); 3186 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx] .fY);
3155 } 3187 }
3156 return sum <= 0; 3188 return sum <= 0;
3157 } 3189 }
3158 3190
3159 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const { 3191 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const {
3160 if (fVerb == SkPath::kLine_Verb) { 3192 SkASSERT(fVerb != SkPath::kLine_Verb);
3161 return false;
3162 }
3163 if (fVerb == SkPath::kQuad_Verb) { 3193 if (fVerb == SkPath::kQuad_Verb) {
3164 SkDQuad dst = SkDQuad::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT); 3194 SkDQuad dst = SkDQuad::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
3165 return dst.monotonicInY(); 3195 return dst.monotonicInY();
3166 } 3196 }
3167 SkASSERT(fVerb == SkPath::kCubic_Verb); 3197 SkASSERT(fVerb == SkPath::kCubic_Verb);
3168 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT); 3198 SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
3169 return dst.monotonicInY(); 3199 return dst.monotonicInY();
3170 } 3200 }
3171 3201
3172 bool SkOpSegment::serpentine(int tStart, int tEnd) const { 3202 bool SkOpSegment::serpentine(int tStart, int tEnd) const {
(...skipping 30 matching lines...) Expand all
3203 debugShowNewWinding(funName, span, span.fWindSum); 3233 debugShowNewWinding(funName, span, span.fWindSum);
3204 #endif 3234 #endif
3205 // If the prior angle in the sort is unorderable, the winding sum may not be com putable. 3235 // If the prior angle in the sort is unorderable, the winding sum may not be com putable.
3206 // To enable the assert, the 'prior is unorderable' state could be 3236 // To enable the assert, the 'prior is unorderable' state could be
3207 // piped down to this test, but not sure it's worth it. 3237 // piped down to this test, but not sure it's worth it.
3208 // (Once the sort order is stored in the span, this test may be feasible.) 3238 // (Once the sort order is stored in the span, this test may be feasible.)
3209 // SkASSERT(span.fWindSum != SK_MinS32); 3239 // SkASSERT(span.fWindSum != SK_MinS32);
3210 return &span; 3240 return &span;
3211 } 3241 }
3212 3242
3213 // note that just because a span has one end that is unsortable, that's
3214 // not enough to mark it done. The other end may be sortable, allowing the
3215 // span to be added.
3216 // FIXME: if abs(start - end) > 1, mark intermediates as unsortable on both ends
3217 void SkOpSegment::markUnsortable(int start, int end) {
3218 SkOpSpan* span = &fTs[start];
3219 if (start < end) {
3220 #if DEBUG_UNSORTABLE
3221 debugShowNewWinding(__FUNCTION__, *span, 0);
3222 #endif
3223 span->fUnsortableStart = true;
3224 } else {
3225 --span;
3226 #if DEBUG_UNSORTABLE
3227 debugShowNewWinding(__FUNCTION__, *span, 0);
3228 #endif
3229 span->fUnsortableEnd = true;
3230 }
3231 if (!span->fUnsortableStart || !span->fUnsortableEnd || span->fDone) {
3232 debugValidate();
3233 return;
3234 }
3235 span->fDone = true;
3236 fDoneSpans++;
3237 debugValidate();
3238 }
3239
3240 void SkOpSegment::markWinding(int index, int winding) { 3243 void SkOpSegment::markWinding(int index, int winding) {
3241 // SkASSERT(!done()); 3244 // SkASSERT(!done());
3242 SkASSERT(winding); 3245 SkASSERT(winding);
3243 double referenceT = fTs[index].fT; 3246 double referenceT = fTs[index].fT;
3244 int lesser = index; 3247 int lesser = index;
3245 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 3248 while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3246 markOneWinding(__FUNCTION__, lesser, winding); 3249 markOneWinding(__FUNCTION__, lesser, winding);
3247 } 3250 }
3248 do { 3251 do {
3249 markOneWinding(__FUNCTION__, index, winding); 3252 markOneWinding(__FUNCTION__, index, winding);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
3419 *maxWinding = *sumSuWinding; 3422 *maxWinding = *sumSuWinding;
3420 *sumWinding = *sumSuWinding -= deltaSum; 3423 *sumWinding = *sumSuWinding -= deltaSum;
3421 *oppMaxWinding = *sumMiWinding; 3424 *oppMaxWinding = *sumMiWinding;
3422 *oppSumWinding = *sumMiWinding -= oppDeltaSum; 3425 *oppSumWinding = *sumMiWinding -= oppDeltaSum;
3423 } else { 3426 } else {
3424 *maxWinding = *sumMiWinding; 3427 *maxWinding = *sumMiWinding;
3425 *sumWinding = *sumMiWinding -= deltaSum; 3428 *sumWinding = *sumMiWinding -= deltaSum;
3426 *oppMaxWinding = *sumSuWinding; 3429 *oppMaxWinding = *sumSuWinding;
3427 *oppSumWinding = *sumSuWinding -= oppDeltaSum; 3430 *oppSumWinding = *sumSuWinding -= oppDeltaSum;
3428 } 3431 }
3429 SkASSERT(abs(*sumWinding) <= SkPathOpsDebug::gMaxWindSum); 3432 #if DEBUG_LIMIT_WIND_SUM
3430 SkASSERT(abs(*oppSumWinding) <= SkPathOpsDebug::gMaxWindSum); 3433 SkASSERT(abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
3434 SkASSERT(abs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM);
3435 #endif
3431 } 3436 }
3432 3437
3433 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, 3438 void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding,
3434 int* maxWinding, int* sumWinding) { 3439 int* maxWinding, int* sumWinding) {
3435 int deltaSum = spanSign(index, endIndex); 3440 int deltaSum = spanSign(index, endIndex);
3436 *maxWinding = *sumMiWinding; 3441 *maxWinding = *sumMiWinding;
3437 *sumWinding = *sumMiWinding -= deltaSum; 3442 *sumWinding = *sumMiWinding -= deltaSum;
3438 SkASSERT(abs(*sumWinding) <= SkPathOpsDebug::gMaxWindSum); 3443 #if DEBUG_LIMIT_WIND_SUM
3444 SkASSERT(abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
3445 #endif
3439 } 3446 }
3440 3447
3441 void SkOpSegment::sortAngles() { 3448 void SkOpSegment::sortAngles() {
3442 int spanCount = fTs.count(); 3449 int spanCount = fTs.count();
3443 if (spanCount <= 2) { 3450 if (spanCount <= 2) {
3444 return; 3451 return;
3445 } 3452 }
3446 int index = 0; 3453 int index = 0;
3447 do { 3454 do {
3448 int fromIndex = fTs[index].fFromAngleIndex; 3455 int fromIndex = fTs[index].fFromAngleIndex;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3487 SkOpSpan& oSpan = other->fTs[span.fOtherIndex]; 3494 SkOpSpan& oSpan = other->fTs[span.fOtherIndex];
3488 int otherAngleIndex = oSpan.fFromAngleIndex; 3495 int otherAngleIndex = oSpan.fFromAngleIndex;
3489 if (otherAngleIndex >= 0) { 3496 if (otherAngleIndex >= 0) {
3490 #if DEBUG_ANGLE 3497 #if DEBUG_ANGLE
3491 if (!wroteAfterHeader) { 3498 if (!wroteAfterHeader) {
3492 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT, 3499 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT,
3493 index); 3500 index);
3494 wroteAfterHeader = true; 3501 wroteAfterHeader = true;
3495 } 3502 }
3496 #endif 3503 #endif
3497 baseAngle->insert(&other->angle(otherAngleIndex)); 3504 SkOpAngle* oAngle = &other->angle(otherAngleIndex);
3505 if (!oAngle->loopContains(*baseAngle)) {
3506 baseAngle->insert(oAngle);
3507 }
3498 } 3508 }
3499 otherAngleIndex = oSpan.fToAngleIndex; 3509 otherAngleIndex = oSpan.fToAngleIndex;
3500 if (otherAngleIndex >= 0) { 3510 if (otherAngleIndex >= 0) {
3501 #if DEBUG_ANGLE 3511 #if DEBUG_ANGLE
3502 if (!wroteAfterHeader) { 3512 if (!wroteAfterHeader) {
3503 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT, 3513 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugI D(), fTs[index].fT,
3504 index); 3514 index);
3505 wroteAfterHeader = true; 3515 wroteAfterHeader = true;
3506 } 3516 }
3507 #endif 3517 #endif
3508 baseAngle->insert(&other->angle(otherAngleIndex)); 3518 SkOpAngle* oAngle = &other->angle(otherAngleIndex);
3519 if (!oAngle->loopContains(*baseAngle)) {
3520 baseAngle->insert(oAngle);
3521 }
3509 } 3522 }
3510 if (++index == spanCount) { 3523 if (++index == spanCount) {
3511 break; 3524 break;
3512 } 3525 }
3513 nextFrom = fTs[index].fFromAngleIndex; 3526 nextFrom = fTs[index].fFromAngleIndex;
3514 nextTo = fTs[index].fToAngleIndex; 3527 nextTo = fTs[index].fToAngleIndex;
3515 } while (fromIndex == nextFrom && toIndex == nextTo); 3528 } while (fromIndex == nextFrom && toIndex == nextTo);
3516 if (baseAngle && baseAngle->loopCount() == 1) { 3529 if (baseAngle && baseAngle->loopCount() == 1) {
3517 index = firstIndex; 3530 index = firstIndex;
3518 do { 3531 do {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
3666 3679
3667 int SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { 3680 int SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const {
3668 int startIndex = angle->start(); 3681 int startIndex = angle->start();
3669 int endIndex = angle->end(); 3682 int endIndex = angle->end();
3670 return updateOppWinding(startIndex, endIndex); 3683 return updateOppWinding(startIndex, endIndex);
3671 } 3684 }
3672 3685
3673 int SkOpSegment::updateWinding(int index, int endIndex) const { 3686 int SkOpSegment::updateWinding(int index, int endIndex) const {
3674 int lesser = SkMin32(index, endIndex); 3687 int lesser = SkMin32(index, endIndex);
3675 int winding = windSum(lesser); 3688 int winding = windSum(lesser);
3689 if (winding == SK_MinS32) {
3690 return winding;
3691 }
3676 int spanWinding = spanSign(index, endIndex); 3692 int spanWinding = spanSign(index, endIndex);
3677 if (winding && UseInnerWinding(winding - spanWinding, winding) 3693 if (winding && UseInnerWinding(winding - spanWinding, winding)
3678 && winding != SK_MaxS32) { 3694 && winding != SK_MaxS32) {
3679 winding -= spanWinding; 3695 winding -= spanWinding;
3680 } 3696 }
3681 return winding; 3697 return winding;
3682 } 3698 }
3683 3699
3684 int SkOpSegment::updateWinding(const SkOpAngle* angle) const { 3700 int SkOpSegment::updateWinding(const SkOpAngle* angle) const {
3685 int startIndex = angle->start(); 3701 int startIndex = angle->start();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
3769 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 3785 SkASSERT(span->fWindValue > 0 || span->fOppValue != 0);
3770 span->fWindValue = 0; 3786 span->fWindValue = 0;
3771 span->fOppValue = 0; 3787 span->fOppValue = 0;
3772 if (span->fTiny || span->fSmall) { 3788 if (span->fTiny || span->fSmall) {
3773 return; 3789 return;
3774 } 3790 }
3775 SkASSERT(!span->fDone); 3791 SkASSERT(!span->fDone);
3776 span->fDone = true; 3792 span->fDone = true;
3777 ++fDoneSpans; 3793 ++fDoneSpans;
3778 } 3794 }
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