1 // Copyright 2013 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/animation/tween.h"
6 
7 #include <math.h>
8 
9 #include "base/time/time.h"
10 #include "build/build_config.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/test/gfx_util.h"
13 
14 #if defined(OS_WIN)
15 #include <float.h>
16 #endif
17 
18 namespace gfx {
19 namespace {
20 
next_double(double d)21 double next_double(double d) {
22 #if defined(OS_WIN)
23   return _nextafter(d, d + 1);
24 #else
25   // Step two units of least precision towards positive infinity. On some 32
26   // bit x86 compilers a single step was not enough due to loss of precision in
27   // optimized code.
28   return nextafter(nextafter(d, d + 1), d + 1);
29 #endif
30 }
31 
32 // Validates that the same interpolations are made as in Blink.
TEST(TweenTest,ColorValueBetween)33 TEST(TweenTest, ColorValueBetween) {
34   // From blink's AnimatableColorTest.
35   EXPECT_SKCOLOR_EQ(0xFF00FF00,
36                   Tween::ColorValueBetween(-10.0, 0xFF00FF00, 0xFF00FF00));
37   EXPECT_SKCOLOR_EQ(0xFF00FF00,
38                   Tween::ColorValueBetween(-10.0, 0xFF00FF00, 0xFFFF00FF));
39   EXPECT_SKCOLOR_EQ(0xFF00FF00,
40                   Tween::ColorValueBetween(0.0, 0xFF00FF00, 0xFFFF00FF));
41   EXPECT_SKCOLOR_EQ(0xFF01FE01,
42                   Tween::ColorValueBetween(1.0 / 255, 0xFF00FF00, 0xFFFF00FF));
43   EXPECT_SKCOLOR_EQ(0xFF808080,
44                   Tween::ColorValueBetween(0.5, 0xFF00FF00, 0xFFFF00FF));
45   EXPECT_SKCOLOR_EQ(
46       0xFFFE01FE,
47       Tween::ColorValueBetween(254.0 / 255.0, 0xFF00FF00, 0xFFFF00FF));
48   EXPECT_SKCOLOR_EQ(0xFFFF00FF,
49                   Tween::ColorValueBetween(1.0, 0xFF00FF00, 0xFFFF00FF));
50   EXPECT_SKCOLOR_EQ(0xFFFF00FF,
51                   Tween::ColorValueBetween(10.0, 0xFF00FF00, 0xFFFF00FF));
52   EXPECT_SKCOLOR_EQ(0xFF0C253E,
53                   Tween::ColorValueBetween(3.0 / 16.0, 0xFF001020, 0xFF4080C0));
54   EXPECT_SKCOLOR_EQ(0x80FF00FF,
55                   Tween::ColorValueBetween(0.5, 0x0000FF00, 0xFFFF00FF));
56   EXPECT_SKCOLOR_EQ(0x60AA55AA,
57                   Tween::ColorValueBetween(0.5, 0x4000FF00, 0x80FF00FF));
58   EXPECT_SKCOLOR_EQ(0x60FFAAFF,
59                   Tween::ColorValueBetween(0.5, 0x40FF00FF, 0x80FFFFFF));
60   EXPECT_SKCOLOR_EQ(0x103060A0,
61                   Tween::ColorValueBetween(0.5, 0x10204080, 0x104080C0));
62 }
63 
64 // Ensures that each of the 3 integers in [0, 1, 2] ae selected with equal
65 // weight.
TEST(TweenTest,IntValueBetween)66 TEST(TweenTest, IntValueBetween) {
67   EXPECT_EQ(0, Tween::IntValueBetween(0.0, 0, 2));
68   EXPECT_EQ(0, Tween::IntValueBetween(0.5 / 3.0, 0, 2));
69   EXPECT_EQ(0, Tween::IntValueBetween(1.0 / 3.0, 0, 2));
70 
71   EXPECT_EQ(1, Tween::IntValueBetween(next_double(1.0 / 3.0), 0, 2));
72   EXPECT_EQ(1, Tween::IntValueBetween(1.5 / 3.0, 0, 2));
73   EXPECT_EQ(1, Tween::IntValueBetween(2.0 / 3.0, 0, 2));
74 
75   EXPECT_EQ(2, Tween::IntValueBetween(next_double(2.0 / 3.0), 0, 2));
76   EXPECT_EQ(2, Tween::IntValueBetween(2.5 / 3.0, 0, 2));
77   EXPECT_EQ(2, Tween::IntValueBetween(3.0 / 3.0, 0, 2));
78 }
79 
TEST(TweenTest,IntValueBetweenNegative)80 TEST(TweenTest, IntValueBetweenNegative) {
81   EXPECT_EQ(-2, Tween::IntValueBetween(0.0, -2, 0));
82   EXPECT_EQ(-2, Tween::IntValueBetween(0.5 / 3.0, -2, 0));
83   EXPECT_EQ(-2, Tween::IntValueBetween(1.0 / 3.0, -2, 0));
84 
85   EXPECT_EQ(-1, Tween::IntValueBetween(next_double(1.0 / 3.0), -2, 0));
86   EXPECT_EQ(-1, Tween::IntValueBetween(1.5 / 3.0, -2, 0));
87   EXPECT_EQ(-1, Tween::IntValueBetween(2.0 / 3.0, -2, 0));
88 
89   EXPECT_EQ(0, Tween::IntValueBetween(next_double(2.0 / 3.0), -2, 0));
90   EXPECT_EQ(0, Tween::IntValueBetween(2.5 / 3.0, -2, 0));
91   EXPECT_EQ(0, Tween::IntValueBetween(3.0 / 3.0, -2, 0));
92 }
93 
TEST(TweenTest,IntValueBetweenReverse)94 TEST(TweenTest, IntValueBetweenReverse) {
95   EXPECT_EQ(2, Tween::IntValueBetween(0.0, 2, 0));
96   EXPECT_EQ(2, Tween::IntValueBetween(0.5 / 3.0, 2, 0));
97   EXPECT_EQ(2, Tween::IntValueBetween(1.0 / 3.0, 2, 0));
98 
99   EXPECT_EQ(1, Tween::IntValueBetween(next_double(1.0 / 3.0), 2, 0));
100   EXPECT_EQ(1, Tween::IntValueBetween(1.5 / 3.0, 2, 0));
101   EXPECT_EQ(1, Tween::IntValueBetween(2.0 / 3.0, 2, 0));
102 
103   EXPECT_EQ(0, Tween::IntValueBetween(next_double(2.0 / 3.0), 2, 0));
104   EXPECT_EQ(0, Tween::IntValueBetween(2.5 / 3.0, 2, 0));
105   EXPECT_EQ(0, Tween::IntValueBetween(3.0 / 3.0, 2, 0));
106 }
107 
TEST(TweenTest,LinearIntValueBetween)108 TEST(TweenTest, LinearIntValueBetween) {
109   EXPECT_EQ(0, Tween::LinearIntValueBetween(0.0, 0, 2));
110   EXPECT_EQ(0, Tween::LinearIntValueBetween(0.5 / 4.0, 0, 2));
111   EXPECT_EQ(0, Tween::LinearIntValueBetween(0.99 / 4.0, 0, 2));
112 
113   EXPECT_EQ(1, Tween::LinearIntValueBetween(1.0 / 4.0, 0, 2));
114   EXPECT_EQ(1, Tween::LinearIntValueBetween(1.5 / 4.0, 0, 2));
115   EXPECT_EQ(1, Tween::LinearIntValueBetween(2.0 / 4.0, 0, 2));
116   EXPECT_EQ(1, Tween::LinearIntValueBetween(2.5 / 4.0, 0, 2));
117   EXPECT_EQ(1, Tween::LinearIntValueBetween(2.99 / 4.0, 0, 2));
118 
119   EXPECT_EQ(2, Tween::LinearIntValueBetween(3.0 / 4.0, 0, 2));
120   EXPECT_EQ(2, Tween::LinearIntValueBetween(3.5 / 4.0, 0, 2));
121   EXPECT_EQ(2, Tween::LinearIntValueBetween(4.0 / 4.0, 0, 2));
122 }
123 
TEST(TweenTest,LinearIntValueBetweenNegative)124 TEST(TweenTest, LinearIntValueBetweenNegative) {
125   EXPECT_EQ(-2, Tween::LinearIntValueBetween(0.0, -2, 0));
126   EXPECT_EQ(-2, Tween::LinearIntValueBetween(0.5 / 4.0, -2, 0));
127   EXPECT_EQ(-2, Tween::LinearIntValueBetween(0.99 / 4.0, -2, 0));
128 
129   EXPECT_EQ(-1, Tween::LinearIntValueBetween(1.0 / 4.0, -2, 0));
130   EXPECT_EQ(-1, Tween::LinearIntValueBetween(1.5 / 4.0, -2, 0));
131   EXPECT_EQ(-1, Tween::LinearIntValueBetween(2.0 / 4.0, -2, 0));
132   EXPECT_EQ(-1, Tween::LinearIntValueBetween(2.5 / 4.0, -2, 0));
133   EXPECT_EQ(-1, Tween::LinearIntValueBetween(2.99 / 4.0, -2, 0));
134 
135   EXPECT_EQ(0, Tween::LinearIntValueBetween(3.0 / 4.0, -2, 0));
136   EXPECT_EQ(0, Tween::LinearIntValueBetween(3.5 / 4.0, -2, 0));
137   EXPECT_EQ(0, Tween::LinearIntValueBetween(4.0 / 4.0, -2, 0));
138 }
139 
TEST(TweenTest,ClampedFloatValueBetweenTimeTicks)140 TEST(TweenTest, ClampedFloatValueBetweenTimeTicks) {
141   const float v1 = 10.0f;
142   const float v2 = 20.0f;
143 
144   const auto t0 = base::TimeTicks();
145 
146   base::TimeTicks from = t0 + base::TimeDelta::FromSecondsD(1);
147   base::TimeTicks to = t0 + base::TimeDelta::FromSecondsD(2);
148 
149   base::TimeTicks t_before = t0 + base::TimeDelta::FromSecondsD(0.9);
150   base::TimeTicks t_between = t0 + base::TimeDelta::FromSecondsD(1.6);
151   base::TimeTicks t_after = t0 + base::TimeDelta::FromSecondsD(2.2);
152 
153   EXPECT_EQ(v1, Tween::ClampedFloatValueBetween(t_before, from, v1, to, v2));
154   EXPECT_EQ(16.0, Tween::ClampedFloatValueBetween(t_between, from, v1, to, v2));
155   EXPECT_EQ(v2, Tween::ClampedFloatValueBetween(t_after, from, v1, to, v2));
156 }
157 
158 // Verifies the corners of the rect are animated, rather than the origin/size
159 // (which would result in different rounding).
TEST(TweenTest,RectValueBetween)160 TEST(TweenTest, RectValueBetween) {
161   constexpr gfx::Rect r1(0, 0, 10, 10);
162   constexpr gfx::Rect r2(10, 10, 30, 30);
163 
164   // TODO(pkasting): Move the geometry test helpers from
165   // cc/test/geometry_test_utils.h to ui/gfx/test/gfx_util.h or similar and use
166   // a rect-comparison function here.
167   const gfx::Rect tweened = Tween::RectValueBetween(0.08, r1, r2);
168   EXPECT_EQ(11, tweened.width());
169   EXPECT_EQ(11, tweened.height());
170 }
171 
TEST(TweenTest,SizeValueBetween)172 TEST(TweenTest, SizeValueBetween) {
173   constexpr gfx::Size kSize1(12, 24);
174   constexpr gfx::Size kSize2(36, 48);
175 
176   constexpr double kBefore = -0.125;
177   constexpr double kFrom = 0.0;
178   constexpr double kBetween = 0.5;
179   constexpr double kTo = 1.0;
180   constexpr double kAfter = 1.125;
181 
182   EXPECT_EQ(gfx::Size(9, 21), Tween::SizeValueBetween(kBefore, kSize1, kSize2));
183   EXPECT_EQ(kSize1, Tween::SizeValueBetween(kFrom, kSize1, kSize2));
184   EXPECT_EQ(gfx::Size(24, 36),
185             Tween::SizeValueBetween(kBetween, kSize1, kSize2));
186   EXPECT_EQ(kSize2, Tween::SizeValueBetween(kTo, kSize1, kSize2));
187   EXPECT_EQ(gfx::Size(39, 51), Tween::SizeValueBetween(kAfter, kSize1, kSize2));
188 }
189 
TEST(TweenTest,SizeValueBetweenClampedExtrapolation)190 TEST(TweenTest, SizeValueBetweenClampedExtrapolation) {
191   constexpr gfx::Size kSize1(0, 0);
192   constexpr gfx::Size kSize2(36, 48);
193 
194   constexpr double kBefore = -1.0f;
195 
196   // We should not extrapolate in this case as it would result in a negative and
197   // invalid size.
198   EXPECT_EQ(kSize1, Tween::SizeValueBetween(kBefore, kSize1, kSize2));
199 }
200 
TEST(TweenTest,SizeFValueBetween)201 TEST(TweenTest, SizeFValueBetween) {
202   const gfx::SizeF s1(12.0f, 24.0f);
203   const gfx::SizeF s2(36.0f, 48.0f);
204 
205   constexpr double kBefore = -0.125;
206   constexpr double kFrom = 0.0;
207   constexpr double kBetween = 0.5;
208   constexpr double kTo = 1.0;
209   constexpr double kAfter = 1.125;
210 
211   EXPECT_SIZEF_EQ(gfx::SizeF(9.0f, 21.0f),
212                   Tween::SizeFValueBetween(kBefore, s1, s2));
213   EXPECT_SIZEF_EQ(s1, Tween::SizeFValueBetween(kFrom, s1, s2));
214   EXPECT_SIZEF_EQ(gfx::SizeF(24.0f, 36.0f),
215                   Tween::SizeFValueBetween(kBetween, s1, s2));
216   EXPECT_SIZEF_EQ(s2, Tween::SizeFValueBetween(kTo, s1, s2));
217   EXPECT_SIZEF_EQ(gfx::SizeF(39.0f, 51.0f),
218                   Tween::SizeFValueBetween(kAfter, s1, s2));
219 }
220 
TEST(TweenTest,SizeFValueBetweenClampedExtrapolation)221 TEST(TweenTest, SizeFValueBetweenClampedExtrapolation) {
222   const gfx::SizeF s1(0.0f, 0.0f);
223   const gfx::SizeF s2(36.0f, 48.0f);
224 
225   constexpr double kBefore = -1.0f;
226 
227   // We should not extrapolate in this case as it would result in a negative and
228   // invalid size.
229   EXPECT_SIZEF_EQ(s1, Tween::SizeFValueBetween(kBefore, s1, s2));
230 }
231 
232 }  // namespace
233 }  // namespace gfx
234