Example #1
0
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;
}
Example #2
0
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);
}
ScriptPromise Animation::finished(ScriptState* scriptState)
{
    if (!m_finishedPromise) {
        m_finishedPromise = new AnimationPromise(scriptState->executionContext(), this, AnimationPromise::Finished);
        if (playStateInternal() == Finished)
            m_finishedPromise->resolve(this);
    }
    return m_finishedPromise->promise(scriptState->world());
}
ScriptPromise Animation::ready(ScriptState* scriptState)
{
    if (!m_readyPromise) {
        m_readyPromise = new AnimationPromise(scriptState->executionContext(), this, AnimationPromise::Ready);
        if (playStateInternal() != Pending)
            m_readyPromise->resolve(this);
    }
    return m_readyPromise->promise(scriptState->world());
}
double Animation::unlimitedCurrentTimeInternal() const
{
#if ENABLE(ASSERT)
    currentTimeInternal();
#endif
    return playStateInternal() == Paused || isNull(m_startTime)
        ? currentTimeInternal()
        : calculateCurrentTime();
}
double Animation::currentTime()
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (m_currentTimePending || playStateInternal() == Idle)
        return std::numeric_limits<double>::quiet_NaN();

    return currentTimeInternal() * 1000;
}
Example #7
0
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 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 Animation::finish(ExceptionState& exceptionState)
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (!m_playbackRate || playStateInternal() == Idle) {
        return;
    }
    if (m_playbackRate > 0 && effectEnd() == std::numeric_limits<double>::infinity()) {
        exceptionState.throwDOMException(InvalidStateError, "Animation has effect whose end time is infinity.");
        return;
    }

    double newCurrentTime = m_playbackRate < 0 ? 0 : effectEnd();
    setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand);
    if (!paused()) {
        m_startTime = calculateStartTime(newCurrentTime);
    }

    m_currentTimePending = false;
    ASSERT(playStateInternal() != Idle);
    ASSERT(limited());
}
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;
}
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());
}
Example #12
0
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);
}
Example #13
0
String AnimationPlayer::playState()
{
    switch (playStateInternal()) {
    case Idle:
        return "idle";
    case Pending:
        return "pending";
    case Running:
        return "running";
    case Paused:
        return "paused";
    case Finished:
        return "finished";
    default:
        ASSERT_NOT_REACHED();
        return "";
    }
}
Example #14
0
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();
}
// Update timing to reflect updated animation clock due to tick
void Animation::updateCurrentTimingState(TimingUpdateReason reason)
{
    if (m_held) {
        double newCurrentTime = m_holdTime;
        if (playStateInternal() == Finished && !isNull(m_startTime) && m_timeline) {
            // Add hystersis due to floating point error accumulation
            if (!limited(calculateCurrentTime() + 0.001 * m_playbackRate)) {
                // The current time became unlimited, eg. due to a backwards
                // seek of the timeline.
                newCurrentTime = calculateCurrentTime();
            } else if (!limited(m_holdTime)) {
                // The hold time became unlimited, eg. due to the effect
                // becoming longer.
                newCurrentTime = clampTo<double>(calculateCurrentTime(), 0, effectEnd());
            }
        }
        setCurrentTimeInternal(newCurrentTime, reason);
    } else if (limited(calculateCurrentTime())) {
        m_held = true;
        m_holdTime = m_playbackRate < 0 ? 0 : effectEnd();
    }
}