| 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 |