add computation for error in conic-as-quad

git-svn-id: http://skia.googlecode.com/svn/trunk@8887 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
mike@reedtribe.org 2013-04-27 18:23:16 +00:00
parent 214c870f5e
commit 97514f22e4
2 changed files with 31 additions and 21 deletions

View File

@ -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;

View File

@ -1543,21 +1543,32 @@ void SkConic::chop(SkConic dst[2]) const {
dst[0].fW = dst[1].fW = subdivide_w_value(fW);
}
/*
* "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;
}
int SkConic::computeQuadPOW2(SkScalar tol) const {
if (fW <= SK_ScalarNearlyZero) {
return 0; // treat as a line
SkVector diff;
if (!this->computeErrorAsQuad(&diff)) {
return 0;
}
tol = SkScalarAbs(tol);
SkScalar w = fW;
int i = 0;
for (; i < 8; ++i) {
if (SkScalarAbs(w - 1) <= tol) {
break;
}
w = subdivide_w_value(w);
}
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))
*/