| Index: src/pathops/SkOpAngle.cpp
|
| ===================================================================
|
| --- src/pathops/SkOpAngle.cpp (revision 9040)
|
| +++ src/pathops/SkOpAngle.cpp (working copy)
|
| @@ -9,6 +9,10 @@
|
| #include "SkPathOpsCurve.h"
|
| #include "SkTSort.h"
|
|
|
| +#if DEBUG_SORT || DEBUG_SORT_SINGLE
|
| +#include "SkOpSegment.h"
|
| +#endif
|
| +
|
| // FIXME: this is bogus for quads and cubics
|
| // if the quads and cubics' line from end pt to ctrl pt are coincident,
|
| // there's no obvious way to determine the curve ordering from the
|
| @@ -27,14 +31,10 @@
|
|
|
| maybe I could set up LineParameters lazily
|
| */
|
| -bool SkOpAngle::operator<(const SkOpAngle& rh) const {
|
| - double y = dy();
|
| - double ry = rh.dy();
|
| +static int simple_compare(double x, double y, double rx, double ry) {
|
| if ((y < 0) ^ (ry < 0)) { // OPTIMIZATION: better to use y * ry < 0 ?
|
| return y < 0;
|
| }
|
| - double x = dx();
|
| - double rx = rh.dx();
|
| if (y == 0 && ry == 0 && x * rx < 0) {
|
| return x < rx;
|
| }
|
| @@ -48,6 +48,18 @@
|
| && !approximately_zero_squared(cmp)) {
|
| return cmp < 0;
|
| }
|
| + return -1;
|
| +}
|
| +
|
| +bool SkOpAngle::operator<(const SkOpAngle& rh) const {
|
| + double x = dx();
|
| + double y = dy();
|
| + double rx = rh.dx();
|
| + double ry = rh.dy();
|
| + int simple = simple_compare(x, y, rx, ry);
|
| + if (simple >= 0) {
|
| + return simple;
|
| + }
|
| // at this point, the initial tangent line is coincident
|
| // see if edges curl away from each other
|
| if (fSide * rh.fSide <= 0 && (!approximately_zero(fSide)
|
| @@ -93,8 +105,10 @@
|
| SkIntersections i, ri;
|
| int roots, rroots;
|
| bool flip = false;
|
| + bool useThis;
|
| + bool leftLessThanRight = fSide > 0;
|
| do {
|
| - bool useThis = (len < rlen) ^ flip;
|
| + useThis = (len < rlen) ^ flip;
|
| const SkDCubic& part = useThis ? fCurvePart : rh.fCurvePart;
|
| SkPath::Verb partVerb = useThis ? fVerb : rh.fVerb;
|
| ray[0] = partVerb == SkPath::kCubic_Verb && part[0].approximatelyEqual(part[1]) ?
|
| @@ -113,28 +127,65 @@
|
| rh.fUnsortable = true;
|
| return this < &rh; // even with no solution, return a stable sort
|
| }
|
| - SkDPoint loc;
|
| + SkASSERT(fSide != 0 && rh.fSide != 0);
|
| + SkASSERT(fSide * rh.fSide > 0); // both are the same sign
|
| + SkDPoint lLoc;
|
| double best = SK_ScalarInfinity;
|
| - SkDVector dxy;
|
| - double dist;
|
| - int index;
|
| - for (index = 0; index < roots; ++index) {
|
| - loc = (*CurveDPointAtT[fVerb])(fPts, i[0][index]);
|
| - dxy = loc - ray[0];
|
| - dist = dxy.lengthSquared();
|
| +#if DEBUG_SORT
|
| + SkDebugf("lh=%d rh=%d use-lh=%d ray={{%1.9g,%1.9g}, {%1.9g,%1.9g}} %c\n",
|
| + fSegment->debugID(), rh.fSegment->debugID(), useThis, ray[0].fX, ray[0].fY,
|
| + ray[1].fX, ray[1].fY, "-+"[fSide > 0]);
|
| +#endif
|
| + for (int index = 0; index < roots; ++index) {
|
| + SkDPoint loc = i.pt(index);
|
| + SkDVector dxy = loc - ray[0];
|
| + double dist = dxy.lengthSquared();
|
| +#if DEBUG_SORT
|
| + SkDebugf("best=%1.9g dist=%1.9g loc={%1.9g,%1.9g} dxy={%1.9g,%1.9g}\n",
|
| + best, dist, loc.fX, loc.fY, dxy.fX, dxy.fY);
|
| +#endif
|
| if (best > dist) {
|
| + lLoc = loc;
|
| best = dist;
|
| }
|
| }
|
| - for (index = 0; index < rroots; ++index) {
|
| - loc = (*CurveDPointAtT[rh.fVerb])(rh.fPts, ri[0][index]);
|
| - dxy = loc - ray[0];
|
| - dist = dxy.lengthSquared();
|
| + flip = false;
|
| + SkDPoint rLoc;
|
| + for (int index = 0; index < rroots; ++index) {
|
| + rLoc = ri.pt(index);
|
| + SkDVector dxy = rLoc - ray[0];
|
| + double dist = dxy.lengthSquared();
|
| +#if DEBUG_SORT
|
| + SkDebugf("best=%1.9g dist=%1.9g %c=(fSide < 0) rLoc={%1.9g,%1.9g} dxy={%1.9g,%1.9g}\n",
|
| + best, dist, "><"[fSide < 0], rLoc.fX, rLoc.fY, dxy.fX, dxy.fY);
|
| +#endif
|
| if (best > dist) {
|
| - return fSide < 0;
|
| + flip = true;
|
| + break;
|
| }
|
| }
|
| - return fSide > 0;
|
| + #if 0
|
| + SkDVector lRay = lLoc - fCurvePart[0];
|
| + SkDVector rRay = rLoc - fCurvePart[0];
|
| + int rayDir = simple_compare(lRay.fX, lRay.fY, rRay.fX, rRay.fY);
|
| + SkASSERT(rayDir >= 0);
|
| + if (rayDir < 0) {
|
| + fUnsortable = true;
|
| + rh.fUnsortable = true;
|
| + return this < &rh; // even with no solution, return a stable sort
|
| + }
|
| +#endif
|
| + if (flip) {
|
| + leftLessThanRight = !leftLessThanRight;
|
| + // rayDir = !rayDir;
|
| + }
|
| +#if 0 && (DEBUG_SORT || DEBUG_SORT_SINGLE)
|
| + SkDebugf("%d %c %d (fSide %c 0) loc={{%1.9g,%1.9g}, {%1.9g,%1.9g}} flip=%d rayDir=%d\n",
|
| + fSegment->debugID(), "><"[leftLessThanRight], rh.fSegment->debugID(),
|
| + "<>"[fSide > 0], lLoc.fX, lLoc.fY, rLoc.fX, rLoc.fY, flip, rayDir);
|
| +#endif
|
| +// SkASSERT(leftLessThanRight == (bool) rayDir);
|
| + return leftLessThanRight;
|
| }
|
|
|
| bool SkOpAngle::lengthen() {
|
|
|