Bug 456286 - support altGlyph elements as tspans. r=roc
authorRobert Longson <longsonr@gmail.com>
Tue, 13 Apr 2010 09:58:09 +0100
changeset 40733 caa4eb12ad2029c9d10c4e38fd81c285012c9805
parent 40732 96561ce0c52ac5b23b3d402f536dde125655ae26
child 40734 a005f1749e5edd1c6176f19362be04680db5961f
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs456286
milestone1.9.3a5pre
Bug 456286 - support altGlyph elements as tspans. r=roc
content/svg/content/src/Makefile.in
content/svg/content/src/nsSVGAltGlyphElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGElementFactory.cpp
content/svg/content/src/nsSVGTSpanElement.cpp
content/svg/content/src/nsSVGTextElement.cpp
content/svg/content/src/nsSVGTextPositioningElement.cpp
content/svg/content/src/nsSVGTextPositioningElement.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/interfaces/svg/Makefile.in
dom/interfaces/svg/nsIDOMSVGAltGlyphElement.idl
layout/base/nsCSSFrameConstructor.cpp
layout/reftests/svg/altGlyph-01-ref.svg
layout/reftests/svg/altGlyph-01.svg
layout/reftests/svg/reftest.list
layout/svg/base/src/nsSVGTSpanFrame.cpp
layout/svg/base/src/nsSVGTSpanFrame.h
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -47,16 +47,17 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= content
 LIBRARY_NAME	= gkcontentsvg_s
 LIBXUL_LIBRARY	= 1
 
 CPPSRCS		= \
 		nsDOMSVGZoomEvent.cpp \
 		nsDOMSVGEvent.cpp \
 		nsSVGAElement.cpp \
+		nsSVGAltGlyphElement.cpp \
 		nsSVGAngle.cpp \
 		nsSVGAnimatedLengthList.cpp \
 		nsSVGAnimatedNumberList.cpp \
 		nsSVGAnimatedTransformList.cpp \
 		nsSVGBoolean.cpp \
 		nsSVGCircleElement.cpp \
 		nsSVGClipPathElement.cpp \
 		nsSVGDataParser.cpp \
@@ -108,16 +109,17 @@ CPPSRCS		= \
 		nsSVGStopElement.cpp \
 		nsSVGStyleElement.cpp \
 		nsSVGSwitchElement.cpp \
 		nsSVGSymbolElement.cpp \
 		nsSVGTSpanElement.cpp \
 		nsSVGTextContentElement.cpp \
 		nsSVGTextElement.cpp \
 		nsSVGTextPathElement.cpp \
+		nsSVGTextPositioningElement.cpp \
 		nsSVGTitleElement.cpp \
 		nsSVGTransform.cpp \
 		nsSVGTransformList.cpp \
 		nsSVGTransformListParser.cpp \
 		nsSVGUseElement.cpp \
 		nsSVGValue.cpp \
 		nsSVGViewBox.cpp \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/nsSVGAltGlyphElement.cpp
@@ -0,0 +1,209 @@
+/* -*- 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 Robert Longson.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 "nsSVGStylableElement.h"
+#include "nsGkAtoms.h"
+#include "nsIDOMSVGAltGlyphElement.h"
+#include "nsIDOMSVGURIReference.h"
+#include "nsSVGString.h"
+#include "nsSVGTextPositioningElement.h"
+
+typedef nsSVGStylableElement nsSVGAltGlyphElementBase;
+
+class nsSVGAltGlyphElement : public nsSVGAltGlyphElementBase,
+                             public nsIDOMSVGAltGlyphElement,
+                             public nsIDOMSVGURIReference, 
+                             public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
+{
+protected:
+  friend nsresult NS_NewSVGAltGlyphElement(nsIContent **aResult,
+                                           nsINodeInfo *aNodeInfo);
+  nsSVGAltGlyphElement(nsINodeInfo* aNodeInfo);
+  nsresult Init();
+  
+public:
+  // interfaces:
+  
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDOMSVGALTGLYPHELEMENT
+  NS_DECL_NSIDOMSVGURIREFERENCE
+
+  // xxx If xpcom allowed virtual inheritance we wouldn't need to
+  // forward here :-(
+  NS_FORWARD_NSIDOMNODE(nsSVGAltGlyphElementBase::)
+  NS_FORWARD_NSIDOMELEMENT(nsSVGAltGlyphElementBase::)
+  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAltGlyphElementBase::)
+  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
+  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::)
+
+  // nsIContent interface
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+protected:
+  virtual nsSVGTextContainerFrame* GetTextContainerFrame() {
+    return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
+  }
+
+  // nsSVGElement overrides
+  virtual StringAttributesInfo GetStringInfo();
+
+  virtual PRBool IsEventName(nsIAtom* aName);
+
+  enum { HREF };
+  nsSVGString mStringAttributes[1];
+  static StringInfo sStringInfo[1];
+
+};
+
+nsSVGElement::StringInfo nsSVGAltGlyphElement::sStringInfo[1] =
+{
+  { &nsGkAtoms::href, kNameSpaceID_XLink }
+};
+
+NS_IMPL_NS_NEW_SVG_ELEMENT(AltGlyph)
+
+//----------------------------------------------------------------------
+// nsISupports methods
+
+NS_IMPL_ADDREF_INHERITED(nsSVGAltGlyphElement,nsSVGAltGlyphElementBase)
+NS_IMPL_RELEASE_INHERITED(nsSVGAltGlyphElement,nsSVGAltGlyphElementBase)
+
+DOMCI_DATA(SVGAltGlyphElement, nsSVGAltGlyphElement)
+
+NS_INTERFACE_TABLE_HEAD(nsSVGAltGlyphElement)
+  NS_NODE_INTERFACE_TABLE7(nsSVGAltGlyphElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGAltGlyphElement,
+                           nsIDOMSVGTextPositioningElement, nsIDOMSVGTextContentElement,
+                           nsIDOMSVGURIReference)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAltGlyphElement)
+NS_INTERFACE_MAP_END_INHERITING(nsSVGAltGlyphElementBase)
+
+//----------------------------------------------------------------------
+// Implementation
+
+nsSVGAltGlyphElement::nsSVGAltGlyphElement(nsINodeInfo *aNodeInfo)
+  : nsSVGAltGlyphElementBase(aNodeInfo)
+{
+}
+
+nsresult
+nsSVGAltGlyphElement::Init()
+{
+  nsresult rv = nsSVGAltGlyphElementBase::Init();
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  rv = Initialise(this);
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  return rv;
+}
+
+//----------------------------------------------------------------------
+// nsIDOMNode methods
+
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGAltGlyphElement)
+
+//----------------------------------------------------------------------
+// nsIDOMSVGURIReference methods
+
+/* readonly attribute nsIDOMSVGAnimatedString href; */
+NS_IMETHODIMP nsSVGAltGlyphElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
+{
+  return mStringAttributes[HREF].ToDOMAnimatedString(aHref, this);
+}
+
+//----------------------------------------------------------------------
+// nsIDOMSVGAltGlyphElement methods
+
+/* attribute DOMString glyphRef; */
+NS_IMETHODIMP nsSVGAltGlyphElement::GetGlyphRef(nsAString & aGlyphRef)
+{
+  GetAttr(kNameSpaceID_None, nsGkAtoms::glyphRef, aGlyphRef);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsSVGAltGlyphElement::SetGlyphRef(const nsAString & aGlyphRef)
+{
+  return SetAttr(kNameSpaceID_None, nsGkAtoms::glyphRef, aGlyphRef, PR_TRUE);
+}
+
+/* attribute DOMString format; */
+NS_IMETHODIMP nsSVGAltGlyphElement::GetFormat(nsAString & aFormat)
+{
+  GetAttr(kNameSpaceID_None, nsGkAtoms::format, aFormat);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsSVGAltGlyphElement::SetFormat(const nsAString & aFormat)
+{
+  return SetAttr(kNameSpaceID_None, nsGkAtoms::format, aFormat, PR_TRUE);
+}
+
+//----------------------------------------------------------------------
+// nsIContent methods
+
+NS_IMETHODIMP_(PRBool)
+nsSVGAltGlyphElement::IsAttributeMapped(const nsIAtom* name) const
+{
+  static const MappedAttributeEntry* const map[] = {
+    sColorMap,
+    sFillStrokeMap,
+    sFontSpecificationMap,
+    sGraphicsMap,
+    sTextContentElementsMap
+  };
+  
+  return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
+    nsSVGAltGlyphElementBase::IsAttributeMapped(name);
+}
+
+//----------------------------------------------------------------------
+// nsSVGElement overrides
+
+PRBool
+nsSVGAltGlyphElement::IsEventName(nsIAtom* aName)
+{
+  return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
+}
+
+nsSVGElement::StringAttributesInfo
+nsSVGAltGlyphElement::GetStringInfo()
+{
+  return StringAttributesInfo(mStringAttributes, sStringInfo,
+                              NS_ARRAY_LENGTH(sStringInfo));
+}
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -184,16 +184,17 @@ protected:
   virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                 const nsAString* aValue, PRBool aNotify);
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
                                 const nsAString& aValue, nsAttrValue& aResult);
   static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
                                               nsIAtom* aAttribute,
                                               const nsAString& aValue);
 
+  friend class nsSVGTextPositioningElement;
   // Hooks for subclasses
   virtual PRBool IsEventName(nsIAtom* aName);
 
   void UpdateContentStyleRule();
 #ifdef MOZ_SMIL
   void UpdateAnimatedContentStyleRule();
   nsICSSStyleRule* GetAnimatedContentStyleRule();
 #endif // MOZ_SMIL
--- a/content/svg/content/src/nsSVGElementFactory.cpp
+++ b/content/svg/content/src/nsSVGElementFactory.cpp
@@ -45,16 +45,18 @@
 #include "nsContentDLF.h"
 #include "nsContentUtils.h"
 #include "nsSVGUtils.h"
 #include "nsDebug.h"
 
 nsresult
 NS_NewSVGAElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
 nsresult
+NS_NewSVGAltGlyphElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
+nsresult
 NS_NewSVGPolylineElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
 nsresult
 NS_NewSVGPolygonElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
 nsresult
 NS_NewSVGCircleElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
 nsresult
 NS_NewSVGEllipseElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
 nsresult
@@ -184,16 +186,18 @@ NS_NewSVGElement(nsIContent** aResult, n
   nsIDocument *doc = aNodeInfo->GetDocument();
   if (doc)
     doc->EnsureCatalogStyleSheet(kSVGStyleSheetURI);
 
   nsIAtom *name = aNodeInfo->NameAtom();
   
   if (name == nsGkAtoms::a)
     return NS_NewSVGAElement(aResult, aNodeInfo);
+  if (name == nsGkAtoms::altGlyph)
+    return NS_NewSVGAltGlyphElement(aResult, aNodeInfo);
   if (name == nsGkAtoms::polyline)
     return NS_NewSVGPolylineElement(aResult, aNodeInfo);
   if (name == nsGkAtoms::polygon)
     return NS_NewSVGPolygonElement(aResult, aNodeInfo);
   if (name == nsGkAtoms::circle)
     return NS_NewSVGCircleElement(aResult, aNodeInfo);
   if (name == nsGkAtoms::ellipse)
     return NS_NewSVGEllipseElement(aResult, aNodeInfo);
--- a/content/svg/content/src/nsSVGTSpanElement.cpp
+++ b/content/svg/content/src/nsSVGTSpanElement.cpp
@@ -34,72 +34,57 @@
  * 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 "nsSVGStylableElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGTSpanElement.h"
-#include "nsCOMPtr.h"
-#include "nsSVGAnimatedLengthList.h"
-#include "nsSVGAnimatedNumberList.h"
-#include "nsSVGLengthList.h"
-#include "nsSVGNumberList.h"
 #include "nsSVGSVGElement.h"
-#include "nsSVGTextContentElement.h"
-#include "nsIFrame.h"
-#include "nsDOMError.h"
+#include "nsSVGTextPositioningElement.h"
 
 typedef nsSVGStylableElement nsSVGTSpanElementBase;
 
 class nsSVGTSpanElement : public nsSVGTSpanElementBase,
-                          public nsIDOMSVGTSpanElement,  // : nsIDOMSVGTextPositioningElement
-                          public nsSVGTextContentElement // = nsIDOMSVGTextContentElement
+                          public nsIDOMSVGTSpanElement,
+                          public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
 {
 protected:
   friend nsresult NS_NewSVGTSpanElement(nsIContent **aResult,
                                         nsINodeInfo *aNodeInfo);
   nsSVGTSpanElement(nsINodeInfo* aNodeInfo);
   nsresult Init();
   
 public:
   // interfaces:
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGTSPANELEMENT
-  NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
 
   // xxx If xpcom allowed virtual inheritance we wouldn't need to
   // forward here :-(
   NS_FORWARD_NSIDOMNODE(nsSVGTSpanElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGTSpanElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTSpanElementBase::)
   NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
+  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::)
 
   // nsIContent interface
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
   virtual nsSVGTextContainerFrame* GetTextContainerFrame() {
     return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
   }
 
   // nsSVGElement overrides
   virtual PRBool IsEventName(nsIAtom* aName);
-
-  // nsIDOMSVGTextPositioning properties:
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX;
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
-
 };
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(TSpan)
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
@@ -128,77 +113,18 @@ nsSVGTSpanElement::nsSVGTSpanElement(nsI
 
   
 nsresult
 nsSVGTSpanElement::Init()
 {
   nsresult rv = nsSVGTSpanElementBase::Init();
   NS_ENSURE_SUCCESS(rv,rv);
 
-  // Create mapped properties:
-
-  // DOM property: nsIDOMSVGTextPositioningElement::x, #IMPLIED attrib: x
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mX),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::x, mX);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-  
-  // DOM property: nsIDOMSVGTextPositioningElement::y, #IMPLIED attrib: y
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mY),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::y, mY);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  // DOM property: nsIDOMSVGTextPositioningElement::dx, #IMPLIED attrib: dx
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdX),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::dx, mdX);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-  
-  // DOM property: nsIDOMSVGTextPositioningElement::dy, #IMPLIED attrib: dy
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdY),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::dy, mdY);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
-  {
-    nsCOMPtr<nsIDOMSVGNumberList> numberList;
-    rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
-                                     numberList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
+  rv = Initialise(this);
+  NS_ENSURE_SUCCESS(rv,rv);
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
@@ -206,59 +132,16 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTSp
 
 
 //----------------------------------------------------------------------
 // nsIDOMSVGTSpanElement methods
 
 // - no methods -
 
 //----------------------------------------------------------------------
-// nsIDOMSVGTextPositioningElement methods
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList x; */
-NS_IMETHODIMP nsSVGTSpanElement::GetX(nsIDOMSVGAnimatedLengthList * *aX)
-{
-  *aX = mX;
-  NS_IF_ADDREF(*aX);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList y; */
-NS_IMETHODIMP nsSVGTSpanElement::GetY(nsIDOMSVGAnimatedLengthList * *aY)
-{
-  *aY = mY;
-  NS_IF_ADDREF(*aY);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList dx; */
-NS_IMETHODIMP nsSVGTSpanElement::GetDx(nsIDOMSVGAnimatedLengthList * *aDx)
-{
-  *aDx = mdX;
-  NS_IF_ADDREF(*aDx);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList dy; */
-NS_IMETHODIMP nsSVGTSpanElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy)
-{
-  *aDy = mdY;
-  NS_IF_ADDREF(*aDy);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
-NS_IMETHODIMP nsSVGTSpanElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
-{
-  *aRotate = mRotate;
-  NS_IF_ADDREF(*aRotate);
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(PRBool)
 nsSVGTSpanElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sColorMap,
     sFillStrokeMap,
--- a/content/svg/content/src/nsSVGTextElement.cpp
+++ b/content/svg/content/src/nsSVGTextElement.cpp
@@ -35,68 +35,57 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGGraphicElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGTextElement.h"
 #include "nsCOMPtr.h"
-#include "nsSVGAnimatedLengthList.h"
-#include "nsSVGAnimatedNumberList.h"
-#include "nsSVGLengthList.h"
-#include "nsSVGNumberList.h"
 #include "nsSVGSVGElement.h"
-#include "nsSVGTextContentElement.h"
+#include "nsSVGTextPositioningElement.h"
 #include "nsIFrame.h"
 #include "nsDOMError.h"
 
 typedef nsSVGGraphicElement nsSVGTextElementBase;
 
 class nsSVGTextElement : public nsSVGTextElementBase,
-                         public nsIDOMSVGTextElement,   // : nsIDOMSVGTextPositioningElement
-                         public nsSVGTextContentElement // = nsIDOMSVGTextContentElement
+                         public nsIDOMSVGTextElement,
+                         public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
 {
 protected:
   friend nsresult NS_NewSVGTextElement(nsIContent **aResult,
                                        nsINodeInfo *aNodeInfo);
   nsSVGTextElement(nsINodeInfo* aNodeInfo);
   nsresult Init();
   
 public:
   // interfaces:
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGTEXTELEMENT
-  NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
 
   // xxx If xpcom allowed virtual inheritance we wouldn't need to
   // forward here :-(
   NS_FORWARD_NSIDOMNODE(nsSVGTextElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGTextElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextElementBase::)
   NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
+  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::)
 
   // nsIContent interface
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
   virtual nsSVGTextContainerFrame* GetTextContainerFrame() {
     return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
   }
 
-  // nsIDOMSVGTextPositioning properties:
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX;
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
-  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
-
 };
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Text)
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
@@ -124,77 +113,18 @@ nsSVGTextElement::nsSVGTextElement(nsINo
 }
   
 nsresult
 nsSVGTextElement::Init()
 {
   nsresult rv = nsSVGTextElementBase::Init();
   NS_ENSURE_SUCCESS(rv,rv);
 
-  // Create mapped properties:
-
-  // DOM property: nsIDOMSVGTextPositioningElement::x, #IMPLIED attrib: x
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mX),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::x, mX);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-  
-  // DOM property: nsIDOMSVGTextPositioningElement::y, #IMPLIED attrib: y
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mY),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::y, mY);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  // DOM property: nsIDOMSVGTextPositioningElement::dx, #IMPLIED attrib: dx
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdX),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::dx, mdX);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-  
-  // DOM property: nsIDOMSVGTextPositioningElement::dy, #IMPLIED attrib: dy
-  {
-    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdY),
-                                     lengthList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::dy, mdY);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
-  {
-    nsCOMPtr<nsIDOMSVGNumberList> numberList;
-    rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
-                                     numberList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
+  rv = Initialise(this);
+  NS_ENSURE_SUCCESS(rv,rv);
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
@@ -202,59 +132,16 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTex
 
 
 //----------------------------------------------------------------------
 // nsIDOMSVGTextElement methods
 
 // - no methods -
 
 //----------------------------------------------------------------------
-// nsIDOMSVGTextPositioningElement methods
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList x; */
-NS_IMETHODIMP nsSVGTextElement::GetX(nsIDOMSVGAnimatedLengthList * *aX)
-{
-  *aX = mX;
-  NS_IF_ADDREF(*aX);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList y; */
-NS_IMETHODIMP nsSVGTextElement::GetY(nsIDOMSVGAnimatedLengthList * *aY)
-{
-  *aY = mY;
-  NS_IF_ADDREF(*aY);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList dx; */
-NS_IMETHODIMP nsSVGTextElement::GetDx(nsIDOMSVGAnimatedLengthList * *aDx)
-{
-  *aDx = mdX;
-  NS_IF_ADDREF(*aDx);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedLengthList dy; */
-NS_IMETHODIMP nsSVGTextElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy)
-{
-  *aDy = mdY;
-  NS_IF_ADDREF(*aDy);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
-NS_IMETHODIMP nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
-{
-  *aRotate = mRotate;
-  NS_IF_ADDREF(*aRotate);
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(PRBool)
 nsSVGTextElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sTextContentElementsMap,
     sFontSpecificationMap
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/nsSVGTextPositioningElement.cpp
@@ -0,0 +1,152 @@
+/* -*- 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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 "nsSVGTextPositioningElement.h"
+#include "nsSVGAnimatedLengthList.h"
+#include "nsSVGAnimatedNumberList.h"
+#include "nsSVGLengthList.h"
+#include "nsSVGNumberList.h"
+
+nsresult
+nsSVGTextPositioningElement::Initialise(nsSVGElement *aSVGElement)
+{
+  nsresult rv;
+  // Create mapped properties:
+
+  // DOM property: nsIDOMSVGTextPositioningElement::x, #IMPLIED attrib: x
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::X);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mX),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::x, mX);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+  
+  // DOM property: nsIDOMSVGTextPositioningElement::y, #IMPLIED attrib: y
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::Y);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mY),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::y, mY);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  // DOM property: nsIDOMSVGTextPositioningElement::dx, #IMPLIED attrib: dx
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::X);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdX),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::dx, mdX);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+  
+  // DOM property: nsIDOMSVGTextPositioningElement::dy, #IMPLIED attrib: dy
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::Y);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdY),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::dy, mdY);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
+  {
+    nsCOMPtr<nsIDOMSVGNumberList> numberList;
+    rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
+                                     numberList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  return rv;
+}
+
+//----------------------------------------------------------------------
+// nsIDOMSVGTextPositioningElement methods
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList x; */
+NS_IMETHODIMP nsSVGTextPositioningElement::GetX(nsIDOMSVGAnimatedLengthList * *aX)
+{
+  *aX = mX;
+  NS_IF_ADDREF(*aX);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList y; */
+NS_IMETHODIMP nsSVGTextPositioningElement::GetY(nsIDOMSVGAnimatedLengthList * *aY)
+{
+  *aY = mY;
+  NS_IF_ADDREF(*aY);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList dx; */
+NS_IMETHODIMP nsSVGTextPositioningElement::GetDx(nsIDOMSVGAnimatedLengthList * *aDx)
+{
+  *aDx = mdX;
+  NS_IF_ADDREF(*aDx);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList dy; */
+NS_IMETHODIMP nsSVGTextPositioningElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy)
+{
+  *aDy = mdY;
+  NS_IF_ADDREF(*aDy);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
+NS_IMETHODIMP nsSVGTextPositioningElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
+{
+  *aRotate = mRotate;
+  NS_IF_ADDREF(*aRotate);
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/nsSVGTextPositioningElement.h
@@ -0,0 +1,60 @@
+/* -*- 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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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_SVGTEXTPOSITIONINGELEMENTBASE_H__
+#define __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__
+
+#include "nsIDOMSVGTextPositionElem.h"
+#include "nsSVGTextContentElement.h"
+#include "nsIDOMSVGAnimatedLengthList.h"
+#include "nsIDOMSVGAnimatedNumberList.h"
+
+class nsSVGTextPositioningElement : public nsSVGTextContentElement
+{
+public:
+  NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
+
+protected:
+  nsresult Initialise(nsSVGElement *aSVGElement);
+
+  // nsIDOMSVGTextPositioning properties:
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX;
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
+  nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
+};
+
+#endif
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -348,16 +348,17 @@
 #include "nsIDOMXPathExpression.h"
 #include "nsIDOMNSXPathExpression.h"
 #include "nsIDOMXPathNSResolver.h"
 #include "nsIDOMXPathResult.h"
 
 #ifdef MOZ_SVG
 #include "nsIDOMGetSVGDocument.h"
 #include "nsIDOMSVGAElement.h"
+#include "nsIDOMSVGAltGlyphElement.h"
 #include "nsIDOMSVGAngle.h"
 #include "nsIDOMSVGAnimatedAngle.h"
 #include "nsIDOMSVGAnimatedBoolean.h"
 #include "nsIDOMSVGAnimatedEnum.h"
 #include "nsIDOMSVGAnimatedInteger.h"
 #include "nsIDOMSVGAnimatedLength.h"
 #include "nsIDOMSVGAnimatedLengthList.h"
 #include "nsIDOMSVGAnimatedNumber.h"
@@ -932,16 +933,18 @@ static nsDOMClassInfoData sClassInfoData
 #ifdef MOZ_SVG
   // SVG document
   NS_DEFINE_CLASSINFO_DATA(SVGDocument, nsDocumentSH,
                            DOCUMENT_SCRIPTABLE_FLAGS)
 
   // SVG element classes
   NS_DEFINE_CLASSINFO_DATA(SVGAElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(SVGAltGlyphElement, nsElementSH,
+                           ELEMENT_SCRIPTABLE_FLAGS)
 #ifdef MOZ_SMIL
   NS_DEFINE_CLASSINFO_DATA(SVGAnimateElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGAnimateTransformElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGSetElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
 #endif // MOZ_SMIL
@@ -2844,16 +2847,26 @@ nsDOMClassInfo::Init()
 
   // SVG element classes
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAElement, nsIDOMSVGAElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAElement)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(SVGAltGlyphElement, nsIDOMSVGAltGlyphElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextPositioningElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextContentElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
+    DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
+  DOM_CLASSINFO_MAP_END
+
 #ifdef MOZ_SMIL
   DOM_CLASSINFO_MAP_BEGIN(SVGAnimateElement, nsIDOMSVGAnimateElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -225,16 +225,17 @@ DOMCI_CLASS(CSSMozDocumentRule)
 DOMCI_CLASS(BeforeUnloadEvent)
 
 #ifdef MOZ_SVG
 // The SVG document
 DOMCI_CLASS(SVGDocument)
 
 // SVG element classes
 DOMCI_CLASS(SVGAElement)
+DOMCI_CLASS(SVGAltGlyphElement)
 #ifdef MOZ_SMIL
 DOMCI_CLASS(SVGAnimateElement)
 DOMCI_CLASS(SVGAnimateTransformElement)
 DOMCI_CLASS(SVGSetElement)
 #endif // MOZ_SMIL
 DOMCI_CLASS(SVGCircleElement)
 DOMCI_CLASS(SVGClipPathElement)
 DOMCI_CLASS(SVGDefsElement)
--- a/dom/interfaces/svg/Makefile.in
+++ b/dom/interfaces/svg/Makefile.in
@@ -47,30 +47,31 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= dom
 XPIDL_MODULE	= dom_svg
 
 
 XPIDLSRCS	= \
 		nsIDOMGetSVGDocument.idl \
 		nsIDOMSVGAElement.idl \
+		nsIDOMSVGAltGlyphElement.idl \
 		nsIDOMSVGAngle.idl \
 		nsIDOMSVGAnimatedAngle.idl \
 		nsIDOMSVGAnimatedBoolean.idl \
 		nsIDOMSVGAnimatedEnum.idl \
 		nsIDOMSVGAnimatedInteger.idl \
 		nsIDOMSVGAnimatedLength.idl \
 		nsIDOMSVGAnimatedLengthList.idl \
 		nsIDOMSVGAnimatedNumber.idl \
 		nsIDOMSVGAnimatedNumberList.idl \
 		nsIDOMSVGAnimatedPathData.idl \
 		nsIDOMSVGAnimatedPoints.idl \
+		nsIDOMSVGAnimatedRect.idl \
 		nsIDOMSVGAnimatedString.idl \
 		nsIDOMSVGAnimPresAspRatio.idl \
-		nsIDOMSVGAnimatedRect.idl \
 		nsIDOMSVGAnimTransformList.idl \
 		nsIDOMSVGCircleElement.idl \
 		nsIDOMSVGClipPathElement.idl \
 		nsIDOMSVGDefsElement.idl \
 		nsIDOMSVGDescElement.idl \
 		nsIDOMSVGDocument.idl \
 		nsIDOMSVGElement.idl \
 		nsIDOMSVGEllipseElement.idl \
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/svg/nsIDOMSVGAltGlyphElement.idl
@@ -0,0 +1,55 @@
+/* -*- Mode: IDL; 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
+ *   Robert Longson <longsonr@yahoo.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 "nsIDOMSVGTextPositionElem.idl"
+
+[scriptable, uuid(b688b5fd-48b6-447c-bb20-766a9392d0d0)]
+interface nsIDOMSVGAltGlyphElement : nsIDOMSVGTextPositioningElement
+/*
+        The SVG DOM makes use of multiple interface inheritance.
+        Since XPCOM only supports single interface inheritance,
+        the best thing that we can do is to promise that whenever
+        an object implements _this_ interface it will also
+        implement the following interfaces. (We then have to QI to
+        hop between them.)
+
+    nsIDOMSVGURIReference
+*/
+{
+  attribute DOMString glyphRef;
+  // raises DOMException on setting
+  attribute DOMString format;
+  // raises DOMException on setting
+};
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -4789,17 +4789,17 @@ nsCSSFrameConstructor::FindSVGData(nsICo
     if (ancestorFrame) {
       nsSVGTextContainerFrame* metrics = do_QueryFrame(ancestorFrame);
       // Text cannot be nested
       if (metrics) {
         return &sGenericContainerData;
       }
     }
   }
-  else if (aTag == nsGkAtoms::tspan) {
+  else if (aTag == nsGkAtoms::tspan || aTag == nsGkAtoms::altGlyph) {
     NS_ASSERTION(aParentFrame, "Should have aParentFrame here");
     nsIFrame *ancestorFrame =
       nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
     if (ancestorFrame) {
       nsSVGTextContainerFrame* metrics = do_QueryFrame(ancestorFrame);
       if (!metrics) {
         return &sGenericContainerData;
       }
@@ -4825,16 +4825,17 @@ nsCSSFrameConstructor::FindSVGData(nsICo
     SIMPLE_SVG_CREATE(line, NS_NewSVGPathGeometryFrame),
     SIMPLE_SVG_CREATE(rect, NS_NewSVGPathGeometryFrame),
     SIMPLE_SVG_CREATE(path, NS_NewSVGPathGeometryFrame),
     SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame),
     { &nsGkAtoms::foreignObject,
       FULL_CTOR_FCDATA(FCDATA_DISALLOW_OUT_OF_FLOW,
                        &nsCSSFrameConstructor::ConstructSVGForeignObjectFrame) },
     SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame),
+    SIMPLE_SVG_CREATE(altGlyph, NS_NewSVGTSpanFrame),
     SIMPLE_SVG_CREATE(text, NS_NewSVGTextFrame),
     SIMPLE_SVG_CREATE(tspan, NS_NewSVGTSpanFrame),
     SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame),
     SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame),
     SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame),
     SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame),
     SIMPLE_SVG_CREATE(marker, NS_NewSVGMarkerFrame),
     SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame),
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/altGlyph-01-ref.svg
@@ -0,0 +1,14 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/licenses/publicdomain/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
+     font-family="monospace" font-size="20" xml:space="preserve">
+
+  <title>Reference to check that that altGlyph falls back to tspan behaviour</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=456286 -->
+
+  <text><tspan x="20" y="20" rotate="90">T</tspan>EST1</text>
+
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/altGlyph-01.svg
@@ -0,0 +1,14 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/licenses/publicdomain/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
+     font-family="monospace" font-size="20" xml:space="preserve">
+
+  <title>Testcase to check that altGlyph falls back to tspan behaviour</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=456286 -->
+
+  <text><altGlyph x="20" y="20" rotate="90">T</altGlyph>EST1</text>
+
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -11,16 +11,17 @@ include filters/reftest.list
 include smil/reftest.list
 
 # Mozilla only tests (i.e. those containing XUL/XBL/etc.)
 include moz-only/reftest.list
 
 # svg-integration tests (using svg effects in e.g. HTML)
 include svg-integration/reftest.list
 
+== altGlyph-01.svg altGlyph-01-ref.svg
 == clip-01.svg pass.svg
 == clip-02a.svg clip-02-ref.svg
 == clip-02b.svg clip-02-ref.svg
 == clipPath-advanced-01.svg pass.svg
 == clipPath-and-shape-rendering-01.svg clipPath-and-shape-rendering-01-ref.svg
 == clipPath-basic-01.svg pass.svg
 == clipPath-basic-02.svg pass.svg
 == clipPath-basic-03.svg pass.svg
--- a/layout/svg/base/src/nsSVGTSpanFrame.cpp
+++ b/layout/svg/base/src/nsSVGTSpanFrame.cpp
@@ -32,16 +32,17 @@
  * 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 "nsIDOMSVGTSpanElement.h"
+#include "nsIDOMSVGAltGlyphElement.h"
 #include "nsSVGTSpanFrame.h"
 #include "nsSVGUtils.h"
 #include "nsSVGTextFrame.h"
 #include "nsSVGOuterSVGFrame.h"
 
 //----------------------------------------------------------------------
 // Implementation
 
@@ -86,17 +87,18 @@ nsSVGTSpanFrame::Init(nsIContent* aConte
     NS_ASSERTION(ancestorFrame, "Must have ancestor");
 
     nsSVGTextContainerFrame *metrics = do_QueryFrame(ancestorFrame);
     NS_ASSERTION(metrics,
                  "trying to construct an SVGTSpanFrame for an invalid "
                  "container");
 
     nsCOMPtr<nsIDOMSVGTSpanElement> tspan = do_QueryInterface(aContent);
-    NS_ASSERTION(tspan, "Content is not an SVG tspan");
+    nsCOMPtr<nsIDOMSVGAltGlyphElement> altGlyph = do_QueryInterface(aContent);
+    NS_ASSERTION(tspan || altGlyph, "Content is not an SVG tspan or altGlyph");
   }
 
   return nsSVGTSpanFrameBase::Init(aContent, aParent, aPrevInFlow);
 }
 #endif /* DEBUG */
 
 NS_IMETHODIMP
 nsSVGTSpanFrame::AttributeChanged(PRInt32         aNameSpaceID,
--- a/layout/svg/base/src/nsSVGTSpanFrame.h
+++ b/layout/svg/base/src/nsSVGTSpanFrame.h
@@ -47,17 +47,17 @@ typedef nsSVGTextContainerFrame nsSVGTSp
 
 class nsSVGTSpanFrame : public nsSVGTSpanFrameBase,
                         public nsISVGGlyphFragmentNode
 {
   friend nsIFrame*
   NS_NewSVGTSpanFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   nsSVGTSpanFrame(nsStyleContext* aContext) :
-    nsSVGTextContainerFrame(aContext) {}
+    nsSVGTSpanFrameBase(aContext) {}
 
 public:
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame:
 #ifdef DEBUG
   NS_IMETHOD Init(nsIContent*      aContent,