blob: 782b51e0bfac69a00e0247eea3c19146ec29568d [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@google.com125002a2011-06-09 19:13:41 +00008#include "Test.h"
9#include "SkMatrix44.h"
10
vollick@chromium.org3959a762012-11-13 15:08:22 +000011static bool nearly_equal_double(double a, double b) {
12 const double tolerance = 1e-7;
13 double diff = a - b;
14 if (diff < 0)
15 diff = -diff;
16 return diff <= tolerance;
17}
18
reed@google.comda9fac02011-06-13 14:46:52 +000019static bool nearly_equal_scalar(SkMScalar a, SkMScalar b) {
reed@google.com125002a2011-06-09 19:13:41 +000020 // Note that we get more compounded error for multiple operations when
21 // SK_SCALAR_IS_FIXED.
22#ifdef SK_SCALAR_IS_FLOAT
23 const SkScalar tolerance = SK_Scalar1 / 200000;
24#else
25 const SkScalar tolerance = SK_Scalar1 / 1024;
26#endif
27
28 return SkScalarAbs(a - b) <= tolerance;
29}
30
reed@google.comda9fac02011-06-13 14:46:52 +000031template <typename T> void assert16(skiatest::Reporter* reporter, const T data[],
32 T m0, T m1, T m2, T m3,
33 T m4, T m5, T m6, T m7,
34 T m8, T m9, T m10, T m11,
35 T m12, T m13, T m14, T m15) {
36 REPORTER_ASSERT(reporter, data[0] == m0);
37 REPORTER_ASSERT(reporter, data[1] == m1);
38 REPORTER_ASSERT(reporter, data[2] == m2);
39 REPORTER_ASSERT(reporter, data[3] == m3);
40
41 REPORTER_ASSERT(reporter, data[4] == m4);
42 REPORTER_ASSERT(reporter, data[5] == m5);
43 REPORTER_ASSERT(reporter, data[6] == m6);
44 REPORTER_ASSERT(reporter, data[7] == m7);
45
46 REPORTER_ASSERT(reporter, data[8] == m8);
47 REPORTER_ASSERT(reporter, data[9] == m9);
48 REPORTER_ASSERT(reporter, data[10] == m10);
49 REPORTER_ASSERT(reporter, data[11] == m11);
50
51 REPORTER_ASSERT(reporter, data[12] == m12);
52 REPORTER_ASSERT(reporter, data[13] == m13);
53 REPORTER_ASSERT(reporter, data[14] == m14);
54 REPORTER_ASSERT(reporter, data[15] == m15);
55}
56
reed@google.com125002a2011-06-09 19:13:41 +000057static bool nearly_equal(const SkMatrix44& a, const SkMatrix44& b) {
58 for (int i = 0; i < 4; ++i) {
59 for (int j = 0; j < 4; ++j) {
60 if (!nearly_equal_scalar(a.get(i, j), b.get(i, j))) {
reed@google.comda9fac02011-06-13 14:46:52 +000061 printf("not equal %g %g\n", a.get(i, j), b.get(i, j));
reed@google.com125002a2011-06-09 19:13:41 +000062 return false;
63 }
64 }
65 }
66 return true;
67}
68
69static bool is_identity(const SkMatrix44& m) {
70 SkMatrix44 identity;
71 identity.reset();
72 return nearly_equal(m, identity);
73}
74
reed@google.com6f2b44d2011-06-24 18:13:39 +000075static void test_common_angles(skiatest::Reporter* reporter) {
76 SkMatrix44 rot;
77 // Test precision of rotation in common cases
78 int common_angles[] = { 0, 90, -90, 180, -180, 270, -270, 360, -360 };
79 for (int i = 0; i < 9; ++i) {
robertphillips@google.com09042b82012-04-06 20:01:46 +000080 rot.setRotateDegreesAbout(0, 0, -1, SkIntToScalar(common_angles[i]));
reed@google.com6f2b44d2011-06-24 18:13:39 +000081
82 SkMatrix rot3x3 = rot;
83 REPORTER_ASSERT(reporter, rot3x3.rectStaysRect());
84 }
85}
86
reed@google.com80b577e2012-11-09 21:25:06 +000087static void test_concat(skiatest::Reporter* reporter) {
88 int i;
89 SkMatrix44 a, b, c, d;
90
91 a.setTranslate(10, 10, 10);
92 b.setScale(2, 2, 2);
93
94 SkScalar src[8] = {
95 0, 0, 0, 1,
96 1, 1, 1, 1
97 };
98 SkScalar dst[8];
99
100 c.setConcat(a, b);
101
102 d = a;
103 d.preConcat(b);
104 REPORTER_ASSERT(reporter, d == c);
skia.committer@gmail.com453995e2012-11-10 02:01:26 +0000105
reed@google.com1ea95be2012-11-09 21:39:48 +0000106 c.mapScalars(src, dst); c.mapScalars(src + 4, dst + 4);
reed@google.com80b577e2012-11-09 21:25:06 +0000107 for (i = 0; i < 3; ++i) {
108 REPORTER_ASSERT(reporter, 10 == dst[i]);
109 REPORTER_ASSERT(reporter, 12 == dst[i + 4]);
110 }
skia.committer@gmail.com453995e2012-11-10 02:01:26 +0000111
reed@google.com80b577e2012-11-09 21:25:06 +0000112 c.setConcat(b, a);
113
114 d = a;
115 d.postConcat(b);
116 REPORTER_ASSERT(reporter, d == c);
117
reed@google.com1ea95be2012-11-09 21:39:48 +0000118 c.mapScalars(src, dst); c.mapScalars(src + 4, dst + 4);
reed@google.com80b577e2012-11-09 21:25:06 +0000119 for (i = 0; i < 3; ++i) {
120 REPORTER_ASSERT(reporter, 20 == dst[i]);
121 REPORTER_ASSERT(reporter, 22 == dst[i + 4]);
122 }
123}
124
vollick@chromium.org3959a762012-11-13 15:08:22 +0000125static void test_determinant(skiatest::Reporter* reporter) {
126 SkMatrix44 a;
127 REPORTER_ASSERT(reporter, nearly_equal_double(1, a.determinant()));
128 a.set(1, 1, SkFloatToMScalar(2));
129 REPORTER_ASSERT(reporter, nearly_equal_double(2, a.determinant()));
130 SkMatrix44 b;
131 REPORTER_ASSERT(reporter, a.invert(&b));
132 REPORTER_ASSERT(reporter, nearly_equal_double(0.5, b.determinant()));
133 SkMatrix44 c = b = a;
134 c.set(0, 1, SkFloatToMScalar(4));
135 b.set(1, 0, SkFloatToMScalar(4));
136 REPORTER_ASSERT(reporter,
137 nearly_equal_double(a.determinant(),
138 b.determinant()));
139 SkMatrix44 d = a;
140 d.set(0, 0, SkFloatToMScalar(8));
141 REPORTER_ASSERT(reporter, nearly_equal_double(16, d.determinant()));
142
143 SkMatrix44 e = a;
144 e.postConcat(d);
145 REPORTER_ASSERT(reporter, nearly_equal_double(32, e.determinant()));
146 e.set(0, 0, SkFloatToMScalar(0));
147 REPORTER_ASSERT(reporter, nearly_equal_double(0, e.determinant()));
148}
149
vollick@chromium.org9b21c252012-11-14 21:33:55 +0000150static void test_transpose(skiatest::Reporter* reporter) {
151 SkMatrix44 a;
152 SkMatrix44 b;
153
154 int i = 0;
155 for (int row = 0; row < 4; ++row) {
156 for (int col = 0; col < 4; ++col) {
157 a.setDouble(row, col, i);
158 b.setDouble(col, row, i++);
159 }
160 }
161
162 a.transpose();
163 REPORTER_ASSERT(reporter, nearly_equal(a, b));
164}
165
166static void test_get_set_double(skiatest::Reporter* reporter) {
167 SkMatrix44 a;
168 for (int row = 0; row < 4; ++row) {
169 for (int col = 0; col < 4; ++col) {
170 a.setDouble(row, col, 3.141592653589793);
171 REPORTER_ASSERT(reporter, nearly_equal_double(3.141592653589793,
172 a.getDouble(row, col)));
173 a.setDouble(row, col, 0);
174 REPORTER_ASSERT(reporter, nearly_equal_double(0, a.getDouble(row, col)));
175 }
176 }
177}
178
caryclark@google.com42639cd2012-06-06 12:03:39 +0000179static void TestMatrix44(skiatest::Reporter* reporter) {
reed@google.comda9fac02011-06-13 14:46:52 +0000180#ifdef SK_SCALAR_IS_FLOAT
reed@google.com125002a2011-06-09 19:13:41 +0000181 SkMatrix44 mat, inverse, iden1, iden2, rot;
182
183 mat.reset();
184 mat.setTranslate(SK_Scalar1, SK_Scalar1, SK_Scalar1);
185 mat.invert(&inverse);
186 iden1.setConcat(mat, inverse);
187 REPORTER_ASSERT(reporter, is_identity(iden1));
188
189 mat.setScale(SkIntToScalar(2), SkIntToScalar(2), SkIntToScalar(2));
190 mat.invert(&inverse);
191 iden1.setConcat(mat, inverse);
192 REPORTER_ASSERT(reporter, is_identity(iden1));
193
194 mat.setScale(SK_Scalar1/2, SK_Scalar1/2, SK_Scalar1/2);
195 mat.invert(&inverse);
196 iden1.setConcat(mat, inverse);
197 REPORTER_ASSERT(reporter, is_identity(iden1));
198
199 mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20));
200 rot.setRotateDegreesAbout(
201 SkIntToScalar(0),
202 SkIntToScalar(0),
203 SkIntToScalar(-1),
204 SkIntToScalar(90));
205 mat.postConcat(rot);
206 REPORTER_ASSERT(reporter, mat.invert(NULL));
207 mat.invert(&inverse);
208 iden1.setConcat(mat, inverse);
209 REPORTER_ASSERT(reporter, is_identity(iden1));
210 iden2.setConcat(inverse, mat);
211 REPORTER_ASSERT(reporter, is_identity(iden2));
reed@google.comda9fac02011-06-13 14:46:52 +0000212
213 // test rol/col Major getters
214 {
215 mat.setTranslate(2, 3, 4);
216 float dataf[16];
217 double datad[16];
rmistry@google.comd6176b02012-08-23 18:14:13 +0000218
reed@google.comda9fac02011-06-13 14:46:52 +0000219 mat.asColMajorf(dataf);
220 assert16<float>(reporter, dataf,
221 1, 0, 0, 0,
222 0, 1, 0, 0,
223 0, 0, 1, 0,
224 2, 3, 4, 1);
225 mat.asColMajord(datad);
226 assert16<double>(reporter, datad, 1, 0, 0, 0,
227 0, 1, 0, 0,
228 0, 0, 1, 0,
229 2, 3, 4, 1);
230 mat.asRowMajorf(dataf);
231 assert16<float>(reporter, dataf, 1, 0, 0, 2,
232 0, 1, 0, 3,
233 0, 0, 1, 4,
234 0, 0, 0, 1);
235 mat.asRowMajord(datad);
236 assert16<double>(reporter, datad, 1, 0, 0, 2,
237 0, 1, 0, 3,
238 0, 0, 1, 4,
239 0, 0, 0, 1);
240 }
reed@google.com6f2b44d2011-06-24 18:13:39 +0000241
reed@google.com80b577e2012-11-09 21:25:06 +0000242 test_concat(reporter);
243
caryclark@google.com42639cd2012-06-06 12:03:39 +0000244 if (false) { // avoid bit rot, suppress warning (working on making this pass)
245 test_common_angles(reporter);
246 }
vollick@chromium.org3959a762012-11-13 15:08:22 +0000247
248 test_determinant(reporter);
vollick@chromium.org9b21c252012-11-14 21:33:55 +0000249 test_transpose(reporter);
250 test_get_set_double(reporter);
reed@google.comda9fac02011-06-13 14:46:52 +0000251#endif
reed@google.com125002a2011-06-09 19:13:41 +0000252}
253
254#include "TestClassDef.h"
255DEFINE_TESTCLASS("Matrix44", Matrix44TestClass, TestMatrix44)