Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(456)

Side by Side Diff: ui/gfx/transform_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698