// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/gfx/transform_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/rect.h" namespace gfx { namespace { TEST(TransformUtilTest, GetScaleTransform) { const Point kAnchor(20, 40); const float kScale = 0.5f; Transform scale = GetScaleTransform(kAnchor, kScale); const int kOffset = 10; for (int sign_x = -1; sign_x <= 1; ++sign_x) { for (int sign_y = -1; sign_y <= 1; ++sign_y) { Point test(kAnchor.x() + sign_x * kOffset, kAnchor.y() + sign_y * kOffset); scale.TransformPoint(&test); EXPECT_EQ(Point(kAnchor.x() + sign_x * kOffset * kScale, kAnchor.y() + sign_y * kOffset * kScale), test); } } } TEST(TransformUtilTest, SnapRotation) { Transform result(Transform::kSkipInitialization); Transform transform; transform.RotateAboutZAxis(89.99); Rect viewport(1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_TRUE(snapped) << "Viewport should snap for this rotation."; } TEST(TransformUtilTest, SnapRotationDistantViewport) { const int kOffset = 5000; Transform result(Transform::kSkipInitialization); Transform transform; transform.RotateAboutZAxis(89.99); Rect viewport(kOffset, kOffset, 1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_FALSE(snapped) << "Distant viewport shouldn't snap by more than 1px."; } TEST(TransformUtilTest, NoSnapRotation) { Transform result(Transform::kSkipInitialization); Transform transform; const int kOffset = 5000; transform.RotateAboutZAxis(89.9); Rect viewport(kOffset, kOffset, 1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_FALSE(snapped) << "Viewport should not snap for this rotation."; } // Translations should always be snappable, the most we would move is 0.5 // pixels towards either direction to the nearest value in each component. TEST(TransformUtilTest, SnapTranslation) { Transform result(Transform::kSkipInitialization); Transform transform; transform.Translate3d( SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0)); Rect viewport(1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_TRUE(snapped) << "Viewport should snap for this translation."; } TEST(TransformUtilTest, SnapTranslationDistantViewport) { Transform result(Transform::kSkipInitialization); Transform transform; const int kOffset = 5000; transform.Translate3d( SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0)); Rect viewport(kOffset, kOffset, 1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_TRUE(snapped) << "Distant viewport should still snap by less than 1px."; } TEST(TransformUtilTest, SnapScale) { Transform result(Transform::kSkipInitialization); Transform transform; transform.Scale3d(SkDoubleToMScalar(5.0), SkDoubleToMScalar(2.00001), SkDoubleToMScalar(1.0)); Rect viewport(1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_TRUE(snapped) << "Viewport should snap for this scaling."; } TEST(TransformUtilTest, NoSnapScale) { Transform result(Transform::kSkipInitialization); Transform transform; transform.Scale3d( SkDoubleToMScalar(5.0), SkDoubleToMScalar(2.1), SkDoubleToMScalar(1.0)); Rect viewport(1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_FALSE(snapped) << "Viewport shouldn't snap for this scaling."; } TEST(TransformUtilTest, SnapCompositeTransform) { Transform result(Transform::kSkipInitialization); Transform transform; transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0), SkDoubleToMScalar(10.1)); transform.RotateAboutZAxis(89.99); transform.Scale3d(SkDoubleToMScalar(1.0), SkDoubleToMScalar(3.00001), SkDoubleToMScalar(2.0)); Rect viewport(1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); ASSERT_TRUE(snapped) << "Viewport should snap all components."; Point3F point; point = Point3F(viewport.origin()); result.TransformPoint(&point); EXPECT_EQ(Point3F(31.f, 20.f, 10.f), point) << "Transformed origin"; point = Point3F(viewport.top_right()); result.TransformPoint(&point); EXPECT_EQ(Point3F(31.f, 1940.f, 10.f), point) << "Transformed top-right"; point = Point3F(viewport.bottom_left()); result.TransformPoint(&point); EXPECT_EQ(Point3F(-3569.f, 20.f, 10.f), point) << "Transformed bottom-left"; point = Point3F(viewport.bottom_right()); result.TransformPoint(&point); EXPECT_EQ(Point3F(-3569.f, 1940.f, 10.f), point) << "Transformed bottom-right"; } TEST(TransformUtilTest, NoSnapSkewedCompositeTransform) { Transform result(Transform::kSkipInitialization); Transform transform; transform.RotateAboutZAxis(89.99); transform.Scale3d(SkDoubleToMScalar(1.0), SkDoubleToMScalar(3.00001), SkDoubleToMScalar(2.0)); transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0), SkDoubleToMScalar(10.1)); transform.SkewX(20.0); Rect viewport(1920, 1200); bool snapped = SnapTransform(&result, transform, viewport); EXPECT_FALSE(snapped) << "Skewed viewport should not snap."; } TEST(TransformUtilTest, TransformAboutPivot) { Transform transform; transform.Scale(3, 4); transform = TransformAboutPivot(Point(7, 8), transform); Point point; point = Point(0, 0); transform.TransformPoint(&point); EXPECT_EQ(Point(-14, -24).ToString(), point.ToString()); point = Point(1, 1); transform.TransformPoint(&point); EXPECT_EQ(Point(-11, -20).ToString(), point.ToString()); } TEST(TransformUtilTest, BlendOppositeQuaternions) { DecomposedTransform first; DecomposedTransform second; second.quaternion[3] = -second.quaternion[3]; DecomposedTransform result; BlendDecomposedTransforms(&result, first, second, 0.25); for (size_t i = 0; i < 4; ++i) { EXPECT_TRUE(std::isfinite(result.quaternion[i])); EXPECT_FALSE(std::isnan(result.quaternion[i])); } } } // namespace } // namespace gfx