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