OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |