/work/obj-fuzz/dist/include/mozilla/dom/Animation.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef mozilla_dom_Animation_h |
8 | | #define mozilla_dom_Animation_h |
9 | | |
10 | | #include "nsWrapperCache.h" |
11 | | #include "nsCycleCollectionParticipant.h" |
12 | | #include "mozilla/AnimationPerformanceWarning.h" |
13 | | #include "mozilla/Attributes.h" |
14 | | #include "mozilla/CycleCollectedJSContext.h" |
15 | | #include "mozilla/DOMEventTargetHelper.h" |
16 | | #include "mozilla/EffectCompositor.h" // For EffectCompositor::CascadeLevel |
17 | | #include "mozilla/LinkedList.h" |
18 | | #include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration |
19 | | #include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState |
20 | | #include "mozilla/dom/AnimationEffect.h" |
21 | | #include "mozilla/dom/AnimationTimeline.h" |
22 | | #include "mozilla/dom/Promise.h" |
23 | | #include "nsCSSPropertyID.h" |
24 | | #include "nsIGlobalObject.h" |
25 | | |
26 | | // X11 has a #define for CurrentTime. |
27 | | #ifdef CurrentTime |
28 | | #undef CurrentTime |
29 | | #endif |
30 | | |
31 | | // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to |
32 | | // GetTickCount(). |
33 | | #ifdef GetCurrentTime |
34 | | #undef GetCurrentTime |
35 | | #endif |
36 | | |
37 | | struct JSContext; |
38 | | class nsCSSPropertyIDSet; |
39 | | class nsIDocument; |
40 | | class nsIFrame; |
41 | | |
42 | | namespace mozilla { |
43 | | |
44 | | struct AnimationRule; |
45 | | |
46 | | namespace dom { |
47 | | |
48 | | class AsyncFinishNotification; |
49 | | class CSSAnimation; |
50 | | class CSSTransition; |
51 | | |
52 | | class Animation |
53 | | : public DOMEventTargetHelper |
54 | | , public LinkedListElement<Animation> |
55 | | { |
56 | | protected: |
57 | 0 | virtual ~Animation() {} |
58 | | |
59 | | public: |
60 | | explicit Animation(nsIGlobalObject* aGlobal) |
61 | | : DOMEventTargetHelper(aGlobal) |
62 | | , mPlaybackRate(1.0) |
63 | | , mAnimationIndex(sNextAnimationIndex++) |
64 | | , mCachedChildIndex(-1) |
65 | | , mPendingState(PendingState::NotPending) |
66 | | , mFinishedAtLastComposeStyle(false) |
67 | | , mIsRelevant(false) |
68 | | , mFinishedIsResolved(false) |
69 | | , mSyncWithGeometricAnimations(false) |
70 | 0 | { |
71 | 0 | } |
72 | | |
73 | | NS_DECL_ISUPPORTS_INHERITED |
74 | | NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Animation, |
75 | | DOMEventTargetHelper) |
76 | | |
77 | 0 | nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); } |
78 | | virtual JSObject* WrapObject(JSContext* aCx, |
79 | | JS::Handle<JSObject*> aGivenProto) override; |
80 | | |
81 | 0 | virtual CSSAnimation* AsCSSAnimation() { return nullptr; } |
82 | 0 | virtual const CSSAnimation* AsCSSAnimation() const { return nullptr; } |
83 | 0 | virtual CSSTransition* AsCSSTransition() { return nullptr; } |
84 | 0 | virtual const CSSTransition* AsCSSTransition() const { return nullptr; } |
85 | | |
86 | | /** |
87 | | * Flag to pass to Play to indicate whether or not it should automatically |
88 | | * rewind the current time to the start point if the animation is finished. |
89 | | * For regular calls to play() from script we should do this, but when a CSS |
90 | | * animation's animation-play-state changes we shouldn't rewind the animation. |
91 | | */ |
92 | | enum class LimitBehavior { |
93 | | AutoRewind, |
94 | | Continue |
95 | | }; |
96 | | |
97 | | // Animation interface methods |
98 | | static already_AddRefed<Animation> |
99 | | Constructor(const GlobalObject& aGlobal, |
100 | | AnimationEffect* aEffect, |
101 | | const Optional<AnimationTimeline*>& aTimeline, |
102 | | ErrorResult& aRv); |
103 | 0 | void GetId(nsAString& aResult) const { aResult = mId; } |
104 | | void SetId(const nsAString& aId); |
105 | 0 | AnimationEffect* GetEffect() const { return mEffect; } |
106 | | void SetEffect(AnimationEffect* aEffect); |
107 | 0 | AnimationTimeline* GetTimeline() const { return mTimeline; } |
108 | | void SetTimeline(AnimationTimeline* aTimeline); |
109 | 0 | Nullable<TimeDuration> GetStartTime() const { return mStartTime; } |
110 | | void SetStartTime(const Nullable<TimeDuration>& aNewStartTime); |
111 | 0 | Nullable<TimeDuration> GetCurrentTime() const { |
112 | 0 | return GetCurrentTimeForHoldTime(mHoldTime); |
113 | 0 | } |
114 | | void SetCurrentTime(const TimeDuration& aNewCurrentTime); |
115 | 0 | double PlaybackRate() const { return mPlaybackRate; } |
116 | | void SetPlaybackRate(double aPlaybackRate); |
117 | | AnimationPlayState PlayState() const; |
118 | 0 | bool Pending() const { return mPendingState != PendingState::NotPending; } |
119 | | virtual Promise* GetReady(ErrorResult& aRv); |
120 | | Promise* GetFinished(ErrorResult& aRv); |
121 | | void Cancel(); |
122 | | void Finish(ErrorResult& aRv); |
123 | | virtual void Play(ErrorResult& aRv, LimitBehavior aLimitBehavior); |
124 | | virtual void Pause(ErrorResult& aRv); |
125 | | void Reverse(ErrorResult& aRv); |
126 | | void UpdatePlaybackRate(double aPlaybackRate); |
127 | | bool IsRunningOnCompositor() const; |
128 | | IMPL_EVENT_HANDLER(finish); |
129 | | IMPL_EVENT_HANDLER(cancel); |
130 | | |
131 | | // Wrapper functions for Animation DOM methods when called |
132 | | // from script. |
133 | | // |
134 | | // We often use the same methods internally and from script but when called |
135 | | // from script we (or one of our subclasses) perform extra steps such as |
136 | | // flushing style or converting the return type. |
137 | | Nullable<double> GetStartTimeAsDouble() const; |
138 | | void SetStartTimeAsDouble(const Nullable<double>& aStartTime); |
139 | | Nullable<double> GetCurrentTimeAsDouble() const; |
140 | | void SetCurrentTimeAsDouble(const Nullable<double>& aCurrentTime, |
141 | | ErrorResult& aRv); |
142 | 0 | virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); } |
143 | 0 | virtual bool PendingFromJS() const { return Pending(); } |
144 | | virtual void PlayFromJS(ErrorResult& aRv) |
145 | 0 | { |
146 | 0 | Play(aRv, LimitBehavior::AutoRewind); |
147 | 0 | } |
148 | | /** |
149 | | * PauseFromJS is currently only here for symmetry with PlayFromJS but |
150 | | * in future we will likely have to flush style in |
151 | | * CSSAnimation::PauseFromJS so we leave it for now. |
152 | | */ |
153 | 0 | void PauseFromJS(ErrorResult& aRv) { Pause(aRv); } |
154 | | |
155 | | // Wrapper functions for Animation DOM methods when called from style. |
156 | | |
157 | 0 | virtual void CancelFromStyle() { CancelNoUpdate(); } |
158 | | void SetTimelineNoUpdate(AnimationTimeline* aTimeline); |
159 | | void SetEffectNoUpdate(AnimationEffect* aEffect); |
160 | | |
161 | | virtual void Tick(); |
162 | | bool NeedsTicks() const |
163 | 0 | { |
164 | 0 | return Pending() || PlayState() == AnimationPlayState::Running; |
165 | 0 | } |
166 | | |
167 | | /** |
168 | | * Set the time to use for starting or pausing a pending animation. |
169 | | * |
170 | | * Typically, when an animation is played, it does not start immediately but |
171 | | * is added to a table of pending animations on the document of its effect. |
172 | | * In the meantime it sets its hold time to the time from which playback |
173 | | * should begin. |
174 | | * |
175 | | * When the document finishes painting, any pending animations in its table |
176 | | * are marked as being ready to start by calling TriggerOnNextTick. |
177 | | * The moment when the paint completed is also recorded, converted to a |
178 | | * timeline time, and passed to StartOnTick. This is so that when these |
179 | | * animations do start, they can be timed from the point when painting |
180 | | * completed. |
181 | | * |
182 | | * After calling TriggerOnNextTick, animations remain in the pending state |
183 | | * until the next refresh driver tick. At that time they transition out of |
184 | | * the pending state using the time passed to TriggerOnNextTick as the |
185 | | * effective time at which they resumed. |
186 | | * |
187 | | * This approach means that any setup time required for performing the |
188 | | * initial paint of an animation such as layerization is not deducted from |
189 | | * the running time of the animation. Without this we can easily drop the |
190 | | * first few frames of an animation, or, on slower devices, the whole |
191 | | * animation. |
192 | | * |
193 | | * Furthermore: |
194 | | * |
195 | | * - Starting the animation immediately when painting finishes is problematic |
196 | | * because the start time of the animation will be ahead of its timeline |
197 | | * (since the timeline time is based on the refresh driver time). |
198 | | * That's a problem because the animation is playing but its timing |
199 | | * suggests it starts in the future. We could update the timeline to match |
200 | | * the start time of the animation but then we'd also have to update the |
201 | | * timing and style of all animations connected to that timeline or else be |
202 | | * stuck in an inconsistent state until the next refresh driver tick. |
203 | | * |
204 | | * - If we simply use the refresh driver time on its next tick, the lag |
205 | | * between triggering an animation and its effective start is unacceptably |
206 | | * long. |
207 | | * |
208 | | * For pausing, we apply the same asynchronous approach. This is so that we |
209 | | * synchronize with animations that are running on the compositor. Otherwise |
210 | | * if the main thread lags behind the compositor there will be a noticeable |
211 | | * jump backwards when the main thread takes over. Even though main thread |
212 | | * animations could be paused immediately, we do it asynchronously for |
213 | | * consistency and so that animations paused together end up in step. |
214 | | * |
215 | | * Note that the caller of this method is responsible for removing the |
216 | | * animation from any PendingAnimationTracker it may have been added to. |
217 | | */ |
218 | | void TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime); |
219 | | /** |
220 | | * Testing only: Start or pause a pending animation using the current |
221 | | * timeline time. This is used to support existing tests that expect |
222 | | * animations to begin immediately. Ideally we would rewrite the those tests |
223 | | * and get rid of this method, but there are a lot of them. |
224 | | * |
225 | | * As with TriggerOnNextTick, the caller of this method is responsible for |
226 | | * removing the animation from any PendingAnimationTracker it may have been |
227 | | * added to. |
228 | | */ |
229 | | void TriggerNow(); |
230 | | /** |
231 | | * When TriggerOnNextTick is called, we store the ready time but we don't |
232 | | * apply it until the next tick. In the meantime, GetStartTime() will return |
233 | | * null. |
234 | | * |
235 | | * However, if we build layer animations again before the next tick, we |
236 | | * should initialize them with the start time that GetStartTime() will return |
237 | | * on the next tick. |
238 | | * |
239 | | * If we were to simply set the start time of layer animations to null, their |
240 | | * start time would be updated to the current wallclock time when rendering |
241 | | * finishes, thus making them out of sync with the start time stored here. |
242 | | * This, in turn, will make the animation jump backwards when we build |
243 | | * animations on the next tick and apply the start time stored here. |
244 | | * |
245 | | * This method returns the start time, if resolved. Otherwise, if we have |
246 | | * a pending ready time, it returns the corresponding start time. If neither |
247 | | * of those are available, it returns null. |
248 | | */ |
249 | | Nullable<TimeDuration> GetCurrentOrPendingStartTime() const; |
250 | | |
251 | | /** |
252 | | * As with the start time, we should use the pending playback rate when |
253 | | * producing layer animations. |
254 | | */ |
255 | | double CurrentOrPendingPlaybackRate() const |
256 | 0 | { |
257 | 0 | return mPendingPlaybackRate.valueOr(mPlaybackRate); |
258 | 0 | } |
259 | 0 | bool HasPendingPlaybackRate() const { return mPendingPlaybackRate.isSome(); } |
260 | | |
261 | | /** |
262 | | * The following relationship from the definition of the 'current time' is |
263 | | * re-used in many algorithms so we extract it here into a static method that |
264 | | * can be re-used: |
265 | | * |
266 | | * current time = (timeline time - start time) * playback rate |
267 | | * |
268 | | * As per https://drafts.csswg.org/web-animations-1/#current-time |
269 | | */ |
270 | | static TimeDuration CurrentTimeFromTimelineTime( |
271 | | const TimeDuration& aTimelineTime, |
272 | | const TimeDuration& aStartTime, |
273 | | float aPlaybackRate) |
274 | 0 | { |
275 | 0 | return (aTimelineTime - aStartTime).MultDouble(aPlaybackRate); |
276 | 0 | } |
277 | | |
278 | | /** |
279 | | * As with calculating the current time, we often need to calculate a start |
280 | | * time from a current time. The following method simply inverts the current |
281 | | * time relationship. |
282 | | * |
283 | | * In each case where this is used, the desired behavior for playbackRate == |
284 | | * 0 is to return the specified timeline time (often referred to as the ready |
285 | | * time). |
286 | | */ |
287 | | static TimeDuration StartTimeFromTimelineTime( |
288 | | const TimeDuration& aTimelineTime, |
289 | | const TimeDuration& aCurrentTime, |
290 | | float aPlaybackRate) |
291 | 0 | { |
292 | 0 | TimeDuration result = aTimelineTime; |
293 | 0 | if (aPlaybackRate == 0) { |
294 | 0 | return result; |
295 | 0 | } |
296 | 0 | |
297 | 0 | result -= aCurrentTime.MultDouble(1.0 / aPlaybackRate); |
298 | 0 | return result; |
299 | 0 | } |
300 | | |
301 | | /** |
302 | | * Converts a time in the timescale of this Animation's currentTime, to a |
303 | | * TimeStamp. Returns a null TimeStamp if the conversion cannot be performed |
304 | | * because of the current state of this Animation (e.g. it has no timeline, a |
305 | | * zero playbackRate, an unresolved start time etc.) or the value of the time |
306 | | * passed-in (e.g. an infinite time). |
307 | | */ |
308 | | TimeStamp AnimationTimeToTimeStamp(const StickyTimeDuration& aTime) const; |
309 | | |
310 | | // Converts an AnimationEvent's elapsedTime value to an equivalent TimeStamp |
311 | | // that can be used to sort events by when they occurred. |
312 | | TimeStamp ElapsedTimeToTimeStamp(const StickyTimeDuration& aElapsedTime) const; |
313 | | |
314 | | bool IsPausedOrPausing() const |
315 | 0 | { |
316 | 0 | return PlayState() == AnimationPlayState::Paused; |
317 | 0 | } |
318 | | |
319 | | bool HasCurrentEffect() const |
320 | 0 | { |
321 | 0 | return GetEffect() && GetEffect()->IsCurrent(); |
322 | 0 | } |
323 | | bool IsInEffect() const |
324 | 0 | { |
325 | 0 | return GetEffect() && GetEffect()->IsInEffect(); |
326 | 0 | } |
327 | | |
328 | | bool IsPlaying() const |
329 | 0 | { |
330 | 0 | return mPlaybackRate != 0.0 && |
331 | 0 | mTimeline && |
332 | 0 | !mTimeline->GetCurrentTime().IsNull() && |
333 | 0 | PlayState() == AnimationPlayState::Running; |
334 | 0 | } |
335 | | |
336 | | bool ShouldBeSynchronizedWithMainThread( |
337 | | nsCSSPropertyID aProperty, |
338 | | const nsIFrame* aFrame, |
339 | | AnimationPerformanceWarning::Type& aPerformanceWarning) const; |
340 | | |
341 | 0 | bool IsRelevant() const { return mIsRelevant; } |
342 | | void UpdateRelevance(); |
343 | | |
344 | | /** |
345 | | * Returns true if this Animation has a lower composite order than aOther. |
346 | | */ |
347 | | bool HasLowerCompositeOrderThan(const Animation& aOther) const; |
348 | | |
349 | | /** |
350 | | * Returns the level at which the effect(s) associated with this Animation |
351 | | * are applied to the CSS cascade. |
352 | | */ |
353 | | virtual EffectCompositor::CascadeLevel CascadeLevel() const |
354 | 0 | { |
355 | 0 | return EffectCompositor::CascadeLevel::Animations; |
356 | 0 | } |
357 | | |
358 | | /** |
359 | | * Returns true if this animation does not currently need to update |
360 | | * style on the main thread (e.g. because it is empty, or is |
361 | | * running on the compositor). |
362 | | */ |
363 | | bool CanThrottle() const; |
364 | | |
365 | | /** |
366 | | * Updates various bits of state that we need to update as the result of |
367 | | * running ComposeStyle(). |
368 | | * See the comment of KeyframeEffect::WillComposeStyle for more detail. |
369 | | */ |
370 | | void WillComposeStyle(); |
371 | | |
372 | | /** |
373 | | * Updates |aComposeResult| with the animation values of this animation's |
374 | | * effect, if any. |
375 | | * Any properties contained in |aPropertiesToSkip| will not be added or |
376 | | * updated in |aComposeResult|. |
377 | | */ |
378 | | void ComposeStyle(RawServoAnimationValueMap& aComposeResult, |
379 | | const nsCSSPropertyIDSet& aPropertiesToSkip); |
380 | | |
381 | | void NotifyEffectTimingUpdated(); |
382 | | void NotifyGeometricAnimationsStartingThisFrame(); |
383 | | |
384 | | /** |
385 | | * Reschedule pending pause or pending play tasks when updating the target |
386 | | * effect. |
387 | | * |
388 | | * If we are pending, we will either be registered in the pending animation |
389 | | * tracker and have a null pending ready time, or, after our effect has been |
390 | | * painted, we will be removed from the tracker and assigned a pending ready |
391 | | * time. |
392 | | * |
393 | | * When the target effect is updated, we'll typically need to repaint so for |
394 | | * the latter case where we already have a pending ready time, clear it and put |
395 | | * ourselves back in the pending animation tracker. |
396 | | */ |
397 | | void ReschedulePendingTasks(); |
398 | | |
399 | | /** |
400 | | * Used by subclasses to synchronously queue a cancel event in situations |
401 | | * where the Animation may have been cancelled. |
402 | | * |
403 | | * We need to do this synchronously because after a CSS animation/transition |
404 | | * is canceled, it will be released by its owning element and may not still |
405 | | * exist when we would normally go to queue events on the next tick. |
406 | | */ |
407 | 0 | virtual void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) {}; |
408 | | |
409 | 0 | int32_t& CachedChildIndexRef() { return mCachedChildIndex; } |
410 | | |
411 | | protected: |
412 | | void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime); |
413 | | void CancelNoUpdate(); |
414 | | void PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior); |
415 | | void ResumeAt(const TimeDuration& aReadyTime); |
416 | | void PauseAt(const TimeDuration& aReadyTime); |
417 | | void FinishPendingAt(const TimeDuration& aReadyTime) |
418 | 0 | { |
419 | 0 | if (mPendingState == PendingState::PlayPending) { |
420 | 0 | ResumeAt(aReadyTime); |
421 | 0 | } else if (mPendingState == PendingState::PausePending) { |
422 | 0 | PauseAt(aReadyTime); |
423 | 0 | } else { |
424 | 0 | MOZ_ASSERT_UNREACHABLE("Can't finish pending if we're not in a pending state"); |
425 | 0 | } |
426 | 0 | } |
427 | | void ApplyPendingPlaybackRate() |
428 | 0 | { |
429 | 0 | if (mPendingPlaybackRate) { |
430 | 0 | mPlaybackRate = *mPendingPlaybackRate; |
431 | 0 | mPendingPlaybackRate.reset(); |
432 | 0 | } |
433 | 0 | } |
434 | | |
435 | | /** |
436 | | * Finishing behavior depends on if changes to timing occurred due |
437 | | * to a seek or regular playback. |
438 | | */ |
439 | | enum class SeekFlag { |
440 | | NoSeek, |
441 | | DidSeek |
442 | | }; |
443 | | |
444 | | enum class SyncNotifyFlag { |
445 | | Sync, |
446 | | Async |
447 | | }; |
448 | | |
449 | | virtual void UpdateTiming(SeekFlag aSeekFlag, |
450 | | SyncNotifyFlag aSyncNotifyFlag); |
451 | | void UpdateFinishedState(SeekFlag aSeekFlag, |
452 | | SyncNotifyFlag aSyncNotifyFlag); |
453 | | void UpdateEffect(); |
454 | | /** |
455 | | * Flush all pending styles other than throttled animation styles (e.g. |
456 | | * animations running on the compositor). |
457 | | */ |
458 | | void FlushUnanimatedStyle() const; |
459 | | void PostUpdate(); |
460 | | void ResetFinishedPromise(); |
461 | | void MaybeResolveFinishedPromise(); |
462 | | void DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag); |
463 | | friend class AsyncFinishNotification; |
464 | | void DoFinishNotificationImmediately(MicroTaskRunnable* aAsync = nullptr); |
465 | | void QueuePlaybackEvent(const nsAString& aName, |
466 | | TimeStamp&& aScheduledEventTime); |
467 | | |
468 | | /** |
469 | | * Remove this animation from the pending animation tracker and reset |
470 | | * mPendingState as necessary. The caller is responsible for resolving or |
471 | | * aborting the mReady promise as necessary. |
472 | | */ |
473 | | void CancelPendingTasks(); |
474 | | |
475 | | /** |
476 | | * Performs the same steps as CancelPendingTasks and also rejects and |
477 | | * recreates the ready promise if the animation was pending. |
478 | | */ |
479 | | void ResetPendingTasks(); |
480 | | |
481 | | /** |
482 | | * Returns true if this animation is not only play-pending, but has |
483 | | * yet to be given a pending ready time. This roughly corresponds to |
484 | | * animations that are waiting to be painted (since we set the pending |
485 | | * ready time at the end of painting). Identifying such animations is |
486 | | * useful because in some cases animations that are painted together |
487 | | * may need to be synchronized. |
488 | | * |
489 | | * We don't, however, want to include animations with a fixed start time such |
490 | | * as animations that are simply having their playbackRate updated or which |
491 | | * are resuming from an aborted pause. |
492 | | */ |
493 | 0 | bool IsNewlyStarted() const { |
494 | 0 | return mPendingState == PendingState::PlayPending && |
495 | 0 | mPendingReadyTime.IsNull() && |
496 | 0 | mStartTime.IsNull(); |
497 | 0 | } |
498 | | bool IsPossiblyOrphanedPendingAnimation() const; |
499 | | StickyTimeDuration EffectEnd() const; |
500 | | |
501 | | Nullable<TimeDuration> GetCurrentTimeForHoldTime( |
502 | | const Nullable<TimeDuration>& aHoldTime) const; |
503 | | Nullable<TimeDuration> GetUnconstrainedCurrentTime() const |
504 | 0 | { |
505 | 0 | return GetCurrentTimeForHoldTime(Nullable<TimeDuration>()); |
506 | 0 | } |
507 | | |
508 | | // Earlier side of the elapsed time range reported in CSS Animations and CSS |
509 | | // Transitions events. |
510 | | // |
511 | | // https://drafts.csswg.org/css-animations-2/#interval-start |
512 | | // https://drafts.csswg.org/css-transitions-2/#interval-start |
513 | | StickyTimeDuration |
514 | | IntervalStartTime(const StickyTimeDuration& aActiveDuration) const |
515 | 0 | { |
516 | 0 | MOZ_ASSERT(AsCSSTransition() || AsCSSAnimation(), |
517 | 0 | "Should be called for CSS animations or transitions"); |
518 | 0 | static constexpr StickyTimeDuration zeroDuration = StickyTimeDuration(); |
519 | 0 | return std::max( |
520 | 0 | std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().Delay()), |
521 | 0 | aActiveDuration), |
522 | 0 | zeroDuration); |
523 | 0 | } |
524 | | |
525 | | // Later side of the elapsed time range reported in CSS Animations and CSS |
526 | | // Transitions events. |
527 | | // |
528 | | // https://drafts.csswg.org/css-animations-2/#interval-end |
529 | | // https://drafts.csswg.org/css-transitions-2/#interval-end |
530 | | StickyTimeDuration |
531 | | IntervalEndTime(const StickyTimeDuration& aActiveDuration) const |
532 | 0 | { |
533 | 0 | MOZ_ASSERT(AsCSSTransition() || AsCSSAnimation(), |
534 | 0 | "Should be called for CSS animations or transitions"); |
535 | 0 |
|
536 | 0 | static constexpr StickyTimeDuration zeroDuration = StickyTimeDuration(); |
537 | 0 | return std::max( |
538 | 0 | std::min((EffectEnd() - mEffect->SpecifiedTiming().Delay()), |
539 | 0 | aActiveDuration), |
540 | 0 | zeroDuration); |
541 | 0 | } |
542 | | |
543 | | TimeStamp GetTimelineCurrentTimeAsTimeStamp() const |
544 | 0 | { |
545 | 0 | return mTimeline ? mTimeline->GetCurrentTimeAsTimeStamp() : TimeStamp(); |
546 | 0 | } |
547 | | |
548 | | nsIDocument* GetRenderedDocument() const; |
549 | | nsIDocument* GetTimelineDocument() const; |
550 | | |
551 | | RefPtr<AnimationTimeline> mTimeline; |
552 | | RefPtr<AnimationEffect> mEffect; |
553 | | // The beginning of the delay period. |
554 | | Nullable<TimeDuration> mStartTime; // Timeline timescale |
555 | | Nullable<TimeDuration> mHoldTime; // Animation timescale |
556 | | Nullable<TimeDuration> mPendingReadyTime; // Timeline timescale |
557 | | Nullable<TimeDuration> mPreviousCurrentTime; // Animation timescale |
558 | | double mPlaybackRate; |
559 | | Maybe<double> mPendingPlaybackRate; |
560 | | |
561 | | // A Promise that is replaced on each call to Play() |
562 | | // and fulfilled when Play() is successfully completed. |
563 | | // This object is lazily created by GetReady. |
564 | | // See http://drafts.csswg.org/web-animations/#current-ready-promise |
565 | | RefPtr<Promise> mReady; |
566 | | |
567 | | // A Promise that is resolved when we reach the end of the effect, or |
568 | | // 0 when playing backwards. The Promise is replaced if the animation is |
569 | | // finished but then a state change makes it not finished. |
570 | | // This object is lazily created by GetFinished. |
571 | | // See http://drafts.csswg.org/web-animations/#current-finished-promise |
572 | | RefPtr<Promise> mFinished; |
573 | | |
574 | | static uint64_t sNextAnimationIndex; |
575 | | |
576 | | // The relative position of this animation within the global animation list. |
577 | | // This is kNoIndex while the animation is in the idle state and is updated |
578 | | // each time the animation transitions out of the idle state. |
579 | | // |
580 | | // Note that subclasses such as CSSTransition and CSSAnimation may repurpose |
581 | | // this member to implement their own brand of sorting. As a result, it is |
582 | | // possible for two different objects to have the same index. |
583 | | uint64_t mAnimationIndex; |
584 | | |
585 | | // While ordering Animation objects for event dispatch, the index of the |
586 | | // target node in its parent may be cached in mCachedChildIndex. |
587 | | int32_t mCachedChildIndex; |
588 | | |
589 | | // Indicates if the animation is in the pending state (and what state it is |
590 | | // waiting to enter when it finished pending). We use this rather than |
591 | | // checking if this animation is tracked by a PendingAnimationTracker because |
592 | | // the animation will continue to be pending even after it has been removed |
593 | | // from the PendingAnimationTracker while it is waiting for the next tick |
594 | | // (see TriggerOnNextTick for details). |
595 | | enum class PendingState : uint8_t |
596 | | { |
597 | | NotPending, |
598 | | PlayPending, |
599 | | PausePending |
600 | | }; |
601 | | PendingState mPendingState; |
602 | | |
603 | | bool mFinishedAtLastComposeStyle; |
604 | | // Indicates that the animation should be exposed in an element's |
605 | | // getAnimations() list. |
606 | | bool mIsRelevant; |
607 | | |
608 | | // True if mFinished is resolved or would be resolved if mFinished has |
609 | | // yet to be created. This is not set when mFinished is rejected since |
610 | | // in that case mFinished is immediately reset to represent a new current |
611 | | // finished promise. |
612 | | bool mFinishedIsResolved; |
613 | | |
614 | | // True if this animation was triggered at the same time as one or more |
615 | | // geometric animations and hence we should run any transform animations on |
616 | | // the main thread. |
617 | | bool mSyncWithGeometricAnimations; |
618 | | |
619 | | RefPtr<MicroTaskRunnable> mFinishNotificationTask; |
620 | | |
621 | | nsString mId; |
622 | | }; |
623 | | |
624 | | } // namespace dom |
625 | | } // namespace mozilla |
626 | | |
627 | | #endif // mozilla_dom_Animation_h |