Chromium Code Reviews| 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 |