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/compositor/layer_animation_sequence.h"
6
7 #include <memory>
8
9 #include "base/compiler_specific.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/time/time.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/compositor/layer_animation_delegate.h"
14 #include "ui/compositor/layer_animation_element.h"
15 #include "ui/compositor/test/test_layer_animation_delegate.h"
16 #include "ui/compositor/test/test_layer_animation_observer.h"
17 #include "ui/compositor/test/test_utils.h"
18 #include "ui/gfx/geometry/rect.h"
19 #include "ui/gfx/transform.h"
20
21 namespace ui {
22
23 namespace {
24
25 // Check that the sequence behaves sanely when it contains no elements.
TEST(LayerAnimationSequenceTest,NoElement)26 TEST(LayerAnimationSequenceTest, NoElement) {
27 LayerAnimationSequence sequence;
28 base::TimeTicks start_time;
29 start_time += base::TimeDelta::FromSeconds(1);
30 sequence.set_start_time(start_time);
31 EXPECT_TRUE(sequence.IsFinished(start_time));
32 EXPECT_EQ(static_cast<LayerAnimationElement::AnimatableProperties>(
33 LayerAnimationElement::UNKNOWN),
34 sequence.properties());
35 EXPECT_FALSE(sequence.HasConflictingProperty(LayerAnimationElement::UNKNOWN));
36 }
37
38 // Check that the sequences progresses the delegate as expected when it contains
39 // a single non-threaded element.
TEST(LayerAnimationSequenceTest,SingleElement)40 TEST(LayerAnimationSequenceTest, SingleElement) {
41 LayerAnimationSequence sequence;
42 TestLayerAnimationDelegate delegate;
43 float start = 0.0f;
44 float middle = 0.5f;
45 float target = 1.0f;
46 base::TimeTicks start_time;
47 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
48 sequence.AddElement(
49 LayerAnimationElement::CreateBrightnessElement(target, delta));
50
51 for (int i = 0; i < 2; ++i) {
52 start_time += delta;
53 sequence.set_start_time(start_time);
54 delegate.SetBrightnessFromAnimation(
55 start, PropertyChangeReason::NOT_FROM_ANIMATION);
56 sequence.Start(&delegate);
57 sequence.Progress(start_time, &delegate);
58 EXPECT_FLOAT_EQ(start, delegate.GetBrightnessForAnimation());
59 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(500),
60 &delegate);
61 EXPECT_FLOAT_EQ(middle, delegate.GetBrightnessForAnimation());
62 EXPECT_TRUE(sequence.IsFinished(start_time + delta));
63 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(1000),
64 &delegate);
65 EXPECT_FLOAT_EQ(target, delegate.GetBrightnessForAnimation());
66 }
67
68 EXPECT_EQ(static_cast<LayerAnimationElement::AnimatableProperties>(
69 LayerAnimationElement::BRIGHTNESS),
70 sequence.properties());
71 }
72
73 // Check that the sequences progresses the delegate as expected when it contains
74 // a single threaded element.
TEST(LayerAnimationSequenceTest,SingleThreadedElement)75 TEST(LayerAnimationSequenceTest, SingleThreadedElement) {
76 LayerAnimationSequence sequence;
77 TestLayerAnimationDelegate delegate;
78 float start = 0.0f;
79 float middle = 0.5f;
80 float target = 1.0f;
81 base::TimeTicks start_time;
82 base::TimeTicks effective_start;
83 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
84 sequence.AddElement(
85 LayerAnimationElement::CreateOpacityElement(target, delta));
86
87 for (int i = 0; i < 2; ++i) {
88 int starting_group_id = 1;
89 sequence.set_animation_group_id(starting_group_id);
90 start_time = effective_start + delta;
91 sequence.set_start_time(start_time);
92 delegate.SetOpacityFromAnimation(start,
93 PropertyChangeReason::NOT_FROM_ANIMATION);
94 sequence.Start(&delegate);
95 sequence.Progress(start_time, &delegate);
96 EXPECT_FLOAT_EQ(start, sequence.last_progressed_fraction());
97 effective_start = start_time + delta;
98 sequence.OnThreadedAnimationStarted(effective_start,
99 cc::TargetProperty::OPACITY,
100 sequence.animation_group_id());
101 sequence.Progress(effective_start + delta/2, &delegate);
102 EXPECT_FLOAT_EQ(middle, sequence.last_progressed_fraction());
103 EXPECT_TRUE(sequence.IsFinished(effective_start + delta));
104 sequence.Progress(effective_start + delta, &delegate);
105 EXPECT_FLOAT_EQ(target, sequence.last_progressed_fraction());
106 EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
107 }
108
109 EXPECT_EQ(static_cast<LayerAnimationElement::AnimatableProperties>(
110 LayerAnimationElement::OPACITY),
111 sequence.properties());
112 }
113
114 // Check that the sequences progresses the delegate as expected when it contains
115 // multiple elements. Note, see the layer animator tests for cyclic sequences.
TEST(LayerAnimationSequenceTest,MultipleElement)116 TEST(LayerAnimationSequenceTest, MultipleElement) {
117 LayerAnimationSequence sequence;
118 TestLayerAnimationDelegate delegate;
119 float start_opacity = 0.0f;
120 float target_opacity = 1.0f;
121 base::TimeTicks start_time;
122 base::TimeTicks opacity_effective_start;
123 base::TimeTicks transform_effective_start;
124 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
125 sequence.AddElement(
126 LayerAnimationElement::CreateOpacityElement(target_opacity, delta));
127
128 // Pause bounds for a second.
129 sequence.AddElement(LayerAnimationElement::CreatePauseElement(
130 LayerAnimationElement::BOUNDS, delta));
131
132 gfx::Transform start_transform, target_transform;
133 start_transform.Rotate(-30.0);
134 target_transform.Rotate(30.0);
135
136 sequence.AddElement(
137 LayerAnimationElement::CreateTransformElement(target_transform, delta));
138
139 for (int i = 0; i < 2; ++i) {
140 int starting_group_id = 1;
141 sequence.set_animation_group_id(starting_group_id);
142 start_time = opacity_effective_start + 4 * delta;
143 sequence.set_start_time(start_time);
144 delegate.SetOpacityFromAnimation(start_opacity,
145 PropertyChangeReason::NOT_FROM_ANIMATION);
146 delegate.SetTransformFromAnimation(
147 start_transform, PropertyChangeReason::NOT_FROM_ANIMATION);
148
149 sequence.Start(&delegate);
150 sequence.Progress(start_time, &delegate);
151 EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction());
152 opacity_effective_start = start_time + delta;
153 EXPECT_EQ(starting_group_id, sequence.animation_group_id());
154 sequence.OnThreadedAnimationStarted(opacity_effective_start,
155 cc::TargetProperty::OPACITY,
156 sequence.animation_group_id());
157 sequence.Progress(opacity_effective_start + delta/2, &delegate);
158 EXPECT_FLOAT_EQ(0.5, sequence.last_progressed_fraction());
159 sequence.Progress(opacity_effective_start + delta, &delegate);
160 EXPECT_FLOAT_EQ(target_opacity, delegate.GetOpacityForAnimation());
161
162 // Now at the start of the pause.
163 EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction());
164 TestLayerAnimationDelegate copy = delegate;
165
166 // In the middle of the pause -- nothing should have changed.
167 sequence.Progress(opacity_effective_start + delta + delta/2,
168 &delegate);
169 CheckApproximatelyEqual(delegate.GetBoundsForAnimation(),
170 copy.GetBoundsForAnimation());
171 CheckApproximatelyEqual(delegate.GetTransformForAnimation(),
172 copy.GetTransformForAnimation());
173 EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(),
174 copy.GetOpacityForAnimation());
175
176 sequence.Progress(opacity_effective_start + 2 * delta, &delegate);
177 CheckApproximatelyEqual(start_transform,
178 delegate.GetTransformForAnimation());
179 EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction());
180 transform_effective_start = opacity_effective_start + 3 * delta;
181 EXPECT_NE(starting_group_id, sequence.animation_group_id());
182 sequence.OnThreadedAnimationStarted(transform_effective_start,
183 cc::TargetProperty::TRANSFORM,
184 sequence.animation_group_id());
185 sequence.Progress(transform_effective_start + delta/2, &delegate);
186 EXPECT_FLOAT_EQ(0.5, sequence.last_progressed_fraction());
187 EXPECT_TRUE(sequence.IsFinished(transform_effective_start + delta));
188 sequence.Progress(transform_effective_start + delta, &delegate);
189 CheckApproximatelyEqual(target_transform,
190 delegate.GetTransformForAnimation());
191 }
192
193 EXPECT_EQ(
194 static_cast<LayerAnimationElement::AnimatableProperties>(
195 LayerAnimationElement::OPACITY | LayerAnimationElement::TRANSFORM |
196 LayerAnimationElement::BOUNDS),
197 sequence.properties());
198 }
199
200 // Check that a sequence can still be aborted if it has cycled many times.
TEST(LayerAnimationSequenceTest,AbortingCyclicSequence)201 TEST(LayerAnimationSequenceTest, AbortingCyclicSequence) {
202 LayerAnimationSequence sequence;
203 TestLayerAnimationDelegate delegate;
204 float start_brightness = 0.0f;
205 float target_brightness = 1.0f;
206 base::TimeTicks start_time;
207 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
208 sequence.AddElement(
209 LayerAnimationElement::CreateBrightnessElement(target_brightness, delta));
210
211 sequence.AddElement(
212 LayerAnimationElement::CreateBrightnessElement(start_brightness, delta));
213
214 sequence.set_is_cyclic(true);
215
216 delegate.SetBrightnessFromAnimation(start_brightness,
217 PropertyChangeReason::NOT_FROM_ANIMATION);
218
219 start_time += delta;
220 sequence.set_start_time(start_time);
221 sequence.Start(&delegate);
222 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(101000),
223 &delegate);
224 EXPECT_FLOAT_EQ(target_brightness, delegate.GetBrightnessForAnimation());
225 sequence.Abort(&delegate);
226
227 // Should be able to reuse the sequence after aborting.
228 delegate.SetBrightnessFromAnimation(start_brightness,
229 PropertyChangeReason::NOT_FROM_ANIMATION);
230 start_time += base::TimeDelta::FromMilliseconds(101000);
231 sequence.set_start_time(start_time);
232 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(100000),
233 &delegate);
234 EXPECT_FLOAT_EQ(start_brightness, delegate.GetBrightnessForAnimation());
235 }
236
237 // Check that a sequence can be 'fast-forwarded' to the end and the target set.
238 // Also check that this has no effect if the sequence is cyclic.
TEST(LayerAnimationSequenceTest,SetTarget)239 TEST(LayerAnimationSequenceTest, SetTarget) {
240 LayerAnimationSequence sequence;
241 TestLayerAnimationDelegate delegate;
242 float start_opacity = 0.0f;
243 float target_opacity = 1.0f;
244 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
245 sequence.AddElement(
246 LayerAnimationElement::CreateOpacityElement(target_opacity, delta));
247
248 LayerAnimationElement::TargetValue target_value(&delegate);
249 target_value.opacity = start_opacity;
250 sequence.GetTargetValue(&target_value);
251 EXPECT_FLOAT_EQ(target_opacity, target_value.opacity);
252
253 sequence.set_is_cyclic(true);
254 target_value.opacity = start_opacity;
255 sequence.GetTargetValue(&target_value);
256 EXPECT_FLOAT_EQ(start_opacity, target_value.opacity);
257 }
258
TEST(LayerAnimationSequenceTest,AddObserver)259 TEST(LayerAnimationSequenceTest, AddObserver) {
260 base::TimeTicks start_time;
261 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
262 LayerAnimationSequence sequence;
263 sequence.AddElement(
264 LayerAnimationElement::CreateBrightnessElement(1.0f, delta));
265 for (int i = 0; i < 2; ++i) {
266 start_time += delta;
267 sequence.set_start_time(start_time);
268 TestLayerAnimationObserver observer;
269 TestLayerAnimationDelegate delegate;
270 sequence.AddObserver(&observer);
271 EXPECT_TRUE(!observer.last_ended_sequence());
272 sequence.Progress(start_time + delta, &delegate);
273 EXPECT_EQ(observer.last_ended_sequence(), &sequence);
274 sequence.RemoveObserver(&observer);
275 }
276 }
277
TEST(LayerAnimationSequenceTest,ToString)278 TEST(LayerAnimationSequenceTest, ToString) {
279 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
280 LayerAnimationSequence sequence;
281 EXPECT_EQ(
282 "LayerAnimationSequence{size=0, properties=, elements=[], is_cyclic=0, "
283 "group_id=0}",
284 sequence.ToString());
285
286 std::unique_ptr<LayerAnimationElement> brightness =
287 LayerAnimationElement::CreateBrightnessElement(1.0f, delta);
288 int brightness_id = brightness->keyframe_model_id();
289 sequence.AddElement(std::move(brightness));
290 EXPECT_EQ(
291 base::StringPrintf(
292 "LayerAnimationSequence{size=1, properties=BRIGHTNESS, "
293 "elements=[LayerAnimationElement{name=BrightnessTransition, id=%d, "
294 "group=0, last_progressed_fraction=0.00}], "
295 "is_cyclic=0, group_id=0}",
296 brightness_id),
297 sequence.ToString());
298
299 std::unique_ptr<LayerAnimationElement> opacity =
300 LayerAnimationElement::CreateOpacityElement(1.0f, delta);
301 int opacity_id = opacity->keyframe_model_id();
302 sequence.AddElement(std::move(opacity));
303 sequence.set_is_cyclic(true);
304 sequence.set_animation_group_id(1973);
305 EXPECT_EQ(
306 base::StringPrintf(
307 "LayerAnimationSequence{size=2, properties=OPACITY|BRIGHTNESS, "
308 "elements=[LayerAnimationElement{name=BrightnessTransition, id=%d, "
309 "group=0, last_progressed_fraction=0.00}, "
310 "LayerAnimationElement{name=ThreadedOpacityTransition, id=%d, "
311 "group=0, "
312 "last_progressed_fraction=0.00}], is_cyclic=1, "
313 "group_id=1973}",
314 brightness_id, opacity_id),
315 sequence.ToString());
316 }
317
318 } // namespace
319
320 } // namespace ui
321