| Index: src/pathops/SkPathOpsCubic.cpp
|
| diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp
|
| index 63f828fb22b1090b80240fdd9003b3623d7c4ddd..777298b2972695dceabae31cfeca03d8e58cbbc0 100644
|
| --- a/src/pathops/SkPathOpsCubic.cpp
|
| +++ b/src/pathops/SkPathOpsCubic.cpp
|
| @@ -75,7 +75,7 @@ double SkDCubic::calcPrecision() const {
|
| return (width > height ? width : height) / gPrecisionUnit;
|
| }
|
|
|
| -bool SkDCubic::clockwise(bool* swap) const {
|
| +bool SkDCubic::clockwise(const SkDCubic& whole, bool* swap) const {
|
| SkDPoint lastPt = fPts[kPointLast];
|
| SkDPoint firstPt = fPts[0];
|
| double sum = 0;
|
| @@ -105,34 +105,15 @@ bool SkDCubic::clockwise(bool* swap) const {
|
| lastPt = firstPt;
|
| firstPt = idx == 1 ? fPts[furthest] : fPts[kPointLast];
|
| }
|
| - *swap = sum > 0 && !this->monotonicInY();
|
| + *swap = sum > 0 && !this->monotonicInY() && !whole.monotonicInY();
|
| return sum <= 0;
|
| }
|
|
|
| bool SkDCubic::Clockwise(const SkPoint* pts, double startT, double endT, bool* swap) {
|
| SkDCubic cubic;
|
| cubic.set(pts);
|
| -#if 0
|
| - bool flip = startT > endT;
|
| - double inflectionTs[2];
|
| - int inflections = cubic.findInflections(inflectionTs);
|
| - for (int index = 0; index < inflections; ++index) {
|
| - double inflectionT = inflectionTs[index];
|
| - if (between(startT, inflectionT, endT)) {
|
| - if (flip) {
|
| - if (!roughly_equal(inflectionT, endT)) {
|
| - startT = inflectionT;
|
| - }
|
| - } else {
|
| - if (!roughly_equal(inflectionT, startT)) {
|
| - endT = inflectionT;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -#endif
|
| SkDCubic part = cubic.subDivide(startT, endT);
|
| - return part.clockwise(swap);
|
| + return part.clockwise(cubic, swap);
|
| }
|
|
|
| void SkDCubic::Coefficients(const double* src, double* A, double* B, double* C, double* D) {
|
| @@ -301,9 +282,14 @@ bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t, CubicType*
|
| return false;
|
| }
|
|
|
| +bool SkDCubic::monotonicInX() const {
|
| + return precisely_between(fPts[0].fX, fPts[1].fX, fPts[3].fX)
|
| + && precisely_between(fPts[0].fX, fPts[2].fX, fPts[3].fX);
|
| +}
|
| +
|
| bool SkDCubic::monotonicInY() const {
|
| - return between(fPts[0].fY, fPts[1].fY, fPts[3].fY)
|
| - && between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
|
| + return precisely_between(fPts[0].fY, fPts[1].fY, fPts[3].fY)
|
| + && precisely_between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
|
| }
|
|
|
| void SkDCubic::otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const {
|
| @@ -343,6 +329,28 @@ int SkDCubic::RootsValidT(double A, double B, double C, double D, double t[3]) {
|
| double s[3];
|
| int realRoots = RootsReal(A, B, C, D, s);
|
| int foundRoots = SkDQuad::AddValidTs(s, realRoots, t);
|
| + for (int index = 0; index < realRoots; ++index) {
|
| + double tValue = s[index];
|
| + if (!approximately_one_or_less(tValue) && between(1, tValue, 1.00005)) {
|
| + for (int idx2 = 0; idx2 < foundRoots; ++idx2) {
|
| + if (approximately_equal(t[idx2], 1)) {
|
| + goto nextRoot;
|
| + }
|
| + }
|
| + SkASSERT(foundRoots < 3);
|
| + t[foundRoots++] = 1;
|
| + } else if (!approximately_zero_or_more(tValue) && between(-0.00005, tValue, 0)) {
|
| + for (int idx2 = 0; idx2 < foundRoots; ++idx2) {
|
| + if (approximately_equal(t[idx2], 0)) {
|
| + goto nextRoot;
|
| + }
|
| + }
|
| + SkASSERT(foundRoots < 3);
|
| + t[foundRoots++] = 0;
|
| + }
|
| +nextRoot:
|
| + ;
|
| + }
|
| return foundRoots;
|
| }
|
|
|
| @@ -487,10 +495,14 @@ static void formulate_F1DotF2(const double src[], double coeff[4]) {
|
| C = 3(b - a)
|
| Solve for t, keeping only those that fit between 0 < t < 1
|
| */
|
| -int SkDCubic::FindExtrema(double a, double b, double c, double d, double tValues[2]) {
|
| +int SkDCubic::FindExtrema(const double src[], double tValues[2]) {
|
| // we divide A,B,C by 3 to simplify
|
| - double A = d - a + 3*(b - c);
|
| - double B = 2*(a - b - b + c);
|
| + double a = src[0];
|
| + double b = src[2];
|
| + double c = src[4];
|
| + double d = src[6];
|
| + double A = d - a + 3 * (b - c);
|
| + double B = 2 * (a - b - b + c);
|
| double C = b - a;
|
|
|
| return SkDQuad::RootsValidT(A, B, C, tValues);
|
| @@ -519,29 +531,6 @@ int SkDCubic::findMaxCurvature(double tValues[]) const {
|
| return RootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues);
|
| }
|
|
|
| -SkDPoint SkDCubic::top(double startT, double endT, double* topT) const {
|
| - SkDCubic sub = subDivide(startT, endT);
|
| - SkDPoint topPt = sub[0];
|
| - *topT = startT;
|
| - if (topPt.fY > sub[3].fY || (topPt.fY == sub[3].fY && topPt.fX > sub[3].fX)) {
|
| - *topT = endT;
|
| - topPt = sub[3];
|
| - }
|
| - double extremeTs[2];
|
| - if (!sub.monotonicInY()) {
|
| - int roots = FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, sub[3].fY, extremeTs);
|
| - for (int index = 0; index < roots; ++index) {
|
| - double t = startT + (endT - startT) * extremeTs[index];
|
| - SkDPoint mid = ptAtT(t);
|
| - if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) {
|
| - *topT = t;
|
| - topPt = mid;
|
| - }
|
| - }
|
| - }
|
| - return topPt;
|
| -}
|
| -
|
| SkDPoint SkDCubic::ptAtT(double t) const {
|
| if (0 == t) {
|
| return fPts[0];
|
|
|