/* 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/. */ #ifndef mozilla_dom_Animation_h #define mozilla_dom_Animation_h #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsIDocument.h" #include "nsWrapperCache.h" #include "mozilla/Attributes.h" #include "mozilla/StyleAnimationValue.h" #include "mozilla/TimeStamp.h" #include "mozilla/dom/Nullable.h" #include "nsSMILKeySpline.h" #include "nsStyleStruct.h" // for nsTimingFunction struct JSContext; namespace mozilla { /** * Input timing parameters. * * Eventually this will represent all the input timing parameters specified * by content but for now it encapsulates just the subset of those * parameters passed to GetPositionInIteration. */ struct AnimationTiming { TimeDuration mIterationDuration; TimeDuration mDelay; float mIterationCount; // mozilla::PositiveInfinity() means infinite uint8_t mDirection; uint8_t mFillMode; bool FillsForwards() const { return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH || mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS; } bool FillsBackwards() const { return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH || mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS; } }; /** * Stores the results of calculating the timing properties of an animation * at a given sample time. */ struct ComputedTiming { ComputedTiming() : mTimeFraction(kNullTimeFraction) , mCurrentIteration(0) , mPhase(AnimationPhase_Null) { } static const double kNullTimeFraction; // The total duration of the animation including all iterations. // Will equal TimeDuration::Forever() if the animation repeats indefinitely. TimeDuration mActiveDuration; // Will be kNullTimeFraction if the animation is neither animating nor // filling at the sampled time. double mTimeFraction; // Zero-based iteration index (meaningless if mTimeFraction is // kNullTimeFraction). uint64_t mCurrentIteration; enum { // Not sampled (null sample time) AnimationPhase_Null, // Sampled prior to the start of the active interval AnimationPhase_Before, // Sampled within the active interval AnimationPhase_Active, // Sampled after (or at) the end of the active interval AnimationPhase_After } mPhase; }; class ComputedTimingFunction { public: typedef nsTimingFunction::Type Type; void Init(const nsTimingFunction &aFunction); double GetValue(double aPortion) const; const nsSMILKeySpline* GetFunction() const { NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch"); return &mTimingFunction; } Type GetType() const { return mType; } uint32_t GetSteps() const { return mSteps; } private: Type mType; nsSMILKeySpline mTimingFunction; uint32_t mSteps; }; struct AnimationPropertySegment { float mFromKey, mToKey; StyleAnimationValue mFromValue, mToValue; ComputedTimingFunction mTimingFunction; }; struct AnimationProperty { nsCSSProperty mProperty; InfallibleTArray mSegments; }; struct ElementPropertyTransition; namespace dom { class AnimationEffect; class Animation : public nsWrapperCache { public: Animation(nsIDocument* aDocument, const AnimationTiming &aTiming, const nsSubstring& aName) : mDocument(aDocument) , mTiming(aTiming) , mName(aName) , mIsFinishedTransition(false) , mLastNotification(LAST_NOTIFICATION_NONE) { SetIsDOMBinding(); } NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Animation) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Animation) nsIDocument* GetParentObject() const { return mDocument; } virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; // FIXME: If we succeed in moving transition-specific code to a type of // AnimationEffect (as per the Web Animations API) we should remove these // virtual methods. virtual ElementPropertyTransition* AsTransition() { return nullptr; } virtual const ElementPropertyTransition* AsTransition() const { return nullptr; } // Animation interface // This currently returns a new object each time when used from C++ but is // cached when used from JS. already_AddRefed GetEffect(); void SetParentTime(Nullable aParentTime); const AnimationTiming& Timing() const { return mTiming; } AnimationTiming& Timing() { return mTiming; } const nsString& Name() const { return mName; } // Return the duration from the start the active interval to the point where // the animation begins playback. This is zero unless the animation has // a negative delay in which case it is the absolute value of the delay. // This is used for setting the elapsedTime member of CSS AnimationEvents. TimeDuration InitialAdvance() const { return std::max(TimeDuration(), mTiming.mDelay * -1); } Nullable GetLocalTime() const { // Since the *animation* start time is currently always zero, the local // time is equal to the parent time. return mParentTime; } // This function takes as input the timing parameters of an animation and // returns the computed timing at the specified local time. // // The local time may be null in which case only static parameters such as the // active duration are calculated. All other members of the returned object // are given a null/initial value. // // This function returns ComputedTiming::kNullTimeFraction for the // mTimeFraction member of the return value if the animation should not be // run (because it is not currently active and is not filling at this time). static ComputedTiming GetComputedTimingAt(const Nullable& aLocalTime, const AnimationTiming& aTiming); // Shortcut for that gets the computed timing using the current local time as // calculated from the timeline time. ComputedTiming GetComputedTiming(const AnimationTiming* aTiming = nullptr) const { return GetComputedTimingAt(GetLocalTime(), aTiming ? *aTiming : mTiming); } // Return the duration of the active interval for the given timing parameters. static TimeDuration ActiveDuration(const AnimationTiming& aTiming); // After transitions finish they need to be retained for one throttle-able // cycle (for reasons see explanation in // layout/style/nsTransitionManager.cpp). // In the meantime, however, they should be ignored. bool IsFinishedTransition() const { return mIsFinishedTransition; } void SetIsFinishedTransition() { MOZ_ASSERT(AsTransition(), "Calling SetIsFinishedTransition but it's not a transition"); mIsFinishedTransition = true; } bool IsCurrent() const { if (IsFinishedTransition()) { return false; } ComputedTiming computedTiming = GetComputedTiming(); return computedTiming.mPhase == ComputedTiming::AnimationPhase_Before || computedTiming.mPhase == ComputedTiming::AnimationPhase_Active; } enum { LAST_NOTIFICATION_NONE = uint64_t(-1), LAST_NOTIFICATION_END = uint64_t(-2) }; uint64_t LastNotification() const { return mLastNotification; } void SetLastNotification(uint64_t aLastNotification) { mLastNotification = aLastNotification; } bool HasAnimationOfProperty(nsCSSProperty aProperty) const; const InfallibleTArray& Properties() const { return mProperties; } InfallibleTArray& Properties() { return mProperties; } protected: virtual ~Animation() { } // We use a document for a parent object since the other likely candidate, // the target element, can be empty. nsRefPtr mDocument; Nullable mParentTime; AnimationTiming mTiming; nsString mName; // A flag to mark transitions that have finished and are due to // be removed on the next throttle-able cycle. bool mIsFinishedTransition; // One of the LAST_NOTIFICATION_* constants, or an integer for the iteration // whose start we last notified on. uint64_t mLastNotification; InfallibleTArray mProperties; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_Animation_h