Bug 561654. nsSVGTextPositioningElement should be on the primary inheritance chain. r=longsonr
authorJonathan Watt <jwatt@jwatt.org>
Mon, 24 May 2010 16:58:24 +0200
changeset 42610 17a065ad96f40add4f72927d035157075c52a59a
parent 42609 9ef7ae88fb81893b96b4b447cf140b8fa327895c
child 42611 f87f31d83650b20a9065f4dabf24e2cf1604baba
child 42782 e5122642e84f0eb819fa51c48cbf10ec28fc711f
push idunknown
push userunknown
push dateunknown
reviewerslongsonr
bugs561654
milestone1.9.3a5pre
Bug 561654. nsSVGTextPositioningElement should be on the primary inheritance chain. r=longsonr
content/svg/content/src/nsSVGAltGlyphElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGTSpanElement.cpp
content/svg/content/src/nsSVGTextContentElement.h
content/svg/content/src/nsSVGTextElement.cpp
content/svg/content/src/nsSVGTextPathElement.h
content/svg/content/src/nsSVGTextPositioningElement.cpp
content/svg/content/src/nsSVGTextPositioningElement.h
--- a/content/svg/content/src/nsSVGAltGlyphElement.cpp
+++ b/content/svg/content/src/nsSVGAltGlyphElement.cpp
@@ -27,60 +27,54 @@
  * 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;
+typedef nsSVGTextPositioningElement nsSVGAltGlyphElementBase;
 
-class nsSVGAltGlyphElement : public nsSVGAltGlyphElementBase,
+class nsSVGAltGlyphElement : public nsSVGAltGlyphElementBase, // = nsIDOMSVGTextPositioningElement
                              public nsIDOMSVGAltGlyphElement,
-                             public nsIDOMSVGURIReference, 
-                             public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
+                             public nsIDOMSVGURIReference
 {
 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::)
+  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGAltGlyphElementBase::)
+  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGAltGlyphElementBase::)
 
   // 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];
@@ -114,27 +108,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGAlt
 //----------------------------------------------------------------------
 // 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
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -189,17 +189,16 @@ 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/nsSVGTSpanElement.cpp
+++ b/content/svg/content/src/nsSVGTSpanElement.cpp
@@ -31,57 +31,51 @@
  * 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 "nsIDOMSVGTSpanElement.h"
 #include "nsSVGSVGElement.h"
 #include "nsSVGTextPositioningElement.h"
 
-typedef nsSVGStylableElement nsSVGTSpanElementBase;
+typedef nsSVGTextPositioningElement nsSVGTSpanElementBase;
 
-class nsSVGTSpanElement : public nsSVGTSpanElementBase,
-                          public nsIDOMSVGTSpanElement,
-                          public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
+class nsSVGTSpanElement : public nsSVGTSpanElementBase, // = nsIDOMSVGTextPositioningElement
+                          public nsIDOMSVGTSpanElement
 {
 protected:
   friend nsresult NS_NewSVGTSpanElement(nsIContent **aResult,
                                         nsINodeInfo *aNodeInfo);
   nsSVGTSpanElement(nsINodeInfo* aNodeInfo);
-  nsresult Init();
   
 public:
   // interfaces:
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGTSPANELEMENT
 
   // 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::)
+  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTSpanElementBase::)
+  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTSpanElementBase::)
 
   // 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);
 };
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(TSpan)
 
@@ -107,28 +101,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGTSp
 
 nsSVGTSpanElement::nsSVGTSpanElement(nsINodeInfo *aNodeInfo)
   : nsSVGTSpanElementBase(aNodeInfo)
 {
 
 }
 
   
-nsresult
-nsSVGTSpanElement::Init()
-{
-  nsresult rv = nsSVGTSpanElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  rv = Initialise(this);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  return rv;
-}
-
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTSpanElement)
 
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGTextContentElement.h
+++ b/content/svg/content/src/nsSVGTextContentElement.h
@@ -36,19 +36,35 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGTEXTCONTENTELEMENTBASE_H__
 #define __NS_SVGTEXTCONTENTELEMENTBASE_H__
 
 #include "nsIDOMSVGTextContentElement.h"
 #include "nsSVGTextContainerFrame.h"
+#include "nsSVGStylableElement.h"
 
-class nsSVGTextContentElement
+typedef nsSVGStylableElement nsSVGTextContentElementBase;
+
+/**
+ * Note that nsSVGTextElement does not inherit nsSVGTextPositioningElement, or
+ * this class - it reimplements us instead (see its documenting comment). The
+ * upshot is that any changes to this class also need to be made in
+ * nsSVGTextElement.
+ */
+class nsSVGTextContentElement : public nsSVGTextContentElementBase
 {
 public:
   NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
 
 protected:
-  virtual nsSVGTextContainerFrame* GetTextContainerFrame()=0;
+
+  nsSVGTextContentElement(nsINodeInfo *aNodeInfo)
+    : nsSVGTextContentElementBase(aNodeInfo)
+  {}
+
+  nsSVGTextContainerFrame* GetTextContainerFrame() {
+    return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
+  }
 };
 
 #endif
--- a/content/svg/content/src/nsSVGTextElement.cpp
+++ b/content/svg/content/src/nsSVGTextElement.cpp
@@ -39,53 +39,74 @@
 #include "nsSVGGraphicElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGTextElement.h"
 #include "nsCOMPtr.h"
 #include "nsSVGSVGElement.h"
 #include "nsSVGTextPositioningElement.h"
 #include "nsIFrame.h"
 #include "nsDOMError.h"
+#include "nsSVGLengthList.h"
+#include "nsSVGAnimatedLengthList.h"
+#include "nsSVGNumberList.h"
+#include "nsSVGAnimatedNumberList.h"
 
 typedef nsSVGGraphicElement nsSVGTextElementBase;
 
+/**
+ * This class does not inherit nsSVGTextPositioningElement - it reimplements it
+ * instead.
+ *
+ * Ideally this class would inherit nsSVGTextPositioningElement in addition to
+ * nsSVGGraphicElement, but we don't want two instances of nsSVGStylableElement
+ * and all the classes it inherits. Instead we choose to inherit one of the
+ * classes (nsSVGGraphicElement) and reimplement the missing pieces from the
+ * other (nsSVGTextPositioningElement (and thus nsSVGTextContentElement)). Care
+ * must be taken when making changes to the reimplemented pieces to keep
+ * nsSVGTextPositioningElement in sync (and vice versa).
+ */
 class nsSVGTextElement : public nsSVGTextElementBase,
-                         public nsIDOMSVGTextElement,
-                         public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
+                         public nsIDOMSVGTextElement // 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
+  NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
 
   // 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() {
+  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
@@ -113,34 +134,280 @@ nsSVGTextElement::nsSVGTextElement(nsINo
 }
   
 nsresult
 nsSVGTextElement::Init()
 {
   nsresult rv = nsSVGTextElementBase::Init();
   NS_ENSURE_SUCCESS(rv,rv);
 
-  rv = Initialise(this);
-  NS_ENSURE_SUCCESS(rv,rv);
+  // 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);
+  }
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTextElement)
 
 
 //----------------------------------------------------------------------
 // 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;
+}
+
+
+//----------------------------------------------------------------------
+// nsIDOMSVGTextContentElement methods
+
+/* readonly attribute nsIDOMSVGAnimatedLength textLength; */
+NS_IMETHODIMP
+nsSVGTextElement::GetTextLength(nsIDOMSVGAnimatedLength * *aTextLength)
+{
+  NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetTextLength");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedEnumeration lengthAdjust; */
+NS_IMETHODIMP
+nsSVGTextElement::GetLengthAdjust(nsIDOMSVGAnimatedEnumeration * *aLengthAdjust)
+{
+  NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetLengthAdjust");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* long getNumberOfChars (); */
+NS_IMETHODIMP
+nsSVGTextElement::GetNumberOfChars(PRInt32 *_retval)
+{
+  *_retval = 0;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (metrics)
+    *_retval = metrics->GetNumberOfChars();
+
+  return NS_OK;
+}
+
+/* float getComputedTextLength (); */
+NS_IMETHODIMP
+nsSVGTextElement::GetComputedTextLength(float *_retval)
+{
+  *_retval = 0.0;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (metrics)
+    *_retval = metrics->GetComputedTextLength();
+
+  return NS_OK;
+}
+
+/* float getSubStringLength (in unsigned long charnum, in unsigned long nchars); */
+NS_IMETHODIMP
+nsSVGTextElement::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
+{
+  *_retval = 0.0f;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (!metrics)
+    return NS_OK;
+
+  PRUint32 charcount = metrics->GetNumberOfChars();
+  if (charcount <= charnum || nchars > charcount - charnum)
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+  if (nchars == 0)
+    return NS_OK;
+
+  *_retval = metrics->GetSubStringLength(charnum, nchars);
+  return NS_OK;
+}
+
+/* nsIDOMSVGPoint getStartPositionOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
+{
+  *_retval = nsnull;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetStartPositionOfChar(charnum, _retval);
+}
+
+/* nsIDOMSVGPoint getEndPositionOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
+{
+  *_retval = nsnull;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetEndPositionOfChar(charnum, _retval);
+}
+
+/* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
+{
+  *_retval = nsnull;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetExtentOfChar(charnum, _retval);
+}
+
+/* float getRotationOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetRotationOfChar(PRUint32 charnum, float *_retval)
+{
+  *_retval = 0.0;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetRotationOfChar(charnum, _retval);
+}
+
+/* long getCharNumAtPosition (in nsIDOMSVGPoint point); */
+NS_IMETHODIMP
+nsSVGTextElement::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
+{
+  if (!point)
+    return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
+
+  *_retval = -1;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (metrics)
+    *_retval = metrics->GetCharNumAtPosition(point);
+
+  return NS_OK;
+}
+
+/* void selectSubString (in unsigned long charnum, in unsigned long nchars); */
+NS_IMETHODIMP
+nsSVGTextElement::SelectSubString(PRUint32 charnum, PRUint32 nchars)
+{
+  NS_NOTYETIMPLEMENTED("nsSVGTextElement::SelectSubString");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(PRBool)
 nsSVGTextElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sTextContentElementsMap,
--- a/content/svg/content/src/nsSVGTextPathElement.h
+++ b/content/svg/content/src/nsSVGTextPathElement.h
@@ -38,22 +38,21 @@
 #ifndef __NS_SVGTEXTPATHELEMENT_H__
 #define __NS_SVGTEXTPATHELEMENT_H__
 
 #include "nsSVGEnum.h"
 #include "nsSVGLength2.h"
 #include "nsSVGString.h"
 #include "nsSVGTextContentElement.h"
 
-typedef nsSVGStylableElement nsSVGTextPathElementBase;
+typedef nsSVGTextContentElement nsSVGTextPathElementBase;
 
-class nsSVGTextPathElement : public nsSVGTextPathElementBase,
+class nsSVGTextPathElement : public nsSVGTextPathElementBase, // = nsIDOMSVGTextContentElement
                              public nsIDOMSVGTextPathElement,
-                             public nsIDOMSVGURIReference,
-                             public nsSVGTextContentElement // = nsIDOMSVGTextContentElement
+                             public nsIDOMSVGURIReference
 {
 friend class nsSVGTextPathFrame;
 
 protected:
   friend nsresult NS_NewSVGTextPathElement(nsIContent **aResult,
                                         nsINodeInfo *aNodeInfo);
   nsSVGTextPathElement(nsINodeInfo* aNodeInfo);
   
@@ -64,29 +63,25 @@ public:
   NS_DECL_NSIDOMSVGTEXTPATHELEMENT
   NS_DECL_NSIDOMSVGURIREFERENCE
 
   // xxx If xpcom allowed virtual inheritance we wouldn't need to
   // forward here :-(
   NS_FORWARD_NSIDOMNODE(nsSVGTextPathElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGTextPathElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextPathElementBase::)
-  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
+  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextPathElementBase::)
 
   // 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));
-  }
-
   virtual LengthAttributesInfo GetLengthInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
 
   virtual PRBool IsEventName(nsIAtom* aName);
 
   enum { STARTOFFSET };
   nsSVGLength2 mLengthAttributes[1];
--- a/content/svg/content/src/nsSVGTextPositioningElement.cpp
+++ b/content/svg/content/src/nsSVGTextPositioningElement.cpp
@@ -35,78 +35,80 @@
 
 #include "nsSVGTextPositioningElement.h"
 #include "nsSVGAnimatedLengthList.h"
 #include "nsSVGAnimatedNumberList.h"
 #include "nsSVGLengthList.h"
 #include "nsSVGNumberList.h"
 
 nsresult
-nsSVGTextPositioningElement::Initialise(nsSVGElement *aSVGElement)
+nsSVGTextPositioningElement::Init()
 {
-  nsresult rv;
+  nsresult rv = nsSVGTextPositioningElementBase::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), aSVGElement, nsSVGUtils::X);
+    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 = aSVGElement->AddMappedSVGValue(nsGkAtoms::x, mX);
+    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), aSVGElement, nsSVGUtils::Y);
+    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 = aSVGElement->AddMappedSVGValue(nsGkAtoms::y, mY);
+    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), aSVGElement, nsSVGUtils::X);
+    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 = aSVGElement->AddMappedSVGValue(nsGkAtoms::dx, mdX);
+    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), aSVGElement, nsSVGUtils::Y);
+    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 = aSVGElement->AddMappedSVGValue(nsGkAtoms::dy, mdY);
+    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 = aSVGElement->AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
+    rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMSVGTextPositioningElement methods
--- a/content/svg/content/src/nsSVGTextPositioningElement.h
+++ b/content/svg/content/src/nsSVGTextPositioningElement.h
@@ -36,23 +36,37 @@
 #ifndef __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__
 #define __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__
 
 #include "nsIDOMSVGTextPositionElem.h"
 #include "nsSVGTextContentElement.h"
 #include "nsIDOMSVGAnimatedLengthList.h"
 #include "nsIDOMSVGAnimatedNumberList.h"
 
-class nsSVGTextPositioningElement : public nsSVGTextContentElement
+class nsSVGElement;
+
+typedef nsSVGTextContentElement nsSVGTextPositioningElementBase;
+
+/**
+ * Note that nsSVGTextElement does not inherit this class - it reimplements it
+ * instead (see its documenting comment). The upshot is that any changes to
+ * this class also need to be made in nsSVGTextElement.
+ */
+class nsSVGTextPositioningElement : public nsSVGTextPositioningElementBase
 {
 public:
   NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
 
 protected:
-  nsresult Initialise(nsSVGElement *aSVGElement);
+
+  nsSVGTextPositioningElement(nsINodeInfo *aNodeInfo)
+    : nsSVGTextPositioningElementBase(aNodeInfo)
+  {}
+
+  nsresult Init();
 
   // nsIDOMSVGTextPositioning properties:
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX;
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
   nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
 };