LCOV - code coverage report
Current view: directory - content/svg/content/src - SVGMotionSMILAnimationFunction.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 207 0 0.0 %
Date: 2012-06-02 Functions: 19 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 SVG project.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is the Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Daniel Holbert <dholbert@mozilla.com>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "SVGMotionSMILAnimationFunction.h"
      39                 : #include "nsSMILParserUtils.h"
      40                 : #include "nsSVGAngle.h"
      41                 : #include "SVGMotionSMILType.h"
      42                 : #include "SVGMotionSMILPathUtils.h"
      43                 : #include "nsSVGPathDataParser.h"
      44                 : #include "nsSVGPathElement.h" // for nsSVGPathList
      45                 : #include "nsSVGMpathElement.h"
      46                 : 
      47                 : namespace mozilla {
      48                 : 
      49               0 : SVGMotionSMILAnimationFunction::SVGMotionSMILAnimationFunction()
      50                 :   : mRotateType(eRotateType_Explicit),
      51                 :     mRotateAngle(0.0f),
      52                 :     mPathSourceType(ePathSourceType_None),
      53               0 :     mIsPathStale(true)  // Try to initialize path on first GetValues call
      54                 : {
      55               0 : }
      56                 : 
      57                 : void
      58               0 : SVGMotionSMILAnimationFunction::MarkStaleIfAttributeAffectsPath(nsIAtom* aAttribute)
      59                 : {
      60                 :   bool isAffected;
      61               0 :   if (aAttribute == nsGkAtoms::path) {
      62               0 :     isAffected = (mPathSourceType <= ePathSourceType_PathAttr);
      63               0 :   } else if (aAttribute == nsGkAtoms::values) {
      64               0 :     isAffected = (mPathSourceType <= ePathSourceType_ValuesAttr);
      65               0 :   } else if (aAttribute == nsGkAtoms::from ||
      66                 :              aAttribute == nsGkAtoms::to) {
      67               0 :     isAffected = (mPathSourceType <= ePathSourceType_ToAttr);
      68               0 :   } else if (aAttribute == nsGkAtoms::by) {
      69               0 :     isAffected = (mPathSourceType <= ePathSourceType_ByAttr);
      70                 :   } else {
      71               0 :     NS_NOTREACHED("Should only call this method for path-describing attrs");
      72               0 :     isAffected = false;
      73                 :   }
      74                 : 
      75               0 :   if (isAffected) {
      76               0 :     mIsPathStale = true;
      77               0 :     mHasChanged = true;
      78                 :   }
      79               0 : }
      80                 : 
      81                 : bool
      82               0 : SVGMotionSMILAnimationFunction::SetAttr(nsIAtom* aAttribute,
      83                 :                                         const nsAString& aValue,
      84                 :                                         nsAttrValue& aResult,
      85                 :                                         nsresult* aParseResult)
      86                 : {
      87                 :   // Handle motion-specific attrs
      88               0 :   if (aAttribute == nsGkAtoms::keyPoints) {
      89               0 :     nsresult rv = SetKeyPoints(aValue, aResult);
      90               0 :     if (aParseResult) {
      91               0 :       *aParseResult = rv;
      92                 :     }
      93               0 :   } else if (aAttribute == nsGkAtoms::rotate) {
      94               0 :     nsresult rv = SetRotate(aValue, aResult);
      95               0 :     if (aParseResult) {
      96               0 :       *aParseResult = rv;
      97                 :     }
      98               0 :   } else if (aAttribute == nsGkAtoms::path) {
      99               0 :     aResult.SetTo(aValue);
     100               0 :     if (aParseResult) {
     101               0 :       *aParseResult = NS_OK;
     102                 :     }
     103               0 :     MarkStaleIfAttributeAffectsPath(aAttribute);
     104               0 :   } else if (aAttribute == nsGkAtoms::by ||
     105                 :              aAttribute == nsGkAtoms::from ||
     106                 :              aAttribute == nsGkAtoms::to ||
     107                 :              aAttribute == nsGkAtoms::values) {
     108               0 :     MarkStaleIfAttributeAffectsPath(aAttribute);
     109                 :   } else {
     110                 :     // Defer to superclass method
     111                 :     return nsSMILAnimationFunction::SetAttr(aAttribute, aValue,
     112               0 :                                             aResult, aParseResult);
     113                 :   }
     114                 : 
     115               0 :   return true;
     116                 : }
     117                 : 
     118                 : bool
     119               0 : SVGMotionSMILAnimationFunction::UnsetAttr(nsIAtom* aAttribute)
     120                 : {
     121               0 :   if (aAttribute == nsGkAtoms::keyPoints) {
     122               0 :     UnsetKeyPoints();
     123               0 :   } else if (aAttribute == nsGkAtoms::rotate) {
     124               0 :     UnsetRotate();
     125               0 :   } else if (aAttribute == nsGkAtoms::path ||
     126                 :              aAttribute == nsGkAtoms::by ||
     127                 :              aAttribute == nsGkAtoms::from ||
     128                 :              aAttribute == nsGkAtoms::to ||
     129                 :              aAttribute == nsGkAtoms::values) {
     130               0 :     MarkStaleIfAttributeAffectsPath(aAttribute);
     131                 :   } else {
     132                 :     // Defer to superclass method
     133               0 :     return nsSMILAnimationFunction::UnsetAttr(aAttribute);
     134                 :   }
     135                 : 
     136               0 :   return true;
     137                 : }
     138                 : 
     139                 : nsSMILAnimationFunction::nsSMILCalcMode
     140               0 : SVGMotionSMILAnimationFunction::GetCalcMode() const
     141                 : {
     142               0 :   const nsAttrValue* value = GetAttr(nsGkAtoms::calcMode);
     143               0 :   if (!value) {
     144               0 :     return CALC_PACED; // animateMotion defaults to calcMode="paced"
     145                 :   }
     146                 : 
     147               0 :   return nsSMILCalcMode(value->GetEnumValue());
     148                 : }
     149                 : 
     150                 : //----------------------------------------------------------------------
     151                 : // Helpers for GetValues
     152                 : 
     153                 : /*
     154                 :  * Returns the first <mpath> child of the given element
     155                 :  */
     156                 : 
     157                 : static nsSVGMpathElement*
     158               0 : GetFirstMpathChild(nsIContent* aElem)
     159                 : {
     160               0 :   for (nsIContent* child = aElem->GetFirstChild();
     161                 :        child;
     162               0 :        child = child->GetNextSibling()) {
     163               0 :     if (child->IsSVG(nsGkAtoms::mpath)) {
     164               0 :       return static_cast<nsSVGMpathElement*>(child);
     165                 :     }
     166                 :   }
     167                 : 
     168               0 :   return nsnull;
     169                 : }
     170                 : 
     171                 : void
     172               0 : SVGMotionSMILAnimationFunction::
     173                 :   RebuildPathAndVerticesFromBasicAttrs(const nsIContent* aContextElem)
     174                 : {
     175               0 :   NS_ABORT_IF_FALSE(!HasAttr(nsGkAtoms::path),
     176                 :                     "Should be using |path| attr if we have it");
     177               0 :   NS_ABORT_IF_FALSE(!mPath, "regenerating when we aleady have path");
     178               0 :   NS_ABORT_IF_FALSE(mPathVertices.IsEmpty(),
     179                 :                     "regenerating when we already have vertices");
     180                 : 
     181               0 :   if (!aContextElem->IsSVG()) {
     182               0 :     NS_ERROR("Uh oh, SVG animateMotion element targeting a non-SVG node");
     183               0 :     return;
     184                 :   }
     185                 : 
     186                 :   SVGMotionSMILPathUtils::PathGenerator
     187               0 :     pathGenerator(static_cast<const nsSVGElement*>(aContextElem));
     188                 : 
     189               0 :   bool success = false;
     190               0 :   if (HasAttr(nsGkAtoms::values)) {
     191                 :     // Generate path based on our values array
     192               0 :     mPathSourceType = ePathSourceType_ValuesAttr;
     193               0 :     const nsAString& valuesStr = GetAttr(nsGkAtoms::values)->GetStringValue();
     194                 :     SVGMotionSMILPathUtils::MotionValueParser parser(&pathGenerator,
     195               0 :                                                      &mPathVertices);
     196                 :     success =
     197               0 :       NS_SUCCEEDED(nsSMILParserUtils::ParseValuesGeneric(valuesStr, parser));
     198               0 :   } else if (HasAttr(nsGkAtoms::to) || HasAttr(nsGkAtoms::by)) {
     199                 :     // Apply 'from' value (or a dummy 0,0 'from' value)
     200               0 :     if (HasAttr(nsGkAtoms::from)) {
     201               0 :       const nsAString& fromStr = GetAttr(nsGkAtoms::from)->GetStringValue();
     202               0 :       success = pathGenerator.MoveToAbsolute(fromStr);
     203               0 :       mPathVertices.AppendElement(0.0);
     204                 :     } else {
     205                 :       // Create dummy 'from' value at 0,0, if we're doing by-animation.
     206                 :       // (NOTE: We don't add the dummy 0-point to our list for *to-animation*,
     207                 :       // because the nsSMILAnimationFunction logic for to-animation doesn't
     208                 :       // expect a dummy value. It only expects one value: the final 'to' value.)
     209               0 :       pathGenerator.MoveToOrigin();
     210               0 :       if (!HasAttr(nsGkAtoms::to)) {
     211               0 :         mPathVertices.AppendElement(0.0);
     212                 :       }
     213               0 :       success = true;
     214                 :     }
     215                 : 
     216                 :     // Apply 'to' or 'by' value
     217               0 :     if (success) {
     218                 :       double dist;
     219               0 :       if (HasAttr(nsGkAtoms::to)) {
     220               0 :         mPathSourceType = ePathSourceType_ToAttr;
     221               0 :         const nsAString& toStr = GetAttr(nsGkAtoms::to)->GetStringValue();
     222               0 :         success = pathGenerator.LineToAbsolute(toStr, dist);
     223                 :       } else { // HasAttr(nsGkAtoms::by)
     224               0 :         mPathSourceType = ePathSourceType_ByAttr;
     225               0 :         const nsAString& byStr = GetAttr(nsGkAtoms::by)->GetStringValue();
     226               0 :         success = pathGenerator.LineToRelative(byStr, dist);
     227                 :       }
     228               0 :       if (success) {
     229               0 :         mPathVertices.AppendElement(dist);
     230                 :       }
     231                 :     }
     232                 :   }
     233               0 :   if (success) {
     234               0 :     mPath = pathGenerator.GetResultingPath();
     235                 :   } else {
     236                 :     // Parse failure. Leave path as null, and clear path-related member data.
     237               0 :     mPathVertices.Clear();
     238                 :   }
     239                 : }
     240                 : 
     241                 : void
     242               0 : SVGMotionSMILAnimationFunction::
     243                 :   RebuildPathAndVerticesFromMpathElem(nsSVGMpathElement* aMpathElem)
     244                 : {
     245               0 :   mPathSourceType = ePathSourceType_Mpath;
     246                 : 
     247                 :   // Use the path that's the target of our chosen <mpath> child.
     248               0 :   nsSVGPathElement* pathElem = aMpathElem->GetReferencedPath();
     249               0 :   if (pathElem) {
     250               0 :     const SVGPathData &path = pathElem->GetAnimPathSegList()->GetAnimValue();
     251                 :     // Path data must contain of at least one path segment (if the path data
     252                 :     // doesn't begin with a valid "M", then it's invalid).
     253               0 :     if (path.Length()) {
     254                 :       bool ok =
     255               0 :         path.GetDistancesFromOriginToEndsOfVisibleSegments(&mPathVertices);
     256               0 :       if (ok && mPathVertices.Length()) {
     257               0 :         mPath = pathElem->GetFlattenedPath(gfxMatrix());
     258                 :       }
     259                 :     }
     260                 :   }
     261               0 : }
     262                 : 
     263                 : void
     264               0 : SVGMotionSMILAnimationFunction::RebuildPathAndVerticesFromPathAttr()
     265                 : {
     266               0 :   const nsAString& pathSpec = GetAttr(nsGkAtoms::path)->GetStringValue();
     267               0 :   mPathSourceType = ePathSourceType_PathAttr;
     268                 : 
     269                 :   // Generate gfxFlattenedPath from |path| attr
     270               0 :   SVGPathData path;
     271               0 :   nsSVGPathDataParserToInternal pathParser(&path);
     272                 : 
     273                 :   // We ignore any failure returned from Parse() since the SVG spec says to
     274                 :   // accept all segments up to the first invalid token. Instead we must
     275                 :   // explicitly check that the parse produces at least one path segment (if
     276                 :   // the path data doesn't begin with a valid "M", then it's invalid).
     277               0 :   pathParser.Parse(pathSpec);
     278               0 :   if (!path.Length()) {
     279                 :     return;
     280                 :   }
     281                 : 
     282               0 :   mPath = path.ToFlattenedPath(gfxMatrix());
     283               0 :   bool ok = path.GetDistancesFromOriginToEndsOfVisibleSegments(&mPathVertices);
     284               0 :   if (!ok || !mPathVertices.Length()) {
     285               0 :     mPath = nsnull;
     286                 :   }
     287                 : }
     288                 : 
     289                 : // Helper to regenerate our path representation & its list of vertices
     290                 : void
     291               0 : SVGMotionSMILAnimationFunction::
     292                 :   RebuildPathAndVertices(const nsIContent* aTargetElement)
     293                 : {
     294               0 :   NS_ABORT_IF_FALSE(mIsPathStale, "rebuilding path when it isn't stale");
     295                 : 
     296                 :   // Clear stale data
     297               0 :   mPath = nsnull;
     298               0 :   mPathVertices.Clear();
     299               0 :   mPathSourceType = ePathSourceType_None;
     300                 : 
     301                 :   // Do we have a mpath child? if so, it trumps everything. Otherwise, we look
     302                 :   // through our list of path-defining attributes, in order of priority.
     303                 :   nsSVGMpathElement* firstMpathChild =
     304               0 :     GetFirstMpathChild(&mAnimationElement->AsElement());
     305                 : 
     306               0 :   if (firstMpathChild) {
     307               0 :     RebuildPathAndVerticesFromMpathElem(firstMpathChild);
     308               0 :     mValueNeedsReparsingEverySample = false;
     309               0 :   } else if (HasAttr(nsGkAtoms::path)) {
     310               0 :     RebuildPathAndVerticesFromPathAttr();
     311               0 :     mValueNeedsReparsingEverySample = false;
     312                 :   } else {
     313                 :     // Get path & vertices from basic SMIL attrs: from/by/to/values
     314                 : 
     315               0 :     RebuildPathAndVerticesFromBasicAttrs(aTargetElement);
     316               0 :     mValueNeedsReparsingEverySample = true;
     317                 :   }
     318               0 :   mIsPathStale = false;
     319               0 : }
     320                 : 
     321                 : bool
     322               0 : SVGMotionSMILAnimationFunction::
     323                 :   GenerateValuesForPathAndPoints(gfxFlattenedPath* aPath,
     324                 :                                  bool aIsKeyPoints,
     325                 :                                  nsTArray<double>& aPointDistances,
     326                 :                                  nsTArray<nsSMILValue>& aResult)
     327                 : {
     328               0 :   NS_ABORT_IF_FALSE(aResult.IsEmpty(), "outparam is non-empty");
     329                 : 
     330                 :   // If we're using "keyPoints" as our list of input distances, then we need
     331                 :   // to de-normalize from the [0, 1] scale to the [0, totalPathLen] scale.
     332               0 :   double distanceMultiplier = aIsKeyPoints ? aPath->GetLength() : 1.0;
     333               0 :   const PRUint32 numPoints = aPointDistances.Length();
     334               0 :   for (PRUint32 i = 0; i < numPoints; ++i) {
     335               0 :     double curDist = aPointDistances[i] * distanceMultiplier;
     336               0 :     if (!aResult.AppendElement(
     337                 :           SVGMotionSMILType::ConstructSMILValue(aPath, curDist,
     338               0 :                                                 mRotateType, mRotateAngle))) {
     339               0 :       return false;
     340                 :     }
     341                 :   }
     342               0 :   return true;
     343                 : }
     344                 : 
     345                 : nsresult
     346               0 : SVGMotionSMILAnimationFunction::GetValues(const nsISMILAttr& aSMILAttr,
     347                 :                                           nsSMILValueArray& aResult)
     348                 : {
     349               0 :   if (mIsPathStale) {
     350               0 :     RebuildPathAndVertices(aSMILAttr.GetTargetNode());
     351                 :   }
     352               0 :   NS_ABORT_IF_FALSE(!mIsPathStale, "Forgot to clear 'is path stale' state");
     353                 : 
     354               0 :   if (!mPath) {
     355                 :     // This could be due to e.g. a parse error.
     356               0 :     NS_ABORT_IF_FALSE(mPathVertices.IsEmpty(), "have vertices but no path");
     357               0 :     return NS_ERROR_FAILURE;
     358                 :   }
     359               0 :   NS_ABORT_IF_FALSE(!mPathVertices.IsEmpty(), "have a path but no vertices");
     360                 : 
     361                 :   // Now: Make the actual list of nsSMILValues (using keyPoints, if set)
     362               0 :   bool isUsingKeyPoints = !mKeyPoints.IsEmpty();
     363                 :   bool success = GenerateValuesForPathAndPoints(mPath, isUsingKeyPoints,
     364                 :                                                   isUsingKeyPoints ?
     365                 :                                                   mKeyPoints : mPathVertices,
     366               0 :                                                   aResult);
     367               0 :   if (!success) {
     368               0 :     return NS_ERROR_OUT_OF_MEMORY;
     369                 :   }
     370                 : 
     371               0 :   return NS_OK;
     372                 : }
     373                 : 
     374                 : void
     375               0 : SVGMotionSMILAnimationFunction::
     376                 :   CheckValueListDependentAttrs(PRUint32 aNumValues)
     377                 : {
     378                 :   // Call superclass method.
     379               0 :   nsSMILAnimationFunction::CheckValueListDependentAttrs(aNumValues);
     380                 : 
     381                 :   // Added behavior: Do checks specific to keyPoints.
     382               0 :   CheckKeyPoints();
     383               0 : }
     384                 : 
     385                 : bool
     386               0 : SVGMotionSMILAnimationFunction::IsToAnimation() const
     387                 : {
     388                 :   // Rely on inherited method, but not if we have an <mpath> child or a |path|
     389                 :   // attribute, because they'll override any 'to' attr we might have.
     390                 :   // NOTE: We can't rely on mPathSourceType, because it might not have been
     391                 :   // set to a useful value yet (or it might be stale).
     392               0 :   return !GetFirstMpathChild(&mAnimationElement->AsElement()) &&
     393               0 :     !HasAttr(nsGkAtoms::path) &&
     394               0 :     nsSMILAnimationFunction::IsToAnimation();
     395                 : }
     396                 : 
     397                 : void
     398               0 : SVGMotionSMILAnimationFunction::CheckKeyPoints()
     399                 : {
     400               0 :   if (!HasAttr(nsGkAtoms::keyPoints))
     401               0 :     return;
     402                 : 
     403                 :   // attribute is ignored for calcMode="paced" (even if it's got errors)
     404               0 :   if (GetCalcMode() == CALC_PACED) {
     405               0 :     SetKeyPointsErrorFlag(false);
     406                 :   }
     407                 : 
     408               0 :   if (mKeyPoints.IsEmpty()) {
     409                 :     // keyPoints attr is set, but array is empty => it failed preliminary checks
     410               0 :     SetKeyPointsErrorFlag(true);
     411               0 :     return;
     412                 :   }
     413                 : 
     414                 :   // Nothing else to check -- we can catch all keyPoints errors elsewhere.
     415                 :   // -  Formatting & range issues will be caught in SetKeyPoints, and will
     416                 :   //  result in an empty mKeyPoints array, which will drop us into the error
     417                 :   //  case above.
     418                 :   // -  Number-of-entries issues will be caught in CheckKeyTimes (and flagged
     419                 :   //  as a problem with |keyTimes|), since we use our keyPoints entries to
     420                 :   //  populate the "values" list, and that list's count gets passed to
     421                 :   //  CheckKeyTimes.
     422                 : }
     423                 : 
     424                 : nsresult
     425               0 : SVGMotionSMILAnimationFunction::SetKeyPoints(const nsAString& aKeyPoints,
     426                 :                                              nsAttrValue& aResult)
     427                 : {
     428               0 :   mKeyPoints.Clear();
     429               0 :   aResult.SetTo(aKeyPoints);
     430                 : 
     431                 :   nsresult rv =
     432                 :     nsSMILParserUtils::ParseSemicolonDelimitedProgressList(aKeyPoints, false,
     433               0 :                                                            mKeyPoints);
     434                 : 
     435               0 :   if (NS_SUCCEEDED(rv) && mKeyPoints.Length() < 1)
     436               0 :     rv = NS_ERROR_FAILURE;
     437                 : 
     438               0 :   if (NS_FAILED(rv)) {
     439               0 :     mKeyPoints.Clear();
     440                 :   }
     441                 : 
     442               0 :   mHasChanged = true;
     443                 : 
     444               0 :   return NS_OK;
     445                 : }
     446                 : 
     447                 : void
     448               0 : SVGMotionSMILAnimationFunction::UnsetKeyPoints()
     449                 : {
     450               0 :   mKeyPoints.Clear();
     451               0 :   SetKeyPointsErrorFlag(false);
     452               0 :   mHasChanged = true;
     453               0 : }
     454                 : 
     455                 : nsresult
     456               0 : SVGMotionSMILAnimationFunction::SetRotate(const nsAString& aRotate,
     457                 :                                           nsAttrValue& aResult)
     458                 : {
     459               0 :   mHasChanged = true;
     460                 : 
     461               0 :   aResult.SetTo(aRotate);
     462               0 :   if (aRotate.EqualsLiteral("auto")) {
     463               0 :     mRotateType = eRotateType_Auto;
     464               0 :   } else if (aRotate.EqualsLiteral("auto-reverse")) {
     465               0 :     mRotateType = eRotateType_AutoReverse;
     466                 :   } else {
     467               0 :     mRotateType = eRotateType_Explicit;
     468                 : 
     469                 :     // Parse numeric angle string, with the help of a temp nsSVGAngle.
     470                 :     nsSVGAngle svgAngle;
     471               0 :     svgAngle.Init();
     472               0 :     nsresult rv = svgAngle.SetBaseValueString(aRotate, nsnull, false);
     473               0 :     if (NS_FAILED(rv)) { // Parse error
     474               0 :       mRotateAngle = 0.0f; // set default rotate angle
     475                 :       // XXX report to console?
     476               0 :       return rv;
     477                 :     }
     478                 : 
     479               0 :     mRotateAngle = svgAngle.GetBaseValInSpecifiedUnits();
     480                 : 
     481                 :     // Convert to radian units, if we're not already in radians.
     482               0 :     PRUint8 angleUnit = svgAngle.GetBaseValueUnit();
     483               0 :     if (angleUnit != nsIDOMSVGAngle::SVG_ANGLETYPE_RAD) {
     484               0 :       mRotateAngle *= nsSVGAngle::GetDegreesPerUnit(angleUnit) /
     485               0 :         nsSVGAngle::GetDegreesPerUnit(nsIDOMSVGAngle::SVG_ANGLETYPE_RAD);
     486                 :     }
     487                 :   }
     488               0 :   return NS_OK;
     489                 : }
     490                 : 
     491                 : void
     492               0 : SVGMotionSMILAnimationFunction::UnsetRotate()
     493                 : {
     494               0 :   mRotateAngle = 0.0f; // default value
     495               0 :   mRotateType = eRotateType_Explicit;
     496               0 :   mHasChanged = true;
     497               0 : }
     498                 : 
     499                 : } // namespace mozilla

Generated by: LCOV version 1.7