Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: src/pathops/SkOpSegment.cpp

Issue 15338003: path ops -- rewrite angle sort (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698