OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
sky
2011/06/09 17:20:29
2011
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/basictypes.h" | |
6 #include "testing/gtest/include/gtest/gtest.h" | |
7 #include "third_party/eigen/Eigen/Geometry" | |
8 #include "ui/gfx/transform.h" | |
9 #include "ui/gfx/point.h" | |
10 #include <iostream> | |
11 #include <limits> | |
12 | |
13 typedef testing::Test XFormTest; | |
14 | |
15 #ifdef NDEBUG | |
16 TEST(XFormTest, MatrixMultStressTest) { | |
17 ui::Transform xform; | |
18 for (int i = 0; i < 1000000; ++i) { | |
19 xform.ConcatRotate(3.0f); | |
20 xform.ConcatScale(2.0f, 2.0f); | |
21 xform.ConcatTranslate(1.0f, 2.0f); | |
22 xform.ConcatScale(0.5f, 0.5f); | |
23 } | |
24 } | |
25 #endif | |
26 | |
27 TEST(XFormTest, ConcatTranslate) { | |
28 static const struct TestCase { | |
sky
2011/06/09 17:20:29
Why are any of these 'static const'?
| |
29 int x1; | |
30 int y1; | |
31 float tx; | |
32 float ty; | |
33 int x2; | |
34 int y2; | |
35 } test_cases[] = { | |
36 { 0, 0, 10.0f, 20.0f, 10, 20 }, | |
37 { 0, 0, -10.0f, -20.0f, 0, 0 }, | |
38 { 0, 0, -10.0f, -20.0f, -10, -20 }, | |
39 { 0, 0, | |
40 std::numeric_limits<float>::quiet_NaN(), | |
41 std::numeric_limits<float>::quiet_NaN(), | |
42 10, 20 }, | |
43 }; | |
44 | |
45 ui::Transform xform; | |
46 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
47 const TestCase& value = test_cases[i]; | |
48 xform.ConcatTranslate(value.tx, value.ty); | |
49 gfx::Point p1(value.x1, value.y1); | |
50 gfx::Point p2(value.x2, value.y2); | |
51 xform.TransformPoint(&p1); | |
52 if (value.tx == value.tx && | |
53 value.ty == value.ty) { | |
54 EXPECT_EQ(p1.x(), p2.x()); | |
55 EXPECT_EQ(p1.y(), p2.y()); | |
56 } | |
57 } | |
58 } | |
59 | |
60 TEST(XFormTest, ConcatScale) { | |
61 static const struct TestCase { | |
62 int before; | |
63 float scale; | |
64 int after; | |
65 } test_cases[] = { | |
66 { 1, 10.0f, 10 }, | |
67 { 1, .1f, 1 }, | |
68 { 1, 100.0f, 100 }, | |
69 { 1, -1.0f, -100 }, | |
70 { 1, std::numeric_limits<float>::quiet_NaN(), 1 } | |
71 }; | |
72 | |
73 ui::Transform xform; | |
74 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
75 const TestCase& value = test_cases[i]; | |
76 xform.ConcatScale(value.scale, value.scale); | |
77 gfx::Point p1(value.before, value.before); | |
78 gfx::Point p2(value.after, value.after); | |
79 xform.TransformPoint(&p1); | |
80 if (value.scale == value.scale) { | |
81 EXPECT_EQ(p1.x(), p2.x()); | |
82 EXPECT_EQ(p1.y(), p2.y()); | |
83 } | |
84 } | |
85 } | |
86 | |
87 TEST(XFormTest, ConcatRotate) { | |
88 static const struct TestCase { | |
89 int x1; | |
90 int y1; | |
91 float degrees; | |
92 int x2; | |
93 int y2; | |
94 } test_cases[] = { | |
95 { 1, 0, 90.0f, 0, 1 }, | |
96 { 1, 0, -90.0f, 1, 0 }, | |
97 { 1, 0, 90.0f, 0, 1 }, | |
98 { 1, 0, 360.0f, 0, 1 }, | |
99 { 1, 0, 0.0f, 0, 1 }, | |
100 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0 } | |
101 }; | |
102 | |
103 ui::Transform xform; | |
104 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
105 const TestCase& value = test_cases[i]; | |
106 xform.ConcatRotate(value.degrees); | |
107 gfx::Point p1(value.x1, value.y1); | |
108 gfx::Point p2(value.x2, value.y2); | |
109 xform.TransformPoint(&p1); | |
110 if (value.degrees == value.degrees) { | |
111 EXPECT_EQ(p1.x(), p2.x()); | |
112 EXPECT_EQ(p1.y(), p2.y()); | |
113 } | |
114 } | |
115 } | |
116 | |
117 TEST(XFormTest, SetTranslate) { | |
118 static const struct TestCase { | |
119 int x1; int y1; | |
120 float tx; float ty; | |
121 int x2; int y2; | |
122 } test_cases[] = { | |
123 { 0, 0, 10.0f, 20.0f, 10, 20 }, | |
124 { 10, 20, 10.0f, 20.0f, 20, 40 }, | |
125 { 10, 20, 0.0f, 0.0f, 10, 20 }, | |
126 { 0, 0, | |
127 std::numeric_limits<float>::quiet_NaN(), | |
128 std::numeric_limits<float>::quiet_NaN(), | |
129 0, 0 } | |
130 }; | |
131 | |
132 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
133 const TestCase& value = test_cases[i]; | |
134 for (int j = -1; j < 2; ++j) { | |
135 for (int k = 0; k < 3; ++k) { | |
136 float epsilon = 0.0001f; | |
137 gfx::Point p0, p1, p2; | |
138 ui::Transform xform; | |
139 switch (k) { | |
140 case 0: | |
141 p1.SetPoint(value.x1, 0); | |
142 p2.SetPoint(value.x2, 0); | |
143 xform.SetTranslateX(value.tx + j * epsilon); | |
144 break; | |
145 case 1: | |
146 p1.SetPoint(0, value.y1); | |
147 p2.SetPoint(0, value.y2); | |
148 xform.SetTranslateY(value.ty + j * epsilon); | |
149 break; | |
150 case 2: | |
151 p1.SetPoint(value.x1, value.y1); | |
152 p2.SetPoint(value.x2, value.y2); | |
153 xform.SetTranslate(value.tx + j * epsilon, | |
154 value.ty + j * epsilon); | |
155 break; | |
156 } | |
157 p0 = p1; | |
158 xform.TransformPoint(&p1); | |
159 if (value.tx == value.tx && | |
160 value.ty == value.ty) { | |
161 EXPECT_EQ(p1.x(), p2.x()); | |
162 EXPECT_EQ(p1.y(), p2.y()); | |
163 xform.TransformPointReverse(&p1); | |
164 EXPECT_EQ(p1.x(), p0.x()); | |
165 EXPECT_EQ(p1.y(), p0.y()); | |
166 } | |
167 } | |
168 } | |
169 } | |
170 } | |
171 | |
172 TEST(XFormTest, SetScale) { | |
173 static const struct TestCase { | |
174 int before; | |
175 float s; | |
176 int after; | |
177 } test_cases[] = { | |
178 { 1, 10.0f, 10 }, | |
179 { 1, 1.0f, 1 }, | |
180 { 1, 0.0f, 0 }, | |
181 { 0, 10.0f, 0 }, | |
182 { 1, std::numeric_limits<float>::quiet_NaN(), 0 }, | |
183 }; | |
184 | |
185 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
186 const TestCase& value = test_cases[i]; | |
187 for (int j = -1; j < 2; ++j) { | |
188 for (int k = 0; k < 3; ++k) { | |
189 float epsilon = 0.0001f; | |
190 gfx::Point p0, p1, p2; | |
191 ui::Transform xform; | |
192 switch (k) { | |
193 case 0: | |
194 p1.SetPoint(value.before, 0); | |
195 p2.SetPoint(value.after, 0); | |
196 xform.SetScaleX(value.s + j * epsilon); | |
197 break; | |
198 case 1: | |
199 p1.SetPoint(0, value.before); | |
200 p2.SetPoint(0, value.after); | |
201 xform.SetScaleY(value.s + j * epsilon); | |
202 break; | |
203 case 2: | |
204 p1.SetPoint(value.before, | |
205 value.before); | |
206 p2.SetPoint(value.after, | |
207 value.after); | |
208 xform.SetScale(value.s + j * epsilon, | |
209 value.s + j * epsilon); | |
210 break; | |
211 } | |
212 p0 = p1; | |
213 xform.TransformPoint(&p1); | |
214 if (value.s == value.s) { | |
215 EXPECT_EQ(p1.x(), p2.x()); | |
216 EXPECT_EQ(p1.y(), p2.y()); | |
217 if (value.s != 0.0f) { | |
218 xform.TransformPointReverse(&p1); | |
219 EXPECT_EQ(p1.x(), p0.x()); | |
220 EXPECT_EQ(p1.y(), p0.y()); | |
221 } | |
222 } | |
223 } | |
224 } | |
225 } | |
226 } | |
227 | |
228 TEST(XFormTest, SetRotate) { | |
229 static const struct SetRotateCase { | |
230 int x; | |
231 int y; | |
232 float degree; | |
233 int xprime; | |
234 int yprime; | |
235 } set_rotate_cases[] = { | |
236 { 100, 0, 90.0f, 0, 100 }, | |
237 { 0, 0, 90.0f, 0, 0 }, | |
238 { 0, 100, 90.0f, -100, 0 }, | |
239 { 100, 0, 0.0f, 100, 0 }, | |
240 { 0, 0, 0.0f, 0, 0 }, | |
241 { 0, 0, std::numeric_limits<float>::quiet_NaN(), 0, 0 }, | |
242 { 100, 0, 360.0f, 100, 0 } | |
243 }; | |
244 | |
245 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) { | |
246 const SetRotateCase& value = set_rotate_cases[i]; | |
247 for (int j = -1; j < 2; ++j) { | |
248 float epsilon = 0.0001f; | |
249 gfx::Point pt(value.x, value.y); | |
250 ui::Transform xform; | |
251 // should be invariant to small floating point errors. | |
252 xform.SetRotate(value.degree + j * epsilon); | |
253 // just want to make sure that we don't crash in the case of NaN. | |
254 if (value.degree == value.degree) { | |
255 xform.TransformPoint(&pt); | |
256 EXPECT_EQ(value.xprime, pt.x()); | |
257 EXPECT_EQ(value.yprime, pt.y()); | |
258 xform.TransformPointReverse(&pt); | |
259 EXPECT_EQ(pt.x(), value.x); | |
260 EXPECT_EQ(pt.y(), value.y); | |
261 } | |
262 } | |
263 } | |
264 } | |
OLD | NEW |