aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkGeometry.h8
-rw-r--r--src/core/SkGeometry.cpp44
2 files changed, 31 insertions, 21 deletions
diff --git a/include/core/SkGeometry.h b/include/core/SkGeometry.h
index d540d34d27..97997c410a 100644
--- a/include/core/SkGeometry.h
+++ b/include/core/SkGeometry.h
@@ -220,6 +220,14 @@ struct SkConic {
void chopAt(SkScalar t, SkConic dst[2]) const;
void chop(SkConic dst[2]) const;
+ /**
+ * Return the max difference between the conic and its framing quadratic
+ * in err and return true. If the conic is degenerate (a line between
+ * pts[0] and pts[2]) or has a negative weight, return false and ignore
+ * the diff parameter.
+ */
+ bool computeErrorAsQuad(SkVector* err) const;
+
int computeQuadPOW2(SkScalar tol) const;
int chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index 6b525faea6..6be62183a9 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -1543,21 +1543,32 @@ void SkConic::chop(SkConic dst[2]) const {
dst[0].fW = dst[1].fW = subdivide_w_value(fW);
}
-int SkConic::computeQuadPOW2(SkScalar tol) const {
- if (fW <= SK_ScalarNearlyZero) {
- return 0; // treat as a line
+/*
+ * "High order approximation of conic sections by quadratic splines"
+ * by Michael Floater, 1993
+ */
+bool SkConic::computeErrorAsQuad(SkVector* err) const {
+ if (fW <= 0) {
+ return false;
}
+ SkScalar a = fW - 1;
+ SkScalar k = a / (4 * (2 + a));
+ err->set(k * (fPts[0].fX - 2 * fPts[1].fX + fPts[2].fX),
+ k * (fPts[0].fY - 2 * fPts[1].fY + fPts[2].fY));
+ return true;
+}
- tol = SkScalarAbs(tol);
- SkScalar w = fW;
- int i = 0;
- for (; i < 8; ++i) {
- if (SkScalarAbs(w - 1) <= tol) {
- break;
- }
- w = subdivide_w_value(w);
+int SkConic::computeQuadPOW2(SkScalar tol) const {
+ SkVector diff;
+ if (!this->computeErrorAsQuad(&diff)) {
+ return 0;
}
- return i;
+
+ // the error reduces by 4 with each subdivision, so return the subdivision
+ // count needed.
+ SkScalar error = diff.length() - SkScalarAbs(tol);
+ uint32_t ierr = (uint32_t)error;
+ return (33 - SkCLZ(ierr)) >> 1;
}
static SkPoint* subdivide(const SkConic& src, SkPoint pts[], int level) {
@@ -1655,12 +1666,3 @@ void SkConic::computeFastBounds(SkRect* bounds) const {
bounds->set(fPts, 3);
}
-/*
- * "High order approximation of conic sections by quadratic splines"
- * by Michael Floater, 1993
- *
- * Max error between conic and simple quad is bounded by this equation
- *
- * a <-- w - 1 (where w >= 0)
- * diff <-- a * (p0 - 2p1 + p2) / (4*(2 + a))
- */