diff options
-rw-r--r-- | include/core/SkGeometry.h | 8 | ||||
-rw-r--r-- | src/core/SkGeometry.cpp | 44 |
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)) - */ |