void AnimationPlayer::notifyCompositorStartTime(double timelineTime) { if (m_compositorState) { ASSERT(m_compositorState->pendingAction == Start); ASSERT(std::isnan(m_compositorState->startTime)); double initialCompositorHoldTime = m_compositorState->holdTime; m_compositorState->pendingAction = None; m_compositorState->startTime = timelineTime; if (paused() || m_compositorState->playbackRate != m_playbackRate || m_compositorState->sourceChanged) { // Paused state, playback rate, or source changed while starting. setCompositorPending(); } if (m_startTime == timelineTime) { // The start time was set to the incoming compositor start time. // Unlikely, but possible. // FIXME: Depending on what changed above this might still be pending. // Maybe... m_currentTimePending = false; return; } if (!std::isnan(m_startTime) || currentTimeInternal() != initialCompositorHoldTime) { // A new start time or current time was set while starting. setCompositorPending(); return; } } if (playing()) { ASSERT(std::isnan(m_startTime)); ASSERT(m_held); if (m_playbackRate == 0) { setStartTimeInternal(timelineTime); } else { setStartTimeInternal(timelineTime + currentTimeInternal() / -m_playbackRate); } // FIXME: This avoids marking this player as outdated needlessly when a start time // is notified, but we should refactor how outdating works to avoid this. m_outdated = false; m_currentTimePending = false; } }
void AnimationPlayer::notifyCompositorStartTime(double timelineTime) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending); if (m_compositorState) { ASSERT(m_compositorState->pendingAction == Start); ASSERT(std::isnan(m_compositorState->startTime)); double initialCompositorHoldTime = m_compositorState->holdTime; m_compositorState->pendingAction = None; m_compositorState->startTime = timelineTime + currentTimeInternal() / -m_playbackRate; if (m_startTime == timelineTime) { // The start time was set to the incoming compositor start time. // Unlikely, but possible. // FIXME: Depending on what changed above this might still be pending. // Maybe... m_currentTimePending = false; return; } if (!std::isnan(m_startTime) || currentTimeInternal() != initialCompositorHoldTime) { // A new start time or current time was set while starting. setCompositorPending(true); return; } } notifyStartTime(timelineTime); }
void AnimationPlayer::unpause() { if (!m_paused) return; setCompositorPending(); m_currentTimePending = true; unpauseInternal(); }
void AnimationPlayer::pause() { if (m_paused) return; if (playing()) { setCompositorPending(); m_currentTimePending = true; } m_paused = true; setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); }
void AnimationPlayer::setStartTime(double startTime) { if (m_paused) // FIXME: Should this throw an exception? return; if (!std::isfinite(startTime)) return; if (startTime == m_startTime) return; setCompositorPending(); m_currentTimePending = false; setStartTimeInternal(startTime / 1000); }
void AnimationPlayer::setCurrentTime(double newCurrentTime) { if (!std::isfinite(newCurrentTime)) return; setCompositorPending(); // Setting current time while pending forces a start time. if (m_currentTimePending) { m_startTime = 0; m_currentTimePending = false; } setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); }
void AnimationPlayer::play() { if (!playing()) m_startTime = nullValue(); setCompositorPending(); unpauseInternal(); if (!m_content) return; double currentTime = this->currentTimeInternal(); if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd())) setCurrentTimeInternal(0, TimingUpdateOnDemand); else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd())) setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand); m_finished = false; }
void AnimationPlayer::setPlaybackRate(double playbackRate) { if (!std::isfinite(playbackRate)) return; if (playbackRate == m_playbackRate) return; setCompositorPending(); if (!finished() && !paused()) m_currentTimePending = true; double storedCurrentTime = currentTimeInternal(); if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && playbackRate <= 0)) m_finished = false; m_playbackRate = playbackRate; m_startTime = std::numeric_limits<double>::quiet_NaN(); setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); }
void AnimationPlayer::finish(ExceptionState& exceptionState) { if (!m_playbackRate) { return; } if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infinity()) { exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity."); return; } if (playing()) { setCompositorPending(); } if (m_playbackRate < 0) { setCurrentTimeInternal(0, TimingUpdateOnDemand); } else { setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand); } ASSERT(finished()); }
void AnimationPlayer::setSource(AnimationNode* newSource) { if (m_content == newSource) return; setCompositorPending(true); double storedCurrentTime = currentTimeInternal(); if (m_content) m_content->detach(); m_content = newSource; if (newSource) { // FIXME: This logic needs to be updated once groups are implemented if (newSource->player()) newSource->player()->cancel(); newSource->attach(this); setOutdated(); } setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); }