blob: 4125f9f24305c804c82ea076e05bb14fd4febb4d [file] [log] [blame]
reed@android.comed673312009-02-27 16:24:51 +00001#include "Test.h"
2#include "SkMatrix.h"
3
4static bool nearly_equal_scalar(SkScalar a, SkScalar b) {
epoger@google.com2047f002011-05-17 17:36:59 +00005 // Note that we get more compounded error for multiple operations when
6 // SK_SCALAR_IS_FIXED.
reed@android.comed673312009-02-27 16:24:51 +00007#ifdef SK_SCALAR_IS_FLOAT
epoger@google.com2047f002011-05-17 17:36:59 +00008 const SkScalar tolerance = SK_Scalar1 / 200000;
reed@android.comed673312009-02-27 16:24:51 +00009#else
epoger@google.com2047f002011-05-17 17:36:59 +000010 const SkScalar tolerance = SK_Scalar1 / 1024;
reed@android.comed673312009-02-27 16:24:51 +000011#endif
12
13 return SkScalarAbs(a - b) <= tolerance;
14}
15
16static bool nearly_equal(const SkMatrix& a, const SkMatrix& b) {
17 for (int i = 0; i < 9; i++) {
18 if (!nearly_equal_scalar(a[i], b[i])) {
reed@android.comd4134452011-02-09 02:24:26 +000019 printf("not equal %g %g\n", (float)a[i], (float)b[i]);
reed@android.comed673312009-02-27 16:24:51 +000020 return false;
21 }
22 }
23 return true;
24}
25
26static bool is_identity(const SkMatrix& m) {
27 SkMatrix identity;
reed@android.com80e39a72009-04-02 16:59:40 +000028 identity.reset();
reed@android.comed673312009-02-27 16:24:51 +000029 return nearly_equal(m, identity);
30}
31
reed@android.com4b7577b2009-06-29 16:14:41 +000032static void test_flatten(skiatest::Reporter* reporter, const SkMatrix& m) {
33 // add 100 in case we have a bug, I don't want to kill my stack in the test
34 char buffer[SkMatrix::kMaxFlattenSize + 100];
35 uint32_t size1 = m.flatten(NULL);
36 uint32_t size2 = m.flatten(buffer);
37 REPORTER_ASSERT(reporter, size1 == size2);
38 REPORTER_ASSERT(reporter, size1 <= SkMatrix::kMaxFlattenSize);
39
40 SkMatrix m2;
41 uint32_t size3 = m2.unflatten(buffer);
42 REPORTER_ASSERT(reporter, size1 == size2);
43 REPORTER_ASSERT(reporter, m == m2);
44
45 char buffer2[SkMatrix::kMaxFlattenSize + 100];
46 size3 = m2.flatten(buffer2);
47 REPORTER_ASSERT(reporter, size1 == size2);
48 REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0);
49}
50
reed@android.comed673312009-02-27 16:24:51 +000051void TestMatrix(skiatest::Reporter* reporter) {
52 SkMatrix mat, inverse, iden1, iden2;
53
54 mat.reset();
55 mat.setTranslate(SK_Scalar1, SK_Scalar1);
56 mat.invert(&inverse);
57 iden1.setConcat(mat, inverse);
58 REPORTER_ASSERT(reporter, is_identity(iden1));
59
60 mat.setScale(SkIntToScalar(2), SkIntToScalar(2));
61 mat.invert(&inverse);
62 iden1.setConcat(mat, inverse);
63 REPORTER_ASSERT(reporter, is_identity(iden1));
reed@android.com4b7577b2009-06-29 16:14:41 +000064 test_flatten(reporter, mat);
reed@android.comed673312009-02-27 16:24:51 +000065
66 mat.setScale(SK_Scalar1/2, SK_Scalar1/2);
67 mat.invert(&inverse);
68 iden1.setConcat(mat, inverse);
69 REPORTER_ASSERT(reporter, is_identity(iden1));
reed@android.com4b7577b2009-06-29 16:14:41 +000070 test_flatten(reporter, mat);
reed@android.comed673312009-02-27 16:24:51 +000071
72 mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0);
73 mat.postRotate(SkIntToScalar(25));
74 REPORTER_ASSERT(reporter, mat.invert(NULL));
75 mat.invert(&inverse);
76 iden1.setConcat(mat, inverse);
77 REPORTER_ASSERT(reporter, is_identity(iden1));
78 iden2.setConcat(inverse, mat);
79 REPORTER_ASSERT(reporter, is_identity(iden2));
reed@android.com4b7577b2009-06-29 16:14:41 +000080 test_flatten(reporter, mat);
81 test_flatten(reporter, iden2);
reed@android.com80e39a72009-04-02 16:59:40 +000082
reed@android.comed673312009-02-27 16:24:51 +000083 // rectStaysRect test
84 {
85 static const struct {
86 SkScalar m00, m01, m10, m11;
87 bool mStaysRect;
88 }
89 gRectStaysRectSamples[] = {
90 { 0, 0, 0, 0, false },
91 { 0, 0, 0, SK_Scalar1, false },
92 { 0, 0, SK_Scalar1, 0, false },
93 { 0, 0, SK_Scalar1, SK_Scalar1, false },
94 { 0, SK_Scalar1, 0, 0, false },
95 { 0, SK_Scalar1, 0, SK_Scalar1, false },
96 { 0, SK_Scalar1, SK_Scalar1, 0, true },
97 { 0, SK_Scalar1, SK_Scalar1, SK_Scalar1, false },
98 { SK_Scalar1, 0, 0, 0, false },
99 { SK_Scalar1, 0, 0, SK_Scalar1, true },
100 { SK_Scalar1, 0, SK_Scalar1, 0, false },
101 { SK_Scalar1, 0, SK_Scalar1, SK_Scalar1, false },
102 { SK_Scalar1, SK_Scalar1, 0, 0, false },
103 { SK_Scalar1, SK_Scalar1, 0, SK_Scalar1, false },
104 { SK_Scalar1, SK_Scalar1, SK_Scalar1, 0, false },
105 { SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, false }
106 };
reed@android.com80e39a72009-04-02 16:59:40 +0000107
reed@android.comed673312009-02-27 16:24:51 +0000108 for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) {
109 SkMatrix m;
reed@android.com80e39a72009-04-02 16:59:40 +0000110
reed@android.comed673312009-02-27 16:24:51 +0000111 m.reset();
112 m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00);
113 m.set(SkMatrix::kMSkewX, gRectStaysRectSamples[i].m01);
114 m.set(SkMatrix::kMSkewY, gRectStaysRectSamples[i].m10);
115 m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11);
116 REPORTER_ASSERT(reporter,
117 m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect);
118 }
119 }
120}
121
reed@android.comd8730ea2009-02-27 22:06:06 +0000122#include "TestClassDef.h"
123DEFINE_TESTCLASS("Matrix", MatrixTestClass, TestMatrix)