blob: df24a5a07872e5a0bec836de9dd84b5afba3b851 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.comed673312009-02-27 16:24:51 +00008#include "Test.h"
9#include "SkMatrix.h"
10
11static bool nearly_equal_scalar(SkScalar a, SkScalar b) {
epoger@google.com2047f002011-05-17 17:36:59 +000012 // Note that we get more compounded error for multiple operations when
13 // SK_SCALAR_IS_FIXED.
reed@android.comed673312009-02-27 16:24:51 +000014#ifdef SK_SCALAR_IS_FLOAT
epoger@google.com2047f002011-05-17 17:36:59 +000015 const SkScalar tolerance = SK_Scalar1 / 200000;
reed@android.comed673312009-02-27 16:24:51 +000016#else
epoger@google.com2047f002011-05-17 17:36:59 +000017 const SkScalar tolerance = SK_Scalar1 / 1024;
reed@android.comed673312009-02-27 16:24:51 +000018#endif
19
20 return SkScalarAbs(a - b) <= tolerance;
21}
22
23static bool nearly_equal(const SkMatrix& a, const SkMatrix& b) {
24 for (int i = 0; i < 9; i++) {
25 if (!nearly_equal_scalar(a[i], b[i])) {
reed@android.comd4134452011-02-09 02:24:26 +000026 printf("not equal %g %g\n", (float)a[i], (float)b[i]);
reed@android.comed673312009-02-27 16:24:51 +000027 return false;
28 }
29 }
30 return true;
31}
32
33static bool is_identity(const SkMatrix& m) {
34 SkMatrix identity;
reed@android.com80e39a72009-04-02 16:59:40 +000035 identity.reset();
reed@android.comed673312009-02-27 16:24:51 +000036 return nearly_equal(m, identity);
37}
38
reed@android.com4b7577b2009-06-29 16:14:41 +000039static void test_flatten(skiatest::Reporter* reporter, const SkMatrix& m) {
40 // add 100 in case we have a bug, I don't want to kill my stack in the test
41 char buffer[SkMatrix::kMaxFlattenSize + 100];
42 uint32_t size1 = m.flatten(NULL);
43 uint32_t size2 = m.flatten(buffer);
44 REPORTER_ASSERT(reporter, size1 == size2);
45 REPORTER_ASSERT(reporter, size1 <= SkMatrix::kMaxFlattenSize);
46
47 SkMatrix m2;
48 uint32_t size3 = m2.unflatten(buffer);
49 REPORTER_ASSERT(reporter, size1 == size2);
50 REPORTER_ASSERT(reporter, m == m2);
51
52 char buffer2[SkMatrix::kMaxFlattenSize + 100];
53 size3 = m2.flatten(buffer2);
54 REPORTER_ASSERT(reporter, size1 == size2);
55 REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0);
56}
57
reed@android.comed673312009-02-27 16:24:51 +000058void TestMatrix(skiatest::Reporter* reporter) {
59 SkMatrix mat, inverse, iden1, iden2;
60
61 mat.reset();
62 mat.setTranslate(SK_Scalar1, SK_Scalar1);
63 mat.invert(&inverse);
64 iden1.setConcat(mat, inverse);
65 REPORTER_ASSERT(reporter, is_identity(iden1));
66
67 mat.setScale(SkIntToScalar(2), SkIntToScalar(2));
68 mat.invert(&inverse);
69 iden1.setConcat(mat, inverse);
70 REPORTER_ASSERT(reporter, is_identity(iden1));
reed@android.com4b7577b2009-06-29 16:14:41 +000071 test_flatten(reporter, mat);
reed@android.comed673312009-02-27 16:24:51 +000072
73 mat.setScale(SK_Scalar1/2, SK_Scalar1/2);
74 mat.invert(&inverse);
75 iden1.setConcat(mat, inverse);
76 REPORTER_ASSERT(reporter, is_identity(iden1));
reed@android.com4b7577b2009-06-29 16:14:41 +000077 test_flatten(reporter, mat);
reed@android.comed673312009-02-27 16:24:51 +000078
79 mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0);
80 mat.postRotate(SkIntToScalar(25));
81 REPORTER_ASSERT(reporter, mat.invert(NULL));
82 mat.invert(&inverse);
83 iden1.setConcat(mat, inverse);
84 REPORTER_ASSERT(reporter, is_identity(iden1));
85 iden2.setConcat(inverse, mat);
86 REPORTER_ASSERT(reporter, is_identity(iden2));
reed@android.com4b7577b2009-06-29 16:14:41 +000087 test_flatten(reporter, mat);
88 test_flatten(reporter, iden2);
reed@android.com80e39a72009-04-02 16:59:40 +000089
reed@android.comed673312009-02-27 16:24:51 +000090 // rectStaysRect test
91 {
92 static const struct {
93 SkScalar m00, m01, m10, m11;
94 bool mStaysRect;
95 }
96 gRectStaysRectSamples[] = {
97 { 0, 0, 0, 0, false },
98 { 0, 0, 0, SK_Scalar1, false },
99 { 0, 0, SK_Scalar1, 0, false },
100 { 0, 0, SK_Scalar1, SK_Scalar1, false },
101 { 0, SK_Scalar1, 0, 0, false },
102 { 0, SK_Scalar1, 0, SK_Scalar1, false },
103 { 0, SK_Scalar1, SK_Scalar1, 0, true },
104 { 0, SK_Scalar1, SK_Scalar1, SK_Scalar1, false },
105 { SK_Scalar1, 0, 0, 0, false },
106 { SK_Scalar1, 0, 0, SK_Scalar1, true },
107 { SK_Scalar1, 0, SK_Scalar1, 0, false },
108 { SK_Scalar1, 0, SK_Scalar1, SK_Scalar1, false },
109 { SK_Scalar1, SK_Scalar1, 0, 0, false },
110 { SK_Scalar1, SK_Scalar1, 0, SK_Scalar1, false },
111 { SK_Scalar1, SK_Scalar1, SK_Scalar1, 0, false },
112 { SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, false }
113 };
reed@android.com80e39a72009-04-02 16:59:40 +0000114
reed@android.comed673312009-02-27 16:24:51 +0000115 for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) {
116 SkMatrix m;
reed@android.com80e39a72009-04-02 16:59:40 +0000117
reed@android.comed673312009-02-27 16:24:51 +0000118 m.reset();
119 m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00);
120 m.set(SkMatrix::kMSkewX, gRectStaysRectSamples[i].m01);
121 m.set(SkMatrix::kMSkewY, gRectStaysRectSamples[i].m10);
122 m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11);
123 REPORTER_ASSERT(reporter,
124 m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect);
125 }
126 }
bungeman@google.com1ddd7c32011-07-13 19:41:55 +0000127
bungeman@google.comba7983e2011-07-13 20:18:16 +0000128 mat.reset();
bungeman@google.com1ddd7c32011-07-13 19:41:55 +0000129 mat.set(SkMatrix::kMScaleX, SkIntToScalar(1));
130 mat.set(SkMatrix::kMSkewX, SkIntToScalar(2));
131 mat.set(SkMatrix::kMTransX, SkIntToScalar(3));
132 mat.set(SkMatrix::kMSkewY, SkIntToScalar(4));
133 mat.set(SkMatrix::kMScaleY, SkIntToScalar(5));
134 mat.set(SkMatrix::kMTransY, SkIntToScalar(6));
bungeman@google.com1ddd7c32011-07-13 19:41:55 +0000135 SkScalar affine[6];
136 REPORTER_ASSERT(reporter, mat.asAffine(affine));
137
138 #define affineEqual(e) affine[SkMatrix::kA##e] == mat.get(SkMatrix::kM##e)
139 REPORTER_ASSERT(reporter, affineEqual(ScaleX));
140 REPORTER_ASSERT(reporter, affineEqual(SkewY));
141 REPORTER_ASSERT(reporter, affineEqual(SkewX));
142 REPORTER_ASSERT(reporter, affineEqual(ScaleY));
143 REPORTER_ASSERT(reporter, affineEqual(TransX));
144 REPORTER_ASSERT(reporter, affineEqual(TransY));
145 #undef affineEqual
146
147 mat.set(SkMatrix::kMPersp1, SkIntToScalar(1));
148 REPORTER_ASSERT(reporter, !mat.asAffine(affine));
reed@android.comed673312009-02-27 16:24:51 +0000149}
150
reed@android.comd8730ea2009-02-27 22:06:06 +0000151#include "TestClassDef.h"
152DEFINE_TESTCLASS("Matrix", MatrixTestClass, TestMatrix)