| 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 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 bool result = gUnaryActiveEdge[from][to]; | 203 bool result = gUnaryActiveEdge[from][to]; |
| 204 return result; | 204 return result; |
| 205 } | 205 } |
| 206 | 206 |
| 207 void SkOpSegment::addAngle(SkTDArray<SkOpAngle>* anglesPtr, int start, int end)
const { | 207 void SkOpSegment::addAngle(SkTDArray<SkOpAngle>* anglesPtr, int start, int end)
const { |
| 208 SkASSERT(start != end); | 208 SkASSERT(start != end); |
| 209 SkOpAngle* angle = anglesPtr->append(); | 209 SkOpAngle* angle = anglesPtr->append(); |
| 210 #if DEBUG_ANGLE | 210 #if DEBUG_ANGLE |
| 211 SkTDArray<SkOpAngle>& angles = *anglesPtr; | 211 SkTDArray<SkOpAngle>& angles = *anglesPtr; |
| 212 if (angles.count() > 1 && !fTs[start].fTiny) { | 212 if (angles.count() > 1 && !fTs[start].fTiny) { |
| 213 SkPoint angle0Pt = (*CurvePointAtT[angles[0].verb()])(angles[0].pts(), | 213 const SkOpSegment* aSeg = angles[0].segment(); |
| 214 (*angles[0].spans())[angles[0].start()].fT); | 214 const SkPoint& angle0Pt = aSeg->xyAtT(angles[0].start()); |
| 215 SkPoint newPt = (*CurvePointAtT[fVerb])(fPts, fTs[start].fT); | 215 SkPoint newPt = (*CurvePointAtT[fVerb])(fPts, fTs[start].fT); |
| 216 bool match = AlmostEqualUlps(angle0Pt.fX, newPt.fX); | 216 bool match = AlmostEqualUlps(angle0Pt.fX, newPt.fX); |
| 217 match &= AlmostEqualUlps(angle0Pt.fY, newPt.fY); | 217 match &= AlmostEqualUlps(angle0Pt.fY, newPt.fY); |
| 218 if (!match) { | 218 if (!match) { |
| 219 SkDebugf("%s no match\n", __FUNCTION__); | 219 SkDebugf("%s no match\n", __FUNCTION__); |
| 220 SkASSERT(0); | 220 SkASSERT(0); |
| 221 } | 221 } |
| 222 } | 222 } |
| 223 #endif | 223 #endif |
| 224 angle->set(fPts, fVerb, this, start, end, fTs); | 224 angle->set(fPts, fVerb, this, start, end, fTs); |
| (...skipping 945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 } | 1170 } |
| 1171 const SkOpAngle* nextAngle = sorted[nextIndex]; | 1171 const SkOpAngle* nextAngle = sorted[nextIndex]; |
| 1172 nextSegment = nextAngle->segment(); | 1172 nextSegment = nextAngle->segment(); |
| 1173 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; | 1173 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; |
| 1174 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle
->start(), | 1174 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle
->start(), |
| 1175 nextAngle->end(), op, &sumMiWinding, &sumSuWinding, | 1175 nextAngle->end(), op, &sumMiWinding, &sumSuWinding, |
| 1176 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); | 1176 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); |
| 1177 if (activeAngle) { | 1177 if (activeAngle) { |
| 1178 ++activeCount; | 1178 ++activeCount; |
| 1179 if (!foundAngle || (foundDone && activeCount & 1)) { | 1179 if (!foundAngle || (foundDone && activeCount & 1)) { |
| 1180 if (nextSegment->tiny(nextAngle)) { | 1180 if (nextSegment->isTiny(nextAngle)) { |
| 1181 *unsortable = true; | 1181 *unsortable = true; |
| 1182 return NULL; | 1182 return NULL; |
| 1183 } | 1183 } |
| 1184 foundAngle = nextAngle; | 1184 foundAngle = nextAngle; |
| 1185 foundDone = nextSegment->done(nextAngle) && !nextSegment->tiny(n
extAngle); | 1185 foundDone = nextSegment->done(nextAngle) && !nextSegment->isTiny
(nextAngle); |
| 1186 } | 1186 } |
| 1187 } | 1187 } |
| 1188 if (nextSegment->done()) { | 1188 if (nextSegment->done()) { |
| 1189 continue; | 1189 continue; |
| 1190 } | 1190 } |
| 1191 if (nextSegment->windSum(nextAngle) != SK_MinS32) { | 1191 if (nextSegment->windSum(nextAngle) != SK_MinS32) { |
| 1192 continue; | 1192 continue; |
| 1193 } | 1193 } |
| 1194 SkOpSpan* last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWi
nding, | 1194 SkOpSpan* last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWi
nding, |
| 1195 oppSumWinding, activeAngle, nextAngle); | 1195 oppSumWinding, activeAngle, nextAngle); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 nextIndex = 0; | 1287 nextIndex = 0; |
| 1288 } | 1288 } |
| 1289 const SkOpAngle* nextAngle = sorted[nextIndex]; | 1289 const SkOpAngle* nextAngle = sorted[nextIndex]; |
| 1290 nextSegment = nextAngle->segment(); | 1290 nextSegment = nextAngle->segment(); |
| 1291 int maxWinding; | 1291 int maxWinding; |
| 1292 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn
gle->end(), | 1292 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn
gle->end(), |
| 1293 &maxWinding, &sumWinding); | 1293 &maxWinding, &sumWinding); |
| 1294 if (activeAngle) { | 1294 if (activeAngle) { |
| 1295 ++activeCount; | 1295 ++activeCount; |
| 1296 if (!foundAngle || (foundDone && activeCount & 1)) { | 1296 if (!foundAngle || (foundDone && activeCount & 1)) { |
| 1297 if (nextSegment->tiny(nextAngle)) { | 1297 if (nextSegment->isTiny(nextAngle)) { |
| 1298 *unsortable = true; | 1298 *unsortable = true; |
| 1299 return NULL; | 1299 return NULL; |
| 1300 } | 1300 } |
| 1301 foundAngle = nextAngle; | 1301 foundAngle = nextAngle; |
| 1302 foundDone = nextSegment->done(nextAngle); | 1302 foundDone = nextSegment->done(nextAngle); |
| 1303 } | 1303 } |
| 1304 } | 1304 } |
| 1305 if (nextSegment->done()) { | 1305 if (nextSegment->done()) { |
| 1306 continue; | 1306 continue; |
| 1307 } | 1307 } |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 int activeCount = 0; | 1409 int activeCount = 0; |
| 1410 do { | 1410 do { |
| 1411 SkASSERT(nextIndex != firstIndex); | 1411 SkASSERT(nextIndex != firstIndex); |
| 1412 if (nextIndex == angleCount) { | 1412 if (nextIndex == angleCount) { |
| 1413 nextIndex = 0; | 1413 nextIndex = 0; |
| 1414 } | 1414 } |
| 1415 const SkOpAngle* nextAngle = sorted[nextIndex]; | 1415 const SkOpAngle* nextAngle = sorted[nextIndex]; |
| 1416 nextSegment = nextAngle->segment(); | 1416 nextSegment = nextAngle->segment(); |
| 1417 ++activeCount; | 1417 ++activeCount; |
| 1418 if (!foundAngle || (foundDone && activeCount & 1)) { | 1418 if (!foundAngle || (foundDone && activeCount & 1)) { |
| 1419 if (nextSegment->tiny(nextAngle)) { | 1419 if (nextSegment->isTiny(nextAngle)) { |
| 1420 *unsortable = true; | 1420 *unsortable = true; |
| 1421 return NULL; | 1421 return NULL; |
| 1422 } | 1422 } |
| 1423 foundAngle = nextAngle; | 1423 foundAngle = nextAngle; |
| 1424 foundDone = nextSegment->done(nextAngle); | 1424 foundDone = nextSegment->done(nextAngle); |
| 1425 } | 1425 } |
| 1426 if (nextSegment->done()) { | 1426 if (nextSegment->done()) { |
| 1427 continue; | 1427 continue; |
| 1428 } | 1428 } |
| 1429 } while (++nextIndex != lastIndex); | 1429 } while (++nextIndex != lastIndex); |
| (...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 edge[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], fTs[start].fT, | 2372 edge[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], fTs[start].fT, |
| 2373 fTs[end].fT).asSkPoint(); | 2373 fTs[end].fT).asSkPoint(); |
| 2374 } else { | 2374 } else { |
| 2375 SkDCubic::SubDivide(fPts, sub[0], sub[1], fTs[start].fT, fTs[end].fT
, sub); | 2375 SkDCubic::SubDivide(fPts, sub[0], sub[1], fTs[start].fT, fTs[end].fT
, sub); |
| 2376 edge[1] = sub[0].asSkPoint(); | 2376 edge[1] = sub[0].asSkPoint(); |
| 2377 edge[2] = sub[1].asSkPoint(); | 2377 edge[2] = sub[1].asSkPoint(); |
| 2378 } | 2378 } |
| 2379 } | 2379 } |
| 2380 } | 2380 } |
| 2381 | 2381 |
| 2382 void SkOpSegment::subDivide(int start, int end, SkDCubic* result) const { |
| 2383 (*result)[0].set(fTs[start].fPt); |
| 2384 (*result)[fVerb].set(fTs[end].fPt); |
| 2385 if (fVerb == SkPath::kQuad_Verb) { |
| 2386 (*result)[1] = SkDQuad::SubDivide(fPts, (*result)[0], (*result)[2], fTs[
start].fT, |
| 2387 fTs[end].fT); |
| 2388 } else if (fVerb == SkPath::kCubic_Verb) { |
| 2389 SkDCubic::SubDivide(fPts, (*result)[0], (*result)[3], fTs[start].fT, fTs
[end].fT, |
| 2390 &(*result)[1]); |
| 2391 } |
| 2392 } |
| 2393 |
| 2382 void SkOpSegment::subDivideBounds(int start, int end, SkPathOpsBounds* bounds) c
onst { | 2394 void SkOpSegment::subDivideBounds(int start, int end, SkPathOpsBounds* bounds) c
onst { |
| 2383 SkPoint edge[4]; | 2395 SkPoint edge[4]; |
| 2384 subDivide(start, end, edge); | 2396 subDivide(start, end, edge); |
| 2385 (bounds->*SetCurveBounds[fVerb])(edge); | 2397 (bounds->*SetCurveBounds[fVerb])(edge); |
| 2386 } | 2398 } |
| 2387 | 2399 |
| 2388 bool SkOpSegment::tiny(const SkOpAngle* angle) const { | 2400 bool SkOpSegment::isTiny(const SkOpAngle* angle) const { |
| 2389 int start = angle->start(); | 2401 int start = angle->start(); |
| 2390 int end = angle->end(); | 2402 int end = angle->end(); |
| 2391 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; | 2403 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; |
| 2392 return mSpan.fTiny; | 2404 return mSpan.fTiny; |
| 2393 } | 2405 } |
| 2394 | 2406 |
| 2395 void SkOpSegment::TrackOutside(SkTDArray<double>* outsideTs, double end, double
start) { | 2407 void SkOpSegment::TrackOutside(SkTDArray<double>* outsideTs, double end, double
start) { |
| 2396 int outCount = outsideTs->count(); | 2408 int outCount = outsideTs->count(); |
| 2397 if (outCount == 0 || !approximately_negative(end - (*outsideTs)[outCount - 2
])) { | 2409 if (outCount == 0 || !approximately_negative(end - (*outsideTs)[outCount - 2
])) { |
| 2398 *outsideTs->append() = end; | 2410 *outsideTs->append() = end; |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2728 lastSum = windSum; | 2740 lastSum = windSum; |
| 2729 windSum -= segment.spanSign(&angle); | 2741 windSum -= segment.spanSign(&angle); |
| 2730 if (oppoSign) { | 2742 if (oppoSign) { |
| 2731 oppLastSum = oppWindSum; | 2743 oppLastSum = oppWindSum; |
| 2732 oppWindSum -= oppoSign; | 2744 oppWindSum -= oppoSign; |
| 2733 } | 2745 } |
| 2734 } | 2746 } |
| 2735 } | 2747 } |
| 2736 SkDebugf("%s [%d] %s", __FUNCTION__, index, | 2748 SkDebugf("%s [%d] %s", __FUNCTION__, index, |
| 2737 angle.unsortable() ? "*** UNSORTABLE *** " : ""); | 2749 angle.unsortable() ? "*** UNSORTABLE *** " : ""); |
| 2738 #if COMPACT_DEBUG_SORT | 2750 #if DEBUG_SORT_COMPACT |
| 2739 SkDebugf("id=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)", | 2751 SkDebugf("id=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)", |
| 2740 segment.fID, kLVerbStr[segment.fVerb], | 2752 segment.fID, kLVerbStr[segment.fVerb], |
| 2741 start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end, | 2753 start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end, |
| 2742 segment.xAtT(&eSpan), segment.yAtT(&eSpan)); | 2754 segment.xAtT(&eSpan), segment.yAtT(&eSpan)); |
| 2743 #else | 2755 #else |
| 2744 switch (segment.fVerb) { | 2756 switch (segment.fVerb) { |
| 2745 case SkPath::kLine_Verb: | 2757 case SkPath::kLine_Verb: |
| 2746 SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts)); | 2758 SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts)); |
| 2747 break; | 2759 break; |
| 2748 case SkPath::kQuad_Verb: | 2760 case SkPath::kQuad_Verb: |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2820 sum += fTs[i].fWindValue; | 2832 sum += fTs[i].fWindValue; |
| 2821 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); | 2833 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); |
| 2822 sum += fTs[i].fOppValue; | 2834 sum += fTs[i].fOppValue; |
| 2823 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); | 2835 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); |
| 2824 } | 2836 } |
| 2825 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, | 2837 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, |
| 2826 slots.begin() + slotCount); | 2838 slots.begin() + slotCount); |
| 2827 return sum; | 2839 return sum; |
| 2828 } | 2840 } |
| 2829 #endif | 2841 #endif |
| OLD | NEW |