Switch nsStyleAnimation from using nsStyleCoord to using its own nsStyleAnimation::Value, so we don't have to add nontrivial destructors to nsStyleCoord. (Bug 522852) r=dholbert,bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Tue, 20 Oct 2009 07:46:16 -0400
changeset 34029 2072cf8f65b4182d4e115f76def7574f7af1eec3
parent 34028 ef4565b6f26890847d30ef9be28a51fd4252c6ba
child 34030 c51d02c508120992f76536e954e13740a02bbc4a
push idunknown
push userunknown
push dateunknown
reviewersdholbert, bzbarsky
bugs522852
milestone1.9.3a1pre
Switch nsStyleAnimation from using nsStyleCoord to using its own nsStyleAnimation::Value, so we don't have to add nontrivial destructors to nsStyleCoord. (Bug 522852) r=dholbert,bzbarsky
content/smil/nsSMILCSSValueType.cpp
layout/style/nsStyleAnimation.cpp
layout/style/nsStyleAnimation.h
layout/style/nsStyleCoord.cpp
layout/style/nsStyleCoord.h
layout/style/nsTransitionManager.cpp
--- a/content/smil/nsSMILCSSValueType.cpp
+++ b/content/smil/nsSMILCSSValueType.cpp
@@ -35,82 +35,84 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* representation of a value for a SMIL-animated CSS property */
 
 #include "nsSMILCSSValueType.h"
 #include "nsString.h"
 #include "nsStyleAnimation.h"
-#include "nsStyleCoord.h"
 #include "nsSMILParserUtils.h"
 #include "nsSMILValue.h"
 #include "nsCSSValue.h"
 #include "nsCSSDeclaration.h"
 #include "nsColor.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsDebug.h"
 
 /*static*/ nsSMILCSSValueType nsSMILCSSValueType::sSingleton;
 
 struct ValueWrapper {
   ValueWrapper() : mCSSValue(), mPropID(eCSSProperty_UNKNOWN),
                    mPresContext(nsnull) {}
 
-  nsStyleCoord   mCSSValue;
+  nsStyleAnimation::Value mCSSValue;
   nsCSSProperty  mPropID;
   nsPresContext* mPresContext;
 };
 
 // Helper "zero" values of various types
 // -------------------------------------
-static const nsStyleCoord sZeroCoord(0, nsStyleCoord::CoordConstructor);
-static const nsStyleCoord sZeroPercent(0.0f, eStyleUnit_Percent);
-static const nsStyleCoord sZeroFactor(0.0f,  eStyleUnit_Factor);
-static const nsStyleCoord sZeroColor(NS_RGB(0,0,0),
-                                     nsStyleCoord::ColorConstructor);
+static const nsStyleAnimation::Value
+  sZeroCoord(0, nsStyleAnimation::Value::CoordConstructor);
+static const nsStyleAnimation::Value
+  sZeroPercent(0.0f, nsStyleAnimation::Value::PercentConstructor);
+static const nsStyleAnimation::Value
+  sZeroFloat(0.0f,  nsStyleAnimation::Value::FloatConstructor);
+static const nsStyleAnimation::Value
+  sZeroColor(NS_RGB(0,0,0), nsStyleAnimation::Value::ColorConstructor);
 
 // Helper Methods
 // --------------
-static const nsStyleCoord*
-GetZeroValueForUnit(nsStyleUnit aUnit)
+static const nsStyleAnimation::Value*
+GetZeroValueForUnit(nsStyleAnimation::Unit aUnit)
 {
-  NS_ABORT_IF_FALSE(aUnit != eStyleUnit_Null,
+  NS_ABORT_IF_FALSE(aUnit != nsStyleAnimation::eUnit_Null,
                     "Need non-null unit for a zero value.");
   switch (aUnit) {
-    case eStyleUnit_Coord:
+    case nsStyleAnimation::eUnit_Coord:
       return &sZeroCoord;
-    case eStyleUnit_Percent:
+    case nsStyleAnimation::eUnit_Percent:
       return &sZeroPercent;
-    case eStyleUnit_Factor:
-      return &sZeroFactor;
-    case eStyleUnit_Color:
+    case nsStyleAnimation::eUnit_Float:
+      return &sZeroFloat;
+    case nsStyleAnimation::eUnit_Color:
       return &sZeroColor;
     default:
       NS_NOTREACHED("Calling GetZeroValueForUnit with an unsupported unit");
       return nsnull;
   }
 }
 
 static void
-InvertStyleCoordSign(nsStyleCoord& aStyleCoord)
+InvertSign(nsStyleAnimation::Value& aStyleCoord)
 {
   switch (aStyleCoord.GetUnit()) {
-    case eStyleUnit_Coord:
+    case nsStyleAnimation::eUnit_Coord:
       aStyleCoord.SetCoordValue(-aStyleCoord.GetCoordValue());
       break;
-    case eStyleUnit_Percent:
+    case nsStyleAnimation::eUnit_Percent:
       aStyleCoord.SetPercentValue(-aStyleCoord.GetPercentValue());
       break;
-    case eStyleUnit_Factor:
-      aStyleCoord.SetFactorValue(-aStyleCoord.GetFactorValue());
+    case nsStyleAnimation::eUnit_Float:
+      aStyleCoord.SetFloatValue(-aStyleCoord.GetFloatValue());
       break;
     default:
-      NS_NOTREACHED("Calling InvertStyleCoordSign with an unsupported unit");
+      NS_NOTREACHED("Calling InvertSign with an unsupported unit");
       break;
   }
 }
 
 static ValueWrapper*
 ExtractValueWrapper(nsSMILValue& aValue)
 {
   return static_cast<ValueWrapper*>(aValue.mU.mPtr);
@@ -212,17 +214,17 @@ nsSMILCSSValueType::ComputeDistance(cons
                     "Trying to compare different types");
   NS_ABORT_IF_FALSE(aFrom.mType == this, "Unexpected source type");
 
   const ValueWrapper* fromWrapper = ExtractValueWrapper(aFrom);
   const ValueWrapper* toWrapper = ExtractValueWrapper(aTo);
   NS_ABORT_IF_FALSE(fromWrapper && toWrapper,
                     "These pointers shouldn't be null");
 
-  const nsStyleCoord* fromCSSValue;
+  const nsStyleAnimation::Value* fromCSSValue;
   if (fromWrapper->mPropID == eCSSProperty_UNKNOWN) {
     NS_ABORT_IF_FALSE(fromWrapper->mCSSValue.IsNull(),
                       "If property ID is unset, then the unit should be, too");
     fromCSSValue = GetZeroValueForUnit(toWrapper->mCSSValue.GetUnit());
   } else {
     fromCSSValue = &fromWrapper->mCSSValue;
   }
   NS_ABORT_IF_FALSE(toWrapper->mPropID != eCSSProperty_UNKNOWN &&
@@ -250,17 +252,17 @@ nsSMILCSSValueType::Interpolate(const ns
 
   const ValueWrapper* startWrapper = ExtractValueWrapper(aStartVal);
   const ValueWrapper* endWrapper = ExtractValueWrapper(aEndVal);
   ValueWrapper* resultWrapper = ExtractValueWrapper(aResult);
 
   NS_ABORT_IF_FALSE(startWrapper && endWrapper && resultWrapper,
                     "These pointers shouldn't be null");
 
-  const nsStyleCoord* startCSSValue;
+  const nsStyleAnimation::Value* startCSSValue;
   if (startWrapper->mPropID == eCSSProperty_UNKNOWN) {
     NS_ABORT_IF_FALSE(startWrapper->mCSSValue.IsNull(),
                       "If property ID is unset, then the unit should be, too");
     startCSSValue = GetZeroValueForUnit(endWrapper->mCSSValue.GetUnit());
   } else {
     startCSSValue = &startWrapper->mCSSValue;
   }
   NS_ABORT_IF_FALSE(endWrapper->mPropID != eCSSProperty_UNKNOWN &&
@@ -304,30 +306,31 @@ nsSMILCSSValueType::ValueFromString(nsCS
   nsDependentSubstring subString(aString, subStringBegin);
   ValueWrapper* wrapper = ExtractValueWrapper(aValue);
   NS_ABORT_IF_FALSE(wrapper, "Wrapper should be non-null if type is set.");
 
   if (nsStyleAnimation::ComputeValue(aPropID, aTargetElement,
                                      subString, wrapper->mCSSValue)) {
     wrapper->mPropID = aPropID;
     if (isNegative) {
-      InvertStyleCoordSign(wrapper->mCSSValue);
+      InvertSign(wrapper->mCSSValue);
     }
     // Cache a reference to the PresContext, if we've got one
     nsIDocument* doc = aTargetElement->GetCurrentDoc();
     NS_ABORT_IF_FALSE(doc, "active animations should only be able to "
                       "target elements that are in a document");
     nsIPresShell* shell = doc->GetPrimaryShell();
     if (shell) {
       wrapper->mPresContext = shell->GetPresContext();
     }
     if (wrapper->mPresContext) {
       // Divide out text-zoom, since SVG is supposed to ignore it
       if (aPropID == eCSSProperty_font_size) {
-        NS_ABORT_IF_FALSE(wrapper->mCSSValue.GetUnit() == eStyleUnit_Coord,
+        NS_ABORT_IF_FALSE(wrapper->mCSSValue.GetUnit() ==
+                            nsStyleAnimation::eUnit_Coord,
                           "'font-size' value with unexpected style unit");
         wrapper->mCSSValue.SetCoordValue(wrapper->mCSSValue.GetCoordValue() /
                                          wrapper->mPresContext->TextZoom());
       }
       return PR_TRUE;
     }
     // Crap! We lack a PresContext or a PresShell
     NS_NOTREACHED("Not parsing animation value; unable to get PresContext");
--- a/layout/style/nsStyleAnimation.cpp
+++ b/layout/style/nsStyleAnimation.cpp
@@ -39,17 +39,16 @@
 
 /* Utilities for animation of computed style values */
 
 #include "nsStyleAnimation.h"
 #include "nsCOMArray.h"
 #include "nsIStyleRule.h"
 #include "nsICSSStyleRule.h"
 #include "nsString.h"
-#include "nsStyleCoord.h"
 #include "nsStyleContext.h"
 #include "nsStyleSet.h"
 #include "nsComputedDOMStyle.h"
 #include "nsICSSParser.h"
 #include "nsICSSLoader.h"
 #include "nsCSSDataBlock.h"
 #include "nsCSSDeclaration.h"
 #include "prlog.h"
@@ -59,34 +58,34 @@
 // --------------
 /*
  * Given two units, this method returns a common unit that they can both be
  * converted into, if possible.  This is intended to facilitate
  * interpolation, distance-computation, and addition between "similar" units.
  *
  * The ordering of the arguments should not affect the output of this method.
  *
- * If there's no sensible common unit, this method returns eStyleUnit_Null.
+ * If there's no sensible common unit, this method returns eUnit_Null.
  *
  * @param   aFirstUnit One unit to resolve.
  * @param   aFirstUnit The other unit to resolve.
  * @return  A "common" unit that both source units can be converted into, or
- *          eStyleUnit_Null if that's not possible.
+ *          eUnit_Null if that's not possible.
  */
 static
-nsStyleUnit
-GetCommonUnit(nsStyleUnit aFirstUnit,
-              nsStyleUnit aSecondUnit)
+nsStyleAnimation::Unit
+GetCommonUnit(nsStyleAnimation::Unit aFirstUnit,
+              nsStyleAnimation::Unit aSecondUnit)
 {
   // XXXdholbert Naive implementation for now: simply require that the input
   // units match.
   if (aFirstUnit != aSecondUnit) {
     // NOTE: Some unit-pairings will need special handling,
     // e.g. percent vs coord (bug 520234)
-    return eStyleUnit_Null;
+    return nsStyleAnimation::eUnit_Null;
   }
   return aFirstUnit;
 }
 
 // CLASS METHODS
 // -------------
 
 #define MAX_PACKED_COLOR_COMPONENT 255
@@ -94,45 +93,44 @@ GetCommonUnit(nsStyleUnit aFirstUnit,
 inline PRUint8 ClampColor(PRUint32 aColor)
 {
   if (aColor >= MAX_PACKED_COLOR_COMPONENT)
     return MAX_PACKED_COLOR_COMPONENT;
   return aColor;
 }
 
 PRBool
-nsStyleAnimation::Add(nsStyleCoord& aDest, const nsStyleCoord& aValueToAdd,
+nsStyleAnimation::Add(Value& aDest, const Value& aValueToAdd,
                       PRUint32 aCount)
 {
-  nsStyleUnit commonUnit = GetCommonUnit(aDest.GetUnit(),
-                                         aValueToAdd.GetUnit());
+  Unit commonUnit = GetCommonUnit(aDest.GetUnit(), aValueToAdd.GetUnit());
   PRBool success = PR_TRUE;
   switch (commonUnit) {
-    case eStyleUnit_Coord: {
+    case eUnit_Coord: {
       nscoord destCoord = aDest.GetCoordValue();
       nscoord valueToAddCoord = aValueToAdd.GetCoordValue();
       destCoord += aCount * valueToAddCoord;
       aDest.SetCoordValue(destCoord);
       break;
     }
-    case eStyleUnit_Percent: {
+    case eUnit_Percent: {
       float destPct = aDest.GetPercentValue();
       float valueToAddPct = aValueToAdd.GetPercentValue();
       destPct += aCount * valueToAddPct;
       aDest.SetPercentValue(destPct);
       break;
     }
-    case eStyleUnit_Factor: {
-      float destFactor = aDest.GetFactorValue();
-      float valueToAddFactor = aValueToAdd.GetFactorValue();
-      destFactor += aCount * valueToAddFactor;
-      aDest.SetFactorValue(destFactor);
+    case eUnit_Float: {
+      float destFloat = aDest.GetFloatValue();
+      float valueToAddFloat = aValueToAdd.GetFloatValue();
+      destFloat += aCount * valueToAddFloat;
+      aDest.SetFloatValue(destFloat);
       break;
     }
-    case eStyleUnit_Color: {
+    case eUnit_Color: {
       // Since nscolor doesn't allow out-of-sRGB values, by-animations
       // of colors don't make much sense in our implementation.
       // FIXME (bug 515919): Animation of colors should really use
       // floating point colors (and when it does, ClampColor and the
       // clamping of aCount should go away).
       // Also, given RGBA colors, it's not clear whether we want
       // premultiplication.  Probably we don't, given that's hard to
       // premultiply aValueToAdd since it's a difference rather than a
@@ -151,56 +149,55 @@ nsStyleAnimation::Add(nsStyleCoord& aDes
         ClampColor(NS_GET_G(destColor) + aCount * NS_GET_G(colorToAdd));
       PRUint8 resultB =
         ClampColor(NS_GET_B(destColor) + aCount * NS_GET_B(colorToAdd));
       PRUint8 resultA =
         ClampColor(NS_GET_A(destColor) + aCount * NS_GET_A(colorToAdd));
       aDest.SetColorValue(NS_RGBA(resultR, resultG, resultB, resultA));
       break;
     }
-    case eStyleUnit_Null:
+    case eUnit_Null:
       success = PR_FALSE;
       break;
     default:
-      NS_NOTREACHED("Can't add nsStyleCoords using the given common unit");
+      NS_NOTREACHED("Can't add Values using the given common unit");
       success = PR_FALSE;
       break;
   }
   return success;
 }
 
 PRBool
-nsStyleAnimation::ComputeDistance(const nsStyleCoord& aStartValue,
-                                  const nsStyleCoord& aEndValue,
+nsStyleAnimation::ComputeDistance(const Value& aStartValue,
+                                  const Value& aEndValue,
                                   double& aDistance)
 {
-  nsStyleUnit commonUnit = GetCommonUnit(aStartValue.GetUnit(),
-                                         aEndValue.GetUnit());
+  Unit commonUnit = GetCommonUnit(aStartValue.GetUnit(), aEndValue.GetUnit());
 
   PRBool success = PR_TRUE;
   switch (commonUnit) {
-    case eStyleUnit_Coord: {
+    case eUnit_Coord: {
       nscoord startCoord = aStartValue.GetCoordValue();
       nscoord endCoord = aEndValue.GetCoordValue();
       aDistance = fabs(double(endCoord - startCoord));
       break;
     }
-    case eStyleUnit_Percent: {
+    case eUnit_Percent: {
       float startPct = aStartValue.GetPercentValue();
       float endPct = aEndValue.GetPercentValue();
       aDistance = fabs(double(endPct - startPct));
       break;
     }
-    case eStyleUnit_Factor: {
-      float startFactor = aStartValue.GetFactorValue();
-      float endFactor = aEndValue.GetFactorValue();
-      aDistance = fabs(double(endFactor - startFactor));
+    case eUnit_Float: {
+      float startFloat = aStartValue.GetFloatValue();
+      float endFloat = aEndValue.GetFloatValue();
+      aDistance = fabs(double(endFloat - startFloat));
       break;
     }
-    case eStyleUnit_Color: {
+    case eUnit_Color: {
       // http://www.w3.org/TR/smil-animation/#animateColorElement says
       // that we should use Euclidean RGB cube distance.  However, we
       // have to extend that to RGBA.  For now, we'll just use the
       // Euclidean distance in the (part of the) 4-cube of premultiplied
       // colors.
       // FIXME (spec): The CSS transitions spec doesn't say whether
       // colors are premultiplied, but things work better when they are,
       // so use premultiplication.  Spec issue is still open per
@@ -227,67 +224,66 @@ nsStyleAnimation::ComputeDistance(const 
       double diffA = startA - endA;
       double diffR = startR - endR;
       double diffG = startG - endG;
       double diffB = startB - endB;
       aDistance = sqrt(diffA * diffA + diffR * diffR +
                        diffG * diffG + diffB * diffB);
       break;
     }
-    case eStyleUnit_Null:
+    case eUnit_Null:
       success = PR_FALSE;
       break;
     default:
       NS_NOTREACHED("Can't compute distance using the given common unit");
       success = PR_FALSE;
       break;
   }
   return success;
 }
 
 PRBool
-nsStyleAnimation::Interpolate(const nsStyleCoord& aStartValue,
-                              const nsStyleCoord& aEndValue,
+nsStyleAnimation::Interpolate(const Value& aStartValue,
+                              const Value& aEndValue,
                               double aPortion,
-                              nsStyleCoord& aResultValue)
+                              Value& aResultValue)
 {
   NS_ABORT_IF_FALSE(aPortion >= 0.0 && aPortion <= 1.0,
                     "aPortion out of bounds");
-  nsStyleUnit commonUnit = GetCommonUnit(aStartValue.GetUnit(),
-                                         aEndValue.GetUnit());
+  Unit commonUnit = GetCommonUnit(aStartValue.GetUnit(), aEndValue.GetUnit());
   // Maybe need a followup method to convert the inputs into the common
   // unit-type, if they don't already match it. (Or would it make sense to do
   // that in GetCommonUnit? in which case maybe ConvertToCommonUnit would be
   // better.)
 
   PRBool success = PR_TRUE;
   switch (commonUnit) {
-    case eStyleUnit_Coord: {
+    case eUnit_Coord: {
       nscoord startCoord = aStartValue.GetCoordValue();
       nscoord endCoord = aEndValue.GetCoordValue();
       nscoord resultCoord = startCoord +
         NSToCoordRound(aPortion * (endCoord - startCoord));
       aResultValue.SetCoordValue(resultCoord);
       break;
     }
-    case eStyleUnit_Percent: {
+    case eUnit_Percent: {
       float startPct = aStartValue.GetPercentValue();
       float endPct = aEndValue.GetPercentValue();
       float resultPct = startPct + aPortion * (endPct - startPct);
       aResultValue.SetPercentValue(resultPct);
       break;
     }
-    case eStyleUnit_Factor: {
-      float startFactor = aStartValue.GetFactorValue();
-      float endFactor = aEndValue.GetFactorValue();
-      float resultFactor = startFactor + aPortion * (endFactor - startFactor);
-      aResultValue.SetFactorValue(resultFactor);
+    case eUnit_Float: {
+      float startFloat = aStartValue.GetFloatValue();
+      float endFloat = aEndValue.GetFloatValue();
+      float resultFloat = startFloat + aPortion * (endFloat - startFloat);
+      aResultValue.SetFloatValue(resultFloat);
       break;
     }
-    case eStyleUnit_Color: {
+    case eUnit_Color: {
       double inv = 1.0 - aPortion;
       nscolor startColor = aStartValue.GetColorValue();
       nscolor endColor = aEndValue.GetColorValue();
       // FIXME (spec): The CSS transitions spec doesn't say whether
       // colors are premultiplied, but things work better when they are,
       // so use premultiplication.  Spec issue is still open per
       // http://lists.w3.org/Archives/Public/www-style/2009Jul/0050.html
 
@@ -311,17 +307,17 @@ nsStyleAnimation::Interpolate(const nsSt
         PRUint8 resR = NSToIntRound((startR * inv + endR * aPortion) * factor);
         PRUint8 resG = NSToIntRound((startG * inv + endG * aPortion) * factor);
         PRUint8 resB = NSToIntRound((startB * inv + endB * aPortion) * factor);
         resultColor = NS_RGBA(resR, resG, resB, resA);
       }
       aResultValue.SetColorValue(resultColor);
       break;
     }
-    case eStyleUnit_Null:
+    case eUnit_Null:
       success = PR_FALSE;
       break;
     default:
       NS_NOTREACHED("Can't interpolate using the given common unit");
       success = PR_FALSE;
       break;
   }
   return success;
@@ -379,17 +375,17 @@ LookupStyleContext(nsIContent* aElement)
   }
   return nsComputedDOMStyle::GetStyleContextForContent(aElement, nsnull, shell);
 }
 
 PRBool
 nsStyleAnimation::ComputeValue(nsCSSProperty aProperty,
                                nsIContent* aTargetElement,
                                const nsAString& aSpecifiedValue,
-                               nsStyleCoord& aComputedValue)
+                               Value& aComputedValue)
 {
   NS_ABORT_IF_FALSE(aTargetElement, "null target element");
   NS_ABORT_IF_FALSE(aTargetElement->GetCurrentDoc(),
                     "we should only be able to actively animate nodes that "
                     "are in a document");
 
   // Look up style context for our target element
   nsRefPtr<nsStyleContext> styleContext = LookupStyleContext(aTargetElement);
@@ -415,56 +411,56 @@ nsStyleAnimation::ComputeValue(nsCSSProp
 
   // Extract computed value of our property from the temporary style rule
   return ExtractComputedValue(aProperty, tmpStyleContext, aComputedValue);
 }
 
 PRBool
 nsStyleAnimation::UncomputeValue(nsCSSProperty aProperty,
                                  nsPresContext* aPresContext,
-                                 const nsStyleCoord& aComputedValue,
+                                 const Value& aComputedValue,
                                  void* aSpecifiedValue)
 {
   NS_ABORT_IF_FALSE(aPresContext, "null pres context");
 
   switch (aComputedValue.GetUnit()) {
-    case eStyleUnit_None:
+    case eUnit_None:
       if (nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_PaintServer) {
         NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] ==
                             eCSSType_ValuePair, "type mismatch");
         static_cast<nsCSSValuePair*>(aSpecifiedValue)->
           SetBothValuesTo(nsCSSValue(eCSSUnit_None));
       } else {
         NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
                           "type mismatch");
         static_cast<nsCSSValue*>(aSpecifiedValue)->SetNoneValue();
       }
       break;
-    case eStyleUnit_Coord: {
+    case eUnit_Coord: {
       NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
                         "type mismatch");
       float pxVal = aPresContext->AppUnitsToFloatCSSPixels(
                                     aComputedValue.GetCoordValue());
       static_cast<nsCSSValue*>(aSpecifiedValue)->
         SetFloatValue(pxVal, eCSSUnit_Pixel);
       break;
     }
-    case eStyleUnit_Percent:
+    case eUnit_Percent:
       NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
                         "type mismatch");
       static_cast<nsCSSValue*>(aSpecifiedValue)->
         SetPercentValue(aComputedValue.GetPercentValue());
       break;
-    case eStyleUnit_Factor:
+    case eUnit_Float:
       NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
                         "type mismatch");
       static_cast<nsCSSValue*>(aSpecifiedValue)->
-        SetFloatValue(aComputedValue.GetFactorValue(), eCSSUnit_Number);
+        SetFloatValue(aComputedValue.GetFloatValue(), eCSSUnit_Number);
       break;
-    case eStyleUnit_Color:
+    case eUnit_Color:
       // colors can be alone, or part of a paint server
       if (nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_PaintServer) {
         NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] ==
                             eCSSType_ValuePair, "type mismatch");
         nsCSSValue val;
         val.SetColorValue(aComputedValue.GetColorValue());
         static_cast<nsCSSValuePair*>(aSpecifiedValue)->
           SetBothValuesTo(val);
@@ -479,17 +475,17 @@ nsStyleAnimation::UncomputeValue(nsCSSPr
       return PR_FALSE;
   }
   return PR_TRUE;
 }
 
 PRBool
 nsStyleAnimation::UncomputeValue(nsCSSProperty aProperty,
                                  nsPresContext* aPresContext,
-                                 const nsStyleCoord& aComputedValue,
+                                 const Value& aComputedValue,
                                  nsAString& aSpecifiedValue)
 {
   NS_ABORT_IF_FALSE(aPresContext, "null pres context");
   aSpecifiedValue.Truncate(); // Clear outparam, if it's not already empty
 
   nsCSSValuePair vp;
   nsCSSRect rect;
   void *ptr = nsnull;
@@ -532,33 +528,64 @@ StyleDataAtOffset(const void* aStyleStru
 inline void*
 StyleDataAtOffset(void* aStyleStruct, ptrdiff_t aOffset)
 {
   return reinterpret_cast<char*>(aStyleStruct) + aOffset;
 }
 
 static void
 ExtractBorderColor(nsStyleContext* aStyleContext, const void* aStyleBorder,
-                   PRUint8 aSide, nsStyleCoord& aComputedValue)
+                   PRUint8 aSide, nsStyleAnimation::Value& aComputedValue)
 {
   nscolor color; 
   PRBool foreground;
   static_cast<const nsStyleBorder*>(aStyleBorder)->
     GetBorderColor(aSide, color, foreground);
   if (foreground) {
     // FIXME: should add test for this
     color = aStyleContext->GetStyleColor()->mColor;
   }
   aComputedValue.SetColorValue(color);
 }
 
+static PRBool
+StyleCoordToValue(const nsStyleCoord& aCoord, nsStyleAnimation::Value& aValue)
+{
+  switch (aCoord.GetUnit()) {
+    case eStyleUnit_Null:
+      return PR_FALSE;
+    case eStyleUnit_Normal:
+      aValue.SetNormalValue();
+      break;
+    case eStyleUnit_Auto:
+      aValue.SetAutoValue();
+      break;
+    case eStyleUnit_None:
+      aValue.SetNoneValue();
+      break;
+    case eStyleUnit_Percent:
+      aValue.SetPercentValue(aCoord.GetPercentValue());
+      break;
+    case eStyleUnit_Factor:
+      aValue.SetFloatValue(aCoord.GetFactorValue());
+      break;
+    case eStyleUnit_Coord:
+      aValue.SetCoordValue(aCoord.GetCoordValue());
+      break;
+    case eStyleUnit_Integer:
+    case eStyleUnit_Enumerated:
+      return PR_FALSE;
+  }
+  return PR_TRUE;
+}
+
 PRBool
 nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
                                        nsStyleContext* aStyleContext,
-                                       nsStyleCoord& aComputedValue)
+                                       Value& aComputedValue)
 {
   NS_ABORT_IF_FALSE(0 <= aProperty &&
                     aProperty < eCSSProperty_COUNT_no_shorthands,
                     "bad property");
   const void* styleStruct =
     aStyleContext->GetStyleData(nsCSSProps::kSIDTable[aProperty]);
   ptrdiff_t ssOffset = nsCSSProps::kStyleStructOffsetTable[aProperty];
   nsStyleAnimType animType = nsCSSProps::kAnimTypeTable[aProperty];
@@ -615,43 +642,43 @@ nsStyleAnimation::ExtractComputedValue(n
         }
 
         default:
           NS_ABORT_IF_FALSE(PR_FALSE, "missing property implementation");
           return PR_FALSE;
       };
       return PR_TRUE;
     case eStyleAnimType_Coord:
-      aComputedValue = *static_cast<const nsStyleCoord*>(
-        StyleDataAtOffset(styleStruct, ssOffset));
-      return PR_TRUE;
+      return StyleCoordToValue(*static_cast<const nsStyleCoord*>(
+        StyleDataAtOffset(styleStruct, ssOffset)), aComputedValue);
     case eStyleAnimType_Sides_Top:
     case eStyleAnimType_Sides_Right:
     case eStyleAnimType_Sides_Bottom:
-    case eStyleAnimType_Sides_Left:
+    case eStyleAnimType_Sides_Left: {
       PR_STATIC_ASSERT(0 == NS_SIDE_TOP);
       PR_STATIC_ASSERT(eStyleAnimType_Sides_Right - eStyleAnimType_Sides_Top
                          == NS_SIDE_RIGHT);
       PR_STATIC_ASSERT(eStyleAnimType_Sides_Bottom - eStyleAnimType_Sides_Top
                          == NS_SIDE_BOTTOM);
       PR_STATIC_ASSERT(eStyleAnimType_Sides_Left - eStyleAnimType_Sides_Top
                          == NS_SIDE_LEFT);
-      aComputedValue = static_cast<const nsStyleSides*>(
+      const nsStyleCoord &coord = static_cast<const nsStyleSides*>(
         StyleDataAtOffset(styleStruct, ssOffset))->
           Get(animType - eStyleAnimType_Sides_Top);
-      return PR_TRUE;
+      return StyleCoordToValue(coord, aComputedValue);
+    }
     case eStyleAnimType_nscoord:
       aComputedValue.SetCoordValue(*static_cast<const nscoord*>(
         StyleDataAtOffset(styleStruct, ssOffset)));
       return PR_TRUE;
     case eStyleAnimType_float:
-      aComputedValue.SetFactorValue(*static_cast<const float*>(
+      aComputedValue.SetFloatValue(*static_cast<const float*>(
         StyleDataAtOffset(styleStruct, ssOffset)));
       if (aProperty == eCSSProperty_font_size_adjust &&
-          aComputedValue.GetFactorValue() == 0.0f) {
+          aComputedValue.GetFloatValue() == 0.0f) {
         // In nsStyleFont, we set mFont.sizeAdjust to 0 to represent
         // font-size-adjust: none.  Here, we have to treat this as a keyword
         // instead of a float value, to make sure we don't end up doing
         // interpolation with it.
         aComputedValue.SetNoneValue();
       }
       return PR_TRUE;
     case eStyleAnimType_Color:
@@ -672,8 +699,144 @@ nsStyleAnimation::ExtractComputedValue(n
       }
       return PR_FALSE;
     }
     case eStyleAnimType_None:
       NS_NOTREACHED("shouldn't use on non-animatable properties");
   }
   return PR_FALSE;
 }
+
+nsStyleAnimation::Value::Value(nscoord aLength, CoordConstructorType)
+{
+  mUnit = eUnit_Coord;
+  mValue.mCoord = aLength;
+}
+
+nsStyleAnimation::Value::Value(float aPercent, PercentConstructorType)
+{
+  mUnit = eUnit_Percent;
+  mValue.mFloat = aPercent;
+}
+
+nsStyleAnimation::Value::Value(float aFloat, FloatConstructorType)
+{
+  mUnit = eUnit_Float;
+  mValue.mFloat = aFloat;
+}
+
+nsStyleAnimation::Value::Value(nscolor aColor, ColorConstructorType)
+{
+  mUnit = eUnit_Color;
+  mValue.mColor = aColor;
+}
+
+nsStyleAnimation::Value&
+nsStyleAnimation::Value::operator=(const Value& aOther)
+{
+  FreeValue();
+
+  mUnit = aOther.mUnit;
+  switch (mUnit) {
+    case eUnit_Null:
+    case eUnit_Normal:
+    case eUnit_Auto:
+    case eUnit_None:
+      break;
+    case eUnit_Coord:
+      mValue.mCoord = aOther.mValue.mCoord;
+      break;
+    case eUnit_Percent:
+    case eUnit_Float:
+      mValue.mFloat = aOther.mValue.mFloat;
+      break;
+    case eUnit_Color:
+      mValue.mColor = aOther.mValue.mColor;
+      break;
+  }
+
+  return *this;
+}
+
+void
+nsStyleAnimation::Value::SetNormalValue()
+{
+  FreeValue();
+  mUnit = eUnit_Normal;
+}
+
+void
+nsStyleAnimation::Value::SetAutoValue()
+{
+  FreeValue();
+  mUnit = eUnit_Auto;
+}
+
+void
+nsStyleAnimation::Value::SetNoneValue()
+{
+  FreeValue();
+  mUnit = eUnit_None;
+}
+
+void
+nsStyleAnimation::Value::SetCoordValue(nscoord aLength)
+{
+  FreeValue();
+  mUnit = eUnit_Coord;
+  mValue.mCoord = aLength;
+}
+
+void
+nsStyleAnimation::Value::SetPercentValue(float aPercent)
+{
+  FreeValue();
+  mUnit = eUnit_Percent;
+  mValue.mFloat = aPercent;
+}
+
+void
+nsStyleAnimation::Value::SetFloatValue(float aFloat)
+{
+  FreeValue();
+  mUnit = eUnit_Float;
+  mValue.mFloat = aFloat;
+}
+
+void
+nsStyleAnimation::Value::SetColorValue(nscolor aColor)
+{
+  FreeValue();
+  mUnit = eUnit_Color;
+  mValue.mColor = aColor;
+}
+
+void
+nsStyleAnimation::Value::FreeValue()
+{
+}
+
+PRBool
+nsStyleAnimation::Value::operator==(const Value& aOther) const
+{
+  if (mUnit != aOther.mUnit) {
+    return PR_FALSE;
+  }
+
+  switch (mUnit) {
+    case eUnit_Null:
+    case eUnit_Normal:
+    case eUnit_Auto:
+    case eUnit_None:
+      return PR_TRUE;
+    case eUnit_Coord:
+      return mValue.mCoord == aOther.mValue.mCoord;
+    case eUnit_Percent:
+    case eUnit_Float:
+      return mValue.mFloat == aOther.mValue.mFloat;
+    case eUnit_Color:
+      return mValue.mColor == aOther.mValue.mColor;
+  }
+
+  NS_NOTREACHED("incomplete case");
+  return PR_FALSE;
+}
+
--- a/layout/style/nsStyleAnimation.h
+++ b/layout/style/nsStyleAnimation.h
@@ -40,61 +40,63 @@
 /* Utilities for animation of computed style values */
 
 #ifndef nsStyleAnimation_h_
 #define nsStyleAnimation_h_
 
 #include "prtypes.h"
 #include "nsAString.h"
 #include "nsCSSProperty.h"
+#include "nsCoord.h"
+#include "nsColor.h"
 
 class nsCSSDeclaration;
 class nsIContent;
 class nsPresContext;
-class nsStyleCoord;
 class nsStyleContext;
 
 /**
  * Utility class to handle animated style values
  */
 class nsStyleAnimation {
 public:
+  class Value;
 
   // Mathematical methods
   // --------------------
   /**
    * Adds |aCount| copies of |aValueToAdd| to |aDest|.  The result of this
    * addition is stored in aDest.
    *
    * Note that if |aCount| is 0, then |aDest| will be unchanged.  Also, if
    * this method fails, then |aDest| will be unchanged.
    *
    * @param aDest       The value to add to.
    * @param aValueToAdd The value to add.
    * @param aCount      The number of times to add aValueToAdd.
    * @return PR_TRUE on success, PR_FALSE on failure.
    */
-  static PRBool Add(nsStyleCoord& aDest, const nsStyleCoord& aValueToAdd,
+  static PRBool Add(Value& aDest, const Value& aValueToAdd,
                     PRUint32 aCount);
 
   /**
    * Calculates a measure of 'distance' between two values.
    *
    * If this method succeeds, the returned distance value is guaranteed to be
    * non-negative.
    *
    * @param aStartValue The start of the interval for which the distance
    *                    should be calculated.
    * @param aEndValue   The end of the interval for which the distance
    *                    should be calculated.
    * @param aDistance   The result of the calculation.
    * @return PR_TRUE on success, PR_FALSE on failure.
    */
-  static PRBool ComputeDistance(const nsStyleCoord& aStartValue,
-                                const nsStyleCoord& aEndValue,
+  static PRBool ComputeDistance(const Value& aStartValue,
+                                const Value& aEndValue,
                                 double& aDistance);
 
   /**
    * Calculates an interpolated value that is the specified |aPortion| between
    * the two given values.
    *
    * This really just does the following calculation:
    *   aResultValue = (1.0 - aPortion) * aStartValue + aPortion * aEndValue
@@ -103,25 +105,25 @@ public:
    *                    interpolation.
    * @param aEndValue   The value defining the end of the interval of
    *                    interpolation.
    * @param aPortion    A number in the range [0.0, 1.0] defining the
    *                    distance of the interpolated value in the interval.
    * @param [out] aResultValue The resulting interpolated value.
    * @return PR_TRUE on success, PR_FALSE on failure.
    */
-  static PRBool Interpolate(const nsStyleCoord& aStartValue,
-                            const nsStyleCoord& aEndValue,
+  static PRBool Interpolate(const Value& aStartValue,
+                            const Value& aEndValue,
                             double aPortion,
-                            nsStyleCoord& aResultValue);
+                            Value& aResultValue);
 
   // Type-conversion methods
   // -----------------------
   /**
-   * Creates a computed value (nsStyleCoord) for the given specified value
+   * Creates a computed value for the given specified value
    * (property ID + string).  A style context is needed in case the
    * specified value depends on inherited style or on the values of other
    * properties.
    * 
    * NOTE: This method uses GetPrimaryShell() to access the style system,
    * so it should only be used for style that applies to all presentations,
    * rather than for style that only applies to a particular presentation.
    * XXX Once we get rid of multiple presentations, we can remove the above
@@ -133,51 +135,136 @@ public:
    * @param aSpecifiedValue The specified value, from which we'll build our
    *                        computed value.
    * @param [out] aComputedValue The resulting computed value.
    * @return PR_TRUE on success, PR_FALSE on failure.
    */
   static PRBool ComputeValue(nsCSSProperty aProperty,
                              nsIContent* aElement,
                              const nsAString& aSpecifiedValue,
-                             nsStyleCoord& aComputedValue);
+                             Value& aComputedValue);
 
   /**
-   * Creates a specified value for the given computed value
-   * (nsStyleCoord).
+   * Creates a specified value for the given computed value.
    *
    * The first form fills in one of the nsCSSType types into the void*;
    * for some types this means that the void* is pointing to memory
-   * owned by the nsStyleCoord.  (For all complex types, the
-   * nsStyleCoord owns the necessary objects so that the caller does not
-   * need to do anything to free them.)
+   * owned by the nsStyleAnimation::Value.  (For all complex types, the
+   * nsStyleAnimation::Value owns the necessary objects so that the
+   * caller does not need to do anything to free them.)
    *
    * @param aProperty      The property whose value we're uncomputing.
    * @param aPresContext   The presentation context for the document in
    *                       which we're working.
    * @param aComputedValue The computed value to be converted.
    * @param [out] aSpecifiedValue The resulting specified value.
    * @return PR_TRUE on success, PR_FALSE on failure.
    */
   static PRBool UncomputeValue(nsCSSProperty aProperty,
                                nsPresContext* aPresContext,
-                               const nsStyleCoord& aComputedValue,
+                               const Value& aComputedValue,
                                void* aSpecifiedValue);
   static PRBool UncomputeValue(nsCSSProperty aProperty,
                                nsPresContext* aPresContext,
-                               const nsStyleCoord& aComputedValue,
+                               const Value& aComputedValue,
                                nsAString& aSpecifiedValue);
 
   /**
    * Gets the computed value for the given property from the given style
    * context.
    *
    * @param aProperty     The property whose value we're looking up.
    * @param aStyleContext The style context to check for the computed value.
    * @param [out] aComputedValue The resulting computed value.
    * @return PR_TRUE on success, PR_FALSE on failure.
    */
   static PRBool ExtractComputedValue(nsCSSProperty aProperty,
                                      nsStyleContext* aStyleContext,
-                                     nsStyleCoord& aComputedValue);
+                                     Value& aComputedValue);
+
+  /**
+   * The types and values for the values that we extract and animate.
+   */
+  enum Unit {
+    eUnit_Null, // not initialized
+    eUnit_Normal,
+    eUnit_Auto,
+    eUnit_None,
+    eUnit_Coord,
+    eUnit_Percent,
+    eUnit_Float,
+    eUnit_Color
+  };
+
+  class Value {
+  private:
+    Unit mUnit;
+    union {
+      nscoord mCoord;
+      float mFloat;
+      nscolor mColor;
+    } mValue;
+  public:
+    Unit GetUnit() const {
+      NS_ASSERTION(mUnit != eUnit_Null, "uninitialized");
+      return mUnit;
+    }
+
+    // Accessor to let us verify assumptions about presence of null unit,
+    // without tripping the assertion in GetUnit().
+    PRBool IsNull() const {
+      return mUnit == eUnit_Null;
+    }
+
+    nscoord GetCoordValue() const {
+      NS_ASSERTION(mUnit == eUnit_Coord, "unit mismatch");
+      return mValue.mCoord;
+    }
+    float GetPercentValue() const {
+      NS_ASSERTION(mUnit == eUnit_Percent, "unit mismatch");
+      return mValue.mFloat;
+    }
+    float GetFloatValue() const {
+      NS_ASSERTION(mUnit == eUnit_Float, "unit mismatch");
+      return mValue.mFloat;
+    }
+    nscolor GetColorValue() const {
+      NS_ASSERTION(mUnit == eUnit_Color, "unit mismatch");
+      return mValue.mColor;
+    }
+
+    explicit Value(Unit aUnit = eUnit_Null) : mUnit(aUnit) {
+      NS_ASSERTION(aUnit == eUnit_Null || aUnit == eUnit_Normal ||
+                   aUnit == eUnit_Auto || aUnit == eUnit_None,
+                   "must be valueless unit");
+    }
+    Value(const Value& aOther) : mUnit(eUnit_Null) { *this = aOther; }
+    enum CoordConstructorType { CoordConstructor };
+    Value(nscoord aLength, CoordConstructorType);
+    enum PercentConstructorType { PercentConstructor };
+    Value(float aPercent, PercentConstructorType);
+    enum FloatConstructorType { FloatConstructor };
+    Value(float aFloat, FloatConstructorType);
+    enum ColorConstructorType { ColorConstructor };
+    Value(nscolor aColor, ColorConstructorType);
+
+    ~Value() { FreeValue(); }
+
+    void SetNormalValue();
+    void SetAutoValue();
+    void SetNoneValue();
+    void SetCoordValue(nscoord aCoord);
+    void SetPercentValue(float aPercent);
+    void SetFloatValue(float aFloat);
+    void SetColorValue(nscolor aColor);
+
+    Value& operator=(const Value& aOther);
+
+    PRBool operator==(const Value& aOther) const;
+    PRBool operator!=(const Value& aOther) const
+      { return !(*this == aOther); }
+
+  private:
+    void FreeValue();
+  };
 };
 
 #endif
--- a/layout/style/nsStyleCoord.cpp
+++ b/layout/style/nsStyleCoord.cpp
@@ -116,22 +116,16 @@ void nsStyleCoord::Reset(void)
 }
 
 void nsStyleCoord::SetCoordValue(nscoord aValue)
 {
   mUnit = eStyleUnit_Coord;
   mValue.mInt = aValue;
 }
 
-void nsStyleCoord::SetColorValue(nscolor aValue)
-{
-  mUnit = eStyleUnit_Color;
-  mValue.mColor = aValue;
-}
-
 void nsStyleCoord::SetIntValue(PRInt32 aValue, nsStyleUnit aUnit)
 {
   NS_ASSERTION((aUnit == eStyleUnit_Enumerated) ||
                (aUnit == eStyleUnit_Integer), "not an int value");
   if ((aUnit == eStyleUnit_Enumerated) ||
       (aUnit == eStyleUnit_Integer)) {
     mUnit = aUnit;
     mValue.mInt = aValue;
--- a/layout/style/nsStyleCoord.h
+++ b/layout/style/nsStyleCoord.h
@@ -37,38 +37,35 @@
 
 /* representation of length values in computed style data */
 
 #ifndef nsStyleCoord_h___
 #define nsStyleCoord_h___
 
 #include "nscore.h"
 #include "nsCoord.h"
-#include "nsColor.h"
 #include "nsCRT.h"
 #include "nsStyleConsts.h"
 class nsString;
 
 enum nsStyleUnit {
   eStyleUnit_Null         = 0,      // (no value) value is not specified
   eStyleUnit_Normal       = 1,      // (no value)
   eStyleUnit_Auto         = 2,      // (no value)
   eStyleUnit_None         = 3,      // (no value)
   eStyleUnit_Percent      = 10,     // (float) 1.0 == 100%
   eStyleUnit_Factor       = 11,     // (float) a multiplier
   eStyleUnit_Coord        = 20,     // (nscoord) value is twips
   eStyleUnit_Integer      = 30,     // (int) value is simple integer
-  eStyleUnit_Enumerated   = 32,     // (int) value has enumerated meaning
-  eStyleUnit_Color        = 40      // (nscolor)
+  eStyleUnit_Enumerated   = 32      // (int) value has enumerated meaning
 };
 
 typedef union {
   PRInt32     mInt;   // nscoord is a PRInt32 for now
   float       mFloat;
-  nscolor     mColor;
 } nsStyleUnion;
 
 /**
  * Class that hold a single size specification used by the style
  * system.  The size specification consists of two parts -- a number
  * and a unit.  The number is an integer, a floating point value, an
  * nscoord, or undefined, and the unit is an nsStyleUnit.  Checking
  * the unit is a must before asking for the value in any particular
@@ -76,52 +73,42 @@ typedef union {
  */
 class nsStyleCoord {
 public:
   nsStyleCoord(nsStyleUnit aUnit = eStyleUnit_Null);
   enum CoordConstructorType { CoordConstructor };
   inline nsStyleCoord(nscoord aValue, CoordConstructorType);
   nsStyleCoord(PRInt32 aValue, nsStyleUnit aUnit);
   nsStyleCoord(float aValue, nsStyleUnit aUnit);
-  enum ColorConstructorType { ColorConstructor };
-  inline nsStyleCoord(nscolor aValue, ColorConstructorType);
   inline nsStyleCoord(const nsStyleCoord& aCopy);
   inline nsStyleCoord(const nsStyleUnion& aValue, nsStyleUnit aUnit);
 
   nsStyleCoord&  operator=(const nsStyleCoord& aCopy);
   PRBool         operator==(const nsStyleCoord& aOther) const;
   PRBool         operator!=(const nsStyleCoord& aOther) const;
 
   nsStyleUnit GetUnit(void) const {
     NS_ASSERTION(mUnit != eStyleUnit_Null, "reading uninitialized value");
     return mUnit;
   }
 
-  // Accessor to let us verify assumptions about presence of null unit,
-  // without tripping the assertion in GetUnit().
-  PRBool IsNull() const {
-    return mUnit == eStyleUnit_Null;
-  }
-
   nscoord     GetCoordValue(void) const;
   PRInt32     GetIntValue(void) const;
   float       GetPercentValue(void) const;
   float       GetFactorValue(void) const;
-  nscolor     GetColorValue() const;
   void        GetUnionValue(nsStyleUnion& aValue) const;
 
   void  Reset(void);  // sets to null
   void  SetCoordValue(nscoord aValue);
   void  SetIntValue(PRInt32 aValue, nsStyleUnit aUnit);
   void  SetPercentValue(float aValue);
   void  SetFactorValue(float aValue);
   void  SetNormalValue(void);
   void  SetAutoValue(void);
   void  SetNoneValue(void);
-  void  SetColorValue(nscolor aValue);
 
 public:
   nsStyleUnit   mUnit;
   nsStyleUnion  mValue;
 };
 
 
 /**
@@ -197,22 +184,16 @@ protected:
 // nsStyleCoord inlines
 //
 inline nsStyleCoord::nsStyleCoord(nscoord aValue, CoordConstructorType)
   : mUnit(eStyleUnit_Coord)
 {
   mValue.mInt = aValue;
 }
 
-inline nsStyleCoord::nsStyleCoord(nscolor aValue, ColorConstructorType)
-  : mUnit(eStyleUnit_Color)
-{
-  mValue.mColor = aValue;
-}
-
 inline nsStyleCoord::nsStyleCoord(const nsStyleCoord& aCopy)
   : mUnit(aCopy.mUnit)
 {
   if ((eStyleUnit_Percent <= mUnit) && (mUnit < eStyleUnit_Coord)) {
     mValue.mFloat = aCopy.mValue.mFloat;
   }
   else {
     mValue.mInt = aCopy.mValue.mInt;
@@ -267,25 +248,16 @@ inline float nsStyleCoord::GetFactorValu
 {
   NS_ASSERTION(mUnit == eStyleUnit_Factor, "not a factor value");
   if (mUnit == eStyleUnit_Factor) {
     return mValue.mFloat;
   }
   return 0.0f;
 }
 
-inline nscolor nsStyleCoord::GetColorValue() const
-{
-  NS_ASSERTION((mUnit == eStyleUnit_Color), "not a color value");
-  if (mUnit == eStyleUnit_Color) {
-    return mValue.mColor;
-  }
-  return NS_RGBA(0, 0, 0, 0);
-}
-
 inline void nsStyleCoord::GetUnionValue(nsStyleUnion& aValue) const
 {
   memcpy(&aValue, &mValue, sizeof(nsStyleUnion));
 }
 
 // -------------------------
 // nsStyleSides inlines
 //
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -59,17 +59,17 @@ using mozilla::TimeDuration;
 
 /*****************************************************************************
  * Per-Element data                                                          *
  *****************************************************************************/
 
 struct ElementPropertyTransition
 {
   nsCSSProperty mProperty;
-  nsStyleCoord mStartValue, mEndValue;
+  nsStyleAnimation::Value mStartValue, mEndValue;
   TimeStamp mStartTime; // actual start plus transition delay
 
   // data from the relevant nsTransition
   TimeDuration mDuration;
   nsSMILKeySpline mTimingFunction;
 };
 
 /**
@@ -124,25 +124,25 @@ public:
 
   // nsIStyleRule implementation
   NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
 #ifdef DEBUG
   NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
   NS_HIDDEN_(void) CoverValue(nsCSSProperty aProperty,
-                              nsStyleCoord &aStartValue)
+                              nsStyleAnimation::Value &aStartValue)
   {
     CoveredValue v = { aProperty, aStartValue };
     mCoveredValues.AppendElement(v);
   }
 
   struct CoveredValue {
     nsCSSProperty mProperty;
-    nsStyleCoord mCoveredValue;
+    nsStyleAnimation::Value mCoveredValue;
   };
 
 private:
   nsTArray<CoveredValue> mCoveredValues;
 };
 
 struct ElementTransitions : public PRCList
 {
@@ -222,17 +222,17 @@ ElementTransitionsStyleRule::MapRuleInfo
         (RefreshTime() - pt.mStartTime).ToSeconds() / pt.mDuration.ToSeconds();
       if (timePortion < 0.0)
         timePortion = 0.0; // use start value during transition-delay
       if (timePortion > 1.0)
         timePortion = 1.0; // we might be behind on flushing
 
       double valuePortion =
         pt.mTimingFunction.GetSplineValue(timePortion);
-      nsStyleCoord value;
+      nsStyleAnimation::Value value;
 #ifdef DEBUG
       PRBool ok =
 #endif
         nsStyleAnimation::Interpolate(pt.mStartValue, pt.mEndValue,
                                       valuePortion, value);
       NS_ABORT_IF_FALSE(ok, "could not interpolate values");
 
       void *prop =
@@ -489,17 +489,17 @@ nsTransitionManager::ConsiderStartingTra
     return;
   }
 
   if (nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) {
     return;
   }
 
   ElementPropertyTransition pt;
-  nsStyleCoord dummyValue;
+  nsStyleAnimation::Value dummyValue;
   // FIXME (Bug 522595): This call on the old style context gets
   // incorrect style data since we don't quite enforce style rule
   // immutability:  we didn't need to worry about callers calling
   // GetStyleData rather than PeekStyleData after a style rule becomes
   // "old" before transitions existed.
   PRBool shouldAnimate =
     nsStyleAnimation::ExtractComputedValue(aProperty, aOldStyleContext,
                                            pt.mStartValue) &&
@@ -550,17 +550,17 @@ nsTransitionManager::ConsiderStartingTra
   // been longer had it started from the endpoint of the currently
   // running transition.
   double durationFraction = 1.0;
 
   // We need to check two things if we have a currently running
   // transition for this property:  see durationFraction comment above
   // and the endpoint check below.
   if (currentIndex != nsTArray<ElementPropertyTransition>::NoIndex) {
-    const nsStyleCoord &endVal =
+    const nsStyleAnimation::Value &endVal =
       aElementTransitions->mPropertyTransitions[currentIndex].mEndValue;
 
     if (endVal == pt.mEndValue) {
       // If we got a style change that changed the value to the endpoint
       // of the currently running transition, we don't want to interrupt
       // its timing function.
       // But don't forget to restyle with animation so we show the
       // current transition.