summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authordominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-19 18:26:07 +0000
committerdominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-19 18:26:07 +0000
commit19f9054c20019e94afbc0a3d8459a4943189d9f0 (patch)
tree5d5a42b7d6a20d586bcc5d3c4fedaa666d3accb2 /ui/gfx
parente6a236465d06825473f8e4e1aaf0eb3ab679c55c (diff)
downloadchromium_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.cc27
-rw-r--r--ui/gfx/transform.h4
-rw-r--r--ui/gfx/transform_unittest.cc77
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;