diff options
author | dominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-19 18:26:07 +0000 |
---|---|---|
committer | dominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-19 18:26:07 +0000 |
commit | 19f9054c20019e94afbc0a3d8459a4943189d9f0 (patch) | |
tree | 5d5a42b7d6a20d586bcc5d3c4fedaa666d3accb2 /ui/gfx | |
parent | e6a236465d06825473f8e4e1aaf0eb3ab679c55c (diff) | |
download | chromium_src-19f9054c20019e94afbc0a3d8459a4943189d9f0.zip chromium_src-19f9054c20019e94afbc0a3d8459a4943189d9f0.tar.gz chromium_src-19f9054c20019e94afbc0a3d8459a4943189d9f0.tar.bz2 |
Provide approximate type functions for SkMatrix44.
Skia's SkMatrix44 class provides methods for computing the type of a matrix
using exact computations, i.e. matrix values must be of exactly some value.
However, in some cases some inaccuracy can be tolerated. This patch provides
methods for computing approximate types in a centralized place
(cc/base/math_util.c,hh). It replaces any other approximate type computation
with calls to the new methods.
BUG=293787
Review URL: https://codereview.chromium.org/27223008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229609 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r-- | ui/gfx/transform.cc | 27 | ||||
-rw-r--r-- | ui/gfx/transform.h | 4 | ||||
-rw-r--r-- | ui/gfx/transform_unittest.cc | 77 |
3 files changed, 108 insertions, 0 deletions
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc index 057c93c..e129af5 100644 --- a/ui/gfx/transform.cc +++ b/ui/gfx/transform.cc @@ -32,6 +32,14 @@ SkMScalar TanDegrees(double degrees) { return SkDoubleToMScalar(std::tan(radians)); } +inline bool ApproximatelyZero(SkMScalar x, SkMScalar tolerance) { + return std::abs(x) <= tolerance; +} + +inline bool ApproximatelyOne(SkMScalar x, SkMScalar tolerance) { + return std::abs(x - SkDoubleToMScalar(1.0)) <= tolerance; +} + } // namespace Transform::Transform(SkMScalar col1row1, @@ -210,6 +218,25 @@ void Transform::ConcatTransform(const Transform& transform) { matrix_.postConcat(transform.matrix_); } +bool Transform::IsApproximatelyIdentityOrTranslation( + SkMScalar tolerance) const { + DCHECK_GE(tolerance, 0); + return + ApproximatelyOne(matrix_.get(0, 0), tolerance) && + ApproximatelyZero(matrix_.get(1, 0), tolerance) && + ApproximatelyZero(matrix_.get(2, 0), tolerance) && + matrix_.get(3, 0) == 0 && + ApproximatelyZero(matrix_.get(0, 1), tolerance) && + ApproximatelyOne(matrix_.get(1, 1), tolerance) && + ApproximatelyZero(matrix_.get(2, 1), tolerance) && + matrix_.get(3, 1) == 0 && + ApproximatelyZero(matrix_.get(0, 2), tolerance) && + ApproximatelyZero(matrix_.get(1, 2), tolerance) && + ApproximatelyOne(matrix_.get(2, 2), tolerance) && + matrix_.get(3, 2) == 0 && + matrix_.get(3, 3) == 1; +} + bool Transform::IsIdentityOrIntegerTranslation() const { if (!IsIdentityOrTranslation()) return false; diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h index 60c3d5c..3621741 100644 --- a/ui/gfx/transform.h +++ b/ui/gfx/transform.h @@ -120,6 +120,10 @@ class GFX_EXPORT Transform { return !(matrix_.getType() & ~SkMatrix44::kTranslate_Mask); } + // Returns true if the matrix is either identity or pure translation, + // allowing for an amount of inaccuracy as specified by the parameter. + bool IsApproximatelyIdentityOrTranslation(SkMScalar tolerance) const; + // Returns true if the matrix is either a positive scale and/or a translation. bool IsPositiveScaleOrTranslation() const { if (!IsScaleOrTranslation()) diff --git a/ui/gfx/transform_unittest.cc b/ui/gfx/transform_unittest.cc index f747e48..0bf9dde 100644 --- a/ui/gfx/transform_unittest.cc +++ b/ui/gfx/transform_unittest.cc @@ -141,6 +141,33 @@ void InitializeTestMatrix2(Transform* transform) { EXPECT_ROW4_EQ(33.0f, 37.0f, 41.0f, 45.0f, (*transform)); } +const SkMScalar kApproxZero = + SkFloatToMScalar(std::numeric_limits<float>::epsilon()); +const SkMScalar kApproxOne = 1 - kApproxZero; + +void InitializeApproxIdentityMatrix(Transform* transform) { + SkMatrix44& matrix = transform->matrix(); + matrix.set(0, 0, kApproxOne); + matrix.set(0, 1, kApproxZero); + matrix.set(0, 2, kApproxZero); + matrix.set(0, 3, kApproxZero); + + matrix.set(1, 0, kApproxZero); + matrix.set(1, 1, kApproxOne); + matrix.set(1, 2, kApproxZero); + matrix.set(1, 3, kApproxZero); + + matrix.set(2, 0, kApproxZero); + matrix.set(2, 1, kApproxZero); + matrix.set(2, 2, kApproxOne); + matrix.set(2, 3, kApproxZero); + + matrix.set(3, 0, kApproxZero); + matrix.set(3, 1, kApproxZero); + matrix.set(3, 2, kApproxZero); + matrix.set(3, 3, kApproxOne); +} + #ifdef SK_MSCALAR_IS_DOUBLE #define ERROR_THRESHOLD 1e-14 #else @@ -2211,6 +2238,56 @@ TEST(XFormTest, verifyIsIdentityOrTranslation) { EXPECT_FALSE(A.IsIdentityOrTranslation()); } +TEST(XFormTest, verifyIsApproximatelyIdentityOrTranslation) { + Transform A; + SkMatrix44& matrix = A.matrix(); + + // Exact pure translation. + A.MakeIdentity(); + + // Set translate values to values other than 0 or 1. + matrix.set(0, 3, 3.4f); + matrix.set(1, 3, 4.4f); + matrix.set(2, 3, 5.6f); + + EXPECT_TRUE(A.IsApproximatelyIdentityOrTranslation(0)); + EXPECT_TRUE(A.IsApproximatelyIdentityOrTranslation(kApproxZero)); + + // Approximately pure translation. + InitializeApproxIdentityMatrix(&A); + + // Some values must be exact. + matrix.set(3, 0, 0); + matrix.set(3, 1, 0); + matrix.set(3, 2, 0); + matrix.set(3, 3, 1); + + // Set translate values to values other than 0 or 1. + matrix.set(0, 3, 3.4f); + matrix.set(1, 3, 4.4f); + matrix.set(2, 3, 5.6f); + + EXPECT_FALSE(A.IsApproximatelyIdentityOrTranslation(0)); + EXPECT_TRUE(A.IsApproximatelyIdentityOrTranslation(kApproxZero)); + + // Not approximately pure translation. + InitializeApproxIdentityMatrix(&A); + + // Some values must be exact. + matrix.set(3, 0, 0); + matrix.set(3, 1, 0); + matrix.set(3, 2, 0); + matrix.set(3, 3, 1); + + // Set some values (not translate values) to values other than 0 or 1. + matrix.set(0, 1, 3.4f); + matrix.set(3, 2, 4.4f); + matrix.set(2, 0, 5.6f); + + EXPECT_FALSE(A.IsApproximatelyIdentityOrTranslation(0)); + EXPECT_FALSE(A.IsApproximatelyIdentityOrTranslation(kApproxZero)); +} + TEST(XFormTest, verifyIsScaleOrTranslation) { Transform A; |