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

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

Issue 1394503003: fix some pathops bugs found in 1M skps (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: init to avoid warning Created 5 years, 2 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
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkOpSpan.h » ('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 "SkOpCoincidence.h" 7 #include "SkOpCoincidence.h"
8 #include "SkOpContour.h" 8 #include "SkOpContour.h"
9 #include "SkOpSegment.h" 9 #include "SkOpSegment.h"
10 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 } 426 }
427 activePrior = active; 427 activePrior = active;
428 prior = span; 428 prior = span;
429 spanBase = next; 429 spanBase = next;
430 } 430 }
431 if (activePrior && !fTail.simple()) { 431 if (activePrior && !fTail.simple()) {
432 addEndSpan(allocator); 432 addEndSpan(allocator);
433 } 433 }
434 } 434 }
435 435
436 void SkOpSegment::checkAngleCoin(SkOpCoincidence* coincidences, SkChunkAlloc* al locator) {
437 SkOpSpanBase* base = &fHead;
438 SkOpSpan* span;
439 do {
440 SkOpAngle* angle = base->fromAngle();
441 if (angle && angle->fCheckCoincidence) {
442 angle->checkNearCoincidence();
443 }
444 if (base->final()) {
445 break;
446 }
447 span = base->upCast();
448 angle = span->toAngle();
449 if (angle && angle->fCheckCoincidence) {
450 angle->checkNearCoincidence();
451 }
452 } while ((base = span->next()));
453 }
454
455 bool SkOpSegment::collapsed() const { 436 bool SkOpSegment::collapsed() const {
456 return fVerb == SkPath::kLine_Verb && fHead.pt() == fTail.pt(); 437 return fVerb == SkPath::kLine_Verb && fHead.pt() == fTail.pt();
457 } 438 }
458 439
459 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle , 440 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle ,
460 SkOpAngle::IncludeType includeType) { 441 SkOpAngle::IncludeType includeType) {
461 SkOpSegment* baseSegment = baseAngle->segment(); 442 SkOpSegment* baseSegment = baseAngle->segment();
462 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 443 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle);
463 int sumSuWinding; 444 int sumSuWinding;
464 bool binary = includeType >= SkOpAngle::kBinarySingle; 445 bool binary = includeType >= SkOpAngle::kBinarySingle;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 } 567 }
587 568
588 void SkOpSegment::detach(const SkOpSpan* span) { 569 void SkOpSegment::detach(const SkOpSpan* span) {
589 if (span->done()) { 570 if (span->done()) {
590 --fDoneCount; 571 --fDoneCount;
591 } 572 }
592 --fCount; 573 --fCount;
593 SkASSERT(fCount >= fDoneCount); 574 SkASSERT(fCount >= fDoneCount);
594 } 575 }
595 576
596 double SkOpSegment::distSq(double t, SkOpAngle* oppAngle) { 577 double SkOpSegment::distSq(double t, const SkOpAngle* oppAngle) const {
597 SkDPoint testPt = this->dPtAtT(t); 578 SkDPoint testPt = this->dPtAtT(t);
598 SkDLine testPerp = {{ testPt, testPt }}; 579 SkDLine testPerp = {{ testPt, testPt }};
599 SkDVector slope = this->dSlopeAtT(t); 580 SkDVector slope = this->dSlopeAtT(t);
600 testPerp[1].fX += slope.fY; 581 testPerp[1].fX += slope.fY;
601 testPerp[1].fY -= slope.fX; 582 testPerp[1].fY -= slope.fX;
602 SkIntersections i; 583 SkIntersections i;
603 SkOpSegment* oppSegment = oppAngle->segment(); 584 const SkOpSegment* oppSegment = oppAngle->segment();
604 (*CurveIntersectRay[oppSegment->verb()])(oppSegment->pts(), oppSegment->weig ht(), testPerp, &i); 585 (*CurveIntersectRay[oppSegment->verb()])(oppSegment->pts(), oppSegment->weig ht(), testPerp, &i);
605 double closestDistSq = SK_ScalarInfinity; 586 double closestDistSq = SK_ScalarInfinity;
606 for (int index = 0; index < i.used(); ++index) { 587 for (int index = 0; index < i.used(); ++index) {
607 if (!between(oppAngle->start()->t(), i[0][index], oppAngle->end()->t())) { 588 if (!between(oppAngle->start()->t(), i[0][index], oppAngle->end()->t())) {
608 continue; 589 continue;
609 } 590 }
610 double testDistSq = testPt.distanceSquared(i.pt(index)); 591 double testDistSq = testPt.distanceSquared(i.pt(index));
611 if (closestDistSq > testDistSq) { 592 if (closestDistSq > testDistSq) {
612 closestDistSq = testDistSq; 593 closestDistSq = testDistSq;
613 } 594 }
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 SkOpSpan* prior = nullptr; 1194 SkOpSpan* prior = nullptr;
1214 SkOpSpanBase* spanBase = &fHead; 1195 SkOpSpanBase* spanBase = &fHead;
1215 do { 1196 do {
1216 SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 1197 SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT;
1217 SkASSERT(ptT->span() == spanBase); 1198 SkASSERT(ptT->span() == spanBase);
1218 while ((ptT = ptT->next()) != spanStopPtT) { 1199 while ((ptT = ptT->next()) != spanStopPtT) {
1219 if (ptT->deleted()) { 1200 if (ptT->deleted()) {
1220 continue; 1201 continue;
1221 } 1202 }
1222 SkOpSegment* opp = ptT->span()->segment(); 1203 SkOpSegment* opp = ptT->span()->segment();
1223 if (opp->verb() == SkPath::kLine_Verb) { 1204 // if (opp->verb() == SkPath::kLine_Verb) {
1224 continue; 1205 // continue;
1225 } 1206 // }
1226 if (opp->done()) { 1207 if (opp->done()) {
1227 continue; 1208 continue;
1228 } 1209 }
1229 // when opp is encounted the 1st time, continue; on 2nd encounter, l ook for coincidence 1210 // when opp is encounted the 1st time, continue; on 2nd encounter, l ook for coincidence
1230 if (!opp->visited()) { 1211 if (!opp->visited()) {
1231 continue; 1212 continue;
1232 } 1213 }
1233 if (spanBase == &fHead) { 1214 if (spanBase == &fHead) {
1234 continue; 1215 continue;
1235 } 1216 }
1236 SkOpSpan* span = spanBase->upCastable(); 1217 SkOpSpan* span = spanBase->upCastable();
1237 // FIXME?: this assumes that if the opposite segment is coincident t hen no more 1218 // FIXME?: this assumes that if the opposite segment is coincident t hen no more
1238 // coincidence needs to be detected. This may not be true. 1219 // coincidence needs to be detected. This may not be true.
1239 if (span && span->containsCoincidence(opp)) { 1220 if (span && span->containsCoincidence(opp)) {
1240 continue; 1221 continue;
1241 } 1222 }
1223 if (spanBase->segment() == opp) {
1224 continue;
1225 }
1242 if (spanBase->containsCoinEnd(opp)) { 1226 if (spanBase->containsCoinEnd(opp)) {
1243 continue; 1227 continue;
1244 } 1228 }
1245 SkOpPtT* priorPtT = nullptr, * priorStopPtT; 1229 SkOpPtT* priorPtT = nullptr, * priorStopPtT;
1246 // find prior span containing opp segment 1230 // find prior span containing opp segment
1247 SkOpSegment* priorOpp = nullptr; 1231 SkOpSegment* priorOpp = nullptr;
1248 SkOpSpan* priorTest = spanBase->prev(); 1232 SkOpSpan* priorTest = spanBase->prev();
1249 while (!priorOpp && priorTest) { 1233 while (!priorOpp && priorTest) {
1250 priorStopPtT = priorPtT = priorTest->ptT(); 1234 priorStopPtT = priorPtT = priorTest->ptT();
1251 while ((priorPtT = priorPtT->next()) != priorStopPtT) { 1235 while ((priorPtT = priorPtT->next()) != priorStopPtT) {
1252 if (priorPtT->deleted()) { 1236 if (priorPtT->deleted()) {
1253 continue; 1237 continue;
1254 } 1238 }
1255 SkOpSegment* segment = priorPtT->span()->segment(); 1239 SkOpSegment* segment = priorPtT->span()->segment();
1256 if (segment == opp) { 1240 if (segment == opp) {
1257 prior = priorTest; 1241 prior = priorTest;
1258 priorOpp = opp; 1242 priorOpp = opp;
1259 break; 1243 break;
1260 } 1244 }
1261 } 1245 }
1262 priorTest = priorTest->prev(); 1246 priorTest = priorTest->prev();
1263 } 1247 }
1264 if (!priorOpp) { 1248 if (!priorOpp) {
1265 continue; 1249 continue;
1266 } 1250 }
1251 if (priorPtT == ptT) {
1252 continue;
1253 }
1267 SkOpPtT* oppStart = prior->ptT(); 1254 SkOpPtT* oppStart = prior->ptT();
1268 SkOpPtT* oppEnd = spanBase->ptT(); 1255 SkOpPtT* oppEnd = spanBase->ptT();
1269 bool swapped = priorPtT->fT > ptT->fT; 1256 bool swapped = priorPtT->fT > ptT->fT;
1270 if (swapped) { 1257 if (swapped) {
1271 SkTSwap(priorPtT, ptT); 1258 SkTSwap(priorPtT, ptT);
1272 SkTSwap(oppStart, oppEnd); 1259 SkTSwap(oppStart, oppEnd);
1273 } 1260 }
1274 bool flipped = oppStart->fT > oppEnd->fT; 1261 bool flipped = oppStart->fT > oppEnd->fT;
1275 bool coincident; 1262 bool coincident = false;
1276 if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped) ) { 1263 if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped) ) {
1277 goto swapBack; 1264 goto swapBack;
1278 } 1265 }
1279 coincident = testForCoincidence(priorPtT, ptT, prior, spanBase, opp, 5000); 1266 if (opp->verb() == SkPath::kLine_Verb) {
1267 coincident = (SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppSta rt->fPt) ||
1268 SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppEnd->fPt) ) &&
1269 (SkDPoint::ApproximatelyEqual(ptT->fPt, oppStart->fPt) | |
1270 SkDPoint::ApproximatelyEqual(ptT->fPt, oppEnd->fPt));
1271 }
1272 if (!coincident) {
1273 coincident = testForCoincidence(priorPtT, ptT, prior, spanBase, opp, 5000);
1274 }
1280 if (coincident) { 1275 if (coincident) {
1281 // mark coincidence 1276 // mark coincidence
1282 if (!coincidences->extend(priorPtT, ptT, oppStart, oppEnd) 1277 if (!coincidences->extend(priorPtT, ptT, oppStart, oppEnd)
1283 && !coincidences->extend(oppStart, oppEnd, priorPtT, ptT )) { 1278 && !coincidences->extend(oppStart, oppEnd, priorPtT, ptT )) {
1284 coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator ); 1279 coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator );
1285 } 1280 }
1286 clear_visited(&fHead); 1281 clear_visited(&fHead);
1287 return true; 1282 return true;
1288 } 1283 }
1289 swapBack: 1284 swapBack:
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
1774 int absOut = SkTAbs(outerWinding); 1769 int absOut = SkTAbs(outerWinding);
1775 int absIn = SkTAbs(innerWinding); 1770 int absIn = SkTAbs(innerWinding);
1776 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; 1771 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
1777 return result; 1772 return result;
1778 } 1773 }
1779 1774
1780 int SkOpSegment::windSum(const SkOpAngle* angle) const { 1775 int SkOpSegment::windSum(const SkOpAngle* angle) const {
1781 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); 1776 const SkOpSpan* minSpan = angle->start()->starter(angle->end());
1782 return minSpan->windSum(); 1777 return minSpan->windSum();
1783 } 1778 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkOpSpan.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698