1// Copyright (c) 2012 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_util.h"
6
7#include "testing/gtest/include/gtest/gtest.h"
8#include "ui/gfx/point.h"
9#include "ui/gfx/point3_f.h"
10#include "ui/gfx/rect.h"
11
12namespace gfx {
13namespace {
14
15TEST(TransformUtilTest, GetScaleTransform) {
16  const Point kAnchor(20, 40);
17  const float kScale = 0.5f;
18
19  Transform scale = GetScaleTransform(kAnchor, kScale);
20
21  const int kOffset = 10;
22  for (int sign_x = -1; sign_x <= 1; ++sign_x) {
23    for (int sign_y = -1; sign_y <= 1; ++sign_y) {
24      Point test(kAnchor.x() + sign_x * kOffset,
25                 kAnchor.y() + sign_y * kOffset);
26      scale.TransformPoint(&test);
27
28      EXPECT_EQ(Point(kAnchor.x() + sign_x * kOffset * kScale,
29                      kAnchor.y() + sign_y * kOffset * kScale),
30                test);
31    }
32  }
33}
34
35TEST(TransformUtilTest, SnapRotation) {
36  Transform result(Transform::kSkipInitialization);
37  Transform transform;
38  transform.RotateAboutZAxis(89.99);
39
40  Rect viewport(1920, 1200);
41  bool snapped = SnapTransform(&result, transform, viewport);
42
43  EXPECT_TRUE(snapped) << "Viewport should snap for this rotation.";
44}
45
46TEST(TransformUtilTest, SnapRotationDistantViewport) {
47  const int kOffset = 5000;
48  Transform result(Transform::kSkipInitialization);
49  Transform transform;
50
51  transform.RotateAboutZAxis(89.99);
52
53  Rect viewport(kOffset, kOffset, 1920, 1200);
54  bool snapped = SnapTransform(&result, transform, viewport);
55
56  EXPECT_FALSE(snapped) << "Distant viewport shouldn't snap by more than 1px.";
57}
58
59TEST(TransformUtilTest, NoSnapRotation) {
60  Transform result(Transform::kSkipInitialization);
61  Transform transform;
62  const int kOffset = 5000;
63
64  transform.RotateAboutZAxis(89.9);
65
66  Rect viewport(kOffset, kOffset, 1920, 1200);
67  bool snapped = SnapTransform(&result, transform, viewport);
68
69  EXPECT_FALSE(snapped) << "Viewport should not snap for this rotation.";
70}
71
72// Translations should always be snappable, the most we would move is 0.5
73// pixels towards either direction to the nearest value in each component.
74TEST(TransformUtilTest, SnapTranslation) {
75  Transform result(Transform::kSkipInitialization);
76  Transform transform;
77
78  transform.Translate3d(
79      SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0));
80
81  Rect viewport(1920, 1200);
82  bool snapped = SnapTransform(&result, transform, viewport);
83
84  EXPECT_TRUE(snapped) << "Viewport should snap for this translation.";
85}
86
87TEST(TransformUtilTest, SnapTranslationDistantViewport) {
88  Transform result(Transform::kSkipInitialization);
89  Transform transform;
90  const int kOffset = 5000;
91
92  transform.Translate3d(
93      SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0));
94
95  Rect viewport(kOffset, kOffset, 1920, 1200);
96  bool snapped = SnapTransform(&result, transform, viewport);
97
98  EXPECT_TRUE(snapped)
99      << "Distant viewport should still snap by less than 1px.";
100}
101
102TEST(TransformUtilTest, SnapScale) {
103  Transform result(Transform::kSkipInitialization);
104  Transform transform;
105
106  transform.Scale3d(SkDoubleToMScalar(5.0),
107                    SkDoubleToMScalar(2.00001),
108                    SkDoubleToMScalar(1.0));
109  Rect viewport(1920, 1200);
110  bool snapped = SnapTransform(&result, transform, viewport);
111
112  EXPECT_TRUE(snapped) << "Viewport should snap for this scaling.";
113}
114
115TEST(TransformUtilTest, NoSnapScale) {
116  Transform result(Transform::kSkipInitialization);
117  Transform transform;
118
119  transform.Scale3d(
120    SkDoubleToMScalar(5.0), SkDoubleToMScalar(2.1), SkDoubleToMScalar(1.0));
121  Rect viewport(1920, 1200);
122  bool snapped = SnapTransform(&result, transform, viewport);
123
124  EXPECT_FALSE(snapped) << "Viewport shouldn't snap for this scaling.";
125}
126
127TEST(TransformUtilTest, SnapCompositeTransform) {
128  Transform result(Transform::kSkipInitialization);
129  Transform transform;
130
131  transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0),
132                        SkDoubleToMScalar(10.1));
133  transform.RotateAboutZAxis(89.99);
134  transform.Scale3d(SkDoubleToMScalar(1.0),
135                    SkDoubleToMScalar(3.00001),
136                    SkDoubleToMScalar(2.0));
137
138  Rect viewport(1920, 1200);
139  bool snapped = SnapTransform(&result, transform, viewport);
140  ASSERT_TRUE(snapped) << "Viewport should snap all components.";
141
142  Point3F point;
143
144  point = Point3F(viewport.origin());
145  result.TransformPoint(&point);
146  EXPECT_EQ(Point3F(31.f, 20.f, 10.f), point) << "Transformed origin";
147
148  point = Point3F(viewport.top_right());
149  result.TransformPoint(&point);
150  EXPECT_EQ(Point3F(31.f, 1940.f, 10.f), point) << "Transformed top-right";
151
152  point = Point3F(viewport.bottom_left());
153  result.TransformPoint(&point);
154  EXPECT_EQ(Point3F(-3569.f, 20.f, 10.f), point) << "Transformed bottom-left";
155
156  point = Point3F(viewport.bottom_right());
157  result.TransformPoint(&point);
158  EXPECT_EQ(Point3F(-3569.f, 1940.f, 10.f), point)
159      << "Transformed bottom-right";
160}
161
162TEST(TransformUtilTest, NoSnapSkewedCompositeTransform) {
163  Transform result(Transform::kSkipInitialization);
164  Transform transform;
165
166
167  transform.RotateAboutZAxis(89.99);
168  transform.Scale3d(SkDoubleToMScalar(1.0),
169                    SkDoubleToMScalar(3.00001),
170                    SkDoubleToMScalar(2.0));
171  transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0),
172                        SkDoubleToMScalar(10.1));
173  transform.SkewX(20.0);
174  Rect viewport(1920, 1200);
175  bool snapped = SnapTransform(&result, transform, viewport);
176  EXPECT_FALSE(snapped) << "Skewed viewport should not snap.";
177}
178
179}  // namespace
180}  // namespace gfx
181