| Index: src/pathops/SkPathOpsCubic.cpp
|
| diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp
|
| index a44d29bb0f32ead583b8a453e7d930fd9817510b..63f828fb22b1090b80240fdd9003b3623d7c4ddd 100644
|
| --- a/src/pathops/SkPathOpsCubic.cpp
|
| +++ b/src/pathops/SkPathOpsCubic.cpp
|
| @@ -8,6 +8,7 @@
|
| #include "SkLineParameters.h"
|
| #include "SkPathOpsConic.h"
|
| #include "SkPathOpsCubic.h"
|
| +#include "SkPathOpsCurve.h"
|
| #include "SkPathOpsLine.h"
|
| #include "SkPathOpsQuad.h"
|
| #include "SkPathOpsRect.h"
|
| @@ -74,14 +75,66 @@ double SkDCubic::calcPrecision() const {
|
| return (width > height ? width : height) / gPrecisionUnit;
|
| }
|
|
|
| -bool SkDCubic::clockwise() const {
|
| - double sum = (fPts[0].fX - fPts[3].fX) * (fPts[0].fY + fPts[3].fY);
|
| - for (int idx = 0; idx < 3; ++idx) {
|
| - sum += (fPts[idx + 1].fX - fPts[idx].fX) * (fPts[idx + 1].fY + fPts[idx].fY);
|
| +bool SkDCubic::clockwise(bool* swap) const {
|
| + SkDPoint lastPt = fPts[kPointLast];
|
| + SkDPoint firstPt = fPts[0];
|
| + double sum = 0;
|
| + // pick the control point furthest from the line connecting the end points
|
| + SkLineParameters lineParameters;
|
| + lineParameters.cubicEndPoints(*this, 0, 3);
|
| + lineParameters.normalize();
|
| + double tiniest = SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY),
|
| + fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY), fPts[3].fX), fPts[3].fY);
|
| + double largest = SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY),
|
| + fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY), fPts[3].fX), fPts[3].fY);
|
| + largest = SkTMax(largest, -tiniest);
|
| + double pt1dist = lineParameters.controlPtDistance(*this, 1);
|
| + double pt2dist = lineParameters.controlPtDistance(*this, 2);
|
| +#if DEBUG_SWAP_TOP
|
| + SkDebugf("%s pt1dist=%1.9g pt2dist=%1.9g\n", __FUNCTION__, pt1dist, pt2dist);
|
| +#endif
|
| + int furthest;
|
| + if (!approximately_zero_when_compared_to(pt1dist, largest)
|
| + && !approximately_zero_when_compared_to(pt2dist, largest) && pt1dist * pt2dist < 0) {
|
| + furthest = 2;
|
| + } else {
|
| + furthest = fabs(pt1dist) < fabs(pt2dist) ? 2 : 1;
|
| + }
|
| + for (int idx = 1; idx <= 3; ++idx) {
|
| + sum += (firstPt.fX - lastPt.fX) * (firstPt.fY + lastPt.fY);
|
| + lastPt = firstPt;
|
| + firstPt = idx == 1 ? fPts[furthest] : fPts[kPointLast];
|
| }
|
| + *swap = sum > 0 && !this->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);
|
| +}
|
| +
|
| void SkDCubic::Coefficients(const double* src, double* A, double* B, double* C, double* D) {
|
| *A = src[6]; // d
|
| *B = src[4] * 3; // 3*c
|
| @@ -186,7 +239,7 @@ bool SkDCubic::isLinear(int startIndex, int endIndex) const {
|
| return approximately_zero_when_compared_to(distance, largest);
|
| }
|
|
|
| -bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) {
|
| +bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t, CubicType* resultType) {
|
| SkScalar d[3];
|
| SkCubicType cubicType = SkClassifyCubic(pointsPtr, d);
|
| if (cubicType == kLoop_SkCubicType) {
|
| @@ -203,6 +256,7 @@ bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) {
|
| SkScalar smaller = SkTMax(0.f, SkTMin(ls, ms));
|
| SkScalar larger = SkTMin(1.f, SkTMax(ls, ms));
|
| *t = (smaller + larger) / 2;
|
| + *resultType = kSplitAtLoop_SkDCubicType;
|
| return *t > 0 && *t < 1;
|
| }
|
| } else if (kSerpentine_SkCubicType == cubicType || kCusp_SkCubicType == cubicType) {
|
| @@ -213,17 +267,36 @@ bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) {
|
| if (infTCount == 2) {
|
| double maxCurvature[3];
|
| int roots = cubic.findMaxCurvature(maxCurvature);
|
| +#if DEBUG_CUBIC_SPLIT
|
| + SkDebugf("%s\n", __FUNCTION__);
|
| + cubic.dump();
|
| + for (int index = 0; index < infTCount; ++index) {
|
| + SkDebugf("inflectionsTs[%d]=%1.9g ", index, inflectionTs[index]);
|
| + SkDPoint pt = cubic.ptAtT(inflectionTs[index]);
|
| + SkDVector dPt = cubic.dxdyAtT(inflectionTs[index]);
|
| + SkDLine perp = {{pt - dPt, pt + dPt}};
|
| + perp.dump();
|
| + }
|
| + for (int index = 0; index < roots; ++index) {
|
| + SkDebugf("maxCurvature[%d]=%1.9g ", index, maxCurvature[index]);
|
| + SkDPoint pt = cubic.ptAtT(maxCurvature[index]);
|
| + SkDVector dPt = cubic.dxdyAtT(maxCurvature[index]);
|
| + SkDLine perp = {{pt - dPt, pt + dPt}};
|
| + perp.dump();
|
| + }
|
| +#endif
|
| for (int index = 0; index < roots; ++index) {
|
| if (between(inflectionTs[0], maxCurvature[index], inflectionTs[1])) {
|
| *t = maxCurvature[index];
|
| + *resultType = kSplitAtMaxCurvature_SkDCubicType;
|
| return true;
|
| }
|
| }
|
| } else if (infTCount == 1) {
|
| *t = inflectionTs[0];
|
| + *resultType = kSplitAtInflection_SkDCubicType;
|
| return *t > 0 && *t < 1;
|
| }
|
| - return false;
|
| }
|
| return false;
|
| }
|
| @@ -446,10 +519,12 @@ int SkDCubic::findMaxCurvature(double tValues[]) const {
|
| return RootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues);
|
| }
|
|
|
| -SkDPoint SkDCubic::top(double startT, double endT) const {
|
| +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];
|
| @@ -459,6 +534,7 @@ SkDPoint SkDCubic::top(double startT, double endT) const {
|
| 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;
|
| }
|
| }
|
|
|