LCOV - code coverage report
Current view: directory - content/smil - nsSMILAnimationFunction.h (source / functions) Found Hit Coverage
Test: app.info Lines: 50 0 0.0 %
Date: 2012-06-02 Functions: 17 0 0.0 %

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

Generated by: LCOV version 1.7