| Index: src/utils/SkMatrix44.cpp |
| =================================================================== |
| --- src/utils/SkMatrix44.cpp (revision 1698) |
| +++ src/utils/SkMatrix44.cpp (working copy) |
| @@ -17,6 +17,41 @@ |
| #include "SkMatrix44.h" |
| +#include <algorithm> |
| + |
| +namespace { |
| + |
| +#ifdef SK_MSCALAR_IS_DOUBLE |
| +const static SkMScalar SK_SkMTolerance = 1e-12; |
| +#else |
| +const static SkMScalar SK_SkMTolerance = 1e-6; |
| +#endif |
| + |
| +bool ApproximatelyZero(SkMScalar value) { |
| + return fabs(value) <= SK_SkMTolerance; |
| +} |
| + |
| +// On inputs near multiples of M_PI_2, cos and sin return values that are |
| +// close to, but not quite zero. Since this is the common case in rotation, |
| +// and because these small errors can lead to future rounding errors, we |
| +// clamp to zero where appropriate. |
| + |
| +double clamped_cos(SkMScalar radians) { |
| + SkMScalar result = SkDoubleToScalar(cos(radians)); |
| + if (ApproximatelyZero(result)) |
| + result = 0; |
| + return result; |
| +} |
| + |
| +double clamped_sin(SkMScalar radians) { |
| + SkMScalar result = SkDoubleToScalar(sin(radians)); |
| + if (ApproximatelyZero(result)) |
| + result = 0; |
| + return result; |
| +} |
| + |
| +} // anonymous namespace |
| + |
| SkMatrix44::SkMatrix44() { |
| this->setIdentity(); |
| } |
| @@ -180,8 +215,8 @@ |
| void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, |
| SkMScalar radians) { |
| - double c = cos(radians); |
| - double s = sin(radians); |
| + double c = clamped_cos(radians); |
| + double s = clamped_sin(radians); |
| double C = 1 - c; |
| double xs = x * s; |
| double ys = y * s; |
| @@ -383,6 +418,3 @@ |
| return dst; |
| } |
| - |
| - |
| - |