Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(353)

Side by Side Diff: Source/core/animation/AnimationPlayer.cpp

Issue 365163004: Web Animations: Remove timeLag from Player API and model (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/animation/AnimationPlayer.h ('k') | Source/core/animation/AnimationPlayer.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 RefPtrWillBeRawPtr<AnimationPlayer> player = adoptRefWillBeRefCountedGarbage Collected(new AnimationPlayer(executionContext, timeline, content)); 54 RefPtrWillBeRawPtr<AnimationPlayer> player = adoptRefWillBeRefCountedGarbage Collected(new AnimationPlayer(executionContext, timeline, content));
55 player->suspendIfNeeded(); 55 player->suspendIfNeeded();
56 return player.release(); 56 return player.release();
57 } 57 }
58 58
59 AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTi meline& timeline, AnimationNode* content) 59 AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTi meline& timeline, AnimationNode* content)
60 : ActiveDOMObject(executionContext) 60 : ActiveDOMObject(executionContext)
61 , m_playbackRate(1) 61 , m_playbackRate(1)
62 , m_startTime(nullValue()) 62 , m_startTime(nullValue())
63 , m_holdTime(nullValue()) 63 , m_holdTime(nullValue())
64 , m_storedTimeLag(0)
65 , m_sortInfo(nextSequenceNumber()) 64 , m_sortInfo(nextSequenceNumber())
66 , m_content(content) 65 , m_content(content)
67 , m_timeline(&timeline) 66 , m_timeline(&timeline)
68 , m_paused(false) 67 , m_paused(false)
69 , m_held(false) 68 , m_held(false)
70 , m_isPausedForTesting(false) 69 , m_isPausedForTesting(false)
71 , m_outdated(true) 70 , m_outdated(true)
72 , m_finished(false) 71 , m_finished(false)
73 { 72 {
74 ScriptWrappable::init(this); 73 ScriptWrappable::init(this);
(...skipping 17 matching lines...) Expand all
92 double AnimationPlayer::sourceEnd() const 91 double AnimationPlayer::sourceEnd() const
93 { 92 {
94 return m_content ? m_content->endTimeInternal() : 0; 93 return m_content ? m_content->endTimeInternal() : 0;
95 } 94 }
96 95
97 bool AnimationPlayer::limited(double currentTime) const 96 bool AnimationPlayer::limited(double currentTime) const
98 { 97 {
99 return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && cu rrentTime >= sourceEnd()); 98 return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && cu rrentTime >= sourceEnd());
100 } 99 }
101 100
102 double AnimationPlayer::currentTimeWithoutLag() const 101 void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime)
103 { 102 {
104 if (isNull(m_startTime) || !m_timeline) 103 ASSERT(std::isfinite(newCurrentTime));
105 return 0;
106 return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate;
107 }
108 104
109 double AnimationPlayer::currentTimeWithLag() const 105 bool oldHeld = m_held;
110 { 106 bool outdated = false;
111 ASSERT(!m_held); 107 m_held = m_paused || !m_playbackRate || limited(newCurrentTime);
112 double time = currentTimeWithoutLag();
113 return std::isinf(time) ? time : time - m_storedTimeLag;
114 }
115 108
116 void AnimationPlayer::updateTimingState(double newCurrentTime)
117 {
118 ASSERT(!isNull(newCurrentTime));
119 bool oldHeld = m_held;
120 m_held = m_paused || !m_playbackRate || limited(newCurrentTime);
121 if (m_held) { 109 if (m_held) {
122 if (!oldHeld || m_holdTime != newCurrentTime) 110 if (!oldHeld || m_holdTime != newCurrentTime)
123 setOutdated(); 111 outdated = true;
124 m_holdTime = newCurrentTime; 112 m_holdTime = newCurrentTime;
125 m_storedTimeLag = nullValue(); 113 if (m_paused || !m_playbackRate)
114 m_startTime = nullValue();
126 } else { 115 } else {
127 m_holdTime = nullValue(); 116 m_holdTime = nullValue();
128 m_storedTimeLag = currentTimeWithoutLag() - newCurrentTime; 117 m_startTime = m_timeline->effectiveTime() - newCurrentTime / m_playbackR ate;
129 m_finished = false; 118 m_finished = false;
119 outdated = true;
120 }
121
122 if (outdated) {
130 setOutdated(); 123 setOutdated();
124 cancelAnimationOnCompositor();
125 if (!m_held)
126 schedulePendingAnimationOnCompositor();
131 } 127 }
132 } 128 }
133 129
130 // Update timing to reflect updated animation clock due to tick
134 void AnimationPlayer::updateCurrentTimingState() 131 void AnimationPlayer::updateCurrentTimingState()
135 { 132 {
136 if (m_held) { 133 if (m_held) {
137 updateTimingState(m_holdTime); 134 setCurrentTimeInternal(m_holdTime);
138 return; 135 return;
139 } 136 }
140 if (!limited(currentTimeWithLag())) 137 if (!limited(calculateCurrentTime()))
141 return; 138 return;
142 m_held = true; 139 m_held = true;
143 m_holdTime = m_playbackRate < 0 ? 0 : sourceEnd(); 140 m_holdTime = m_playbackRate < 0 ? 0 : sourceEnd();
144 m_storedTimeLag = nullValue();
145 } 141 }
146 142
147 double AnimationPlayer::currentTime() 143 double AnimationPlayer::currentTime()
148 { 144 {
149 return currentTimeInternal() * 1000; 145 return currentTimeInternal() * 1000;
150 } 146 }
151 147
152 double AnimationPlayer::currentTimeInternal() 148 double AnimationPlayer::currentTimeInternal()
153 { 149 {
154 updateCurrentTimingState(); 150 updateCurrentTimingState();
155 if (m_held) 151 if (m_held)
156 return m_holdTime; 152 return m_holdTime;
157 return currentTimeWithLag(); 153 return calculateCurrentTime();
154 }
155
156 double AnimationPlayer::calculateCurrentTime() const
157 {
158 ASSERT(!m_held);
159 if (isNull(m_startTime) || !m_timeline)
160 return 0;
161 return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate;
158 } 162 }
159 163
160 void AnimationPlayer::setCurrentTime(double newCurrentTime) 164 void AnimationPlayer::setCurrentTime(double newCurrentTime)
161 { 165 {
162 setCurrentTimeInternal(newCurrentTime / 1000);
163 }
164
165 void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime)
166 {
167 if (!std::isfinite(newCurrentTime)) 166 if (!std::isfinite(newCurrentTime))
168 return; 167 return;
169 updateTimingState(newCurrentTime); 168 setCurrentTimeInternal(newCurrentTime / 1000);
170 cancelAnimationOnCompositor();
171 schedulePendingAnimationOnCompositor();
172 } 169 }
173 170
174 void AnimationPlayer::setStartTimeInternal(double newStartTime, bool isUpdateFro mCompositor) 171 void AnimationPlayer::setStartTimeInternal(double newStartTime, bool isUpdateFro mCompositor)
175 { 172 {
176 ASSERT(!isUpdateFromCompositor || !hasStartTime()); 173 ASSERT(!isUpdateFromCompositor || !hasStartTime());
177 174
175 if (m_paused)
176 return;
178 if (!std::isfinite(newStartTime)) 177 if (!std::isfinite(newStartTime))
179 return; 178 return;
180 if (newStartTime == m_startTime) 179 if (newStartTime == m_startTime)
181 return; 180 return;
182 updateCurrentTimingState(); // Update the value of held 181
183 bool hadStartTime = hasStartTime(); 182 bool hadStartTime = hasStartTime();
184 double previousCurrentTime = currentTimeInternal(); 183 double previousCurrentTime = currentTimeInternal();
185 m_startTime = newStartTime; 184 m_startTime = newStartTime;
186 updateCurrentTimingState(); 185 double newCurrentTime = currentTimeInternal();
187 if (previousCurrentTime != currentTimeInternal()) { 186
187 if (previousCurrentTime != newCurrentTime) {
188 setOutdated(); 188 setOutdated();
189 } else if (!hadStartTime && m_timeline) { 189 } else if (!hadStartTime && m_timeline) {
190 // Even though this player is not outdated, time to effect change is 190 // Even though this player is not outdated, time to effect change is
191 // infinity until start time is set. 191 // infinity until start time is set.
192 m_timeline->wake(); 192 m_timeline->wake();
193 } 193 }
194 if (!isUpdateFromCompositor) { 194 if (!isUpdateFromCompositor) {
195 cancelAnimationOnCompositor(); 195 cancelAnimationOnCompositor();
196 schedulePendingAnimationOnCompositor(); 196 schedulePendingAnimationOnCompositor();
197 } 197 }
198 } 198 }
199 199
200 void AnimationPlayer::setSource(AnimationNode* newSource) 200 void AnimationPlayer::setSource(AnimationNode* newSource)
201 { 201 {
202 if (m_content == newSource) 202 if (m_content == newSource)
203 return; 203 return;
204 cancelAnimationOnCompositor(); 204 cancelAnimationOnCompositor();
205 double storedCurrentTime = currentTimeInternal(); 205 double storedCurrentTime = currentTimeInternal();
206 if (m_content) 206 if (m_content)
207 m_content->detach(); 207 m_content->detach();
208 m_content = newSource; 208 m_content = newSource;
209 if (newSource) { 209 if (newSource) {
210 // FIXME: This logic needs to be updated once groups are implemented 210 // FIXME: This logic needs to be updated once groups are implemented
211 if (newSource->player()) 211 if (newSource->player())
212 newSource->player()->cancel(); 212 newSource->player()->cancel();
213 newSource->attach(this); 213 newSource->attach(this);
214 } 214 }
215 updateTimingState(storedCurrentTime); 215 setCurrentTimeInternal(storedCurrentTime);
216 schedulePendingAnimationOnCompositor(); 216 schedulePendingAnimationOnCompositor();
217 } 217 }
218 218
219 void AnimationPlayer::pause() 219 void AnimationPlayer::pause()
220 { 220 {
221 if (m_paused) 221 if (m_paused)
222 return; 222 return;
223 m_paused = true; 223 m_paused = true;
224 updateTimingState(currentTimeInternal()); 224 setCurrentTimeInternal(currentTimeInternal());
225 cancelAnimationOnCompositor(); 225 cancelAnimationOnCompositor();
226 } 226 }
227 227
228 void AnimationPlayer::unpause() 228 void AnimationPlayer::unpause()
229 { 229 {
230 if (!m_paused) 230 if (!m_paused)
231 return; 231 return;
232 m_paused = false; 232 m_paused = false;
233 updateTimingState(currentTimeInternal()); 233 setCurrentTimeInternal(currentTimeInternal());
234 schedulePendingAnimationOnCompositor();
235 } 234 }
236 235
237 void AnimationPlayer::play() 236 void AnimationPlayer::play()
238 { 237 {
239 cancelAnimationOnCompositor(); 238 cancelAnimationOnCompositor();
240 // Note, unpause schedules pending animation on compositor if necessary.
241 unpause(); 239 unpause();
242 if (!m_content) 240 if (!m_content)
243 return; 241 return;
244 double currentTime = this->currentTimeInternal(); 242 double currentTime = this->currentTimeInternal();
245 if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd())) 243 if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd()))
246 setCurrentTimeInternal(0); 244 setCurrentTimeInternal(0);
247 else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd( ))) 245 else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd( )))
248 setCurrentTimeInternal(sourceEnd()); 246 setCurrentTimeInternal(sourceEnd());
249 m_finished = false; 247 m_finished = false;
250 } 248 }
251 249
252 void AnimationPlayer::reverse() 250 void AnimationPlayer::reverse()
253 { 251 {
254 if (!m_playbackRate) 252 if (!m_playbackRate)
255 return; 253 return;
256 if (m_content) { 254 if (m_content) {
257 if (m_playbackRate > 0 && currentTimeInternal() > sourceEnd()) 255 if (m_playbackRate > 0 && currentTimeInternal() > sourceEnd())
258 setCurrentTimeInternal(sourceEnd()); 256 setCurrentTimeInternal(sourceEnd());
259 else if (m_playbackRate < 0 && currentTimeInternal() < 0) 257 else if (m_playbackRate < 0 && currentTimeInternal() < 0)
260 setCurrentTimeInternal(0); 258 setCurrentTimeInternal(0);
261 } 259 }
262 setPlaybackRate(-m_playbackRate); 260 setPlaybackRate(-m_playbackRate);
263 cancelAnimationOnCompositor();
264 // Note, unpause schedules pending animation on compositor if necessary.
265 unpause(); 261 unpause();
266 } 262 }
267 263
268 void AnimationPlayer::finish(ExceptionState& exceptionState) 264 void AnimationPlayer::finish(ExceptionState& exceptionState)
269 { 265 {
270 if (!m_playbackRate) 266 if (!m_playbackRate)
271 return; 267 return;
272 if (m_playbackRate < 0) { 268 if (m_playbackRate < 0) {
273 setCurrentTimeInternal(0); 269 setCurrentTimeInternal(0);
274 } else { 270 } else {
275 if (sourceEnd() == std::numeric_limits<double>::infinity()) { 271 if (sourceEnd() == std::numeric_limits<double>::infinity()) {
276 exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity."); 272 exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity.");
277 return; 273 return;
278 } 274 }
279 setCurrentTimeInternal(sourceEnd()); 275 setCurrentTimeInternal(sourceEnd());
280 } 276 }
281 ASSERT(finished()); 277 ASSERT(finished());
282 cancelAnimationOnCompositor();
283 } 278 }
284 279
285 const AtomicString& AnimationPlayer::interfaceName() const 280 const AtomicString& AnimationPlayer::interfaceName() const
286 { 281 {
287 return EventTargetNames::AnimationPlayer; 282 return EventTargetNames::AnimationPlayer;
288 } 283 }
289 284
290 ExecutionContext* AnimationPlayer::executionContext() const 285 ExecutionContext* AnimationPlayer::executionContext() const
291 { 286 {
292 return ActiveDOMObject::executionContext(); 287 return ActiveDOMObject::executionContext();
(...skipping 18 matching lines...) Expand all
311 } 306 }
312 307
313 void AnimationPlayer::setPlaybackRate(double playbackRate) 308 void AnimationPlayer::setPlaybackRate(double playbackRate)
314 { 309 {
315 if (!std::isfinite(playbackRate)) 310 if (!std::isfinite(playbackRate))
316 return; 311 return;
317 double storedCurrentTime = currentTimeInternal(); 312 double storedCurrentTime = currentTimeInternal();
318 if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && play backRate <= 0)) 313 if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && play backRate <= 0))
319 m_finished = false; 314 m_finished = false;
320 m_playbackRate = playbackRate; 315 m_playbackRate = playbackRate;
321 updateTimingState(storedCurrentTime); 316 setCurrentTimeInternal(storedCurrentTime);
322 cancelAnimationOnCompositor();
323 schedulePendingAnimationOnCompositor();
324 } 317 }
325 318
326 void AnimationPlayer::setOutdated() 319 void AnimationPlayer::setOutdated()
327 { 320 {
328 m_outdated = true; 321 m_outdated = true;
329 if (m_timeline) 322 if (m_timeline)
330 m_timeline->setOutdatedAnimationPlayer(this); 323 m_timeline->setOutdatedAnimationPlayer(this);
331 } 324 }
332 325
333 bool AnimationPlayer::canStartAnimationOnCompositor() 326 bool AnimationPlayer::canStartAnimationOnCompositor()
334 { 327 {
335 // FIXME: Need compositor support for playback rate != 1. 328 // FIXME: Need compositor support for playback rate != 1.
336 if (playbackRate() != 1) 329 if (playbackRate() != 1)
337 return false; 330 return false;
338 331
339 return m_timeline && m_content && m_content->isAnimation() && !m_held; 332 return m_timeline && m_content && m_content->isAnimation() && !m_held;
340 } 333 }
341 334
342 bool AnimationPlayer::maybeStartAnimationOnCompositor() 335 bool AnimationPlayer::maybeStartAnimationOnCompositor()
343 { 336 {
344 if (!canStartAnimationOnCompositor()) 337 if (!canStartAnimationOnCompositor())
345 return false; 338 return false;
346 339
347 return toAnimation(m_content.get())->maybeStartAnimationOnCompositor(timelin e()->zeroTime() + startTimeInternal() + timeLagInternal()); 340 return toAnimation(m_content.get())->maybeStartAnimationOnCompositor(timelin e()->zeroTime() + startTimeInternal());
348 } 341 }
349 342
350 void AnimationPlayer::schedulePendingAnimationOnCompositor() 343 void AnimationPlayer::schedulePendingAnimationOnCompositor()
351 { 344 {
352 ASSERT(!hasActiveAnimationsOnCompositor()); 345 ASSERT(!hasActiveAnimationsOnCompositor());
353 346
354 if (canStartAnimationOnCompositor()) 347 if (canStartAnimationOnCompositor())
355 timeline()->document()->compositorPendingAnimations().add(this); 348 timeline()->document()->compositorPendingAnimations().add(this);
356 } 349 }
357 350
358 bool AnimationPlayer::hasActiveAnimationsOnCompositor() 351 bool AnimationPlayer::hasActiveAnimationsOnCompositor()
359 { 352 {
360 if (!m_content || !m_content->isAnimation()) 353 if (!m_content || !m_content->isAnimation())
361 return false; 354 return false;
362 355
363 return toAnimation(m_content.get())->hasActiveAnimationsOnCompositor(); 356 return toAnimation(m_content.get())->hasActiveAnimationsOnCompositor();
364 } 357 }
365 358
366 void AnimationPlayer::cancelAnimationOnCompositor() 359 void AnimationPlayer::cancelAnimationOnCompositor()
367 { 360 {
368 if (hasActiveAnimationsOnCompositor()) 361 if (hasActiveAnimationsOnCompositor())
369 toAnimation(m_content.get())->cancelAnimationOnCompositor(); 362 toAnimation(m_content.get())->cancelAnimationOnCompositor();
370 } 363 }
371 364
372 bool AnimationPlayer::update(TimingUpdateReason reason) 365 bool AnimationPlayer::update(TimingUpdateReason reason)
373 { 366 {
374 m_outdated = false;
375
376 if (!m_timeline) 367 if (!m_timeline)
377 return false; 368 return false;
378 369
370 updateCurrentTimingState();
371 m_outdated = false;
372
379 if (m_content) { 373 if (m_content) {
380 double inheritedTime = isNull(m_timeline->currentTimeInternal()) ? nullV alue() : currentTimeInternal(); 374 double inheritedTime = isNull(m_timeline->currentTimeInternal()) ? nullV alue() : currentTimeInternal();
381 m_content->updateInheritedTime(inheritedTime, reason); 375 m_content->updateInheritedTime(inheritedTime, reason);
382 } 376 }
383 377
384 if (finished() && !m_finished) { 378 if (finished() && !m_finished) {
385 if (reason == TimingUpdateForAnimationFrame && hasStartTime()) { 379 if (reason == TimingUpdateForAnimationFrame && hasStartTime()) {
386 const AtomicString& eventType = EventTypeNames::finish; 380 const AtomicString& eventType = EventTypeNames::finish;
387 if (executionContext() && hasEventListeners(eventType)) { 381 if (executionContext() && hasEventListeners(eventType)) {
388 m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, currentTime(), timeline()->currentTime()); 382 m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, currentTime(), timeline()->currentTime());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 bool AnimationPlayer::addEventListener(const AtomicString& eventType, PassRefPtr <EventListener> listener, bool useCapture) 419 bool AnimationPlayer::addEventListener(const AtomicString& eventType, PassRefPtr <EventListener> listener, bool useCapture)
426 { 420 {
427 if (eventType == EventTypeNames::finish) 421 if (eventType == EventTypeNames::finish)
428 UseCounter::count(executionContext(), UseCounter::AnimationPlayerFinishE vent); 422 UseCounter::count(executionContext(), UseCounter::AnimationPlayerFinishE vent);
429 return EventTargetWithInlineData::addEventListener(eventType, listener, useC apture); 423 return EventTargetWithInlineData::addEventListener(eventType, listener, useC apture);
430 } 424 }
431 425
432 void AnimationPlayer::pauseForTesting(double pauseTime) 426 void AnimationPlayer::pauseForTesting(double pauseTime)
433 { 427 {
434 RELEASE_ASSERT(!paused()); 428 RELEASE_ASSERT(!paused());
435 updateTimingState(pauseTime); 429 setCurrentTimeInternal(pauseTime);
436 if (!m_isPausedForTesting && hasActiveAnimationsOnCompositor()) 430 if (!m_isPausedForTesting && hasActiveAnimationsOnCompositor())
437 toAnimation(m_content.get())->pauseAnimationForTestingOnCompositor(curre ntTimeInternal()); 431 toAnimation(m_content.get())->pauseAnimationForTestingOnCompositor(curre ntTimeInternal());
438 m_isPausedForTesting = true; 432 m_isPausedForTesting = true;
439 pause(); 433 pause();
440 } 434 }
441 435
442 void AnimationPlayer::trace(Visitor* visitor) 436 void AnimationPlayer::trace(Visitor* visitor)
443 { 437 {
444 visitor->trace(m_content); 438 visitor->trace(m_content);
445 visitor->trace(m_timeline); 439 visitor->trace(m_timeline);
446 visitor->trace(m_pendingFinishedEvent); 440 visitor->trace(m_pendingFinishedEvent);
447 EventTargetWithInlineData::trace(visitor); 441 EventTargetWithInlineData::trace(visitor);
448 } 442 }
449 443
450 } // namespace 444 } // namespace
OLDNEW
« no previous file with comments | « Source/core/animation/AnimationPlayer.h ('k') | Source/core/animation/AnimationPlayer.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698