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 "SkOpCoincidence.h" | 7 #include "SkOpCoincidence.h" |
8 #include "SkOpContour.h" | 8 #include "SkOpContour.h" |
9 #include "SkOpSegment.h" | 9 #include "SkOpSegment.h" |
10 #include "SkPathWriter.h" | 10 #include "SkPathWriter.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}
, // mi - su | 36 {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}
, // mi - su |
37 {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}
, // mi & su | 37 {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}
, // mi & su |
38 {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}
, // mi | su | 38 {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}
, // mi | su |
39 {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}
, // mi ^ su | 39 {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}
, // mi ^ su |
40 }; | 40 }; |
41 | 41 |
42 #undef F | 42 #undef F |
43 #undef T | 43 #undef T |
44 | 44 |
45 SkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr
, | 45 SkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr
, |
46 SkOpSpanBase** endPtr, bool* done, bool* sortable) { | 46 SkOpSpanBase** endPtr, bool* done) { |
47 if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done, sort
able)) { | 47 if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done)) { |
48 return result; | 48 return result; |
49 } | 49 } |
50 if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done, sort
able)) { | 50 if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done)) { |
51 return result; | 51 return result; |
52 } | 52 } |
53 return NULL; | 53 return NULL; |
54 } | 54 } |
55 | 55 |
56 SkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** sta
rtPtr, | 56 SkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** sta
rtPtr, |
57 SkOpSpanBase** endPtr, bool* done, bool* sortable) { | 57 SkOpSpanBase** endPtr, bool* done) { |
58 SkOpSpan* upSpan = start->upCastable(); | 58 SkOpSpan* upSpan = start->upCastable(); |
59 if (upSpan) { | 59 if (upSpan) { |
60 if (upSpan->windValue() || upSpan->oppValue()) { | 60 if (upSpan->windValue() || upSpan->oppValue()) { |
61 SkOpSpanBase* next = upSpan->next(); | 61 SkOpSpanBase* next = upSpan->next(); |
62 if (!*endPtr) { | 62 if (!*endPtr) { |
63 *startPtr = start; | 63 *startPtr = start; |
64 *endPtr = next; | 64 *endPtr = next; |
65 } | 65 } |
66 if (!upSpan->done()) { | 66 if (!upSpan->done()) { |
67 if (upSpan->windSum() != SK_MinS32) { | 67 if (upSpan->windSum() != SK_MinS32) { |
(...skipping 20 matching lines...) Expand all Loading... |
88 *done = false; | 88 *done = false; |
89 } | 89 } |
90 } else { | 90 } else { |
91 SkASSERT(downSpan->done()); | 91 SkASSERT(downSpan->done()); |
92 } | 92 } |
93 } | 93 } |
94 return NULL; | 94 return NULL; |
95 } | 95 } |
96 | 96 |
97 SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** sta
rtPtr, | 97 SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** sta
rtPtr, |
98 SkOpSpanBase** endPtr, bool* done, bool* sortable) { | 98 SkOpSpanBase** endPtr, bool* done) { |
99 SkOpPtT* oPtT = start->ptT()->next(); | 99 SkOpPtT* oPtT = start->ptT()->next(); |
100 SkOpSegment* other = oPtT->segment(); | 100 SkOpSegment* other = oPtT->segment(); |
101 SkOpSpanBase* oSpan = oPtT->span(); | 101 SkOpSpanBase* oSpan = oPtT->span(); |
102 return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable); | 102 return other->activeAngleInner(oSpan, startPtr, endPtr, done); |
103 } | 103 } |
104 | 104 |
105 bool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask
, int xorSuMask, | 105 bool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask
, int xorSuMask, |
106 SkPathOp op) { | 106 SkPathOp op) { |
107 int sumMiWinding = this->updateWinding(end, start); | 107 int sumMiWinding = this->updateWinding(end, start); |
108 int sumSuWinding = this->updateOppWinding(end, start); | 108 int sumSuWinding = this->updateOppWinding(end, start); |
109 #if DEBUG_LIMIT_WIND_SUM | 109 #if DEBUG_LIMIT_WIND_SUM |
110 SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM); | 110 SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM); |
111 SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM); | 111 SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM); |
112 #endif | 112 #endif |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 } | 304 } |
305 while ((span = span->upCast()->next())) { | 305 while ((span = span->upCast()->next())) { |
306 if (span == &fTail) { | 306 if (span == &fTail) { |
307 break; | 307 break; |
308 } | 308 } |
309 span->align(); | 309 span->align(); |
310 } | 310 } |
311 if (!span->aligned()) { | 311 if (!span->aligned()) { |
312 span->alignEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]); | 312 span->alignEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]); |
313 } | 313 } |
| 314 if (this->collapsed()) { |
| 315 SkOpSpan* span = &fHead; |
| 316 do { |
| 317 span->setWindValue(0); |
| 318 span->setOppValue(0); |
| 319 this->markDone(span); |
| 320 } while ((span = span->next()->upCastable())); |
| 321 } |
314 debugValidate(); | 322 debugValidate(); |
315 } | 323 } |
316 | 324 |
317 void SkOpSegment::calcAngles(SkChunkAlloc* allocator) { | 325 void SkOpSegment::calcAngles(SkChunkAlloc* allocator) { |
318 bool activePrior = !fHead.isCanceled(); | 326 bool activePrior = !fHead.isCanceled(); |
319 if (activePrior && !fHead.simple()) { | 327 if (activePrior && !fHead.simple()) { |
320 addStartSpan(allocator); | 328 addStartSpan(allocator); |
321 } | 329 } |
322 SkOpSpan* prior = &fHead; | 330 SkOpSpan* prior = &fHead; |
323 SkOpSpanBase* spanBase = fHead.next(); | 331 SkOpSpanBase* spanBase = fHead.next(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 break; | 364 break; |
357 } | 365 } |
358 span = base->upCast(); | 366 span = base->upCast(); |
359 angle = span->toAngle(); | 367 angle = span->toAngle(); |
360 if (angle && angle->fCheckCoincidence) { | 368 if (angle && angle->fCheckCoincidence) { |
361 angle->checkNearCoincidence(); | 369 angle->checkNearCoincidence(); |
362 } | 370 } |
363 } while ((base = span->next())); | 371 } while ((base = span->next())); |
364 } | 372 } |
365 | 373 |
| 374 bool SkOpSegment::collapsed() const { |
| 375 return fVerb == SkPath::kLine_Verb && fHead.pt() == fTail.pt(); |
| 376 } |
| 377 |
366 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle
, | 378 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle
, |
367 SkOpAngle::IncludeType includeType) { | 379 SkOpAngle::IncludeType includeType) { |
368 SkOpSegment* baseSegment = baseAngle->segment(); | 380 SkOpSegment* baseSegment = baseAngle->segment(); |
369 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); | 381 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); |
370 int sumSuWinding; | 382 int sumSuWinding; |
371 bool binary = includeType >= SkOpAngle::kBinarySingle; | 383 bool binary = includeType >= SkOpAngle::kBinarySingle; |
372 if (binary) { | 384 if (binary) { |
373 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); | 385 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); |
374 if (baseSegment->operand()) { | 386 if (baseSegment->operand()) { |
375 SkTSwap<int>(sumMiWinding, sumSuWinding); | 387 SkTSwap<int>(sumMiWinding, sumSuWinding); |
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 return set_last(last, endSpan); | 1083 return set_last(last, endSpan); |
1072 } | 1084 } |
1073 *startPtr = foundSpan; | 1085 *startPtr = foundSpan; |
1074 *stepPtr = foundStep; | 1086 *stepPtr = foundStep; |
1075 if (minPtr) { | 1087 if (minPtr) { |
1076 *minPtr = foundMin; | 1088 *minPtr = foundMin; |
1077 } | 1089 } |
1078 return other; | 1090 return other; |
1079 } | 1091 } |
1080 | 1092 |
1081 static void clear_visited(SkOpSpan* span) { | 1093 static void clear_visited(SkOpSpanBase* span) { |
1082 // reset visited flag back to false | 1094 // reset visited flag back to false |
1083 do { | 1095 do { |
1084 SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; | 1096 SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; |
1085 while ((ptT = ptT->next()) != stopPtT) { | 1097 while ((ptT = ptT->next()) != stopPtT) { |
1086 SkOpSegment* opp = ptT->segment(); | 1098 SkOpSegment* opp = ptT->segment(); |
1087 opp->resetVisited(); | 1099 opp->resetVisited(); |
1088 } | 1100 } |
1089 } while ((span = span->next()->upCastable())); | 1101 } while (!span->final() && (span = span->upCast()->next())); |
1090 } | 1102 } |
1091 | 1103 |
1092 // look for pairs of undetected coincident curves | 1104 // look for pairs of undetected coincident curves |
1093 // assumes that segments going in have visited flag clear | 1105 // assumes that segments going in have visited flag clear |
1094 // curve/curve intersection should now do a pretty good job of finding coinciden
t runs so | 1106 // curve/curve intersection should now do a pretty good job of finding coinciden
t runs so |
1095 // this may be only be necessary for line/curve pairs -- so skip unless this is
a line and the | 1107 // this may be only be necessary for line/curve pairs -- so skip unless this is
a line and the |
1096 // the opp is not a line | 1108 // the opp is not a line |
1097 void SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc
* allocator) { | 1109 void SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc
* allocator) { |
1098 if (this->verb() != SkPath::kLine_Verb) { | 1110 if (this->verb() != SkPath::kLine_Verb) { |
1099 return; | 1111 return; |
1100 } | 1112 } |
| 1113 if (this->done()) { |
| 1114 return; |
| 1115 } |
1101 SkOpSpan* prior = NULL; | 1116 SkOpSpan* prior = NULL; |
1102 SkOpSpan* span = &fHead; | 1117 SkOpSpanBase* spanBase = &fHead; |
1103 do { | 1118 do { |
1104 SkOpPtT* ptT = span->ptT(), * spanStopPtT = ptT; | 1119 SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; |
1105 SkASSERT(ptT->span() == span); | 1120 SkASSERT(ptT->span() == spanBase); |
1106 while ((ptT = ptT->next()) != spanStopPtT) { | 1121 while ((ptT = ptT->next()) != spanStopPtT) { |
1107 SkOpSegment* opp = ptT->span()->segment(); | 1122 SkOpSegment* opp = ptT->span()->segment(); |
1108 if (!opp->setVisited()) { | |
1109 continue; | |
1110 } | |
1111 if (opp->verb() == SkPath::kLine_Verb) { | 1123 if (opp->verb() == SkPath::kLine_Verb) { |
1112 continue; | 1124 continue; |
1113 } | 1125 } |
1114 if (span->containsCoincidence(opp)) { // FIXME: this assumes that if
the opposite | 1126 if (opp->done()) { |
1115 // segment is coincident then
no more coincidence | |
1116 // needs to be detected. This
may not be true. | |
1117 continue; | 1127 continue; |
1118 } | 1128 } |
1119 if (span->containsCoinEnd(opp)) { | 1129 // when opp is encounted the 1st time, continue; on 2nd encounter, l
ook for coincidence |
| 1130 if (!opp->visited()) { |
| 1131 continue; |
| 1132 } |
| 1133 if (spanBase == &fHead) { |
| 1134 continue; |
| 1135 } |
| 1136 SkOpSpan* span = spanBase->upCastable(); |
| 1137 // FIXME?: this assumes that if the opposite segment is coincident t
hen no more |
| 1138 // coincidence needs to be detected. This may not be true. |
| 1139 if (span && span->containsCoincidence(opp)) { |
| 1140 continue; |
| 1141 } |
| 1142 if (spanBase->containsCoinEnd(opp)) { |
1120 continue; | 1143 continue; |
1121 } | 1144 } |
1122 // if already visited and visited again, check for coin | |
1123 if (span == &fHead) { | |
1124 continue; | |
1125 } | |
1126 SkOpPtT* priorPtT = NULL, * priorStopPtT; | 1145 SkOpPtT* priorPtT = NULL, * priorStopPtT; |
1127 // find prior span containing opp segment | 1146 // find prior span containing opp segment |
1128 SkOpSegment* priorOpp = NULL; | 1147 SkOpSegment* priorOpp = NULL; |
1129 prior = span; | 1148 SkOpSpan* priorTest = spanBase->prev(); |
1130 while (!priorOpp && (prior = prior->prev())) { | 1149 while (!priorOpp && priorTest) { |
1131 priorStopPtT = priorPtT = prior->ptT(); | 1150 priorStopPtT = priorPtT = priorTest->ptT(); |
1132 while ((priorPtT = priorPtT->next()) != priorStopPtT) { | 1151 while ((priorPtT = priorPtT->next()) != priorStopPtT) { |
1133 SkOpSegment* segment = priorPtT->span()->segment(); | 1152 SkOpSegment* segment = priorPtT->span()->segment(); |
1134 if (segment == opp) { | 1153 if (segment == opp) { |
| 1154 prior = priorTest; |
1135 priorOpp = opp; | 1155 priorOpp = opp; |
1136 break; | 1156 break; |
1137 } | 1157 } |
1138 } | 1158 } |
| 1159 priorTest = priorTest->prev(); |
1139 } | 1160 } |
1140 if (!priorOpp) { | 1161 if (!priorOpp) { |
1141 continue; | 1162 continue; |
1142 } | 1163 } |
1143 SkOpPtT* oppStart = prior->ptT(); | 1164 SkOpPtT* oppStart = prior->ptT(); |
1144 SkOpPtT* oppEnd = span->ptT(); | 1165 SkOpPtT* oppEnd = spanBase->ptT(); |
1145 bool swapped = priorPtT->fT > ptT->fT; | 1166 bool swapped = priorPtT->fT > ptT->fT; |
1146 if (swapped) { | 1167 if (swapped) { |
1147 SkTSwap(priorPtT, ptT); | 1168 SkTSwap(priorPtT, ptT); |
1148 SkTSwap(oppStart, oppEnd); | 1169 SkTSwap(oppStart, oppEnd); |
1149 } | 1170 } |
1150 bool flipped = oppStart->fT > oppEnd->fT; | 1171 bool flipped = oppStart->fT > oppEnd->fT; |
1151 bool coincident; | 1172 bool coincident; |
1152 if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)
) { | 1173 if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)
) { |
1153 goto swapBack; | 1174 goto swapBack; |
1154 } | 1175 } |
1155 { | 1176 { |
1156 // average t, find mid pt | 1177 // average t, find mid pt |
1157 double midT = (prior->t() + span->t()) / 2; | 1178 double midT = (prior->t() + spanBase->t()) / 2; |
1158 SkPoint midPt = this->ptAtT(midT); | 1179 SkPoint midPt = this->ptAtT(midT); |
1159 coincident = true; | 1180 coincident = true; |
1160 // if the mid pt is not near either end pt, project perpendicula
r through opp seg | 1181 // if the mid pt is not near either end pt, project perpendicula
r through opp seg |
1161 if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt) | 1182 if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt) |
1162 && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) { | 1183 && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) { |
1163 coincident = false; | 1184 coincident = false; |
1164 SkIntersections i; | 1185 SkIntersections i; |
1165 SkVector dxdy = (*CurveSlopeAtT[fVerb])(this->pts(), this->w
eight(), midT); | 1186 SkVector dxdy = (*CurveSlopeAtT[fVerb])(this->pts(), this->w
eight(), midT); |
1166 SkDLine ray = {{{midPt.fX, midPt.fY}, | 1187 SkDLine ray = {{{midPt.fX, midPt.fY}, |
1167 {midPt.fX + dxdy.fY, midPt.fY - dxdy.fX}}}; | 1188 {midPt.fX + dxdy.fY, midPt.fY - dxdy.fX}}}; |
1168 (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(),
ray, &i); | 1189 (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(),
ray, &i); |
1169 // measure distance and see if it's small enough to denote c
oincidence | 1190 // measure distance and see if it's small enough to denote c
oincidence |
1170 for (int index = 0; index < i.used(); ++index) { | 1191 for (int index = 0; index < i.used(); ++index) { |
1171 SkDPoint oppPt = i.pt(index); | 1192 SkDPoint oppPt = i.pt(index); |
1172 if (oppPt.approximatelyEqual(midPt)) { | 1193 if (oppPt.approximatelyEqual(midPt)) { |
1173 SkVector oppDxdy = (*CurveSlopeAtT[opp->verb()])(opp
->pts(), | 1194 SkVector oppDxdy = (*CurveSlopeAtT[opp->verb()])(opp
->pts(), |
1174 opp->weight(), i[index][0]); | 1195 opp->weight(), i[index][0]); |
1175 oppDxdy.normalize(); | 1196 oppDxdy.normalize(); |
1176 dxdy.normalize(); | 1197 dxdy.normalize(); |
1177 SkScalar flatness = SkScalarAbs(dxdy.cross(oppDxdy)
/ FLT_EPSILON); | 1198 SkScalar flatness = SkScalarAbs(dxdy.cross(oppDxdy)
/ FLT_EPSILON); |
1178 coincident |= flatness < 5000; // FIXME: replace wi
th tuned value | 1199 coincident |= flatness < 5000; // FIXME: replace wi
th tuned value |
1179 } | 1200 } |
1180 } | 1201 } |
1181 } | 1202 } |
1182 } | 1203 } |
1183 if (coincident) { | 1204 if (coincident) { |
1184 // mark coincidence | 1205 // mark coincidence |
1185 coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator); | 1206 if (!coincidences->extend(priorPtT, ptT, oppStart, oppEnd)) { |
| 1207 coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator
); |
| 1208 } |
1186 clear_visited(&fHead); | 1209 clear_visited(&fHead); |
1187 missingCoincidence(coincidences, allocator); | |
1188 return; | 1210 return; |
1189 } | 1211 } |
1190 swapBack: | 1212 swapBack: |
1191 if (swapped) { | 1213 if (swapped) { |
1192 SkTSwap(priorPtT, ptT); | 1214 SkTSwap(priorPtT, ptT); |
1193 } | 1215 } |
1194 } | 1216 } |
1195 } while ((span = span->next()->upCastable())); | 1217 } while ((spanBase = spanBase->final() ? NULL : spanBase->upCast()->next()))
; |
1196 clear_visited(&fHead); | 1218 clear_visited(&fHead); |
1197 } | 1219 } |
1198 | 1220 |
1199 // if a span has more than one intersection, merge the other segments' span as n
eeded | 1221 // if a span has more than one intersection, merge the other segments' span as n
eeded |
1200 void SkOpSegment::moveMultiples() { | 1222 void SkOpSegment::moveMultiples() { |
1201 debugValidate(); | 1223 debugValidate(); |
1202 SkOpSpanBase* test = &fHead; | 1224 SkOpSpanBase* test = &fHead; |
1203 do { | 1225 do { |
1204 int addCount = test->spanAddsCount(); | 1226 int addCount = test->spanAddsCount(); |
1205 SkASSERT(addCount >= 1); | 1227 SkASSERT(addCount >= 1); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1603 int SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { | 1625 int SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { |
1604 const SkOpSpanBase* startSpan = angle->start(); | 1626 const SkOpSpanBase* startSpan = angle->start(); |
1605 const SkOpSpanBase* endSpan = angle->end(); | 1627 const SkOpSpanBase* endSpan = angle->end(); |
1606 return updateOppWinding(startSpan, endSpan); | 1628 return updateOppWinding(startSpan, endSpan); |
1607 } | 1629 } |
1608 | 1630 |
1609 int SkOpSegment::updateWinding(SkOpSpanBase* start, SkOpSpanBase* end) { | 1631 int SkOpSegment::updateWinding(SkOpSpanBase* start, SkOpSpanBase* end) { |
1610 SkOpSpan* lesser = start->starter(end); | 1632 SkOpSpan* lesser = start->starter(end); |
1611 int winding = lesser->windSum(); | 1633 int winding = lesser->windSum(); |
1612 if (winding == SK_MinS32) { | 1634 if (winding == SK_MinS32) { |
1613 SkOpGlobalState* globals = this->globalState(); | 1635 winding = lesser->computeWindSum(); |
1614 SkOpContour* contourHead = globals->contourHead(); | |
1615 int windTry = 0; | |
1616 while (!lesser->sortableTop(contourHead) && ++windTry < SkOpGlobalState:
:kMaxWindingTries) { | |
1617 ; | |
1618 } | |
1619 winding = lesser->windSum(); | |
1620 } | 1636 } |
1621 if (winding == SK_MinS32) { | 1637 if (winding == SK_MinS32) { |
1622 return winding; | 1638 return winding; |
1623 } | 1639 } |
1624 int spanWinding = SkOpSegment::SpanSign(start, end); | 1640 int spanWinding = SkOpSegment::SpanSign(start, end); |
1625 if (winding && UseInnerWinding(winding - spanWinding, winding) | 1641 if (winding && UseInnerWinding(winding - spanWinding, winding) |
1626 && winding != SK_MaxS32) { | 1642 && winding != SK_MaxS32) { |
1627 winding -= spanWinding; | 1643 winding -= spanWinding; |
1628 } | 1644 } |
1629 return winding; | 1645 return winding; |
(...skipping 20 matching lines...) Expand all Loading... |
1650 int absOut = abs(outerWinding); | 1666 int absOut = abs(outerWinding); |
1651 int absIn = abs(innerWinding); | 1667 int absIn = abs(innerWinding); |
1652 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; | 1668 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; |
1653 return result; | 1669 return result; |
1654 } | 1670 } |
1655 | 1671 |
1656 int SkOpSegment::windSum(const SkOpAngle* angle) const { | 1672 int SkOpSegment::windSum(const SkOpAngle* angle) const { |
1657 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); | 1673 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); |
1658 return minSpan->windSum(); | 1674 return minSpan->windSum(); |
1659 } | 1675 } |
OLD | NEW |