OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2006-2011 The Chromium Authors. All rights reserved. | |
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/point3.h" | |
10 #include <iostream> | |
11 #include <limits> | |
12 | |
13 typedef testing::Test XFormTest; | |
14 | |
15 namespace { | |
16 bool PointsAreNearlyEqual(const gfx::Point3f& lhs, | |
17 const gfx::Point3f& rhs) { | |
18 float epsilon = 0.0001f; | |
19 return lhs.SquaredDistanceTo(rhs) < epsilon; | |
20 } | |
21 } | |
22 | |
23 #ifdef NDEBUG | |
sky
2011/06/17 18:43:41
Use #if defined().
I think you want:
#if !defined(
| |
24 TEST(XFormTest, MatrixMultStressTest) { | |
25 ui::Transform xform; | |
26 for (int i = 0; i < 1000000; ++i) { | |
27 xform.ConcatRotate(3.0f); | |
28 xform.ConcatScale(2.0f, 2.0f); | |
29 xform.ConcatTranslate(1.0f, 2.0f); | |
30 xform.ConcatScale(0.5f, 0.5f); | |
31 } | |
32 } | |
33 #endif | |
34 | |
35 TEST(XFormTest, ConcatTranslate) { | |
36 static const struct TestCase { | |
37 int x1; | |
38 int y1; | |
39 float tx; | |
40 float ty; | |
41 int x2; | |
42 int y2; | |
43 } test_cases[] = { | |
44 { 0, 0, 10.0f, 20.0f, 10, 20 }, | |
45 { 0, 0, -10.0f, -20.0f, 0, 0 }, | |
46 { 0, 0, -10.0f, -20.0f, -10, -20 }, | |
47 { 0, 0, | |
48 std::numeric_limits<float>::quiet_NaN(), | |
49 std::numeric_limits<float>::quiet_NaN(), | |
50 10, 20 }, | |
51 }; | |
52 | |
53 ui::Transform xform; | |
54 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
55 const TestCase& value = test_cases[i]; | |
56 xform.ConcatTranslate(value.tx, value.ty); | |
57 gfx::Point3f p1(value.x1, value.y1, 0); | |
58 gfx::Point3f p2(value.x2, value.y2, 0); | |
59 xform.TransformPoint(p1); | |
60 if (value.tx == value.tx && | |
61 value.ty == value.ty) { | |
62 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | |
63 } | |
64 } | |
65 } | |
66 | |
67 TEST(XFormTest, ConcatScale) { | |
68 static const struct TestCase { | |
69 int before; | |
70 float scale; | |
71 int after; | |
72 } test_cases[] = { | |
73 { 1, 10.0f, 10 }, | |
74 { 1, .1f, 1 }, | |
75 { 1, 100.0f, 100 }, | |
76 { 1, -1.0f, -100 }, | |
77 { 1, std::numeric_limits<float>::quiet_NaN(), 1 } | |
78 }; | |
79 | |
80 ui::Transform xform; | |
81 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
82 const TestCase& value = test_cases[i]; | |
83 xform.ConcatScale(value.scale, value.scale); | |
84 gfx::Point3f p1(value.before, value.before, 0); | |
85 gfx::Point3f p2(value.after, value.after, 0); | |
86 xform.TransformPoint(p1); | |
87 if (value.scale == value.scale) { | |
88 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | |
89 } | |
90 } | |
91 } | |
92 | |
93 TEST(XFormTest, ConcatRotate) { | |
94 static const struct TestCase { | |
95 int x1; | |
96 int y1; | |
97 float degrees; | |
98 int x2; | |
99 int y2; | |
100 } test_cases[] = { | |
101 { 1, 0, 90.0f, 0, 1 }, | |
102 { 1, 0, -90.0f, 1, 0 }, | |
103 { 1, 0, 90.0f, 0, 1 }, | |
104 { 1, 0, 360.0f, 0, 1 }, | |
105 { 1, 0, 0.0f, 0, 1 }, | |
106 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0 } | |
107 }; | |
108 | |
109 ui::Transform xform; | |
110 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
111 const TestCase& value = test_cases[i]; | |
112 xform.ConcatRotate(value.degrees); | |
113 gfx::Point3f p1(value.x1, value.y1, 0); | |
114 gfx::Point3f p2(value.x2, value.y2, 0); | |
115 xform.TransformPoint(p1); | |
116 if (value.degrees == value.degrees) { | |
117 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | |
118 } | |
119 } | |
120 } | |
121 | |
122 TEST(XFormTest, SetTranslate) { | |
123 static const struct TestCase { | |
124 int x1; int y1; | |
125 float tx; float ty; | |
126 int x2; int y2; | |
127 } test_cases[] = { | |
128 { 0, 0, 10.0f, 20.0f, 10, 20 }, | |
129 { 10, 20, 10.0f, 20.0f, 20, 40 }, | |
130 { 10, 20, 0.0f, 0.0f, 10, 20 }, | |
131 { 0, 0, | |
132 std::numeric_limits<float>::quiet_NaN(), | |
133 std::numeric_limits<float>::quiet_NaN(), | |
134 0, 0 } | |
135 }; | |
136 | |
137 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
138 const TestCase& value = test_cases[i]; | |
139 for (int k = 0; k < 3; ++k) { | |
140 gfx::Point3f p0, p1, p2; | |
141 ui::Transform xform; | |
142 switch (k) { | |
143 case 0: | |
144 p1.SetPoint(value.x1, 0, 0); | |
145 p2.SetPoint(value.x2, 0, 0); | |
146 xform.SetTranslateX(value.tx); | |
147 break; | |
148 case 1: | |
149 p1.SetPoint(0, value.y1, 0); | |
150 p2.SetPoint(0, value.y2, 0); | |
151 xform.SetTranslateY(value.ty); | |
152 break; | |
153 case 2: | |
154 p1.SetPoint(value.x1, value.y1, 0); | |
155 p2.SetPoint(value.x2, value.y2, 0); | |
156 xform.SetTranslate(value.tx, value.ty); | |
157 break; | |
158 } | |
159 p0 = p1; | |
160 xform.TransformPoint(p1); | |
161 if (value.tx == value.tx && | |
162 value.ty == value.ty) { | |
163 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | |
164 xform.TransformPointReverse(p1); | |
165 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); | |
166 } | |
167 } | |
168 } | |
169 } | |
170 | |
171 TEST(XFormTest, SetScale) { | |
172 static const struct TestCase { | |
173 int before; | |
174 float s; | |
175 int after; | |
176 } test_cases[] = { | |
177 { 1, 10.0f, 10 }, | |
178 { 1, 1.0f, 1 }, | |
179 { 1, 0.0f, 0 }, | |
180 { 0, 10.0f, 0 }, | |
181 { 1, std::numeric_limits<float>::quiet_NaN(), 0 }, | |
182 }; | |
183 | |
184 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
185 const TestCase& value = test_cases[i]; | |
186 for (int k = 0; k < 3; ++k) { | |
187 gfx::Point3f p0, p1, p2; | |
188 ui::Transform xform; | |
189 switch (k) { | |
190 case 0: | |
191 p1.SetPoint(value.before, 0, 0); | |
192 p2.SetPoint(value.after, 0, 0); | |
193 xform.SetScaleX(value.s); | |
194 break; | |
195 case 1: | |
196 p1.SetPoint(0, value.before, 0); | |
197 p2.SetPoint(0, value.after, 0); | |
198 xform.SetScaleY(value.s); | |
199 break; | |
200 case 2: | |
201 p1.SetPoint(value.before, value.before, 0); | |
202 p2.SetPoint(value.after, value.after, 0); | |
203 xform.SetScale(value.s, value.s); | |
204 break; | |
205 } | |
206 p0 = p1; | |
207 xform.TransformPoint(p1); | |
208 if (value.s == value.s) { | |
209 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | |
210 if (value.s != 0.0f) { | |
211 xform.TransformPointReverse(p1); | |
212 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); | |
213 } | |
214 } | |
215 } | |
216 } | |
217 } | |
218 | |
219 TEST(XFormTest, SetRotate) { | |
220 static const struct SetRotateCase { | |
221 int x; | |
222 int y; | |
223 float degree; | |
224 int xprime; | |
225 int yprime; | |
226 } set_rotate_cases[] = { | |
227 { 100, 0, 90.0f, 0, 100 }, | |
228 { 0, 0, 90.0f, 0, 0 }, | |
229 { 0, 100, 90.0f, -100, 0 }, | |
230 { 0, 1, -90.0f, 1, 0 }, | |
231 { 100, 0, 0.0f, 100, 0 }, | |
232 { 0, 0, 0.0f, 0, 0 }, | |
233 { 0, 0, std::numeric_limits<float>::quiet_NaN(), 0, 0 }, | |
234 { 100, 0, 360.0f, 100, 0 } | |
235 }; | |
236 | |
237 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) { | |
238 const SetRotateCase& value = set_rotate_cases[i]; | |
239 gfx::Point3f p0; | |
240 gfx::Point3f p1(value.x, value.y, 0); | |
241 gfx::Point3f p2(value.xprime, value.yprime, 0); | |
242 p0 = p1; | |
243 ui::Transform xform; | |
244 xform.SetRotate(value.degree); | |
245 // just want to make sure that we don't crash in the case of NaN. | |
246 if (value.degree == value.degree) { | |
247 xform.TransformPoint(p1); | |
248 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | |
249 xform.TransformPointReverse(p1); | |
250 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); | |
251 } | |
252 } | |
253 } | |
254 | |
255 // 2D tests | |
256 TEST(XFormTest, ConcatTranslate2D) { | |
257 static const struct TestCase { | |
258 int x1; | |
259 int y1; | |
260 float tx; | |
261 float ty; | |
262 int x2; | |
263 int y2; | |
264 } test_cases[] = { | |
265 { 0, 0, 10.0f, 20.0f, 10, 20}, | |
266 { 0, 0, -10.0f, -20.0f, 0, 0}, | |
267 { 0, 0, -10.0f, -20.0f, -10, -20}, | |
268 { 0, 0, | |
269 std::numeric_limits<float>::quiet_NaN(), | |
270 std::numeric_limits<float>::quiet_NaN(), | |
271 10, 20}, | |
272 }; | |
273 | |
274 ui::Transform xform; | |
275 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
276 const TestCase& value = test_cases[i]; | |
277 xform.ConcatTranslate(value.tx, value.ty); | |
278 gfx::Point p1(value.x1, value.y1); | |
279 gfx::Point p2(value.x2, value.y2); | |
280 xform.TransformPoint(p1); | |
281 if (value.tx == value.tx && | |
282 value.ty == value.ty) { | |
283 EXPECT_EQ(p1.x(), p2.x()); | |
284 EXPECT_EQ(p1.y(), p2.y()); | |
285 } | |
286 } | |
287 } | |
288 | |
289 TEST(XFormTest, ConcatScale2D) { | |
290 static const struct TestCase { | |
291 int before; | |
292 float scale; | |
293 int after; | |
294 } test_cases[] = { | |
295 { 1, 10.0f, 10}, | |
296 { 1, .1f, 1}, | |
297 { 1, 100.0f, 100}, | |
298 { 1, -1.0f, -100}, | |
299 { 1, std::numeric_limits<float>::quiet_NaN(), 1} | |
300 }; | |
301 | |
302 ui::Transform xform; | |
303 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
304 const TestCase& value = test_cases[i]; | |
305 xform.ConcatScale(value.scale, value.scale); | |
306 gfx::Point p1(value.before, value.before); | |
307 gfx::Point p2(value.after, value.after); | |
308 xform.TransformPoint(p1); | |
309 if (value.scale == value.scale) { | |
310 EXPECT_EQ(p1.x(), p2.x()); | |
311 EXPECT_EQ(p1.y(), p2.y()); | |
312 } | |
313 } | |
314 } | |
315 | |
316 TEST(XFormTest, ConcatRotate2D) { | |
317 static const struct TestCase { | |
318 int x1; | |
319 int y1; | |
320 float degrees; | |
321 int x2; | |
322 int y2; | |
323 } test_cases[] = { | |
324 { 1, 0, 90.0f, 0, 1}, | |
325 { 1, 0, -90.0f, 1, 0}, | |
326 { 1, 0, 90.0f, 0, 1}, | |
327 { 1, 0, 360.0f, 0, 1}, | |
328 { 1, 0, 0.0f, 0, 1}, | |
329 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0} | |
330 }; | |
331 | |
332 ui::Transform xform; | |
333 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
334 const TestCase& value = test_cases[i]; | |
335 xform.ConcatRotate(value.degrees); | |
336 gfx::Point p1(value.x1, value.y1); | |
337 gfx::Point p2(value.x2, value.y2); | |
338 xform.TransformPoint(p1); | |
339 if (value.degrees == value.degrees) { | |
340 EXPECT_EQ(p1.x(), p2.x()); | |
341 EXPECT_EQ(p1.y(), p2.y()); | |
342 } | |
343 } | |
344 } | |
345 | |
346 TEST(XFormTest, SetTranslate2D) { | |
347 static const struct TestCase { | |
348 int x1; int y1; | |
349 float tx; float ty; | |
350 int x2; int y2; | |
351 } test_cases[] = { | |
352 { 0, 0, 10.0f, 20.0f, 10, 20}, | |
353 { 10, 20, 10.0f, 20.0f, 20, 40}, | |
354 { 10, 20, 0.0f, 0.0f, 10, 20}, | |
355 { 0, 0, | |
356 std::numeric_limits<float>::quiet_NaN(), | |
357 std::numeric_limits<float>::quiet_NaN(), | |
358 0, 0} | |
359 }; | |
360 | |
361 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
362 const TestCase& value = test_cases[i]; | |
363 for (int j = -1; j < 2; ++j) { | |
364 for (int k = 0; k < 3; ++k) { | |
365 float epsilon = 0.0001f; | |
366 gfx::Point p0, p1, p2; | |
367 ui::Transform xform; | |
368 switch (k) { | |
369 case 0: | |
370 p1.SetPoint(value.x1, 0); | |
371 p2.SetPoint(value.x2, 0); | |
372 xform.SetTranslateX(value.tx + j * epsilon); | |
373 break; | |
374 case 1: | |
375 p1.SetPoint(0, value.y1); | |
376 p2.SetPoint(0, value.y2); | |
377 xform.SetTranslateY(value.ty + j * epsilon); | |
378 break; | |
379 case 2: | |
380 p1.SetPoint(value.x1, value.y1); | |
381 p2.SetPoint(value.x2, value.y2); | |
382 xform.SetTranslate(value.tx + j * epsilon, | |
383 value.ty + j * epsilon); | |
384 break; | |
385 } | |
386 p0 = p1; | |
387 xform.TransformPoint(p1); | |
388 if (value.tx == value.tx && | |
389 value.ty == value.ty) { | |
390 EXPECT_EQ(p1.x(), p2.x()); | |
391 EXPECT_EQ(p1.y(), p2.y()); | |
392 xform.TransformPointReverse(p1); | |
393 EXPECT_EQ(p1.x(), p0.x()); | |
394 EXPECT_EQ(p1.y(), p0.y()); | |
395 } | |
396 } | |
397 } | |
398 } | |
399 } | |
400 | |
401 TEST(XFormTest, SetScale2D) { | |
402 static const struct TestCase { | |
403 int before; | |
404 float s; | |
405 int after; | |
406 } test_cases[] = { | |
407 { 1, 10.0f, 10}, | |
408 { 1, 1.0f, 1}, | |
409 { 1, 0.0f, 0}, | |
410 { 0, 10.0f, 0}, | |
411 { 1, std::numeric_limits<float>::quiet_NaN(), 0}, | |
412 }; | |
413 | |
414 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
415 const TestCase& value = test_cases[i]; | |
416 for (int j = -1; j < 2; ++j) { | |
417 for (int k = 0; k < 3; ++k) { | |
418 float epsilon = 0.0001f; | |
419 gfx::Point p0, p1, p2; | |
420 ui::Transform xform; | |
421 switch (k) { | |
422 case 0: | |
423 p1.SetPoint(value.before, 0); | |
424 p2.SetPoint(value.after, 0); | |
425 xform.SetScaleX(value.s + j * epsilon); | |
426 break; | |
427 case 1: | |
428 p1.SetPoint(0, value.before); | |
429 p2.SetPoint(0, value.after); | |
430 xform.SetScaleY(value.s + j * epsilon); | |
431 break; | |
432 case 2: | |
433 p1.SetPoint(value.before, | |
434 value.before); | |
435 p2.SetPoint(value.after, | |
436 value.after); | |
437 xform.SetScale(value.s + j * epsilon, | |
438 value.s + j * epsilon); | |
439 break; | |
440 } | |
441 p0 = p1; | |
442 xform.TransformPoint(p1); | |
443 if (value.s == value.s) { | |
444 EXPECT_EQ(p1.x(), p2.x()); | |
445 EXPECT_EQ(p1.y(), p2.y()); | |
446 if (value.s != 0.0f) { | |
447 xform.TransformPointReverse(p1); | |
448 EXPECT_EQ(p1.x(), p0.x()); | |
449 EXPECT_EQ(p1.y(), p0.y()); | |
450 } | |
451 } | |
452 } | |
453 } | |
454 } | |
455 } | |
456 | |
457 TEST(XFormTest, SetRotate2D) { | |
458 static const struct SetRotateCase { | |
459 int x; | |
460 int y; | |
461 float degree; | |
462 int xprime; | |
463 int yprime; | |
464 } set_rotate_cases[] = { | |
465 { 100, 0, 90.0f, 0, 100}, | |
466 { 0, 0, 90.0f, 0, 0}, | |
467 { 0, 100, 90.0f, -100, 0}, | |
468 { 0, 1, -90.0f, 1, 0}, | |
469 { 100, 0, 0.0f, 100, 0}, | |
470 { 0, 0, 0.0f, 0, 0}, | |
471 { 0, 0, std::numeric_limits<float>::quiet_NaN(), 0, 0}, | |
472 { 100, 0, 360.0f, 100, 0} | |
473 }; | |
474 | |
475 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) { | |
476 const SetRotateCase& value = set_rotate_cases[i]; | |
477 for (int j = 1; j >= -1; --j) { | |
478 float epsilon = 0.1f; | |
479 gfx::Point pt(value.x, value.y); | |
480 ui::Transform xform; | |
481 // should be invariant to small floating point errors. | |
482 xform.SetRotate(value.degree + j * epsilon); | |
483 // just want to make sure that we don't crash in the case of NaN. | |
484 if (value.degree == value.degree) { | |
485 xform.TransformPoint(pt); | |
486 EXPECT_EQ(value.xprime, pt.x()); | |
487 EXPECT_EQ(value.yprime, pt.y()); | |
488 xform.TransformPointReverse(pt); | |
489 EXPECT_EQ(pt.x(), value.x); | |
490 EXPECT_EQ(pt.y(), value.y); | |
491 } | |
492 } | |
493 } | |
494 } | |
OLD | NEW |