2014-08-10 07:06:44 +00:00
|
|
|
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "AnimationPlayer.h"
|
2014-08-30 06:11:57 +00:00
|
|
|
#include "AnimationUtils.h"
|
2014-08-10 07:06:44 +00:00
|
|
|
#include "mozilla/dom/AnimationPlayerBinding.h"
|
2014-11-17 04:45:59 +00:00
|
|
|
#include "AnimationCommon.h" // For AnimationPlayerCollection,
|
|
|
|
// CommonAnimationManager
|
2014-11-17 04:45:58 +00:00
|
|
|
#include "nsIDocument.h" // For nsIDocument
|
2014-11-17 04:45:58 +00:00
|
|
|
#include "nsIPresShell.h" // For nsIPresShell
|
2014-10-20 04:55:43 +00:00
|
|
|
#include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336)
|
2014-12-17 23:42:41 +00:00
|
|
|
#include "PendingPlayerTracker.h" // For PendingPlayerTracker
|
2014-08-10 07:06:44 +00:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2014-12-17 23:42:40 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationPlayer, mTimeline,
|
|
|
|
mSource, mReady)
|
2014-12-17 23:42:40 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationPlayer)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationPlayer)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationPlayer)
|
|
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_END
|
2014-08-10 07:06:44 +00:00
|
|
|
|
|
|
|
JSObject*
|
|
|
|
AnimationPlayer::WrapObject(JSContext* aCx)
|
|
|
|
{
|
|
|
|
return dom::AnimationPlayerBinding::Wrap(aCx, this);
|
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:45 +00:00
|
|
|
Nullable<TimeDuration>
|
2014-08-30 06:11:56 +00:00
|
|
|
AnimationPlayer::GetCurrentTime() const
|
2014-08-10 07:06:44 +00:00
|
|
|
{
|
2014-10-20 04:55:45 +00:00
|
|
|
Nullable<TimeDuration> result;
|
|
|
|
if (!mHoldTime.IsNull()) {
|
|
|
|
result = mHoldTime;
|
2014-12-04 20:13:38 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mStartTime.IsNull()) {
|
2014-10-20 04:55:45 +00:00
|
|
|
Nullable<TimeDuration> timelineTime = mTimeline->GetCurrentTime();
|
2014-12-04 20:13:38 +00:00
|
|
|
if (!timelineTime.IsNull()) {
|
2014-10-20 04:55:45 +00:00
|
|
|
result.SetValue(timelineTime.Value() - mStartTime.Value());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
2014-08-10 07:06:44 +00:00
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:45 +00:00
|
|
|
AnimationPlayState
|
|
|
|
AnimationPlayer::PlayState() const
|
|
|
|
{
|
2014-12-17 23:42:41 +00:00
|
|
|
if (mIsPending) {
|
|
|
|
return AnimationPlayState::Pending;
|
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:45 +00:00
|
|
|
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
2014-10-20 04:55:45 +00:00
|
|
|
if (currentTime.IsNull()) {
|
|
|
|
return AnimationPlayState::Idle;
|
|
|
|
}
|
|
|
|
|
2014-12-04 16:28:37 +00:00
|
|
|
if (mStartTime.IsNull()) {
|
2014-10-20 04:55:45 +00:00
|
|
|
return AnimationPlayState::Paused;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentTime.Value() >= SourceContentEnd()) {
|
|
|
|
return AnimationPlayState::Finished;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AnimationPlayState::Running;
|
|
|
|
}
|
|
|
|
|
2014-12-17 23:42:40 +00:00
|
|
|
Promise*
|
|
|
|
AnimationPlayer::GetReady(ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
// Lazily create the ready promise if it doesn't exist
|
|
|
|
if (!mReady) {
|
|
|
|
nsIGlobalObject* global = mTimeline->GetParentObject();
|
|
|
|
if (global) {
|
|
|
|
mReady = Promise::Create(global, aRv);
|
2014-12-17 23:42:41 +00:00
|
|
|
if (mReady && PlayState() != AnimationPlayState::Pending) {
|
2014-12-17 23:42:40 +00:00
|
|
|
mReady->MaybeResolve(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!mReady) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return mReady;
|
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:43 +00:00
|
|
|
void
|
2014-11-17 04:46:01 +00:00
|
|
|
AnimationPlayer::Play()
|
2014-10-20 04:55:43 +00:00
|
|
|
{
|
2014-11-17 04:46:01 +00:00
|
|
|
DoPlay();
|
|
|
|
PostUpdate();
|
2014-10-20 04:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-17 04:46:01 +00:00
|
|
|
AnimationPlayer::Pause()
|
2014-10-20 04:55:43 +00:00
|
|
|
{
|
2014-11-17 04:46:01 +00:00
|
|
|
DoPause();
|
|
|
|
PostUpdate();
|
2014-10-20 04:55:43 +00:00
|
|
|
}
|
|
|
|
|
2014-12-04 16:28:38 +00:00
|
|
|
Nullable<double>
|
|
|
|
AnimationPlayer::GetStartTimeAsDouble() const
|
|
|
|
{
|
|
|
|
return AnimationUtils::TimeDurationToDouble(mStartTime);
|
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:45 +00:00
|
|
|
Nullable<double>
|
|
|
|
AnimationPlayer::GetCurrentTimeAsDouble() const
|
|
|
|
{
|
|
|
|
return AnimationUtils::TimeDurationToDouble(GetCurrentTime());
|
|
|
|
}
|
|
|
|
|
2014-08-10 07:06:47 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::SetSource(Animation* aSource)
|
|
|
|
{
|
2014-08-10 07:06:48 +00:00
|
|
|
if (mSource) {
|
|
|
|
mSource->SetParentTime(Nullable<TimeDuration>());
|
|
|
|
}
|
2014-08-10 07:06:47 +00:00
|
|
|
mSource = aSource;
|
2014-08-10 07:06:48 +00:00
|
|
|
if (mSource) {
|
2014-10-20 04:55:45 +00:00
|
|
|
mSource->SetParentTime(GetCurrentTime());
|
2014-08-10 07:06:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AnimationPlayer::Tick()
|
|
|
|
{
|
2014-12-22 00:35:42 +00:00
|
|
|
UpdateSourceContent();
|
2014-08-10 07:06:47 +00:00
|
|
|
}
|
|
|
|
|
2014-12-04 16:28:38 +00:00
|
|
|
void
|
2014-12-17 23:42:41 +00:00
|
|
|
AnimationPlayer::StartNow()
|
2014-12-04 16:28:38 +00:00
|
|
|
{
|
2014-12-26 02:54:43 +00:00
|
|
|
// Currently we only expect this method to be called when we are in the
|
|
|
|
// middle of initiating/resuming playback so we should have an unresolved
|
|
|
|
// start time to update and a fixed current time to seek to.
|
|
|
|
MOZ_ASSERT(mStartTime.IsNull() && !mHoldTime.IsNull(),
|
|
|
|
"Resolving the start time but we don't appear to be waiting"
|
|
|
|
" to begin playback");
|
2014-12-04 16:28:38 +00:00
|
|
|
|
|
|
|
Nullable<TimeDuration> readyTime = mTimeline->GetCurrentTime();
|
2014-12-26 02:54:43 +00:00
|
|
|
// Bug 1096776: Once we support disappearing or inactive timelines we
|
|
|
|
// will need special handling here.
|
2014-12-04 16:28:38 +00:00
|
|
|
MOZ_ASSERT(!readyTime.IsNull(), "Missing or inactive timeline");
|
|
|
|
mStartTime.SetValue(readyTime.Value() - mHoldTime.Value());
|
|
|
|
mHoldTime.SetNull();
|
2014-12-17 23:42:40 +00:00
|
|
|
|
|
|
|
if (mReady) {
|
|
|
|
mReady->MaybeResolve(this);
|
|
|
|
}
|
2014-12-04 16:28:38 +00:00
|
|
|
}
|
|
|
|
|
2014-12-17 23:42:41 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::Cancel()
|
|
|
|
{
|
|
|
|
if (mIsPending) {
|
|
|
|
CancelPendingPlay();
|
|
|
|
if (mReady) {
|
|
|
|
mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mHoldTime.SetNull();
|
|
|
|
mStartTime.SetNull();
|
|
|
|
}
|
|
|
|
|
2014-08-10 07:06:44 +00:00
|
|
|
bool
|
|
|
|
AnimationPlayer::IsRunning() const
|
|
|
|
{
|
2014-08-10 07:06:51 +00:00
|
|
|
if (IsPaused() || !GetSource() || GetSource()->IsFinishedTransition()) {
|
2014-08-10 07:06:44 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-08-10 07:06:50 +00:00
|
|
|
ComputedTiming computedTiming = GetSource()->GetComputedTiming();
|
2014-08-10 07:06:44 +00:00
|
|
|
return computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
|
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:45 +00:00
|
|
|
bool
|
|
|
|
AnimationPlayer::CanThrottle() const
|
|
|
|
{
|
|
|
|
if (!mSource ||
|
|
|
|
mSource->IsFinishedTransition() ||
|
|
|
|
mSource->Properties().IsEmpty()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mIsRunningOnCompositor) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PlayState() != AnimationPlayState::Finished) {
|
|
|
|
// Unfinished animations can be throttled.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The animation has finished but, if this is the first sample since
|
|
|
|
// finishing, we need an unthrottled sample so we can apply the correct
|
|
|
|
// end-of-animation behavior on the main thread (either removing the
|
|
|
|
// animation style or applying the fill mode).
|
Bug 1078122 part 6 - Store the previous finished state; r=dholbert
AnimationPlayer::CanThrottle determines if an animation player has just finished
by inspecting the value of mLastNotification. This is problematic for two
reasons:
1. mLastNotification is intended to be used for events (as the XXX comment
notes)
2. mLastNotification is specific to CSS Animations and should be moved to
CSSAnimationPlayer.
To address this, this patch adds an extra member mIsPreviousStateFinished. The
Web Animations spec already defines animation players as having such a member:
http://w3c.github.io/web-animations/#previous-finished-state
We set it to true when we calculate the style for an animation that has
finished. This differs slightly from the code it is replacing as explained
below.
In the case of CSS Animations we perform the following sequence of steps on each
sample.
1. EnsureStyleRuleFor (calls CanThrottle, and maybe ComposeStyle)
2. GetEventsForCurrentTime
In the existing code, we update mLastNotification in (2) which happens on every
sample, even throttled samples.
In this patch, however, we update mIsPreviousStateFinished in (1) during the
ComposeStyle step which only happens for unthrottled samples. So, as of this
patch, in CanThrottle, we ask "have we newly entered the finished state since
the last *unthrottled* sample?", whereas previously we simply looked for
a change since the last sample, throttled or not. However, if the answer to the
question is "yes", then we'll run an unthrottled sample and update
mIsPreviousStateFinished so these should be functionally equivalent.
Another subtle difference is that this patch looks at the player's finished
state rather than the animation phase of its source content, and these will
produce different results in the case where the player is paused. However, since
paused animations are not run on the compositor, this should not matter.
In the case of CSS Transitions, AnimationPlayer::CanThrottle() is not currently
used and so mIsPreviousStateFinished is irrelevant.
Ultimately, both the existing and the new code is somewhat fragile but hopefully
this will be addressed by:
* Replacing mIsPreviousStateFinished with inspecting whether the finished
promise is settled (bug 1074630),
* Merging more of the code in nsAnimationManager and nsTransitionManager and
applying a unified approach to sampling that better accommodates these
considerations.
2014-10-20 04:55:47 +00:00
|
|
|
return mIsPreviousStateFinished;
|
2014-10-20 04:55:45 +00:00
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:46 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
|
|
|
nsCSSPropertySet& aSetProperties,
|
|
|
|
bool& aNeedsRefreshes)
|
|
|
|
{
|
|
|
|
if (!mSource || mSource->IsFinishedTransition()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Bug 1078122 part 6 - Store the previous finished state; r=dholbert
AnimationPlayer::CanThrottle determines if an animation player has just finished
by inspecting the value of mLastNotification. This is problematic for two
reasons:
1. mLastNotification is intended to be used for events (as the XXX comment
notes)
2. mLastNotification is specific to CSS Animations and should be moved to
CSSAnimationPlayer.
To address this, this patch adds an extra member mIsPreviousStateFinished. The
Web Animations spec already defines animation players as having such a member:
http://w3c.github.io/web-animations/#previous-finished-state
We set it to true when we calculate the style for an animation that has
finished. This differs slightly from the code it is replacing as explained
below.
In the case of CSS Animations we perform the following sequence of steps on each
sample.
1. EnsureStyleRuleFor (calls CanThrottle, and maybe ComposeStyle)
2. GetEventsForCurrentTime
In the existing code, we update mLastNotification in (2) which happens on every
sample, even throttled samples.
In this patch, however, we update mIsPreviousStateFinished in (1) during the
ComposeStyle step which only happens for unthrottled samples. So, as of this
patch, in CanThrottle, we ask "have we newly entered the finished state since
the last *unthrottled* sample?", whereas previously we simply looked for
a change since the last sample, throttled or not. However, if the answer to the
question is "yes", then we'll run an unthrottled sample and update
mIsPreviousStateFinished so these should be functionally equivalent.
Another subtle difference is that this patch looks at the player's finished
state rather than the animation phase of its source content, and these will
produce different results in the case where the player is paused. However, since
paused animations are not run on the compositor, this should not matter.
In the case of CSS Transitions, AnimationPlayer::CanThrottle() is not currently
used and so mIsPreviousStateFinished is irrelevant.
Ultimately, both the existing and the new code is somewhat fragile but hopefully
this will be addressed by:
* Replacing mIsPreviousStateFinished with inspecting whether the finished
promise is settled (bug 1074630),
* Merging more of the code in nsAnimationManager and nsTransitionManager and
applying a unified approach to sampling that better accommodates these
considerations.
2014-10-20 04:55:47 +00:00
|
|
|
AnimationPlayState playState = PlayState();
|
2014-12-17 23:42:41 +00:00
|
|
|
if (playState == AnimationPlayState::Running ||
|
|
|
|
playState == AnimationPlayState::Pending) {
|
2014-10-20 04:55:46 +00:00
|
|
|
aNeedsRefreshes = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
mSource->ComposeStyle(aStyleRule, aSetProperties);
|
Bug 1078122 part 6 - Store the previous finished state; r=dholbert
AnimationPlayer::CanThrottle determines if an animation player has just finished
by inspecting the value of mLastNotification. This is problematic for two
reasons:
1. mLastNotification is intended to be used for events (as the XXX comment
notes)
2. mLastNotification is specific to CSS Animations and should be moved to
CSSAnimationPlayer.
To address this, this patch adds an extra member mIsPreviousStateFinished. The
Web Animations spec already defines animation players as having such a member:
http://w3c.github.io/web-animations/#previous-finished-state
We set it to true when we calculate the style for an animation that has
finished. This differs slightly from the code it is replacing as explained
below.
In the case of CSS Animations we perform the following sequence of steps on each
sample.
1. EnsureStyleRuleFor (calls CanThrottle, and maybe ComposeStyle)
2. GetEventsForCurrentTime
In the existing code, we update mLastNotification in (2) which happens on every
sample, even throttled samples.
In this patch, however, we update mIsPreviousStateFinished in (1) during the
ComposeStyle step which only happens for unthrottled samples. So, as of this
patch, in CanThrottle, we ask "have we newly entered the finished state since
the last *unthrottled* sample?", whereas previously we simply looked for
a change since the last sample, throttled or not. However, if the answer to the
question is "yes", then we'll run an unthrottled sample and update
mIsPreviousStateFinished so these should be functionally equivalent.
Another subtle difference is that this patch looks at the player's finished
state rather than the animation phase of its source content, and these will
produce different results in the case where the player is paused. However, since
paused animations are not run on the compositor, this should not matter.
In the case of CSS Transitions, AnimationPlayer::CanThrottle() is not currently
used and so mIsPreviousStateFinished is irrelevant.
Ultimately, both the existing and the new code is somewhat fragile but hopefully
this will be addressed by:
* Replacing mIsPreviousStateFinished with inspecting whether the finished
promise is settled (bug 1074630),
* Merging more of the code in nsAnimationManager and nsTransitionManager and
applying a unified approach to sampling that better accommodates these
considerations.
2014-10-20 04:55:47 +00:00
|
|
|
|
|
|
|
mIsPreviousStateFinished = (playState == AnimationPlayState::Finished);
|
2014-10-20 04:55:46 +00:00
|
|
|
}
|
|
|
|
|
2014-11-17 04:46:01 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::DoPlay()
|
|
|
|
{
|
2014-12-04 16:28:37 +00:00
|
|
|
// FIXME: When we implement finishing behavior (bug 1074630) we will
|
|
|
|
// need to pass a flag so that when we start playing due to a change in
|
|
|
|
// animation-play-state we *don't* trigger finishing behavior.
|
|
|
|
|
|
|
|
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
|
|
|
if (currentTime.IsNull()) {
|
|
|
|
mHoldTime.SetValue(TimeDuration(0));
|
|
|
|
} else if (mHoldTime.IsNull()) {
|
|
|
|
// If the hold time is null, we are already playing normally
|
2014-11-17 04:46:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-17 23:42:41 +00:00
|
|
|
// Clear ready promise. We'll create a new one lazily.
|
|
|
|
mReady = nullptr;
|
2014-12-17 23:42:40 +00:00
|
|
|
|
2014-12-26 02:54:43 +00:00
|
|
|
StartNow();
|
2014-11-17 04:46:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AnimationPlayer::DoPause()
|
|
|
|
{
|
2014-12-17 23:42:41 +00:00
|
|
|
if (mIsPending) {
|
2014-12-17 23:42:41 +00:00
|
|
|
CancelPendingPlay();
|
2014-12-17 23:42:41 +00:00
|
|
|
// Resolve the ready promise since we currently only use it for
|
|
|
|
// players that are waiting to play. Later (in bug 1109390), we will
|
|
|
|
// use this for players waiting to pause as well and then we won't
|
|
|
|
// want to resolve it just yet.
|
|
|
|
if (mReady) {
|
|
|
|
mReady->MaybeResolve(this);
|
|
|
|
}
|
2014-11-17 04:46:01 +00:00
|
|
|
}
|
2014-12-17 23:42:41 +00:00
|
|
|
|
2014-12-04 16:28:37 +00:00
|
|
|
// Mark this as no longer running on the compositor so that next time
|
|
|
|
// we update animations we won't throttle them and will have a chance
|
|
|
|
// to remove the animation from any layer it might be on.
|
2014-11-17 04:46:01 +00:00
|
|
|
mIsRunningOnCompositor = false;
|
|
|
|
|
2014-12-17 23:42:41 +00:00
|
|
|
// Bug 1109390 - check for null result here and go to pending state
|
2014-11-17 04:46:01 +00:00
|
|
|
mHoldTime = GetCurrentTime();
|
|
|
|
mStartTime.SetNull();
|
|
|
|
}
|
|
|
|
|
2014-12-22 00:35:42 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::UpdateSourceContent()
|
|
|
|
{
|
|
|
|
if (mSource) {
|
|
|
|
mSource->SetParentTime(GetCurrentTime());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:43 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::FlushStyle() const
|
|
|
|
{
|
2014-11-17 04:45:58 +00:00
|
|
|
nsIDocument* doc = GetRenderedDocument();
|
2014-10-20 04:55:47 +00:00
|
|
|
if (doc) {
|
|
|
|
doc->FlushPendingNotifications(Flush_Style);
|
2014-10-20 04:55:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-17 04:45:59 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::PostUpdate()
|
|
|
|
{
|
|
|
|
AnimationPlayerCollection* collection = GetCollection();
|
|
|
|
if (collection) {
|
|
|
|
collection->NotifyPlayerUpdated();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-17 23:42:41 +00:00
|
|
|
void
|
|
|
|
AnimationPlayer::CancelPendingPlay()
|
|
|
|
{
|
|
|
|
if (!mIsPending) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDocument* doc = GetRenderedDocument();
|
|
|
|
if (doc) {
|
|
|
|
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
|
|
|
|
if (tracker) {
|
|
|
|
tracker->RemovePlayPending(*this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mIsPending = false;
|
|
|
|
}
|
|
|
|
|
2014-10-20 04:55:45 +00:00
|
|
|
StickyTimeDuration
|
|
|
|
AnimationPlayer::SourceContentEnd() const
|
|
|
|
{
|
|
|
|
if (!mSource) {
|
|
|
|
return StickyTimeDuration(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return mSource->Timing().mDelay
|
|
|
|
+ mSource->GetComputedTiming().mActiveDuration;
|
|
|
|
}
|
|
|
|
|
2014-11-17 04:45:58 +00:00
|
|
|
nsIDocument*
|
|
|
|
AnimationPlayer::GetRenderedDocument() const
|
|
|
|
{
|
|
|
|
if (!mSource) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Element* targetElement;
|
|
|
|
nsCSSPseudoElements::Type pseudoType;
|
|
|
|
mSource->GetTarget(targetElement, pseudoType);
|
|
|
|
if (!targetElement) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return targetElement->GetComposedDoc();
|
|
|
|
}
|
|
|
|
|
2014-11-17 04:45:58 +00:00
|
|
|
nsPresContext*
|
|
|
|
AnimationPlayer::GetPresContext() const
|
|
|
|
{
|
|
|
|
nsIDocument* doc = GetRenderedDocument();
|
|
|
|
if (!doc) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
nsIPresShell* shell = doc->GetShell();
|
|
|
|
if (!shell) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return shell->GetPresContext();
|
|
|
|
}
|
|
|
|
|
2014-11-17 04:45:59 +00:00
|
|
|
AnimationPlayerCollection*
|
|
|
|
AnimationPlayer::GetCollection() const
|
|
|
|
{
|
|
|
|
css::CommonAnimationManager* manager = GetAnimationManager();
|
|
|
|
if (!manager) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(mSource, "A player with an animation manager must have a source");
|
|
|
|
|
|
|
|
Element* targetElement;
|
|
|
|
nsCSSPseudoElements::Type targetPseudoType;
|
|
|
|
mSource->GetTarget(targetElement, targetPseudoType);
|
|
|
|
MOZ_ASSERT(targetElement,
|
|
|
|
"A player with an animation manager must have a target");
|
|
|
|
|
|
|
|
return manager->GetAnimationPlayers(targetElement, targetPseudoType, false);
|
|
|
|
}
|
|
|
|
|
2014-08-10 07:06:44 +00:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|