diff options
author | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-08-28 20:06:54 +0000 |
---|---|---|
committer | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-08-28 20:06:54 +0000 |
commit | a964028843ec3f69b3b2e556426ff881d1fcb4b2 (patch) | |
tree | 5f4b9f35200f31d6e5cbdf651f548f947126c852 /src | |
parent | 28937283e16928a562b3f9e19908db51bbb89ff9 (diff) |
Detect when we no longer have a valid range for chopping due to finite float
precision, and just return a degenerate cubic at the end.
git-svn-id: http://skia.googlecode.com/svn/trunk@341 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkGeometry.cpp | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp index 229c3d8999..2775543919 100644 --- a/src/core/SkGeometry.cpp +++ b/src/core/SkGeometry.cpp @@ -505,6 +505,29 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t) interp_cubic_coords(&src[0].fY, &dst[0].fY, t); } +/* http://code.google.com/p/skia/issues/detail?id=32 + + This test code would fail when we didn't check the return result of + valid_unit_divide in SkChopCubicAt(... tValues[], int roots). The reason is + that after the first chop, the parameters to valid_unit_divide are equal + (thanks to finite float precision and rounding in the subtracts). Thus + even though the 2nd tValue looks < 1.0, after we renormalize it, we end + up with 1.0, hence the need to check and just return the last cubic as + a degenerate clump of 4 points in the sampe place. + + static void test_cubic() { + SkPoint src[4] = { + { 556.25000, 523.03003 }, + { 556.23999, 522.96002 }, + { 556.21997, 522.89001 }, + { 556.21997, 522.82001 } + }; + SkPoint dst[10]; + SkScalar tval[] = { 0.33333334f, 0.99999994f }; + SkChopCubicAt(src, dst, tval, 2); + } + */ + void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[], int roots) { #ifdef SK_DEBUG @@ -533,12 +556,18 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[] if (i == roots - 1) break; - SkDEBUGCODE(int valid =) valid_unit_divide(tValues[i+1] - tValues[i], SK_Scalar1 - tValues[i], &t); - SkASSERT(valid); - dst += 3; + // have src point to the remaining cubic (after the chop) memcpy(tmp, dst, 4 * sizeof(SkPoint)); src = tmp; + + // watch out in case the renormalized t isn't in range + if (!valid_unit_divide(tValues[i+1] - tValues[i], + SK_Scalar1 - tValues[i], &t)) { + // if we can't, just create a degenerate cubic + dst[4] = dst[5] = dst[6] = src[3]; + break; + } } } } |