| 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 } | 126 } |
| 127 { | 127 { |
| 128 const SkPoint& xy = xyAtT(&span); | 128 const SkPoint& xy = xyAtT(&span); |
| 129 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { | 129 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { |
| 130 topPt = xy; | 130 topPt = xy; |
| 131 if (firstT) { | 131 if (firstT) { |
| 132 *firstT = index; | 132 *firstT = index; |
| 133 } | 133 } |
| 134 } | 134 } |
| 135 if (fVerb != SkPath::kLine_Verb && !lastDone) { | 135 if (fVerb != SkPath::kLine_Verb && !lastDone) { |
| 136 SkPoint curveTop = (*CurveTop[fVerb])(fPts, lastT, span.fT); | 136 SkPoint curveTop = (*CurveTop[SkPathOpsVerbToPoints(fVerb)])(fPt
s, lastT, span.fT); |
| 137 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY | 137 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY |
| 138 && topPt.fX > curveTop.fX)) { | 138 && topPt.fX > curveTop.fX)) { |
| 139 topPt = curveTop; | 139 topPt = curveTop; |
| 140 if (firstT) { | 140 if (firstT) { |
| 141 *firstT = index; | 141 *firstT = index; |
| 142 } | 142 } |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 lastT = span.fT; | 145 lastT = span.fT; |
| 146 } | 146 } |
| (...skipping 56 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 SkPoint angle0Pt = (*CurvePointAtT[SkPathOpsVerbToPoints(angles[0].verb(
))])(angles[0].pts(), |
| 214 (*angles[0].spans())[angles[0].start()].fT); | 214 (*angles[0].spans())[angles[0].start()].fT); |
| 215 SkPoint newPt = (*CurvePointAtT[fVerb])(fPts, fTs[start].fT); | 215 SkPoint newPt = (*CurvePointAtT[SkPathOpsVerbToPoints(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); |
| 225 } | 225 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 if (lastT < 0 || (start == 0 && end == lastT) || (start == lastT && end == 0
)) { | 347 if (lastT < 0 || (start == 0 && end == lastT) || (start == lastT && end == 0
)) { |
| 348 ePtr = fPts; | 348 ePtr = fPts; |
| 349 } else { | 349 } else { |
| 350 // OPTIMIZE? if not active, skip remainder and return xyAtT(end) | 350 // OPTIMIZE? if not active, skip remainder and return xyAtT(end) |
| 351 subDivide(start, end, edge); | 351 subDivide(start, end, edge); |
| 352 ePtr = edge; | 352 ePtr = edge; |
| 353 } | 353 } |
| 354 if (active) { | 354 if (active) { |
| 355 bool reverse = ePtr == fPts && start != 0; | 355 bool reverse = ePtr == fPts && start != 0; |
| 356 if (reverse) { | 356 if (reverse) { |
| 357 path->deferredMoveLine(ePtr[fVerb]); | 357 path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]); |
| 358 switch (fVerb) { | 358 switch (fVerb) { |
| 359 case SkPath::kLine_Verb: | 359 case SkPath::kLine_Verb: |
| 360 path->deferredLine(ePtr[0]); | 360 path->deferredLine(ePtr[0]); |
| 361 break; | 361 break; |
| 362 case SkPath::kQuad_Verb: | 362 case SkPath::kQuad_Verb: |
| 363 path->quadTo(ePtr[1], ePtr[0]); | 363 path->quadTo(ePtr[1], ePtr[0]); |
| 364 break; | 364 break; |
| 365 case SkPath::kCubic_Verb: | 365 case SkPath::kCubic_Verb: |
| 366 path->cubicTo(ePtr[2], ePtr[1], ePtr[0]); | 366 path->cubicTo(ePtr[2], ePtr[1], ePtr[0]); |
| 367 break; | 367 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 379 path->quadTo(ePtr[1], ePtr[2]); | 379 path->quadTo(ePtr[1], ePtr[2]); |
| 380 break; | 380 break; |
| 381 case SkPath::kCubic_Verb: | 381 case SkPath::kCubic_Verb: |
| 382 path->cubicTo(ePtr[1], ePtr[2], ePtr[3]); | 382 path->cubicTo(ePtr[1], ePtr[2], ePtr[3]); |
| 383 break; | 383 break; |
| 384 default: | 384 default: |
| 385 SkASSERT(0); | 385 SkASSERT(0); |
| 386 } | 386 } |
| 387 } | 387 } |
| 388 } | 388 } |
| 389 // return ePtr[fVerb]; | 389 // return ePtr[SkPathOpsVerbToPoints(fVerb)]; |
| 390 } | 390 } |
| 391 | 391 |
| 392 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) { | 392 void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) { |
| 393 init(pts, SkPath::kLine_Verb, operand, evenOdd); | 393 init(pts, SkPath::kLine_Verb, operand, evenOdd); |
| 394 fBounds.set(pts, 2); | 394 fBounds.set(pts, 2); |
| 395 } | 395 } |
| 396 | 396 |
| 397 // add 2 to edge or out of range values to get T extremes | 397 // add 2 to edge or out of range values to get T extremes |
| 398 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) { | 398 void SkOpSegment::addOtherT(int index, double otherT, int otherIndex) { |
| 399 SkOpSpan& span = fTs[index]; | 399 SkOpSpan& span = fTs[index]; |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 972 return bestTIndex; | 972 return bestTIndex; |
| 973 } | 973 } |
| 974 if (fBounds.fLeft == fBounds.fRight) { | 974 if (fBounds.fLeft == fBounds.fRight) { |
| 975 // if vertical, and directly above test point, wait for another one | 975 // if vertical, and directly above test point, wait for another one |
| 976 return AlmostEqualUlps(basePt.fX, fBounds.fLeft) ? SK_MinS32 : bestTInde
x; | 976 return AlmostEqualUlps(basePt.fX, fBounds.fLeft) ? SK_MinS32 : bestTInde
x; |
| 977 } | 977 } |
| 978 // intersect ray starting at basePt with edge | 978 // intersect ray starting at basePt with edge |
| 979 SkIntersections intersections; | 979 SkIntersections intersections; |
| 980 // OPTIMIZE: use specialty function that intersects ray with curve, | 980 // OPTIMIZE: use specialty function that intersects ray with curve, |
| 981 // returning t values only for curve (we don't care about t on ray) | 981 // returning t values only for curve (we don't care about t on ray) |
| 982 int pts = (intersections.*CurveVertical[fVerb])(fPts, top, bottom, basePt.fX
, false); | 982 int pts = (intersections.*CurveVertical[SkPathOpsVerbToPoints(fVerb)])(fPts,
top, bottom, basePt.fX, false); |
| 983 if (pts == 0 || (current && pts == 1)) { | 983 if (pts == 0 || (current && pts == 1)) { |
| 984 return bestTIndex; | 984 return bestTIndex; |
| 985 } | 985 } |
| 986 if (current) { | 986 if (current) { |
| 987 SkASSERT(pts > 1); | 987 SkASSERT(pts > 1); |
| 988 int closestIdx = 0; | 988 int closestIdx = 0; |
| 989 double closest = fabs(intersections[0][0] - mid); | 989 double closest = fabs(intersections[0][0] - mid); |
| 990 for (int idx = 1; idx < pts; ++idx) { | 990 for (int idx = 1; idx < pts; ++idx) { |
| 991 double test = fabs(intersections[0][idx] - mid); | 991 double test = fabs(intersections[0][idx] - mid); |
| 992 if (closest > test) { | 992 if (closest > test) { |
| 993 closestIdx = idx; | 993 closestIdx = idx; |
| 994 closest = test; | 994 closest = test; |
| 995 } | 995 } |
| 996 } | 996 } |
| 997 intersections.quickRemoveOne(closestIdx, --pts); | 997 intersections.quickRemoveOne(closestIdx, --pts); |
| 998 } | 998 } |
| 999 double bestT = -1; | 999 double bestT = -1; |
| 1000 for (int index = 0; index < pts; ++index) { | 1000 for (int index = 0; index < pts; ++index) { |
| 1001 double foundT = intersections[0][index]; | 1001 double foundT = intersections[0][index]; |
| 1002 if (approximately_less_than_zero(foundT) | 1002 if (approximately_less_than_zero(foundT) |
| 1003 || approximately_greater_than_one(foundT)) { | 1003 || approximately_greater_than_one(foundT)) { |
| 1004 continue; | 1004 continue; |
| 1005 } | 1005 } |
| 1006 SkScalar testY = (*CurvePointAtT[fVerb])(fPts, foundT).fY; | 1006 SkScalar testY = (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fo
undT).fY; |
| 1007 if (approximately_negative(testY - *bestY) | 1007 if (approximately_negative(testY - *bestY) |
| 1008 || approximately_negative(basePt.fY - testY)) { | 1008 || approximately_negative(basePt.fY - testY)) { |
| 1009 continue; | 1009 continue; |
| 1010 } | 1010 } |
| 1011 if (pts > 1 && fVerb == SkPath::kLine_Verb) { | 1011 if (pts > 1 && fVerb == SkPath::kLine_Verb) { |
| 1012 return SK_MinS32; // if the intersection is edge on, wait for anoth
er one | 1012 return SK_MinS32; // if the intersection is edge on, wait for anoth
er one |
| 1013 } | 1013 } |
| 1014 if (fVerb > SkPath::kLine_Verb) { | 1014 if (fVerb > SkPath::kLine_Verb) { |
| 1015 SkScalar dx = (*CurveSlopeAtT[fVerb])(fPts, foundT).fX; | 1015 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, f
oundT).fX; |
| 1016 if (approximately_zero(dx)) { | 1016 if (approximately_zero(dx)) { |
| 1017 return SK_MinS32; // hit vertical, wait for another one | 1017 return SK_MinS32; // hit vertical, wait for another one |
| 1018 } | 1018 } |
| 1019 } | 1019 } |
| 1020 *bestY = testY; | 1020 *bestY = testY; |
| 1021 bestT = foundT; | 1021 bestT = foundT; |
| 1022 } | 1022 } |
| 1023 if (bestT < 0) { | 1023 if (bestT < 0) { |
| 1024 return bestTIndex; | 1024 return bestTIndex; |
| 1025 } | 1025 } |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1731 the left or the right of vertical. This determines if we need to add the span's | 1731 the left or the right of vertical. This determines if we need to add the span's |
| 1732 sign or not. However, this isn't enough. | 1732 sign or not. However, this isn't enough. |
| 1733 If the supplied sign (winding) is zero, then we didn't hit another vertical span
, so dx is needed. | 1733 If the supplied sign (winding) is zero, then we didn't hit another vertical span
, so dx is needed. |
| 1734 If there was a winding, then it may or may not need adjusting. If the span the w
inding was borrowed | 1734 If there was a winding, then it may or may not need adjusting. If the span the w
inding was borrowed |
| 1735 from has the same x direction as this span, the winding should change. If the dx
is opposite, then | 1735 from has the same x direction as this span, the winding should change. If the dx
is opposite, then |
| 1736 the same winding is shared by both. | 1736 the same winding is shared by both. |
| 1737 */ | 1737 */ |
| 1738 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc
alar hitDx, | 1738 void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc
alar hitDx, |
| 1739 int oppWind, SkScalar hitOppDx) { | 1739 int oppWind, SkScalar hitOppDx) { |
| 1740 SkASSERT(hitDx || !winding); | 1740 SkASSERT(hitDx || !winding); |
| 1741 SkScalar dx = (*CurveSlopeAtT[fVerb])(fPts, tHit).fX; | 1741 SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; |
| 1742 SkASSERT(dx); | 1742 SkASSERT(dx); |
| 1743 int windVal = windValue(SkMin32(start, end)); | 1743 int windVal = windValue(SkMin32(start, end)); |
| 1744 #if DEBUG_WINDING_AT_T | 1744 #if DEBUG_WINDING_AT_T |
| 1745 SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding
, | 1745 SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding
, |
| 1746 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); | 1746 hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); |
| 1747 #endif | 1747 #endif |
| 1748 if (!winding) { | 1748 if (!winding) { |
| 1749 winding = dx < 0 ? windVal : -windVal; | 1749 winding = dx < 0 ? windVal : -windVal; |
| 1750 } else if (winding * dx < 0) { | 1750 } else if (winding * dx < 0) { |
| 1751 int sideWind = winding + (dx < 0 ? windVal : -windVal); | 1751 int sideWind = winding + (dx < 0 ? windVal : -windVal); |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 #endif | 2074 #endif |
| 2075 span.fOppSum = oppWinding; | 2075 span.fOppSum = oppWinding; |
| 2076 return &span; | 2076 return &span; |
| 2077 } | 2077 } |
| 2078 | 2078 |
| 2079 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of
-polygon-points-are-in-clockwise-order | 2079 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of
-polygon-points-are-in-clockwise-order |
| 2080 bool SkOpSegment::clockwise(int tStart, int tEnd) const { | 2080 bool SkOpSegment::clockwise(int tStart, int tEnd) const { |
| 2081 SkASSERT(fVerb != SkPath::kLine_Verb); | 2081 SkASSERT(fVerb != SkPath::kLine_Verb); |
| 2082 SkPoint edge[4]; | 2082 SkPoint edge[4]; |
| 2083 subDivide(tStart, tEnd, edge); | 2083 subDivide(tStart, tEnd, edge); |
| 2084 double sum = (edge[0].fX - edge[fVerb].fX) * (edge[0].fY + edge[fVerb].fY); | 2084 double sum = (edge[0].fX - edge[SkPathOpsVerbToPoints(fVerb)].fX) * (edge[0]
.fY + edge[SkPathOpsVerbToPoints(fVerb)].fY); |
| 2085 if (fVerb == SkPath::kCubic_Verb) { | 2085 if (fVerb == SkPath::kCubic_Verb) { |
| 2086 SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY); | 2086 SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY); |
| 2087 if (edge[1].fY < lesser && edge[2].fY < lesser) { | 2087 if (edge[1].fY < lesser && edge[2].fY < lesser) { |
| 2088 SkDLine tangent1 = {{ {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1]
.fY} }}; | 2088 SkDLine tangent1 = {{ {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1]
.fY} }}; |
| 2089 SkDLine tangent2 = {{ {edge[2].fX, edge[2].fY}, {edge[3].fX, edge[3]
.fY} }}; | 2089 SkDLine tangent2 = {{ {edge[2].fX, edge[2].fY}, {edge[3].fX, edge[3]
.fY} }}; |
| 2090 if (SkIntersections::Test(tangent1, tangent2)) { | 2090 if (SkIntersections::Test(tangent1, tangent2)) { |
| 2091 SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT); | 2091 SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT); |
| 2092 sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY); | 2092 sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY); |
| 2093 sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY); | 2093 sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY); |
| 2094 return sum <= 0; | 2094 return sum <= 0; |
| 2095 } | 2095 } |
| 2096 } | 2096 } |
| 2097 } | 2097 } |
| 2098 for (int idx = 0; idx < fVerb; ++idx){ | 2098 for (int idx = 0; idx < SkPathOpsVerbToPoints(fVerb); ++idx){ |
| 2099 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx]
.fY); | 2099 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx]
.fY); |
| 2100 } | 2100 } |
| 2101 return sum <= 0; | 2101 return sum <= 0; |
| 2102 } | 2102 } |
| 2103 | 2103 |
| 2104 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const { | 2104 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const { |
| 2105 if (fVerb == SkPath::kLine_Verb) { | 2105 if (fVerb == SkPath::kLine_Verb) { |
| 2106 return false; | 2106 return false; |
| 2107 } | 2107 } |
| 2108 if (fVerb == SkPath::kQuad_Verb) { | 2108 if (fVerb == SkPath::kQuad_Verb) { |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2358 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { | 2358 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { |
| 2359 const SkOpAngle& angle = angles[angleIndex]; | 2359 const SkOpAngle& angle = angles[angleIndex]; |
| 2360 angle.segment()->markUnsortable(angle.start(), angle.end()); | 2360 angle.segment()->markUnsortable(angle.start(), angle.end()); |
| 2361 } | 2361 } |
| 2362 } | 2362 } |
| 2363 return sortable; | 2363 return sortable; |
| 2364 } | 2364 } |
| 2365 | 2365 |
| 2366 void SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { | 2366 void SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { |
| 2367 edge[0] = fTs[start].fPt; | 2367 edge[0] = fTs[start].fPt; |
| 2368 edge[fVerb] = fTs[end].fPt; | 2368 edge[SkPathOpsVerbToPoints(fVerb)] = fTs[end].fPt; |
| 2369 if (fVerb == SkPath::kQuad_Verb || fVerb == SkPath::kCubic_Verb) { | 2369 if (fVerb == SkPath::kQuad_Verb || fVerb == SkPath::kCubic_Verb) { |
| 2370 SkDPoint sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[fVerb].fX, edge[fVer
b].fY }}; | 2370 SkDPoint sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[SkPathOpsVerbToPoint
s(fVerb)].fX, edge[SkPathOpsVerbToPoints(fVerb)].fY }}; |
| 2371 if (fVerb == SkPath::kQuad_Verb) { | 2371 if (fVerb == SkPath::kQuad_Verb) { |
| 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::subDivideBounds(int start, int end, SkPathOpsBounds* bounds) c
onst { | 2382 void SkOpSegment::subDivideBounds(int start, int end, SkPathOpsBounds* bounds) c
onst { |
| 2383 SkPoint edge[4]; | 2383 SkPoint edge[4]; |
| 2384 subDivide(start, end, edge); | 2384 subDivide(start, end, edge); |
| 2385 (bounds->*SetCurveBounds[fVerb])(edge); | 2385 (bounds->*SetCurveBounds[SkPathOpsVerbToPoints(fVerb)])(edge); |
| 2386 } | 2386 } |
| 2387 | 2387 |
| 2388 bool SkOpSegment::tiny(const SkOpAngle* angle) const { | 2388 bool SkOpSegment::tiny(const SkOpAngle* angle) const { |
| 2389 int start = angle->start(); | 2389 int start = angle->start(); |
| 2390 int end = angle->end(); | 2390 int end = angle->end(); |
| 2391 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; | 2391 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; |
| 2392 return mSpan.fTiny; | 2392 return mSpan.fTiny; |
| 2393 } | 2393 } |
| 2394 | 2394 |
| 2395 void SkOpSegment::TrackOutside(SkTDArray<double>* outsideTs, double end, double
start) { | 2395 void SkOpSegment::TrackOutside(SkTDArray<double>* outsideTs, double end, double
start) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2466 if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span,
disregard | 2466 if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span,
disregard |
| 2467 return SK_MinS32; | 2467 return SK_MinS32; |
| 2468 } | 2468 } |
| 2469 int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex); | 2469 int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex); |
| 2470 SkASSERT(winding != SK_MinS32); | 2470 SkASSERT(winding != SK_MinS32); |
| 2471 int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex); | 2471 int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex); |
| 2472 #if DEBUG_WINDING_AT_T | 2472 #if DEBUG_WINDING_AT_T |
| 2473 SkDebugf("%s oldWinding=%d windValue=%d", __FUNCTION__, winding, windVal); | 2473 SkDebugf("%s oldWinding=%d windValue=%d", __FUNCTION__, winding, windVal); |
| 2474 #endif | 2474 #endif |
| 2475 // see if a + change in T results in a +/- change in X (compute x'(T)) | 2475 // see if a + change in T results in a +/- change in X (compute x'(T)) |
| 2476 *dx = (*CurveSlopeAtT[fVerb])(fPts, tHit).fX; | 2476 *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; |
| 2477 if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { | 2477 if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { |
| 2478 *dx = fPts[2].fX - fPts[1].fX - *dx; | 2478 *dx = fPts[2].fX - fPts[1].fX - *dx; |
| 2479 } | 2479 } |
| 2480 if (*dx == 0) { | 2480 if (*dx == 0) { |
| 2481 #if DEBUG_WINDING_AT_T | 2481 #if DEBUG_WINDING_AT_T |
| 2482 SkDebugf(" dx=0 winding=SK_MinS32\n"); | 2482 SkDebugf(" dx=0 winding=SK_MinS32\n"); |
| 2483 #endif | 2483 #endif |
| 2484 return SK_MinS32; | 2484 return SK_MinS32; |
| 2485 } | 2485 } |
| 2486 if (winding * *dx > 0) { // if same signs, result is negative | 2486 if (winding * *dx > 0) { // if same signs, result is negative |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2604 SkASSERT(i < fTs.count() - 1); | 2604 SkASSERT(i < fTs.count() - 1); |
| 2605 #if DEBUG_ACTIVE_SPANS_SHORT_FORM | 2605 #if DEBUG_ACTIVE_SPANS_SHORT_FORM |
| 2606 if (lastId == fID && lastT == fTs[i].fT) { | 2606 if (lastId == fID && lastT == fTs[i].fT) { |
| 2607 continue; | 2607 continue; |
| 2608 } | 2608 } |
| 2609 lastId = fID; | 2609 lastId = fID; |
| 2610 lastT = fTs[i].fT; | 2610 lastT = fTs[i].fT; |
| 2611 #endif | 2611 #endif |
| 2612 SkDebugf("%s id=%d", __FUNCTION__, fID); | 2612 SkDebugf("%s id=%d", __FUNCTION__, fID); |
| 2613 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); | 2613 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); |
| 2614 for (int vIndex = 1; vIndex <= fVerb; ++vIndex) { | 2614 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { |
| 2615 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); | 2615 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); |
| 2616 } | 2616 } |
| 2617 const SkOpSpan* span = &fTs[i]; | 2617 const SkOpSpan* span = &fTs[i]; |
| 2618 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span)); | 2618 SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span)); |
| 2619 int iEnd = i + 1; | 2619 int iEnd = i + 1; |
| 2620 while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT))
{ | 2620 while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT))
{ |
| 2621 ++iEnd; | 2621 ++iEnd; |
| 2622 } | 2622 } |
| 2623 SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT); | 2623 SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT); |
| 2624 const SkOpSegment* other = fTs[i].fOther; | 2624 const SkOpSegment* other = fTs[i].fOther; |
| 2625 SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=", | 2625 SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=", |
| 2626 other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex); | 2626 other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex); |
| 2627 if (fTs[i].fWindSum == SK_MinS32) { | 2627 if (fTs[i].fWindSum == SK_MinS32) { |
| 2628 SkDebugf("?"); | 2628 SkDebugf("?"); |
| 2629 } else { | 2629 } else { |
| 2630 SkDebugf("%d", fTs[i].fWindSum); | 2630 SkDebugf("%d", fTs[i].fWindSum); |
| 2631 } | 2631 } |
| 2632 SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppVa
lue); | 2632 SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppVa
lue); |
| 2633 } | 2633 } |
| 2634 } | 2634 } |
| 2635 #endif | 2635 #endif |
| 2636 | 2636 |
| 2637 | 2637 |
| 2638 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE | 2638 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE |
| 2639 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int
winding) { | 2639 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int
winding) { |
| 2640 const SkPoint& pt = xyAtT(&span); | 2640 const SkPoint& pt = xyAtT(&span); |
| 2641 SkDebugf("%s id=%d", fun, fID); | 2641 SkDebugf("%s id=%d", fun, fID); |
| 2642 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); | 2642 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); |
| 2643 for (int vIndex = 1; vIndex <= fVerb; ++vIndex) { | 2643 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { |
| 2644 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); | 2644 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); |
| 2645 } | 2645 } |
| 2646 SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> | 2646 SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> |
| 2647 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]); | 2647 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]); |
| 2648 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=", | 2648 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=", |
| 2649 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f
Y, | 2649 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f
Y, |
| 2650 (&span)[1].fT, winding); | 2650 (&span)[1].fT, winding); |
| 2651 if (span.fWindSum == SK_MinS32) { | 2651 if (span.fWindSum == SK_MinS32) { |
| 2652 SkDebugf("?"); | 2652 SkDebugf("?"); |
| 2653 } else { | 2653 } else { |
| 2654 SkDebugf("%d", span.fWindSum); | 2654 SkDebugf("%d", span.fWindSum); |
| 2655 } | 2655 } |
| 2656 SkDebugf(" windValue=%d\n", span.fWindValue); | 2656 SkDebugf(" windValue=%d\n", span.fWindValue); |
| 2657 } | 2657 } |
| 2658 | 2658 |
| 2659 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int
winding, | 2659 void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int
winding, |
| 2660 int oppWinding) { | 2660 int oppWinding) { |
| 2661 const SkPoint& pt = xyAtT(&span); | 2661 const SkPoint& pt = xyAtT(&span); |
| 2662 SkDebugf("%s id=%d", fun, fID); | 2662 SkDebugf("%s id=%d", fun, fID); |
| 2663 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); | 2663 SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); |
| 2664 for (int vIndex = 1; vIndex <= fVerb; ++vIndex) { | 2664 for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { |
| 2665 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); | 2665 SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); |
| 2666 } | 2666 } |
| 2667 SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> | 2667 SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther-> |
| 2668 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]); | 2668 fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]); |
| 2669 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d
oppSum=", | 2669 SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d
oppSum=", |
| 2670 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f
Y, | 2670 span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.f
Y, |
| 2671 (&span)[1].fT, winding, oppWinding); | 2671 (&span)[1].fT, winding, oppWinding); |
| 2672 if (span.fOppSum == SK_MinS32) { | 2672 if (span.fOppSum == SK_MinS32) { |
| 2673 SkDebugf("?"); | 2673 SkDebugf("?"); |
| 2674 } else { | 2674 } else { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2730 if (oppoSign) { | 2730 if (oppoSign) { |
| 2731 oppLastSum = oppWindSum; | 2731 oppLastSum = oppWindSum; |
| 2732 oppWindSum -= oppoSign; | 2732 oppWindSum -= oppoSign; |
| 2733 } | 2733 } |
| 2734 } | 2734 } |
| 2735 } | 2735 } |
| 2736 SkDebugf("%s [%d] %s", __FUNCTION__, index, | 2736 SkDebugf("%s [%d] %s", __FUNCTION__, index, |
| 2737 angle.unsortable() ? "*** UNSORTABLE *** " : ""); | 2737 angle.unsortable() ? "*** UNSORTABLE *** " : ""); |
| 2738 #if COMPACT_DEBUG_SORT | 2738 #if COMPACT_DEBUG_SORT |
| 2739 SkDebugf("id=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)", | 2739 SkDebugf("id=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)", |
| 2740 segment.fID, kLVerbStr[segment.fVerb], | 2740 segment.fID, kLVerbStr[SkPathOpsVerbToPoints(segment.fVerb)], |
| 2741 start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end, | 2741 start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end, |
| 2742 segment.xAtT(&eSpan), segment.yAtT(&eSpan)); | 2742 segment.xAtT(&eSpan), segment.yAtT(&eSpan)); |
| 2743 #else | 2743 #else |
| 2744 switch (segment.fVerb) { | 2744 switch (segment.fVerb) { |
| 2745 case SkPath::kLine_Verb: | 2745 case SkPath::kLine_Verb: |
| 2746 SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts)); | 2746 SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts)); |
| 2747 break; | 2747 break; |
| 2748 case SkPath::kQuad_Verb: | 2748 case SkPath::kQuad_Verb: |
| 2749 SkDebugf(QUAD_DEBUG_STR, QUAD_DEBUG_DATA(segment.fPts)); | 2749 SkDebugf(QUAD_DEBUG_STR, QUAD_DEBUG_DATA(segment.fPts)); |
| 2750 break; | 2750 break; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2820 sum += fTs[i].fWindValue; | 2820 sum += fTs[i].fWindValue; |
| 2821 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); | 2821 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); |
| 2822 sum += fTs[i].fOppValue; | 2822 sum += fTs[i].fOppValue; |
| 2823 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); | 2823 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); |
| 2824 } | 2824 } |
| 2825 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, | 2825 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, |
| 2826 slots.begin() + slotCount); | 2826 slots.begin() + slotCount); |
| 2827 return sum; | 2827 return sum; |
| 2828 } | 2828 } |
| 2829 #endif | 2829 #endif |
| OLD | NEW |