void AnimationPlayer::postCommit(double timelineTime) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending); m_compositorPending = false; if (!m_compositorState || m_compositorState->pendingAction == None) return; switch (m_compositorState->pendingAction) { case Start: if (!std::isnan(m_compositorState->startTime)) { ASSERT(m_startTime == m_compositorState->startTime); m_compositorState->pendingAction = None; } break; case Pause: case PauseThenStart: ASSERT(std::isnan(m_startTime)); m_compositorState->pendingAction = None; setCurrentTimeInternal((timelineTime - m_compositorState->startTime) * m_playbackRate, TimingUpdateForAnimationFrame); m_currentTimePending = false; break; default: ASSERT_NOT_REACHED(); } }
STDMETHODIMP CTimelineCleanupService::OnTimer(ITimerService* pTimerService) { RETURN_IF_FAILED(m_pTimerServiceCleanup->StopTimer()); UINT uiTopIndex = 0; RETURN_IF_FAILED(m_pTimelineControl->GetTopVisibleItemIndex(&uiTopIndex)); if (uiTopIndex < MAX_ITEMS_COUNT) m_counter++; else m_counter = 0; if (m_counter > MAX_MINUTES) { //cleanup CUpdateScope updateScope(m_pTimelineControl); UINT uiCount = 0; RETURN_IF_FAILED(m_pTimelineControl->GetItemsCount(&uiCount)); while (uiCount > MAX_ITEMS_COUNT) { RETURN_IF_FAILED(m_pTimelineControl->RemoveItemByIndex(uiCount - 2)); //remove last but not "show more" uiCount--; } m_counter = 0; } RETURN_IF_FAILED(m_pTimerServiceCleanup->ResumeTimer()); return S_OK; }
void AnimationPlayer::stop() { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); m_finished = true; m_pendingFinishedEvent = nullptr; }
void AnimationPlayer::play() { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); if (!playing()) m_startTime = nullValue(); if (playStateInternal() == Idle) { // We may not go into the pending state, but setting it to something other // than Idle here will force an update. ASSERT(isNull(m_startTime)); m_playState = Pending; m_held = true; m_holdTime = 0; } m_finished = false; 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); }
bool AnimationPlayer::update(TimingUpdateReason reason) { if (!m_timeline) return false; PlayStateUpdateScope updateScope(*this, reason, DoNotSetCompositorPending); m_outdated = false; bool idle = playStateInternal() == Idle; if (m_content) { double inheritedTime = idle || isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal(); // Special case for end-exclusivity when playing backwards. if (inheritedTime == 0 && m_playbackRate < 0) inheritedTime = -1; m_content->updateInheritedTime(inheritedTime, reason); } if ((idle || finished()) && !m_finished) { if (reason == TimingUpdateForAnimationFrame && (idle || hasStartTime())) { const AtomicString& eventType = EventTypeNames::finish; if (executionContext() && hasEventListeners(eventType)) { double eventCurrentTime = currentTimeInternal() * 1000; m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, eventCurrentTime, timeline()->currentTime()); m_pendingFinishedEvent->setTarget(this); m_pendingFinishedEvent->setCurrentTarget(this); m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent); } m_finished = true; } } ASSERT(!m_outdated); return !m_finished; }
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 Animation::setPlaybackRate(double playbackRate) { if (playbackRate == m_playbackRate) return; PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); setPlaybackRateInternal(playbackRate); }
double Animation::currentTime() { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); if (m_currentTimePending || playStateInternal() == Idle) return std::numeric_limits<double>::quiet_NaN(); return currentTimeInternal() * 1000; }
void Animation::setCurrentTime(double newCurrentTime) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); m_currentTimePending = false; setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); if (calculatePlayState() == Finished) m_startTime = calculateStartTime(newCurrentTime); }
void AnimationPlayer::unpause() { if (!m_paused) return; PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); m_currentTimePending = true; unpauseInternal(); }
double AnimationPlayer::currentTime() { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetCurrentTime); if (m_currentTimePending || playStateInternal() == Idle) return std::numeric_limits<double>::quiet_NaN(); return currentTimeInternal() * 1000; }
void AnimationPlayer::setCurrentTime(double newCurrentTime) { UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentTime); if (!std::isfinite(newCurrentTime)) return; PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); m_currentTimePending = false; setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); }
void Animation::setStartTime(double startTime) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); if (m_paused || playStateInternal() == Idle) return; if (startTime == m_startTime) return; m_currentTimePending = false; setStartTimeInternal(startTime / 1000); }
void AnimationPlayer::setPlaybackRate(double playbackRate) { UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetPlaybackRate); if (!std::isfinite(playbackRate)) return; if (playbackRate == m_playbackRate) return; PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); setPlaybackRateInternal(playbackRate); }
void AnimationPlayer::pause() { if (m_paused) return; PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); if (playing()) { m_currentTimePending = true; } m_paused = true; setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); }
bool Animation::update(TimingUpdateReason reason) { if (!m_timeline) return false; PlayStateUpdateScope updateScope(*this, reason, DoNotSetCompositorPending); clearOutdated(); bool idle = playStateInternal() == Idle; if (m_content) { double inheritedTime = idle || isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal(); if (!isNull(inheritedTime)) { double timeForClipping = m_held && (!limited(inheritedTime) || isNull(m_startTime)) // Use hold time when there is no start time. ? inheritedTime // Use calculated current time when the animation is limited. : calculateCurrentTime(); if (clipped(timeForClipping)) inheritedTime = nullValue(); } // Special case for end-exclusivity when playing backwards. if (inheritedTime == 0 && m_playbackRate < 0) inheritedTime = -1; m_content->updateInheritedTime(inheritedTime, reason); } if ((idle || limited()) && !m_finished) { if (reason == TimingUpdateForAnimationFrame && (idle || hasStartTime())) { if (idle) { // TODO(dstockwell): Fire the cancel event. } else { const AtomicString& eventType = EventTypeNames::finish; if (executionContext() && hasEventListeners(eventType)) { double eventCurrentTime = currentTimeInternal() * 1000; m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, eventCurrentTime, timeline()->currentTime()); m_pendingFinishedEvent->setTarget(this); m_pendingFinishedEvent->setCurrentTarget(this); m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent); } } m_finished = true; } } ASSERT(!m_outdated); return !m_finished || std::isfinite(timeToEffectChange()); }
void Animation::cancel() { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); if (playStateInternal() == Idle) return; m_holdTime = currentTimeInternal(); m_held = true; // TODO m_playState = Idle; m_startTime = nullValue(); m_currentTimePending = false; }
void AnimationPlayer::setStartTime(double startTime) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetStartTime); if (m_paused || playStateInternal() == Idle) return; if (!std::isfinite(startTime)) return; if (startTime == m_startTime) return; m_currentTimePending = false; setStartTimeInternal(startTime / 1000); }
bool Animation::preCommit(int compositorGroup, bool startOnCompositor) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending); bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate); bool hardChange = m_compositorState && (m_compositorState->effectChanged || m_compositorState->startTime != m_startTime); // FIXME: softChange && !hardChange should generate a Pause/ThenStart, // not a Cancel, but we can't communicate these to the compositor yet. bool changed = softChange || hardChange; bool shouldCancel = (!playing() && m_compositorState) || changed; bool shouldStart = playing() && (!m_compositorState || changed); if (startOnCompositor && shouldCancel && shouldStart && m_compositorState && m_compositorState->pendingAction == Start) { // Restarting but still waiting for a start time. return false; } if (shouldCancel) { cancelAnimationOnCompositor(); m_compositorState = nullptr; } ASSERT(!m_compositorState || !std::isnan(m_compositorState->startTime)); if (!shouldStart) { m_currentTimePending = false; } if (shouldStart) { m_compositorGroup = compositorGroup; if (startOnCompositor) { if (isCandidateForAnimationOnCompositor()) createCompositorPlayer(); if (maybeStartAnimationOnCompositor()) m_compositorState = adoptPtr(new CompositorState(*this)); else cancelIncompatibleAnimationsOnCompositor(); } } return true; }
void AnimationPlayer::cancel() { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); if (playStateInternal() == Idle) return; m_holdTime = currentTimeInternal(); m_held = true; // TODO m_playState = Idle; m_startTime = nullValue(); m_currentTimePending = false; // after cancelation, transitions must be downgraded or they'll fail // to be considered when retriggering themselves. This can happen if // the transition is captured through getAnimationPlayers then played. if (m_content && m_content->isAnimation()) toAnimation(m_content.get())->downgradeToNormalAnimation(); }
void Animation::setEffect(AnimationEffect* newEffect) { if (m_content == newEffect) return; PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, SetCompositorPendingWithEffectChanged); double storedCurrentTime = currentTimeInternal(); if (m_content) m_content->detach(); m_content = newEffect; if (newEffect) { // FIXME: This logic needs to be updated once groups are implemented if (newEffect->animation()) { newEffect->animation()->cancel(); newEffect->animation()->setEffect(0); } newEffect->attach(this); setOutdated(); } setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); }
void AnimationPlayer::finish(ExceptionState& exceptionState) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); if (!m_playbackRate || playStateInternal() == Idle) { return; } if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infinity()) { exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity."); return; } double newCurrentTime = m_playbackRate < 0 ? 0 : sourceEnd(); setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand); if (!paused()) { m_startTime = calculateStartTime(newCurrentTime); } m_currentTimePending = false; ASSERT(finished()); }
void AnimationPlayer::setSource(AnimationNode* newSource) { if (m_content == newSource) return; PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, SetCompositorPendingWithSourceChanged); 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->player()->setSource(0); } newSource->attach(this); setOutdated(); } setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); }