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

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

Issue 2426753002: break ambiguous angle sorting loop (Closed)
Patch Set: fix linux warning Created 4 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/SkOpAngle.h ('k') | src/pathops/SkOpContour.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 "SkOpAngle.h" 7 #include "SkOpAngle.h"
8 #include "SkOpSegment.h" 8 #include "SkOpSegment.h"
9 #include "SkPathOpsCurve.h" 9 #include "SkPathOpsCurve.h"
10 #include "SkTSort.h" 10 #include "SkTSort.h"
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 return false; 313 return false;
314 } 314 }
315 SkOpSpanBase* saveEnd = fEnd; 315 SkOpSpanBase* saveEnd = fEnd;
316 fComputedEnd = fEnd = computedEnd; 316 fComputedEnd = fEnd = computedEnd;
317 setSpans(); 317 setSpans();
318 setSector(); 318 setSector();
319 fEnd = saveEnd; 319 fEnd = saveEnd;
320 return !fUnorderable; 320 return !fUnorderable;
321 } 321 }
322 322
323 int SkOpAngle::convexHullOverlaps(const SkOpAngle* rh) const { 323 int SkOpAngle::convexHullOverlaps(const SkOpAngle* rh) {
324 const SkDVector* sweep = this->fPart.fSweep; 324 const SkDVector* sweep = this->fPart.fSweep;
325 const SkDVector* tweep = rh->fPart.fSweep; 325 const SkDVector* tweep = rh->fPart.fSweep;
326 double s0xs1 = sweep[0].crossCheck(sweep[1]); 326 double s0xs1 = sweep[0].crossCheck(sweep[1]);
327 double s0xt0 = sweep[0].crossCheck(tweep[0]); 327 double s0xt0 = sweep[0].crossCheck(tweep[0]);
328 double s1xt0 = sweep[1].crossCheck(tweep[0]); 328 double s1xt0 = sweep[1].crossCheck(tweep[0]);
329 bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0 ; 329 bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0 ;
330 double s0xt1 = sweep[0].crossCheck(tweep[1]); 330 double s0xt1 = sweep[0].crossCheck(tweep[1]);
331 double s1xt1 = sweep[1].crossCheck(tweep[1]); 331 double s1xt1 = sweep[1].crossCheck(tweep[1]);
332 tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0; 332 tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0;
333 double t0xt1 = tweep[0].crossCheck(tweep[1]); 333 double t0xt1 = tweep[0].crossCheck(tweep[1]);
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 return sector; 586 return sector;
587 } 587 }
588 588
589 SkOpGlobalState* SkOpAngle::globalState() const { 589 SkOpGlobalState* SkOpAngle::globalState() const {
590 return this->segment()->globalState(); 590 return this->segment()->globalState();
591 } 591 }
592 592
593 593
594 // OPTIMIZE: if this loops to only one other angle, after first compare fails, i nsert on other side 594 // OPTIMIZE: if this loops to only one other angle, after first compare fails, i nsert on other side
595 // OPTIMIZE: return where insertion succeeded. Then, start next insertion on opp osite side 595 // OPTIMIZE: return where insertion succeeded. Then, start next insertion on opp osite side
596 void SkOpAngle::insert(SkOpAngle* angle) { 596 bool SkOpAngle::insert(SkOpAngle* angle) {
597 if (angle->fNext) { 597 if (angle->fNext) {
598 if (loopCount() >= angle->loopCount()) { 598 if (loopCount() >= angle->loopCount()) {
599 if (!merge(angle)) { 599 if (!merge(angle)) {
600 return; 600 return true;
601 } 601 }
602 } else if (fNext) { 602 } else if (fNext) {
603 if (!angle->merge(this)) { 603 if (!angle->merge(this)) {
604 return; 604 return true;
605 } 605 }
606 } else { 606 } else {
607 angle->insert(this); 607 angle->insert(this);
608 } 608 }
609 return; 609 return true;
610 } 610 }
611 bool singleton = nullptr == fNext; 611 bool singleton = nullptr == fNext;
612 if (singleton) { 612 if (singleton) {
613 fNext = this; 613 fNext = this;
614 } 614 }
615 SkOpAngle* next = fNext; 615 SkOpAngle* next = fNext;
616 if (next->fNext == this) { 616 if (next->fNext == this) {
617 if (singleton || angle->after(this)) { 617 if (singleton || angle->after(this)) {
618 this->fNext = angle; 618 this->fNext = angle;
619 angle->fNext = next; 619 angle->fNext = next;
620 } else { 620 } else {
621 next->fNext = angle; 621 next->fNext = angle;
622 angle->fNext = this; 622 angle->fNext = this;
623 } 623 }
624 debugValidateNext(); 624 debugValidateNext();
625 return; 625 return true;
626 } 626 }
627 SkOpAngle* last = this; 627 SkOpAngle* last = this;
628 bool flipAmbiguity = false;
628 do { 629 do {
629 SkASSERT(last->fNext == next); 630 SkASSERT(last->fNext == next);
630 if (angle->after(last)) { 631 if (angle->after(last) ^ (angle->tangentsAmbiguous() & flipAmbiguity)) {
631 last->fNext = angle; 632 last->fNext = angle;
632 angle->fNext = next; 633 angle->fNext = next;
633 debugValidateNext(); 634 debugValidateNext();
634 return; 635 return true;
635 } 636 }
636 last = next; 637 last = next;
638 if (last == this) {
639 FAIL_IF(flipAmbiguity);
640 // We're in a loop. If a sort was ambiguous, flip it to end the loop .
641 flipAmbiguity = true;
642 }
637 next = next->fNext; 643 next = next->fNext;
638 } while (true); 644 } while (true);
645 return true;
639 } 646 }
640 647
641 SkOpSpanBase* SkOpAngle::lastMarked() const { 648 SkOpSpanBase* SkOpAngle::lastMarked() const {
642 if (fLastMarked) { 649 if (fLastMarked) {
643 if (fLastMarked->chased()) { 650 if (fLastMarked->chased()) {
644 return nullptr; 651 return nullptr;
645 } 652 }
646 fLastMarked->setChased(true); 653 fLastMarked->setChased(true);
647 } 654 }
648 return fLastMarked; 655 return fLastMarked;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 815
809 SkOpSegment* SkOpAngle::segment() const { 816 SkOpSegment* SkOpAngle::segment() const {
810 return fStart->segment(); 817 return fStart->segment();
811 } 818 }
812 819
813 void SkOpAngle::set(SkOpSpanBase* start, SkOpSpanBase* end) { 820 void SkOpAngle::set(SkOpSpanBase* start, SkOpSpanBase* end) {
814 fStart = start; 821 fStart = start;
815 fComputedEnd = fEnd = end; 822 fComputedEnd = fEnd = end;
816 SkASSERT(start != end); 823 SkASSERT(start != end);
817 fNext = nullptr; 824 fNext = nullptr;
818 fComputeSector = fComputedSector = fCheckCoincidence = false; 825 fComputeSector = fComputedSector = fCheckCoincidence = fTangentsAmbiguous = false;
819 setSpans(); 826 setSpans();
820 setSector(); 827 setSector();
821 SkDEBUGCODE(fID = start ? start->globalState()->nextAngleID() : -1); 828 SkDEBUGCODE(fID = start ? start->globalState()->nextAngleID() : -1);
822 } 829 }
823 830
824 void SkOpAngle::setSpans() { 831 void SkOpAngle::setSpans() {
825 fUnorderable = false; 832 fUnorderable = false;
826 fLastMarked = nullptr; 833 fLastMarked = nullptr;
827 if (!fStart) { 834 if (!fStart) {
828 fUnorderable = true; 835 fUnorderable = true;
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 fSectorMask = (unsigned) -1 >> (31 - end + start) << start; 966 fSectorMask = (unsigned) -1 >> (31 - end + start) << start;
960 } else { 967 } else {
961 fSectorMask = (unsigned) -1 >> (31 - start) | ((unsigned) -1 << end); 968 fSectorMask = (unsigned) -1 >> (31 - start) | ((unsigned) -1 << end);
962 } 969 }
963 } 970 }
964 971
965 SkOpSpan* SkOpAngle::starter() { 972 SkOpSpan* SkOpAngle::starter() {
966 return fStart->starter(fEnd); 973 return fStart->starter(fEnd);
967 } 974 }
968 975
969 bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) const { 976 bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) {
970 if (s0xt0 == 0) { 977 if (s0xt0 == 0) {
971 return false; 978 return false;
972 } 979 }
973 // if the ctrl tangents are not nearly parallel, use them 980 // if the ctrl tangents are not nearly parallel, use them
974 // solve for opposite direction displacement scale factor == m 981 // solve for opposite direction displacement scale factor == m
975 // initial dir = v1.cross(v2) == v2.x * v1.y - v2.y * v1.x 982 // initial dir = v1.cross(v2) == v2.x * v1.y - v2.y * v1.x
976 // displacement of q1[1] : dq1 = { -m * v1.y, m * v1.x } + q1[1] 983 // displacement of q1[1] : dq1 = { -m * v1.y, m * v1.x } + q1[1]
977 // straight angle when : v2.x * (dq1.y - q1[0].y) == v2.y * (dq1.x - q1[0].x ) 984 // straight angle when : v2.x * (dq1.y - q1[0].y) == v2.y * (dq1.x - q1[0].x )
978 // v2.x * (m * v1.x + v1.y) == v2.y * (-m * v1.y + v1. x) 985 // v2.x * (m * v1.x + v1.y) == v2.y * (-m * v1.y + v1. x)
979 // - m * (v2.x * v1.x + v2.y * v1.y) == v2.x * v1.y - v2.y * v1.x 986 // - m * (v2.x * v1.x + v2.y * v1.y) == v2.x * v1.y - v2.y * v1.x
980 // m = (v2.y * v1.x - v2.x * v1.y) / (v2.x * v1.x + v2.y * v1.y) 987 // m = (v2.y * v1.x - v2.x * v1.y) / (v2.x * v1.x + v2.y * v1.y)
981 // m = v1.cross(v2) / v1.dot(v2) 988 // m = v1.cross(v2) / v1.dot(v2)
982 const SkDVector* sweep = fPart.fSweep; 989 const SkDVector* sweep = fPart.fSweep;
983 const SkDVector* tweep = rh->fPart.fSweep; 990 const SkDVector* tweep = rh->fPart.fSweep;
984 double s0dt0 = sweep[0].dot(tweep[0]); 991 double s0dt0 = sweep[0].dot(tweep[0]);
985 if (!s0dt0) { 992 if (!s0dt0) {
986 return true; 993 return true;
987 } 994 }
988 SkASSERT(s0dt0 != 0); 995 SkASSERT(s0dt0 != 0);
989 double m = s0xt0 / s0dt0; 996 double m = s0xt0 / s0dt0;
990 double sDist = sweep[0].length() * m; 997 double sDist = sweep[0].length() * m;
991 double tDist = tweep[0].length() * m; 998 double tDist = tweep[0].length() * m;
992 bool useS = fabs(sDist) < fabs(tDist); 999 bool useS = fabs(sDist) < fabs(tDist);
993 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD ist)); 1000 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD ist));
1001 fTangentsAmbiguous = mFactor >= 50 && mFactor < 200;
994 return mFactor < 50; // empirically found limit 1002 return mFactor < 50; // empirically found limit
995 } 1003 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpContour.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698