aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops/SkPathOpsCubic.cpp
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-04-29 08:28:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-29 08:28:30 -0700
commitaec251012542e971100e218bf463adbfb5d21d20 (patch)
tree16c2e84c2d59d94b75d7d2bc50fec53c0e38a898 /src/pathops/SkPathOpsCubic.cpp
parent97fdea6c4393cf0102d7eee5790782509fb4f57b (diff)
minor fixes to cubics code and overall alignment of how bounds and tops are computed for all curve types
All but 17 extended tests work. A helper function is privately added to SkPath.h to permit a test to modify a given point in a path. BUG=skia:3588 Review URL: https://codereview.chromium.org/1107353004
Diffstat (limited to 'src/pathops/SkPathOpsCubic.cpp')
-rw-r--r--src/pathops/SkPathOpsCubic.cpp89
1 files changed, 39 insertions, 50 deletions
diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp
index 63f828fb22..777298b297 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];