LCOV - app.info - content/svg/content/src/SVGMotionSMILAnimationFunction.cpp

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