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 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 bool to = *sumWinding != 0; | 202 bool to = *sumWinding != 0; |
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) { |
213 SkPoint angle0Pt = (*CurvePointAtT[SkPathOpsVerbToPoints(angles[0].verb(
))])(angles[0].pts(), | 213 const SkOpSegment* aSeg = angles[0].segment(); |
214 (*angles[0].spans())[angles[0].start()].fT); | 214 int aStart = angles[0].start(); |
215 SkPoint newPt = (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs
[start].fT); | 215 if (!aSeg->fTs[aStart].fTiny) { |
216 bool match = AlmostEqualUlps(angle0Pt.fX, newPt.fX); | 216 const SkPoint& angle0Pt = aSeg->xyAtT(aStart); |
217 match &= AlmostEqualUlps(angle0Pt.fY, newPt.fY); | 217 SkDPoint newPt = (*CurveDPointAtT[SkPathOpsVerbToPoints(aSeg->fVerb)
])(aSeg->fPts, |
218 if (!match) { | 218 aSeg->fTs[aStart].fT); |
219 SkDebugf("%s no match\n", __FUNCTION__); | 219 #if ONE_OFF_DEBUG |
220 SkASSERT(0); | 220 SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g)\n", __FUNCTION__
, |
| 221 aSeg->fTs[aStart].fT, newPt.fX, newPt.fY, angle0Pt.fX, angle
0Pt.fY); |
| 222 #endif |
| 223 SkASSERT(newPt.approximatelyEqual(angle0Pt)); |
221 } | 224 } |
222 } | 225 } |
223 #endif | 226 #endif |
224 angle->set(fPts, fVerb, this, start, end, fTs); | 227 angle->set(this, start, end); |
225 } | 228 } |
226 | 229 |
227 void SkOpSegment::addCancelOutsides(double tStart, double oStart, SkOpSegment* o
ther, double oEnd) { | 230 void SkOpSegment::addCancelOutsides(double tStart, double oStart, SkOpSegment* o
ther, double oEnd) { |
228 int tIndex = -1; | 231 int tIndex = -1; |
229 int tCount = fTs.count(); | 232 int tCount = fTs.count(); |
230 int oIndex = -1; | 233 int oIndex = -1; |
231 int oCount = other->fTs.count(); | 234 int oCount = other->fTs.count(); |
232 do { | 235 do { |
233 ++tIndex; | 236 ++tIndex; |
234 } while (!approximately_negative(tStart - fTs[tIndex].fT) && tIndex < tCount
); | 237 } while (!approximately_negative(tStart - fTs[tIndex].fT) && tIndex < tCount
); |
(...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
846 other->addTwoAngles(next, oIndex, angles); | 849 other->addTwoAngles(next, oIndex, angles); |
847 } | 850 } |
848 | 851 |
849 int SkOpSegment::computeSum(int startIndex, int endIndex, bool binary) { | 852 int SkOpSegment::computeSum(int startIndex, int endIndex, bool binary) { |
850 SkTDArray<SkOpAngle> angles; | 853 SkTDArray<SkOpAngle> angles; |
851 addTwoAngles(startIndex, endIndex, &angles); | 854 addTwoAngles(startIndex, endIndex, &angles); |
852 buildAngles(endIndex, &angles, false); | 855 buildAngles(endIndex, &angles, false); |
853 // OPTIMIZATION: check all angles to see if any have computed wind sum | 856 // OPTIMIZATION: check all angles to see if any have computed wind sum |
854 // before sorting (early exit if none) | 857 // before sorting (early exit if none) |
855 SkTDArray<SkOpAngle*> sorted; | 858 SkTDArray<SkOpAngle*> sorted; |
856 bool sortable = SortAngles(angles, &sorted); | 859 // FIXME?: Not sure if this sort must be ordered or if the relaxed ordering
is OK ... |
| 860 bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_Sort
AngleKind); |
857 #if DEBUG_SORT | 861 #if DEBUG_SORT |
858 sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0); | 862 sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0); |
859 #endif | 863 #endif |
860 if (!sortable) { | 864 if (!sortable) { |
861 return SK_MinS32; | 865 return SK_MinS32; |
862 } | 866 } |
863 int angleCount = angles.count(); | 867 int angleCount = angles.count(); |
864 const SkOpAngle* angle; | 868 const SkOpAngle* angle; |
865 const SkOpSegment* base; | 869 const SkOpSegment* base; |
866 int winding; | 870 int winding; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 return bestTIndex; | 976 return bestTIndex; |
973 } | 977 } |
974 if (fBounds.fLeft == fBounds.fRight) { | 978 if (fBounds.fLeft == fBounds.fRight) { |
975 // if vertical, and directly above test point, wait for another one | 979 // if vertical, and directly above test point, wait for another one |
976 return AlmostEqualUlps(basePt.fX, fBounds.fLeft) ? SK_MinS32 : bestTInde
x; | 980 return AlmostEqualUlps(basePt.fX, fBounds.fLeft) ? SK_MinS32 : bestTInde
x; |
977 } | 981 } |
978 // intersect ray starting at basePt with edge | 982 // intersect ray starting at basePt with edge |
979 SkIntersections intersections; | 983 SkIntersections intersections; |
980 // OPTIMIZE: use specialty function that intersects ray with curve, | 984 // OPTIMIZE: use specialty function that intersects ray with curve, |
981 // returning t values only for curve (we don't care about t on ray) | 985 // returning t values only for curve (we don't care about t on ray) |
982 int pts = (intersections.*CurveVertical[SkPathOpsVerbToPoints(fVerb)])(fPts,
top, bottom, basePt.fX, false); | 986 int pts = (intersections.*CurveVertical[SkPathOpsVerbToPoints(fVerb)]) |
| 987 (fPts, top, bottom, basePt.fX, false); |
983 if (pts == 0 || (current && pts == 1)) { | 988 if (pts == 0 || (current && pts == 1)) { |
984 return bestTIndex; | 989 return bestTIndex; |
985 } | 990 } |
986 if (current) { | 991 if (current) { |
987 SkASSERT(pts > 1); | 992 SkASSERT(pts > 1); |
988 int closestIdx = 0; | 993 int closestIdx = 0; |
989 double closest = fabs(intersections[0][0] - mid); | 994 double closest = fabs(intersections[0][0] - mid); |
990 for (int idx = 1; idx < pts; ++idx) { | 995 for (int idx = 1; idx < pts; ++idx) { |
991 double test = fabs(intersections[0][idx] - mid); | 996 double test = fabs(intersections[0][idx] - mid); |
992 if (closest > test) { | 997 if (closest > test) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 markDoneBinary(min); | 1124 markDoneBinary(min); |
1120 other = endSpan->fOther; | 1125 other = endSpan->fOther; |
1121 *nextStart = endSpan->fOtherIndex; | 1126 *nextStart = endSpan->fOtherIndex; |
1122 double startT = other->fTs[*nextStart].fT; | 1127 double startT = other->fTs[*nextStart].fT; |
1123 *nextEnd = *nextStart; | 1128 *nextEnd = *nextStart; |
1124 do { | 1129 do { |
1125 *nextEnd += step; | 1130 *nextEnd += step; |
1126 } | 1131 } |
1127 while (precisely_zero(startT - other->fTs[*nextEnd].fT)); | 1132 while (precisely_zero(startT - other->fTs[*nextEnd].fT)); |
1128 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); | 1133 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); |
| 1134 if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { |
| 1135 return NULL; |
| 1136 } |
1129 return other; | 1137 return other; |
1130 } | 1138 } |
1131 // more than one viable candidate -- measure angles to find best | 1139 // more than one viable candidate -- measure angles to find best |
1132 SkTDArray<SkOpAngle> angles; | 1140 SkTDArray<SkOpAngle> angles; |
1133 SkASSERT(startIndex - endIndex != 0); | 1141 SkASSERT(startIndex - endIndex != 0); |
1134 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); | 1142 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); |
1135 addTwoAngles(startIndex, end, &angles); | 1143 addTwoAngles(startIndex, end, &angles); |
1136 buildAngles(end, &angles, true); | 1144 buildAngles(end, &angles, true); |
1137 SkTDArray<SkOpAngle*> sorted; | 1145 SkTDArray<SkOpAngle*> sorted; |
1138 bool sortable = SortAngles(angles, &sorted); | 1146 bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_Sort
AngleKind); |
1139 int angleCount = angles.count(); | 1147 int angleCount = angles.count(); |
1140 int firstIndex = findStartingEdge(sorted, startIndex, end); | 1148 int firstIndex = findStartingEdge(sorted, startIndex, end); |
1141 SkASSERT(firstIndex >= 0); | 1149 SkASSERT(firstIndex >= 0); |
1142 #if DEBUG_SORT | 1150 #if DEBUG_SORT |
1143 debugShowSort(__FUNCTION__, sorted, firstIndex); | 1151 debugShowSort(__FUNCTION__, sorted, firstIndex); |
1144 #endif | 1152 #endif |
1145 if (!sortable) { | 1153 if (!sortable) { |
1146 *unsortable = true; | 1154 *unsortable = true; |
1147 return NULL; | 1155 return NULL; |
1148 } | 1156 } |
(...skipping 21 matching lines...) Expand all Loading... |
1170 } | 1178 } |
1171 const SkOpAngle* nextAngle = sorted[nextIndex]; | 1179 const SkOpAngle* nextAngle = sorted[nextIndex]; |
1172 nextSegment = nextAngle->segment(); | 1180 nextSegment = nextAngle->segment(); |
1173 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; | 1181 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; |
1174 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle
->start(), | 1182 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle
->start(), |
1175 nextAngle->end(), op, &sumMiWinding, &sumSuWinding, | 1183 nextAngle->end(), op, &sumMiWinding, &sumSuWinding, |
1176 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); | 1184 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); |
1177 if (activeAngle) { | 1185 if (activeAngle) { |
1178 ++activeCount; | 1186 ++activeCount; |
1179 if (!foundAngle || (foundDone && activeCount & 1)) { | 1187 if (!foundAngle || (foundDone && activeCount & 1)) { |
1180 if (nextSegment->tiny(nextAngle)) { | 1188 if (nextSegment->isTiny(nextAngle)) { |
1181 *unsortable = true; | 1189 *unsortable = true; |
1182 return NULL; | 1190 return NULL; |
1183 } | 1191 } |
1184 foundAngle = nextAngle; | 1192 foundAngle = nextAngle; |
1185 foundDone = nextSegment->done(nextAngle) && !nextSegment->tiny(n
extAngle); | 1193 foundDone = nextSegment->done(nextAngle) && !nextSegment->isTiny
(nextAngle); |
1186 } | 1194 } |
1187 } | 1195 } |
1188 if (nextSegment->done()) { | 1196 if (nextSegment->done()) { |
1189 continue; | 1197 continue; |
1190 } | 1198 } |
1191 if (nextSegment->windSum(nextAngle) != SK_MinS32) { | 1199 if (nextSegment->windSum(nextAngle) != SK_MinS32) { |
1192 continue; | 1200 continue; |
1193 } | 1201 } |
1194 SkOpSpan* last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWi
nding, | 1202 SkOpSpan* last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWi
nding, |
1195 oppSumWinding, activeAngle, nextAngle); | 1203 oppSumWinding, activeAngle, nextAngle); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1250 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); | 1258 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); |
1251 return other; | 1259 return other; |
1252 } | 1260 } |
1253 // more than one viable candidate -- measure angles to find best | 1261 // more than one viable candidate -- measure angles to find best |
1254 SkTDArray<SkOpAngle> angles; | 1262 SkTDArray<SkOpAngle> angles; |
1255 SkASSERT(startIndex - endIndex != 0); | 1263 SkASSERT(startIndex - endIndex != 0); |
1256 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); | 1264 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); |
1257 addTwoAngles(startIndex, end, &angles); | 1265 addTwoAngles(startIndex, end, &angles); |
1258 buildAngles(end, &angles, true); | 1266 buildAngles(end, &angles, true); |
1259 SkTDArray<SkOpAngle*> sorted; | 1267 SkTDArray<SkOpAngle*> sorted; |
1260 bool sortable = SortAngles(angles, &sorted); | 1268 bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_Sort
AngleKind); |
1261 int angleCount = angles.count(); | 1269 int angleCount = angles.count(); |
1262 int firstIndex = findStartingEdge(sorted, startIndex, end); | 1270 int firstIndex = findStartingEdge(sorted, startIndex, end); |
1263 SkASSERT(firstIndex >= 0); | 1271 SkASSERT(firstIndex >= 0); |
1264 #if DEBUG_SORT | 1272 #if DEBUG_SORT |
1265 debugShowSort(__FUNCTION__, sorted, firstIndex); | 1273 debugShowSort(__FUNCTION__, sorted, firstIndex); |
1266 #endif | 1274 #endif |
1267 if (!sortable) { | 1275 if (!sortable) { |
1268 *unsortable = true; | 1276 *unsortable = true; |
1269 return NULL; | 1277 return NULL; |
1270 } | 1278 } |
(...skipping 16 matching lines...) Expand all Loading... |
1287 nextIndex = 0; | 1295 nextIndex = 0; |
1288 } | 1296 } |
1289 const SkOpAngle* nextAngle = sorted[nextIndex]; | 1297 const SkOpAngle* nextAngle = sorted[nextIndex]; |
1290 nextSegment = nextAngle->segment(); | 1298 nextSegment = nextAngle->segment(); |
1291 int maxWinding; | 1299 int maxWinding; |
1292 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn
gle->end(), | 1300 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAn
gle->end(), |
1293 &maxWinding, &sumWinding); | 1301 &maxWinding, &sumWinding); |
1294 if (activeAngle) { | 1302 if (activeAngle) { |
1295 ++activeCount; | 1303 ++activeCount; |
1296 if (!foundAngle || (foundDone && activeCount & 1)) { | 1304 if (!foundAngle || (foundDone && activeCount & 1)) { |
1297 if (nextSegment->tiny(nextAngle)) { | 1305 if (nextSegment->isTiny(nextAngle)) { |
1298 *unsortable = true; | 1306 *unsortable = true; |
1299 return NULL; | 1307 return NULL; |
1300 } | 1308 } |
1301 foundAngle = nextAngle; | 1309 foundAngle = nextAngle; |
1302 foundDone = nextSegment->done(nextAngle); | 1310 foundDone = nextSegment->done(nextAngle); |
1303 } | 1311 } |
1304 } | 1312 } |
1305 if (nextSegment->done()) { | 1313 if (nextSegment->done()) { |
1306 continue; | 1314 continue; |
1307 } | 1315 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1379 } while (true); | 1387 } while (true); |
1380 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); | 1388 SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); |
1381 return other; | 1389 return other; |
1382 } | 1390 } |
1383 SkTDArray<SkOpAngle> angles; | 1391 SkTDArray<SkOpAngle> angles; |
1384 SkASSERT(startIndex - endIndex != 0); | 1392 SkASSERT(startIndex - endIndex != 0); |
1385 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); | 1393 SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); |
1386 addTwoAngles(startIndex, end, &angles); | 1394 addTwoAngles(startIndex, end, &angles); |
1387 buildAngles(end, &angles, false); | 1395 buildAngles(end, &angles, false); |
1388 SkTDArray<SkOpAngle*> sorted; | 1396 SkTDArray<SkOpAngle*> sorted; |
1389 bool sortable = SortAngles(angles, &sorted); | 1397 bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_Sort
AngleKind); |
1390 if (!sortable) { | 1398 if (!sortable) { |
1391 *unsortable = true; | 1399 *unsortable = true; |
1392 #if DEBUG_SORT | 1400 #if DEBUG_SORT |
1393 debugShowSort(__FUNCTION__, sorted, findStartingEdge(sorted, startIndex,
end), 0, 0); | 1401 debugShowSort(__FUNCTION__, sorted, findStartingEdge(sorted, startIndex,
end), 0, 0); |
1394 #endif | 1402 #endif |
1395 return NULL; | 1403 return NULL; |
1396 } | 1404 } |
1397 int angleCount = angles.count(); | 1405 int angleCount = angles.count(); |
1398 int firstIndex = findStartingEdge(sorted, startIndex, end); | 1406 int firstIndex = findStartingEdge(sorted, startIndex, end); |
1399 SkASSERT(firstIndex >= 0); | 1407 SkASSERT(firstIndex >= 0); |
1400 #if DEBUG_SORT | 1408 #if DEBUG_SORT |
1401 debugShowSort(__FUNCTION__, sorted, firstIndex, 0, 0); | 1409 debugShowSort(__FUNCTION__, sorted, firstIndex, 0, 0); |
1402 #endif | 1410 #endif |
1403 SkASSERT(sorted[firstIndex]->segment() == this); | 1411 SkASSERT(sorted[firstIndex]->segment() == this); |
1404 int nextIndex = firstIndex + 1; | 1412 int nextIndex = firstIndex + 1; |
1405 int lastIndex = firstIndex != 0 ? firstIndex : angleCount; | 1413 int lastIndex = firstIndex != 0 ? firstIndex : angleCount; |
1406 const SkOpAngle* foundAngle = NULL; | 1414 const SkOpAngle* foundAngle = NULL; |
1407 bool foundDone = false; | 1415 bool foundDone = false; |
1408 SkOpSegment* nextSegment; | 1416 SkOpSegment* nextSegment; |
1409 int activeCount = 0; | 1417 int activeCount = 0; |
1410 do { | 1418 do { |
1411 SkASSERT(nextIndex != firstIndex); | 1419 SkASSERT(nextIndex != firstIndex); |
1412 if (nextIndex == angleCount) { | 1420 if (nextIndex == angleCount) { |
1413 nextIndex = 0; | 1421 nextIndex = 0; |
1414 } | 1422 } |
1415 const SkOpAngle* nextAngle = sorted[nextIndex]; | 1423 const SkOpAngle* nextAngle = sorted[nextIndex]; |
1416 nextSegment = nextAngle->segment(); | 1424 nextSegment = nextAngle->segment(); |
1417 ++activeCount; | 1425 ++activeCount; |
1418 if (!foundAngle || (foundDone && activeCount & 1)) { | 1426 if (!foundAngle || (foundDone && activeCount & 1)) { |
1419 if (nextSegment->tiny(nextAngle)) { | 1427 if (nextSegment->isTiny(nextAngle)) { |
1420 *unsortable = true; | 1428 *unsortable = true; |
1421 return NULL; | 1429 return NULL; |
1422 } | 1430 } |
1423 foundAngle = nextAngle; | 1431 foundAngle = nextAngle; |
1424 foundDone = nextSegment->done(nextAngle); | 1432 foundDone = nextSegment->done(nextAngle); |
1425 } | 1433 } |
1426 if (nextSegment->done()) { | 1434 if (nextSegment->done()) { |
1427 continue; | 1435 continue; |
1428 } | 1436 } |
1429 } while (++nextIndex != lastIndex); | 1437 } while (++nextIndex != lastIndex); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1621 end = nextSpan(firstT, step); | 1629 end = nextSpan(firstT, step); |
1622 SkASSERT(end != -1); | 1630 SkASSERT(end != -1); |
1623 } | 1631 } |
1624 // if the topmost T is not on end, or is three-way or more, find left | 1632 // if the topmost T is not on end, or is three-way or more, find left |
1625 // look for left-ness from tLeft to firstT (matching y of other) | 1633 // look for left-ness from tLeft to firstT (matching y of other) |
1626 SkTDArray<SkOpAngle> angles; | 1634 SkTDArray<SkOpAngle> angles; |
1627 SkASSERT(firstT - end != 0); | 1635 SkASSERT(firstT - end != 0); |
1628 addTwoAngles(end, firstT, &angles); | 1636 addTwoAngles(end, firstT, &angles); |
1629 buildAngles(firstT, &angles, true); | 1637 buildAngles(firstT, &angles, true); |
1630 SkTDArray<SkOpAngle*> sorted; | 1638 SkTDArray<SkOpAngle*> sorted; |
1631 bool sortable = SortAngles(angles, &sorted); | 1639 bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMayBeUnordered_Sor
tAngleKind); |
1632 int first = SK_MaxS32; | 1640 int first = SK_MaxS32; |
1633 SkScalar top = SK_ScalarMax; | 1641 SkScalar top = SK_ScalarMax; |
1634 int count = sorted.count(); | 1642 int count = sorted.count(); |
1635 for (int index = 0; index < count; ++index) { | 1643 for (int index = 0; index < count; ++index) { |
1636 const SkOpAngle* angle = sorted[index]; | 1644 const SkOpAngle* angle = sorted[index]; |
1637 SkOpSegment* next = angle->segment(); | 1645 SkOpSegment* next = angle->segment(); |
1638 SkPathOpsBounds bounds; | 1646 SkPathOpsBounds bounds; |
1639 next->subDivideBounds(angle->end(), angle->start(), &bounds); | 1647 next->subDivideBounds(angle->end(), angle->start(), &bounds); |
1640 if (approximately_greater(top, bounds.fTop)) { | 1648 if (approximately_greater(top, bounds.fTop)) { |
1641 top = bounds.fTop; | 1649 top = bounds.fTop; |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2074 #endif | 2082 #endif |
2075 span.fOppSum = oppWinding; | 2083 span.fOppSum = oppWinding; |
2076 return &span; | 2084 return &span; |
2077 } | 2085 } |
2078 | 2086 |
2079 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of
-polygon-points-are-in-clockwise-order | 2087 // 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 { | 2088 bool SkOpSegment::clockwise(int tStart, int tEnd) const { |
2081 SkASSERT(fVerb != SkPath::kLine_Verb); | 2089 SkASSERT(fVerb != SkPath::kLine_Verb); |
2082 SkPoint edge[4]; | 2090 SkPoint edge[4]; |
2083 subDivide(tStart, tEnd, edge); | 2091 subDivide(tStart, tEnd, edge); |
2084 double sum = (edge[0].fX - edge[SkPathOpsVerbToPoints(fVerb)].fX) * (edge[0]
.fY + edge[SkPathOpsVerbToPoints(fVerb)].fY); | 2092 int points = SkPathOpsVerbToPoints(fVerb); |
| 2093 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY)
; |
2085 if (fVerb == SkPath::kCubic_Verb) { | 2094 if (fVerb == SkPath::kCubic_Verb) { |
2086 SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY); | 2095 SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY); |
2087 if (edge[1].fY < lesser && edge[2].fY < lesser) { | 2096 if (edge[1].fY < lesser && edge[2].fY < lesser) { |
2088 SkDLine tangent1 = {{ {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1]
.fY} }}; | 2097 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} }}; | 2098 SkDLine tangent2 = {{ {edge[2].fX, edge[2].fY}, {edge[3].fX, edge[3]
.fY} }}; |
2090 if (SkIntersections::Test(tangent1, tangent2)) { | 2099 if (SkIntersections::Test(tangent1, tangent2)) { |
2091 SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT); | 2100 SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT); |
2092 sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY); | 2101 sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY); |
2093 sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY); | 2102 sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY); |
2094 return sum <= 0; | 2103 return sum <= 0; |
2095 } | 2104 } |
2096 } | 2105 } |
2097 } | 2106 } |
2098 for (int idx = 0; idx < SkPathOpsVerbToPoints(fVerb); ++idx){ | 2107 for (int idx = 0; idx < points; ++idx){ |
2099 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx]
.fY); | 2108 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx]
.fY); |
2100 } | 2109 } |
2101 return sum <= 0; | 2110 return sum <= 0; |
2102 } | 2111 } |
2103 | 2112 |
2104 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const { | 2113 bool SkOpSegment::monotonicInY(int tStart, int tEnd) const { |
2105 if (fVerb == SkPath::kLine_Verb) { | 2114 if (fVerb == SkPath::kLine_Verb) { |
2106 return false; | 2115 return false; |
2107 } | 2116 } |
2108 if (fVerb == SkPath::kQuad_Verb) { | 2117 if (fVerb == SkPath::kQuad_Verb) { |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2327 *sumWinding = *sumMiWinding -= deltaSum; | 2336 *sumWinding = *sumMiWinding -= deltaSum; |
2328 *oppMaxWinding = *sumSuWinding; | 2337 *oppMaxWinding = *sumSuWinding; |
2329 *oppSumWinding = *sumSuWinding -= oppDeltaSum; | 2338 *oppSumWinding = *sumSuWinding -= oppDeltaSum; |
2330 } | 2339 } |
2331 } | 2340 } |
2332 | 2341 |
2333 // This marks all spans unsortable so that this info is available for early | 2342 // This marks all spans unsortable so that this info is available for early |
2334 // exclusion in find top and others. This could be optimized to only mark | 2343 // exclusion in find top and others. This could be optimized to only mark |
2335 // adjacent spans that unsortable. However, this makes it difficult to later | 2344 // adjacent spans that unsortable. However, this makes it difficult to later |
2336 // determine starting points for edge detection in find top and the like. | 2345 // determine starting points for edge detection in find top and the like. |
2337 bool SkOpSegment::SortAngles(const SkTDArray<SkOpAngle>& angles, | 2346 bool SkOpSegment::SortAngles(const SkTDArray<SkOpAngle>& angles, SkTDArray<SkOpA
ngle*>* angleList, |
2338 SkTDArray<SkOpAngle*>* angleList) { | 2347 SortAngleKind orderKind) { |
2339 bool sortable = true; | 2348 bool sortable = true; |
2340 int angleCount = angles.count(); | 2349 int angleCount = angles.count(); |
2341 int angleIndex; | 2350 int angleIndex; |
2342 angleList->setReserve(angleCount); | 2351 angleList->setReserve(angleCount); |
2343 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { | 2352 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { |
2344 const SkOpAngle& angle = angles[angleIndex]; | 2353 const SkOpAngle& angle = angles[angleIndex]; |
2345 *angleList->append() = const_cast<SkOpAngle*>(&angle); | 2354 *angleList->append() = const_cast<SkOpAngle*>(&angle); |
2346 sortable &= !angle.unsortable(); | 2355 #if DEBUG_ANGLE |
| 2356 (*(angleList->end() - 1))->setID(angleIndex); |
| 2357 #endif |
| 2358 sortable &= !(angle.unsortable() || (orderKind == kMustBeOrdered_SortAng
leKind |
| 2359 && angle.unorderable())); |
2347 } | 2360 } |
2348 if (sortable) { | 2361 if (sortable) { |
2349 SkTQSort<SkOpAngle>(angleList->begin(), angleList->end() - 1); | 2362 SkTQSort<SkOpAngle>(angleList->begin(), angleList->end() - 1); |
2350 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { | 2363 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { |
2351 if (angles[angleIndex].unsortable()) { | 2364 if (angles[angleIndex].unsortable() || (orderKind == kMustBeOrdered_
SortAngleKind |
| 2365 && angles[angleIndex].unorderable())) { |
2352 sortable = false; | 2366 sortable = false; |
2353 break; | 2367 break; |
2354 } | 2368 } |
2355 } | 2369 } |
2356 } | 2370 } |
2357 if (!sortable) { | 2371 if (!sortable) { |
2358 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { | 2372 for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) { |
2359 const SkOpAngle& angle = angles[angleIndex]; | 2373 const SkOpAngle& angle = angles[angleIndex]; |
2360 angle.segment()->markUnsortable(angle.start(), angle.end()); | 2374 angle.segment()->markUnsortable(angle.start(), angle.end()); |
2361 } | 2375 } |
2362 } | 2376 } |
2363 return sortable; | 2377 return sortable; |
2364 } | 2378 } |
2365 | 2379 |
2366 void SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { | 2380 // return true if midpoints were computed |
| 2381 bool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { |
| 2382 SkASSERT(start != end); |
2367 edge[0] = fTs[start].fPt; | 2383 edge[0] = fTs[start].fPt; |
2368 edge[SkPathOpsVerbToPoints(fVerb)] = fTs[end].fPt; | 2384 int points = SkPathOpsVerbToPoints(fVerb); |
2369 if (fVerb == SkPath::kQuad_Verb || fVerb == SkPath::kCubic_Verb) { | 2385 edge[points] = fTs[end].fPt; |
2370 SkDPoint sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[SkPathOpsVerbToPoint
s(fVerb)].fX, edge[SkPathOpsVerbToPoints(fVerb)].fY }}; | 2386 if (fVerb == SkPath::kLine_Verb) { |
| 2387 return false; |
| 2388 } |
| 2389 double startT = fTs[start].fT; |
| 2390 double endT = fTs[end].fT; |
| 2391 if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { |
| 2392 // don't compute midpoints if we already have them |
2371 if (fVerb == SkPath::kQuad_Verb) { | 2393 if (fVerb == SkPath::kQuad_Verb) { |
2372 edge[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], fTs[start].fT, | 2394 edge[1] = fPts[1]; |
2373 fTs[end].fT).asSkPoint(); | 2395 return false; |
2374 } else { | |
2375 SkDCubic::SubDivide(fPts, sub[0], sub[1], fTs[start].fT, fTs[end].fT
, sub); | |
2376 edge[1] = sub[0].asSkPoint(); | |
2377 edge[2] = sub[1].asSkPoint(); | |
2378 } | 2396 } |
| 2397 SkASSERT(fVerb == SkPath::kCubic_Verb); |
| 2398 if (start < end) { |
| 2399 edge[1] = fPts[1]; |
| 2400 edge[2] = fPts[2]; |
| 2401 return false; |
| 2402 } |
| 2403 edge[1] = fPts[2]; |
| 2404 edge[2] = fPts[1]; |
| 2405 return false; |
2379 } | 2406 } |
| 2407 const SkDPoint sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[points].fX, edge[p
oints].fY }}; |
| 2408 if (fVerb == SkPath::kQuad_Verb) { |
| 2409 edge[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], startT, endT).asSkPoi
nt(); |
| 2410 } else { |
| 2411 SkASSERT(fVerb == SkPath::kCubic_Verb); |
| 2412 SkDPoint ctrl[2]; |
| 2413 SkDCubic::SubDivide(fPts, sub[0], sub[1], startT, endT, ctrl); |
| 2414 edge[1] = ctrl[0].asSkPoint(); |
| 2415 edge[2] = ctrl[1].asSkPoint(); |
| 2416 } |
| 2417 return true; |
| 2418 } |
| 2419 |
| 2420 // return true if midpoints were computed |
| 2421 bool SkOpSegment::subDivide(int start, int end, SkDCubic* result) const { |
| 2422 SkASSERT(start != end); |
| 2423 (*result)[0].set(fTs[start].fPt); |
| 2424 int points = SkPathOpsVerbToPoints(fVerb); |
| 2425 (*result)[points].set(fTs[end].fPt); |
| 2426 if (fVerb == SkPath::kLine_Verb) { |
| 2427 return false; |
| 2428 } |
| 2429 double startT = fTs[start].fT; |
| 2430 double endT = fTs[end].fT; |
| 2431 if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { |
| 2432 // don't compute midpoints if we already have them |
| 2433 if (fVerb == SkPath::kQuad_Verb) { |
| 2434 (*result)[1].set(fPts[1]); |
| 2435 return false; |
| 2436 } |
| 2437 SkASSERT(fVerb == SkPath::kCubic_Verb); |
| 2438 if (start < end) { |
| 2439 (*result)[1].set(fPts[1]); |
| 2440 (*result)[2].set(fPts[2]); |
| 2441 return false; |
| 2442 } |
| 2443 (*result)[1].set(fPts[2]); |
| 2444 (*result)[2].set(fPts[1]); |
| 2445 return false; |
| 2446 } |
| 2447 if (fVerb == SkPath::kQuad_Verb) { |
| 2448 (*result)[1] = SkDQuad::SubDivide(fPts, (*result)[0], (*result)[2], star
tT, endT); |
| 2449 } else { |
| 2450 SkASSERT(fVerb == SkPath::kCubic_Verb); |
| 2451 SkDCubic::SubDivide(fPts, (*result)[0], (*result)[3], startT, endT, &(*r
esult)[1]); |
| 2452 } |
| 2453 return true; |
2380 } | 2454 } |
2381 | 2455 |
2382 void SkOpSegment::subDivideBounds(int start, int end, SkPathOpsBounds* bounds) c
onst { | 2456 void SkOpSegment::subDivideBounds(int start, int end, SkPathOpsBounds* bounds) c
onst { |
2383 SkPoint edge[4]; | 2457 SkPoint edge[4]; |
2384 subDivide(start, end, edge); | 2458 subDivide(start, end, edge); |
2385 (bounds->*SetCurveBounds[SkPathOpsVerbToPoints(fVerb)])(edge); | 2459 (bounds->*SetCurveBounds[SkPathOpsVerbToPoints(fVerb)])(edge); |
2386 } | 2460 } |
2387 | 2461 |
2388 bool SkOpSegment::tiny(const SkOpAngle* angle) const { | 2462 bool SkOpSegment::isTiny(const SkOpAngle* angle) const { |
2389 int start = angle->start(); | 2463 int start = angle->start(); |
2390 int end = angle->end(); | 2464 int end = angle->end(); |
2391 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; | 2465 const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; |
2392 return mSpan.fTiny; | 2466 return mSpan.fTiny; |
2393 } | 2467 } |
2394 | 2468 |
| 2469 bool SkOpSegment::isTiny(int index) const { |
| 2470 return fTs[index].fTiny; |
| 2471 } |
| 2472 |
2395 void SkOpSegment::TrackOutside(SkTDArray<double>* outsideTs, double end, double
start) { | 2473 void SkOpSegment::TrackOutside(SkTDArray<double>* outsideTs, double end, double
start) { |
2396 int outCount = outsideTs->count(); | 2474 int outCount = outsideTs->count(); |
2397 if (outCount == 0 || !approximately_negative(end - (*outsideTs)[outCount - 2
])) { | 2475 if (outCount == 0 || !approximately_negative(end - (*outsideTs)[outCount - 2
])) { |
2398 *outsideTs->append() = end; | 2476 *outsideTs->append() = end; |
2399 *outsideTs->append() = start; | 2477 *outsideTs->append() = start; |
2400 } | 2478 } |
2401 } | 2479 } |
2402 | 2480 |
2403 void SkOpSegment::undoneSpan(int* start, int* end) { | 2481 void SkOpSegment::undoneSpan(int* start, int* end) { |
2404 size_t tCount = fTs.count(); | 2482 size_t tCount = fTs.count(); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2728 lastSum = windSum; | 2806 lastSum = windSum; |
2729 windSum -= segment.spanSign(&angle); | 2807 windSum -= segment.spanSign(&angle); |
2730 if (oppoSign) { | 2808 if (oppoSign) { |
2731 oppLastSum = oppWindSum; | 2809 oppLastSum = oppWindSum; |
2732 oppWindSum -= oppoSign; | 2810 oppWindSum -= oppoSign; |
2733 } | 2811 } |
2734 } | 2812 } |
2735 } | 2813 } |
2736 SkDebugf("%s [%d] %s", __FUNCTION__, index, | 2814 SkDebugf("%s [%d] %s", __FUNCTION__, index, |
2737 angle.unsortable() ? "*** UNSORTABLE *** " : ""); | 2815 angle.unsortable() ? "*** UNSORTABLE *** " : ""); |
2738 #if COMPACT_DEBUG_SORT | 2816 #if DEBUG_SORT_COMPACT |
2739 SkDebugf("id=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)", | 2817 SkDebugf("id=%d %s start=%d (%1.9g,%1.9g) end=%d (%1.9g,%1.9g)", |
2740 segment.fID, kLVerbStr[SkPathOpsVerbToPoints(segment.fVerb)], | 2818 segment.fID, kLVerbStr[SkPathOpsVerbToPoints(segment.fVerb)], |
2741 start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end, | 2819 start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end, |
2742 segment.xAtT(&eSpan), segment.yAtT(&eSpan)); | 2820 segment.xAtT(&eSpan), segment.yAtT(&eSpan)); |
2743 #else | 2821 #else |
2744 switch (segment.fVerb) { | 2822 switch (segment.fVerb) { |
2745 case SkPath::kLine_Verb: | 2823 case SkPath::kLine_Verb: |
2746 SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts)); | 2824 SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts)); |
2747 break; | 2825 break; |
2748 case SkPath::kQuad_Verb: | 2826 case SkPath::kQuad_Verb: |
2749 SkDebugf(QUAD_DEBUG_STR, QUAD_DEBUG_DATA(segment.fPts)); | 2827 SkDebugf(QUAD_DEBUG_STR, QUAD_DEBUG_DATA(segment.fPts)); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2820 sum += fTs[i].fWindValue; | 2898 sum += fTs[i].fWindValue; |
2821 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); | 2899 slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue); |
2822 sum += fTs[i].fOppValue; | 2900 sum += fTs[i].fOppValue; |
2823 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); | 2901 slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue); |
2824 } | 2902 } |
2825 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, | 2903 SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begi
n(), slotCount, |
2826 slots.begin() + slotCount); | 2904 slots.begin() + slotCount); |
2827 return sum; | 2905 return sum; |
2828 } | 2906 } |
2829 #endif | 2907 #endif |
OLD | NEW |