15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/transform_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/gfx/point3_f.h" 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/gfx/rect.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(TransformUtilTest, GetScaleTransform) { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Point kAnchor(20, 40); 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const float kScale = 0.5f; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Transform scale = GetScaleTransform(kAnchor, kScale); 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kOffset = 10; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int sign_x = -1; sign_x <= 1; ++sign_x) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int sign_y = -1; sign_y <= 1; ++sign_y) { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Point test(kAnchor.x() + sign_x * kOffset, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAnchor.y() + sign_y * kOffset); 26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scale.TransformPoint(&test); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(Point(kAnchor.x() + sign_x * kOffset * kScale, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAnchor.y() + sign_y * kOffset * kScale), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, SnapRotation) { 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.RotateAboutZAxis(89.99); 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(1920, 1200); 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(snapped) << "Viewport should snap for this rotation."; 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, SnapRotationDistantViewport) { 471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const int kOffset = 5000; 481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.RotateAboutZAxis(89.99); 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(kOffset, kOffset, 1920, 1200); 541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(snapped) << "Distant viewport shouldn't snap by more than 1px."; 571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, NoSnapRotation) { 601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const int kOffset = 5000; 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.RotateAboutZAxis(89.9); 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(kOffset, kOffset, 1920, 1200); 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(snapped) << "Viewport should not snap for this rotation."; 701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Translations should always be snappable, the most we would move is 0.5 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// pixels towards either direction to the nearest value in each component. 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, SnapTranslation) { 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Translate3d( 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0)); 801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(1920, 1200); 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(snapped) << "Viewport should snap for this translation."; 851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, SnapTranslationDistantViewport) { 881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const int kOffset = 5000; 911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Translate3d( 931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0)); 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(kOffset, kOffset, 1920, 1200); 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(snapped) 991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << "Distant viewport should still snap by less than 1px."; 1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, SnapScale) { 1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Scale3d(SkDoubleToMScalar(5.0), 1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(2.00001), 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(1.0)); 1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(1920, 1200); 1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(snapped) << "Viewport should snap for this scaling."; 1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, NoSnapScale) { 1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Scale3d( 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(5.0), SkDoubleToMScalar(2.1), SkDoubleToMScalar(1.0)); 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(1920, 1200); 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(snapped) << "Viewport shouldn't snap for this scaling."; 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, SnapCompositeTransform) { 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0), 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(10.1)); 1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.RotateAboutZAxis(89.99); 1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Scale3d(SkDoubleToMScalar(1.0), 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(3.00001), 1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(2.0)); 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(1920, 1200); 1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(snapped) << "Viewport should snap all components."; 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Point3F point; 1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) point = Point3F(viewport.origin()); 1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.TransformPoint(&point); 1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(Point3F(31.f, 20.f, 10.f), point) << "Transformed origin"; 1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) point = Point3F(viewport.top_right()); 1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.TransformPoint(&point); 1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(Point3F(31.f, 1940.f, 10.f), point) << "Transformed top-right"; 1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) point = Point3F(viewport.bottom_left()); 1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.TransformPoint(&point); 1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(Point3F(-3569.f, 20.f, 10.f), point) << "Transformed bottom-left"; 1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) point = Point3F(viewport.bottom_right()); 1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.TransformPoint(&point); 1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(Point3F(-3569.f, 1940.f, 10.f), point) 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << "Transformed bottom-right"; 1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST(TransformUtilTest, NoSnapSkewedCompositeTransform) { 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform result(Transform::kSkipInitialization); 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Transform transform; 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.RotateAboutZAxis(89.99); 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Scale3d(SkDoubleToMScalar(1.0), 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(3.00001), 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(2.0)); 1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0), 1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SkDoubleToMScalar(10.1)); 1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transform.SkewX(20.0); 1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Rect viewport(1920, 1200); 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool snapped = SnapTransform(&result, transform, viewport); 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(snapped) << "Skewed viewport should not snap."; 1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 181