Index: src/pathops/SkPathOpsCubic.cpp |
diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp |
index 777298b2972695dceabae31cfeca03d8e58cbbc0..972c510643f48accd5998a45c5a9397586f572c6 100644 |
--- a/src/pathops/SkPathOpsCubic.cpp |
+++ b/src/pathops/SkPathOpsCubic.cpp |
@@ -16,6 +16,15 @@ |
const int SkDCubic::gPrecisionUnit = 256; // FIXME: test different values in test framework |
+void SkDCubic::align(int endIndex, int ctrlIndex, SkDPoint* dstPt) const { |
+ if (fPts[endIndex].fX == fPts[ctrlIndex].fX) { |
+ dstPt->fX = fPts[endIndex].fX; |
+ } |
+ if (fPts[endIndex].fY == fPts[ctrlIndex].fY) { |
+ dstPt->fY = fPts[endIndex].fY; |
+ } |
+} |
+ |
// give up when changing t no longer moves point |
// also, copy point rather than recompute it when it does change |
double SkDCubic::binarySearch(double min, double max, double axisIntercept, |
@@ -75,45 +84,45 @@ double SkDCubic::calcPrecision() const { |
return (width > height ? width : height) / gPrecisionUnit; |
} |
-bool SkDCubic::clockwise(const SkDCubic& whole, 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() && !whole.monotonicInY(); |
- return sum <= 0; |
+ |
+/* classic one t subdivision */ |
+static void interp_cubic_coords(const double* src, double* dst, double t) { |
+ double ab = SkDInterp(src[0], src[2], t); |
+ double bc = SkDInterp(src[2], src[4], t); |
+ double cd = SkDInterp(src[4], src[6], t); |
+ double abc = SkDInterp(ab, bc, t); |
+ double bcd = SkDInterp(bc, cd, t); |
+ double abcd = SkDInterp(abc, bcd, t); |
+ |
+ dst[0] = src[0]; |
+ dst[2] = ab; |
+ dst[4] = abc; |
+ dst[6] = abcd; |
+ dst[8] = bcd; |
+ dst[10] = cd; |
+ dst[12] = src[6]; |
} |
-bool SkDCubic::Clockwise(const SkPoint* pts, double startT, double endT, bool* swap) { |
- SkDCubic cubic; |
- cubic.set(pts); |
- SkDCubic part = cubic.subDivide(startT, endT); |
- return part.clockwise(cubic, swap); |
+SkDCubicPair SkDCubic::chopAt(double t) const { |
+ SkDCubicPair dst; |
+ if (t == 0.5) { |
+ dst.pts[0] = fPts[0]; |
+ dst.pts[1].fX = (fPts[0].fX + fPts[1].fX) / 2; |
+ dst.pts[1].fY = (fPts[0].fY + fPts[1].fY) / 2; |
+ dst.pts[2].fX = (fPts[0].fX + 2 * fPts[1].fX + fPts[2].fX) / 4; |
+ dst.pts[2].fY = (fPts[0].fY + 2 * fPts[1].fY + fPts[2].fY) / 4; |
+ dst.pts[3].fX = (fPts[0].fX + 3 * (fPts[1].fX + fPts[2].fX) + fPts[3].fX) / 8; |
+ dst.pts[3].fY = (fPts[0].fY + 3 * (fPts[1].fY + fPts[2].fY) + fPts[3].fY) / 8; |
+ dst.pts[4].fX = (fPts[1].fX + 2 * fPts[2].fX + fPts[3].fX) / 4; |
+ dst.pts[4].fY = (fPts[1].fY + 2 * fPts[2].fY + fPts[3].fY) / 4; |
+ dst.pts[5].fX = (fPts[2].fX + fPts[3].fX) / 2; |
+ dst.pts[5].fY = (fPts[2].fY + fPts[3].fY) / 2; |
+ dst.pts[6] = fPts[3]; |
+ return dst; |
+ } |
+ interp_cubic_coords(&fPts[0].fX, &dst.pts[0].fX, t); |
+ interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t); |
+ return dst; |
} |
void SkDCubic::Coefficients(const double* src, double* A, double* B, double* C, double* D) { |
@@ -636,15 +645,6 @@ SkDCubic SkDCubic::subDivide(double t1, double t2) const { |
return dst; |
} |
-void SkDCubic::align(int endIndex, int ctrlIndex, SkDPoint* dstPt) const { |
- if (fPts[endIndex].fX == fPts[ctrlIndex].fX) { |
- dstPt->fX = fPts[endIndex].fX; |
- } |
- if (fPts[endIndex].fY == fPts[ctrlIndex].fY) { |
- dstPt->fY = fPts[endIndex].fY; |
- } |
-} |
- |
void SkDCubic::subDivide(const SkDPoint& a, const SkDPoint& d, |
double t1, double t2, SkDPoint dst[2]) const { |
SkASSERT(t1 != t2); |
@@ -672,42 +672,17 @@ void SkDCubic::subDivide(const SkDPoint& a, const SkDPoint& d, |
} |
} |
-/* classic one t subdivision */ |
-static void interp_cubic_coords(const double* src, double* dst, double t) { |
- double ab = SkDInterp(src[0], src[2], t); |
- double bc = SkDInterp(src[2], src[4], t); |
- double cd = SkDInterp(src[4], src[6], t); |
- double abc = SkDInterp(ab, bc, t); |
- double bcd = SkDInterp(bc, cd, t); |
- double abcd = SkDInterp(abc, bcd, t); |
- |
- dst[0] = src[0]; |
- dst[2] = ab; |
- dst[4] = abc; |
- dst[6] = abcd; |
- dst[8] = bcd; |
- dst[10] = cd; |
- dst[12] = src[6]; |
-} |
- |
-SkDCubicPair SkDCubic::chopAt(double t) const { |
- SkDCubicPair dst; |
- if (t == 0.5) { |
- dst.pts[0] = fPts[0]; |
- dst.pts[1].fX = (fPts[0].fX + fPts[1].fX) / 2; |
- dst.pts[1].fY = (fPts[0].fY + fPts[1].fY) / 2; |
- dst.pts[2].fX = (fPts[0].fX + 2 * fPts[1].fX + fPts[2].fX) / 4; |
- dst.pts[2].fY = (fPts[0].fY + 2 * fPts[1].fY + fPts[2].fY) / 4; |
- dst.pts[3].fX = (fPts[0].fX + 3 * (fPts[1].fX + fPts[2].fX) + fPts[3].fX) / 8; |
- dst.pts[3].fY = (fPts[0].fY + 3 * (fPts[1].fY + fPts[2].fY) + fPts[3].fY) / 8; |
- dst.pts[4].fX = (fPts[1].fX + 2 * fPts[2].fX + fPts[3].fX) / 4; |
- dst.pts[4].fY = (fPts[1].fY + 2 * fPts[2].fY + fPts[3].fY) / 4; |
- dst.pts[5].fX = (fPts[2].fX + fPts[3].fX) / 2; |
- dst.pts[5].fY = (fPts[2].fY + fPts[3].fY) / 2; |
- dst.pts[6] = fPts[3]; |
- return dst; |
+double SkDCubic::top(const SkDCubic& dCurve, double startT, double endT, SkDPoint*topPt) const { |
+ double extremeTs[2]; |
+ double topT = -1; |
+ int roots = SkDCubic::FindExtrema(&fPts[0].fY, extremeTs); |
+ for (int index = 0; index < roots; ++index) { |
+ double t = startT + (endT - startT) * extremeTs[index]; |
+ SkDPoint mid = dCurve.ptAtT(t); |
+ if (topPt->fY > mid.fY || (topPt->fY == mid.fY && topPt->fX > mid.fX)) { |
+ topT = t; |
+ *topPt = mid; |
+ } |
} |
- interp_cubic_coords(&fPts[0].fX, &dst.pts[0].fX, t); |
- interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t); |
- return dst; |
+ return topT; |
} |