Backout of 397749 - suspicion of talos regression.
authortor@cs.brown.edu
Fri, 05 Oct 2007 10:06:47 -0700
changeset 6665 c0ef978d8e12b4d8b10a4c75d03fccd1af3c5513
parent 6664 199b6f951c04e6dfdff456be9baaa45cb2ae1e31
child 6666 09ed469e7c18cb260a72c9d3eaf74b69eaab1c42
push idunknown
push userunknown
push dateunknown
bugs397749
milestone1.9a9pre
Backout of 397749 - suspicion of talos regression.
content/svg/content/src/Makefile.in
content/svg/content/src/nsSVGAngle.cpp
content/svg/content/src/nsSVGAngle.h
content/svg/content/src/nsSVGAnimatedAngle.cpp
content/svg/content/src/nsSVGAnimatedAngle.h
content/svg/content/src/nsSVGElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGEnum.cpp
content/svg/content/src/nsSVGEnum.h
content/svg/content/src/nsSVGMarkerElement.cpp
content/svg/content/src/nsSVGMarkerElement.h
content/svg/content/src/nsSVGSVGElement.cpp
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -66,16 +66,17 @@ REQUIRES	= xpcom \
 		  docshell \
 		  thebes
 
 CPPSRCS		= \
 		nsDOMSVGZoomEvent.cpp \
 		nsDOMSVGEvent.cpp \
 		nsSVGAElement.cpp \
 		nsSVGAngle.cpp \
+		nsSVGAnimatedAngle.cpp \
 		nsSVGAnimatedLengthList.cpp \
 		nsSVGAnimatedNumberList.cpp \
 		nsSVGAnimatedRect.cpp \
 		nsSVGAnimatedPreserveAspectRatio.cpp \
 		nsSVGAnimatedString.cpp \
 		nsSVGAnimatedTransformList.cpp \
 		nsSVGBoolean.cpp \
 		nsSVGCircleElement.cpp \
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -31,319 +31,365 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGAngle.h"
 #include "prdtoa.h"
+#include "nsGkAtoms.h"
+#include "nsSVGValue.h"
+#include "nsReadableUtils.h"
 #include "nsTextFormatter.h"
+#include "nsCRT.h"
+#include "nsIDOMSVGNumber.h"
+#include "nsISVGValueUtils.h"
+#include "nsWeakReference.h"
+#include "nsContentUtils.h"
 #include "nsSVGUtils.h"
+#include <math.h>
+
+////////////////////////////////////////////////////////////////////////
+// nsSVGAngle class
 
-class DOMSVGAngle : public nsIDOMSVGAngle
+class nsSVGAngle : public nsIDOMSVGAngle,
+                   public nsSVGValue,
+                   public nsISVGValueObserver
 {
+protected:
+  friend nsresult NS_NewSVGAngle(nsIDOMSVGAngle** result,
+                                 float value,
+                                 PRUint16 unit);
+
+  friend nsresult NS_NewSVGAngle(nsIDOMSVGAngle** result,
+                                 const nsAString &value);
+  
+  nsSVGAngle(float value, PRUint16 unit);
+  nsSVGAngle();
+
 public:
+  // nsISupports interface:
   NS_DECL_ISUPPORTS
 
-  DOMSVGAngle()
-    { mVal.Init(); }
-    
-  NS_IMETHOD GetUnitType(PRUint16* aResult)
-    { *aResult = mVal.mSpecifiedUnitType; return NS_OK; }
-
-  NS_IMETHOD GetValue(float* aResult)
-    { *aResult = mVal.GetBaseValue(); return NS_OK; }
-  NS_IMETHOD SetValue(float aValue)
-    { mVal.SetBaseValue(aValue, nsnull); return NS_OK; }
-
-  NS_IMETHOD GetValueInSpecifiedUnits(float* aResult)
-    { *aResult = mVal.mBaseVal; return NS_OK; }
-  NS_IMETHOD SetValueInSpecifiedUnits(float aValue)
-    { mVal.mBaseVal = aValue; return NS_OK; }
+  // nsIDOMSVGAngle interface:
+  NS_DECL_NSIDOMSVGANGLE
 
-  NS_IMETHOD SetValueAsString(const nsAString& aValue)
-    { return mVal.SetBaseValueString(aValue, nsnull, PR_FALSE); }
-  NS_IMETHOD GetValueAsString(nsAString& aValue)
-    { mVal.GetBaseValueString(aValue); return NS_OK; }
+  // nsISVGValue interface:
+  NS_IMETHOD SetValueString(const nsAString& aValue);
+  NS_IMETHOD GetValueString(nsAString& aValue);
+  
+  // nsISVGValueObserver interface:
+  NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
+                                     modificationType aModType);
+  NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
+                                     modificationType aModType);
 
-  NS_IMETHOD NewValueSpecifiedUnits(PRUint16 unitType,
-                                    float valueInSpecifiedUnits)
-    { mVal.NewValueSpecifiedUnits(unitType, valueInSpecifiedUnits, nsnull);
-      return NS_OK; }
+  // nsISupportsWeakReference
+  // implementation inherited from nsSupportsWeakReference
+  
+protected:
+  // implementation helpers:
+  void  GetUnitString(nsAString& unit);
+  PRUint16 GetUnitTypeForString(const char* unitStr);
+  PRBool IsValidUnitType(PRUint16 unit);
 
-  NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
-    { mVal.ConvertToSpecifiedUnits(unitType, nsnull); return NS_OK; }
-
-private:
-  nsSVGAngle mVal;
+  float mValueInSpecifiedUnits;
+  PRUint8 mSpecifiedUnitType;
 };
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMBaseVal)
-NS_IMPL_RELEASE(nsSVGAngle::DOMBaseVal)
+
+//----------------------------------------------------------------------
+// Implementation
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMAnimVal)
-NS_IMPL_RELEASE(nsSVGAngle::DOMAnimVal)
-
-NS_IMPL_ADDREF(nsSVGAngle::DOMAnimatedAngle)
-NS_IMPL_RELEASE(nsSVGAngle::DOMAnimatedAngle)
+nsresult
+NS_NewSVGAngle(nsIDOMSVGAngle** result,
+               float value,
+               PRUint16 unit)
+{
+  nsSVGAngle *pl = new nsSVGAngle(value, unit);
+  NS_ENSURE_TRUE(pl, NS_ERROR_OUT_OF_MEMORY);
+  NS_ADDREF(pl);
+  *result = pl;
+  return NS_OK;
+}
 
-NS_IMPL_ADDREF(DOMSVGAngle)
-NS_IMPL_RELEASE(DOMSVGAngle)
+nsresult
+NS_NewSVGAngle(nsIDOMSVGAngle** result,
+               const nsAString &value)
+{
+  *result = nsnull;
+  nsSVGAngle *pl = new nsSVGAngle();
+  NS_ENSURE_TRUE(pl, NS_ERROR_OUT_OF_MEMORY);
+  NS_ADDREF(pl);
+  if (NS_FAILED(pl->SetValueAsString(value))) {
+    NS_RELEASE(pl);
+    return NS_ERROR_FAILURE;
+  }
+  *result = pl;
+  return NS_OK;
+}  
+
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMBaseVal)
+nsSVGAngle::nsSVGAngle(float value,
+                       PRUint16 unit)
+  : mValueInSpecifiedUnits(value)
+{
+  NS_ASSERTION(unit == SVG_ANGLETYPE_UNKNOWN || IsValidUnitType(unit), "unknown unit");
+  mSpecifiedUnitType = unit;
+}
+
+nsSVGAngle::nsSVGAngle()
+{
+}
+
+//----------------------------------------------------------------------
+// nsISupports methods:
+
+NS_IMPL_ADDREF(nsSVGAngle)
+NS_IMPL_RELEASE(nsSVGAngle)
+
+NS_INTERFACE_MAP_BEGIN(nsSVGAngle)
+  NS_INTERFACE_MAP_ENTRY(nsISVGValue)
+  NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle)
-NS_INTERFACE_MAP_END
-
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMAnimVal)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMAnimatedAngle)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedAngle)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedAngle)
-NS_INTERFACE_MAP_END
+//----------------------------------------------------------------------
+// nsISVGValue methods:
+NS_IMETHODIMP
+nsSVGAngle::SetValueString(const nsAString& aValue)
+{
+  return SetValueAsString(aValue);
+}
 
-NS_INTERFACE_MAP_BEGIN(DOMSVGAngle)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle)
-NS_INTERFACE_MAP_END
+NS_IMETHODIMP
+nsSVGAngle::GetValueString(nsAString& aValue)
+{
+  return GetValueAsString(aValue);
+}
 
-static nsIAtom** const unitMap[] =
+//----------------------------------------------------------------------
+// nsISVGValueObserver methods
+
+NS_IMETHODIMP
+nsSVGAngle::WillModifySVGObservable(nsISVGValue* observable,
+                                    modificationType aModType)
 {
-  nsnull, /* SVG_ANGLETYPE_UNKNOWN */
-  nsnull, /* SVG_ANGLETYPE_UNSPECIFIED */
-  &nsGkAtoms::deg,
-  &nsGkAtoms::rad,
-  &nsGkAtoms::grad
-};
-
-/* Helper functions */
+  WillModify(aModType);
+  return NS_OK;
+}
 
-static PRBool
-IsValidUnitType(PRUint16 unit)
+NS_IMETHODIMP
+nsSVGAngle::DidModifySVGObservable(nsISVGValue* observable,
+                                   modificationType aModType)
 {
-  if (unit > nsIDOMSVGAngle::SVG_ANGLETYPE_UNKNOWN &&
-      unit <= nsIDOMSVGAngle::SVG_ANGLETYPE_GRAD)
-    return PR_TRUE;
+  DidModify(aModType);
+  return NS_OK;
+}
+
+//----------------------------------------------------------------------
+// nsIDOMSVGAngle methods:
 
-  return PR_FALSE;
+/* readonly attribute unsigned short unitType; */
+NS_IMETHODIMP
+nsSVGAngle::GetUnitType(PRUint16 *aUnitType)
+{
+  *aUnitType = mSpecifiedUnitType;
+  return NS_OK;
 }
 
-static void 
-GetUnitString(nsAString& unit, PRUint16 unitType)
+/* attribute float value; */
+NS_IMETHODIMP
+nsSVGAngle::GetValue(float *aValue)
 {
-  if (IsValidUnitType(unitType)) {
-    if (unitMap[unitType]) {
-      (*unitMap[unitType])->ToString(unit);
-    }
-    return;
+  nsresult rv = NS_OK;
+  
+  switch (mSpecifiedUnitType) {
+  case SVG_ANGLETYPE_UNSPECIFIED:
+  case SVG_ANGLETYPE_DEG:
+    *aValue = float((mValueInSpecifiedUnits * M_PI) / 180.0);
+    break;
+  case SVG_ANGLETYPE_RAD:
+    *aValue = mValueInSpecifiedUnits;
+    break;
+  case SVG_ANGLETYPE_GRAD:
+    *aValue = float((mValueInSpecifiedUnits * M_PI) / 100.0);
+    break;
+  default:
+    rv = NS_ERROR_FAILURE;
+    break;
   }
-
-  NS_NOTREACHED("Unknown unit type");
-  return;
+  return rv;
 }
 
-static PRUint16
-GetUnitTypeForString(const char* unitStr)
+NS_IMETHODIMP
+nsSVGAngle::SetValue(float aValue)
 {
-  if (!unitStr || *unitStr == '\0') 
-    return nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED;
-                   
-  nsCOMPtr<nsIAtom> unitAtom = do_GetAtom(unitStr);
-
-  for (int i = 0 ; i < NS_ARRAY_LENGTH(unitMap) ; i++) {
-    if (unitMap[i] && *unitMap[i] == unitAtom) {
-      return i;
-    }
+  nsresult rv;
+  
+  switch (mSpecifiedUnitType) {
+  case SVG_ANGLETYPE_UNSPECIFIED:
+  case SVG_ANGLETYPE_DEG:
+    rv = SetValueInSpecifiedUnits(float((aValue * 180.0) / M_PI));
+    break;
+  case SVG_ANGLETYPE_RAD:
+    rv = SetValueInSpecifiedUnits(aValue);
+    break;
+  case SVG_ANGLETYPE_GRAD:
+    rv = SetValueInSpecifiedUnits(float((aValue * 100.0) / M_PI));
+    break;
+  default:
+    rv = NS_ERROR_FAILURE;
+    break;
   }
 
-  return nsIDOMSVGAngle::SVG_ANGLETYPE_UNKNOWN;
+  return rv;
+}
+
+/* attribute float valueInSpecifiedUnits; */
+NS_IMETHODIMP
+nsSVGAngle::GetValueInSpecifiedUnits(float *aValueInSpecifiedUnits)
+{
+  *aValueInSpecifiedUnits = mValueInSpecifiedUnits;
+  return NS_OK;
 }
 
-static void
-GetValueString(nsAString &aValueAsString, float aValue, PRUint16 aUnitType)
+NS_IMETHODIMP
+nsSVGAngle::SetValueInSpecifiedUnits(float aValueInSpecifiedUnits)
+{
+  WillModify();
+  mValueInSpecifiedUnits = aValueInSpecifiedUnits;
+  DidModify();
+  return NS_OK;
+}
+
+/* attribute DOMString valueAsString; */
+NS_IMETHODIMP
+nsSVGAngle::GetValueAsString(nsAString & aValueAsString)
 {
   PRUnichar buf[24];
   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
                             NS_LITERAL_STRING("%g").get(),
-                            (double)aValue);
+                            (double)mValueInSpecifiedUnits);
   aValueAsString.Assign(buf);
-
+  
   nsAutoString unitString;
-  GetUnitString(unitString, aUnitType);
+  GetUnitString(unitString);
   aValueAsString.Append(unitString);
+  
+  return NS_OK;
 }
 
-static nsresult
-GetValueFromString(const nsAString &aValueAsString,
-                   float *aValue,
-                   PRUint16 *aUnitType)
+NS_IMETHODIMP
+nsSVGAngle::SetValueAsString(const nsAString & aValueAsString)
 {
-  char *str = ToNewCString(aValueAsString);
-  if (!str)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  nsresult rv = NS_ERROR_FAILURE;
+  nsresult rv = NS_OK;
   
-  if (*str) {
+  char *str = ToNewCString(aValueAsString);
+
+  char* number = str;
+  while (*number && isspace(*number))
+    ++number;
+
+  if (*number) {
     char *rest;
-    *aValue = static_cast<float>(PR_strtod(str, &rest));
-    if (rest != str) {
-      *aUnitType = GetUnitTypeForString(nsCRT::strtok(rest,
-                                        "\x20\x9\xD\xA",
-                                        &rest));
-      if (IsValidUnitType(*aUnitType)) {
-        rv = NS_OK;
-      }
+    double value = PR_strtod(number, &rest);
+    if (rest!=number) {
+      PRUint16 unitType = GetUnitTypeForString(nsCRT::strtok(rest, "\x20\x9\xD\xA", &rest));
+      rv = NewValueSpecifiedUnits(unitType, (float)value);
+    }
+    else { // parse error
+      // no number
+      rv = NS_ERROR_FAILURE;
     }
   }
   
   nsMemory::Free(str);
     
   return rv;
 }
 
-float
-nsSVGAngle::GetUnitScaleFactor() const
+/* void newValueSpecifiedUnits (in unsigned short unitType, in float valueInSpecifiedUnits); */
+NS_IMETHODIMP
+nsSVGAngle::NewValueSpecifiedUnits(PRUint16 unitType, float valueInSpecifiedUnits)
 {
-  switch (mSpecifiedUnitType) {
-  case nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED:
-  case nsIDOMSVGAngle::SVG_ANGLETYPE_DEG:
-    return static_cast<float>(180.0 / M_PI);
-  case nsIDOMSVGAngle::SVG_ANGLETYPE_RAD:
-    return 1;
-  case nsIDOMSVGAngle::SVG_ANGLETYPE_GRAD:
-    return static_cast<float>(100.0 / M_PI);
-  default:
-    NS_NOTREACHED("Unknown unit type");
-    return 0;
-  }
-}
+  if (!IsValidUnitType(unitType)) return NS_ERROR_FAILURE;
 
-void
-nsSVGAngle::SetBaseValueInSpecifiedUnits(float aValue,
-                                         nsSVGElement *aSVGElement)
-{
-  mBaseVal = aValue;
-  aSVGElement->DidChangeAngle(mAttrEnum, PR_TRUE);
+  WillModify();
+  mValueInSpecifiedUnits = valueInSpecifiedUnits;
+  mSpecifiedUnitType     = unitType;
+  DidModify();
+  
+  return NS_OK;
 }
 
-void
-nsSVGAngle::ConvertToSpecifiedUnits(PRUint16 unitType,
-                                    nsSVGElement *aSVGElement)
-{
-  if (!IsValidUnitType(unitType))
-    return;
-
-  float valueInUserUnits = mBaseVal / GetUnitScaleFactor();
-  mSpecifiedUnitType = PRUint8(unitType);
-  SetBaseValue(valueInUserUnits, aSVGElement);
-}
-
-void
-nsSVGAngle::NewValueSpecifiedUnits(PRUint16 unitType,
-                                   float valueInSpecifiedUnits,
-                                   nsSVGElement *aSVGElement)
+/* void convertToSpecifiedUnits (in unsigned short unitType); */
+NS_IMETHODIMP
+nsSVGAngle::ConvertToSpecifiedUnits(PRUint16 unitType)
 {
-  if (!IsValidUnitType(unitType))
-    return;
+  if (!IsValidUnitType(unitType)) return NS_ERROR_FAILURE;
 
-  mBaseVal = mAnimVal = valueInSpecifiedUnits;
-  mSpecifiedUnitType = PRUint8(unitType);
-  if (aSVGElement) {
-    aSVGElement->DidChangeAngle(mAttrEnum, PR_TRUE);
-  }
-}
-
-nsresult
-nsSVGAngle::ToDOMBaseVal(nsIDOMSVGAngle **aResult, nsSVGElement *aSVGElement)
-{
-  *aResult = new DOMBaseVal(this, aSVGElement);
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF(*aResult);
+  float valueInUserUnits;
+  GetValue(&valueInUserUnits);
+  mSpecifiedUnitType = unitType;
+  SetValue(valueInUserUnits);
+  
   return NS_OK;
 }
 
-nsresult
-nsSVGAngle::ToDOMAnimVal(nsIDOMSVGAngle **aResult, nsSVGElement *aSVGElement)
-{
-  *aResult = new DOMAnimVal(this, aSVGElement);
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
 
-  NS_ADDREF(*aResult);
-  return NS_OK;
-}
+//----------------------------------------------------------------------
+// Implementation helpers:
 
-/* Implementation */
 
-nsresult
-nsSVGAngle::SetBaseValueString(const nsAString &aValueAsString,
-                               nsSVGElement *aSVGElement,
-                               PRBool aDoSetAttr)
+void nsSVGAngle::GetUnitString(nsAString& unit)
 {
-  float value;
-  PRUint16 unitType;
+  nsIAtom* UnitAtom = nsnull;
   
-  nsresult rv = GetValueFromString(aValueAsString, &value, &unitType);
-  NS_ENSURE_SUCCESS(rv, rv);
+  switch (mSpecifiedUnitType) {
+  case SVG_ANGLETYPE_UNSPECIFIED:
+    UnitAtom = nsnull;
+    break;
+  case SVG_ANGLETYPE_DEG:
+    UnitAtom = nsGkAtoms::deg;
+    break;
+  case SVG_ANGLETYPE_GRAD:
+    UnitAtom = nsGkAtoms::grad;
+    break;
+  case SVG_ANGLETYPE_RAD:
+    UnitAtom = nsGkAtoms::rad;
+    break;
+  default:
+    NS_ASSERTION(PR_FALSE, "unknown unit");
+    break;
+  }
+  if (!UnitAtom) return;
 
-  mBaseVal = mAnimVal = value;
-  mSpecifiedUnitType = PRUint8(unitType);
-  if (aSVGElement) {
-    aSVGElement->DidChangeAngle(mAttrEnum, aDoSetAttr);
-  }
-
-  return NS_OK;
+  UnitAtom->ToString(unit);
 }
 
-void
-nsSVGAngle::GetBaseValueString(nsAString & aValueAsString)
-{
-  GetValueString(aValueAsString, mBaseVal, mSpecifiedUnitType);
-}
-
-void
-nsSVGAngle::GetAnimValueString(nsAString & aValueAsString)
+PRUint16 nsSVGAngle::GetUnitTypeForString(const char* unitStr)
 {
-  GetValueString(aValueAsString, mAnimVal, mSpecifiedUnitType);
-}
+  if (!unitStr || *unitStr=='\0') return SVG_ANGLETYPE_UNSPECIFIED;
+                   
+  nsCOMPtr<nsIAtom> unitAtom = do_GetAtom(unitStr);
 
-void
-nsSVGAngle::SetBaseValue(float aValue, nsSVGElement *aSVGElement)
-{
-  mAnimVal = mBaseVal = aValue * GetUnitScaleFactor();
-  if (aSVGElement) {
-    aSVGElement->DidChangeAngle(mAttrEnum, PR_TRUE);
-  }
+  if (unitAtom == nsGkAtoms::deg)
+    return SVG_ANGLETYPE_DEG;
+  else if (unitAtom == nsGkAtoms::grad)
+    return SVG_ANGLETYPE_GRAD;
+  else if (unitAtom == nsGkAtoms::rad)
+    return SVG_ANGLETYPE_RAD;
+
+  return SVG_ANGLETYPE_UNKNOWN;
 }
 
-nsresult
-nsSVGAngle::ToDOMAnimatedAngle(nsIDOMSVGAnimatedAngle **aResult,
-                               nsSVGElement *aSVGElement)
+PRBool nsSVGAngle::IsValidUnitType(PRUint16 unit)
 {
-  *aResult = new DOMAnimatedAngle(this, aSVGElement);
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
+  if (unit > SVG_ANGLETYPE_UNKNOWN && unit <= SVG_ANGLETYPE_GRAD)
+    return PR_TRUE;
 
-  NS_ADDREF(*aResult);
-  return NS_OK;
+  return PR_FALSE;
 }
-
-nsresult
-NS_NewDOMSVGAngle(nsIDOMSVGAngle** aResult)
-{
-  *aResult = new DOMSVGAngle;
-  if (!*aResult)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF(*aResult);
-  return NS_OK;
-}
--- a/content/svg/content/src/nsSVGAngle.h
+++ b/content/svg/content/src/nsSVGAngle.h
@@ -33,158 +33,20 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGANGLE_H__
 #define __NS_SVGANGLE_H__
 
 #include "nsIDOMSVGAngle.h"
-#include "nsIDOMSVGAnimatedAngle.h"
-#include "nsSVGElement.h"
-#include "nsDOMError.h"
-
-class nsSVGAngle
-{
-  friend class DOMSVGAngle;
-
-public:
-  void Init(PRUint8 aAttrEnum = 0xff,
-            float aValue = 0,
-            PRUint8 aUnitType = nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED) {
-    mAnimVal = mBaseVal = aValue;
-    mSpecifiedUnitType = aUnitType;
-    mAttrEnum = aAttrEnum;
-  }
-
-  nsresult SetBaseValueString(const nsAString& aValue,
-                              nsSVGElement *aSVGElement,
-                              PRBool aDoSetAttr);
-  void GetBaseValueString(nsAString& aValue);
-  void GetAnimValueString(nsAString& aValue);
-
-  float GetBaseValue() const
-    { return mBaseVal / GetUnitScaleFactor(); }
-  float GetAnimValue() const
-    { return mAnimVal / GetUnitScaleFactor(); }
-
-  void SetBaseValue(float aValue, nsSVGElement *aSVGElement);
-
-  PRUint8 GetSpecifiedUnitType() const { return mSpecifiedUnitType; }
-  float GetAnimValInSpecifiedUnits() const { return mAnimVal; }
-  float GetBaseValInSpecifiedUnits() const { return mBaseVal; }
-
-  static nsresult ToDOMSVGAngle(nsIDOMSVGAngle **aResult);
-  nsresult ToDOMAnimatedAngle(nsIDOMSVGAnimatedAngle **aResult,
-                              nsSVGElement* aSVGElement);
-
-private:
-  
-  float mAnimVal;
-  float mBaseVal;
-  PRUint8 mSpecifiedUnitType;
-  PRUint8 mAttrEnum; // element specified tracking for attribute
-  
-  float GetUnitScaleFactor() const;
-  void SetBaseValueInSpecifiedUnits(float aValue, nsSVGElement *aSVGElement);
-  void NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue,
-                              nsSVGElement *aSVGElement);
-  void ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement);
-  nsresult ToDOMBaseVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
-  nsresult ToDOMAnimVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
-
-  struct DOMBaseVal : public nsIDOMSVGAngle
-  {
-    NS_DECL_ISUPPORTS
-
-    DOMBaseVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
-      : mVal(aVal), mSVGElement(aSVGElement) {}
-    
-    nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
-    nsRefPtr<nsSVGElement> mSVGElement;
-    
-    NS_IMETHOD GetUnitType(PRUint16* aResult)
-      { *aResult = mVal->mSpecifiedUnitType; return NS_OK; }
-
-    NS_IMETHOD GetValue(float* aResult)
-      { *aResult = mVal->GetBaseValue(); return NS_OK; }
-    NS_IMETHOD SetValue(float aValue)
-      { mVal->SetBaseValue(aValue, mSVGElement); return NS_OK; }
-
-    NS_IMETHOD GetValueInSpecifiedUnits(float* aResult)
-      { *aResult = mVal->mBaseVal; return NS_OK; }
-    NS_IMETHOD SetValueInSpecifiedUnits(float aValue)
-      { mVal->SetBaseValueInSpecifiedUnits(aValue, mSVGElement);
-        return NS_OK; }
-
-    NS_IMETHOD SetValueAsString(const nsAString& aValue)
-      { return mVal->SetBaseValueString(aValue, mSVGElement, PR_TRUE); }
-    NS_IMETHOD GetValueAsString(nsAString& aValue)
-      { mVal->GetBaseValueString(aValue); return NS_OK; }
-
-    NS_IMETHOD NewValueSpecifiedUnits(PRUint16 unitType,
-                                      float valueInSpecifiedUnits)
-      { mVal->NewValueSpecifiedUnits(unitType, valueInSpecifiedUnits,
-                                     mSVGElement); 
-        return NS_OK; }
-
-    NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
-      { mVal->ConvertToSpecifiedUnits(unitType, mSVGElement); return NS_OK; }
-  };
-
-  struct DOMAnimVal : public nsIDOMSVGAngle
-  {
-    NS_DECL_ISUPPORTS
-
-    DOMAnimVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
-      : mVal(aVal), mSVGElement(aSVGElement) {}
-    
-    nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
-    nsRefPtr<nsSVGElement> mSVGElement;
-    
-    NS_IMETHOD GetUnitType(PRUint16* aResult)
-      { *aResult = mVal->mSpecifiedUnitType; return NS_OK; }
-
-    NS_IMETHOD GetValue(float* aResult)
-      { *aResult = mVal->GetAnimValue(); return NS_OK; }
-    NS_IMETHOD SetValue(float aValue)
-      { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
-
-    NS_IMETHOD GetValueInSpecifiedUnits(float* aResult)
-      { *aResult = mVal->mAnimVal; return NS_OK; }
-    NS_IMETHOD SetValueInSpecifiedUnits(float aValue)
-      { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
-
-    NS_IMETHOD SetValueAsString(const nsAString& aValue)
-      { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
-    NS_IMETHOD GetValueAsString(nsAString& aValue)
-      { mVal->GetAnimValueString(aValue); return NS_OK; }
-
-    NS_IMETHOD NewValueSpecifiedUnits(PRUint16 unitType,
-                                      float valueInSpecifiedUnits)
-      { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
-
-    NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
-      { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
-  };
-
-  struct DOMAnimatedAngle : public nsIDOMSVGAnimatedAngle
-  {
-    NS_DECL_ISUPPORTS
-
-    DOMAnimatedAngle(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
-      : mVal(aVal), mSVGElement(aSVGElement) {}
-    
-    nsSVGAngle* mVal; // kept alive because it belongs to content
-    nsRefPtr<nsSVGElement> mSVGElement;
-
-    NS_IMETHOD GetBaseVal(nsIDOMSVGAngle **aBaseVal)
-      { return mVal->ToDOMBaseVal(aBaseVal, mSVGElement); }
-
-    NS_IMETHOD GetAnimVal(nsIDOMSVGAngle **aAnimVal)
-      { return mVal->ToDOMAnimVal(aAnimVal, mSVGElement); }
-  };
-};
+#include "nsAString.h"
 
 nsresult
-NS_NewDOMSVGAngle(nsIDOMSVGAngle** result);
+NS_NewSVGAngle(nsIDOMSVGAngle** result,
+               float value=0.0f,
+               PRUint16 unit=nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED);
+
+nsresult
+NS_NewSVGAngle(nsIDOMSVGAngle** result,
+               const nsAString &value);
 
 #endif //__NS_SVGANGLE_H__
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/nsSVGAnimatedAngle.cpp
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSVGValue.h"
+#include "nsWeakReference.h"
+#include "nsSVGAnimatedAngle.h"
+#include "nsSVGLength.h"
+#include "nsContentUtils.h"
+
+
+////////////////////////////////////////////////////////////////////////
+// nsSVGAnimatedAngle
+
+class nsSVGAnimatedAngle : public nsIDOMSVGAnimatedAngle,
+                           public nsSVGValue,
+                           public nsISVGValueObserver
+{
+protected:
+  friend nsresult NS_NewSVGAnimatedAngle(nsIDOMSVGAnimatedAngle** result,
+                                         nsIDOMSVGAngle* baseVal);
+  nsSVGAnimatedAngle();
+  ~nsSVGAnimatedAngle();
+  void Init(nsIDOMSVGAngle* baseVal);
+  
+public:
+  // nsISupports interface:
+  NS_DECL_ISUPPORTS
+
+  // nsIDOMSVGAnimatedAngle interface:
+  NS_DECL_NSIDOMSVGANIMATEDANGLE
+
+  // remainder of nsISVGValue interface:
+  NS_IMETHOD SetValueString(const nsAString& aValue);
+  NS_IMETHOD GetValueString(nsAString& aValue);
+
+  // nsISVGValueObserver
+  NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
+                                     modificationType aModType);
+  NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
+                                     modificationType aModType);
+  
+  // nsISupportsWeakReference
+  // implementation inherited from nsSupportsWeakReference
+  
+protected:
+  nsCOMPtr<nsIDOMSVGAngle> mBaseVal;
+};
+
+
+
+//----------------------------------------------------------------------
+// Implementation
+
+nsSVGAnimatedAngle::nsSVGAnimatedAngle()
+{
+}
+
+nsSVGAnimatedAngle::~nsSVGAnimatedAngle()
+{
+  if (!mBaseVal) return;
+  nsCOMPtr<nsISVGValue> val = do_QueryInterface(mBaseVal);
+  if (!val) return;
+  val->RemoveObserver(this);
+}
+
+void
+nsSVGAnimatedAngle::Init(nsIDOMSVGAngle* baseVal)
+{
+  mBaseVal = baseVal;
+  if (!mBaseVal) return;
+  nsCOMPtr<nsISVGValue> val = do_QueryInterface(mBaseVal);
+  NS_ASSERTION(val, "baseval needs to implement nsISVGValue interface");
+  if (!val) return;
+  val->AddObserver(this);
+}
+
+//----------------------------------------------------------------------
+// nsISupports methods:
+
+NS_IMPL_ADDREF(nsSVGAnimatedAngle)
+NS_IMPL_RELEASE(nsSVGAnimatedAngle)
+
+
+NS_INTERFACE_MAP_BEGIN(nsSVGAnimatedAngle)
+  NS_INTERFACE_MAP_ENTRY(nsISVGValue)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedAngle)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedAngle)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
+NS_INTERFACE_MAP_END
+  
+//----------------------------------------------------------------------
+// nsISVGValue methods:
+
+NS_IMETHODIMP
+nsSVGAnimatedAngle::SetValueString(const nsAString& aValue)
+{
+  nsCOMPtr<nsISVGValue> value = do_QueryInterface(mBaseVal);
+  return value->SetValueString(aValue);
+}
+
+NS_IMETHODIMP
+nsSVGAnimatedAngle::GetValueString(nsAString& aValue)
+{
+  nsCOMPtr<nsISVGValue> value = do_QueryInterface(mBaseVal);
+  return value->GetValueString(aValue);
+}
+
+//----------------------------------------------------------------------
+// nsIDOMSVGAnimatedAngle methods:
+
+/* readonly attribute nsIDOMSVGAngle baseVal; */
+NS_IMETHODIMP
+nsSVGAnimatedAngle::GetBaseVal(nsIDOMSVGAngle * *aBaseVal)
+{
+  *aBaseVal = mBaseVal;
+  NS_ADDREF(*aBaseVal);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAngle animVal; */
+NS_IMETHODIMP
+nsSVGAnimatedAngle::GetAnimVal(nsIDOMSVGAngle * *aAnimVal)
+{
+  *aAnimVal = mBaseVal;
+  NS_ADDREF(*aAnimVal);
+  return NS_OK;
+}
+
+//----------------------------------------------------------------------
+// nsISVGValueObserver methods
+
+NS_IMETHODIMP
+nsSVGAnimatedAngle::WillModifySVGObservable(nsISVGValue* observable,
+                                            modificationType aModType)
+{
+  WillModify(aModType);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSVGAnimatedAngle::DidModifySVGObservable (nsISVGValue* observable,
+                                            modificationType aModType)
+{
+  DidModify(aModType);
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////
+// Exported creation functions
+
+nsresult
+NS_NewSVGAnimatedAngle(nsIDOMSVGAnimatedAngle** aResult,
+                       nsIDOMSVGAngle* baseVal)
+{
+  *aResult = nsnull;
+  
+  nsSVGAnimatedAngle* animatedLength = new nsSVGAnimatedAngle();
+  if(!animatedLength) return NS_ERROR_OUT_OF_MEMORY;
+  NS_ADDREF(animatedLength);
+
+  animatedLength->Init(baseVal);
+  
+  *aResult = (nsIDOMSVGAnimatedAngle*) animatedLength;
+  
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/nsSVGAnimatedAngle.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SVGANIMATEDANGLE_H__
+#define __NS_SVGANIMATEDANGLE_H__
+
+#include "nsIDOMSVGAnimatedAngle.h"
+#include "nsIDOMSVGAngle.h"
+
+nsresult NS_NewSVGAnimatedAngle(nsIDOMSVGAnimatedAngle** result,
+                                nsIDOMSVGAngle* baseVal);
+
+#endif //__NS_SVGANIMATEDANGLE_H__
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -63,20 +63,24 @@
 #include "nsGenericHTMLElement.h"
 #include "nsNodeInfoManager.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIEventListenerManager.h"
 #include "nsSVGUtils.h"
 #include "nsSVGLength2.h"
 #include "nsSVGNumber2.h"
 #include "nsSVGInteger.h"
-#include "nsSVGAngle.h"
 #include "nsSVGBoolean.h"
 #include "nsSVGEnum.h"
 #include "nsIDOMSVGUnitTypes.h"
+#include "nsIDOMSVGAngle.h"
+#include "nsIDOMSVGAnimatedAngle.h"
+#include "nsIDOMSVGAnimatedBoolean.h"
+#include "nsIDOMSVGAnimatedInteger.h"
+#include "nsIDOMSVGLength.h"
 #include "nsIDOMSVGLengthList.h"
 #include "nsIDOMSVGAnimatedLengthList.h"
 #include "nsIDOMSVGNumberList.h"
 #include "nsIDOMSVGAnimatedNumberList.h"
 #include "nsIDOMSVGPointList.h"
 #include "nsIDOMSVGAnimatedPoints.h"
 #include "nsIDOMSVGPresAspectRatio.h"
 #include "nsIDOMSVGAnimPresAspRatio.h"
@@ -122,24 +126,16 @@ nsSVGElement::Init()
   }
 
   IntegerAttributesInfo integerInfo = GetIntegerInfo();
 
   for (i = 0; i < integerInfo.mIntegerCount; i++) {
     integerInfo.mIntegers[i].Init(i, integerInfo.mIntegerInfo[i].mDefaultValue);
   }
 
-  AngleAttributesInfo angleInfo = GetAngleInfo();
-
-  for (i = 0; i < angleInfo.mAngleCount; i++) {
-    angleInfo.mAngles[i].Init(i,
-                              angleInfo.mAngleInfo[i].mDefaultValue,
-                              angleInfo.mAngleInfo[i].mDefaultUnitType);
-  }
-
   BooleanAttributesInfo booleanInfo = GetBooleanInfo();
 
   for (i = 0; i < booleanInfo.mBooleanCount; i++) {
     booleanInfo.mBooleans[i].Init(i, booleanInfo.mBooleanInfo[i].mDefaultValue);
   }
 
   EnumAttributesInfo enumInfo = GetEnumInfo();
 
@@ -258,64 +254,53 @@ nsSVGElement::ParseAttribute(PRInt32 aNa
   }
 
   if (aNamespaceID == kNameSpaceID_None) {
     nsresult rv;
     PRBool foundMatch = PR_FALSE;
 
     // Check for nsSVGLength2 attribute
     LengthAttributesInfo lengthInfo = GetLengthInfo();
-
-    PRUint32 i;
-    for (i = 0; i < lengthInfo.mLengthCount && !foundMatch; i++) {
+    for (PRUint32 i = 0; i < lengthInfo.mLengthCount && !foundMatch; i++) {
       if (aAttribute == *lengthInfo.mLengthInfo[i].mName) {
         rv = lengthInfo.mLengths[i].SetBaseValueString(aValue, this, PR_FALSE);
         foundMatch = PR_TRUE;
       }
     }
 
     // Check for nsSVGNumber2 attribute
     NumberAttributesInfo numberInfo = GetNumberInfo();
-    for (i = 0; i < numberInfo.mNumberCount && !foundMatch; i++) {
+    for (PRUint32 i = 0; i < numberInfo.mNumberCount && !foundMatch; i++) {
       if (aAttribute == *numberInfo.mNumberInfo[i].mName) {
         rv = numberInfo.mNumbers[i].SetBaseValueString(aValue, this, PR_FALSE);
         foundMatch = PR_TRUE;
       }
     }
 
     // Check for nsSVGInteger attribute
     IntegerAttributesInfo integerInfo = GetIntegerInfo();
-    for (i = 0; i < integerInfo.mIntegerCount && !foundMatch; i++) {
+    for (PRUint32 i = 0; i < integerInfo.mIntegerCount && !foundMatch; i++) {
       if (aAttribute == *integerInfo.mIntegerInfo[i].mName) {
         rv = integerInfo.mIntegers[i].SetBaseValueString(aValue, this, PR_FALSE);
         foundMatch = PR_TRUE;
       }
     }
 
-    // Check for nsSVGAngle attribute
-    AngleAttributesInfo angleInfo = GetAngleInfo();
-    for (i = 0; i < angleInfo.mAngleCount && !foundMatch; i++) {
-      if (aAttribute == *angleInfo.mAngleInfo[i].mName) {
-        rv = angleInfo.mAngles[i].SetBaseValueString(aValue, this, PR_FALSE);
-        foundMatch = PR_TRUE;
-      }
-    }
-
     // Check for nsSVGBoolean attribute
     BooleanAttributesInfo booleanInfo = GetBooleanInfo();
-    for (i = 0; i < booleanInfo.mBooleanCount && !foundMatch; i++) {
+    for (PRUint32 i = 0; i < booleanInfo.mBooleanCount && !foundMatch; i++) {
       if (aAttribute == *booleanInfo.mBooleanInfo[i].mName) {
         rv = booleanInfo.mBooleans[i].SetBaseValueString(aValue, this, PR_FALSE);
         foundMatch = PR_TRUE;
       }
     }
 
     // Check for nsSVGEnum attribute
     EnumAttributesInfo enumInfo = GetEnumInfo();
-    for (i = 0; i < enumInfo.mEnumCount && !foundMatch; i++) {
+    for (PRUint32 i = 0; i < enumInfo.mEnumCount && !foundMatch; i++) {
       if (aAttribute == *enumInfo.mEnumInfo[i].mName) {
         rv = enumInfo.mEnums[i].SetBaseValueString(aValue, this, PR_FALSE);
         foundMatch = PR_TRUE;
       }
     }
 
     if (foundMatch) {
       if (NS_FAILED(rv)) {
@@ -376,28 +361,16 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespa
 
       for (i = 0; i < intInfo.mIntegerCount; i++) {
         if (aName == *intInfo.mIntegerInfo[i].mName) {
           intInfo.mIntegers[i].Init(i, intInfo.mIntegerInfo[i].mDefaultValue);
           DidChangeInteger(i, PR_FALSE);
         }
       }
 
-      // Check if this is an angle attribute going away
-      AngleAttributesInfo angleInfo = GetAngleInfo();
-
-      for (i = 0; i < angleInfo.mAngleCount; i++) {
-        if (aName == *angleInfo.mAngleInfo[i].mName) {
-          angleInfo.mAngles[i].Init(i, 
-                                    angleInfo.mAngleInfo[i].mDefaultValue,
-                                    angleInfo.mAngleInfo[i].mDefaultUnitType);
-          DidChangeAngle(i, PR_FALSE);
-        }
-      }
-
       // Check if this is a boolean attribute going away
       BooleanAttributesInfo boolInfo = GetBooleanInfo();
 
       for (i = 0; i < boolInfo.mBooleanCount; i++) {
         if (aName == *boolInfo.mBooleanInfo[i].mName) {
           boolInfo.mBooleans[i].Init(i, boolInfo.mBooleanInfo[i].mDefaultValue);
           DidChangeBoolean(i, PR_FALSE);
         }
@@ -412,16 +385,21 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespa
           DidChangeEnum(i, PR_FALSE);
         }
       }
 
       // Now check for one of the old style basetypes going away
       nsCOMPtr<nsISVGValue> svg_value = GetMappedAttribute(aNamespaceID, aName);
 
       if (svg_value) {
+#ifdef DEBUG_tor
+        nsCOMPtr<nsIDOMSVGAnimatedAngle> a = do_QueryInterface(svg_value);
+        NS_ASSERTION(!a, "must provide element processing for unset angle");
+#endif
+
         nsCOMPtr<nsIDOMSVGAnimatedRect> r = do_QueryInterface(svg_value);
         if (r) {
           nsCOMPtr<nsIDOMSVGRect> rect;
           r->GetBaseVal(getter_AddRefs(rect));
           static_cast<nsSVGRect*>(rect.get())->Clear();
         }
         nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> ar = do_QueryInterface(svg_value);
         if (ar) {
@@ -1080,58 +1058,32 @@ nsSVGElement::GetAnimatedIntegerValues(P
 
   while (n && i < info.mIntegerCount) {
     *n = info.mIntegers[i++].GetAnimValue();
     n = va_arg(args, PRInt32*);
   }
   va_end(args);
 }
 
-nsSVGElement::AngleAttributesInfo
-nsSVGElement::GetAngleInfo()
-{
-  return AngleAttributesInfo(nsnull, nsnull, 0);
-}
-
-void
-nsSVGElement::DidChangeAngle(PRUint8 aAttrEnum, PRBool aDoSetAttr)
-{
-  if (!aDoSetAttr)
-    return;
-
-  AngleAttributesInfo info = GetAngleInfo();
-
-  NS_ASSERTION(info.mAngleCount > 0,
-               "DidChangeAngle on element with no angle attribs");
-
-  NS_ASSERTION(aAttrEnum < info.mAngleCount, "aAttrEnum out of range");
-
-  nsAutoString newStr;
-  info.mAngles[aAttrEnum].GetBaseValueString(newStr);
-
-  SetAttr(kNameSpaceID_None, *info.mAngleInfo[aAttrEnum].mName,
-          newStr, PR_TRUE);
-}
-
 nsSVGElement::BooleanAttributesInfo
 nsSVGElement::GetBooleanInfo()
 {
   return BooleanAttributesInfo(nsnull, nsnull, 0);
 }
 
 void
 nsSVGElement::DidChangeBoolean(PRUint8 aAttrEnum, PRBool aDoSetAttr)
 {
   if (!aDoSetAttr)
     return;
 
   BooleanAttributesInfo info = GetBooleanInfo();
 
   NS_ASSERTION(info.mBooleanCount > 0,
-               "DidChangeBoolean on element with no boolean attribs");
+               "DidChangeInteger on element with no boolean attribs");
 
   NS_ASSERTION(aAttrEnum < info.mBooleanCount, "aAttrEnum out of range");
 
   nsAutoString newStr;
   info.mBooleans[aAttrEnum].GetBaseValueString(newStr);
 
   SetAttr(kNameSpaceID_None, *info.mBooleanInfo[aAttrEnum].mName,
           newStr, PR_TRUE);
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -53,17 +53,16 @@
 #include "nsISVGValueObserver.h"
 #include "nsWeakReference.h"
 #include "nsICSSStyleRule.h"
 
 class nsSVGSVGElement;
 class nsSVGLength2;
 class nsSVGNumber2;
 class nsSVGInteger;
-class nsSVGAngle;
 class nsSVGBoolean;
 class nsSVGEnum;
 struct nsSVGEnumMapping;
 
 typedef nsStyledElement nsSVGElementBase;
 
 class nsSVGElement : public nsSVGElementBase,    // nsIContent
                      public nsISVGValueObserver  // :nsISupportsWeakReference
@@ -117,17 +116,16 @@ public:
   // nsISupportsWeakReference
   // implementation inherited from nsSupportsWeakReference
 
   nsSVGSVGElement* GetCtx();
 
   virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeNumber(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeInteger(PRUint8 aAttrEnum, PRBool aDoSetAttr);
-  virtual void DidChangeAngle(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeBoolean(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr);
 
   void GetAnimatedLengthValues(float *aFirst, ...);
   void GetAnimatedNumberValues(float *aFirst, ...);
   void GetAnimatedIntegerValues(PRInt32 *aFirst, ...);
 
   virtual void RecompileScriptEventListeners();
@@ -148,17 +146,17 @@ protected:
   nsresult AddMappedSVGValue(nsIAtom* aName, nsISupports* aValue,
                              PRInt32 aNamespaceID = kNameSpaceID_None);
   
   static nsIAtom* GetEventNameForAttr(nsIAtom* aAttr);
 
   struct LengthInfo {
     nsIAtom** mName;
     float     mDefaultValue;
-    PRUint8   mDefaultUnitType;
+    PRUint16  mDefaultUnitType;
     PRUint8   mCtxType;
   };
 
   struct LengthAttributesInfo {
     nsSVGLength2* mLengths;
     LengthInfo*   mLengthInfo;
     PRUint32      mLengthCount;
 
@@ -198,34 +196,16 @@ protected:
 
     IntegerAttributesInfo(nsSVGInteger *aIntegers,
                           IntegerInfo *aIntegerInfo,
                           PRUint32 aIntegerCount) :
       mIntegers(aIntegers), mIntegerInfo(aIntegerInfo), mIntegerCount(aIntegerCount)
       {}
   };
 
-  struct AngleInfo {
-    nsIAtom** mName;
-    float     mDefaultValue;
-    PRUint8   mDefaultUnitType;
-  };
-
-  struct AngleAttributesInfo {
-    nsSVGAngle* mAngles;
-    AngleInfo*  mAngleInfo;
-    PRUint32    mAngleCount;
-
-    AngleAttributesInfo(nsSVGAngle *aAngles,
-                        AngleInfo *aAngleInfo,
-                        PRUint32 aAngleCount) :
-      mAngles(aAngles), mAngleInfo(aAngleInfo), mAngleCount(aAngleCount)
-      {}
-  };
-
   struct BooleanInfo {
     nsIAtom**    mName;
     PRPackedBool mDefaultValue;
   };
 
   struct BooleanAttributesInfo {
     nsSVGBoolean* mBooleans;
     BooleanInfo*  mBooleanInfo;
@@ -256,26 +236,25 @@ protected:
                        PRUint32 aEnumCount) :
       mEnums(aEnums), mEnumInfo(aEnumInfo), mEnumCount(aEnumCount)
       {}
   };
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual NumberAttributesInfo GetNumberInfo();
   virtual IntegerAttributesInfo GetIntegerInfo();
-  virtual AngleAttributesInfo GetAngleInfo();
   virtual BooleanAttributesInfo GetBooleanInfo();
   virtual EnumAttributesInfo GetEnumInfo();
 
-  static nsSVGEnumMapping sSVGUnitTypesMap[];
-
   static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
                                               nsIAtom* aAttribute,
                                               const nsAString& aValue);
 
+  static nsSVGEnumMapping sSVGUnitTypesMap[];
+
   nsCOMPtr<nsICSSStyleRule> mContentStyleRule;
   nsAttrAndChildArray mMappedAttributes;
 
   PRPackedBool mSuppressNotification;
 };
 
 /**
  * A macro to implement the NS_NewSVGXXXElement() functions.
--- a/content/svg/content/src/nsSVGEnum.cpp
+++ b/content/svg/content/src/nsSVGEnum.cpp
@@ -99,17 +99,17 @@ nsresult
 nsSVGEnum::SetBaseValue(PRUint16 aValue,
                         nsSVGElement *aSVGElement,
                         PRBool aDoSetAttr)
 {
   nsSVGEnumMapping *tmp = GetMapping(aSVGElement);
 
   while (tmp && tmp->mKey) {
     if (tmp->mVal == aValue) {
-      mAnimVal = mBaseVal = PRUint8(aValue);
+      mAnimVal = mBaseVal = static_cast<PRUint8>(aValue);
       aSVGElement->DidChangeEnum(mAttrEnum, aDoSetAttr);
       return NS_OK;
     }
     tmp++;
   }
   return NS_ERROR_FAILURE;
 }
 
--- a/content/svg/content/src/nsSVGEnum.h
+++ b/content/svg/content/src/nsSVGEnum.h
@@ -45,21 +45,19 @@ typedef PRUint8 nsSVGEnumValue;
 
 struct nsSVGEnumMapping {
   nsIAtom **mKey;
   nsSVGEnumValue mVal;
 };
 
 class nsSVGEnum
 {
-friend class nsSVGMarkerElement;
-
 public:
   void Init(PRUint8 aAttrEnum, PRUint16 aValue) {
-    mAnimVal = mBaseVal = PRUint8(aValue);
+    mAnimVal = mBaseVal = static_cast<PRUint8>(aValue);
     mAttrEnum = aAttrEnum;
   }
 
   nsresult SetBaseValueString(const nsAString& aValue,
                               nsSVGElement *aSVGElement,
                               PRBool aDoSetAttr);
   void GetBaseValueString(nsAString& aValue,
                           nsSVGElement *aSVGElement);
@@ -78,20 +76,16 @@ public:
 
 private:
   nsSVGEnumValue mAnimVal;
   nsSVGEnumValue mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   nsSVGEnumMapping *GetMapping(nsSVGElement *aSVGElement);
 
-  nsresult SetBaseValue(PRUint16 aValue)
-  { mAnimVal = mBaseVal = PRUint8(aValue);
-    return NS_OK; }
-
   struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
   {
     NS_DECL_ISUPPORTS
 
     DOMAnimatedEnum(nsSVGEnum* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGEnum *mVal; // kept alive because it belongs to content
--- a/content/svg/content/src/nsSVGMarkerElement.cpp
+++ b/content/svg/content/src/nsSVGMarkerElement.cpp
@@ -30,17 +30,20 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsGkAtoms.h"
+#include "nsSVGAnimatedAngle.h"
 #include "nsSVGAnimatedRect.h"
+#include "nsSVGLength.h"
+#include "nsSVGAngle.h"
 #include "nsSVGRect.h"
 #include "nsCOMPtr.h"
 #include "nsISVGValueUtils.h"
 #include "nsSVGAnimatedPreserveAspectRatio.h"
 #include "nsSVGPreserveAspectRatio.h"
 #include "nsSVGMatrix.h"
 #include "nsDOMError.h"
 #include "nsSVGUtils.h"
@@ -63,21 +66,16 @@ nsSVGEnumMapping nsSVGMarkerElement::sUn
 nsSVGElement::EnumInfo nsSVGMarkerElement::sEnumInfo[1] =
 {
   { &nsGkAtoms::markerUnits,
     sUnitsMap,
     nsIDOMSVGMarkerElement::SVG_MARKERUNITS_STROKEWIDTH
   }
 };
 
-nsSVGElement::AngleInfo nsSVGMarkerElement::sAngleInfo[1] =
-{
-  { &nsGkAtoms::orient, 0, nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED }
-};
-
 NS_IMPL_NS_NEW_SVG_ELEMENT(Marker)
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
 
@@ -104,16 +102,25 @@ nsSVGMarkerElement::Init()
   nsresult rv = nsSVGMarkerElementBase::Init();
   NS_ENSURE_SUCCESS(rv,rv);
 
   // derived (non-attrib) DOM properties
 
   // DOM property: orientType
   mOrientType.Init(ORIENTTYPE, SVG_MARKER_ORIENT_ANGLE);
 
+  // DOM property: orientAngle
+  {
+    nsCOMPtr<nsIDOMSVGAngle> angle;
+    rv = NS_NewSVGAngle(getter_AddRefs(angle), 0.0f);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedAngle(getter_AddRefs(mOrientAngle), angle);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
   // Create mapped properties:
 
   // DOM property: viewBox
   {
     nsCOMPtr<nsIDOMSVGRect> viewbox;
     rv = NS_NewSVGRect(getter_AddRefs(viewbox));
     NS_ENSURE_SUCCESS(rv,rv);
     rv = NS_NewSVGAnimatedRect(getter_AddRefs(mViewBox), viewbox);
@@ -201,36 +208,41 @@ NS_IMETHODIMP nsSVGMarkerElement::GetMar
 NS_IMETHODIMP nsSVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType)
 {
   return mOrientType.ToDOMAnimatedEnum(aOrientType, this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedLength orientAngle; */
 NS_IMETHODIMP nsSVGMarkerElement::GetOrientAngle(nsIDOMSVGAnimatedAngle * *aOrientAngle)
 {
-  return mAngleAttributes[ORIENT].ToDOMAnimatedAngle(aOrientAngle, this);
+  *aOrientAngle = mOrientAngle;
+  NS_IF_ADDREF(*aOrientAngle);
+  return NS_OK;
 }
 
 /* void setOrientToAuto (); */
 NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAuto()
 {
-  SetAttr(kNameSpaceID_None, nsGkAtoms::orient, nsnull,
-          NS_LITERAL_STRING("auto"), PR_TRUE);
+  mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO, this, PR_TRUE);
   return NS_OK;
 }
 
 /* void setOrientToAngle (in nsIDOMSVGAngle angle); */
 NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAngle(nsIDOMSVGAngle *angle)
 {
   if (!angle)
     return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
 
+  nsIDOMSVGAngle *a;
+  mOrientAngle->GetBaseVal(&a);
   float f;
   angle->GetValue(&f);
-  mAngleAttributes[ORIENT].SetBaseValue(f, this);
+  a->SetValue(f);
+
+  mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE, this, PR_TRUE);
 
   return NS_OK;
 }
 
 //----------------------------------------------------------------------
 // nsISVGValueObserver methods:
 
 NS_IMETHODIMP
@@ -264,34 +276,45 @@ nsSVGMarkerElement::IsAttributeMapped(co
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 PRBool
 nsSVGMarkerElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                             nsAString &aResult) const
 {
-  if (aNameSpaceID == kNameSpaceID_None &&
-      aName == nsGkAtoms::orient &&
-      mOrientType.GetBaseValue() == SVG_MARKER_ORIENT_AUTO) {
-    aResult.AssignLiteral("auto");
+  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient) {
+    if (mOrientType.GetBaseValue() == SVG_MARKER_ORIENT_AUTO) {
+      aResult.AssignLiteral("auto");
+    } else {
+      nsCOMPtr<nsIDOMSVGAngle> a;
+      mOrientAngle->GetBaseVal(getter_AddRefs(a));
+      nsCOMPtr<nsISVGValue> value = do_QueryInterface(a);
+      value->GetValueString(aResult);
+    }
     return PR_TRUE;
   }
   return nsSVGMarkerElementBase::GetAttr(aNameSpaceID, aName, aResult);
 }
 
 nsresult
 nsSVGMarkerElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                             nsIAtom* aPrefix, const nsAString& aValue,
                             PRBool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient) {
-    mOrientType.SetBaseValue(aValue.EqualsLiteral("auto") ?
-                               SVG_MARKER_ORIENT_AUTO :
-                               SVG_MARKER_ORIENT_ANGLE);
+    if (aValue.EqualsLiteral("auto")) {
+      mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO, this, PR_FALSE);
+    } else {
+      mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE, this, PR_FALSE);
+      nsCOMPtr<nsIDOMSVGAngle> a;
+      mOrientAngle->GetBaseVal(getter_AddRefs(a));
+      nsCOMPtr<nsISVGValue> value = do_QueryInterface(a);
+      value->SetValueString(aValue);
+    }
   }
 
   return nsSVGMarkerElementBase::SetAttr(aNameSpaceID, aName,
                                          aPrefix, aValue, aNotify);
 }
 
 nsresult
 nsSVGMarkerElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
@@ -300,20 +323,25 @@ nsSVGMarkerElement::UnsetAttr(PRInt32 aN
   if (aNamespaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::viewBox && mCoordCtx) {
       nsCOMPtr<nsIDOMSVGRect> vb;
       mViewBox->GetAnimVal(getter_AddRefs(vb));
       vb->SetX(0);
       vb->SetY(0);
       vb->SetWidth(mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx));
       vb->SetHeight(mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx));
-      return nsGenericElement::UnsetAttr(aNamespaceID, aName, aNotify);
     } else if (aName == nsGkAtoms::orient) {
-      mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE);
+      mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE, this, PR_FALSE);
+      nsIDOMSVGAngle *angle;
+      mOrientAngle->GetBaseVal(&angle);
+      angle->NewValueSpecifiedUnits(nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED,
+                                    0.0f);
     }
+
+    return nsGenericElement::UnsetAttr(aNamespaceID, aName, aNotify);
   }
 
   return nsSVGMarkerElementBase::UnsetAttr(aNamespaceID, aName, aNotify);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
@@ -328,16 +356,41 @@ nsSVGMarkerElement::DidChangeLength(PRUi
       (aAttrEnum == MARKERWIDTH || aAttrEnum == MARKERHEIGHT)) {
     nsCOMPtr<nsIDOMSVGRect> vb;
     mViewBox->GetAnimVal(getter_AddRefs(vb));
     vb->SetWidth(mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx));
     vb->SetHeight(mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx));
   }
 }
 
+void
+nsSVGMarkerElement::DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr)
+{
+  if (!aDoSetAttr)
+    return;
+
+  if (aAttrEnum == ORIENTTYPE) {
+    if (mOrientType.GetBaseValue() == SVG_MARKER_ORIENT_AUTO) {
+      nsSVGMarkerElementBase::SetAttr(kNameSpaceID_None, nsGkAtoms::orient,
+                                      NS_LITERAL_STRING("auto"), PR_TRUE);
+    } else {
+      nsAutoString value;
+      GetAttr(kNameSpaceID_None, nsGkAtoms::orient, value);
+      if (value.EqualsLiteral("auto")) {
+        // type is being set to non-auto - remove an "auto" valued
+        // attribute if it's set, otherwise leave the angle specified.
+        UnsetAttr(kNameSpaceID_None, nsGkAtoms::orient, PR_TRUE);
+      }
+    }
+    return;
+  }
+
+  nsSVGMarkerElementBase::DidChangeEnum(aAttrEnum, aDoSetAttr);
+}
+
 void 
 nsSVGMarkerElement::SetParentCoordCtxProvider(nsSVGSVGElement *aContext)
 {
   mCoordCtx = aContext;
   mViewBoxToViewportTransform = nsnull;
 
   if (mCoordCtx && !HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) {
     nsCOMPtr<nsIDOMSVGRect> vb;
@@ -349,23 +402,16 @@ nsSVGMarkerElement::SetParentCoordCtxPro
 
 nsSVGElement::LengthAttributesInfo
 nsSVGMarkerElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               NS_ARRAY_LENGTH(sLengthInfo));
 }
 
-nsSVGElement::AngleAttributesInfo
-nsSVGMarkerElement::GetAngleInfo()
-{
-  return AngleAttributesInfo(mAngleAttributes, sAngleInfo,
-                             NS_ARRAY_LENGTH(sAngleInfo));
-}
-
 nsSVGElement::EnumAttributesInfo
 nsSVGMarkerElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             NS_ARRAY_LENGTH(sEnumInfo));
 }
 
 //----------------------------------------------------------------------
@@ -376,18 +422,20 @@ nsSVGMarkerElement::GetMarkerTransform(f
                                        float aX, float aY, float aAngle,
                                        nsIDOMSVGMatrix **_retval)
 {
   float scale = 1.0;
   if (mEnumAttributes[MARKERUNITS].GetAnimValue() ==
       SVG_MARKERUNITS_STROKEWIDTH)
     scale = aStrokeWidth;
 
-  if (mOrientType.GetAnimValue() != SVG_MARKER_ORIENT_AUTO) {
-    aAngle = mAngleAttributes[ORIENT].GetAnimValue();
+  if (mOrientType.GetBaseValue() != SVG_MARKER_ORIENT_AUTO) {
+    nsCOMPtr<nsIDOMSVGAngle> a;
+    mOrientAngle->GetAnimVal(getter_AddRefs(a));
+    a->GetValue(&aAngle);
   }
 
   nsCOMPtr<nsIDOMSVGMatrix> matrix;
   NS_NewSVGMatrix(getter_AddRefs(matrix),
                   cos(aAngle) * scale,   sin(aAngle) * scale,
                   -sin(aAngle) * scale,  cos(aAngle) * scale,
                   aX,                    aY);
     
--- a/content/svg/content/src/nsSVGMarkerElement.h
+++ b/content/svg/content/src/nsSVGMarkerElement.h
@@ -37,17 +37,16 @@
 #ifndef __NS_SVGMARKERELEMENT_H__
 #define __NS_SVGMARKERELEMENT_H__
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGMarkerElement.h"
 #include "nsIDOMSVGFitToViewBox.h"
 #include "nsSVGLength2.h"
 #include "nsSVGEnum.h"
-#include "nsSVGAngle.h"
 
 typedef nsSVGGraphicElement nsSVGMarkerElementBase;
 
 class nsSVGMarkerElement : public nsSVGMarkerElementBase,
                            public nsIDOMSVGMarkerElement,
                            public nsIDOMSVGFitToViewBox
 {
   friend class nsSVGMarkerFrame;
@@ -82,48 +81,45 @@ public:
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              PRBool aNotify);
 
   // nsSVGElement specializations:
   virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
+  virtual void DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr);
 
   // public helpers
   nsresult GetMarkerTransform(float aStrokeWidth,
                               float aX, float aY, float aAngle,
                               nsIDOMSVGMatrix **_retval);
   nsresult GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
 
   void SetParentCoordCtxProvider(nsSVGSVGElement *aContext);
 
   virtual LengthAttributesInfo GetLengthInfo();
-  virtual AngleAttributesInfo GetAngleInfo();
   virtual EnumAttributesInfo GetEnumInfo();
 
   enum { REFX, REFY, MARKERWIDTH, MARKERHEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 
   enum { MARKERUNITS, ORIENTTYPE = 0xFF };
   nsSVGEnum mEnumAttributes[1];
   static nsSVGEnumMapping sUnitsMap[];
   static EnumInfo sEnumInfo[1];
 
-  enum { ORIENT };
-  nsSVGAngle mAngleAttributes[1];
-  static AngleInfo sAngleInfo[1];
-
   // derived properties (from 'orient') handled separately
   nsSVGEnum                              mOrientType;
+  nsCOMPtr<nsIDOMSVGAnimatedAngle>       mOrientAngle;
 
   nsSVGSVGElement                       *mCoordCtx;
   nsCOMPtr<nsIDOMSVGAnimatedRect>        mViewBox;
   nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> mPreserveAspectRatio;
   nsCOMPtr<nsIDOMSVGMatrix>         mViewBoxToViewportTransform;
 };
 
 #endif
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -374,17 +374,17 @@ nsSVGSVGElement::SuspendRedraw(PRUint32 
     return NS_OK;
 
   nsIFrame* frame = GetPrimaryFrame();
 #ifdef DEBUG
   // XXX We sometimes hit this assertion when the svg:svg element is
   // in a binding and svg children are inserted underneath it using
   // <children/>. If the svg children then call suspendRedraw, the
   // above function call fails although the svg:svg's frame has been
-  // built. Strange...
+  // build. Strange...
   
   NS_ASSERTION(frame, "suspending redraw w/o frame");
 #endif
   if (frame) {
     nsISVGSVGFrame* svgframe;
     CallQueryInterface(frame, &svgframe);
     NS_ASSERTION(svgframe, "wrong frame type");
     if (svgframe) {
@@ -562,17 +562,17 @@ nsSVGSVGElement::CreateSVGLength(nsIDOMS
 {
   return NS_NewSVGLength(reinterpret_cast<nsISVGLength**>(_retval));
 }
 
 /* nsIDOMSVGAngle createSVGAngle (); */
 NS_IMETHODIMP
 nsSVGSVGElement::CreateSVGAngle(nsIDOMSVGAngle **_retval)
 {
-  return NS_NewDOMSVGAngle(_retval);
+  return NS_NewSVGAngle(_retval);
 }
 
 /* nsIDOMSVGPoint createSVGPoint (); */
 NS_IMETHODIMP
 nsSVGSVGElement::CreateSVGPoint(nsIDOMSVGPoint **_retval)
 {
   return NS_NewSVGPoint(_retval);
 }