forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeyframe_model.h
298 lines (242 loc) · 11.8 KB
/
keyframe_model.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
// Copyright 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.
#ifndef CC_ANIMATION_KEYFRAME_MODEL_H_
#define CC_ANIMATION_KEYFRAME_MODEL_H_
#include <memory>
#include "base/optional.h"
#include "base/time/time.h"
#include "cc/animation/animation_export.h"
#include "cc/paint/element_id.h"
namespace cc {
class AnimationCurve;
// A KeyframeModel contains all the state required to play an AnimationCurve.
// Specifically, the affected property, the run state (paused, finished, etc.),
// loop count, last pause time, and the total time spent paused.
// It represents a model of the keyframes (internally represented as a curve).
class CC_ANIMATION_EXPORT KeyframeModel {
public:
// KeyframeModels begin in the 'WAITING_FOR_TARGET_AVAILABILITY' state. A
// KeyframeModel waiting for target availibility will run as soon as its
// target property is free (and all the KeyframeModels animating with it are
// also able to run). When this time arrives, the controller will move the
// keyframe model into the STARTING state, and then into the RUNNING state.
// RUNNING KeyframeModels may toggle between RUNNING and PAUSED, and may be
// stopped by moving into either the ABORTED or FINISHED states. A FINISHED
// keyframe model was allowed to run to completion, but an ABORTED keyframe
// model was not. An animation in the state ABORTED_BUT_NEEDS_COMPLETION is a
// keyframe model that was aborted for some reason, but needs to be finished.
// Currently this is for impl-only scroll offset KeyframeModels that need to
// be completed on the main thread.
enum RunState {
WAITING_FOR_TARGET_AVAILABILITY = 0,
WAITING_FOR_DELETION,
STARTING,
RUNNING,
PAUSED,
FINISHED,
ABORTED,
ABORTED_BUT_NEEDS_COMPLETION,
// This sentinel must be last.
LAST_RUN_STATE = ABORTED_BUT_NEEDS_COMPLETION
};
static std::string ToString(RunState);
enum class Direction { NORMAL, REVERSE, ALTERNATE_NORMAL, ALTERNATE_REVERSE };
enum class FillMode { NONE, FORWARDS, BACKWARDS, BOTH, AUTO };
enum class Phase { BEFORE, ACTIVE, AFTER };
// The |custom_property_name| has a default value of an empty string,
// indicating that the animated property is a native property. When it is an
// animated custom property, it should be the property name.
static std::unique_ptr<KeyframeModel> Create(
std::unique_ptr<AnimationCurve> curve,
int keyframe_model_id,
int group_id,
int target_property_id,
const std::string& custom_property_name = "");
std::unique_ptr<KeyframeModel> CreateImplInstance(
RunState initial_run_state) const;
KeyframeModel(const KeyframeModel&) = delete;
virtual ~KeyframeModel();
KeyframeModel& operator=(const KeyframeModel&) = delete;
int id() const { return id_; }
int group() const { return group_; }
int target_property_id() const { return target_property_id_; }
ElementId element_id() const { return element_id_; }
void set_element_id(ElementId element_id) { element_id_ = element_id; }
RunState run_state() const { return run_state_; }
void SetRunState(RunState run_state, base::TimeTicks monotonic_time);
// This is the number of times that the keyframe model will play. If this
// value is zero the keyframe model will not play. If it is negative, then
// the keyframe model will loop indefinitely.
double iterations() const { return iterations_; }
void set_iterations(double n) { iterations_ = n; }
double iteration_start() const { return iteration_start_; }
void set_iteration_start(double iteration_start) {
iteration_start_ = iteration_start;
}
base::TimeTicks start_time() const { return start_time_; }
void set_start_time(base::TimeTicks monotonic_time) {
start_time_ = monotonic_time;
}
bool has_set_start_time() const { return !start_time_.is_null(); }
base::TimeDelta time_offset() const { return time_offset_; }
void set_time_offset(base::TimeDelta monotonic_time) {
time_offset_ = monotonic_time;
}
// Pause the keyframe effect at local time |pause_offset|.
void Pause(base::TimeDelta pause_offset);
Direction direction() { return direction_; }
void set_direction(Direction direction) { direction_ = direction; }
FillMode fill_mode() { return fill_mode_; }
void set_fill_mode(FillMode fill_mode) { fill_mode_ = fill_mode; }
double playback_rate() { return playback_rate_; }
void set_playback_rate(double playback_rate) {
playback_rate_ = playback_rate;
}
bool IsFinishedAt(base::TimeTicks monotonic_time) const;
bool is_finished() const {
return run_state_ == FINISHED || run_state_ == ABORTED ||
run_state_ == WAITING_FOR_DELETION;
}
bool InEffect(base::TimeTicks monotonic_time) const;
AnimationCurve* curve() { return curve_.get(); }
const AnimationCurve* curve() const { return curve_.get(); }
// If this is true, even if the keyframe model is running, it will not be
// tickable until it is given a start time. This is true for KeyframeModels
// running on the main thread.
bool needs_synchronized_start_time() const {
return needs_synchronized_start_time_;
}
void set_needs_synchronized_start_time(bool needs_synchronized_start_time) {
needs_synchronized_start_time_ = needs_synchronized_start_time;
}
// This is true for KeyframeModels running on the main thread when the
// FINISHED event sent by the corresponding impl keyframe model has been
// received.
bool received_finished_event() const { return received_finished_event_; }
void set_received_finished_event(bool received_finished_event) {
received_finished_event_ = received_finished_event;
}
// Takes the given absolute time, and using the start time and the number
// of iterations, returns the relative time in the current iteration.
base::TimeDelta TrimTimeToCurrentIteration(
base::TimeTicks monotonic_time) const;
void set_is_controlling_instance_for_test(bool is_controlling_instance) {
is_controlling_instance_ = is_controlling_instance;
}
bool is_controlling_instance() const { return is_controlling_instance_; }
void PushPropertiesTo(KeyframeModel* other) const;
std::string ToString() const;
void SetIsImplOnly();
bool is_impl_only() const { return is_impl_only_; }
void set_affects_active_elements(bool affects_active_elements) {
affects_active_elements_ = affects_active_elements;
}
bool affects_active_elements() const { return affects_active_elements_; }
void set_affects_pending_elements(bool affects_pending_elements) {
affects_pending_elements_ = affects_pending_elements;
}
bool affects_pending_elements() const { return affects_pending_elements_; }
const std::string& custom_property_name() const {
return custom_property_name_;
}
KeyframeModel::Phase CalculatePhaseForTesting(
base::TimeDelta local_time) const;
private:
KeyframeModel(std::unique_ptr<AnimationCurve> curve,
int keyframe_model_id,
int group_id,
int target_property_id,
const std::string& custom_property_name);
// Return local time for this keyframe model given the absolute monotonic
// time.
//
// Local time represents the time value that is used to tick this keyframe
// model and is relative to its start time. It is closely related to the local
// time concept in web animations [1]. It is:
// - for playing animation : wall time - start time - paused duration
// - for paused animation : paused time
// - otherwise : zero
//
// Here is small diagram that shows how active, local, and monotonic times
// relate to each other and to the run state.
//
// run state Starting (R)unning Paused (R) Paused (R) Finished
// ^ ^
// | |
// monotonic time ------------------------------------------------->
// | |
// local time +-----------------+ +---+ +--------->
// | |
// active time + +------+ +---+ +------+
// (-offset)
//
// [1] https://drafts.csswg.org/web-animations/#local-time-section
base::TimeDelta ConvertMonotonicTimeToLocalTime(
base::TimeTicks monotonic_time) const;
KeyframeModel::Phase CalculatePhase(base::TimeDelta local_time) const;
base::Optional<base::TimeDelta> CalculateActiveTime(
base::TimeTicks monotonic_time) const;
std::unique_ptr<AnimationCurve> curve_;
// IDs must be unique.
int id_;
// KeyframeModels that must be run together are called 'grouped' and have the
// same group id. Grouped KeyframeModels are guaranteed to start at the same
// time and no other KeyframeModels may animate any of the group's target
// properties until all KeyframeModels in the group have finished animating.
int group_;
// If specified, overrides the ElementId to apply this KeyframeModel's effect
// value on.
ElementId element_id_;
int target_property_id_;
RunState run_state_;
double iterations_;
double iteration_start_;
base::TimeTicks start_time_;
Direction direction_;
double playback_rate_;
FillMode fill_mode_;
// The time offset effectively pushes the start of the keyframe model back in
// time. This is used for resuming paused KeyframeModels -- an animation is
// added with a non-zero time offset, causing the keyframe model to skip ahead
// to the desired point in time.
base::TimeDelta time_offset_;
bool needs_synchronized_start_time_;
bool received_finished_event_;
// These are used when converting monotonic to local time to account for time
// spent while paused. This is not included in AnimationState since it
// there is absolutely no need for clients of this controller to know
// about these values.
base::TimeTicks pause_time_;
base::TimeDelta total_paused_duration_;
// KeyframeModels lead dual lives. An active keyframe model will be
// conceptually owned by two controllers, one on the impl thread and one on
// the main. In reality, there will be two separate KeyframeModel instances
// for the same keyframe model. They will have the same group id and the same
// target property (these two values uniquely identify a keyframe model). The
// instance on the impl thread is the instance that ultimately controls the
// values of the animating layer and so we will refer to it as the
// 'controlling instance'.
// Impl only keyframe models are the exception to this rule. They have only a
// single instance. We consider this instance as the 'controlling instance'.
bool is_controlling_instance_;
bool is_impl_only_;
// When pushed from a main-thread controller to a compositor-thread
// controller, a keyframe model will initially only affect pending elements
// (corresponding to layers in the pending tree). KeyframeModels that only
// affect pending elements are able to reach the STARTING state and tick
// pending elements, but cannot proceed any further and do not tick active
// elements. After activation, such KeyframeModels affect both kinds of
// elements and are able to proceed past the STARTING state. When the removal
// of a keyframe model is pushed from a main-thread controller to a
// compositor-thread controller, this initially only makes the keyframe model
// stop affecting pending elements. After activation, such KeyframeModels no
// longer affect any elements, and are deleted.
bool affects_active_elements_;
bool affects_pending_elements_;
// Name of the animated custom property. Empty if it is an animated native
// property.
std::string custom_property_name_;
};
} // namespace cc
#endif // CC_ANIMATION_KEYFRAME_MODEL_H_