dom/smil/nsSMILAnimationFunction.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef NS_SMILANIMATIONFUNCTION_H_
     7 #define NS_SMILANIMATIONFUNCTION_H_
     9 #include "nsISMILAttr.h"
    10 #include "nsGkAtoms.h"
    11 #include "nsString.h"
    12 #include "nsSMILTargetIdentifier.h"
    13 #include "nsSMILTimeValue.h"
    14 #include "nsSMILKeySpline.h"
    15 #include "nsSMILValue.h"
    16 #include "nsAutoPtr.h"
    17 #include "nsTArray.h"
    18 #include "nsAttrValue.h"
    19 #include "nsSMILTypes.h"
    21 namespace mozilla {
    22 namespace dom {
    23 class SVGAnimationElement;
    24 }
    25 }
    27 //----------------------------------------------------------------------
    28 // nsSMILAnimationFunction
    29 //
    30 // The animation function calculates animation values. It it is provided with
    31 // time parameters (sample time, repeat iteration etc.) and it uses this to
    32 // build an appropriate animation value by performing interpolation and
    33 // addition operations.
    34 //
    35 // It is responsible for implementing the animation parameters of an animation
    36 // element (e.g. from, by, to, values, calcMode, additive, accumulate, keyTimes,
    37 // keySplines)
    38 //
    39 class nsSMILAnimationFunction
    40 {
    41 public:
    42   nsSMILAnimationFunction();
    44   /*
    45    * Sets the owning animation element which this class uses to query attribute
    46    * values and compare document positions.
    47    */
    48   void SetAnimationElement(mozilla::dom::SVGAnimationElement* aAnimationElement);
    50   /*
    51    * Sets animation-specific attributes (or marks them dirty, in the case
    52    * of from/to/by/values).
    53    *
    54    * @param aAttribute The attribute being set
    55    * @param aValue     The updated value of the attribute.
    56    * @param aResult    The nsAttrValue object that may be used for storing the
    57    *                   parsed result.
    58    * @param aParseResult  Outparam used for reporting parse errors. Will be set
    59    *                      to NS_OK if everything succeeds.
    60    * @return  true if aAttribute is a recognized animation-related
    61    *          attribute; false otherwise.
    62    */
    63   virtual bool SetAttr(nsIAtom* aAttribute, const nsAString& aValue,
    64                          nsAttrValue& aResult, nsresult* aParseResult = nullptr);
    66   /*
    67    * Unsets the given attribute.
    68    *
    69    * @returns true if aAttribute is a recognized animation-related
    70    *          attribute; false otherwise.
    71    */
    72   virtual bool UnsetAttr(nsIAtom* aAttribute);
    74   /**
    75    * Indicate a new sample has occurred.
    76    *
    77    * @param aSampleTime The sample time for this timed element expressed in
    78    *                    simple time.
    79    * @param aSimpleDuration The simple duration for this timed element.
    80    * @param aRepeatIteration  The repeat iteration for this sample. The first
    81    *                          iteration has a value of 0.
    82    */
    83   void SampleAt(nsSMILTime aSampleTime,
    84                 const nsSMILTimeValue& aSimpleDuration,
    85                 uint32_t aRepeatIteration);
    87   /**
    88    * Indicate to sample using the last value defined for the animation function.
    89    * This value is not normally sampled due to the end-point exclusive timing
    90    * model but only occurs when the fill mode is "freeze" and the active
    91    * duration is an even multiple of the simple duration.
    92    *
    93    * @param aRepeatIteration  The repeat iteration for this sample. The first
    94    *                          iteration has a value of 0.
    95    */
    96   void SampleLastValue(uint32_t aRepeatIteration);
    98   /**
    99    * Indicate that this animation is now active. This is used to instruct the
   100    * animation function that it should now add its result to the animation
   101    * sandwich. The begin time is also provided for proper prioritization of
   102    * animation functions, and for this reason, this method must be called
   103    * before either of the Sample methods.
   104    *
   105    * @param aBeginTime The begin time for the newly active interval.
   106    */
   107   void Activate(nsSMILTime aBeginTime);
   109   /**
   110    * Indicate that this animation is no longer active. This is used to instruct
   111    * the animation function that it should no longer add its result to the
   112    * animation sandwich.
   113    *
   114    * @param aIsFrozen true if this animation should continue to contribute
   115    *                  to the animation sandwich using the most recent sample
   116    *                  parameters.
   117    */
   118   void Inactivate(bool aIsFrozen);
   120   /**
   121    * Combines the result of this animation function for the last sample with the
   122    * specified value.
   123    *
   124    * @param aSMILAttr This animation's target attribute. Used here for
   125    *                  doing attribute-specific parsing of from/to/by/values.
   126    *
   127    * @param aResult   The value to compose with.
   128    */
   129   void ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult);
   131   /**
   132    * Returns the relative priority of this animation to another. The priority is
   133    * used for determining the position of the animation in the animation
   134    * sandwich -- higher priority animations are applied on top of lower
   135    * priority animations.
   136    *
   137    * @return  -1 if this animation has lower priority or 1 if this animation has
   138    *          higher priority
   139    *
   140    * This method should never return any other value, including 0.
   141    */
   142   int8_t CompareTo(const nsSMILAnimationFunction* aOther) const;
   144   /*
   145    * The following methods are provided so that the compositor can optimize its
   146    * operations by only composing those animation that will affect the final
   147    * result.
   148    */
   150   /**
   151    * Indicates if the animation is currently active or frozen. Inactive
   152    * animations will not contribute to the composed result.
   153    *
   154    * @return  true if the animation is active or frozen, false otherwise.
   155    */
   156   bool IsActiveOrFrozen() const
   157   {
   158     /*
   159      * - Frozen animations should be considered active for the purposes of
   160      * compositing.
   161      * - This function does not assume that our nsSMILValues (by/from/to/values)
   162      * have already been parsed.
   163      */
   164     return (mIsActive || mIsFrozen);
   165   }
   167   /**
   168    * Indicates if the animation is active.
   169    *
   170    * @return  true if the animation is active, false otherwise.
   171    */
   172   bool IsActive() const {
   173     return mIsActive;
   174   }
   176   /**
   177    * Indicates if this animation will replace the passed in result rather than
   178    * adding to it. Animations that replace the underlying value may be called
   179    * without first calling lower priority animations.
   180    *
   181    * @return  True if the animation will replace, false if it will add or
   182    *          otherwise build on the passed in value.
   183    */
   184   virtual bool WillReplace() const;
   186   /**
   187    * Indicates if the parameters for this animation have changed since the last
   188    * time it was composited. This allows rendering to be performed only when
   189    * necessary, particularly when no animations are active.
   190    *
   191    * Note that the caller is responsible for determining if the animation
   192    * target has changed (with help from my UpdateCachedTarget() method).
   193    *
   194    * @return  true if the animation parameters have changed, false
   195    *          otherwise.
   196    */
   197   bool HasChanged() const;
   199   /**
   200    * This method lets us clear the 'HasChanged' flag for inactive animations
   201    * after we've reacted to their change to the 'inactive' state, so that we
   202    * won't needlessly recompose their targets in every sample.
   203    *
   204    * This should only be called on an animation function that is inactive and
   205    * that returns true from HasChanged().
   206    */
   207   void ClearHasChanged()
   208   {
   209     NS_ABORT_IF_FALSE(HasChanged(),
   210                       "clearing mHasChanged flag, when it's already false");
   211     NS_ABORT_IF_FALSE(!IsActiveOrFrozen(),
   212                       "clearing mHasChanged flag for active animation");
   213     mHasChanged = false;
   214   }
   216   /**
   217    * Updates the cached record of our animation target, and returns a boolean
   218    * that indicates whether the target has changed since the last call to this
   219    * function. (This lets nsSMILCompositor check whether its animation
   220    * functions have changed value or target since the last sample.  If none of
   221    * them have, then the compositor doesn't need to do anything.)
   222    *
   223    * @param aNewTarget A nsSMILTargetIdentifier representing the animation
   224    *                   target of this function for this sample.
   225    * @return  true if |aNewTarget| is different from the old cached value;
   226    *          otherwise, false.
   227    */
   228   bool UpdateCachedTarget(const nsSMILTargetIdentifier& aNewTarget);
   230   /**
   231    * Returns true if this function was skipped in the previous sample (because
   232    * there was a higher-priority non-additive animation). If a skipped animation
   233    * function is later used, then the animation sandwich must be recomposited.
   234    */
   235   bool WasSkippedInPrevSample() const {
   236     return mWasSkippedInPrevSample;
   237   }
   239   /**
   240    * Mark this animation function as having been skipped. By marking the
   241    * function as skipped, if it is used in a subsequent sample we'll know to
   242    * recomposite the sandwich.
   243    */
   244   void SetWasSkipped() {
   245     mWasSkippedInPrevSample = true;
   246   }
   248   // Comparator utility class, used for sorting nsSMILAnimationFunctions
   249   class Comparator {
   250     public:
   251       bool Equals(const nsSMILAnimationFunction* aElem1,
   252                     const nsSMILAnimationFunction* aElem2) const {
   253         return (aElem1->CompareTo(aElem2) == 0);
   254       }
   255       bool LessThan(const nsSMILAnimationFunction* aElem1,
   256                       const nsSMILAnimationFunction* aElem2) const {
   257         return (aElem1->CompareTo(aElem2) < 0);
   258       }
   259   };
   261 protected:
   262   // Typedefs
   263   typedef FallibleTArray<nsSMILValue> nsSMILValueArray;
   265   // Types
   266   enum nsSMILCalcMode
   267   {
   268     CALC_LINEAR,
   269     CALC_DISCRETE,
   270     CALC_PACED,
   271     CALC_SPLINE
   272   };
   274   // Used for sorting nsSMILAnimationFunctions
   275   nsSMILTime GetBeginTime() const { return mBeginTime; }
   277   // Property getters
   278   bool                   GetAccumulate() const;
   279   bool                   GetAdditive() const;
   280   virtual nsSMILCalcMode GetCalcMode() const;
   282   // Property setters
   283   nsresult SetAccumulate(const nsAString& aAccumulate, nsAttrValue& aResult);
   284   nsresult SetAdditive(const nsAString& aAdditive, nsAttrValue& aResult);
   285   nsresult SetCalcMode(const nsAString& aCalcMode, nsAttrValue& aResult);
   286   nsresult SetKeyTimes(const nsAString& aKeyTimes, nsAttrValue& aResult);
   287   nsresult SetKeySplines(const nsAString& aKeySplines, nsAttrValue& aResult);
   289   // Property un-setters
   290   void     UnsetAccumulate();
   291   void     UnsetAdditive();
   292   void     UnsetCalcMode();
   293   void     UnsetKeyTimes();
   294   void     UnsetKeySplines();
   296   // Helpers
   297   virtual nsresult InterpolateResult(const nsSMILValueArray& aValues,
   298                                      nsSMILValue& aResult,
   299                                      nsSMILValue& aBaseValue);
   300   nsresult AccumulateResult(const nsSMILValueArray& aValues,
   301                             nsSMILValue& aResult);
   303   nsresult ComputePacedPosition(const nsSMILValueArray& aValues,
   304                                 double aSimpleProgress,
   305                                 double& aIntervalProgress,
   306                                 const nsSMILValue*& aFrom,
   307                                 const nsSMILValue*& aTo);
   308   double   ComputePacedTotalDistance(const nsSMILValueArray& aValues) const;
   310   /**
   311    * Adjust the simple progress, that is, the point within the simple duration,
   312    * by applying any keyTimes.
   313    */
   314   double   ScaleSimpleProgress(double aProgress, nsSMILCalcMode aCalcMode);
   315   /**
   316    * Adjust the progress within an interval, that is, between two animation
   317    * values, by applying any keySplines.
   318    */
   319   double   ScaleIntervalProgress(double aProgress, uint32_t aIntervalIndex);
   321   // Convenience attribute getters -- use these instead of querying
   322   // mAnimationElement as these may need to be overridden by subclasses
   323   virtual bool               HasAttr(nsIAtom* aAttName) const;
   324   virtual const nsAttrValue* GetAttr(nsIAtom* aAttName) const;
   325   virtual bool               GetAttr(nsIAtom* aAttName,
   326                                      nsAString& aResult) const;
   328   bool     ParseAttr(nsIAtom* aAttName, const nsISMILAttr& aSMILAttr,
   329                      nsSMILValue& aResult,
   330                      bool& aPreventCachingOfSandwich) const;
   332   virtual nsresult GetValues(const nsISMILAttr& aSMILAttr,
   333                              nsSMILValueArray& aResult);
   335   virtual void CheckValueListDependentAttrs(uint32_t aNumValues);
   336   void         CheckKeyTimes(uint32_t aNumValues);
   337   void         CheckKeySplines(uint32_t aNumValues);
   339   virtual bool IsToAnimation() const {
   340     return !HasAttr(nsGkAtoms::values) &&
   341             HasAttr(nsGkAtoms::to) &&
   342            !HasAttr(nsGkAtoms::from);
   343   }
   345   // Returns true if we know our composited value won't change over the
   346   // simple duration of this animation (for a fixed base value).
   347   virtual bool IsValueFixedForSimpleDuration() const;
   349   inline bool IsAdditive() const {
   350     /*
   351      * Animation is additive if:
   352      *
   353      * (1) additive = "sum" (GetAdditive() == true), or
   354      * (2) it is 'by animation' (by is set, from and values are not)
   355      *
   356      * Although animation is not additive if it is 'to animation'
   357      */
   358     bool isByAnimation = (!HasAttr(nsGkAtoms::values) &&
   359                              HasAttr(nsGkAtoms::by) &&
   360                             !HasAttr(nsGkAtoms::from));
   361     return !IsToAnimation() && (GetAdditive() || isByAnimation);
   362   }
   364   // Setters for error flags
   365   // These correspond to bit-indices in mErrorFlags, for tracking parse errors
   366   // in these attributes, when those parse errors should block us from doing
   367   // animation.
   368   enum AnimationAttributeIdx {
   369     BF_ACCUMULATE  = 0,
   370     BF_ADDITIVE    = 1,
   371     BF_CALC_MODE   = 2,
   372     BF_KEY_TIMES   = 3,
   373     BF_KEY_SPLINES = 4,
   374     BF_KEY_POINTS  = 5 // <animateMotion> only
   375   };
   377   inline void SetAccumulateErrorFlag(bool aNewValue) {
   378     SetErrorFlag(BF_ACCUMULATE, aNewValue);
   379   }
   380   inline void SetAdditiveErrorFlag(bool aNewValue) {
   381     SetErrorFlag(BF_ADDITIVE, aNewValue);
   382   }
   383   inline void SetCalcModeErrorFlag(bool aNewValue) {
   384     SetErrorFlag(BF_CALC_MODE, aNewValue);
   385   }
   386   inline void SetKeyTimesErrorFlag(bool aNewValue) {
   387     SetErrorFlag(BF_KEY_TIMES, aNewValue);
   388   }
   389   inline void SetKeySplinesErrorFlag(bool aNewValue) {
   390     SetErrorFlag(BF_KEY_SPLINES, aNewValue);
   391   }
   392   inline void SetKeyPointsErrorFlag(bool aNewValue) {
   393     SetErrorFlag(BF_KEY_POINTS, aNewValue);
   394   }
   395   inline void SetErrorFlag(AnimationAttributeIdx aField, bool aValue) {
   396     if (aValue) {
   397       mErrorFlags |=  (0x01 << aField);
   398     } else {
   399       mErrorFlags &= ~(0x01 << aField);
   400     }
   401   }
   403   // Members
   404   // -------
   406   static nsAttrValue::EnumTable sAdditiveTable[];
   407   static nsAttrValue::EnumTable sCalcModeTable[];
   408   static nsAttrValue::EnumTable sAccumulateTable[];
   410   FallibleTArray<double>          mKeyTimes;
   411   FallibleTArray<nsSMILKeySpline> mKeySplines;
   413   // These are the parameters provided by the previous sample. Currently we
   414   // perform lazy calculation. That is, we only calculate the result if and when
   415   // instructed by the compositor. This allows us to apply the result directly
   416   // to the animation value and allows the compositor to filter out functions
   417   // that it determines will not contribute to the final result.
   418   nsSMILTime                    mSampleTime; // sample time within simple dur
   419   nsSMILTimeValue               mSimpleDuration;
   420   uint32_t                      mRepeatIteration;
   422   nsSMILTime                    mBeginTime; // document time
   424   // The owning animation element. This is used for sorting based on document
   425   // position and for fetching attribute values stored in the element.
   426   // Raw pointer is OK here, because this nsSMILAnimationFunction can't outlive
   427   // its owning animation element.
   428   mozilla::dom::SVGAnimationElement* mAnimationElement;
   430   // Which attributes have been set but have had errors. This is not used for
   431   // all attributes but only those which have specified error behaviour
   432   // associated with them.
   433   uint16_t                      mErrorFlags;
   435   // Allows us to check whether an animation function has changed target from
   436   // sample to sample (because if neither target nor animated value have
   437   // changed, we don't have to do anything).
   438   nsSMILWeakTargetIdentifier    mLastTarget;
   440   // Boolean flags
   441   bool mIsActive:1;
   442   bool mIsFrozen:1;
   443   bool mLastValue:1;
   444   bool mHasChanged:1;
   445   bool mValueNeedsReparsingEverySample:1;
   446   bool mPrevSampleWasSingleValueAnimation:1;
   447   bool mWasSkippedInPrevSample:1;
   448 };
   450 #endif // NS_SMILANIMATIONFUNCTION_H_

mercurial