Merge cedar into mozilla-central
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 15 Apr 2011 09:35:11 -0400
changeset 68180 754e793c647eb5c5e27c87b9841a9978149c866b
parent 68179 0c1749cfcc3849a4bd40ca882162e519a7deaee9 (current diff)
parent 68162 df7ee8ae671f925f9851ad81766dd25bf7e8f63b (diff)
child 68181 555c8cfbdb2dc2e66f13e269570afd62dc53a384
child 68239 aada30c4e0d3ac8544dc850bdbb72da3ca94d794
push id19528
push usereakhgari@mozilla.com
push dateFri, 15 Apr 2011 13:35:33 +0000
treeherdermozilla-central@754e793c647e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge cedar into mozilla-central
accessible/tests/mochitest/tree/test_colorpicker.xul
accessible/tests/mochitest/tree/test_menu.xul
content/base/public/nsIContentUtils.h
gfx/src/nsIFontMetrics.h
gfx/src/nsIThebesFontMetrics.h
gfx/src/nsThebesFontMetrics.cpp
gfx/src/nsThebesFontMetrics.h
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -59,17 +59,16 @@
 ACCESSIBILITY_ATOM(button, "button")
 ACCESSIBILITY_ATOM(checkbox, "checkbox")
 ACCESSIBILITY_ATOM(col, "col")
 ACCESSIBILITY_ATOM(_empty, "")
 ACCESSIBILITY_ATOM(_false, "false")
 ACCESSIBILITY_ATOM(image, "image")
 ACCESSIBILITY_ATOM(menu, "menu")
 ACCESSIBILITY_ATOM(menuButton, "menu-button")
-ACCESSIBILITY_ATOM(menugenerated, "menugenerated")
 ACCESSIBILITY_ATOM(multiple, "multiple")
 ACCESSIBILITY_ATOM(open, "open")
 ACCESSIBILITY_ATOM(password, "password")
 ACCESSIBILITY_ATOM(radio, "radio")
 ACCESSIBILITY_ATOM(reset, "reset")
 ACCESSIBILITY_ATOM(row, "row")
 ACCESSIBILITY_ATOM(submit, "submit")
 ACCESSIBILITY_ATOM(_true, "true")
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -756,57 +756,16 @@ nsCoreUtils::IsColumnHidden(nsITreeColum
 {
   nsCOMPtr<nsIDOMElement> element;
   aColumn->GetElement(getter_AddRefs(element));
   nsCOMPtr<nsIContent> content = do_QueryInterface(element);
   return content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::hidden,
                               nsAccessibilityAtoms::_true, eCaseMatters);
 }
 
-void
-nsCoreUtils::GeneratePopupTree(nsIContent *aContent, PRBool aIsAnon)
-{
-  // Set menugenerated="true" on the menupopup node to generate the sub-menu
-  // items if they have not been generated.
-
-  nsCOMPtr<nsIDOMNodeList> list;
-  if (aIsAnon) {    
-    nsIDocument* document = aContent->GetCurrentDoc();
-    if (document)
-      document->GetXBLChildNodesFor(aContent, getter_AddRefs(list));
-
-  } else {
-    list = aContent->GetChildNodesList();
-  }
-
-  PRUint32 length = 0;
-  if (!list || NS_FAILED(list->GetLength(&length)))
-    return;
-
-  for (PRUint32 idx = 0; idx < length; idx++) {
-    nsCOMPtr<nsIDOMNode> childNode;
-    list->Item(idx, getter_AddRefs(childNode));
-    nsCOMPtr<nsIContent> child(do_QueryInterface(childNode));
-
-    PRBool isPopup = child->NodeInfo()->Equals(nsAccessibilityAtoms::menupopup,
-                                               kNameSpaceID_XUL) ||
-                     child->NodeInfo()->Equals(nsAccessibilityAtoms::panel,
-                                               kNameSpaceID_XUL);
-    if (isPopup && !child->AttrValueIs(kNameSpaceID_None,
-                                       nsAccessibilityAtoms::menugenerated,
-                                       nsAccessibilityAtoms::_true,
-                                       eCaseMatters)) {
-
-      child->SetAttr(kNameSpaceID_None, nsAccessibilityAtoms::menugenerated,
-                     NS_LITERAL_STRING("true"), PR_TRUE);
-      return;
-    }
-  }
-}
-
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibleDOMStringList
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS1(nsAccessibleDOMStringList, nsIDOMDOMStringList)
 
 NS_IMETHODIMP
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -362,26 +362,16 @@ public:
   /**
    * Return true if the given node is table header element.
    */
   static PRBool IsHTMLTableHeader(nsIContent *aContent)
   {
     return aContent->NodeInfo()->Equals(nsAccessibilityAtoms::th) ||
       aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::scope);
   }
-
-  /**
-   * Generates frames for popup subtree.
-   *
-   * @param aContent [in] DOM node containing the menupopup element as a child
-   * @param aIsAnon  [in] specifies whether popup should be searched inside of
-   *                  anonymous or explicit content
-   */
-  static void GeneratePopupTree(nsIContent *aContent,
-                                PRBool aIsAnon = PR_FALSE);
 };
 
 
 /**
  * nsIDOMDOMStringList implementation.
  */
 class nsAccessibleDOMStringList : public nsIDOMDOMStringList
 {
--- a/accessible/src/base/nsTextAttrs.cpp
+++ b/accessible/src/base/nsTextAttrs.cpp
@@ -39,17 +39,17 @@
 #include "nsTextAttrs.h"
 
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsHyperTextAccessibleWrap.h"
 
 #include "gfxFont.h"
 #include "gfxUserFontSet.h"
-#include "nsIThebesFontMetrics.h"
+#include "nsFontMetrics.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constants and structures
 
 /**
  * Item of the gCSSTextAttrsMap map.
  */
 struct nsCSSTextAttrMapItem
@@ -527,23 +527,22 @@ nsFontWeightTextAttr::GetFontWeight(nsIF
 {
   // nsFont::width isn't suitable here because it's necessary to expose real
   // value of font weight (used font might not have some font weight values).
   nsStyleFont* styleFont =
     (nsStyleFont*)(aFrame->GetStyleDataExternal(eStyleStruct_Font));
 
   gfxUserFontSet *fs = aFrame->PresContext()->GetUserFontSet();
 
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   aFrame->PresContext()->DeviceContext()->
     GetMetricsFor(styleFont->mFont, aFrame->GetStyleVisibility()->mLanguage,
                   fs, *getter_AddRefs(fm));
 
-  nsCOMPtr<nsIThebesFontMetrics> tfm = do_QueryInterface(fm);
-  gfxFontGroup *fontGroup = tfm->GetThebesFontGroup();
+  gfxFontGroup *fontGroup = fm->GetThebesFontGroup();
   gfxFont *font = fontGroup->GetFontAt(0);
 
   // When there doesn't exist a bold font in the family and so the rendering of
   // a non-bold font face is changed so that the user sees what looks like a
   // bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
   // needed on Mac, but it is "safe" to use on all platforms.  (For non-Mac
   // platforms it always return false.)
   if (font->IsSyntheticBold())
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -53,17 +53,16 @@
 #include "nsPIDOMWindow.h"        
 #include "nsIDOMDocumentView.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMNSRange.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIEditingSession.h"
 #include "nsIEditor.h"
-#include "nsIFontMetrics.h"
 #include "nsIFrame.h"
 #include "nsFrameSelection.h"
 #include "nsILineIterator.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIScrollableFrame.h"
 #include "nsISelection2.h"
 #include "nsISelectionPrivate.h"
--- a/accessible/src/msaa/nsTextAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsTextAccessibleWrap.cpp
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsTextAccessibleWrap.h"
 #include "ISimpleDOMText_i.c"
 
 #include "nsCoreUtils.h"
 #include "nsDocAccessible.h"
 #include "nsIFrame.h"
-#include "nsIThebesFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsPresContext.h"
 
 #include "gfxFont.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsTextAccessibleWrap Accessible
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -250,26 +250,24 @@ STDMETHODIMP nsTextAccessibleWrap::get_f
 __try {
   *aFontFamily = NULL;
 
   nsIFrame* frame = GetFrame();
   if (!frame) {
     return E_FAIL;
   }
 
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   frame->PresContext()->DeviceContext()->
     GetMetricsFor(frame->GetStyleFont()->mFont,
                   frame->GetStyleVisibility()->mLanguage,
                   frame->PresContext()->GetUserFontSet(),
                   *getter_AddRefs(fm));
 
-  nsCOMPtr<nsIThebesFontMetrics> tfm = do_QueryInterface(fm);
-  const nsString& name = tfm->GetThebesFontGroup()->GetFontAt(0)->GetName();
-
+  const nsString& name = fm->GetThebesFontGroup()->GetFontAt(0)->GetName();
   if (name.IsEmpty())
     return S_FALSE;
 
   *aFontFamily = ::SysAllocStringLen(name.get(), name.Length());
   if (!*aFontFamily)
     return E_OUTOFMEMORY;
 
 } __except(FilterA11yExceptions(::GetExceptionCode(),
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp
+++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp
@@ -112,29 +112,16 @@ nsXULColorPickerTileAccessible::NativeSt
 
 nsXULColorPickerAccessible::
   nsXULColorPickerAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsXULColorPickerTileAccessible(aContent, aShell)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULColorPickerAccessible: nsAccessNode
-
-PRBool
-nsXULColorPickerAccessible::Init()
-{
-  if (!nsXULColorPickerTileAccessible::Init())
-    return PR_FALSE;
-
-  nsCoreUtils::GeneratePopupTree(mContent, PR_TRUE);
-  return PR_TRUE;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULColorPickerAccessible: nsAccessible
 
 PRUint64
 nsXULColorPickerAccessible::NativeState()
 {
   // Possible states: focused, focusable, unavailable(disabled).
 
   // get focus and disable status from base class
--- a/accessible/src/xul/nsXULColorPickerAccessible.h
+++ b/accessible/src/xul/nsXULColorPickerAccessible.h
@@ -63,19 +63,16 @@ public:
 /**
  * Used for colorpicker button (xul:colorpicker@type="button").
  */
 class nsXULColorPickerAccessible : public nsXULColorPickerTileAccessible
 {
 public:
   nsXULColorPickerAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
 
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
--- a/accessible/src/xul/nsXULComboboxAccessible.cpp
+++ b/accessible/src/xul/nsXULComboboxAccessible.cpp
@@ -52,26 +52,16 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULComboboxAccessible::
   nsXULComboboxAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsAccessibleWrap(aContent, aShell)
 {
 }
 
-PRBool
-nsXULComboboxAccessible::Init()
-{
-  if (!nsAccessibleWrap::Init())
-    return PR_FALSE;
-
-  nsCoreUtils::GeneratePopupTree(mContent);
-  return PR_TRUE;
-}
-
 PRUint32
 nsXULComboboxAccessible::NativeRole()
 {
   if (mContent->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
                             nsAccessibilityAtoms::autocomplete, eIgnoreCase))
     return nsIAccessibleRole::ROLE_AUTOCOMPLETE;
   return nsIAccessibleRole::ROLE_COMBOBOX;
 }
--- a/accessible/src/xul/nsXULComboboxAccessible.h
+++ b/accessible/src/xul/nsXULComboboxAccessible.h
@@ -55,18 +55,15 @@ public:
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& aValue);
   NS_IMETHOD GetDescription(nsAString& aDescription);
   NS_IMETHOD DoAction(PRUint8 aIndex);
   NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
   virtual PRBool GetAllowsAnonChildAccessibles();
 };
 
 #endif
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -105,31 +105,16 @@ nsXULButtonAccessible::DoAction(PRUint8 
   if (aIndex != 0)
     return NS_ERROR_INVALID_ARG;
 
   DoCommand();
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULButtonAccessible: nsAccessNode
-
-PRBool
-nsXULButtonAccessible::Init()
-{
-  if (!nsAccessibleWrap::Init())
-    return PR_FALSE;
-
-  if (ContainsMenu())
-    nsCoreUtils::GeneratePopupTree(mContent);
-
-  return PR_TRUE;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULButtonAccessible: nsAccessible
 
 PRUint32
 nsXULButtonAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_PUSHBUTTON;
 }
 
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -61,19 +61,16 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
 
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -275,26 +275,16 @@ nsXULSelectableAccessible::SelectAll()
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULMenuitemAccessible::
   nsXULMenuitemAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsAccessibleWrap(aContent, aShell)
 {
 }
 
-PRBool
-nsXULMenuitemAccessible::Init()
-{
-  if (!nsAccessibleWrap::Init())
-    return PR_FALSE;
-
-  nsCoreUtils::GeneratePopupTree(mContent);
-  return PR_TRUE;
-}
-
 PRUint64
 nsXULMenuitemAccessible::NativeState()
 {
   PRUint64 state = nsAccessible::NativeState();
 
   // Focused?
   if (mContent->HasAttr(kNameSpaceID_None,
                         nsAccessibilityAtoms::_moz_menuactive))
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -84,19 +84,16 @@ public:
   // nsIAccessible
   NS_IMETHOD GetDescription(nsAString& aDescription);
   NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
   NS_IMETHOD GetDefaultKeyBinding(nsAString& aKeyBinding);
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
   virtual PRInt32 GetLevelInternal();
   virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
                                           PRInt32 *aSetSize);
 
--- a/accessible/tests/mochitest/actions/test_general.xul
+++ b/accessible/tests/mochitest/actions/test_general.xul
@@ -24,17 +24,22 @@
   <script type="application/javascript">
   <![CDATA[
     function doTest()
     {
       var actionsArray = [
         {
           ID: "menu",
           actionName: "click",
-          events: CLICK_EVENTS
+          events: CLICK_EVENTS,
+          // Wait for focus event, it guarantees us the submenu tree is created,
+          // that's necessary for next test.
+          eventSeq: [
+            new invokerChecker(EVENT_FOCUS, getNode("menu"))
+          ]
         },
         {
           ID: "submenu",
           actionName: "click",
           events: CLICK_EVENTS
         },
         {
           ID: "menuitem",
--- a/accessible/tests/mochitest/tree/Makefile.in
+++ b/accessible/tests/mochitest/tree/Makefile.in
@@ -46,31 +46,29 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		dockids.html \
 	$(warning test_applicationacc.xul temporarily disabled, see bug 561508) \
 		test_aria_globals.html \
 		test_aria_imgmap.html \
 		test_button.xul \
-		test_colorpicker.xul \
 		test_combobox.xul \
 		test_cssoverflow.html \
 		test_dochierarchy.html \
 		test_dockids.html \
 		test_filectrl.html \
 		test_formctrl.html \
 		test_formctrl.xul \
 		test_gencontent.html \
 		test_groupbox.xul \
 		test_iframe.html \
 		test_img.html \
 		test_list.html \
 		test_media.html \
-		test_menu.xul \
 		test_select.html \
 		test_tabbox.xul \
 		test_tabbrowser.xul \
 		test_table.html \
 		test_tree.xul \
 		test_txtcntr.html \
 		test_txtctrl.html \
 		test_txtctrl.xul \
--- a/accessible/tests/mochitest/tree/test_button.xul
+++ b/accessible/tests/mochitest/tree/test_button.xul
@@ -19,132 +19,34 @@
   <script type="application/javascript">
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
-      // button1
+      // button
 
       var accTree = {
         role: ROLE_PUSHBUTTON,
         name: "hello",
         children: [ ]
       };
       testAccessibleTree("button1", accTree);
 
       //////////////////////////////////////////////////////////////////////////
-      // button2
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button2", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button3
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button3", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button4
+      // toolbarbutton
 
       var accTree = {
         role: ROLE_PUSHBUTTON,
         name: "hello",
         children: [ ]
       };
-      testAccessibleTree("button4", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button5
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button5", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button6
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button6", accTree);
+      testAccessibleTree("button2", accTree);
 
       SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
@@ -160,39 +62,14 @@
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
       <button id="button1" label="hello"/>
-      <button id="button2" type="menu" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </button>
-      <button id="button3" type="menu-button" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </button>
-
-      <toolbarbutton id="button4" label="hello"/>
-      <toolbarbutton id="button5" type="menu" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </toolbarbutton>
-      <toolbarbutton id="button6" type="menu-button" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </toolbarbutton>
+      <toolbarbutton id="button2" label="hello"/>
     </vbox>
   </hbox>
 
 </window>
 
deleted file mode 100644
--- a/accessible/tests/mochitest/tree/test_menu.xul
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Accessible XUL menu hierarchy tests">
-
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/MochiKit/packed.js" />
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-
-  <script type="application/javascript"
-          src="../common.js" />
-  <script type="application/javascript"
-          src="../role.js" />
-
-  <script type="application/javascript">
-  <![CDATA[
-    ////////////////////////////////////////////////////////////////////////////
-    // Test
-
-    function doTest()
-    {
-      if (LINUX || SOLARIS) {
-        // XXX: bug 527646
-
-        todo(false, "Failure on Linux and Solaris.");
-        SimpleTest.finish();
-        return;
-      }
-
-      var accTree = {
-        role: ROLE_PARENT_MENUITEM,
-        name: "menu",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("menu", accTree);
-
-      SimpleTest.finish();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  ]]>
-  </script>
-
-  <hbox flex="1" style="overflow: auto;">
-    <body xmlns="http://www.w3.org/1999/xhtml">
-      <a target="_blank"
-         href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
-         title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
-        Mozilla Bug 249292
-      </a><br/>
-      <p id="display"></p>
-      <div id="content" style="display: none">
-      </div>
-      <pre id="test">
-      </pre>
-    </body>
-
-    <vbox flex="1">
-      <menu id="menu" label="menu">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </menu>
-    </vbox>
-  </hbox>
-
-</window>
-
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -42,21 +42,24 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/treeupdate
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_ariadialog.html \
+		test_colorpicker.xul \
+		test_contextmenu.xul \
 		test_doc.html \
 		test_gencontent.html \
 		test_list_editabledoc.html \
 		test_list.html \
 		test_menu.xul \
+		test_menubutton.xul \
 		test_recreation.html \
 		test_select.html \
 		test_textleaf.html \
 		test_visibility.html \
 		test_whitespace.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
rename from accessible/tests/mochitest/tree/test_colorpicker.xul
rename to accessible/tests/mochitest/treeupdate/test_colorpicker.xul
--- a/accessible/tests/mochitest/tree/test_colorpicker.xul
+++ b/accessible/tests/mochitest/treeupdate/test_colorpicker.xul
@@ -10,60 +10,137 @@
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
+  <script type="application/javascript"
+          src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
+    function openColorpicker(aColorpickerID)
+    {
+      this.node = getNode(aColorpickerID);
+
+      this.eventSeq = [];
+
+      var it = new colorButtonIterator(this.node);
+      for (var btnNode = it.next(); btnNode = it.next(); btnNode)
+        this.eventSeq.push(new invokerChecker(EVENT_SHOW, btnNode));
+
+      var popupNode = getPopupNode(this.node);
+      this.eventSeq.push(new invokerChecker(EVENT_REORDER, popupNode));
+
+      this.invoke = function openColorpicker_invoke()
+      {
+        var tree =
+          { BUTTONDROPDOWNGRID: [
+            { ALERT: [ ] }
+          ] };
+        testAccessibleTree(this.node, tree);
+
+        this.node.showPopup();
+      }
+
+      this.finalCheck = function openColorpicker_finalCheck()
+      {
+        var tree =
+          { BUTTONDROPDOWNGRID: [
+            { ALERT: [ ] }
+          ] };
+
+        var colorButtons = tree.BUTTONDROPDOWNGRID[0].ALERT;
+        var it = new colorButtonIterator(this.node);
+        while (it.next()) {
+          var obj = { PUSHBUTTON: [ ] };
+          colorButtons.push(obj);
+        }
+
+        testAccessibleTree(this.node, tree);
+      }
+
+      this.getID = function openColorpicker_getID()
+      {
+        return "open colorpicker " + prettyName(aColorpickerID);
+      }
+    }
+
+    function getPopupNode(aColorpickerNode)
+    {
+      return aColorpickerNode.mPicker.parentNode;
+    }
+
+    function colorButtonIterator(aColorpickerNode)
+    {
+      this.container = aColorpickerNode.mPicker.mBox;
+      this.group = this.container.firstChild;
+      this.item = null;
+
+      this.next = function colorButtonIterator_next()
+      {
+        if (!this.group)
+          return null;
+
+        if (!this.item) {
+          this.item = this.group.firstChild;
+          return this.item;
+        }
+
+        if (this.item.nextSibling) {
+          this.item = this.item.nextSibling;
+          return this.item;
+        }
+
+        if (this.group.nextSibling) {
+          this.group = this.group.nextSibling;
+          this.item = this.group.firstChild;
+          return this.item;
+        }
+
+        this.group = null;
+        this.item = null;
+        return null;
+      }
+    }
+
+    //gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
     function doTest()
     {
-      //////////////////////////////////////////////////////////////////////////
-      // button1
-
-      var accTree = {
-        role: ROLE_BUTTONDROPDOWNGRID,
-        children: [
-          {
-            role: ROLE_ALERT,
-            children: [ ]
-          }
-        ]
-      };
-
-      var colorButtons = accTree.children[0].children;
-      for (var idx = 0; idx < 70; idx++) {
-        var obj = { role: ROLE_PUSHBUTTON };
-        colorButtons.push(obj);
-      }
-
-      testAccessibleTree("colorpicker", accTree);
-
-      SimpleTest.finish()
+      gQueue = new eventQueue();
+      gQueue.push(new openColorpicker("colorpicker"));
+      gQueue.invoke(); // Will call SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
     <body xmlns="http://www.w3.org/1999/xhtml">
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
          title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
         Mozilla Bug 249292
-      </a><br/>
+      </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+         title="Don't force accessible creation for popup children.">
+        Mozilla Bug 630486
+      </a>
+      <br/>
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_contextmenu.xul
@@ -0,0 +1,321 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="menu tree and events">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+
+    function openMenu(aID, aTree)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_MENUPOPUP_START, getNode(aID))
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        var button = getNode("button");
+        getNode(aID).openPopup(button, "after_start", 0, 0, true, false);
+      }
+
+      this.finalCheck = function openMenu_finalCheck(aEvent)
+      {
+        testAccessibleTree(aID, aTree);
+      }
+
+      this.getID = function openMenu_getID()
+      {
+        return "open menu " + prettyName(aID);
+      }
+    }
+
+    function selectNextMenuItem(aID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, getNode(aID))
+      ];
+
+      this.invoke = function selectMenuItem_invoke()
+      {
+        synthesizeKey("VK_DOWN", { });
+      }
+
+      this.getID = function selectMenuItem_getID()
+      {
+        return "select menuitem " + prettyName(aID);
+      }
+    }
+    
+    function openSubMenu(aSubMenuID, aItemID, aMenuID, aTree)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
+      ];
+
+      this.invoke = function openSubMenu_invoke()
+      {
+        synthesizeKey("VK_ENTER", { });
+      }
+
+      this.finalCheck = function openSubMenu_finalCheck(aEvent)
+      {
+        testAccessibleTree(aMenuID, aTree);
+      }
+
+      this.getID = function openSubMenu_getID()
+      {
+        return "open submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
+      }
+    }
+
+    function closeSubMenu(aSubMenuID, aItemID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
+      ];
+
+      this.invoke = function closeSubMenu_invoke()
+      {
+        synthesizeKey("VK_ESCAPE", { });
+      }
+
+      this.getID = function closeSubMenu_getID()
+      {
+        return "close submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
+      }
+    }
+
+    function closeMenu(aID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_MENUPOPUP_END, getNode(aID))
+      ];
+
+      this.invoke = function closeMenu_invoke()
+      {
+        synthesizeKey("VK_ESCAPE", { });
+      }
+
+      this.getID = function closeMenu_getID()
+      {
+        return "close menu " + prettyName(aID);
+      }
+    }
+
+    //gA11yEventDumpID = "eventdump";
+    //gA11yEventDumpToConsole = true;
+
+    var gQueue = null;
+    var gContextTree = {};
+
+    // Linux and Windows menu trees discrepancy: bug 527646.
+
+    /**
+     * Return the context menu tree before submenus were open.
+     */
+    function getMenuTree1()
+    {
+      if (LINUX || SOLARIS) {
+        var tree = {
+          role: ROLE_MENUPOPUP,
+          children: [
+            {
+              name: "item0",
+              role: ROLE_MENUITEM,
+              children: []
+            },
+            {
+              name: "item1",
+              role: ROLE_MENUITEM,
+              children: []
+            },
+            {
+              name: "item2",
+              role: ROLE_PARENT_MENUITEM,
+              children: [ ]
+            }
+          ]
+        };
+        return tree;
+      }
+
+      // Windows
+      var tree = {
+        role: ROLE_MENUPOPUP,
+        children: [
+          {
+            name: "item0",
+            role: ROLE_MENUITEM,
+            children: []
+          },
+          {
+            name: "item1",
+            role: ROLE_MENUITEM,
+            children: []
+          },
+          {
+            name: "item2",
+            role: ROLE_PARENT_MENUITEM,
+            children: [
+              {
+                name: "item2",
+                role: ROLE_MENUPOPUP,
+                children: [ ]
+              }
+            ]
+          }
+        ]
+      };
+      return tree;
+    }
+
+    /**
+     * Return context menu tree when submenu was open.
+     */
+    function getMenuTree2()
+    {
+      var tree = getMenuTree1();
+      if (LINUX || SOLARIS) {
+        var submenuTree =
+        {
+          name: "item2.0",
+          role: ROLE_PARENT_MENUITEM,
+          children: [ ]
+        };
+        tree.children[2].children.push(submenuTree);
+        return tree;
+      }
+
+      // Windows
+      var submenuTree =
+      {
+        name: "item2.0",
+        role: ROLE_PARENT_MENUITEM,
+        children: [
+          {
+            name: "item2.0",
+            role: ROLE_MENUPOPUP,
+            children: [ ]
+          }
+        ]
+      };
+
+      tree.children[2].children[0].children.push(submenuTree);
+      return tree;
+    }
+
+    /**
+     * Return context menu tree when subsub menu was open.
+     */
+    function getMenuTree3()
+    {
+      var tree = getMenuTree2();
+      var subsubmenuTree =
+      {
+        name: "item2.0.0",
+        role: ROLE_MENUITEM,
+        children: []
+      };
+
+      if (LINUX || SOLARIS)
+        tree.children[2].children[0].\(subsubmenuTree);
+      else
+        tree.children[2].children[0].children[0].children[0].children.push(subsubmenuTree);
+
+      return tree;
+    }
+
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      // Check initial empty tree
+      testAccessibleTree("context", { MENUPOPUP: [] });
+
+      // Open context menu and check that menu item accesibles are created.
+      gQueue.push(new openMenu("context", getMenuTree1()));
+
+      // Select items and check focus event on them.
+      gQueue.push(new selectNextMenuItem("item0"));
+      gQueue.push(new selectNextMenuItem("item1"));
+      gQueue.push(new selectNextMenuItem("item2"));
+
+      // Open sub menu and check menu accessible tree and focus event.
+      gQueue.push(new openSubMenu("submenu2", "item2.0",
+                                  "context", getMenuTree2()));
+      gQueue.push(new openSubMenu("submenu2.0", "item2.0.0",
+                                  "context", getMenuTree3()));
+
+      // Close submenus and check that focus goes to parent.
+      gQueue.push(new closeSubMenu("submenu2.0", "item2.0"));
+      gQueue.push(new closeSubMenu("submenu2", "item2"));
+
+      gQueue.push(new closeMenu("context"));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=630194"
+       title="Update accessible tree when opening the menu popup">
+      Mozilla Bug 630194
+    </a>
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+       title="Don't force accessible creation for popup children.">
+      Mozilla Bug 630486
+    </a>
+  <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+    <pre id="test">
+    </pre>
+  </body>
+
+    <vbox flex="1">
+
+      <menupopup id="context">
+        <menuitem id="item0" label="item0"/>
+        <menuitem id="item1" label="item1"/>
+        <menu id="item2" label="item2">
+          <menupopup id="submenu2">
+            <menu id="item2.0" label="item2.0">
+              <menupopup id="submenu2.0">
+                <menuitem id="item2.0.0" label="item2.0.0"/>
+              </menupopup>
+            </menu>
+          </menupopup>
+        </menu>
+      </menupopup>
+
+      <button context="context" id="button">btn</button>
+
+      <vbox id="eventdump" role="log"/>
+    </vbox>
+  </hbox>
+</window>
--- a/accessible/tests/mochitest/treeupdate/test_menu.xul
+++ b/accessible/tests/mochitest/treeupdate/test_menu.xul
@@ -1,277 +1,130 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="menu tree and events">
+        title="Accessible XUL menu hierarchy tests">
 
   <script type="application/javascript" 
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
-          src="../events.js" />
+          src="../role.js" />
   <script type="application/javascript"
-          src="../role.js" />
+          src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
-    function openMenu(aID, aTree)
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function openMenu(aID)
     {
+      this.menuNode = getNode(aID),
+
       this.eventSeq = [
-        new invokerChecker(EVENT_MENUPOPUP_START, getNode(aID))
+        new invokerChecker(EVENT_FOCUS, this.menuNode)
       ];
 
       this.invoke = function openMenu_invoke()
       {
-        var button = getNode("button");
-        getNode(aID).openPopup(button, "after_start", 0, 0, true, false);
+        var tree;
+        if (LINUX || SOLARIS) {
+          tree =
+            { PARENT_MENUITEM: [ ] };
+
+        } else {
+          tree =
+            { PARENT_MENUITEM: [
+              { MENUPOPUP: [ ] }
+            ] };
+        }
+        testAccessibleTree(aID, tree);
+
+        // Show menu.
+        this.menuNode.open = true;
       }
 
-      this.finalCheck = function openMenu_finalCheck(aEvent)
+      this.finalCheck = function openMenu_finalCheck()
       {
-        testAccessibleTree(aID, aTree);
+        var tree;
+        if (LINUX || SOLARIS) {
+          tree =
+            { PARENT_MENUITEM: [
+              { MENUITEM: [ ] },
+              { MENUITEM: [ ] }
+            ] };
+
+        } else {
+          tree =
+            { PARENT_MENUITEM: [
+              { MENUPOPUP: [
+                { MENUITEM: [ ] },
+                { MENUITEM: [ ] }
+              ] }
+            ] };
+        }
+        testAccessibleTree(aID, tree);
       }
 
       this.getID = function openMenu_getID()
       {
         return "open menu " + prettyName(aID);
       }
     }
 
-    function selectNextMenuItem(aID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_FOCUS, getNode(aID))
-      ];
-
-      this.invoke = function selectMenuItem_invoke()
-      {
-        synthesizeKey("VK_DOWN", { });
-      }
-
-      this.getID = function selectMenuItem_getID()
-      {
-        return "select menuitem " + prettyName(aID);
-      }
-    }
-    
-    function openSubMenu(aSubMenuID, aItemID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
-      ];
-
-      this.invoke = function openSubMenu_invoke()
-      {
-        synthesizeKey("VK_ENTER", { });
-      }
-
-      this.finalCheck = function openSubMenu_finalCheck(aEvent)
-      {
-        getAccessible(aItemID);
-      }
-
-      this.getID = function openSubMenu_getID()
-      {
-        return "open submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
-      }
-    }
-
-    function closeSubMenu(aSubMenuID, aItemID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
-      ];
-
-      this.invoke = function closeSubMenu_invoke()
-      {
-        synthesizeKey("VK_ESCAPE", { });
-      }
-
-      this.getID = function closeSubMenu_getID()
-      {
-        return "close submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
-      }
-    }
-
-    function closeMenu(aID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_MENUPOPUP_END, getNode(aID))
-      ];
-
-      this.invoke = function closeMenu_invoke()
-      {
-        synthesizeKey("VK_ESCAPE", { });
-      }
-
-      this.getID = function closeMenu_getID()
-      {
-        return "close menu " + prettyName(aID);
-      }
-    }
-
-    //gA11yEventDumpID = "eventdump";
-    //gA11yEventDumpToConsole = true;
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
 
     var gQueue = null;
-    var gContextTree = {};
-
-    // bug 527646
-    if (LINUX || SOLARIS) {
-      gContextTree = {
-        role: ROLE_MENUPOPUP,
-        children: [
-          {
-            name: "item0",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item1",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item2",
-            role: ROLE_PARENT_MENUITEM,
-            children: [
-              {
-                name: "item2.0",
-                role: ROLE_PARENT_MENUITEM,
-                children: [
-                  { 
-                    name: "item2.0.0",
-                    role: ROLE_MENUITEM,
-                    children: []
-                  }
-                ]
-              }
-            ]
-          }
-        ]
-      };
-    } else {
-      gContextTree = {
-        role: ROLE_MENUPOPUP,
-        children: [
-          {
-            name: "item0",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item1",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item2",
-            role: ROLE_PARENT_MENUITEM,
-            children: [
-              {
-                name: "item2",
-                role: ROLE_MENUPOPUP,
-                children: [
-                  {
-                    name: "item2.0",
-                    role: ROLE_PARENT_MENUITEM,
-                    children: [
-                      { 
-                        name: "item2.0",
-                        role: ROLE_MENUPOPUP,
-                        children: [
-                          { 
-                            name: "item2.0.0",
-                            role: ROLE_MENUITEM,
-                            children: []
-                          }
-                        ]
-                      }
-                    ]
-                  }
-                ]
-              }
-            ]
-          }
-        ]
-      };
-    }
-
-
-    function doTests()
+    function doTest()
     {
       gQueue = new eventQueue();
-
-      // Check initial empty tree
-      testAccessibleTree("context", { MENUPOPUP: [] });
-
-      // Open context menu and check that menu item accesibles are created.
-      gQueue.push(new openMenu("context", gContextTree));
-
-      // Select items and check focus event on them.
-      gQueue.push(new selectNextMenuItem("item0"));
-      gQueue.push(new selectNextMenuItem("item1"));
-      gQueue.push(new selectNextMenuItem("item2"));
-
-      // Open sub menu and check menu item accessibles and focus event.
-      gQueue.push(new openSubMenu("submenu2", "item2.0"));
-      gQueue.push(new openSubMenu("submenu2.0", "item2.0.0"));
-
-      // Close submenus and check that focus goes to parent.
-      gQueue.push(new closeSubMenu("submenu2.0", "item2.0"));
-      gQueue.push(new closeSubMenu("submenu2", "item2"));
-
-      gQueue.push(new closeMenu("context"));
-
+      gQueue.push(new openMenu("menu"));
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTests);
+    addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=630194"
-       title="Update accessible tree when opening the menu popup">
-      Mozilla Bug 630194
-    </a>
-  <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
+         title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
+        Mozilla Bug 249292
+      </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+         title="Don't force accessible creation for popup children.">
+        Mozilla Bug 630486
+      </a>
+      <br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
 
     <vbox flex="1">
-
-      <menupopup id="context">
-        <menuitem id="item0" label="item0"/>
-        <menuitem id="item1" label="item1"/>
-        <menu id="item2" label="item2">
-          <menupopup id="submenu2">
-            <menu id="item2.0" label="item2.0">
-              <menupopup id="submenu2.0">
-                <menuitem id="item2.0.0" label="item2.0.0"/>
-              </menupopup>
-            </menu>
+      <menubar>
+        <menu id="menu" label="menu">
+          <menupopup>
+            <menuitem label="menuitem"/>
+            <menuitem label="menuitem"/>
           </menupopup>
         </menu>
-      </menupopup>
-
-      <button context="context" id="button">btn</button>
-
-      <vbox id="eventdump" role="log"/>
+      </menubar>
     </vbox>
   </hbox>
+
 </window>
+
copy from accessible/tests/mochitest/tree/test_button.xul
copy to accessible/tests/mochitest/treeupdate/test_menubutton.xul
--- a/accessible/tests/mochitest/tree/test_button.xul
+++ b/accessible/tests/mochitest/treeupdate/test_menubutton.xul
@@ -10,187 +10,168 @@
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
+  <script type="application/javascript"
+          src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
+
     ////////////////////////////////////////////////////////////////////////////
-    // Test
+    // Invokers
+
+    function openMenu(aButtonID)
+    {
+      this.buttonNode = getNode(aButtonID);
+      this.menupoupNode = this.buttonNode.firstChild;
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.menupoupNode)
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [ ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+
+        this.buttonNode.open = true;
+      }
+
+      this.finalCheck = function openMenu_finalCheck()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [
+              { MENUITEM: [ ] },
+              { MENUITEM: [ ] }
+            ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+      }
+
+      this.getID = function openMenu_getID()
+      {
+        return "open menu for button " + prettyName(aButtonID);
+      }
+    }
+
+    function openMenuButton(aButtonID)
+    {
+      this.buttonNode = getNode(aButtonID);
+      this.menupoupNode = this.buttonNode.firstChild;
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.menupoupNode)
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [ ] },
+            { PUSHBUTTON: [ ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+
+        this.buttonNode.open = true;
+      }
+
+      this.finalCheck = function openMenu_finalCheck()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [
+              { MENUITEM: [ ] },
+              { MENUITEM: [ ] }
+            ] },
+            { PUSHBUTTON: [ ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+      }
+
+      this.getID = function openMenu_getID()
+      {
+        return "open menu for menu button " + prettyName(aButtonID);
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Do test
+
+    gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
 
     function doTest()
     {
-      //////////////////////////////////////////////////////////////////////////
-      // button1
-
-      var accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [ ]
-      };
-      testAccessibleTree("button1", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button2
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button2", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button3
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button3", accTree);
+      gQueue = new eventQueue();
 
-      //////////////////////////////////////////////////////////////////////////
-      // button4
-
-      var accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [ ]
-      };
-      testAccessibleTree("button4", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button5
+      gQueue.push(new openMenu("button1"));
+      gQueue.push(new openMenuButton("button2"));
+      gQueue.push(new openMenu("button3"));
+      gQueue.push(new openMenuButton("button4"));
 
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button5", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button6
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button6", accTree);
-
-      SimpleTest.finish()
+      gQueue.invoke(); // SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
     <body xmlns="http://www.w3.org/1999/xhtml">
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
          title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
         Mozilla Bug 249292
-      </a><br/>
+      </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+         title="Don't force accessible creation for popup children.">
+        Mozilla Bug 630486
+      </a>
+      <br/>
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
-      <button id="button1" label="hello"/>
-      <button id="button2" type="menu" label="hello">
+      <button id="button1" type="menu" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </button>
-      <button id="button3" type="menu-button" label="hello">
+      <button id="button2" type="menu-button" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </button>
 
-      <toolbarbutton id="button4" label="hello"/>
-      <toolbarbutton id="button5" type="menu" label="hello">
+      <toolbarbutton id="button3" type="menu" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </toolbarbutton>
-      <toolbarbutton id="button6" type="menu-button" label="hello">
+      <toolbarbutton id="button4" type="menu-button" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </toolbarbutton>
     </vbox>
   </hbox>
 
--- a/browser/components/feeds/content/subscribe.xml
+++ b/browser/components/feeds/content/subscribe.xml
@@ -44,17 +44,17 @@
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <binding id="feedreaderUI">
     <content>
       <xul:vbox>
         <xul:hbox align="center">
           <xul:description anonid="subscribeUsingDescription" class="subscribeUsingDescription"/>
           <xul:menulist anonid="handlersMenuList" class="handlersMenuList" aria-labelledby="subscribeUsingDescription">
-            <xul:menupopup menugenerated="true" anonid="handlersMenuPopup" class="handlersMenuPopup">
+            <xul:menupopup anonid="handlersMenuPopup" class="handlersMenuPopup">
               <xul:menuitem anonid="liveBookmarksMenuItem" label="&feedLiveBookmarks;" class="menuitem-iconic liveBookmarksMenuItem" image="chrome://browser/skin/page-livemarks.png" selected="true"/>
               <xul:menuseparator/>
             </xul:menupopup>
           </xul:menulist>
         </xul:hbox>
         <xul:hbox>
           <xul:checkbox anonid="alwaysUse" class="alwaysUse" checked="false"/>
         </xul:hbox>
new file mode 100644
--- /dev/null
+++ b/build/stdc++compat.cpp
@@ -0,0 +1,114 @@
+/* ***** 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 a hack to avoid dependencies on recent libstdc++.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mike Hommey <mh@glandium.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 <ostream>
+#include <istream>
+#ifdef DEBUG
+#include <string>
+#endif
+
+namespace std {
+#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)
+    /* Instantiate these templates to avoid GLIBCXX_3.4.9 symbol versions */
+    template ostream& ostream::_M_insert(double);
+    template ostream& ostream::_M_insert(long);
+    template ostream& ostream::_M_insert(unsigned long);
+    template ostream& __ostream_insert(ostream&, const char*, streamsize);
+    template istream& istream::_M_extract(double&);
+#endif
+#ifdef DEBUG
+#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)
+    /* Instantiate these templates to avoid GLIBCXX_3.4.14 symbol versions
+     * in debug builds */
+    template char *basic_string<char, char_traits<char>, allocator<char> >::_S_construct_aux_2(size_type, char, allocator<char> const&);
+    template wchar_t *basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >::_S_construct_aux_2(size_type, wchar_t, allocator<wchar_t> const&);
+#endif
+#endif
+}
+
+namespace std __attribute__((visibility("default"))) {
+
+#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)
+    /* Hack to avoid GLIBCXX_3.4.14 symbol versions */
+    struct _List_node_base
+    {
+        void hook(_List_node_base * const __position) throw ();
+
+        void unhook() throw ();
+
+        void transfer(_List_node_base * const __first,
+                      _List_node_base * const __last) throw();
+
+        void _M_hook(_List_node_base * const __position) throw ();
+
+        void _M_unhook() throw ();
+
+        void _M_transfer(_List_node_base * const __first,
+                         _List_node_base * const __last) throw();
+    };
+
+    /* The functions actually have the same implementation */
+    void
+    _List_node_base::_M_hook(_List_node_base * const __position) throw ()
+    {
+        hook(__position);
+    }
+
+    void
+    _List_node_base::_M_unhook() throw ()
+    {
+        unhook();
+    }
+
+    void
+    _List_node_base::_M_transfer(_List_node_base * const __first,
+                                 _List_node_base * const __last) throw ()
+    {
+        transfer(__first, __last);
+    }
+#endif
+
+#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)
+    /* Hack to avoid GLIBCXX_3.4.11 symbol versions
+       An inline definition of ctype<char>::_M_widen_init() used to be in
+       locale_facets.h before GCC 4.4, but moved out of headers in more
+       recent versions.
+       It is actually safe to make it do nothing. */
+    void ctype<char>::_M_widen_init() const {}
+#endif
+
+}
--- a/build/unix/elfhack/Makefile.in
+++ b/build/unix/elfhack/Makefile.in
@@ -43,19 +43,22 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 INTERNAL_TOOLS = 1
 
 HOST_PROGRAM = elfhack
 NO_DIST_INSTALL = 1
 
+VPATH += $(topsrcdir)/build
+
 HOST_CPPSRCS = \
   elf.cpp \
   elfhack.cpp \
+  $(STDCXX_COMPAT) \
   $(NULL)
 
 OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
 
 ifneq (,$(filter %86,$(TARGET_CPU)))
 CPU := x86
 else
 ifneq (,$(filter arm%,$(TARGET_CPU)))
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -112,16 +112,17 @@ MOZ_CALLGRIND   = @MOZ_CALLGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
 MOZ_TRACE_JSCALLS = @MOZ_TRACE_JSCALLS@
 MOZ_TRACEVIS    = @MOZ_TRACEVIS@
 DEHYDRA_PATH    = @DEHYDRA_PATH@
 
 NS_TRACE_MALLOC = @NS_TRACE_MALLOC@
 USE_ELF_DYNSTR_GC = @USE_ELF_DYNSTR_GC@
 USE_ELF_HACK = @USE_ELF_HACK@
+STDCXX_COMPAT = @STDCXX_COMPAT@
 INCREMENTAL_LINKER = @INCREMENTAL_LINKER@
 MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@
 MOZ_MAIL_NEWS	= @MOZ_MAIL_NEWS@
 BUILD_STATIC_LIBS = @BUILD_STATIC_LIBS@
 MOZ_ENABLE_LIBXUL = @MOZ_ENABLE_LIBXUL@
 ENABLE_TESTS	= @ENABLE_TESTS@
 IBMBIDI = @IBMBIDI@
 MOZ_UNIVERSALCHARDET = @MOZ_UNIVERSALCHARDET@
--- a/config/config.mk
+++ b/config/config.mk
@@ -844,8 +844,12 @@ CREATE_PRECOMPLETE_CMD = $(PYTHON) $(cal
 EXPAND_LIBS = $(PYTHON) -I$(DEPTH)/config $(topsrcdir)/config/expandlibs.py
 EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py
 EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py
 EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
 EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist -- $(MKSHLIB)
+
+ifdef STDCXX_COMPAT
+CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && echo "Error: We don't want these libstdc++ symbol versions to be used" && exit 1 || exit 0
+endif
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -987,16 +987,17 @@ endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
 endif
 else # !WINNT || GNU_CC
 ifeq ($(CPP_PROG_LINK),1)
 	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(EXE_DEF_FILE)
+	$(call CHECK_STDCXX,$@)
 else # ! CPP_PROG_LINK
 	$(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
 endif # CPP_PROG_LINK
 endif # WINNT && !GNU_CC
 endif # WINCE
 
 ifdef ENABLE_STRIP
 	$(STRIP) $@
@@ -1052,16 +1053,17 @@ ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
 ifeq ($(CPP_PROG_LINK),1)
 	$(EXPAND_CCC) $(WRAP_MALLOC_CFLAGS) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
+	$(call CHECK_STDCXX,$@)
 else
 	$(EXPAND_CC) $(WRAP_MALLOC_CFLAGS) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
 endif # CPP_PROG_LINK
 endif # WINNT && !GNU_CC
 endif # WINCE
 
 ifdef ENABLE_STRIP
 	$(STRIP) $@
@@ -1172,16 +1174,17 @@ ifdef DTRACE_LIB_DEPENDENT
 ifndef XP_MACOSX
 	dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
 endif
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 	@$(RM) $(DTRACE_PROBE_OBJ)
 else # ! DTRACE_LIB_DEPENDENT
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 endif # DTRACE_LIB_DEPENDENT
+	$(call CHECK_STDCXX,$@)
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		rm -f $@.manifest; \
 	fi
--- a/configure.in
+++ b/configure.in
@@ -6433,17 +6433,17 @@ if test -n "$LIBJPEG_TURBO_X86_ASM" -o -
     if test -z "$LIBJPEG_TURBO_AS" ; then
         AC_MSG_ERROR([yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have yasm installed.  Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
     fi
 
     dnl Check that we have the right yasm version.  We require 1.0.1 or newer
     dnl on Linux and 1.1 or newer everywhere else.
     if test "$OS_ARCH" = "Linux" ; then
         if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -eq "0" -a "$_YASM_RELEASE" -lt "1" \) ; then
-            AC_MSG_ERROR([yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_MINOR_VERSION.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
+            AC_MSG_ERROR([yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_RELEASE.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
         fi
     else
         if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -lt "1" \) ; then
             AC_MSG_ERROR([yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.  Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder.  See https://developer.mozilla.org/en/YASM for more details.])
         fi
     fi
 fi
 
@@ -7712,16 +7712,38 @@ if test "$USE_ELF_HACK" = 1; then
         ;;
     *)
         USE_ELF_HACK=
         ;;
     esac
 fi
 
 dnl ========================================================
+dnl = libstdc++ compatibility hacks
+dnl ========================================================
+
+STDCXX_COMPAT=stdc++compat.cpp
+MOZ_ARG_DISABLE_BOOL(stdcxx-compat,
+[  --disable-stdcxx-compat Disable libstdc++ compatibility],
+    STDCXX_COMPAT=)
+
+# Disable on platforms where it doesn't make sense
+if test -n "$STDCXX_COMPAT"; then
+    case "${OS_TARGET}" in
+    Linux)
+        ;;
+    *)
+        STDCXX_COMPAT=
+        ;;
+    esac
+fi
+
+AC_SUBST(STDCXX_COMPAT)
+
+dnl ========================================================
 dnl = 
 dnl = Profiling and Instrumenting
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Profiling and Instrumenting)
 
 dnl ========================================================
 dnl = Enable timeline service, which provides lightweight
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -556,17 +556,16 @@ GK_ATOM(maxwidth, "maxwidth")
 GK_ATOM(mayscript, "mayscript")
 GK_ATOM(media, "media")
 GK_ATOM(mediaType, "media-type")
 GK_ATOM(member, "member")
 GK_ATOM(menu, "menu")
 GK_ATOM(menubar, "menubar")
 GK_ATOM(menubutton, "menubutton")
 GK_ATOM(menuButton, "menu-button")
-GK_ATOM(menugenerated, "menugenerated")
 GK_ATOM(menuitem, "menuitem")
 GK_ATOM(menulist, "menulist")
 GK_ATOM(menupopup, "menupopup")
 GK_ATOM(message, "message")
 GK_ATOM(meta, "meta")
 GK_ATOM(meter, "meter")
 GK_ATOM(method, "method")
 GK_ATOM(middle, "middle")
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -139,17 +139,17 @@
 
 #include "imgIContainer.h"
 #include "nsIProperties.h"
 #include "nsISupportsPrimitives.h"
 #include "nsEventDispatcher.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsITimer.h"
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "nsDOMDataTransfer.h"
 #include "nsContentAreaDragDrop.h"
 #ifdef MOZ_XUL
 #include "nsTreeBodyFrame.h"
 #endif
@@ -2485,22 +2485,21 @@ GetScrollableLineHeight(nsIFrame* aTarge
     nsIScrollableFrame* sf = f->GetScrollTargetFrame();
     if (sf)
       return sf->GetLineScrollAmount().height;
   }
 
   // Fall back to the font height of the target frame.
   const nsStyleFont* font = aTargetFrame->GetStyleFont();
   const nsFont& f = font->mFont;
-  nsCOMPtr<nsIFontMetrics> fm = aTargetFrame->PresContext()->GetMetricsFor(f);
+  nsRefPtr<nsFontMetrics> fm = aTargetFrame->PresContext()->GetMetricsFor(f);
   NS_ASSERTION(fm, "FontMetrics is null!");
-  nscoord lineHeight = 0;
   if (fm)
-    fm->GetHeight(lineHeight);
-  return lineHeight;
+    return fm->MaxHeight();
+  return 0;
 }
 
 void
 nsEventStateManager::SendLineScrollEvent(nsIFrame* aTargetFrame,
                                          nsMouseScrollEvent* aEvent,
                                          nsPresContext* aPresContext,
                                          nsEventStatus* aStatus,
                                          PRInt32 aNumLines)
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -203,18 +203,17 @@ VideoData* VideoData::Create(nsVideoInfo
   data.mStereoMode = aInfo.mStereoMode;
 
   videoImage->SetData(data); // Copies buffer
   return v.forget();
 }
 
 nsBuiltinDecoderReader::nsBuiltinDecoderReader(nsBuiltinDecoder* aDecoder)
   : mMonitor("media.decoderreader"),
-    mDecoder(aDecoder),
-    mDataOffset(0)
+    mDecoder(aDecoder)
 {
   MOZ_COUNT_CTOR(nsBuiltinDecoderReader);
 }
 
 nsBuiltinDecoderReader::~nsBuiltinDecoderReader()
 {
   ResetDecode();
   MOZ_COUNT_DTOR(nsBuiltinDecoderReader);
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -87,20 +87,16 @@ public:
 
   // The picture region inside the video frame to be displayed.
   nsIntRect mPicture;
 
   // Display size of the video frame. The picture region will be scaled
   // to and displayed at this size.
   nsIntSize mDisplay;
 
-  // The offset of the first non-header page in the file, in bytes.
-  // Used to seek to the start of the media.
-  PRInt64 mDataOffset;
-
   // Indicates the frame layout for single track stereo videos.
   mozilla::layers::StereoMode mStereoMode;
 
   // PR_TRUE if we have an active audio bitstream.
   PRPackedBool mHasAudio;
 
   // PR_TRUE if we have an active video bitstream.
   PRPackedBool mHasVideo;
@@ -508,18 +504,14 @@ protected:
   // The lock which we hold whenever we read or decode. This ensures the thread
   // safety of the reader and its data fields.
   Monitor mMonitor;
 
   // Reference to the owning decoder object. Do not hold the
   // reader's monitor when accessing this.
   nsBuiltinDecoder* mDecoder;
 
-  // The offset of the start of the first non-header page in the file.
-  // Used to seek to media start time.
-  PRInt64 mDataOffset;
-
   // Stores presentation info required for playback. The reader's monitor
   // must be held when accessing this.
   nsVideoInfo mInfo;
 };
 
 #endif
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -1552,20 +1552,19 @@ void nsBuiltinDecoderStateMachine::Wait(
 
 VideoData* nsBuiltinDecoderStateMachine::FindStartTime()
 {
   NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread), "Should be on state machine thread.");
   mDecoder->GetMonitor().AssertCurrentThreadIn();
   PRInt64 startTime = 0;
   mStartTime = 0;
   VideoData* v = nsnull;
-  PRInt64 dataOffset = mInfo.mDataOffset;
   {
     MonitorAutoExit exitMon(mDecoder->GetMonitor());
-    v = mReader->FindStartTime(dataOffset, startTime);
+    v = mReader->FindStartTime(0, startTime);
   }
   if (startTime != 0) {
     mStartTime = startTime;
     if (mGotDurationFromMetaData) {
       NS_ASSERTION(mEndTime != -1,
                    "We should have mEndTime as supplied duration here");
       // We were specified a duration from a Content-Duration HTTP header.
       // Adjust mEndTime so that mEndTime-mStartTime matches the specified
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -102,17 +102,18 @@ nsOggReader::nsOggReader(nsBuiltinDecode
   : nsBuiltinDecoderReader(aDecoder),
     mTheoraState(nsnull),
     mVorbisState(nsnull),
     mSkeletonState(nsnull),
     mVorbisSerial(0),
     mTheoraSerial(0),
     mPageOffset(0),
     mTheoraGranulepos(-1),
-    mVorbisGranulepos(-1)
+    mVorbisGranulepos(-1),
+    mDataOffset(0)
 {
   MOZ_COUNT_CTOR(nsOggReader);
 }
 
 nsOggReader::~nsOggReader()
 {
   ogg_sync_clear(&mOggState);
   MOZ_COUNT_DTOR(nsOggReader);
@@ -319,17 +320,16 @@ nsresult nsOggReader::ReadMetadata(nsVid
                                mTheoraState->mInfo.pic_y,
                                mTheoraState->mInfo.pic_width,
                                mTheoraState->mInfo.pic_height);
     mInfo.mFrame = nsIntSize(mTheoraState->mInfo.frame_width,
                              mTheoraState->mInfo.frame_height);
     mInfo.mDisplay = nsIntSize(mInfo.mPicture.width,
                                mInfo.mPicture.height);
   }
-  mInfo.mDataOffset = mDataOffset;
 
   if (mSkeletonState && mSkeletonState->HasIndex()) {
     // Extract the duration info out of the index, so we don't need to seek to
     // the end of stream to get it.
     nsAutoTArray<PRUint32, 2> tracks;
     if (HasVideo()) {
       tracks.AppendElement(mTheoraState->mSerial);
     }
@@ -901,29 +901,34 @@ GetChecksum(ogg_page* page)
 
 VideoData* nsOggReader::FindStartTime(PRInt64 aOffset,
                                       PRInt64& aOutStartTime)
 {
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
   nsMediaStream* stream = mDecoder->GetCurrentStream();
   NS_ENSURE_TRUE(stream != nsnull, nsnull);
-  nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
+  // Ensure aOffset is after mDataOffset, the offset of the first non-header page.
+  // This prevents us from trying to parse header pages as content pages.
+  NS_ASSERTION(mDataOffset > 0, "Must know mDataOffset by now");
+  PRInt64 offset = NS_MAX(mDataOffset, aOffset);
+  nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
   NS_ENSURE_SUCCESS(res, nsnull);
-  return nsBuiltinDecoderReader::FindStartTime(aOffset, aOutStartTime);
+  return nsBuiltinDecoderReader::FindStartTime(offset, aOutStartTime);
 }
 
 PRInt64 nsOggReader::FindEndTime(PRInt64 aEndOffset)
 {
   MonitorAutoEnter mon(mMonitor);
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
   NS_ASSERTION(mDataOffset > 0,
                "Should have offset of first non-header page");
-  PRInt64 endTime = FindEndTime(mDataOffset, aEndOffset, PR_FALSE, &mOggState);
+  PRInt64 offset = NS_MAX(mDataOffset, aEndOffset);
+  PRInt64 endTime = FindEndTime(mDataOffset, offset, PR_FALSE, &mOggState);
   // Reset read head to start of media data.
   nsMediaStream* stream = mDecoder->GetCurrentStream();
   NS_ENSURE_TRUE(stream != nsnull, -1);
   nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset);
   NS_ENSURE_SUCCESS(res, -1);
   return endTime;
 }
 
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -277,11 +277,16 @@ private:
   // the page we're about to read.
   PRInt64 mPageOffset;
 
   // The granulepos of the last decoded Theora frame.
   PRInt64 mTheoraGranulepos;
 
   // The granulepos of the last decoded Vorbis sample.
   PRInt64 mVorbisGranulepos;
+
+  // The offset of the first non-header page in the file, in bytes.
+  // Used to seek to the start of the media, and to prevent us trying to
+  // decode pages before this offset (the header pages) as content pages.
+  PRInt64 mDataOffset;
 };
 
 #endif
--- a/content/media/raw/nsRawReader.h
+++ b/content/media/raw/nsRawReader.h
@@ -107,17 +107,16 @@ public:
 
   virtual PRBool HasVideo()
   {
     return PR_TRUE;
   }
 
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
-  virtual PRInt64 FindEndTime(PRInt64 aEndOffset);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
 
 private:
   PRBool ReadFromStream(nsMediaStream *aStream, PRUint8 *aBuf,
                         PRUint32 aLength);
 
   nsRawVideoHeader mMetadata;
   PRUint32 mCurrentFrame;
--- a/content/media/wave/nsWaveReader.cpp
+++ b/content/media/wave/nsWaveReader.cpp
@@ -159,17 +159,16 @@ nsresult nsWaveReader::ReadMetadata(nsVi
   if (!loaded) {
     return NS_ERROR_FAILURE;
   }
 
   mInfo.mHasAudio = PR_TRUE;
   mInfo.mHasVideo = PR_FALSE;
   mInfo.mAudioRate = mSampleRate;
   mInfo.mAudioChannels = mChannels;
-  mInfo.mDataOffset = -1;
 
   *aInfo = mInfo;
 
   MonitorAutoExit exitReaderMon(mMonitor);
   MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
 
   mDecoder->GetStateMachine()->SetDuration(
     static_cast<PRInt64>(BytesToTime(GetDataLength()) * USECS_PER_S));
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -325,21 +325,16 @@ nsresult nsWebMReader::ReadMetadata(nsVi
           break;
         case 4:
           mInfo.mStereoMode = STEREO_MODE_BOTTOM_TOP;
           break;
         default:
           mInfo.mStereoMode = STEREO_MODE_MONO;
         }
       }
-
-      // mDataOffset is not used by the WebM backend.
-      // See bug 566779 for a suggestion to refactor
-      // and remove it.
-      mInfo.mDataOffset = -1;
     }
     else if (!mHasAudio && type == NESTEGG_TRACK_AUDIO) {
       nestegg_audio_params params;
       r = nestegg_track_audio_params(mContext, track, &params);
       if (r == -1) {
         Cleanup();
         return NS_ERROR_FAILURE;
       }
--- a/content/svg/content/src/SVGAnimatedNumberList.cpp
+++ b/content/svg/content/src/SVGAnimatedNumberList.cpp
@@ -38,17 +38,17 @@
 #include "DOMSVGAnimatedNumberList.h"
 #include "nsSVGElement.h"
 #include "nsSVGAttrTearoffTable.h"
 #ifdef MOZ_SMIL
 #include "nsSMILValue.h"
 #include "SVGNumberListSMILType.h"
 #endif // MOZ_SMIL
 
-using namespace mozilla;
+namespace mozilla {
 
 nsresult
 SVGAnimatedNumberList::SetBaseValueString(const nsAString& aValue)
 {
   SVGNumberList newBaseValue;
   nsresult rv = newBaseValue.SetValueFromString(aValue);
   if (NS_FAILED(rv)) {
     return rv;
@@ -209,8 +209,10 @@ SVGAnimatedNumberList::SMILAnimatedNumbe
 void
 SVGAnimatedNumberList::SMILAnimatedNumberList::ClearAnimValue()
 {
   if (mVal->mAnimVal) {
     mVal->ClearAnimValue(mElement, mAttrEnum);
   }
 }
 #endif // MOZ_SMIL
+
+} // namespace mozilla
--- a/content/svg/content/src/SVGAnimatedPathSegList.cpp
+++ b/content/svg/content/src/SVGAnimatedPathSegList.cpp
@@ -40,17 +40,17 @@
 #include "nsSVGAttrTearoffTable.h"
 #ifdef MOZ_SMIL
 #include "nsSMILValue.h"
 #include "SVGPathSegListSMILType.h"
 #endif // MOZ_SMIL
 
 // See the comments in this file's header!
 
-using namespace mozilla;
+namespace mozilla {
 
 nsresult
 SVGAnimatedPathSegList::SetBaseValueString(const nsAString& aValue)
 {
   SVGPathData newBaseValue;
 
   // The spec says that the path data is parsed and accepted up to the first
   // error encountered, so we don't return early if an error occurs. However,
@@ -233,8 +233,9 @@ void
 SVGAnimatedPathSegList::SMILAnimatedPathSegList::ClearAnimValue()
 {
   if (mVal->mAnimVal) {
     mVal->ClearAnimValue(mElement);
   }
 }
 #endif // MOZ_SMIL
 
+} // namespace mozilla
--- a/content/svg/content/src/SVGAnimatedPointList.cpp
+++ b/content/svg/content/src/SVGAnimatedPointList.cpp
@@ -40,17 +40,17 @@
 #include "nsSVGAttrTearoffTable.h"
 #ifdef MOZ_SMIL
 #include "nsSMILValue.h"
 #include "SVGPointListSMILType.h"
 #endif // MOZ_SMIL
 
 // See the comments in this file's header!
 
-using namespace mozilla;
+namespace mozilla {
 
 nsresult
 SVGAnimatedPointList::SetBaseValueString(const nsAString& aValue)
 {
   SVGPointList newBaseValue;
 
   // The spec says that the point data is parsed and accepted up to the first
   // error encountered, so we don't return early if an error occurs. However,
@@ -236,8 +236,9 @@ void
 SVGAnimatedPointList::SMILAnimatedPointList::ClearAnimValue()
 {
   if (mVal->mAnimVal) {
     mVal->ClearAnimValue(mElement);
   }
 }
 #endif // MOZ_SMIL
 
+} // namespace mozilla
--- a/content/svg/content/src/SVGLengthList.h
+++ b/content/svg/content/src/SVGLengthList.h
@@ -131,24 +131,24 @@ private:
   }
 
   PRBool InsertItem(PRUint32 aIndex, const SVGLength &aLength) {
     if (aIndex >= mLengths.Length()) aIndex = mLengths.Length();
     return !!mLengths.InsertElementAt(aIndex, aLength);
   }
 
   void ReplaceItem(PRUint32 aIndex, const SVGLength &aLength) {
-    NS_ASSERTION(aIndex < mLengths.Length(),
-                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    NS_ABORT_IF_FALSE(aIndex < mLengths.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
     mLengths[aIndex] = aLength;
   }
 
   void RemoveItem(PRUint32 aIndex) {
-    NS_ASSERTION(aIndex < mLengths.Length(),
-                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    NS_ABORT_IF_FALSE(aIndex < mLengths.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
     mLengths.RemoveElementAt(aIndex);
   }
 
   PRBool AppendItem(SVGLength aLength) {
     return !!mLengths.AppendElement(aLength);
   }
 
 protected:
@@ -217,17 +217,17 @@ public:
     mCanZeroPadList = aCanZeroPadList;
   }
 
   nsSVGElement* Element() const {
     return mElement; // .get();
   }
 
   PRUint8 Axis() const {
-    NS_ASSERTION(mElement, "Axis() isn't valid");
+    NS_ABORT_IF_FALSE(mElement, "Axis() isn't valid");
     return mAxis;
   }
 
   /**
    * The value returned by this function depends on which attribute this object
    * is for. If appending a list of zeros to the attribute's list would have no
    * affect on rendering (e.g. the attributes 'dx' and 'dy' on <text>), then
    * this method will return PR_TRUE. If appending a list of zeros to the
--- a/content/svg/content/src/SVGLengthListSMILType.cpp
+++ b/content/svg/content/src/SVGLengthListSMILType.cpp
@@ -117,26 +117,51 @@ SVGLengthListSMILType::Add(nsSMILValue& 
   // and *not* vice versa! It's okay in the case of adding a shorter list to a
   // longer list because during the add operation we'll end up adding the
   // zeros to actual specified values. It's *not* okay in the case of adding a
   // longer list to a shorter list because then we end up adding to implicit
   // zeros when we'd actually need to add to whatever the underlying values
   // should be, not zeros, and those values are not explicit or otherwise
   // available.
 
+  NS_ABORT_IF_FALSE(!dest.IsEmpty() || !valueToAdd.IsEmpty(),
+                    "Expecting at least one non-identity operand");
+
+  if (!valueToAdd.Element()) { // Adding identity value - no-op
+    NS_ABORT_IF_FALSE(valueToAdd.IsEmpty(),
+                      "Identity values should be empty");
+    return NS_OK;
+  }
+
+  if (!dest.Element()) { // Adding *to* an identity value
+    NS_ABORT_IF_FALSE(dest.IsEmpty(),
+                      "Identity values should be empty");
+    if (!dest.SetLength(valueToAdd.Length())) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    for (PRUint32 i = 0; i < dest.Length(); ++i) {
+      dest[i].SetValueAndUnit(valueToAdd[i].GetValueInCurrentUnits() * aCount,
+                              valueToAdd[i].GetUnit());
+    }
+    dest.SetInfo(valueToAdd.Element(), valueToAdd.Axis(),
+                 valueToAdd.CanZeroPadList()); // propagate target element info!
+    return NS_OK;
+  }
+  NS_ABORT_IF_FALSE(dest.Element() == valueToAdd.Element(),
+                    "adding values from different elements...?");
+
+  // Zero-pad our |dest| list, if necessary.
   if (dest.Length() < valueToAdd.Length()) {
     if (!dest.CanZeroPadList()) {
       // nsSVGUtils::ReportToConsole
       return NS_ERROR_FAILURE;
     }
 
-    NS_ASSERTION(valueToAdd.CanZeroPadList() || dest.Length() == 0,
-                 "Only \"zero\" nsSMILValues from the SMIL engine should "
-                 "return PR_TRUE for CanZeroPadList() when the attribute "
-                 "being animated can't be zero padded");
+    NS_ABORT_IF_FALSE(valueToAdd.CanZeroPadList(),
+                      "values disagree about attribute's zero-paddibility");
 
     PRUint32 i = dest.Length();
     if (!dest.SetLength(valueToAdd.Length())) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     for (; i < valueToAdd.Length(); ++i) {
       dest[i].SetValueAndUnit(0.0f, valueToAdd[i].GetUnit());
     }
@@ -148,23 +173,24 @@ SVGLengthListSMILType::Add(nsSMILValue& 
       valToAdd = valueToAdd[i].GetValueInCurrentUnits();
     } else {
       // If units differ, we use the unit of the item in 'dest'.
       // We leave it to the frame code to check that values are finite.
       valToAdd = valueToAdd[i].GetValueInSpecifiedUnit(dest[i].GetUnit(),
                                                        dest.Element(),
                                                        dest.Axis());
     }
-    dest[i].SetValueAndUnit(dest[i].GetValueInCurrentUnits() + valToAdd,
-                            dest[i].GetUnit());
+    dest[i].SetValueAndUnit(
+      dest[i].GetValueInCurrentUnits() + valToAdd * aCount,
+      dest[i].GetUnit());
   }
 
-  // propagate flag:
-  dest.SetCanZeroPadList(dest.CanZeroPadList() &&
-                         valueToAdd.CanZeroPadList());
+  // propagate target element info!
+  dest.SetInfo(valueToAdd.Element(), valueToAdd.Axis(),
+               dest.CanZeroPadList() && valueToAdd.CanZeroPadList());
 
   return NS_OK;
 }
 
 nsresult
 SVGLengthListSMILType::ComputeDistance(const nsSMILValue& aFrom,
                                        const nsSMILValue& aTo,
                                        double& aDistance) const
@@ -176,18 +202,18 @@ SVGLengthListSMILType::ComputeDistance(c
     *static_cast<const SVGLengthListAndInfo*>(aFrom.mU.mPtr);
   const SVGLengthListAndInfo& to =
     *static_cast<const SVGLengthListAndInfo*>(aTo.mU.mPtr);
 
   // To understand this code, see the comments documenting our Init() method,
   // and documenting SVGLengthListAndInfo::CanZeroPadList().
 
   NS_ASSERTION((from.CanZeroPadList() == to.CanZeroPadList()) ||
-               (from.CanZeroPadList() && from.Length() == 0) ||
-               (to.CanZeroPadList() && to.Length() == 0),
+               (from.CanZeroPadList() && from.IsEmpty()) ||
+               (to.CanZeroPadList() && to.IsEmpty()),
                "Only \"zero\" nsSMILValues from the SMIL engine should "
                "return PR_TRUE for CanZeroPadList() when the attribute "
                "being animated can't be zero padded");
 
   if ((from.Length() < to.Length() && !from.CanZeroPadList()) ||
       (to.Length() < from.Length() && !to.CanZeroPadList())) {
     // nsSVGUtils::ReportToConsole
     return NS_ERROR_FAILURE;
@@ -251,18 +277,18 @@ SVGLengthListSMILType::Interpolate(const
     *static_cast<const SVGLengthListAndInfo*>(aEndVal.mU.mPtr);
   SVGLengthListAndInfo& result =
     *static_cast<SVGLengthListAndInfo*>(aResult.mU.mPtr);
 
   // To understand this code, see the comments documenting our Init() method,
   // and documenting SVGLengthListAndInfo::CanZeroPadList().
 
   NS_ASSERTION((start.CanZeroPadList() == end.CanZeroPadList()) ||
-               (start.CanZeroPadList() && start.Length() == 0) ||
-               (end.CanZeroPadList() && end.Length() == 0),
+               (start.CanZeroPadList() && start.IsEmpty()) ||
+               (end.CanZeroPadList() && end.IsEmpty()),
                "Only \"zero\" nsSMILValues from the SMIL engine should "
                "return PR_TRUE for CanZeroPadList() when the attribute "
                "being animated can't be zero padded");
 
   if ((start.Length() < end.Length() && !start.CanZeroPadList()) ||
       (end.Length() < start.Length() && !end.CanZeroPadList())) {
     // nsSVGUtils::ReportToConsole
     return NS_ERROR_FAILURE;
@@ -294,16 +320,16 @@ SVGLengthListSMILType::Interpolate(const
                               start[i].GetValueInCurrentUnits() * aUnitDistance,
                               start[i].GetUnit());
   }
   for (; i < end.Length(); ++i) {
     result[i].SetValueAndUnit(end[i].GetValueInCurrentUnits() * aUnitDistance,
                               end[i].GetUnit());
   }
 
-  // propagate flag:
-  result.SetCanZeroPadList(start.CanZeroPadList() &&
-                           end.CanZeroPadList());
+  // propagate target element info!
+  result.SetInfo(end.Element(), end.Axis(),
+                 start.CanZeroPadList() && end.CanZeroPadList());
 
   return NS_OK;
 }
 
 } // namespace mozilla
--- a/content/svg/content/src/SVGNumberList.cpp
+++ b/content/svg/content/src/SVGNumberList.cpp
@@ -42,17 +42,17 @@
 #include "nsContentUtils.h"
 #include "nsString.h"
 #include "nsSVGUtils.h"
 #include "string.h"
 #include "prdtoa.h"
 #include "nsTextFormatter.h"
 #include "nsCharSeparatedTokenizer.h"
 
-using namespace mozilla;
+namespace mozilla {
 
 nsresult
 SVGNumberList::CopyFrom(const SVGNumberList& rhs)
 {
   if (!mNumbers.SetCapacity(rhs.Length())) {
     // Yes, we do want fallible alloc here
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -103,8 +103,10 @@ SVGNumberList::SetValueFromString(const 
     }
     temp.AppendItem(num);
   }
   if (tokenizer.lastTokenEndedWithSeparator()) {
     return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
   }
   return CopyFrom(temp);
 }
+
+} // namespace mozilla
--- a/content/svg/content/src/SVGNumberList.h
+++ b/content/svg/content/src/SVGNumberList.h
@@ -134,24 +134,24 @@ private:
   PRBool InsertItem(PRUint32 aIndex, const float &aNumber) {
     if (aIndex >= mNumbers.Length()) {
       aIndex = mNumbers.Length();
     }
     return !!mNumbers.InsertElementAt(aIndex, aNumber);
   }
 
   void ReplaceItem(PRUint32 aIndex, const float &aNumber) {
-    NS_ASSERTION(aIndex < mNumbers.Length(),
-                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    NS_ABORT_IF_FALSE(aIndex < mNumbers.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
     mNumbers[aIndex] = aNumber;
   }
 
   void RemoveItem(PRUint32 aIndex) {
-    NS_ASSERTION(aIndex < mNumbers.Length(),
-                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    NS_ABORT_IF_FALSE(aIndex < mNumbers.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
     mNumbers.RemoveElementAt(aIndex);
   }
 
   PRBool AppendItem(float aNumber) {
     return !!mNumbers.AppendElement(aNumber);
   }
 
 protected:
--- a/content/svg/content/src/SVGNumberListSMILType.cpp
+++ b/content/svg/content/src/SVGNumberListSMILType.cpp
@@ -51,17 +51,17 @@
  *
  * Note that we don't need to worry about that variation here, however. The way
  * that the SMIL engine creates and composites sandwich layers together allows
  * us to treat "identity" nsSMILValue objects as a number list of zeros. Such
  * identity nsSMILValues are identified by the fact that their
  # SVGNumberListAndInfo has not been given an element yet.
  */
 
-using namespace mozilla;
+namespace mozilla {
 
 /*static*/ SVGNumberListSMILType SVGNumberListSMILType::sSingleton;
 
 //----------------------------------------------------------------------
 // nsISMILType implementation
 
 void
 SVGNumberListSMILType::Init(nsSMILValue &aValue) const
@@ -235,8 +235,10 @@ SVGNumberListSMILType::Interpolate(const
     }
     return NS_OK;
   }
   for (PRUint32 i = 0; i < end.Length(); ++i) {
     result[i] = start[i] + (end[i] - start[i]) * aUnitDistance;
   }
   return NS_OK;
 }
+
+} // namespace mozilla
--- a/content/svg/content/src/SVGPathSegListSMILType.cpp
+++ b/content/svg/content/src/SVGPathSegListSMILType.cpp
@@ -34,17 +34,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "SVGPathSegListSMILType.h"
 #include "nsSMILValue.h"
 #include "SVGPathData.h"
 #include <math.h>
 
-using namespace mozilla;
+namespace mozilla {
 
 /*static*/ SVGPathSegListSMILType SVGPathSegListSMILType::sSingleton;
 
 //----------------------------------------------------------------------
 // nsISMILType implementation
 
 void
 SVGPathSegListSMILType::Init(nsSMILValue &aValue) const
@@ -464,8 +464,10 @@ SVGPathSegListSMILType::Interpolate(cons
 
     NS_ABORT_IF_FALSE(pStart == pStartDataEnd && pEnd == pEndDataEnd &&
                       pResult == result.end(),
                       "Very, very bad - path data corrupt");
   }
 
   return NS_OK;
 }
+
+} // namespace mozilla
--- a/content/svg/content/src/SVGPointList.cpp
+++ b/content/svg/content/src/SVGPointList.cpp
@@ -42,17 +42,17 @@
 #include "nsContentUtils.h"
 #include "nsString.h"
 #include "nsSVGUtils.h"
 #include "string.h"
 #include "prdtoa.h"
 #include "nsTextFormatter.h"
 #include "nsCharSeparatedTokenizer.h"
 
-using namespace mozilla;
+namespace mozilla {
 
 nsresult
 SVGPointList::CopyFrom(const SVGPointList& rhs)
 {
   if (!SetCapacity(rhs.Length())) {
     // Yes, we do want fallible alloc here
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -147,8 +147,10 @@ SVGPointList::SetValueFromString(const n
     rv = NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
   }
   nsresult rv2 = CopyFrom(temp);
   if (NS_FAILED(rv2)) {
     return rv2; // prioritize OOM error code over syntax errors
   }
   return rv;
 }
+
+} // namespace mozilla
--- a/content/svg/content/src/SVGPointList.h
+++ b/content/svg/content/src/SVGPointList.h
@@ -138,24 +138,24 @@ private:
   PRBool InsertItem(PRUint32 aIndex, const SVGPoint &aPoint) {
     if (aIndex >= mItems.Length()) {
       aIndex = mItems.Length();
     }
     return !!mItems.InsertElementAt(aIndex, aPoint);
   }
 
   void ReplaceItem(PRUint32 aIndex, const SVGPoint &aPoint) {
-    NS_ASSERTION(aIndex < mItems.Length(),
-                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    NS_ABORT_IF_FALSE(aIndex < mItems.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
     mItems[aIndex] = aPoint;
   }
 
   void RemoveItem(PRUint32 aIndex) {
-    NS_ASSERTION(aIndex < mItems.Length(),
-                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    NS_ABORT_IF_FALSE(aIndex < mItems.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
     mItems.RemoveElementAt(aIndex);
   }
 
   PRBool AppendItem(SVGPoint aPoint) {
     return !!mItems.AppendElement(aPoint);
   }
 
 protected:
--- a/content/svg/content/src/SVGPointListSMILType.cpp
+++ b/content/svg/content/src/SVGPointListSMILType.cpp
@@ -35,17 +35,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "SVGPointListSMILType.h"
 #include "nsSMILValue.h"
 #include "SVGPointList.h"
 #include "nsMathUtils.h"
 #include <math.h>
 
-using namespace mozilla;
+namespace mozilla {
 
 /*static*/ SVGPointListSMILType SVGPointListSMILType::sSingleton;
 
 //----------------------------------------------------------------------
 // nsISMILType implementation
 
 void
 SVGPointListSMILType::Init(nsSMILValue &aValue) const
@@ -220,8 +220,10 @@ SVGPointListSMILType::Interpolate(const 
     }
     return NS_OK;
   }
   for (PRUint32 i = 0; i < end.Length(); ++i) {
     result[i] = start[i] + (end[i] - start[i]) * aUnitDistance;
   }
   return NS_OK;
 }
+
+} // namespace mozilla
--- a/content/svg/content/test/test_SVGxxxList.xhtml
+++ b/content/svg/content/test/test_SVGxxxList.xhtml
@@ -75,16 +75,20 @@ To have the battery of generic tests run
   attr_val_3a:
   attr_val_3b:
     Two attribute values containing three different items.
   attr_val_4
     An attribute value containing four items.
   attr_val_5a:
   attr_val_5b:
     Two attribute values containing five different items.
+  attr_val_5b_firstItem_x3_constructor:
+    Function to construct a list-item that should match the first item in a
+    SVGXxxList after three repeats of a cumulative animation to attr_val_5b.
+    This function takes t.item_constructor as its only argument.
   item_constructor:
     Function to create a dummy list item.
   item_is:
     Function to compare two list items for equality, like "is()". If this
     property is omitted, it is assumed that we can just compare
     "item.value" (which is the case for most list types).
 */
 
@@ -99,17 +103,22 @@ var tests = [
     el_type: 'SVGTextElement',
     prop_type: 'SVGAnimatedLengthList',
     list_type: 'SVGLengthList',
     item_type: 'SVGLength',
     attr_val_3a: '10 20ex, 30in',
     attr_val_3b: '30in 10, 20ex',
     attr_val_4 : '10 20ex, 30in ,40cm',
     attr_val_5a: '10 20ex, 30in ,40cm , 50%',
-    attr_val_5b: '50% 10, 20ex ,30in , 40cm',
+    attr_val_5b: '20 50%, 20ex ,30in , 40cm',
+    attr_val_5b_firstItem_x3_constructor: function(constructor) {
+      var expected = constructor();
+      expected.value = 60;
+      return expected;
+    },
     item_constructor: function() {
       // We need this function literal to avoid "Illegal operation on
       // WrappedNative prototype object" NS_ERROR_XPC_BAD_OP_ON_WN_PROTO.
       return document.getElementById('svg').createSVGLength();
     }
   },
   {
     // SVGNumberList test:
@@ -122,16 +131,21 @@ var tests = [
     prop_type: 'SVGAnimatedNumberList',
     list_type: 'SVGNumberList',
     item_type: 'SVGNumber',
     attr_val_3a: '0 20 40',
     attr_val_3b: '60 40 20',
     attr_val_4 : '40 20 10 80',
     attr_val_5a: '90 30 60 20 70',
     attr_val_5b: '30 20 70 30 90',
+    attr_val_5b_firstItem_x3_constructor: function(constructor) {
+      var expected = constructor();
+      expected.value = 90;
+      return expected;
+    },
     item_constructor: function() {
       // We need this function literal to avoid "Illegal operation on
       // WrappedNative prototype object" NS_ERROR_XPC_BAD_OP_ON_WN_PROTO.
       return document.getElementById('svg').createSVGNumber();
     }
   },
   {
     // SVGNumberList test:
@@ -144,16 +158,21 @@ var tests = [
     prop_type: 'SVGAnimatedNumberList',
     list_type: 'SVGNumberList',
     item_type: 'SVGNumber',
     attr_val_3a: '0 .5 .2',
     attr_val_3b: '1 .7 .1',
     attr_val_4 : '.5 .3 .8 .2',
     attr_val_5a: '3 4 5 6 7',
     attr_val_5b: '7 6 5 4 3',
+    attr_val_5b_firstItem_x3_constructor: function(constructor) {
+      var expected = constructor();
+      expected.value = 21;
+      return expected;
+    },
     item_constructor: function() {
       // We need this function literal to avoid "Illegal operation on
       // WrappedNative prototype object" NS_ERROR_XPC_BAD_OP_ON_WN_PROTO.
       return document.getElementById('svg').createSVGNumber();
     }
   },
   {
     // SVGPointList test:
@@ -166,16 +185,22 @@ var tests = [
     prop_type: null,
     list_type: 'SVGPointList',
     item_type: 'SVGPoint',
     attr_val_3a: ' 10,10 50,50 90,10 ',
     attr_val_3b: ' 10,50 50,10 90,50 ',
     attr_val_4 : ' 10,10 50,50 90,10 200,100 ',
     attr_val_5a: ' 10,10 50,50 90,10 130,50 170,10 ',
     attr_val_5b: ' 50,10 50,10 90,50 130,10 170,50 ',
+    attr_val_5b_firstItem_x3_constructor: function(constructor) {
+      var expected = constructor();
+      expected.x = 150;
+      expected.y = 30;
+      return expected;
+    },
     item_constructor: function() {
       // XXX return different values each time
       return document.getElementById('svg').createSVGPoint();
     },
     item_is: function(itemA, itemB, message) {
       ok(typeof(itemA.x) != 'undefined' &&
          typeof(itemB.x) != 'undefined',
          'expecting x property');
@@ -198,27 +223,53 @@ var tests = [
     prop_type: null,
     list_type: 'SVGPathSegList',
     item_type: 'SVGPathSeg',
     attr_val_3a: 'M 10,10 L 50,50 L 90,10',
     attr_val_3b: 'M 10,50 L 50,10 L 90,50',
     attr_val_4 : 'M 10,10 L 50,50 L 90,10 M 200,100',
     attr_val_5a: 'M 10,10 L 50,50 L 90,10 L 130,50 L 170,10',
     attr_val_5b: 'M 50,10 L 50,10 L 90,50 L 130,10 L 170,50',
+    attr_val_5b_firstItem_x3_constructor: function(constructor) {
+      var expected = constructor();
+      is(expected.pathSegTypeAsLetter, "M",
+         "test error -- expected constructor to generate a segment of type M");
+      expected.x = 150;
+      expected.y = 30;
+      return expected;
+    },
     item_constructor: function() {
       // XXX return different values each time
       return document.getElementById('path').createSVGPathSegMovetoAbs(1, 1);
     },
     item_is: function(itemA, itemB, message) {
-      ok(typeof(itemA.pathSegType) != 'undefined' &&
-         typeof(itemB.pathSegType) != 'undefined',
-         'expecting pathSegType property');
+      ok(typeof(itemA.pathSegTypeAsLetter) != 'undefined' &&
+         typeof(itemB.pathSegTypeAsLetter) != 'undefined',
+         'expecting pathSegTypeAsLetter property');
+
+      // First: are we dealing  with the same type of segment?
+      is(itemA.pathSegTypeAsLetter, itemB.pathSegTypeAsLetter, message);
+      if (itemA.pathSegTypeAsLetter != itemB.pathSegTypeAsLetter)
+        return;  // The rest of this function is nonsense if types don't match.
 
-      // NOTE: Just comparing pathSegType - probably sufficient for our purposes
-      is(itemA.pathSegType, itemB.pathSegType, message);
+      // Make sure property-counts match (so we can iterate across itemA's
+      // properties and not worry about itemB having extra properties that
+      // we might be skipping over).
+      is(keys(itemA).length, keys(itemB).length,
+        'expecting same property-count when comparing path segs of same type.');
+
+      // Compare the properties, skipping the constant properties inherited
+      // from 'SVGPathSeg', and skipping the pathSegTypeAsLetter field since we
+      // already checked that above. 
+      for (var prop in itemA) {
+        if (!SVGPathSeg.hasOwnProperty(prop) &&
+            prop != 'pathSegTypeAsLetter') {
+          is(itemA[prop], itemB[prop], message);
+        }
+      }
     }
   },
 /*
   {
     // SVGPathSegList test:
     target_element_id: 'path',
     attr_name: 'd',
     prop_name: null, // SVGAnimatedPathData is an inherited interface!
@@ -233,22 +284,40 @@ var tests = [
     attr_val_4 : '',
     attr_val_5a: '',
     attr_val_5b: '',
     item_constructor: function() {
       // XXX return different values each time
       return SVGPathElement.createSVGPathSegLinetoAbs(1, 1);
     },
     item_is: function(itemA, itemB, message) {
-      ok(typeof(itemA.pathSegType) != 'undefined' &&
-         typeof(itemB.pathSegType) != 'undefined',
-         'expecting pathSegType property');
+      ok(typeof(itemA.pathSegTypeAsLetter) != 'undefined' &&
+         typeof(itemB.pathSegTypeAsLetter) != 'undefined',
+         'expecting pathSegTypeAsLetter property');
+
+      // First: are we dealing  with the same type of segment?
+      is(itemA.pathSegTypeAsLetter, itemB.pathSegTypeAsLetter, message);
+      if (itemA.pathSegTypeAsLetter != itemB.pathSegTypeAsLetter)
+        return;  // The rest of this function is nonsense if types don't match.
 
-      // NOTE: Just comparing pathSegType - probably sufficient for our purposes
-      is(itemA.pathSegType, itemB.pathSegType, message);
+      // Make sure property-counts match (so we can iterate across itemA's
+      // properties and not worry about itemB having extra properties that
+      // we might be skipping over).
+      is(keys(itemA).length, keys(itemB).length,
+        'expecting same property-count when comparing path segs of same type.');
+
+      // Compare the properties, skipping the constant properties inherited
+      // from 'SVGPathSeg', and skipping the pathSegTypeAsLetter field since we
+      // already checked that above. 
+      for (var prop in itemA) {
+        if (!SVGPathSeg.hasOwnProperty(prop) &&
+            prop != 'pathSegTypeAsLetter') {
+          is(itemA[prop], itemB[prop], message);
+        }
+      }
     }
   },
   {
     // SVGStringList test:
     target_element_id: 'g',
     attr_name: 'requiredFeatures', // requiredExtensions, systemLanguage, viewTarget
     prop_name: null, // SVGStringList attributes are not animatable
     bv_name: 'requiredFeatures',
@@ -294,22 +363,22 @@ var tests = [
   },
   */
 ];
 
 
 /*
 This function returns a DocumentFragment with three 'animate' element children. The duration of the three animations is as follows:
 
-  animation 1: |  *-----------*-----------*
+  animation 1: |  *-----------*-----------*-----------*
   animation 2: |     *--*
   animation 3: |                    *--*
-               |__________________________________> time (s)
-               |  |  |  |  |  |  |  |  |  |  |  |
-               0  1  2  3  4  5  6  7  8  9 10 11
+               |___________________________________________> time (s)
+               |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+               0  1  2  3  4  5  6  7  8  9 10 11 12 13 14
 
 The first animation repeats once so that we can test state on a repeat animation.
 
 The second animation overrides the first animation for a short time, and has fewer list items than the first animation. This allows us to test object identity and other state on and after an overriding animation. Specifically, it allows us to check whether animVal list items are kept or discarded after the end of an overriding animation that has fewer items.
 
 The third animation has additive="sum", with fewer items than the lower priority animation 1, allowing us to test object identity and other state in that scenario. TODO: some type aware tests to check whether the composite fails or works?
 
 At t=0s and t=1s we test the effect of an attribute value changes in the absence and presence of SMIL animation respectively.
@@ -338,17 +407,18 @@ function create_animate_elements(test)
     var animate3 = document.createElementNS(SVG_NS, 'animate');
   }
 
   animate1.setAttribute('attributeName', test.attr_name);
   animate1.setAttribute('from', test.attr_val_5a);
   animate1.setAttribute('to', test.attr_val_5b);
   animate1.setAttribute('begin', '1s');
   animate1.setAttribute('dur', '4s');
-  animate1.setAttribute('repeatCount', '2');
+  animate1.setAttribute('repeatCount', '3');
+  animate1.setAttribute('accumulate', 'sum');
   animate1.setAttribute('fill', 'freeze');
   df.appendChild(animate1);
 
   animate2.setAttribute('attributeName', test.attr_name);
   animate2.setAttribute('from', test.attr_val_3a);
   animate2.setAttribute('to', test.attr_val_3b);
   animate2.setAttribute('begin', '2s');
   animate2.setAttribute('dur', '1s');
@@ -1212,35 +1282,41 @@ function run_animation_timeline_tests()
     // all SVGLengthList attributes allow a short list to be added to longer
     // list, they do not all allow a longer list to be added to shorter list.
     // Specifically that would not be good for 'x' and 'y' on <text> since
     // lengths there are not naturally zero. See the comment in
     // SVGLengthListSMILAttr::Add().
   }
 
 
-  /********************    t = 10s    ********************/
+  /********************    t = 13s    ********************/
 
-  svg.setCurrentTime(10); // all animations have finished, but one is frozen
+  svg.setCurrentTime(13); // all animations have finished, but one is frozen
 
   for each (var t in tests) {
     if (!t.animVal)
       continue;
 
     ok(t.baseVal.numberOfItems == t.old_baseVal_items.length &&
        t.baseVal.getItem(3) === t.old_baseVal_items[3],
        'When a SMIL animation ends, it should never affect the '+
        t.list_type+' for '+t.bv_path+', or its list items.');
 
     is(t.animVal.numberOfItems, 5,
        'Even though all SMIL animation have finished, the number '+
        'of items in the '+t.list_type+' for '+t.av_path+
        ' should still be more than the same as the number of items in '+
        t.bv_path+' since one of the animations is still frozen.');
 
+    var expected = t.attr_val_5b_firstItem_x3_constructor(t.item_constructor);
+    t.item_is(t.animVal.getItem(0), expected,
+      'animation with accumulate="sum" and repeatCount="3" for attribute "'+
+       t.attr_name+'" should end up at 3x the "to" value.');
+
+    // Unfreeze frozen animation (removing its effects)
     var frozen_animate_element =
       t.element.querySelector('animate[fill][attributeName="'+t.attr_name+'"]');
     frozen_animate_element.removeAttribute('fill');
 
     ok(t.animVal.numberOfItems == t.baseVal.numberOfItems,
        'Once all SMIL animation have finished and been un-frozen, the number '+
        'of items in the '+t.list_type+' for '+t.av_path+
        ' should be the same as the number of items in '+t.bv_path+'.');
--- a/gfx/src/Makefile.in
+++ b/gfx/src/Makefile.in
@@ -68,24 +68,23 @@ EXPORTS	= \
 	nsFont.h \
 	nsRect.h \
 	nsRegion.h \
 	nsPoint.h \
 	nsSize.h \
 	nsMargin.h \
 	nsTransform2D.h \
 	nsRenderingContext.h \
-	nsIFontMetrics.h \
+	nsFontMetrics.h \
 	nsIDeviceContext.h \
 	nsGfxCIID.h \
 	nsIRegion.h \
 	nsITheme.h \
 	nsThemeConstants.h \
 	gfxCrashReporterUtils.h \
-	nsIThebesFontMetrics.h \
 	nsBoundingMetrics.h \
 	$(NULL)
 
 ifdef MOZ_X11
 EXPORTS_NAMESPACES	= mozilla
 EXPORTS_mozilla		= X11Util.h
 endif
 
@@ -96,17 +95,17 @@ CPPSRCS = \
         nsRegion.cpp \
         nsTransform2D.cpp \
         nsScriptableRegion.cpp \
         gfxCrashReporterUtils.cpp \
         nsThebesDeviceContext.cpp \
         nsThebesRegion.cpp \
         nsThebesGfxFactory.cpp \
         nsRenderingContext.cpp \
-        nsThebesFontMetrics.cpp \
+        nsFontMetrics.cpp \
         nsThebesFontEnumerator.cpp \
        $(NULL)
 
 ifdef MOZ_X11
 CPPSRCS += X11Util.cpp
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
--- a/gfx/src/nsBoundingMetrics.h
+++ b/gfx/src/nsBoundingMetrics.h
@@ -38,17 +38,17 @@
 #ifndef __nsBoundingMetrics_h
 #define __nsBoundingMetrics_h
 
 #include "nsCoord.h"
 
 /* Struct used for accurate measurements of a string, in order to
  * allow precise positioning when processing MathML.  This is in its
  * own header file because some very-widely-included headers need it
- * but not the rest of nsIFontMetrics, or vice versa.
+ * but not the rest of nsFontMetrics, or vice versa.
  */
 
 #ifdef MOZ_MATHML
 struct nsBoundingMetrics {
 
     ///////////
     // Metrics that _exactly_ enclose the text:
 
rename from gfx/src/nsThebesFontMetrics.cpp
rename to gfx/src/nsFontMetrics.cpp
--- a/gfx/src/nsThebesFontMetrics.cpp
+++ b/gfx/src/nsFontMetrics.cpp
@@ -31,132 +31,162 @@
  * 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 "nsThebesFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsBoundingMetrics.h"
+#include "nsRenderingContext.h"
 #include "nsThebesDeviceContext.h"
-#include "nsFont.h"
-
-#include "nsString.h"
-#include <stdio.h>
-
 #include "gfxTextRunCache.h"
-#include "gfxPlatform.h"
-#include "gfxUserFontSet.h"
+
+namespace {
 
-NS_IMPL_ISUPPORTS1(nsThebesFontMetrics, nsIFontMetrics)
+class AutoTextRun : public gfxTextRunCache::AutoTextRun {
+public:
+    AutoTextRun(nsFontMetrics* aMetrics, nsRenderingContext* aRC,
+                const char* aString, PRInt32 aLength)
+        : gfxTextRunCache::AutoTextRun(gfxTextRunCache::MakeTextRun(
+            reinterpret_cast<const PRUint8*>(aString), aLength,
+            aMetrics->GetThebesFontGroup(), aRC->ThebesContext(),
+            aMetrics->AppUnitsPerDevPixel(),
+            ComputeFlags(aMetrics)))
+    {}
+
+    AutoTextRun(nsFontMetrics* aMetrics, nsRenderingContext* aRC,
+                const PRUnichar* aString, PRInt32 aLength)
+        : gfxTextRunCache::AutoTextRun(gfxTextRunCache::MakeTextRun(
+            aString, aLength, aMetrics->GetThebesFontGroup(),
+            aRC->ThebesContext(),
+            aMetrics->AppUnitsPerDevPixel(),
+            ComputeFlags(aMetrics)))
+    {}
 
-#include <stdlib.h>
+private:
+    static PRUint32 ComputeFlags(nsFontMetrics* aMetrics) {
+        PRUint32 flags = 0;
+        if (aMetrics->GetTextRunRTL()) {
+            flags |= gfxTextRunFactory::TEXT_IS_RTL;
+        }
+        return flags;
+    }
+};
 
-nsThebesFontMetrics::nsThebesFontMetrics()
+class StubPropertyProvider : public gfxTextRun::PropertyProvider {
+public:
+    virtual void GetHyphenationBreaks(PRUint32 aStart, PRUint32 aLength,
+                                      PRPackedBool* aBreakBefore) {
+        NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
+    }
+    virtual gfxFloat GetHyphenWidth() {
+        NS_ERROR("This shouldn't be called because we never enable hyphens");
+        return 0;
+    }
+    virtual void GetSpacing(PRUint32 aStart, PRUint32 aLength,
+                            Spacing* aSpacing) {
+        NS_ERROR("This shouldn't be called because we never enable spacing");
+    }
+};
+
+} // anon namespace
+
+nsFontMetrics::nsFontMetrics()
+    : mDeviceContext(nsnull), mP2A(-1), mTextRunRTL(PR_FALSE)
 {
-    mFontStyle = nsnull;
-    mFontGroup = nsnull;
 }
 
-nsThebesFontMetrics::~nsThebesFontMetrics()
+nsFontMetrics::~nsFontMetrics()
 {
     if (mDeviceContext)
         mDeviceContext->FontMetricsDeleted(this);
-    delete mFontStyle;
-    //delete mFontGroup;
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLanguage,
-                          nsIDeviceContext *aContext, 
-                          gfxUserFontSet *aUserFontSet)
+nsresult
+nsFontMetrics::Init(const nsFont& aFont, nsIAtom* aLanguage,
+                    nsIDeviceContext *aContext,
+                    gfxUserFontSet *aUserFontSet)
 {
+    NS_ABORT_IF_FALSE(mP2A == -1, "already initialized");
+
     mFont = aFont;
     mLanguage = aLanguage;
     mDeviceContext = (nsThebesDeviceContext*)aContext;
     mP2A = mDeviceContext->AppUnitsPerDevPixel();
-    mIsRightToLeft = PR_FALSE;
-    mTextRunRTL = PR_FALSE;
-
-    gfxFloat size = gfxFloat(aFont.size) / mP2A;
 
-    PRBool printerFont = mDeviceContext->IsPrinterSurface();
-    mFontStyle = new gfxFontStyle(aFont.style, aFont.weight, aFont.stretch,
-                                  size, aLanguage,
-                                  aFont.sizeAdjust, aFont.systemFont,
-                                  printerFont,
-                                  aFont.featureSettings,
-                                  aFont.languageOverride);
+    gfxFontStyle style(aFont.style,
+                       aFont.weight,
+                       aFont.stretch,
+                       gfxFloat(aFont.size) / mP2A,
+                       aLanguage,
+                       aFont.sizeAdjust,
+                       aFont.systemFont,
+                       mDeviceContext->IsPrinterSurface(),
+                       aFont.featureSettings,
+                       aFont.languageOverride);
 
-    mFontGroup =
-        gfxPlatform::GetPlatform()->CreateFontGroup(aFont.name, mFontStyle, 
-                                                    aUserFontSet);
-    if (mFontGroup->FontListLength() < 1) 
+    mFontGroup = gfxPlatform::GetPlatform()->
+        CreateFontGroup(aFont.name, &style, aUserFontSet);
+    if (mFontGroup->FontListLength() < 1)
         return NS_ERROR_UNEXPECTED;
 
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::Destroy()
+void
+nsFontMetrics::Destroy()
 {
     mDeviceContext = nsnull;
-    return NS_OK;
 }
 
 // XXXTODO get rid of this macro
 #define ROUND_TO_TWIPS(x) (nscoord)floor(((x) * mP2A) + 0.5)
 #define CEIL_TO_TWIPS(x) (nscoord)NS_ceil((x) * mP2A)
 
-const gfxFont::Metrics& nsThebesFontMetrics::GetMetrics() const
+const gfxFont::Metrics& nsFontMetrics::GetMetrics() const
 {
     return mFontGroup->GetFontAt(0)->GetMetrics();
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetXHeight(nscoord& aResult)
+nscoord
+nsFontMetrics::XHeight()
 {
-    aResult = ROUND_TO_TWIPS(GetMetrics().xHeight);
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().xHeight);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetSuperscriptOffset(nscoord& aResult)
+nscoord
+nsFontMetrics::SuperscriptOffset()
 {
-    aResult = ROUND_TO_TWIPS(GetMetrics().superscriptOffset);
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().superscriptOffset);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetSubscriptOffset(nscoord& aResult)
+nscoord
+nsFontMetrics::SubscriptOffset()
 {
-    aResult = ROUND_TO_TWIPS(GetMetrics().subscriptOffset);
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().subscriptOffset);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetStrikeout(nscoord& aOffset, nscoord& aSize)
+void
+nsFontMetrics::GetStrikeout(nscoord& aOffset, nscoord& aSize)
 {
     aOffset = ROUND_TO_TWIPS(GetMetrics().strikeoutOffset);
     aSize = ROUND_TO_TWIPS(GetMetrics().strikeoutSize);
-    return NS_OK;
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetUnderline(nscoord& aOffset, nscoord& aSize)
+void
+nsFontMetrics::GetUnderline(nscoord& aOffset, nscoord& aSize)
 {
     aOffset = ROUND_TO_TWIPS(mFontGroup->GetUnderlineOffset());
     aSize = ROUND_TO_TWIPS(GetMetrics().underlineSize);
-
-    return NS_OK;
 }
 
-// GetHeight/GetMaxAscent/GetMaxDescent/GetMaxHeight must contain the
+// GetMaxAscent/GetMaxDescent/GetMaxHeight must contain the
 // text-decoration lines drawable area. See bug 421353.
 // BE CAREFUL for rounding each values. The logic MUST be same as
 // nsCSSRendering::GetTextDecorationRectInternal's.
 
 static gfxFloat ComputeMaxDescent(const gfxFont::Metrics& aMetrics,
                                   gfxFontGroup* aFontGroup)
 {
     gfxFloat offset = NS_floor(-aFontGroup->GetUnderlineOffset() + 0.5);
@@ -165,343 +195,175 @@ static gfxFloat ComputeMaxDescent(const 
     return PR_MAX(minDescent, aMetrics.maxDescent);
 }
 
 static gfxFloat ComputeMaxAscent(const gfxFont::Metrics& aMetrics)
 {
     return NS_floor(aMetrics.maxAscent + 0.5);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetHeight(nscoord &aHeight)
+nscoord
+nsFontMetrics::InternalLeading()
 {
-    aHeight = CEIL_TO_TWIPS(ComputeMaxAscent(GetMetrics())) +
-        CEIL_TO_TWIPS(ComputeMaxDescent(GetMetrics(), mFontGroup));
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().internalLeading);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetInternalLeading(nscoord &aLeading)
+nscoord
+nsFontMetrics::ExternalLeading()
 {
-    aLeading = ROUND_TO_TWIPS(GetMetrics().internalLeading);
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().externalLeading);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetExternalLeading(nscoord &aLeading)
+nscoord
+nsFontMetrics::EmHeight()
 {
-    aLeading = ROUND_TO_TWIPS(GetMetrics().externalLeading);
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().emHeight);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetEmHeight(nscoord &aHeight)
+nscoord
+nsFontMetrics::EmAscent()
 {
-    aHeight = ROUND_TO_TWIPS(GetMetrics().emHeight);
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().emAscent);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetEmAscent(nscoord &aAscent)
+nscoord
+nsFontMetrics::EmDescent()
 {
-    aAscent = ROUND_TO_TWIPS(GetMetrics().emAscent);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsThebesFontMetrics::GetEmDescent(nscoord &aDescent)
-{
-    aDescent = ROUND_TO_TWIPS(GetMetrics().emDescent);
-    return NS_OK;
+    return ROUND_TO_TWIPS(GetMetrics().emDescent);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetMaxHeight(nscoord &aHeight)
+nscoord
+nsFontMetrics::MaxHeight()
 {
-    aHeight = CEIL_TO_TWIPS(ComputeMaxAscent(GetMetrics())) +
+    return CEIL_TO_TWIPS(ComputeMaxAscent(GetMetrics())) +
         CEIL_TO_TWIPS(ComputeMaxDescent(GetMetrics(), mFontGroup));
-    return NS_OK;
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetMaxAscent(nscoord &aAscent)
+nscoord
+nsFontMetrics::MaxAscent()
 {
-    aAscent = CEIL_TO_TWIPS(ComputeMaxAscent(GetMetrics()));
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsThebesFontMetrics::GetMaxDescent(nscoord &aDescent)
-{
-    aDescent = CEIL_TO_TWIPS(ComputeMaxDescent(GetMetrics(), mFontGroup));
-    return NS_OK;
+    return CEIL_TO_TWIPS(ComputeMaxAscent(GetMetrics()));
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetMaxAdvance(nscoord &aAdvance)
+nscoord
+nsFontMetrics::MaxDescent()
 {
-    aAdvance = CEIL_TO_TWIPS(GetMetrics().maxAdvance);
-    return NS_OK;
+    return CEIL_TO_TWIPS(ComputeMaxDescent(GetMetrics(), mFontGroup));
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetLanguage(nsIAtom** aLanguage)
+nscoord
+nsFontMetrics::MaxAdvance()
 {
-    *aLanguage = mLanguage;
-    NS_IF_ADDREF(*aLanguage);
-    return NS_OK;
+    return CEIL_TO_TWIPS(GetMetrics().maxAdvance);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetFontHandle(nsFontHandle &aHandle)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsThebesFontMetrics::GetAveCharWidth(nscoord& aAveCharWidth)
+nscoord
+nsFontMetrics::AveCharWidth()
 {
     // Use CEIL instead of ROUND for consistency with GetMaxAdvance
-    aAveCharWidth = CEIL_TO_TWIPS(GetMetrics().aveCharWidth);
-    return NS_OK;
+    return CEIL_TO_TWIPS(GetMetrics().aveCharWidth);
 }
 
-NS_IMETHODIMP
-nsThebesFontMetrics::GetSpaceWidth(nscoord& aSpaceCharWidth)
+nscoord
+nsFontMetrics::SpaceWidth()
 {
-    aSpaceCharWidth = CEIL_TO_TWIPS(GetMetrics().spaceWidth);
-    return NS_OK;
+    return CEIL_TO_TWIPS(GetMetrics().spaceWidth);
 }
 
 PRInt32
-nsThebesFontMetrics::GetMaxStringLength()
+nsFontMetrics::GetMaxStringLength()
 {
     const gfxFont::Metrics& m = GetMetrics();
     const double x = 32767.0 / m.maxAdvance;
     PRInt32 len = (PRInt32)floor(x);
     return PR_MAX(1, len);
 }
 
-class StubPropertyProvider : public gfxTextRun::PropertyProvider {
-public:
-    virtual void GetHyphenationBreaks(PRUint32 aStart, PRUint32 aLength,
-                                      PRPackedBool* aBreakBefore) {
-        NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
-    }
-    virtual gfxFloat GetHyphenWidth() {
-        NS_ERROR("This shouldn't be called because we never enable hyphens");
+nscoord
+nsFontMetrics::GetWidth(const char* aString, PRUint32 aLength,
+                        nsRenderingContext *aContext)
+{
+    if (aLength == 0)
         return 0;
-    }
-    virtual void GetSpacing(PRUint32 aStart, PRUint32 aLength,
-                            Spacing* aSpacing) {
-        NS_ERROR("This shouldn't be called because we never enable spacing");
-    }
-};
-
-nsresult 
-nsThebesFontMetrics::GetWidth(const char* aString, PRUint32 aLength, nscoord& aWidth,
-                              nsRenderingContext *aContext)
-{
-    if (aLength == 0) {
-        aWidth = 0;
-        return NS_OK;
-    }
 
-    // callers that hit this should not be so stupid
-    if ((aLength == 1) && (aString[0] == ' '))
-        return GetSpaceWidth(aWidth);
-
-    StubPropertyProvider provider;
-    AutoTextRun textRun(this, aContext, aString, aLength);
-    if (!textRun.get())
-        return NS_ERROR_FAILURE;
-
-    aWidth = NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider));
-
-    return NS_OK;
-}
-
-nsresult
-nsThebesFontMetrics::GetWidth(const PRUnichar* aString, PRUint32 aLength,
-                              nscoord& aWidth, PRInt32 *aFontID,
-                              nsRenderingContext *aContext)
-{
-    if (aLength == 0) {
-        aWidth = 0;
-        return NS_OK;
-    }
-
-    // callers that hit this should not be so stupid
-    if ((aLength == 1) && (aString[0] == ' '))
-        return GetSpaceWidth(aWidth);
+    if (aLength == 1 && aString[0] == ' ')
+        return SpaceWidth();
 
     StubPropertyProvider provider;
     AutoTextRun textRun(this, aContext, aString, aLength);
-    if (!textRun.get())
-        return NS_ERROR_FAILURE;
-
-    aWidth = NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider));
-
-    return NS_OK;
-}
-
-// Get the text dimensions for this string
-nsresult
-nsThebesFontMetrics::GetTextDimensions(const PRUnichar* aString,
-                                    PRUint32 aLength,
-                                    nsTextDimensions& aDimensions, 
-                                    PRInt32* aFontID)
-{
-    return NS_OK;
+    return NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider));
 }
 
-nsresult
-nsThebesFontMetrics::GetTextDimensions(const char*         aString,
-                                   PRInt32             aLength,
-                                   PRInt32             aAvailWidth,
-                                   PRInt32*            aBreaks,
-                                   PRInt32             aNumBreaks,
-                                   nsTextDimensions&   aDimensions,
-                                   PRInt32&            aNumCharsFit,
-                                   nsTextDimensions&   aLastWordDimensions,
-                                   PRInt32*            aFontID)
+nscoord
+nsFontMetrics::GetWidth(const PRUnichar* aString, PRUint32 aLength,
+                        nsRenderingContext *aContext)
 {
-    return NS_OK;
-}
-nsresult
-nsThebesFontMetrics::GetTextDimensions(const PRUnichar*    aString,
-                                   PRInt32             aLength,
-                                   PRInt32             aAvailWidth,
-                                   PRInt32*            aBreaks,
-                                   PRInt32             aNumBreaks,
-                                   nsTextDimensions&   aDimensions,
-                                   PRInt32&            aNumCharsFit,
-                                   nsTextDimensions&   aLastWordDimensions,
-                                   PRInt32*            aFontID)
-{
-    return NS_OK;
+    if (aLength == 0)
+        return 0;
+
+    if (aLength == 1 && aString[0] == ' ')
+        return SpaceWidth();
+
+    StubPropertyProvider provider;
+    AutoTextRun textRun(this, aContext, aString, aLength);
+    return NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider));
 }
 
-// Draw a string using this font handle on the surface passed in.  
-nsresult
-nsThebesFontMetrics::DrawString(const char *aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                const nscoord* aSpacing,
-                                nsRenderingContext *aContext)
+// Draw a string using this font handle on the surface passed in.
+void
+nsFontMetrics::DrawString(const char *aString, PRUint32 aLength,
+                          nscoord aX, nscoord aY,
+                          nsRenderingContext *aContext)
 {
     if (aLength == 0)
-        return NS_OK;
+        return;
 
-    NS_ASSERTION(!aSpacing, "Spacing not supported here");
     StubPropertyProvider provider;
     AutoTextRun textRun(this, aContext, aString, aLength);
-    if (!textRun.get())
-        return NS_ERROR_FAILURE;
     gfxPoint pt(aX, aY);
     if (mTextRunRTL) {
         pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
     }
-    textRun->Draw(aContext->ThebesContext(), pt, 0, aLength,
-                  &provider, nsnull);
-    return NS_OK;
+    textRun->Draw(aContext->ThebesContext(), pt, 0, aLength, &provider, nsnull);
 }
 
-nsresult
-nsThebesFontMetrics::DrawString(const PRUnichar* aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                nsRenderingContext *aContext,
-                                nsRenderingContext *aTextRunConstructionContext)
+void
+nsFontMetrics::DrawString(const PRUnichar* aString, PRUint32 aLength,
+                          nscoord aX, nscoord aY,
+                          nsRenderingContext *aContext,
+                          nsRenderingContext *aTextRunConstructionContext)
 {
     if (aLength == 0)
-        return NS_OK;
+        return;
 
     StubPropertyProvider provider;
     AutoTextRun textRun(this, aTextRunConstructionContext, aString, aLength);
-    if (!textRun.get())
-        return NS_ERROR_FAILURE;
     gfxPoint pt(aX, aY);
     if (mTextRunRTL) {
         pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
     }
-    textRun->Draw(aContext->ThebesContext(), pt, 0, aLength,
-                  &provider, nsnull);
-    return NS_OK;
+    textRun->Draw(aContext->ThebesContext(), pt, 0, aLength, &provider, nsnull);
 }
 
 #ifdef MOZ_MATHML
-
-static void
-GetTextRunBoundingMetrics(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aLength,
-                          nsRenderingContext *aContext,
-                          nsBoundingMetrics &aBoundingMetrics)
+nsBoundingMetrics
+nsFontMetrics::GetBoundingMetrics(const PRUnichar *aString, PRUint32 aLength,
+                                  nsRenderingContext *aContext)
 {
-    StubPropertyProvider provider;
-    gfxTextRun::Metrics theMetrics =
-        aTextRun->MeasureText(aStart, aLength, gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS,
-                              aContext->ThebesContext(), &provider);
-        // note that TIGHT_HINTED_OUTLINE_EXTENTS can be expensive (on Windows)
-        // but this is only used for MathML positioning so it's not critical
-
-    aBoundingMetrics.leftBearing = NSToCoordFloor(theMetrics.mBoundingBox.X());
-    aBoundingMetrics.rightBearing = NSToCoordCeil(theMetrics.mBoundingBox.XMost());
-    aBoundingMetrics.width = NSToCoordRound(theMetrics.mAdvanceWidth);
-    aBoundingMetrics.ascent = NSToCoordCeil(- theMetrics.mBoundingBox.Y());
-    aBoundingMetrics.descent = NSToCoordCeil(theMetrics.mBoundingBox.YMost());
-}
-
-nsresult
-nsThebesFontMetrics::GetBoundingMetrics(const char *aString, PRUint32 aLength,
-                                        nsRenderingContext *aContext,
-                                        nsBoundingMetrics &aBoundingMetrics)
-{
-    if (aLength == 0) {
-        aBoundingMetrics = nsBoundingMetrics();
-        return NS_OK;
-    }
-
-    AutoTextRun textRun(this, aContext, aString, aLength);
-    if (!textRun.get())
-        return NS_ERROR_FAILURE;
-
-    GetTextRunBoundingMetrics(textRun.get(), 0, aLength, aContext, aBoundingMetrics);
-    return NS_OK;
-}
+    if (aLength == 0)
+        return nsBoundingMetrics();
 
-nsresult
-nsThebesFontMetrics::GetBoundingMetrics(const PRUnichar *aString, PRUint32 aLength,
-                                        nsRenderingContext *aContext,
-                                        nsBoundingMetrics &aBoundingMetrics)
-{
-    if (aLength == 0) {
-        aBoundingMetrics = nsBoundingMetrics();
-        return NS_OK;
-    }
-
+    StubPropertyProvider provider;
     AutoTextRun textRun(this, aContext, aString, aLength);
-    if (!textRun.get())
-        return NS_ERROR_FAILURE;
-
-    GetTextRunBoundingMetrics(textRun.get(), 0, aLength, aContext, aBoundingMetrics);
-    return NS_OK;
-}
-
-#endif /* MOZ_MATHML */
+    gfxTextRun::Metrics theMetrics =
+        textRun->MeasureText(0, aLength,
+                             gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS,
+                             aContext->ThebesContext(), &provider);
 
-// Set the direction of the text rendering
-nsresult
-nsThebesFontMetrics::SetRightToLeftText(PRBool aIsRTL)
-{
-    mIsRightToLeft = aIsRTL;
-    return NS_OK;
+    nsBoundingMetrics m;
+    m.leftBearing  = NSToCoordFloor( theMetrics.mBoundingBox.X());
+    m.rightBearing = NSToCoordCeil(  theMetrics.mBoundingBox.XMost());
+    m.ascent       = NSToCoordCeil( -theMetrics.mBoundingBox.Y());
+    m.descent      = NSToCoordCeil(  theMetrics.mBoundingBox.YMost());
+    m.width        = NSToCoordRound( theMetrics.mAdvanceWidth);
+    return m;
 }
-
-// Set the direction of the text rendering
-PRBool
-nsThebesFontMetrics::GetRightToLeftText()
-{
-    return mIsRightToLeft;
-}
-
-/* virtual */ gfxUserFontSet*
-nsThebesFontMetrics::GetUserFontSet()
-{
-    return mFontGroup->GetUserFontSet();
-}
+#endif /* MOZ_MATHML */
rename from gfx/src/nsThebesFontMetrics.h
rename to gfx/src/nsFontMetrics.h
--- a/gfx/src/nsThebesFontMetrics.h
+++ b/gfx/src/nsFontMetrics.h
@@ -31,179 +31,216 @@
  * 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 NSTHEBESFONTMETRICS__H__
-#define NSTHEBESFONTMETRICS__H__
+#ifndef NSFONTMETRICS__H__
+#define NSFONTMETRICS__H__
 
-#include "nsIThebesFontMetrics.h"
 #include "nsCOMPtr.h"
-#include "nsRenderingContext.h"
+#include "nsCoord.h"
+#include "nsFont.h"
 #include "gfxFont.h"
-#include "gfxTextRunCache.h"
 
 class nsIAtom;
 class nsIDeviceContext;
+class nsRenderingContext;
 class nsThebesDeviceContext;
+struct nsBoundingMetrics;
 
-class nsThebesFontMetrics : public nsIThebesFontMetrics
+/**
+ * Font metrics
+ *
+ * This class may be somewhat misnamed. A better name might be
+ * nsFontList. The style system uses the nsFont struct for various
+ * font properties, one of which is font-family, which can contain a
+ * *list* of font names. The nsFont struct is "realized" by asking the
+ * device context to cough up an nsFontMetrics object, which contains
+ * a list of real font handles, one for each font mentioned in
+ * font-family (and for each fallback when we fall off the end of that
+ * list).
+ *
+ * The style system needs to have access to certain metrics, such as
+ * the em height (for the CSS "em" unit), and we use the first Western
+ * font's metrics for that purpose. The platform-specific
+ * implementations are expected to select non-Western fonts that "fit"
+ * reasonably well with the Western font that is loaded at Init time.
+ */
+class nsFontMetrics
 {
 public:
-    nsThebesFontMetrics();
-    virtual ~nsThebesFontMetrics();
+    nsFontMetrics();
+    ~nsFontMetrics();
+
+    NS_INLINE_DECL_REFCOUNTING(nsFontMetrics)
+
+    /**
+     * Initialize the font metrics. Call this after creating the font metrics.
+     * Font metrics you get from the font cache do NOT need to be initialized
+     *
+     * @see nsIDeviceContext#GetMetricsFor()
+     */
+    nsresult Init(const nsFont& aFont, nsIAtom* aLanguage,
+                  nsIDeviceContext *aContext,
+                  gfxUserFontSet *aUserFontSet = nsnull);
 
-    NS_DECL_ISUPPORTS
+    /**
+     * Destroy this font metrics. This breaks the association between
+     * the font metrics and the device context.
+     */
+    void Destroy();
+
+    /**
+     * Return the font's x-height.
+     */
+    nscoord XHeight();
+
+    /**
+     * Return the font's superscript offset (the distance from the
+     * baseline to where a superscript's baseline should be placed).
+     * The value returned will be positive.
+     */
+    nscoord SuperscriptOffset();
 
-    NS_IMETHOD  Init(const nsFont& aFont, nsIAtom* aLanguage,
-                     nsIDeviceContext *aContext,
-                     gfxUserFontSet *aUserFontSet = nsnull);
-    NS_IMETHOD  Destroy();
-    NS_IMETHOD  GetXHeight(nscoord& aResult);
-    NS_IMETHOD  GetSuperscriptOffset(nscoord& aResult);
-    NS_IMETHOD  GetSubscriptOffset(nscoord& aResult);
-    NS_IMETHOD  GetStrikeout(nscoord& aOffset, nscoord& aSize);
-    NS_IMETHOD  GetUnderline(nscoord& aOffset, nscoord& aSize);
-    NS_IMETHOD  GetHeight(nscoord &aHeight);
-    NS_IMETHOD  GetInternalLeading(nscoord &aLeading);
-    NS_IMETHOD  GetExternalLeading(nscoord &aLeading);
-    NS_IMETHOD  GetEmHeight(nscoord &aHeight);
-    NS_IMETHOD  GetEmAscent(nscoord &aAscent);
-    NS_IMETHOD  GetEmDescent(nscoord &aDescent);
-    NS_IMETHOD  GetMaxHeight(nscoord &aHeight);
-    NS_IMETHOD  GetMaxAscent(nscoord &aAscent);
-    NS_IMETHOD  GetMaxDescent(nscoord &aDescent);
-    NS_IMETHOD  GetMaxAdvance(nscoord &aAdvance);
-    NS_IMETHOD  GetLanguage(nsIAtom** aLanguage);
-    NS_IMETHOD  GetFontHandle(nsFontHandle &aHandle);
-    NS_IMETHOD  GetAveCharWidth(nscoord& aAveCharWidth);
-    NS_IMETHOD  GetSpaceWidth(nscoord& aSpaceCharWidth);
-    virtual PRInt32 GetMaxStringLength();
+    /**
+     * Return the font's subscript offset (the distance from the
+     * baseline to where a subscript's baseline should be placed).
+     * The value returned will be positive.
+     */
+    nscoord SubscriptOffset();
+
+    /**
+     * Return the font's strikeout offset (the distance from the
+     * baseline to where a strikeout should be placed) and size.
+     * Positive values are above the baseline, negative below.
+     */
+    void GetStrikeout(nscoord& aOffset, nscoord& aSize);
 
+    /**
+     * Return the font's underline offset (the distance from the
+     * baseline to where a underline should be placed) and size.
+     * Positive values are above the baseline, negative below.
+     */
+    void GetUnderline(nscoord& aOffset, nscoord& aSize);
 
-    virtual nsresult GetWidth(const char* aString, PRUint32 aLength, nscoord& aWidth,
-                              nsRenderingContext *aContext);
-    virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
-                              nscoord& aWidth, PRInt32 *aFontID,
-                              nsRenderingContext *aContext);
+    /**
+     * Returns the amount of internal leading for the font.
+     * This is normally the difference between the max ascent
+     * and the em ascent.
+     */
+    nscoord InternalLeading();
+
+    /**
+     * Returns the amount of external leading for the font.
+     * em ascent(?) plus external leading is the font designer's
+     * recommended line-height for this font.
+     */
+    nscoord ExternalLeading();
 
-    // Get the text dimensions for this string
-    virtual nsresult GetTextDimensions(const PRUnichar* aString,
-                                       PRUint32 aLength,
-                                       nsTextDimensions& aDimensions, 
-                                       PRInt32* aFontID);
-    virtual nsresult GetTextDimensions(const char*         aString,
-                                       PRInt32             aLength,
-                                       PRInt32             aAvailWidth,
-                                       PRInt32*            aBreaks,
-                                       PRInt32             aNumBreaks,
-                                       nsTextDimensions&   aDimensions,
-                                       PRInt32&            aNumCharsFit,
-                                       nsTextDimensions&   aLastWordDimensions,
-                                       PRInt32*            aFontID);
-    virtual nsresult GetTextDimensions(const PRUnichar*    aString,
-                                       PRInt32             aLength,
-                                       PRInt32             aAvailWidth,
-                                       PRInt32*            aBreaks,
-                                       PRInt32             aNumBreaks,
-                                       nsTextDimensions&   aDimensions,
-                                       PRInt32&            aNumCharsFit,
-                                       nsTextDimensions&   aLastWordDimensions,
-                                       PRInt32*            aFontID);
+    /**
+     * Returns the height of the em square.
+     * This is em ascent plus em descent.
+     */
+    nscoord EmHeight();
+
+    /**
+     * Returns the ascent part of the em square.
+     */
+    nscoord EmAscent();
+
+    /**
+     * Returns the descent part of the em square.
+     */
+    nscoord EmDescent();
+
+    /**
+     * Returns the height of the bounding box.
+     * This is max ascent plus max descent.
+     */
+    nscoord MaxHeight();
+
+    /**
+     * Returns the maximum distance characters in this font extend
+     * above the base line.
+     */
+    nscoord MaxAscent();
+
+    /**
+     * Returns the maximum distance characters in this font extend
+     * below the base line.
+     */
+    nscoord MaxDescent();
+
+    /**
+     * Returns the maximum character advance for the font.
+     */
+    nscoord MaxAdvance();
 
-    // Draw a string using this font handle on the surface passed in.  
-    virtual nsresult DrawString(const char *aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                const nscoord* aSpacing,
-                                nsRenderingContext *aContext);
-    virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                PRInt32 aFontID,
-                                const nscoord* aSpacing,
-                                nsRenderingContext *aContext)
-    {
-      NS_ASSERTION(!aSpacing, "Spacing not supported here");
-      return DrawString(aString, aLength, aX, aY, aContext, aContext);
-    }
-    virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                nsRenderingContext *aContext,
-                                nsRenderingContext *aTextRunConstructionContext);
+    /**
+     * Returns the average character width
+     */
+    nscoord AveCharWidth();
+
+    /**
+     * Returns the often needed width of the space character
+     */
+    nscoord SpaceWidth();
+
+    /**
+     * Returns the font associated with these metrics. The return value
+     * is only defined after Init() has been called.
+     */
+    const nsFont &Font() { return mFont; }
+
+    /**
+     * Returns the language associated with these metrics
+     */
+    nsIAtom* Language() { return mLanguage; }
+
+    PRInt32 GetMaxStringLength();
+
+    // Get the width for this string.  aWidth will be updated with the
+    // width in points, not twips.  Callers must convert it if they
+    // want it in another format.
+    nscoord GetWidth(const char* aString, PRUint32 aLength,
+                     nsRenderingContext *aContext);
+    nscoord GetWidth(const PRUnichar* aString, PRUint32 aLength,
+                     nsRenderingContext *aContext);
+
+    // Draw a string using this font handle on the surface passed in.
+    void DrawString(const char *aString, PRUint32 aLength,
+                    nscoord aX, nscoord aY,
+                    nsRenderingContext *aContext);
+    void DrawString(const PRUnichar* aString, PRUint32 aLength,
+                    nscoord aX, nscoord aY,
+                    nsRenderingContext *aContext,
+                    nsRenderingContext *aTextRunConstructionContext);
 
 #ifdef MOZ_MATHML
-    // These two functions get the bounding metrics for this handle,
-    // updating the aBoundingMetrics in app units.
-    virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
-                                        nsRenderingContext *aContext,
-                                        nsBoundingMetrics &aBoundingMetrics);
-    virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
-                                        PRUint32 aLength,
-                                        nsRenderingContext *aContext,
-                                        nsBoundingMetrics &aBoundingMetrics);
+    nsBoundingMetrics GetBoundingMetrics(const PRUnichar *aString,
+                                         PRUint32 aLength,
+                                         nsRenderingContext *aContext);
 #endif /* MOZ_MATHML */
 
-    // Set the direction of the text rendering
-    virtual nsresult SetRightToLeftText(PRBool aIsRTL);
-    virtual PRBool GetRightToLeftText();
-    virtual void SetTextRunRTL(PRBool aIsRTL) { mTextRunRTL = aIsRTL; }
+    void SetTextRunRTL(PRBool aIsRTL) { mTextRunRTL = aIsRTL; }
+    PRBool GetTextRunRTL() { return mTextRunRTL; }
 
-    virtual gfxFontGroup* GetThebesFontGroup() { return mFontGroup; }
+    gfxFontGroup* GetThebesFontGroup() { return mFontGroup; }
+    gfxUserFontSet* GetUserFontSet() { return mFontGroup->GetUserFontSet(); }
 
-    virtual gfxUserFontSet* GetUserFontSet();
-    
-    PRBool GetRightToLeftTextRunMode() {
-        return mTextRunRTL;
-    }
+    PRInt32 AppUnitsPerDevPixel() { return mP2A; }
 
 protected:
-
     const gfxFont::Metrics& GetMetrics() const;
 
-    class AutoTextRun {
-    public:
-        AutoTextRun(nsThebesFontMetrics* aMetrics, nsRenderingContext* aRC,
-                    const char* aString, PRInt32 aLength) {
-            mTextRun = gfxTextRunCache::MakeTextRun(
-                reinterpret_cast<const PRUint8*>(aString), aLength,
-                aMetrics->mFontGroup, aRC->ThebesContext(),
-                aMetrics->mP2A,
-                ComputeFlags(aMetrics));
-        }
-        AutoTextRun(nsThebesFontMetrics* aMetrics, nsRenderingContext* aRC,
-                    const PRUnichar* aString, PRInt32 aLength) {
-            mTextRun = gfxTextRunCache::MakeTextRun(
-                aString, aLength, aMetrics->mFontGroup,
-                aRC->ThebesContext(),
-                aMetrics->mP2A,
-                ComputeFlags(aMetrics));
-        }
-        gfxTextRun* operator->() { return mTextRun.get(); }
-        gfxTextRun* get() { return mTextRun.get(); }
-
-    private:
-        gfxTextRunCache::AutoTextRun mTextRun;
-        
-        static PRUint32 ComputeFlags(nsThebesFontMetrics* aMetrics) {
-            PRUint32 flags = 0;
-            if (aMetrics->GetRightToLeftTextRunMode()) {
-                flags |= gfxTextRunFactory::TEXT_IS_RTL;
-            }
-            return flags;
-        }
-    };
-    friend class AutoTextRun;
-
+    nsFont mFont;
     nsRefPtr<gfxFontGroup> mFontGroup;
-    gfxFontStyle *mFontStyle;
-
-private:
+    nsCOMPtr<nsIAtom> mLanguage;
     nsThebesDeviceContext *mDeviceContext;
-    nsCOMPtr<nsIAtom> mLanguage;
     PRInt32 mP2A;
-    PRPackedBool mIsRightToLeft;
     PRPackedBool mTextRunRTL;
 };
 
-#endif /* NSTHEBESFONTMETRICS__H__ */
+#endif /* NSFONTMETRICS__H__ */
--- a/gfx/src/nsGfxCIID.h
+++ b/gfx/src/nsGfxCIID.h
@@ -45,20 +45,16 @@
 #define NS_IMAGE_CID \
 { 0x6049b260, 0xc1e6, 0x11d1, \
 { 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
 
 #define NS_DEVICE_CONTEXT_CID \
 { 0x6049b262, 0xc1e6, 0x11d1, \
 { 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
 
-#define NS_FONT_METRICS_CID \
-{ 0x6049b263, 0xc1e6, 0x11d1, \
-{ 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
-
 #define NS_FONT_ENUMERATOR_CID \
 { 0xa6cf9115, 0x15b3, 0x11d2, \
 { 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } }
 
 #define NS_REGION_CID \
 { 0xe12752f0, 0xee9a, 0x11d1, \
 { 0xa8, 0x2a, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
 
--- a/gfx/src/nsIDeviceContext.h
+++ b/gfx/src/nsIDeviceContext.h
@@ -41,17 +41,17 @@
 
 #include "nsISupports.h"
 #include "nsCoord.h"
 #include "nsRect.h"
 #include "gfxTypes.h"
 #include "nsStringFwd.h"
 
 class nsIView;
-class nsIFontMetrics;
+class nsFontMetrics;
 class nsIWidget;
 class nsIDeviceContextSpec;
 class nsIAtom;
 class gfxUserFontSet;
 class nsRenderingContext;
 
 struct nsFont;
 
@@ -304,55 +304,55 @@ public:
    *
    * @param aID    The system font ID.
    * @param aInfo  The font structure to be filled in.
    * @return error status
    */
   NS_IMETHOD  GetSystemFont(nsSystemFontID aID, nsFont *aFont) const = 0;
 
   /**
-   * Get the nsIFontMetrics that describe the properties of
+   * Get the nsFontMetrics that describe the properties of
    * an nsFont.
    * @param aFont font description to obtain metrics for
    * @param aLanguage the language of the document
    * @param aMetrics out parameter for font metrics
    * @param aUserFontSet user font set
    * @return error status
    */
   NS_IMETHOD  GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
                             gfxUserFontSet* aUserFontSet,
-                            nsIFontMetrics*& aMetrics) = 0;
+                            nsFontMetrics*& aMetrics) = 0;
 
   /**
-   * Get the nsIFontMetrics that describe the properties of
+   * Get the nsFontMetrics that describe the properties of
    * an nsFont.
    * @param aFont font description to obtain metrics for
    * @param aMetrics out parameter for font metrics
    * @param aUserFontSet user font set
    * @return error status
    */
   NS_IMETHOD  GetMetricsFor(const nsFont& aFont, gfxUserFontSet* aUserFontSet,
-                            nsIFontMetrics*& aMetrics) = 0;
+                            nsFontMetrics*& aMetrics) = 0;
 
   /**
    * Check to see if a particular named font exists.
    * @param aFontName character string of font face name
    * @return NS_OK if font is available, else font is unavailable
    */
   NS_IMETHOD CheckFontExistence(const nsString& aFaceName) = 0;
   NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName) = 0;
 
   NS_IMETHOD GetLocalFontName(const nsString& aFaceName, nsString& aLocalName,
                               PRBool& aAliased) = 0;
 
   /**
    * Notification when a font metrics instance created for this device is
    * about to be deleted
    */
-  NS_IMETHOD FontMetricsDeleted(const nsIFontMetrics* aFontMetrics) = 0;
+  NS_IMETHOD FontMetricsDeleted(const nsFontMetrics* aFontMetrics) = 0;
 
   /**
    * Attempt to free up resoruces by flushing out any fonts no longer
    * referenced by anything other than the font cache itself.
    * @return error status
    */
   NS_IMETHOD FlushFontCache(void) = 0;
 
deleted file mode 100644
--- a/gfx/src/nsIFontMetrics.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* -*- 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 mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * 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 nsIFontMetrics_h___
-#define nsIFontMetrics_h___
-
-#include "nsISupports.h"
-#include "nsCoord.h"
-#include "nsFont.h"
-
-class nsString;
-class nsIDeviceContext;
-class nsIAtom;
-class gfxUserFontSet;
-
-// IID for the nsIFontMetrics interface
-#define NS_IFONT_METRICS_IID   \
-{ 0x360C5575, 0xF7AC, 0x4079, \
-{ 0xB8, 0xA6, 0x56, 0x91, 0x4B, 0xEA, 0x2A, 0xEA } }
-
-//----------------------------------------------------------------------
-
-/**
- * A native font handle
- */
-typedef void* nsFontHandle;
-
-/**
- * Font metrics interface
- *
- * This interface may be somewhat misnamed. A better name might be
- * nsIFontList. The style system uses the nsFont struct for various font
- * properties, one of which is font-family, which can contain a *list* of
- * font names. The nsFont struct is "realized" by asking the device context
- * to cough up an nsIFontMetrics object, which contains a list of real font
- * handles, one for each font mentioned in font-family (and for each fallback
- * when we fall off the end of that list).
- *
- * The style system needs to have access to certain metrics, such as the
- * em height (for the CSS "em" unit), and we use the first Western font's
- * metrics for that purpose. The platform-specific implementations are
- * expected to select non-Western fonts that "fit" reasonably well with the
- * Western font that is loaded at Init time.
- */
-class nsIFontMetrics : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFONT_METRICS_IID)
-
-  /**
-   * Initialize the font metrics. Call this after creating the font metrics.
-   * Font metrics you get from the font cache do NOT need to be initialized
-   *
-   * @see nsIDeviceContext#GetMetricsFor()
-   */
-  NS_IMETHOD  Init(const nsFont& aFont, nsIAtom* aLanguage,
-                   nsIDeviceContext *aContext, gfxUserFontSet *aUserFontSet = nsnull) = 0;
-
-  /**
-   * Destroy this font metrics. This breaks the association between
-   * the font metrics and the device context.
-   */
-  NS_IMETHOD  Destroy() = 0;
-
-  /**
-   * Return the font's xheight property, scaled into app-units.
-   */
-  NS_IMETHOD  GetXHeight(nscoord& aResult) = 0;
-
-  /**
-   * Return the font's superscript offset (the distance from the
-   * baseline to where a superscript's baseline should be placed). The
-   * value returned will be a positive value.
-   */
-  NS_IMETHOD  GetSuperscriptOffset(nscoord& aResult) = 0;
-
-  /**
-   * Return the font's subscript offset (the distance from the
-   * baseline to where a subscript's baseline should be placed). The
-   * value returned will be a positive value.
-   */
-  NS_IMETHOD  GetSubscriptOffset(nscoord& aResult) = 0;
-
-  /**
-   * Return the font's strikeout offset (the distance from the 
-   * baseline to where a strikeout should be placed) and size
-   * Positive values are above the baseline, negative below.
-   */
-  NS_IMETHOD  GetStrikeout(nscoord& aOffset, nscoord& aSize) = 0;
-
-  /**
-   * Return the font's underline offset (the distance from the 
-   * baseline to where a underline should be placed) and size.
-   * Positive values are above the baseline, negative below.
-   */
-  NS_IMETHOD  GetUnderline(nscoord& aOffset, nscoord& aSize) = 0;
-
-  /**
-   * Returns the height (in app units) of the font. This is ascent plus descent
-   * plus any internal leading
-   *
-   * This method will be removed once the callers have been moved over to the
-   * new GetEmHeight (and possibly GetMaxHeight).
-   */
-  NS_IMETHOD  GetHeight(nscoord &aHeight) = 0;
-
-  /**
-   * Returns the amount of internal leading (in app units) for the font. This
-   * is computed as the "height  - (ascent + descent)"
-   */
-  NS_IMETHOD  GetInternalLeading(nscoord &aLeading) = 0;
-
-  /**
-   * Returns the amount of external leading (in app units) as suggested by font
-   * vendor. This value is suggested by font vendor to add to normal line-height 
-   * beside font height.
-   */
-  NS_IMETHOD  GetExternalLeading(nscoord &aLeading) = 0;
-
-  /**
-   * Returns the height (in app units) of the Western font's em square. This is
-   * em ascent plus em descent.
-   */
-  NS_IMETHOD  GetEmHeight(nscoord &aHeight) = 0;
-
-  /**
-   * Returns, in app units, the ascent part of the Western font's em square.
-   */
-  NS_IMETHOD  GetEmAscent(nscoord &aAscent) = 0;
-
-  /**
-   * Returns, in app units, the descent part of the Western font's em square.
-   */
-  NS_IMETHOD  GetEmDescent(nscoord &aDescent) = 0;
-
-  /**
-   * Returns the height (in app units) of the Western font's bounding box.
-   * This is max ascent plus max descent.
-   */
-  NS_IMETHOD  GetMaxHeight(nscoord &aHeight) = 0;
-
-  /**
-   * Returns, in app units, the maximum distance characters in this font extend
-   * above the base line.
-   */
-  NS_IMETHOD  GetMaxAscent(nscoord &aAscent) = 0;
-
-  /**
-   * Returns, in app units, the maximum distance characters in this font extend
-   * below the base line.
-   */
-  NS_IMETHOD  GetMaxDescent(nscoord &aDescent) = 0;
-
-  /**
-   * Returns, in app units, the maximum character advance for the font
-   */
-  NS_IMETHOD  GetMaxAdvance(nscoord &aAdvance) = 0;
-
-  /**
-   * Returns the font associated with these metrics. The return value
-   * is only defined after Init() has been called.
-   */
-  const nsFont &Font() { return mFont; }
-
-  /**
-   * Returns the language associated with these metrics
-   */
-  NS_IMETHOD  GetLanguage(nsIAtom** aLanguage) = 0;
-
-  /**
-   * Returns the font handle associated with these metrics
-   */
-  NS_IMETHOD  GetFontHandle(nsFontHandle &aHandle) = 0;
-
-  /**
-   * Returns the average character width
-   */
-  NS_IMETHOD  GetAveCharWidth(nscoord& aAveCharWidth) = 0;
-
-  /**
-   * Returns the often needed width of the space character
-   */
-  NS_IMETHOD  GetSpaceWidth(nscoord& aSpaceCharWidth) = 0;
-
-protected:
-
-  nsFont mFont;		// The font for this metrics object.
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIFontMetrics, NS_IFONT_METRICS_IID)
-
-#endif /* nsIFontMetrics_h___ */
deleted file mode 100644
--- a/gfx/src/nsIThebesFontMetrics.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** 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 mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Christopher Blizzard <blizzard@mozilla.org>.  
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 __nsIThebesFontMetrics_h
-#define __nsIThebesFontMetrics_h
-
-#include "nsIFontMetrics.h"
-
-struct nsTextDimensions;
-struct nsBoundingMetrics;
-class gfxFontGroup;
-class nsRenderingContext;
-
-class nsIThebesFontMetrics : public nsIFontMetrics {
-public:
-    // Get the width for this string.  aWidth will be updated with the
-    // width in points, not twips.  Callers must convert it if they
-    // want it in another format.
-    virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
-                              nscoord& aWidth, nsRenderingContext *aContext) = 0;
-    virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
-                              nscoord& aWidth, PRInt32 *aFontID,
-                              nsRenderingContext *aContext) = 0;
-
-    // Get the text dimensions for this string
-    virtual nsresult GetTextDimensions(const PRUnichar* aString,
-                                       PRUint32 aLength,
-                                       nsTextDimensions& aDimensions, 
-                                       PRInt32* aFontID) = 0;
-    virtual nsresult GetTextDimensions(const char*         aString,
-                                       PRInt32             aLength,
-                                       PRInt32             aAvailWidth,
-                                       PRInt32*            aBreaks,
-                                       PRInt32             aNumBreaks,
-                                       nsTextDimensions&   aDimensions,
-                                       PRInt32&            aNumCharsFit,
-                                       nsTextDimensions&   aLastWordDimensions,
-                                       PRInt32*            aFontID) = 0;
-    virtual nsresult GetTextDimensions(const PRUnichar*    aString,
-                                       PRInt32             aLength,
-                                       PRInt32             aAvailWidth,
-                                       PRInt32*            aBreaks,
-                                       PRInt32             aNumBreaks,
-                                       nsTextDimensions&   aDimensions,
-                                       PRInt32&            aNumCharsFit,
-                                       nsTextDimensions&   aLastWordDimensions,
-                                       PRInt32*            aFontID) = 0;
-
-    // Draw a string using this font handle on the surface passed in.  
-    virtual nsresult DrawString(const char *aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                const nscoord* aSpacing,
-                                nsRenderingContext *aContext) = 0;
-    virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                PRInt32 aFontID,
-                                const nscoord* aSpacing,
-                                nsRenderingContext *aContext) = 0;
-    virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
-                                nscoord aX, nscoord aY,
-                                nsRenderingContext *aContext,
-                                nsRenderingContext *aTextRunConstructionContext) = 0;
-
-#ifdef MOZ_MATHML
-    // These two functions get the bounding metrics for this handle,
-    // updating the aBoundingMetrics in Points.  This means that the
-    // caller will have to update them to twips before passing it
-    // back.
-    virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
-                                        nsRenderingContext *aContext,
-                                        nsBoundingMetrics &aBoundingMetrics) = 0;
-    // aCachedOffset will be updated with a new offset.
-    virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
-                                        PRUint32 aLength,
-                                        nsRenderingContext *aContext,
-                                        nsBoundingMetrics &aBoundingMetrics) = 0;
-#endif /* MOZ_MATHML */
-
-    // Set the direction of the text rendering
-    virtual nsresult SetRightToLeftText(PRBool aIsRTL) = 0;
-    virtual PRBool GetRightToLeftText() = 0;
-    virtual void SetTextRunRTL(PRBool aIsRTL) = 0;
-
-    virtual PRInt32 GetMaxStringLength() = 0;
-
-    virtual gfxFontGroup* GetThebesFontGroup() = 0;
-
-    // Needs to be virtual and at this level so that its caller in gkgfx can
-    // avoid linking against thebes.
-    virtual gfxUserFontSet* GetUserFontSet() = 0;
-};
-
-#endif /* __nsIThebesFontMetrics_h */
--- a/gfx/src/nsRenderingContext.cpp
+++ b/gfx/src/nsRenderingContext.cpp
@@ -444,68 +444,56 @@ nsRenderingContext::FillPolygon(const ns
     mThebes->Fill();
 }
 
 //
 // text
 //
 
 void
-nsRenderingContext::SetRightToLeftText(PRBool aIsRTL)
-{
-    mFontMetrics->SetRightToLeftText(aIsRTL);
-}
-
-void
 nsRenderingContext::SetTextRunRTL(PRBool aIsRTL)
 {
     mFontMetrics->SetTextRunRTL(aIsRTL);
 }
 
 void
 nsRenderingContext::SetFont(const nsFont& aFont, nsIAtom* aLanguage,
                             gfxUserFontSet *aUserFontSet)
 {
-    nsCOMPtr<nsIFontMetrics> newMetrics;
     mDeviceContext->GetMetricsFor(aFont, aLanguage, aUserFontSet,
-                                  *getter_AddRefs(newMetrics));
-    mFontMetrics = reinterpret_cast<nsIThebesFontMetrics*>(newMetrics.get());
+                                  *getter_AddRefs(mFontMetrics));
 }
 
 void
 nsRenderingContext::SetFont(const nsFont& aFont,
                             gfxUserFontSet *aUserFontSet)
 {
-    nsCOMPtr<nsIFontMetrics> newMetrics;
     mDeviceContext->GetMetricsFor(aFont, nsnull, aUserFontSet,
-                                  *getter_AddRefs(newMetrics));
-    mFontMetrics = reinterpret_cast<nsIThebesFontMetrics*>(newMetrics.get());
+                                  *getter_AddRefs(mFontMetrics));
 }
 
 void
-nsRenderingContext::SetFont(nsIFontMetrics *aFontMetrics)
+nsRenderingContext::SetFont(nsFontMetrics *aFontMetrics)
 {
-    mFontMetrics = static_cast<nsIThebesFontMetrics*>(aFontMetrics);
+    mFontMetrics = aFontMetrics;
 }
 
 PRInt32
 nsRenderingContext::GetMaxChunkLength()
 {
     if (!mFontMetrics)
         return 1;
     return PR_MIN(mFontMetrics->GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
 }
 
 nscoord
 nsRenderingContext::GetWidth(char aC)
 {
     if (aC == ' ' && mFontMetrics) {
-        nscoord width;
-        mFontMetrics->GetSpaceWidth(width);
-        return width;
+        return mFontMetrics->SpaceWidth();
     }
 
     return GetWidth(&aC, 1);
 }
 
 nscoord
 nsRenderingContext::GetWidth(PRUnichar aC)
 {
@@ -526,76 +514,76 @@ nsRenderingContext::GetWidth(const char*
 
 nscoord
 nsRenderingContext::GetWidth(const char* aString, PRUint32 aLength)
 {
     PRUint32 maxChunkLength = GetMaxChunkLength();
     nscoord width = 0;
     while (aLength > 0) {
         PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength);
-        width += GetWidthInternal(aString, len);
+        width += mFontMetrics->GetWidth(aString, len, this);
         aLength -= len;
         aString += len;
     }
     return width;
 }
 
 nscoord
 nsRenderingContext::GetWidth(const PRUnichar *aString, PRUint32 aLength)
 {
     PRUint32 maxChunkLength = GetMaxChunkLength();
     nscoord width = 0;
     while (aLength > 0) {
         PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength);
-        width += GetWidthInternal(aString, len);
+        width += mFontMetrics->GetWidth(aString, len, this);
         aLength -= len;
         aString += len;
     }
     return width;
 }
 
 #ifdef MOZ_MATHML
 nsBoundingMetrics
 nsRenderingContext::GetBoundingMetrics(const PRUnichar* aString,
                                        PRUint32 aLength)
 {
     PRUint32 maxChunkLength = GetMaxChunkLength();
     PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength);
     // Assign directly in the first iteration. This ensures that
     // negative ascent/descent can be returned and the left bearing
     // is properly initialized.
-    nsBoundingMetrics totalMetrics;
-    mFontMetrics->GetBoundingMetrics(aString, len, this, totalMetrics);
+    nsBoundingMetrics totalMetrics
+        = mFontMetrics->GetBoundingMetrics(aString, len, this);
     aLength -= len;
     aString += len;
 
     while (aLength > 0) {
         len = FindSafeLength(aString, aLength, maxChunkLength);
-        nsBoundingMetrics metrics;
-        mFontMetrics->GetBoundingMetrics(aString, len, this, metrics);
+        nsBoundingMetrics metrics
+            = mFontMetrics->GetBoundingMetrics(aString, len, this);
         totalMetrics += metrics;
         aLength -= len;
         aString += len;
     }
     return totalMetrics;
 }
 #endif
 
 void
 nsRenderingContext::DrawString(const char *aString, PRUint32 aLength,
                                nscoord aX, nscoord aY)
 {
     PRUint32 maxChunkLength = GetMaxChunkLength();
     while (aLength > 0) {
         PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength);
-        mFontMetrics->DrawString(aString, len, aX, aY, nsnull, this);
+        mFontMetrics->DrawString(aString, len, aX, aY, this);
         aLength -= len;
 
         if (aLength > 0) {
-            nscoord width = GetWidthInternal(aString, len);
+            nscoord width = mFontMetrics->GetWidth(aString, len, this);
             aX += width;
             aString += len;
         }
     }
 }
 
 void
 nsRenderingContext::DrawString(const nsString& aString, nscoord aX, nscoord aY)
@@ -608,53 +596,29 @@ nsRenderingContext::DrawString(const PRU
                                nscoord aX, nscoord aY)
 {
     PRUint32 maxChunkLength = GetMaxChunkLength();
     if (aLength <= maxChunkLength) {
         mFontMetrics->DrawString(aString, aLength, aX, aY, this, this);
         return;
     }
 
-    PRBool isRTL = mFontMetrics->GetRightToLeftText();
+    PRBool isRTL = mFontMetrics->GetTextRunRTL();
 
     // If we're drawing right to left, we must start at the end.
     if (isRTL) {
         aX += GetWidth(aString, aLength);
     }
 
     while (aLength > 0) {
         PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength);
-        nscoord width = GetWidthInternal(aString, len);
+        nscoord width = mFontMetrics->GetWidth(aString, len, this);
         if (isRTL) {
             aX -= width;
         }
         mFontMetrics->DrawString(aString, len, aX, aY, this, this);
         if (!isRTL) {
             aX += width;
         }
         aLength -= len;
         aString += len;
     }
 }
-
-nscoord
-nsRenderingContext::GetWidthInternal(const char* aString, PRUint32 aLength)
-{
-    if (aLength == 0) {
-        return 0;
-    }
-
-    nscoord width;
-    mFontMetrics->GetWidth(aString, aLength, width, this);
-    return width;
-}
-
-nscoord
-nsRenderingContext::GetWidthInternal(const PRUnichar *aString, PRUint32 aLength)
-{
-    if (aLength == 0) {
-        return 0;
-    }
-
-    nscoord width;
-    mFontMetrics->GetWidth(aString, aLength, width, nsnull, this);
-    return width;
-}
--- a/gfx/src/nsRenderingContext.h
+++ b/gfx/src/nsRenderingContext.h
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef NSRENDERINGCONTEXT__H__
 #define NSRENDERINGCONTEXT__H__
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIDeviceContext.h"
-#include "nsIThebesFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsColor.h"
 #include "nsCoord.h"
 #include "gfxContext.h"
 
 class nsIntRegion;
 
 typedef enum {
     nsLineStyle_kNone   = 0,
@@ -115,20 +115,19 @@ public:
     void InvertRect(const nsRect& aRect);
     void InvertRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
 
     // Text
 
     void SetFont(const nsFont& aFont, nsIAtom* aLanguage,
                  gfxUserFontSet *aUserFontSet);
     void SetFont(const nsFont& aFont, gfxUserFontSet *aUserFontSet);
-    void SetFont(nsIFontMetrics *aFontMetrics);
-    nsIThebesFontMetrics *FontMetrics() { return mFontMetrics; } // may be null
+    void SetFont(nsFontMetrics *aFontMetrics);
+    nsFontMetrics *FontMetrics() { return mFontMetrics; } // may be null
 
-    void SetRightToLeftText(PRBool aIsRTL);
     void SetTextRunRTL(PRBool aIsRTL);
 
     nscoord GetWidth(char aC);
     nscoord GetWidth(PRUnichar aC);
     nscoord GetWidth(const nsString& aString);
     nscoord GetWidth(const char* aString);
     nscoord GetWidth(const char* aString, PRUint32 aLength);
     nscoord GetWidth(const PRUnichar *aString, PRUint32 aLength);
@@ -141,19 +140,17 @@ public:
     void DrawString(const nsString& aString, nscoord aX, nscoord aY);
     void DrawString(const char *aString, PRUint32 aLength,
                     nscoord aX, nscoord aY);
     void DrawString(const PRUnichar *aString, PRUint32 aLength,
                     nscoord aX, nscoord aY);
 
 protected:
     PRInt32 GetMaxChunkLength();
-    nscoord GetWidthInternal(const char *aString, PRUint32 aLength);
-    nscoord GetWidthInternal(const PRUnichar *aString, PRUint32 aLength);
 
     nsRefPtr<gfxContext> mThebes;
     nsCOMPtr<nsIDeviceContext> mDeviceContext;
-    nsCOMPtr<nsIThebesFontMetrics> mFontMetrics;
+    nsRefPtr<nsFontMetrics> mFontMetrics;
 
     double mP2A; // cached app units per device pixel value
 };
 
 #endif  // NSRENDERINGCONTEXT__H__
--- a/gfx/src/nsThebesDeviceContext.cpp
+++ b/gfx/src/nsThebesDeviceContext.cpp
@@ -34,18 +34,16 @@
  * 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 "nsFont.h"
 #include "nsGfxCIID.h"
-#include "nsIThebesFontMetrics.h"
-#include "nsHashtable.h"
 #include "nsILanguageAtomService.h"
 #include "nsUnicharUtils.h"
 
 #include "nsIServiceManager.h"
 #include "nsIPrefService.h"
 #include "nsCRT.h"
 #include "mozilla/Services.h"
 
@@ -102,25 +100,24 @@ class nsFontCache
 {
 public:
     nsFontCache();
     ~nsFontCache();
 
     nsresult Init(nsIDeviceContext* aContext);
     nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
                            gfxUserFontSet* aUserFontSet,
-                           nsIFontMetrics*& aMetrics);
+                           nsFontMetrics*& aMetrics);
 
-    nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
+    nsresult FontMetricsDeleted(const nsFontMetrics* aFontMetrics);
     nsresult Compact();
     nsresult Flush();
-    nsresult CreateFontMetricsInstance(nsIFontMetrics** fm);
 
 protected:
-    nsTArray<nsIFontMetrics*> mFontMetrics;
+    nsTArray<nsFontMetrics*>  mFontMetrics;
     nsIDeviceContext         *mContext; // we do not addref this since
                                         // ownership is implied. MMP.
 };
 
 nsFontCache::nsFontCache()
 {
     MOZ_COUNT_CTOR(nsFontCache);
     mContext = nsnull;
@@ -139,71 +136,65 @@ nsFontCache::Init(nsIDeviceContext* aCon
     // Note: we don't hold a reference to the device context, because it
     // holds a reference to us and we don't want circular references
     mContext = aContext;
     return NS_OK;
 }
 
 nsresult
 nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
-  gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics)
+  gfxUserFontSet* aUserFontSet, nsFontMetrics*& aMetrics)
 {
     // First check our cache
     // start from the end, which is where we put the most-recent-used element
 
-    nsIFontMetrics* fm;
+    nsFontMetrics* fm;
     PRInt32 n = mFontMetrics.Length() - 1;
     for (PRInt32 i = n; i >= 0; --i) {
         fm = mFontMetrics[i];
-        nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm);
-        if (fm->Font().Equals(aFont) && tfm->GetUserFontSet() == aUserFontSet) {
-            nsCOMPtr<nsIAtom> language;
-            fm->GetLanguage(getter_AddRefs(language));
-            if (aLanguage == language.get()) {
-                if (i != n) {
-                    // promote it to the end of the cache
-                    mFontMetrics.RemoveElementAt(i);
-                    mFontMetrics.AppendElement(fm);
-                }
-                tfm->GetThebesFontGroup()->UpdateFontList();
-                NS_ADDREF(aMetrics = fm);
-                return NS_OK;
+        if (fm->Font().Equals(aFont) && fm->GetUserFontSet() == aUserFontSet &&
+            fm->Language() == aLanguage) {
+            if (i != n) {
+                // promote it to the end of the cache
+                mFontMetrics.RemoveElementAt(i);
+                mFontMetrics.AppendElement(fm);
             }
+            fm->GetThebesFontGroup()->UpdateFontList();
+            NS_ADDREF(aMetrics = fm);
+            return NS_OK;
         }
     }
 
     // It's not in the cache. Get font metrics and then cache them.
 
-    aMetrics = nsnull;
-    nsresult rv = CreateFontMetricsInstance(&fm);
-    if (NS_FAILED(rv)) return rv;
-    rv = fm->Init(aFont, aLanguage, mContext, aUserFontSet);
+    fm = new nsFontMetrics();
+    NS_ADDREF(fm);
+    nsresult rv = fm->Init(aFont, aLanguage, mContext, aUserFontSet);
     if (NS_SUCCEEDED(rv)) {
         // the mFontMetrics list has the "head" at the end, because append
         // is cheaper than insert
         mFontMetrics.AppendElement(fm);
         aMetrics = fm;
         NS_ADDREF(aMetrics);
         return NS_OK;
     }
     fm->Destroy();
     NS_RELEASE(fm);
 
     // One reason why Init() fails is because the system is running out of
     // resources. e.g., on Win95/98 only a very limited number of GDI
     // objects are available. Compact the cache and try again.
 
     Compact();
-    rv = CreateFontMetricsInstance(&fm);
-    if (NS_FAILED(rv)) return rv;
+    fm = new nsFontMetrics();
+    NS_ADDREF(fm);
     rv = fm->Init(aFont, aLanguage, mContext, aUserFontSet);
     if (NS_SUCCEEDED(rv)) {
         mFontMetrics.AppendElement(fm);
         aMetrics = fm;
-        NS_ADDREF(aMetrics);
         return NS_OK;
     }
     fm->Destroy();
     NS_RELEASE(fm);
 
     // could not setup a new one, send an old one (XXX search a "best
     // match"?)
 
@@ -213,53 +204,46 @@ nsFontCache::GetMetricsFor(const nsFont&
         NS_ADDREF(aMetrics);
         return NS_OK;
     }
 
     NS_POSTCONDITION(NS_SUCCEEDED(rv), "font metrics should not be null - bug 136248");
     return rv;
 }
 
-nsresult
-nsFontCache::CreateFontMetricsInstance(nsIFontMetrics** fm)
-{
-    static NS_DEFINE_CID(kFontMetricsCID, NS_FONT_METRICS_CID);
-    return CallCreateInstance(kFontMetricsCID, fm);
-}
-
-nsresult nsFontCache::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics)
+nsresult nsFontCache::FontMetricsDeleted(const nsFontMetrics* aFontMetrics)
 {
     mFontMetrics.RemoveElement(aFontMetrics);
     return NS_OK;
 }
 
 nsresult nsFontCache::Compact()
 {
     // Need to loop backward because the running element can be removed on
     // the way
     for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
-        nsIFontMetrics* fm = mFontMetrics[i];
-        nsIFontMetrics* oldfm = fm;
+        nsFontMetrics* fm = mFontMetrics[i];
+        nsFontMetrics* oldfm = fm;
         // Destroy() isn't here because we want our device context to be
         // notified
         NS_RELEASE(fm); // this will reset fm to nsnull
         // if the font is really gone, it would have called back in
         // FontMetricsDeleted() and would have removed itself
         if (mFontMetrics.IndexOf(oldfm) != mFontMetrics.NoIndex) { 
             // nope, the font is still there, so let's hold onto it too
             NS_ADDREF(oldfm);
         }
     }
     return NS_OK;
 }
 
 nsresult nsFontCache::Flush()
 {
     for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
-        nsIFontMetrics* fm = mFontMetrics[i];
+        nsFontMetrics* fm = mFontMetrics[i];
         // Destroy() will unhook our device context from the fm so that we
         // won't waste time in triggering the notification of
         // FontMetricsDeleted() in the subsequent release
         fm->Destroy();
         NS_RELEASE(fm);
     }
 
     mFontMetrics.Clear();
@@ -280,50 +264,38 @@ nsThebesDeviceContext::nsThebesDeviceCon
 
     mAppUnitsPerDevPixel = nscoord(-1);
     mAppUnitsPerPhysicalInch = nscoord(-1);
     mAppUnitsPerDevNotScaledPixel = nscoord(-1);
     mPixelScale = 1.0f;
 
     mFontCache = nsnull;
     mWidget = nsnull;
-    mFontAliasTable = nsnull;
 
     mDepth = 0;
     mWidth = 0;
     mHeight = 0;
     mPrintingScale = 1.0f;
 
 #if defined(XP_WIN) && !defined(WINCE)
     SCRIPT_DIGITSUBSTITUTE sds;
     ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &sds);
 #endif
 }
 
-static PRBool DeleteValue(nsHashKey* aKey, void* aValue, void* closure)
-{
-    delete ((nsString*)aValue);
-    return PR_TRUE;
-}
-
 nsThebesDeviceContext::~nsThebesDeviceContext()
 {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs)
         obs->RemoveObserver(this, "memory-pressure");
 
     if (nsnull != mFontCache) {
         delete mFontCache;
         mFontCache = nsnull;
     }
-
-    if (nsnull != mFontAliasTable) {
-        mFontAliasTable->Enumerate(DeleteValue);
-        delete mFontAliasTable;
-    }
 }
 
 NS_IMETHODIMP
 nsThebesDeviceContext::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aSomeData)
 {
     if (mFontCache && !nsCRT::strcmp(aTopic, "memory-pressure")) {
         mFontCache->Compact();
     }
@@ -334,17 +306,17 @@ NS_IMETHODIMP nsThebesDeviceContext::Cre
 {
     mFontCache = new nsFontCache();
     if (!mFontCache) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
     return mFontCache->Init(this);
 }
 
-NS_IMETHODIMP nsThebesDeviceContext::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics)
+NS_IMETHODIMP nsThebesDeviceContext::FontMetricsDeleted(const nsFontMetrics* aFontMetrics)
 {
     if (mFontCache) {
         mFontCache->FontMetricsDeleted(aFontMetrics);
     }
     return NS_OK;
 }
 
 void
@@ -358,17 +330,17 @@ nsThebesDeviceContext::GetLocaleLanguage
         }
         if (!mLocaleLanguage) {
             mLocaleLanguage = do_GetAtom("x-western");
         }
     }
 }
 
 NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont,
-  nsIAtom* aLanguage, gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics)
+  nsIAtom* aLanguage, gfxUserFontSet* aUserFontSet, nsFontMetrics*& aMetrics)
 {
     if (nsnull == mFontCache) {
         nsresult rv = CreateFontCache();
         if (NS_FAILED(rv)) {
             aMetrics = nsnull;
             return rv;
         }
         // XXX temporary fix for performance problem -- erik
@@ -381,197 +353,63 @@ NS_IMETHODIMP nsThebesDeviceContext::Get
         aLanguage = mLocaleLanguage;
     }
 
     return mFontCache->GetMetricsFor(aFont, aLanguage, aUserFontSet, aMetrics);
 }
 
 NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont,
                                                    gfxUserFontSet* aUserFontSet,
-                                                   nsIFontMetrics*& aMetrics)
+                                                   nsFontMetrics*& aMetrics)
 {
     if (nsnull == mFontCache) {
         nsresult rv = CreateFontCache();
         if (NS_FAILED(rv)) {
             aMetrics = nsnull;
             return rv;
         }
         // XXX temporary fix for performance problem -- erik
         GetLocaleLanguage();
     }
     return mFontCache->GetMetricsFor(aFont, mLocaleLanguage, aUserFontSet,
                                      aMetrics);
 }
 
 struct FontEnumData {
-    FontEnumData(nsIDeviceContext* aDC, nsString& aFaceName)
-        : mDC(aDC), mFaceName(aFaceName)
-    {}
-    nsIDeviceContext* mDC;
-    nsString&         mFaceName;
+    FontEnumData(nsString& aFaceName) : mFaceName(aFaceName) {}
+    nsString& mFaceName;
 };
 
-static PRBool FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
+static PRBool
+FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
 {
     FontEnumData* data = (FontEnumData*)aData;
-    // XXX for now, all generic fonts are presumed to exist
-    //     we may want to actually check if there's an installed conversion
-    if (aGeneric) {
-        data->mFaceName = aFamily;
-        return PR_FALSE; // found one, stop.
-    }
-    else {
-        nsAutoString local;
-        PRBool       aliased;
-        data->mDC->GetLocalFontName(aFamily, local, aliased);
-        if (aliased || (NS_SUCCEEDED(data->mDC->CheckFontExistence(local)))) {
-            data->mFaceName = local;
-            return PR_FALSE; // found one, stop.
-        }
-    }
-    return PR_TRUE; // didn't exist, continue looking
+    data->mFaceName = aFamily;
+    return PR_FALSE; // stop
 }
 
-NS_IMETHODIMP nsThebesDeviceContext::FirstExistingFont(const nsFont& aFont, nsString& aFaceName)
+NS_IMETHODIMP
+nsThebesDeviceContext::FirstExistingFont(const nsFont& aFont,
+                                         nsString& aFaceName)
 {
-    FontEnumData data(this, aFaceName);
+    FontEnumData data(aFaceName);
     if (aFont.EnumerateFamilies(FontEnumCallback, &data)) {
-        return NS_ERROR_FAILURE; // ran out
+        return NS_ERROR_FAILURE; // can only happen for an empty font
     }
     return NS_OK;
 }
 
-class FontAliasKey: public nsHashKey
-{
-public:
-    FontAliasKey(const nsString& aString)
-    { mString.Assign(aString); }
-
-    virtual PRUint32 HashCode(void) const;
-    virtual PRBool Equals(const nsHashKey *aKey) const;
-    virtual nsHashKey *Clone(void) const;
-
-    nsString mString;
-};
-
-PRUint32 FontAliasKey::HashCode(void) const
-{
-    PRUint32 hash = 0;
-    const PRUnichar* string = mString.get();
-    PRUnichar ch;
-    while ((ch = *string++) != 0) {
-        // FYI: hash = hash*37 + ch
-        ch = ToUpperCase(ch);
-        hash = ((hash << 5) + (hash << 2) + hash) + ch;
-    }
-    return hash;
-}
-
-PRBool FontAliasKey::Equals(const nsHashKey *aKey) const
-{
-    return mString.Equals(((FontAliasKey*)aKey)->mString, nsCaseInsensitiveStringComparator());
-}
-
-nsHashKey* FontAliasKey::Clone(void) const
-{
-    return new FontAliasKey(mString);
-}
-
-nsresult nsThebesDeviceContext::CreateFontAliasTable()
+NS_IMETHODIMP
+nsThebesDeviceContext::GetLocalFontName(const nsString& aFaceName,
+                                        nsString& aLocalName,
+                                        PRBool& aAliased)
 {
-    nsresult result = NS_OK;
-
-    if (nsnull == mFontAliasTable) {
-        mFontAliasTable = new nsHashtable();
-        if (nsnull != mFontAliasTable) {
-
-            nsAutoString times;         times.AssignLiteral("Times");
-            nsAutoString timesNewRoman; timesNewRoman.AssignLiteral("Times New Roman");
-            nsAutoString timesRoman;    timesRoman.AssignLiteral("Times Roman");
-            nsAutoString arial;         arial.AssignLiteral("Arial");
-            nsAutoString helvetica;     helvetica.AssignLiteral("Helvetica");
-            nsAutoString courier;       courier.AssignLiteral("Courier");
-            nsAutoString courierNew;    courierNew.AssignLiteral("Courier New");
-            nsAutoString nullStr;
-
-            AliasFont(times, timesNewRoman, timesRoman, PR_FALSE);
-            AliasFont(timesRoman, timesNewRoman, times, PR_FALSE);
-            AliasFont(timesNewRoman, timesRoman, times, PR_FALSE);
-            AliasFont(arial, helvetica, nullStr, PR_FALSE);
-            AliasFont(helvetica, arial, nullStr, PR_FALSE);
-            AliasFont(courier, courierNew, nullStr, PR_TRUE);
-            AliasFont(courierNew, courier, nullStr, PR_FALSE);
-        }
-        else {
-            result = NS_ERROR_OUT_OF_MEMORY;
-        }
-    }
-    return result;
-}
-
-nsresult nsThebesDeviceContext::AliasFont(const nsString& aFont,
-                                          const nsString& aAlias,
-                                          const nsString& aAltAlias,
-                                          PRBool aForceAlias)
-{
-    nsresult result = NS_OK;
-
-    if (nsnull != mFontAliasTable) {
-        if (aForceAlias || NS_FAILED(CheckFontExistence(aFont))) {
-            if (NS_SUCCEEDED(CheckFontExistence(aAlias))) {
-                nsString* entry = new nsString(aAlias);
-                if (nsnull != entry) {
-                    FontAliasKey key(aFont);
-                    mFontAliasTable->Put(&key, entry);
-                }
-                else {
-                    result = NS_ERROR_OUT_OF_MEMORY;
-                }
-            }
-            else if (!aAltAlias.IsEmpty() && NS_SUCCEEDED(CheckFontExistence(aAltAlias))) {
-                nsString* entry = new nsString(aAltAlias);
-                if (nsnull != entry) {
-                    FontAliasKey key(aFont);
-                    mFontAliasTable->Put(&key, entry);
-                }
-                else {
-                    result = NS_ERROR_OUT_OF_MEMORY;
-                }
-            }
-        }
-    }
-    else {
-        result = NS_ERROR_FAILURE;
-    }
-    return result;
-}
-
-NS_IMETHODIMP nsThebesDeviceContext::GetLocalFontName(const nsString& aFaceName,
-                                                      nsString& aLocalName,
-                                                      PRBool& aAliased)
-{
-    nsresult result = NS_OK;
-
-    if (nsnull == mFontAliasTable) {
-        result = CreateFontAliasTable();
-    }
-
-    if (nsnull != mFontAliasTable) {
-        FontAliasKey key(aFaceName);
-        const nsString* alias = (const nsString*)mFontAliasTable->Get(&key);
-        if (nsnull != alias) {
-            aLocalName = *alias;
-            aAliased = PR_TRUE;
-        }
-        else {
-            aLocalName = aFaceName;
-            aAliased = PR_FALSE;
-        }
-    }
-    return result;
+    aLocalName = aFaceName;
+    aAliased = PR_FALSE;
+    return NS_OK;
 }
 
 NS_IMETHODIMP nsThebesDeviceContext::FlushFontCache(void)
 {
     if (nsnull != mFontCache)
         mFontCache->Flush();
     return NS_OK;
 }
--- a/gfx/src/nsThebesDeviceContext.h
+++ b/gfx/src/nsThebesDeviceContext.h
@@ -45,32 +45,28 @@
 #include "nsIDeviceContextSpec.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsWeakReference.h"
 #include "gfxContext.h"
 
-#include "nsRefPtrHashtable.h"
-#include "nsHashKeys.h"
-
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gThebesGFXLog;
 #endif
 
 #ifdef XP_WIN
 #include "gfxWindowsSurface.h"
 #elif defined(XP_OS2)
 #include "gfxOS2Surface.h"
 #endif
 
-class nsHashtable;
 class nsFontCache;
 
 class nsThebesDeviceContext : public nsIDeviceContext,
                               public nsIObserver,
                               public nsSupportsWeakReference
 {
 public:
     nsThebesDeviceContext();
@@ -85,28 +81,28 @@ public:
     NS_IMETHOD InitForPrinting(nsIDeviceContextSpec *aDevSpec);
     NS_IMETHOD CreateRenderingContext(nsIView *aView, nsRenderingContext *&aContext);
     NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsRenderingContext *&aContext);
     NS_IMETHOD CreateRenderingContext(nsRenderingContext *&aContext);
     NS_IMETHOD CreateRenderingContextInstance(nsRenderingContext *&aContext);
 
     NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
                              gfxUserFontSet* aUserFontSet,
-                             nsIFontMetrics*& aMetrics);
+                             nsFontMetrics*& aMetrics);
     NS_IMETHOD GetMetricsFor(const nsFont& aFont,
                              gfxUserFontSet* aUserFontSet,
-                             nsIFontMetrics*& aMetrics);
+                             nsFontMetrics*& aMetrics);
 
     NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName);
 
     NS_IMETHOD GetLocalFontName(const nsString& aFaceName, nsString& aLocalName,
                                 PRBool& aAliased);
 
     NS_IMETHOD CreateFontCache();
-    NS_IMETHOD FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
+    NS_IMETHOD FontMetricsDeleted(const nsFontMetrics* aFontMetrics);
     NS_IMETHOD FlushFontCache(void);
 
     NS_IMETHOD PrepareNativeWidget(nsIWidget *aWidget, void **aOut);
 
     NS_IMETHOD GetSystemFont(nsSystemFontID aID, nsFont *aFont) const;
     NS_IMETHOD ClearCachedSystemFonts();
 
     NS_IMETHOD CheckFontExistence(const nsString& aFaceName);
@@ -138,32 +134,27 @@ public:
 
     PRBool IsPrinterSurface(void);
 
 #if defined(XP_WIN) || defined(XP_OS2)
     HDC GetPrintHDC();
 #endif
 
 protected:
-    virtual nsresult CreateFontAliasTable();
-    nsresult AliasFont(const nsString& aFont, 
-                       const nsString& aAlias, const nsString& aAltAlias,
-                       PRBool aForceAlias);
     void GetLocaleLanguage(void);
     nsresult SetDPI();
     void ComputeClientRectUsingScreen(nsRect *outRect);
     void ComputeFullAreaUsingScreen(nsRect *outRect);
     void FindScreen(nsIScreen **outScreen);
     void CalcPrintingSize();
     void UpdateScaledAppUnits();
 
     PRUint32          mDepth;
     nsFontCache*      mFontCache;
     nsCOMPtr<nsIAtom> mLocaleLanguage; // XXX temp fix for performance bug
-    nsHashtable*      mFontAliasTable;
     nsCOMPtr<nsIWidget> mWidget;
 
 private:
     nsCOMPtr<nsIScreenManager> mScreenManager;
 
     nscoord mWidth;
     nscoord mHeight;
 
--- a/gfx/src/nsThebesGfxFactory.cpp
+++ b/gfx/src/nsThebesGfxFactory.cpp
@@ -39,21 +39,19 @@
 #include "mozilla/ModuleUtils.h"
 #include "nsCOMPtr.h"
 #include "nsGfxCIID.h"
 
 #include "nsScriptableRegion.h"
 
 #include "nsThebesDeviceContext.h"
 #include "nsThebesRegion.h"
-#include "nsThebesFontMetrics.h"
 #include "nsThebesFontEnumerator.h"
 #include "gfxPlatform.h"
 
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesFontMetrics)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesDeviceContext)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesRegion)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesFontEnumerator)
 
 static nsresult
 nsScriptableRegionConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
 {
   nsresult rv;
@@ -89,33 +87,30 @@ nsScriptableRegionConstructor(nsISupport
   // reference - we don't want this to go out of scope early!
   scriptableRgn = nsnull;
   rv = inst->QueryInterface(aIID, aResult);
   NS_RELEASE(inst);
 
   return rv;
 }
 
-NS_DEFINE_NAMED_CID(NS_FONT_METRICS_CID);
 NS_DEFINE_NAMED_CID(NS_FONT_ENUMERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_CID);
 NS_DEFINE_NAMED_CID(NS_REGION_CID);
 NS_DEFINE_NAMED_CID(NS_SCRIPTABLE_REGION_CID);
 
 static const mozilla::Module::CIDEntry kThebesCIDs[] = {
-    { &kNS_FONT_METRICS_CID, false, NULL, nsThebesFontMetricsConstructor },
     { &kNS_FONT_ENUMERATOR_CID, false, NULL, nsThebesFontEnumeratorConstructor },
     { &kNS_DEVICE_CONTEXT_CID, false, NULL, nsThebesDeviceContextConstructor },
     { &kNS_REGION_CID, false, NULL, nsThebesRegionConstructor },
     { &kNS_SCRIPTABLE_REGION_CID, false, NULL, nsScriptableRegionConstructor },
     { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kThebesContracts[] = {
-    { "@mozilla.org/gfx/fontmetrics;1", &kNS_FONT_METRICS_CID },
     { "@mozilla.org/gfx/fontenumerator;1", &kNS_FONT_ENUMERATOR_CID },
     { "@mozilla.org/gfx/devicecontext;1", &kNS_DEVICE_CONTEXT_CID },
     { "@mozilla.org/gfx/region/nsThebes;1", &kNS_REGION_CID },
     { "@mozilla.org/gfx/region;1", &kNS_SCRIPTABLE_REGION_CID },
     { NULL }
 };
 
 static nsresult
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -844,8 +844,12 @@ CREATE_PRECOMPLETE_CMD = $(PYTHON) $(cal
 EXPAND_LIBS = $(PYTHON) -I$(DEPTH)/config $(topsrcdir)/config/expandlibs.py
 EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_exec.py
 EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py
 EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
 EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist -- $(MKSHLIB)
+
+ifdef STDCXX_COMPAT
+CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && echo "Error: We don't want these libstdc++ symbol versions to be used" && exit 1 || exit 0
+endif
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -987,16 +987,17 @@ endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
 endif
 else # !WINNT || GNU_CC
 ifeq ($(CPP_PROG_LINK),1)
 	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(EXE_DEF_FILE)
+	$(call CHECK_STDCXX,$@)
 else # ! CPP_PROG_LINK
 	$(EXPAND_CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
 endif # CPP_PROG_LINK
 endif # WINNT && !GNU_CC
 endif # WINCE
 
 ifdef ENABLE_STRIP
 	$(STRIP) $@
@@ -1052,16 +1053,17 @@ ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
 ifeq ($(CPP_PROG_LINK),1)
 	$(EXPAND_CCC) $(WRAP_MALLOC_CFLAGS) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
+	$(call CHECK_STDCXX,$@)
 else
 	$(EXPAND_CC) $(WRAP_MALLOC_CFLAGS) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(BIN_FLAGS)
 endif # CPP_PROG_LINK
 endif # WINNT && !GNU_CC
 endif # WINCE
 
 ifdef ENABLE_STRIP
 	$(STRIP) $@
@@ -1172,16 +1174,17 @@ ifdef DTRACE_LIB_DEPENDENT
 ifndef XP_MACOSX
 	dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
 endif
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 	@$(RM) $(DTRACE_PROBE_OBJ)
 else # ! DTRACE_LIB_DEPENDENT
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 endif # DTRACE_LIB_DEPENDENT
+	$(call CHECK_STDCXX,$@)
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		rm -f $@.manifest; \
 	fi
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -50,17 +50,16 @@
 #include "nsBidiUtils.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsInlineFrame.h"
 #include "nsPlaceholderFrame.h"
 #include "nsContainerFrame.h"
 #include "nsFirstLetterFrame.h"
 #include "gfxUnicodeProperties.h"
-#include "nsIThebesFontMetrics.h"
 #include "nsTextFrame.h"
 
 #undef NOISY_BIDI
 #undef REALLY_NOISY_BIDI
 
 using namespace mozilla;
 
 static const PRUnichar kSpace            = 0x0020;
@@ -1760,17 +1759,17 @@ class NS_STACK_CLASS nsIRenderingContext
 public:
   nsIRenderingContextBidiProcessor(nsRenderingContext* aCtx,
                                    nsRenderingContext* aTextRunConstructionContext,
                                    const nsPoint&       aPt)
     : mCtx(aCtx), mTextRunConstructionContext(aTextRunConstructionContext), mPt(aPt) { }
 
   ~nsIRenderingContextBidiProcessor()
   {
-    mCtx->SetRightToLeftText(PR_FALSE);
+    mCtx->SetTextRunRTL(PR_FALSE);
   }
 
   virtual void SetText(const PRUnichar* aText,
                        PRInt32          aLength,
                        nsBidiDirection  aDirection)
   {
     mTextRunConstructionContext->SetTextRunRTL(aDirection==NSBIDI_RTL);
     mText = aText;
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -46,17 +46,16 @@
 
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsFrameSelection.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMRange.h"
-#include "nsIFontMetrics.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsRenderingContext.h"
 #include "nsIDeviceContext.h"
 #include "nsPresContext.h"
@@ -352,22 +351,22 @@ nsCaret::GetGeometryForFrame(nsIFrame* a
   nsresult rv = aFrame->GetPointFromOffset(aFrameOffset, &framePos);
   if (NS_FAILED(rv))
     return rv;
 
   nsIFrame *frame = aFrame->GetContentInsertionFrame();
   NS_ASSERTION(frame, "We should not be in the middle of reflow");
   nscoord baseline = frame->GetCaretBaseline();
   nscoord ascent = 0, descent = 0;
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
   NS_ASSERTION(fm, "We should be able to get the font metrics");
   if (fm) {
-    fm->GetMaxAscent(ascent);
-    fm->GetMaxDescent(descent);
+    ascent = fm->MaxAscent();
+    descent = fm->MaxDescent();
   }
   nscoord height = ascent + descent;
   framePos.y = baseline - ascent;
   Metrics caretMetrics = ComputeMetrics(aFrame, aFrameOffset, height);
   *aRect = nsRect(framePos, nsSize(caretMetrics.mCaretWidth, height));
 
   // Clamp the x-position to be within our scroll frame. If we don't, then it
   // clips us, and we don't appear at all. See bug 335560.
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -34,17 +34,16 @@
  * 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 "nsLayoutUtils.h"
-#include "nsIFontMetrics.h"
 #include "nsIFormControlFrame.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsFrameList.h"
 #include "nsGkAtoms.h"
@@ -1640,17 +1639,17 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   // Update the widget's transparent region information. This sets
   // glass boundaries on Windows.
   if ((aFlags & PAINT_WIDGET_LAYERS) &&
       !willFlushRetainedLayers &&
       !(aFlags & PAINT_DOCUMENT_RELATIVE)) {
     nsIWidget *widget = aFrame->GetNearestWidget();
     if (widget) {
       PRInt32 pixelRatio = presContext->AppUnitsPerDevPixel();
-      nsIntRegion visibleWindowRegion(visibleRegion.ToOutsidePixels(presContext->AppUnitsPerDevPixel()));
+      nsIntRegion visibleWindowRegion(visibleRegion.ToOutsidePixels(pixelRatio));
       widget->UpdateTransparentRegion(visibleWindowRegion);
     }
   }
 
 #ifdef DEBUG
   if (gDumpPaintList) {
     fprintf(stderr, "Painting --- after optimization:\n");
     nsFrame::PrintDisplayList(&builder, list);
@@ -1863,25 +1862,25 @@ nsLayoutUtils::GetTextShadowRectsUnion(c
 
     resultRect.UnionRect(resultRect, tmpRect);
   }
   return resultRect;
 }
 
 nsresult
 nsLayoutUtils::GetFontMetricsForFrame(const nsIFrame* aFrame,
-                                      nsIFontMetrics** aFontMetrics)
+                                      nsFontMetrics** aFontMetrics)
 {
   return nsLayoutUtils::GetFontMetricsForStyleContext(aFrame->GetStyleContext(),
                                                       aFontMetrics);
 }
 
 nsresult
 nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext,
-                                             nsIFontMetrics** aFontMetrics)
+                                             nsFontMetrics** aFontMetrics)
 {
   // pass the user font set object into the device context to pass along to CreateFontGroup
   gfxUserFontSet* fs = aStyleContext->PresContext()->GetUserFontSet();
 
   return aStyleContext->PresContext()->DeviceContext()->GetMetricsFor(
                   aStyleContext->GetStyleFont()->mFont,
                   aStyleContext->GetStyleVisibility()->mLanguage,
                   fs, *aFontMetrics);
@@ -2838,22 +2837,21 @@ nsLayoutUtils::GetStringWidth(const nsIF
                                              direction, presContext, *aContext);
   }
 #endif // IBMBIDI
   aContext->SetTextRunRTL(PR_FALSE);
   return aContext->GetWidth(aString, aLength);
 }
 
 /* static */ nscoord
-nsLayoutUtils::GetCenteredFontBaseline(nsIFontMetrics* aFontMetrics,
+nsLayoutUtils::GetCenteredFontBaseline(nsFontMetrics* aFontMetrics,
                                        nscoord         aLineHeight)
 {
-  nscoord fontAscent, fontHeight;
-  aFontMetrics->GetMaxAscent(fontAscent);
-  aFontMetrics->GetHeight(fontHeight);
+  nscoord fontAscent = aFontMetrics->MaxAscent();
+  nscoord fontHeight = aFontMetrics->MaxHeight();
 
   nscoord leading = aLineHeight - fontHeight;
   return fontAscent + leading/2;
 }
 
 
 /* static */ PRBool
 nsLayoutUtils::GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -45,17 +45,17 @@ class nsIFormControlFrame;
 class nsPresContext;
 class nsIContent;
 class nsIAtom;
 class nsIScrollableFrame;
 class nsIDOMEvent;
 class nsRegion;
 class nsDisplayListBuilder;
 class nsDisplayItem;
-class nsIFontMetrics;
+class nsFontMetrics;
 class nsClientRectList;
 
 #include "prtypes.h"
 #include "nsStyleContext.h"
 #include "nsAutoPtr.h"
 #include "nsStyleSet.h"
 #include "nsIView.h"
 #include "nsIFrame.h"
@@ -733,26 +733,26 @@ public:
 
   /**
    * Get the font metrics corresponding to the frame's style data.
    * @param aFrame the frame
    * @param aFontMetrics the font metrics result
    * @return success or failure code
    */
   static nsresult GetFontMetricsForFrame(const nsIFrame* aFrame,
-                                         nsIFontMetrics** aFontMetrics);
+                                         nsFontMetrics** aFontMetrics);
 
   /**
    * Get the font metrics corresponding to the given style data.
    * @param aStyleContext the style data
    * @param aFontMetrics the font metrics result
    * @return success or failure code
    */
   static nsresult GetFontMetricsForStyleContext(nsStyleContext* aStyleContext,
-                                                nsIFontMetrics** aFontMetrics);
+                                                nsFontMetrics** aFontMetrics);
 
   /**
    * Find the immediate child of aParent whose frame subtree contains
    * aDescendantFrame. Returns null if aDescendantFrame is not a descendant
    * of aParent.
    */
   static nsIFrame* FindChildContainingDescendant(nsIFrame* aParent, nsIFrame* aDescendantFrame);
 
@@ -930,17 +930,17 @@ public:
                                 PRInt32              aLength);
 
   /**
    * Gets the baseline to vertically center text from a font within a
    * line of specified height.
    *
    * Returns the baseline position relative to the top of the line.
    */
-  static nscoord GetCenteredFontBaseline(nsIFontMetrics* aFontMetrics,
+  static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics,
                                          nscoord         aLineHeight);
 
   /**
    * Derive a baseline of |aFrame| (measured from its top border edge)
    * from its first in-flow line box (not descending into anything with
    * 'overflow' not 'visible', potentially including aFrame itself).
    *
    * Returns true if a baseline was found (and fills in aResult).
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1284,20 +1284,20 @@ nsPresContext::SetImageAnimationModeInte
 }
 
 void
 nsPresContext::SetImageAnimationModeExternal(PRUint16 aMode)
 {
   SetImageAnimationModeInternal(aMode);
 }
 
-already_AddRefed<nsIFontMetrics>
+already_AddRefed<nsFontMetrics>
 nsPresContext::GetMetricsFor(const nsFont& aFont, PRBool aUseUserFontSet)
 {
-  nsIFontMetrics* metrics = nsnull;
+  nsFontMetrics* metrics = nsnull;
   mDeviceContext->GetMetricsFor(aFont, mLanguage,
                                 aUseUserFontSet ? GetUserFontSet() : nsnull,
                                 metrics);
   return metrics;
 }
 
 const nsFont*
 nsPresContext::GetDefaultFont(PRUint8 aFontID) const
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -78,17 +78,17 @@ class nsImageLoader;
 #ifdef IBMBIDI
 class nsBidiPresUtils;
 #endif // IBMBIDI
 
 struct nsRect;
 
 class imgIRequest;
 
-class nsIFontMetrics;
+class nsFontMetrics;
 class nsIFrame;
 class nsFrameManager;
 class nsILinkHandler;
 class nsStyleContext;
 class nsIAtom;
 class nsIEventStateManager;
 class nsIURI;
 class nsILookAndFeel;
@@ -323,17 +323,17 @@ public:
   /**
    * Get the font metrics for a given font.
    *
    * If aUseUserFontSet is false, don't build or use the user font set.
    * This is intended only for nsRuleNode::CalcLengthWithInitialFont
    * (which is used from media query matching, which is in turn called
    * when building the user font set).
    */
-  NS_HIDDEN_(already_AddRefed<nsIFontMetrics>)
+  NS_HIDDEN_(already_AddRefed<nsFontMetrics>)
   GetMetricsFor(const nsFont& aFont, PRBool aUseUserFontSet = PR_TRUE);
 
   /**
    * Get the default font corresponding to the given ID.  This object is
    * read-only, you must copy the font to modify it.
    * 
    * When aFontID is kPresContext_DefaultVariableFontID or
    * kPresContext_DefaultFixedFontID (which equals
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -137,17 +137,17 @@
 #include "nsIAttribute.h"
 #include "nsIGlobalHistory2.h"
 #include "nsDisplayList.h"
 #include "nsIRegion.h"
 #include "nsRegion.h"
 #include "nsRenderingContext.h"
 
 #ifdef MOZ_REFLOW_PERF
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #endif
 
 #include "nsIReflowCallback.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsFocusManager.h"
 #include "nsIPluginInstance.h"
 #include "nsIObjectFrame.h"
@@ -8800,26 +8800,24 @@ void ReflowCountMgr::PaintCount(const ch
       (IndiReflowCounter *)PL_HashTableLookup(mIndiFrameCounts, key);
     if (counter != nsnull && counter->mName.EqualsASCII(aName)) {
       aRenderingContext->PushState();
       aRenderingContext->Translate(aOffset);
       nsFont font("Times", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
                   NS_FONT_WEIGHT_NORMAL, NS_FONT_STRETCH_NORMAL, 0,
                   nsPresContext::CSSPixelsToAppUnits(11));
 
-      nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
+      nsRefPtr<nsFontMetrics> fm = aPresContext->GetMetricsFor(font);
       aRenderingContext->SetFont(fm);
       char buf[16];
       sprintf(buf, "%d", counter->mCount);
-      nscoord x = 0, y;
-      nscoord width, height;
+      nscoord x = 0, y = fm->MaxAscent();
+      nscoord width, height = fm->MaxHeight();
       aRenderingContext->SetTextRunRTL(PR_FALSE);
       aRenderingContext->GetWidth((char*)buf, width);
-      fm->GetHeight(height);
-      fm->GetMaxAscent(y);
 
       PRUint32 color;
       PRUint32 color2;
       if (aColor != 0) {
         color  = aColor;
         color2 = NS_RGB(0,0,0);
       } else {
         PRUint8 rc = 0, gc = 0, bc = 0;
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -32,17 +32,16 @@
  * 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 "nsGfxButtonControlFrame.h"
 #include "nsWidgetsCID.h"
-#include "nsIFontMetrics.h"
 #include "nsFormControlFrame.h"
 #include "nsIFormControl.h"
 #include "nsINameSpaceManager.h"
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 #include "nsIServiceManager.h"
 #include "nsIDOMNode.h"
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -42,17 +42,16 @@
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsStyleContext.h"
 #include "nsLeafFrame.h"
 #include "nsCSSRendering.h"
 #include "nsISupports.h"
 #include "nsGkAtoms.h"
 #include "nsIDeviceContext.h"
-#include "nsIFontMetrics.h"
 #include "nsStyleConsts.h"
 #include "nsFormControlFrame.h"
 #include "nsGUIEvent.h"
 #include "nsIServiceManager.h"
 #include "nsContainerFrame.h"
 #include "nsLayoutUtils.h"
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -64,17 +64,17 @@
 #include "nsIEventListenerManager.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIComponentManager.h"
 #include "nsILookAndFeel.h"
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMNSEvent.h"
 #include "nsGUIEvent.h"
 #include "nsIServiceManager.h"
 #include "nsINodeInfo.h"
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
@@ -1873,21 +1873,21 @@ nsListControlFrame::IsLeftButton(nsIDOME
   }
   return PR_FALSE;
 }
 
 nscoord
 nsListControlFrame::CalcFallbackRowHeight()
 {
   nscoord rowHeight = 0;
-  
-  nsCOMPtr<nsIFontMetrics> fontMet;
+
+  nsRefPtr<nsFontMetrics> fontMet;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
   if (fontMet) {
-    fontMet->GetHeight(rowHeight);
+    rowHeight = fontMet->MaxHeight();
   }
 
   return rowHeight;
 }
 
 nscoord
 nsListControlFrame::CalcIntrinsicHeight(nscoord aHeightOfARow,
                                         PRInt32 aNumberOfOptions)
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -113,17 +113,16 @@
 #include "nsContentCreatorFunctions.h"
 #include "nsIDOMKeyListener.h"
 #include "nsIDOMEventGroup.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsINativeKeyBindings.h"
 #include "nsIJSContextStack.h"
 #include "nsFocusManager.h"
 #include "nsTextEditRules.h"
-#include "nsIFontMetrics.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsPresState.h"
 
 #include "mozilla/FunctionTimer.h"
 
 #define DEFAULT_COLUMN_WIDTH 20
 
 #include "nsContentCID.h"
@@ -225,26 +224,26 @@ nsresult
 nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext,
                                       nsSize&              aIntrinsicSize)
 {
   // Get leading and the Average/MaxAdvance char width 
   nscoord lineHeight  = 0;
   nscoord charWidth   = 0;
   nscoord charMaxAdvance  = 0;
 
-  nsCOMPtr<nsIFontMetrics> fontMet;
+  nsRefPtr<nsFontMetrics> fontMet;
   nsresult rv =
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
   NS_ENSURE_SUCCESS(rv, rv);
   aRenderingContext->SetFont(fontMet);
 
   lineHeight =
     nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT);
-  fontMet->GetAveCharWidth(charWidth);
-  fontMet->GetMaxAdvance(charMaxAdvance);
+  charWidth = fontMet->AveCharWidth();
+  charMaxAdvance = fontMet->MaxAdvance();
 
   // Set the width equal to the width in characters
   PRInt32 cols = GetCols();
   aIntrinsicSize.width = cols * charWidth;
 
   // To better match IE, take the maximum character width(in twips) and remove
   // 4 pixels add this on as additional padding(internalPadding). But only do
   // this if charMaxAdvance != charWidth; if they are equal, this is almost
@@ -587,17 +586,17 @@ nsTextControlFrame::GetBoxAscent(nsBoxLa
 
   // First calculate the ascent wrt the client rect
   nsRect clientRect;
   GetClientRect(clientRect);
   nscoord lineHeight =
     IsSingleLineTextControl() ? clientRect.height :
     nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT);
 
-  nsCOMPtr<nsIFontMetrics> fontMet;
+  nsRefPtr<nsFontMetrics> fontMet;
   nsresult rv =
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
   NS_ENSURE_SUCCESS(rv, 0);
 
   nscoord ascent = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight);
 
   // Now adjust for our borders and padding
   ascent += clientRect.y;
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -39,17 +39,16 @@
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsHTMLParts.h"
 #include "nsPresContext.h"
 #include "nsLineLayout.h"
 #include "nsStyleConsts.h"
 #include "nsGkAtoms.h"
-#include "nsIFontMetrics.h"
 #include "nsRenderingContext.h"
 #include "nsLayoutUtils.h"
 
 #ifdef ACCESSIBILITY
 #include "nsIServiceManager.h"
 #include "nsAccessibilityService.h"
 #endif
 
@@ -147,17 +146,17 @@ BRFrame::Reflow(nsPresContext* aPresCont
       // quirks-mode fix that doesn't apply the block's min
       // line-height makes this necessary to make BR cause a line
       // of the full line-height
 
       // We also do this in strict mode because BR should act like a
       // normal inline frame.  That line-height is used is important
       // here for cases where the line-height is less than 1.
       nsLayoutUtils::SetFontFromStyle(aReflowState.rendContext, mStyleContext);
-      nsIFontMetrics *fm = aReflowState.rendContext->FontMetrics();
+      nsFontMetrics *fm = aReflowState.rendContext->FontMetrics();
       if (fm) {
         nscoord logicalHeight = aReflowState.CalcLineHeight();
         aMetrics.height = logicalHeight;
         aMetrics.ascent =
           nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight);
         AddStateBits(BR_USING_CENTERED_FONT_BASELINE);
       }
       else {
@@ -228,25 +227,24 @@ BRFrame::GetType() const
 {
   return nsGkAtoms::brFrame;
 }
 
 nscoord
 BRFrame::GetBaseline() const
 {
   nscoord ascent = 0;
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   if (fm) {
     nscoord logicalHeight = GetRect().height;
     if (GetStateBits() & BR_USING_CENTERED_FONT_BASELINE) {
       ascent = nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight);
     } else {
-      fm->GetMaxAscent(ascent);
-      ascent += GetUsedBorderAndPadding().top;
+      ascent = fm->MaxAscent() + GetUsedBorderAndPadding().top;
     }
   }
   return NS_MIN(mRect.height, ascent);
 }
 
 nsIFrame::ContentOffsets BRFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint)
 {
   ContentOffsets offsets;
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -56,17 +56,16 @@
 #include "nsLineLayout.h"
 #include "nsPlaceholderFrame.h"
 #include "nsStyleConsts.h"
 #include "nsFrameManager.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsStyleContext.h"
 #include "nsIView.h"
-#include "nsIFontMetrics.h"
 #include "nsHTMLParts.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMEvent.h"
 #include "nsGenericHTMLElement.h"
 #include "prprf.h"
 #include "nsStyleChangeList.h"
 #include "nsFrameSelection.h"
 #include "nsFloatManager.h"
@@ -565,17 +564,17 @@ nsBlockFrame::GetCaretBaseline() const
 
   if (!mLines.empty()) {
     const_line_iterator line = begin_lines();
     const nsLineBox* firstLine = line;
     if (firstLine->GetChildCount()) {
       return bp.top + firstLine->mFirstChild->GetCaretBaseline();
     }
   }
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   return nsLayoutUtils::GetCenteredFontBaseline(fm, nsHTMLReflowState::
       CalcLineHeight(GetStyleContext(), contentRect.height)) +
     bp.top;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Child frame enumeration
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -37,17 +37,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* class that a parent frame uses to reflow a block frame */
 
 #include "nsBlockReflowContext.h"
 #include "nsLineLayout.h"
 #include "nsFloatManager.h"
-#include "nsIFontMetrics.h"
 #include "nsPresContext.h"
 #include "nsFrameManager.h"
 #include "nsIContent.h"
 #include "nsStyleContext.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsBlockFrame.h"
 #include "nsLineBox.h"
 #include "nsIDOMHTMLTableCellElement.h"
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -37,17 +37,16 @@
 
 /* rendering object for list-item bullets */
 
 #include "nsCOMPtr.h"
 #include "nsBulletFrame.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLParts.h"
 #include "nsHTMLContainerFrame.h"
-#include "nsIFontMetrics.h"
 #include "nsGenericHTMLElement.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
 #include "nsRenderingContext.h"
 #include "nsILoadGroup.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
@@ -285,17 +284,17 @@ nsBulletFrame::PaintBullet(nsRenderingCo
         nsLayoutUtils::DrawSingleImage(&aRenderingContext,
              imageCon, nsLayoutUtils::GetGraphicsFilterForFrame(this),
              dest + aPt, aDirtyRect, imgIContainer::FLAG_NONE);
         return;
       }
     }
   }
 
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   aRenderingContext.SetColor(GetVisitedDependentColor(eCSSProperty_color));
 
   mTextIsRTL = PR_FALSE;
 
   nsAutoString text;
   switch (listStyleType) {
   case NS_STYLE_LIST_STYLE_NONE:
     break;
@@ -384,18 +383,17 @@ nsBulletFrame::PaintBullet(nsRenderingCo
   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
     GetListItemText(*myList, text);
     aRenderingContext.SetFont(fm);
-    nscoord ascent;
-    fm->GetMaxAscent(ascent);
+    nscoord ascent = fm->MaxAscent();
     aRenderingContext.SetTextRunRTL(mTextIsRTL);
     aRenderingContext.DrawString(text, mPadding.left + aPt.x,
                                  mPadding.top + aPt.y + ascent);
     break;
   }
 }
 
 PRInt32
@@ -1343,31 +1341,31 @@ nsBulletFrame::GetDesiredSize(nsPresCont
   // If we're getting our desired size and don't have an image, reset
   // mIntrinsicSize to (0,0).  Otherwise, if we used to have an image, it
   // changed, and the new one is coming in, but we're reflowing before it's
   // fully there, we'll end up with mIntrinsicSize not matching our size, but
   // won't trigger a reflow in OnStartContainer (because mIntrinsicSize will
   // match the image size).
   mIntrinsicSize.SizeTo(0, 0);
 
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   nscoord bulletSize;
 
   nsAutoString text;
   switch (myList->mListStyleType) {
     case NS_STYLE_LIST_STYLE_NONE:
       aMetrics.width = 0;
       aMetrics.ascent = aMetrics.height = 0;
       break;
 
     case NS_STYLE_LIST_STYLE_DISC:
     case NS_STYLE_LIST_STYLE_CIRCLE:
     case NS_STYLE_LIST_STYLE_SQUARE:
-      fm->GetMaxAscent(ascent);
+      ascent = fm->MaxAscent();
       bulletSize = NS_MAX(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
                           NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
       mPadding.bottom = NSToCoordRound(float(ascent) / 8.0f);
       aMetrics.width = mPadding.right + bulletSize;
       aMetrics.ascent = aMetrics.height = mPadding.bottom + bulletSize;
       break;
 
     default:
@@ -1418,21 +1416,23 @@ nsBulletFrame::GetDesiredSize(nsPresCont
     case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
     case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
       GetListItemText(*myList, text);
-      fm->GetHeight(aMetrics.height);
+      aMetrics.height = fm->MaxHeight();
       aRenderingContext->SetFont(fm);
-      aMetrics.width = nsLayoutUtils::GetStringWidth(this, aRenderingContext, text.get(), text.Length());
+      aMetrics.width =
+        nsLayoutUtils::GetStringWidth(this, aRenderingContext,
+                                      text.get(), text.Length());
       aMetrics.width += mPadding.right;
-      fm->GetMaxAscent(aMetrics.ascent);
+      aMetrics.ascent = fm->MaxAscent();
       break;
   }
 }
 
 NS_IMETHODIMP
 nsBulletFrame::Reflow(nsPresContext* aPresContext,
                       nsHTMLReflowMetrics& aMetrics,
                       const nsHTMLReflowState& aReflowState,
@@ -1587,35 +1587,35 @@ nsBulletFrame::GetLoadGroup(nsPresContex
 
 nscoord
 nsBulletFrame::GetBaseline() const
 {
   nscoord ascent = 0, bottomPadding;
   if (GetStateBits() & BULLET_FRAME_IMAGE_LOADING) {
     ascent = GetRect().height;
   } else {
-    nsCOMPtr<nsIFontMetrics> fm;
+    nsRefPtr<nsFontMetrics> fm;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
     const nsStyleList* myList = GetStyleList();
     switch (myList->mListStyleType) {
       case NS_STYLE_LIST_STYLE_NONE:
         break;
 
       case NS_STYLE_LIST_STYLE_DISC:
       case NS_STYLE_LIST_STYLE_CIRCLE:
       case NS_STYLE_LIST_STYLE_SQUARE:
-        fm->GetMaxAscent(ascent);
+        ascent = fm->MaxAscent();
         bottomPadding = NSToCoordRound(float(ascent) / 8.0f);
         ascent = NS_MAX(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
                         NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
         ascent += bottomPadding;
         break;
 
       default:
-        fm->GetMaxAscent(ascent);
+        ascent = fm->MaxAscent();
         break;
     }
   }
   return ascent + GetUsedBorderAndPadding().top;
 }
 
 
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -46,17 +46,17 @@
 #include "nsIView.h"
 #include "nsIScrollable.h"
 #include "nsIViewManager.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsGfxScrollFrame.h"
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDocument.h"
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsIDocumentObserver.h"
 #include "nsIDocument.h"
 #include "nsBoxLayoutState.h"
 #include "nsINodeInfo.h"
 #include "nsIScrollbarFrame.h"
 #include "nsIScrollbarMediator.h"
 #include "nsITextControlFrame.h"
 #include "nsIDOMHTMLTextAreaElement.h"
@@ -2197,21 +2197,21 @@ nsGfxScrollFrameInner::ScrollBy(nsIntPoi
   }
 }
 
 nsSize
 nsGfxScrollFrameInner::GetLineScrollAmount() const
 {
   const nsStyleFont* font = mOuter->GetStyleFont();
   const nsFont& f = font->mFont;
-  nsCOMPtr<nsIFontMetrics> fm = mOuter->PresContext()->GetMetricsFor(f);
+  nsRefPtr<nsFontMetrics> fm = mOuter->PresContext()->GetMetricsFor(f);
   NS_ASSERTION(fm, "FontMetrics is null, assuming fontHeight == 1 appunit");
   nscoord fontHeight = 1;
   if (fm) {
-    fm->GetHeight(fontHeight);
+    fontHeight = fm->MaxHeight();
   }
 
   return nsSize(fontHeight, fontHeight);
 }
 
 nsSize
 nsGfxScrollFrameInner::GetPageScrollAmount() const
 {
--- a/layout/generic/nsHTMLContainerFrame.cpp
+++ b/layout/generic/nsHTMLContainerFrame.cpp
@@ -56,18 +56,16 @@
 #include "nsPlaceholderFrame.h"
 #include "nsHTMLParts.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsIDOMEvent.h"
 #include "nsWidgetsCID.h"
 #include "nsCOMPtr.h"
 #include "nsIDeviceContext.h"
-#include "nsIFontMetrics.h"
-#include "nsIThebesFontMetrics.h"
 #include "gfxFont.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsDisplayList.h"
 #include "nsBlockFrame.h"
 #include "nsLineBox.h"
 #include "nsDisplayList.h"
 #include "nsCSSRendering.h"
 
@@ -102,20 +100,19 @@ private:
   PRUint8    mDecoration;
   PRUint8    mStyle;
 };
 
 void
 nsDisplayTextDecoration::Paint(nsDisplayListBuilder* aBuilder,
                                nsRenderingContext* aCtx)
 {
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm));
-  nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm.get());
-  gfxFontGroup* fontGroup = tfm->GetThebesFontGroup();
+  gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
   gfxFont* firstFont = fontGroup->GetFontAt(0);
   if (!firstFont)
     return; // OOM
   const gfxFont::Metrics& metrics = firstFont->GetMetrics();
 
   gfxFloat ascent;
   // The ascent of first-letter frame's text may not be the same as the ascent
   // of the font metrics. Because that may use the tight box of the actual
@@ -183,20 +180,19 @@ private:
   PRUint8       mOverlineStyle;
   PRUint8       mStrikeThroughStyle;
 };
 
 void
 nsDisplayTextShadow::Paint(nsDisplayListBuilder* aBuilder,
                            nsRenderingContext* aCtx)
 {
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm));
-  nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm.get());
-  gfxFontGroup* fontGroup = tfm->GetThebesFontGroup();
+  gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
   gfxFont* firstFont = fontGroup->GetFontAt(0);
   if (!firstFont)
     return; // OOM
 
   const gfxFont::Metrics& metrics = firstFont->GetMetrics();
   gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
 
   nsHTMLContainerFrame* f = static_cast<nsHTMLContainerFrame*>(mFrame);
@@ -339,21 +335,20 @@ nsHTMLContainerFrame::DisplayTextDecorat
                                              nsLineBox* aLine)
 {
   if (eCompatibility_NavQuirks == PresContext()->CompatibilityMode())
     return NS_OK;
   if (!IsVisibleForPainting(aBuilder))
     return NS_OK;
 
   // Hide text decorations if we're currently hiding @font-face fallback text
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsresult rv = nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   NS_ENSURE_SUCCESS(rv, rv);
-  nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm.get());
-  if (tfm->GetThebesFontGroup()->ShouldSkipDrawing())
+  if (fm->GetThebesFontGroup()->ShouldSkipDrawing())
     return NS_OK;
 
   // Do standards mode painting of 'text-decoration's: under+overline
   // behind children, line-through in front.  For Quirks mode, see
   // nsTextFrame::PaintTextDecorations.  (See bug 1777.)
   nscolor underColor, overColor, strikeColor;
   PRUint8 underStyle, overStyle, strikeStyle;
   PRUint8 decorations = NS_STYLE_TEXT_DECORATION_NONE;
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -42,17 +42,17 @@
 #include "nsStyleConsts.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsFrame.h"
 #include "nsIContent.h"
 #include "nsGkAtoms.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIDeviceContext.h"
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsBlockFrame.h"
 #include "nsLineBox.h"
 #include "nsImageFrame.h"
 #include "nsTableFrame.h"
 #include "nsTableCellFrame.h"
 #include "nsIServiceManager.h"
 #include "nsIPercentHeightObserver.h"
 #include "nsContentUtils.h"
@@ -2101,26 +2101,25 @@ nsHTMLReflowState::CalculateBlockSideMar
 // If both internal leading and  external leading specified by font itself
 // are zeros, we should compensate this by creating extra (external) leading 
 // in eCompensateLeading mode. This is necessary because without this 
 // compensation, normal line height might looks too tight. 
 
 // For risk management, we use preference to control the behavior, and 
 // eNoExternalLeading is the old behavior.
 static nscoord
-GetNormalLineHeight(nsIFontMetrics* aFontMetrics)
+GetNormalLineHeight(nsFontMetrics* aFontMetrics)
 {
   NS_PRECONDITION(nsnull != aFontMetrics, "no font metrics");
 
   nscoord normalLineHeight;
 
-  nscoord externalLeading, internalLeading, emHeight;
-  aFontMetrics->GetExternalLeading(externalLeading);
-  aFontMetrics->GetInternalLeading(internalLeading);
-  aFontMetrics->GetEmHeight(emHeight);
+  nscoord externalLeading = aFontMetrics->ExternalLeading();
+  nscoord internalLeading = aFontMetrics->InternalLeading();
+  nscoord emHeight = aFontMetrics->EmHeight();
   switch (GetNormalLineHeightCalcControl()) {
   case eIncludeExternalLeading:
     normalLineHeight = emHeight+ internalLeading + externalLeading;
     break;
   case eCompensateLeading:
     if (!internalLeading && !externalLeading)
       normalLineHeight = NSToCoordRound(emHeight * NORMAL_LINE_HEIGHT_FACTOR);
     else
@@ -2155,17 +2154,17 @@ ComputeLineHeight(nsStyleContext* aStyle
   
   if (lhCoord.GetUnit() == eStyleUnit_Enumerated) {
     NS_ASSERTION(lhCoord.GetIntValue() == NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
                  "bad line-height value");
     if (aBlockHeight != NS_AUTOHEIGHT)
       return aBlockHeight;
   }
 
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext,
                                                getter_AddRefs(fm));
   return GetNormalLineHeight(fm);
 }
 
 nscoord
 nsHTMLReflowState::CalcLineHeight() const
 {
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -62,17 +62,16 @@
 #include "nsIIOService.h"
 #include "nsIURL.h"
 #include "nsILoadGroup.h"
 #include "nsISupportsPriority.h"
 #include "nsIServiceManager.h"
 #include "nsNetUtil.h"
 #include "nsHTMLContainerFrame.h"
 #include "prprf.h"
-#include "nsIFontMetrics.h"
 #include "nsCSSRendering.h"
 #include "nsILink.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDeviceContext.h"
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsIDOMHTMLMapElement.h"
@@ -970,22 +969,21 @@ nsImageFrame::DisplayAltText(nsPresConte
                              const nsString&      aAltText,
                              const nsRect&        aRect)
 {
   // Set font and color
   aRenderingContext.SetColor(GetStyleColor()->mColor);
   nsLayoutUtils::SetFontFromStyle(&aRenderingContext, mStyleContext);
 
   // Format the text to display within the formatting rect
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
-  nscoord maxAscent, maxDescent, height;
-  fm->GetMaxAscent(maxAscent);
-  fm->GetMaxDescent(maxDescent);
-  fm->GetHeight(height);
+  nscoord maxAscent = fm->MaxAscent();
+  nscoord maxDescent = fm->MaxDescent();
+  nscoord height = fm->MaxHeight();
 
   // XXX It would be nice if there was a way to have the font metrics tell
   // use where to break the text given a maximum width. At a minimum we need
   // to be able to get the break character...
   const PRUnichar* str = aAltText.get();
   PRInt32          strLen = aAltText.Length();
   nscoord          y = aRect.y;
 
@@ -1120,17 +1118,16 @@ nsImageFrame::DisplayAltFeedback(nsRende
         nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
         imgIContainer::FLAG_NONE);
       iconUsed = PR_TRUE;
     }
 
     // if we could not draw the icon, flag that we're waiting for it and
     // just draw some graffiti in the mean time
     if (!iconUsed) {
-      nscolor oldColor;
       nscoord iconXPos = (vis->mDirection ==   NS_STYLE_DIRECTION_RTL) ?
                          inner.XMost() - size : inner.x;
       nscoord twoPX = nsPresContext::CSSPixelsToAppUnits(2);
       aRenderingContext.DrawRect(iconXPos, inner.y,size,size);
       aRenderingContext.PushState();
       aRenderingContext.SetColor(NS_RGB(0xFF,0,0));
       aRenderingContext.FillEllipse(size/2 + iconXPos, size/2 + inner.y,
                                     size/2 - twoPX, size/2 - twoPX);
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -42,17 +42,16 @@
 #include "nsBlockFrame.h"
 #include "nsPlaceholderFrame.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLParts.h"
 #include "nsStyleContext.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 #include "nsAbsoluteContainingBlock.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsAutoPtr.h"
 #include "nsFrameManager.h"
 #ifdef ACCESSIBILITY
 #include "nsIServiceManager.h"
 #include "nsAccessibilityService.h"
 #endif
@@ -639,31 +638,31 @@ nsInlineFrame::ReflowFrames(nsPresContex
   if (NS_FRAME_IS_COMPLETE(aStatus) &&
       !GetLastInFlow()->GetNextContinuation() &&
       !nsLayoutUtils::FrameIsNonLastInIBSplit(this)) {
     aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.right
                           : aReflowState.mComputedBorderPadding.left;
   }
 
   nsLayoutUtils::SetFontFromStyle(aReflowState.rendContext, mStyleContext);
-  nsIFontMetrics* fm = aReflowState.rendContext->FontMetrics();
+  nsFontMetrics* fm = aReflowState.rendContext->FontMetrics();
 
   if (fm) {
     // Compute final height of the frame.
     //
     // Do things the standard css2 way -- though it's hard to find it
     // in the css2 spec! It's actually found in the css1 spec section
     // 4.4 (you will have to read between the lines to really see
     // it).
     //
     // The height of our box is the sum of our font size plus the top
     // and bottom border and padding. The height of children do not
     // affect our height.
-    fm->GetMaxAscent(aMetrics.ascent);
-    fm->GetHeight(aMetrics.height);
+    aMetrics.ascent = fm->MaxAscent();
+    aMetrics.height = fm->MaxHeight();
   } else {
     NS_WARNING("Cannot get font metrics - defaulting sizes to 0");
     aMetrics.ascent = aMetrics.height = 0;
   }
   aMetrics.ascent += aReflowState.mComputedBorderPadding.top;
   aMetrics.height += aReflowState.mComputedBorderPadding.top +
     aReflowState.mComputedBorderPadding.bottom;
 
@@ -909,19 +908,20 @@ nsInlineFrame::GetSkipSides() const
 
   return skip;
 }
 
 nscoord
 nsInlineFrame::GetBaseline() const
 {
   nscoord ascent = 0;
-  nsCOMPtr<nsIFontMetrics> fm;
-  if (NS_SUCCEEDED(nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)))) {
-    fm->GetMaxAscent(ascent);
+  nsRefPtr<nsFontMetrics> fm;
+  nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
+  if (fm) {
+    ascent = fm->MaxAscent();
   }
   return NS_MIN(mRect.height, ascent + GetUsedBorderAndPadding().top);
 }
 
 #ifdef ACCESSIBILITY
 already_AddRefed<nsAccessible>
 nsInlineFrame::CreateAccessible()
 {
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -50,18 +50,16 @@
 #include "nsLineLayout.h"
 #include "nsBlockFrame.h"
 #include "nsInlineFrame.h"
 #include "nsStyleConsts.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsFloatManager.h"
 #include "nsStyleContext.h"
 #include "nsPresContext.h"
-#include "nsIFontMetrics.h"
-#include "nsIThebesFontMetrics.h"
 #include "nsRenderingContext.h"
 #include "nsGkAtoms.h"
 #include "nsPlaceholderFrame.h"
 #include "nsIDocument.h"
 #include "nsIHTMLDocument.h"
 #include "nsIContent.h"
 #include "nsTextFragment.h"
 #include "nsBidiUtils.h"
@@ -1558,17 +1556,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
   // Get parent frame info
   PerFrameData* spanFramePFD = psd->mFrame;
   nsIFrame* spanFrame = spanFramePFD->mFrame;
 
   // Get the parent frame's font for all of the frames in this span
   nsStyleContext* styleContext = spanFrame->GetStyleContext();
   nsRenderingContext* rc = mBlockReflowState->rendContext;
   nsLayoutUtils::SetFontFromStyle(mBlockReflowState->rendContext, styleContext);
-  nsIFontMetrics* fm = rc->FontMetrics();
+  nsFontMetrics* fm = rc->FontMetrics();
 
   PRBool preMode = mStyleText->WhiteSpaceIsSignificant();
 
   // See if the span is an empty continuation. It's an empty continuation iff:
   // - it has a prev-in-flow
   // - it has no next in flow
   // - it's zero sized
   PRBool emptyContinuation = psd != mRootSpan &&
@@ -1807,32 +1805,30 @@ nsLineLayout::VerticalAlignFrames(PerSpa
         }
 
         case NS_STYLE_VERTICAL_ALIGN_SUB:
         {
           // Lower the baseline of the box to the subscript offset
           // of the parent's box. This is identical to the baseline
           // alignment except for the addition of the subscript
           // offset to the baseline Y.
-          nscoord parentSubscript;
-          fm->GetSubscriptOffset(parentSubscript);
+          nscoord parentSubscript = fm->SubscriptOffset();
           nscoord revisedBaselineY = baselineY + parentSubscript;
           pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
           pfd->mVerticalAlign = VALIGN_OTHER;
           break;
         }
 
         case NS_STYLE_VERTICAL_ALIGN_SUPER:
         {
           // Raise the baseline of the box to the superscript offset
           // of the parent's box. This is identical to the baseline
           // alignment except for the subtraction of the superscript
           // offset to the baseline Y.
-          nscoord parentSuperscript;
-          fm->GetSuperscriptOffset(parentSuperscript);
+          nscoord parentSuperscript = fm->SuperscriptOffset();
           nscoord revisedBaselineY = baselineY - parentSuperscript;
           pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
           pfd->mVerticalAlign = VALIGN_OTHER;
           break;
         }
 
         case NS_STYLE_VERTICAL_ALIGN_TOP:
         {
@@ -1863,53 +1859,50 @@ nsLineLayout::VerticalAlignFrames(PerSpa
           }
           break;
         }
 
         case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
         {
           // Align the midpoint of the frame with 1/2 the parents
           // x-height above the baseline.
-          nscoord parentXHeight;
-          fm->GetXHeight(parentXHeight);
+          nscoord parentXHeight = fm->XHeight();
           if (frameSpan) {
             pfd->mBounds.y = baselineY -
               (parentXHeight + pfd->mBounds.height)/2;
           }
           else {
             pfd->mBounds.y = baselineY - (parentXHeight + logicalHeight)/2 +
               pfd->mMargin.top;
           }
           pfd->mVerticalAlign = VALIGN_OTHER;
           break;
         }
 
         case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
         {
           // The top of the logical box is aligned with the top of
           // the parent element's text.
-          nscoord parentAscent;
-          fm->GetMaxAscent(parentAscent);
+          nscoord parentAscent = fm->MaxAscent();
           if (frameSpan) {
             pfd->mBounds.y = baselineY - parentAscent -
               pfd->mBorderPadding.top + frameSpan->mTopLeading;
           }
           else {
             pfd->mBounds.y = baselineY - parentAscent + pfd->mMargin.top;
           }
           pfd->mVerticalAlign = VALIGN_OTHER;
           break;
         }
 
         case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
         {
           // The bottom of the logical box is aligned with the
           // bottom of the parent elements text.
-          nscoord parentDescent;
-          fm->GetMaxDescent(parentDescent);
+          nscoord parentDescent = fm->MaxDescent();
           if (frameSpan) {
             pfd->mBounds.y = baselineY + parentDescent -
               pfd->mBounds.height + pfd->mBorderPadding.bottom -
               frameSpan->mBottomLeading;
           }
           else {
             pfd->mBounds.y = baselineY + parentDescent -
               pfd->mBounds.height - pfd->mMargin.bottom;
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -48,17 +48,16 @@
 #include "nsDisplayList.h"
 #include "nsLayoutUtils.h" // for function BinarySearchForPosition
 #include "nsCSSRendering.h"
 #include "nsSimplePageSequence.h" // for nsSharedPageData
 #include "nsTextFormatter.h" // for page number localization formatting
 #ifdef IBMBIDI
 #include "nsBidiUtils.h"
 #endif
-#include "nsIFontMetrics.h"
 #include "nsIPrintSettings.h"
 #include "nsRegion.h"
 
 #include "prlog.h"
 #ifdef PR_LOGGING 
 extern PRLogModuleInfo * kLayoutPrintingLogMod;
 #define PR_PL(_p1)  PR_LOG(kLayoutPrintingLogMod, PR_LOG_DEBUG, _p1)
 #else
@@ -506,28 +505,28 @@ nsPageFrame::PaintHeaderFooter(nsRenderi
   }
 
   nsRect rect(aPt.x, aPt.y, mRect.width - mPD->mShadowSize.width,
               mRect.height - mPD->mShadowSize.height);
 
   aRenderingContext.SetColor(NS_RGB(0,0,0));
 
   // Get the FontMetrics to determine width.height of strings
-  nsCOMPtr<nsIFontMetrics> fontMet;
+  nsRefPtr<nsFontMetrics> fontMet;
   pc->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont,
                                      pc->GetUserFontSet(),
                                      *getter_AddRefs(fontMet));
 
   aRenderingContext.SetFont(fontMet);
 
   nscoord ascent = 0;
   nscoord visibleHeight = 0;
   if (fontMet) {
-    fontMet->GetHeight(visibleHeight);
-    fontMet->GetMaxAscent(ascent);
+    visibleHeight = fontMet->MaxHeight();
+    ascent = fontMet->MaxAscent();
   }
 
   // print document headers and footers
   nsXPIDLString headerLeft, headerCenter, headerRight;
   mPD->mPrintSettings->GetHeaderStrLeft(getter_Copies(headerLeft));
   mPD->mPrintSettings->GetHeaderStrCenter(getter_Copies(headerCenter));
   mPD->mPrintSettings->GetHeaderStrRight(getter_Copies(headerRight));
   DrawHeaderFooter(aRenderingContext, eHeader,
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -38,17 +38,16 @@
 #include "nsReadableUtils.h"
 #include "nsSimplePageSequence.h"
 #include "nsPresContext.h"
 #include "gfxContext.h"
 #include "nsRenderingContext.h"
 #include "nsGkAtoms.h"
 #include "nsIDeviceContext.h"
 #include "nsIPresShell.h"
-#include "nsIFontMetrics.h"
 #include "nsIPrintSettings.h"
 #include "nsPageFrame.h"
 #include "nsStyleConsts.h"
 #include "nsRegion.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -58,17 +58,16 @@
 #include "nsLineLayout.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsStyleConsts.h"
 #include "nsStyleContext.h"
 #include "nsCoord.h"
-#include "nsIFontMetrics.h"
 #include "nsRenderingContext.h"
 #include "nsIPresShell.h"
 #include "nsITimer.h"
 #include "nsTArray.h"
 #include "nsIDOMText.h"
 #include "nsIDocument.h"
 #include "nsIDeviceContext.h"
 #include "nsCSSPseudoElements.h"
@@ -105,17 +104,16 @@
 #include "nsIServiceManager.h"
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 #include "nsAutoPtr.h"
 
 #include "nsBidiUtils.h"
 
-#include "nsIThebesFontMetrics.h"
 #include "gfxFont.h"
 #include "gfxContext.h"
 #include "gfxTextRunWordCache.h"
 #include "gfxImageSurface.h"
 #include "mozilla/dom/Element.h"
 
 #ifdef NS_DEBUG
 #undef NOISY_BLINK
@@ -1577,38 +1575,36 @@ BuildTextRunsScanner::GetNextBreakBefore
 static PRUint32
 GetSpacingFlags(nscoord spacing)
 {
   return spacing ? gfxTextRunFactory::TEXT_ENABLE_SPACING : 0;
 }
 
 static gfxFontGroup*
 GetFontGroupForFrame(nsIFrame* aFrame,
-                     nsIFontMetrics** aOutFontMetrics = nsnull)
+                     nsFontMetrics** aOutFontMetrics = nsnull)
 {
   if (aOutFontMetrics)
     *aOutFontMetrics = nsnull;
 
-  nsCOMPtr<nsIFontMetrics> metrics;
+  nsRefPtr<nsFontMetrics> metrics;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(metrics));
 
   if (!metrics)
     return nsnull;
 
-  nsIFontMetrics* metricsRaw = metrics;
   if (aOutFontMetrics) {
-    *aOutFontMetrics = metricsRaw;
+    *aOutFontMetrics = metrics;
     NS_ADDREF(*aOutFontMetrics);
   }
-  nsIThebesFontMetrics* fm = static_cast<nsIThebesFontMetrics*>(metricsRaw);
-  // XXX this is a bit bogus, we're releasing 'metrics' so the returned font-group
-  // might actually be torn down, although because of the way the device context
-  // caches font metrics, this seems to not actually happen. But we should fix
-  // this.
-  return fm->GetThebesFontGroup();
+  // XXX this is a bit bogus, we're releasing 'metrics' so the
+  // returned font-group might actually be torn down, although because
+  // of the way the device context caches font metrics, this seems to
+  // not actually happen. But we should fix this.
+  return metrics->GetThebesFontGroup();
 }
 
 static already_AddRefed<gfxContext>
 GetReferenceRenderingContext(nsTextFrame* aTextFrame, nsRenderingContext* aRC)
 {
   nsRefPtr<nsRenderingContext> tmp = aRC;
   if (!tmp) {
     tmp = aTextFrame->PresContext()->PresShell()->GetReferenceRenderingContext();
@@ -2488,17 +2484,17 @@ public:
   const nsTextFragment* GetFragment() { return mFrag; }
 
   gfxFontGroup* GetFontGroup() {
     if (!mFontGroup)
       InitFontGroupAndFontMetrics();
     return mFontGroup;
   }
 
-  nsIFontMetrics* GetFontMetrics() {
+  nsFontMetrics* GetFontMetrics() {
     if (!mFontMetrics)
       InitFontGroupAndFontMetrics();
     return mFontMetrics;
   }
 
   void CalcTabWidths(PRUint32 aTransformedStart, PRUint32 aTransformedLength);
 
   const gfxSkipCharsIterator& GetEndHint() { return mTempIterator; }
@@ -2507,17 +2503,17 @@ protected:
   void SetupJustificationSpacing();
 
   void InitFontGroupAndFontMetrics() {
     mFontGroup = GetFontGroupForFrame(mFrame, getter_AddRefs(mFontMetrics));
   }
 
   gfxTextRun*           mTextRun;
   gfxFontGroup*         mFontGroup;
-  nsCOMPtr<nsIFontMetrics> mFontMetrics;
+  nsRefPtr<nsFontMetrics> mFontMetrics;
   const nsStyleText*    mTextStyle;
   const nsTextFragment* mFrag;
   nsIFrame*             mLineContainer;
   nsTextFrame*          mFrame;
   gfxSkipCharsIterator  mStart;  // Offset in original and transformed string
   gfxSkipCharsIterator  mTempIterator;
   
   // Either null, or pointing to the frame's tabWidthProperty.
@@ -4337,20 +4333,19 @@ nsTextFrame::UnionTextDecorationOverflow
   // Text-shadow overflows
   nsRect shadowRect =
     nsLayoutUtils::GetTextShadowRectsUnion(*aVisualOverflowRect, this);
   aVisualOverflowRect->UnionRect(*aVisualOverflowRect, shadowRect);
 
   if (IsFloatingFirstLetterChild()) {
     // The underline/overline drawable area must be contained in the overflow
     // rect when this is in floating first letter frame at *both* modes.
-    nscoord fontAscent, fontHeight;
-    nsIFontMetrics* fm = aProvider.GetFontMetrics();
-    fm->GetMaxAscent(fontAscent);
-    fm->GetMaxHeight(fontHeight);
+    nsFontMetrics* fm = aProvider.GetFontMetrics();
+    nscoord fontAscent = fm->MaxAscent();
+    nscoord fontHeight = fm->MaxHeight();
     nsRect fontRect(0, mAscent - fontAscent, GetSize().width, fontHeight);
     aVisualOverflowRect->UnionRect(*aVisualOverflowRect, fontRect);
   }
 
   // When this frame is not selected, the text-decoration area must be in
   // frame bounds.
   nsRect decorationRect;
   if (!(GetStateBits() & NS_FRAME_SELECTED_CONTENT) ||
@@ -5291,20 +5286,19 @@ PRBool
 nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
                                            nsRect& aRect)
 {
   if (aRect.IsEmpty())
     return PR_FALSE;
 
   nsRect givenRect = aRect;
 
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
-  nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm.get());
-  gfxFontGroup* fontGroup = tfm->GetThebesFontGroup();
+  gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
   gfxFont* firstFont = fontGroup->GetFontAt(0);
   if (!firstFont)
     return PR_FALSE; // OOM
   const gfxFont::Metrics& metrics = firstFont->GetMetrics();
   gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
   gfxFloat ascent = aPresContext->AppUnitsToGfxUnits(mAscent);
   gfxFloat descentLimit =
     ComputeDescentLimitForSelectionUnderline(aPresContext, this, metrics);
@@ -6784,23 +6778,20 @@ nsTextFrame::ReflowText(nsLineLayout& aL
                                   &provider, !aLineLayout.LineIsBreakable(),
                                   canTrimTrailingWhitespace ? &trimmedWidth : nsnull,
                                   &textMetrics, boundingBoxType, ctx,
                                   &usedHyphenation, &transformedLastBreak,
                                   textStyle->WordCanWrap(), &breakPriority);
   if (!length && !textMetrics.mAscent && !textMetrics.mDescent) {
     // If we're measuring a zero-length piece of text, update
     // the height manually.
-    nsIFontMetrics* fm = provider.GetFontMetrics();
+    nsFontMetrics* fm = provider.GetFontMetrics();
     if (fm) {
-      nscoord ascent, descent;
-      fm->GetMaxAscent(ascent);
-      fm->GetMaxDescent(descent);
-      textMetrics.mAscent = gfxFloat(ascent);
-      textMetrics.mDescent = gfxFloat(descent);
+      textMetrics.mAscent = gfxFloat(fm->MaxAscent());
+      textMetrics.mDescent = gfxFloat(fm->MaxDescent());
     }
   }
   // The "end" iterator points to the first character after the string mapped
   // by this frame. Basically, its original-string offset is offset+charsFit
   // after we've computed charsFit.
   gfxSkipCharsIterator end(provider.GetEndHint());
   end.SetSkippedOffset(transformedOffset + transformedCharsFit);
   PRInt32 charsFit = end.GetOriginalOffset() - offset;
@@ -6894,21 +6885,20 @@ nsTextFrame::ReflowText(nsLineLayout& aL
     aMetrics.height = 0;
   } else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) {
     // Use actual text metrics for floating first letter frame.
     aMetrics.ascent = NSToCoordCeil(textMetrics.mAscent);
     aMetrics.height = aMetrics.ascent + NSToCoordCeil(textMetrics.mDescent);
   } else {
     // Otherwise, ascent should contain the overline drawable area.
     // And also descent should contain the underline drawable area.
-    // nsIFontMetrics::GetMaxAscent/GetMaxDescent contains them.
-    nscoord fontAscent, fontDescent;
-    nsIFontMetrics* fm = provider.GetFontMetrics();
-    fm->GetMaxAscent(fontAscent);
-    fm->GetMaxDescent(fontDescent);
+    // nsFontMetrics::GetMaxAscent/GetMaxDescent contains them.
+    nsFontMetrics* fm = provider.GetFontMetrics();
+    nscoord fontAscent = fm->MaxAscent();
+    nscoord fontDescent = fm->MaxDescent();
     aMetrics.ascent = NS_MAX(NSToCoordCeil(textMetrics.mAscent), fontAscent);
     nscoord descent = NS_MAX(NSToCoordCeil(textMetrics.mDescent), fontDescent);
     aMetrics.height = aMetrics.ascent + descent;
   }
 
   NS_ASSERTION(aMetrics.ascent >= 0, "Negative ascent???");
   NS_ASSERTION(aMetrics.height - aMetrics.ascent >= 0, "Negative descent???");
 
--- a/layout/mathml/mathfont.properties
+++ b/layout/mathml/mathfont.properties
@@ -32,25 +32,18 @@
 # 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 *****
 
-##LOCALIZATION NOTE:
-# These are used to display an alert box to warn users when MathML fonts
-# are not installed on their system. The list of missing fonts will be
-# substituted in argument %1$S (see a screenshot in bug 128139).
-mathfont_missing_dialog_title = Missing MathML Fonts
-mathfont_missing_dialog_message = To properly display the MathML on this page you need to install the following fonts:\n%1$S.\n\n\nFor further information see:\nhttp://www.mozilla.org/projects/mathml/fonts
-
-##LOCALIZATION NOTE:
-# Do not translate anything else in this file
+#  LOCALIZATION NOTE: FILE
+#  Do not translate anything in this file
 
 # List of fonts that have corresponding properties files containing special
 # glyph tables for stretching MathML characters.  See the documentation at the
 # end of this file for details on the setup of the property file associated to
 # each font.  Do not include the Unicode table in this list.
 
 %ifdef XP_WIN
 font.mathfont-glyph-tables = STIXNonUnicode, STIXSizeOneSym, STIXSize1, Standard Symbols L, Symbol
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -43,36 +43,32 @@
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsRenderingContext.h"
 #include "gfxPlatform.h"
-#include "nsIFontMetrics.h"
 
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIComponentManager.h"
 #include "nsIPersistentProperties2.h"
 #include "nsIServiceManager.h"
 #include "nsIObserverService.h"
 #include "nsIObserver.h"
 #include "nsNetUtil.h"
 
 #include "nsILookAndFeel.h"
 #include "nsIDeviceContext.h"
 #include "nsCSSRendering.h"
 #include "prprf.h"         // For PR_snprintf()
 
-#if ALERT_MISSING_FONTS
-#include "nsIStringBundle.h"
-#endif
 #include "nsDisplayList.h"
 
 #include "nsMathMLOperators.h"
 #include "nsMathMLChar.h"
 
 //#define SHOW_BORDERS 1
 //#define NOISY_SEARCH 1
 
@@ -127,57 +123,16 @@ typedef enum {eExtension_base, eExtensio
 
 #define NS_TABLE_TYPE_UNICODE       0
 #define NS_TABLE_TYPE_GLYPH_INDEX   1
 
 #define NS_TABLE_STATE_ERROR       -1
 #define NS_TABLE_STATE_EMPTY        0
 #define NS_TABLE_STATE_READY        1
 
-// helper to check if a font is installed
-static PRBool
-CheckFontExistence(nsPresContext* aPresContext, const nsString& aFontName)
-{
-  PRBool aliased;
-  nsAutoString localName;
-  nsIDeviceContext *deviceContext = aPresContext->DeviceContext();
-  deviceContext->GetLocalFontName(aFontName, localName, aliased);
-  // XXXkt CheckFontExistence always returns NS_OK.
-  PRBool rv = (aliased || (NS_OK == deviceContext->CheckFontExistence(localName)));
-  // (see bug 35824 for comments about the aliased localName)
-  return rv;
-}
-
-#if ALERT_MISSING_FONTS
-// alert the user if some of the needed MathML fonts are not installed.
-// it is non-modal (i.e., it doesn't wait for input from the user)
-static void
-AlertMissingFonts(nsString& aMissingFonts)
-{
-  nsCOMPtr<nsIStringBundleService> sbs =
-    mozilla::services::GetStringBundleService();
-  if (!sbs)
-    return;
-
-  nsCOMPtr<nsIStringBundle> sb;
-  sbs->CreateBundle("resource://gre/res/fonts/mathfont.properties", getter_AddRefs(sb));
-  if (!sb)
-    return;
-
-  nsXPIDLString title, message;
-  const PRUnichar* strings[] = { aMissingFonts.get() };
-  sb->GetStringFromName(NS_LITERAL_STRING("mathfont_missing_dialog_title").get(), getter_Copies(title));
-  sb->FormatStringFromName(NS_LITERAL_STRING("mathfont_missing_dialog_message").get(),
-                           strings, 1, getter_Copies(message));
-
-  // XXX Bug 309090 - could show a notification bar here. Bug 563114 removed
-  // the nsINonBlockingAlertService interface that was previously used here.
-}
-#endif
-
 // helper to trim off comments from data in a MathFont Property File
 static void
 Clean(nsString& aValue)
 {
   // chop the trailing # comment portion if any ...
   PRInt32 comment = aValue.RFindChar('#');
   if (comment > 0) aValue.Truncate(comment);
   aValue.CompressWhitespace();
@@ -398,17 +353,17 @@ nsGlyphTable::ElementAt(nsPresContext* a
         ++i;
         font = value[i] - '0';
         ++i;
         if (font >= mFontName.Length()) {
           NS_ERROR("Nonexistent font referenced in glyph table");
           return kNullGlyph;
         }
         // The char cannot be handled if this font is not installed
-        if (!mFontName[font].Length() || !CheckFontExistence(aPresContext, mFontName[font])) {
+        if (!mFontName[font].Length()) {
           return kNullGlyph;
         }
       }
       buffer.Append(code);
       buffer.Append(font);
       ++j;
     }
     // update our cache with the new settings
@@ -711,46 +666,20 @@ GetFontExtensionPref(nsIPrefBranch* aPre
   NS_ConvertUTF16toUTF8 tmp(&aChar, 1);
   alternateKey.Append(tmp);
   alternateKey.Append(extension);
 
   return GetPrefValue(aPrefBranch, key.get(), aValue) ||
     GetPrefValue(aPrefBranch, alternateKey.get(), aValue);
 }
 
-#if ALERT_MISSING_FONTS
-struct MathFontEnumContext {
-  nsPresContext* mPresContext;
-  nsString*       mMissingFamilyList;
-};
-#endif
 
 static PRBool
 MathFontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
 {
-#if ALERT_MISSING_FONTS
-  // check if the font is missing
-  MathFontEnumContext* context = (MathFontEnumContext*)aData;
-  nsPresContext* presContext = context->mPresContext;
-  nsString* missingFamilyList = context->mMissingFamilyList;
-  if (!CheckFontExistence(presContext, aFamily)) {
-//#ifndef _WIN32
-   // XXX In principle, the mathfont-family list in the mathfont.properties file
-   // is customizable depending on the platform. For now, this is here since there
-   // is no need to alert Linux users about TrueType fonts specific to Windows.
-   if (aFamily.LowerCaseEqualsLiteral("mt extra"))
-     return PR_TRUE; // continue to try other fonts
-//#endif
-    if (!missingFamilyList->IsEmpty()) {
-      missingFamilyList->AppendLiteral(", ");
-    }
-    missingFamilyList->Append(aFamily);
-  }
-#endif
-
   if (!gGlyphTableList->AddGlyphTable(aFamily))
     return PR_FALSE; // stop in low-memory situations
   return PR_TRUE; // don't stop
 }
 
 static nsresult
 InitGlobals(nsPresContext* aPresContext)
 {
@@ -795,31 +724,17 @@ InitGlobals(nsPresContext* aPresContext)
   nsFont font("", 0, 0, 0, 0, 0, 0);
   NS_NAMED_LITERAL_CSTRING(defaultKey, "font.mathfont-glyph-tables");
   rv = mathfontProp->GetStringProperty(defaultKey, font.name);
   if (NS_FAILED(rv)) return rv;
 
   // Parse the font list and append an entry for each family to gGlyphTableList
   nsAutoString missingFamilyList;
 
-#if ALERT_MISSING_FONTS
-  // We don't really need all these fonts, so alerting on some missing is not
-  // right.  The best place to alert would be Stretch when we notice that we
-  // can't get the char we want.  In this way the user would not be alerted
-  // unnecessarily when the document contains only simple math.  The alert
-  // also needs a "don't tell me again box".
-  MathFontEnumContext context = {aPresContext, &missingFamilyList};
-  font.EnumerateFamilies(MathFontEnumCallback, &context);
-  // alert the user if some of the expected fonts are missing
-  if (!missingFamilyList.IsEmpty()) {
-    AlertMissingFonts(missingFamilyList);
-  }
-#else
   font.EnumerateFamilies(MathFontEnumCallback, nsnull);
-#endif
   return rv;
 }
 
 // -----------------------------------------------------------------------------------
 // And now the implementation of nsMathMLChar
 
 nsStyleContext*
 nsMathMLChar::GetStyleContext() const
@@ -2224,17 +2139,16 @@ SnapToDevPixels(const gfxContext* aThebe
 nsresult
 nsMathMLChar::PaintVertically(nsPresContext*      aPresContext,
                               nsRenderingContext& aRenderingContext,
                               nsFont&              aFont,
                               nsStyleContext*      aStyleContext,
                               nsGlyphTable*        aGlyphTable,
                               nsRect&              aRect)
 {
-  nsresult rv = NS_OK;
   // Get the device pixel size in the vertical direction.
   // (This makes no effort to optimize for non-translation transformations.)
   nscoord oneDevPixel = aPresContext->AppUnitsPerDevPixel();
 
   // get metrics data to be re-used later
   PRInt32 i = 0;
   nsGlyphCode ch, chdata[4];
   nsBoundingMetrics bmdata[4];
@@ -2453,17 +2367,16 @@ nsMathMLChar::PaintVertically(nsPresCont
 nsresult
 nsMathMLChar::PaintHorizontally(nsPresContext*      aPresContext,
                                 nsRenderingContext& aRenderingContext,
                                 nsFont&              aFont,
                                 nsStyleContext*      aStyleContext,
                                 nsGlyphTable*        aGlyphTable,
                                 nsRect&              aRect)
 {
-  nsresult rv = NS_OK;
   // Get the device pixel size in the horizontal direction.
   // (This makes no effort to optimize for non-translation transformations.)
   nscoord oneDevPixel = aPresContext->AppUnitsPerDevPixel();
 
   // get metrics data to be re-used later
   PRInt32 i = 0;
   nsGlyphCode ch, chdata[4];
   nsBoundingMetrics bmdata[4];
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -45,17 +45,16 @@
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsINameSpaceManager.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsIDOMText.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsFrameManager.h"
 #include "nsStyleChangeList.h"
 
 #include "nsGkAtoms.h"
 #include "nsMathMLParts.h"
@@ -81,36 +80,33 @@ NS_QUERYFRAME_TAIL_INHERITING(nsHTMLCont
 // =============================================================================
 
 // error handlers
 // provide a feedback to the user when a frame with bad markup can not be rendered
 nsresult
 nsMathMLContainerFrame::ReflowError(nsRenderingContext& aRenderingContext,
                                     nsHTMLReflowMetrics& aDesiredSize)
 {
-  nsresult rv;
-
   // clear all other flags and record that there is an error with this frame
   mEmbellishData.flags = 0;
   mPresentationData.flags = NS_MATHML_ERROR;
 
   ///////////////
   // Set font
   nsLayoutUtils::SetFontFromStyle(&aRenderingContext, GetStyleContext());
 
   // bounding metrics
   nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
   mBoundingMetrics =
     aRenderingContext.GetBoundingMetrics(errorMsg.get(), errorMsg.Length());
 
   // reflow metrics
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
-  fm->GetMaxAscent(aDesiredSize.ascent);
-  nscoord descent;
-  fm->GetMaxDescent(descent);
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
+  aDesiredSize.ascent = fm->MaxAscent();
+  nscoord descent = fm->MaxDescent();
   aDesiredSize.height = aDesiredSize.ascent + descent;
   aDesiredSize.width = mBoundingMetrics.width;
 
   // Also return our bounding metrics
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   return NS_OK;
 }
@@ -138,21 +134,21 @@ void nsDisplayMathMLError::Paint(nsDispl
   // Set color and font ...
   nsLayoutUtils::SetFontFromStyle(aCtx, mFrame->GetStyleContext());
 
   nsPoint pt = ToReferenceFrame();
   aCtx->SetColor(NS_RGB(255,0,0));
   aCtx->FillRect(nsRect(pt, mFrame->GetSize()));
   aCtx->SetColor(NS_RGB(255,255,255));
 
-  nscoord ascent;
-  aCtx->FontMetrics()->GetMaxAscent(ascent);
+  nscoord ascent = aCtx->FontMetrics()->MaxAscent();
 
-  nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
-  aCtx->DrawString(errorMsg.get(), PRUint32(errorMsg.Length()), pt.x, pt.y+ascent);
+  NS_NAMED_LITERAL_STRING(errorMsg, "invalid-markup");
+  aCtx->DrawString(errorMsg.get(), PRUint32(errorMsg.Length()),
+                   pt.x, pt.y+ascent);
 }
 
 /* /////////////
  * nsIMathMLFrame - support methods for stretchy elements
  * =============================================================================
  */
 
 static PRBool
--- a/layout/mathml/nsMathMLForeignFrameWrapper.cpp
+++ b/layout/mathml/nsMathMLForeignFrameWrapper.cpp
@@ -44,17 +44,16 @@
 #include "nsCOMPtr.h"
 #include "nsHTMLParts.h"
 #include "nsFrame.h"
 #include "nsBlockFrame.h"
 #include "nsLineLayout.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLForeignFrameWrapper.h"
 
 NS_QUERYFRAME_HEAD(nsMathMLForeignFrameWrapper)
   NS_QUERYFRAME_ENTRY(nsMathMLFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
 
 nsIFrame*
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -272,49 +272,47 @@ nsMathMLFrame::GetAttribute(nsIContent* 
 
   // recurse all the way up into the <mstyle> hierarchy
   return GetAttribute(aMathMLmstyleFrame->GetContent(),
                       mstyleParentData.mstyle, aAttributeAtom, aValue);
 }
 
 /* static */ void
 nsMathMLFrame::GetRuleThickness(nsRenderingContext& aRenderingContext,
-                                nsIFontMetrics*      aFontMetrics,
+                                nsFontMetrics*      aFontMetrics,
                                 nscoord&             aRuleThickness)
 {
   // get the bounding metrics of the overbar char, the rendering context
   // is assumed to have been set with the font of the current style context
   NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
                Equals(aFontMetrics->Font()),
                "unexpected state");
 
-  nscoord xHeight;
-  aFontMetrics->GetXHeight(xHeight);
+  nscoord xHeight = aFontMetrics->XHeight();
   PRUnichar overBar = 0x00AF;
   nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&overBar, 1);
   aRuleThickness = bm.ascent + bm.descent;
   if (aRuleThickness <= 0 || aRuleThickness >= xHeight) {
     // fall-back to the other version
     GetRuleThickness(aFontMetrics, aRuleThickness);
   }
 }
 
 /* static */ void
 nsMathMLFrame::GetAxisHeight(nsRenderingContext& aRenderingContext,
-                             nsIFontMetrics*      aFontMetrics,
+                             nsFontMetrics*      aFontMetrics,
                              nscoord&             aAxisHeight)
 {
   // get the bounding metrics of the minus sign, the rendering context
   // is assumed to have been set with the font of the current style context
   NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
                Equals(aFontMetrics->Font()),
                "unexpected state");
 
-  nscoord xHeight;
-  aFontMetrics->GetXHeight(xHeight);
+  nscoord xHeight = aFontMetrics->XHeight();
   PRUnichar minus = 0x2212; // not '-', but official Unicode minus sign
   nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&minus, 1);
   aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2;
   if (aAxisHeight <= 0 || aAxisHeight >= xHeight) {
     // fall-back to the other version
     GetAxisHeight(aFontMetrics, aAxisHeight);
   }
 }
@@ -335,20 +333,19 @@ nsMathMLFrame::CalcLength(nsPresContext*
 
   nsCSSUnit unit = aCSSValue.GetUnit();
 
   if (eCSSUnit_EM == unit) {
     const nsStyleFont* font = aStyleContext->GetStyleFont();
     return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size);
   }
   else if (eCSSUnit_XHeight == unit) {
-    nscoord xHeight;
     const nsStyleFont* font = aStyleContext->GetStyleFont();
-    nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font->mFont);
-    fm->GetXHeight(xHeight);
+    nsRefPtr<nsFontMetrics> fm = aPresContext->GetMetricsFor(font->mFont);
+    nscoord xHeight = fm->XHeight();
     return NSToCoordRound(aCSSValue.GetFloatValue() * (float)xHeight);
   }
 
   // MathML doesn't specify other CSS units such as rem or ch
   NS_ERROR("Unsupported unit");
   return 0;
 }
 
--- a/layout/mathml/nsMathMLFrame.h
+++ b/layout/mathml/nsMathMLFrame.h
@@ -36,17 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsMathMLFrame_h___
 #define nsMathMLFrame_h___
 
 #include "nsCOMPtr.h"
 #include "nsPresContext.h"
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsStyleContext.h"
 #include "nsMathMLAtoms.h"
 #include "nsMathMLOperators.h"
 #include "nsIMathMLFrame.h"
 #include "nsFrame.h"
 #include "nsCSSValue.h"
 #include "nsMathMLElement.h"
 
@@ -235,167 +235,158 @@ public:
   }
 
   // helper methods for getting sup/subdrop's from a child
   static void 
   GetSubDropFromChild(nsIFrame*       aChild,
                       nscoord&        aSubDrop) 
   {
     const nsStyleFont* font = aChild->GetStyleFont();
-    nsCOMPtr<nsIFontMetrics> fm = aChild->PresContext()->GetMetricsFor(
+    nsRefPtr<nsFontMetrics> fm = aChild->PresContext()->GetMetricsFor(
                                                               font->mFont);
     GetSubDrop(fm, aSubDrop);
   }
 
   static void 
   GetSupDropFromChild(nsIFrame*       aChild,
                       nscoord&        aSupDrop) 
   {
     const nsStyleFont* font = aChild->GetStyleFont();
-    nsCOMPtr<nsIFontMetrics> fm = aChild->PresContext()->GetMetricsFor(
+    nsRefPtr<nsFontMetrics> fm = aChild->PresContext()->GetMetricsFor(
                                                               font->mFont);
     GetSupDrop(fm, aSupDrop);
   }
 
   static void
   GetSkewCorrectionFromChild(nsIFrame*       aChild,
                              nscoord&        aSkewCorrection) 
   {
     // default is 0
     // individual classes should over-ride this method if necessary
     aSkewCorrection = 0;
   }
 
   // 2 levels of subscript shifts
   static void
-  GetSubScriptShifts(nsIFontMetrics* fm, 
+  GetSubScriptShifts(nsFontMetrics* fm, 
                      nscoord&        aSubScriptShift1, 
                      nscoord&        aSubScriptShift2)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     aSubScriptShift1 = NSToCoordRound(150.000f/430.556f * xHeight);
     aSubScriptShift2 = NSToCoordRound(247.217f/430.556f * xHeight);
   }
 
   // 3 levels of superscript shifts
   static void
-  GetSupScriptShifts(nsIFontMetrics* fm, 
+  GetSupScriptShifts(nsFontMetrics* fm, 
                      nscoord&        aSupScriptShift1, 
                      nscoord&        aSupScriptShift2, 
                      nscoord&        aSupScriptShift3)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     aSupScriptShift1 = NSToCoordRound(412.892f/430.556f * xHeight);
     aSupScriptShift2 = NSToCoordRound(362.892f/430.556f * xHeight);
     aSupScriptShift3 = NSToCoordRound(288.889f/430.556f * xHeight);
   }
 
   // these are TeX specific params not found in ordinary fonts
 
   static void
-  GetSubDrop(nsIFontMetrics* fm,
+  GetSubDrop(nsFontMetrics* fm,
              nscoord&        aSubDrop)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     aSubDrop = NSToCoordRound(50.000f/430.556f * xHeight);
   }
 
   static void
-  GetSupDrop(nsIFontMetrics* fm,
+  GetSupDrop(nsFontMetrics* fm,
              nscoord&        aSupDrop)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     aSupDrop = NSToCoordRound(386.108f/430.556f * xHeight);
   }
 
   static void
-  GetNumeratorShifts(nsIFontMetrics* fm, 
+  GetNumeratorShifts(nsFontMetrics* fm, 
                      nscoord&        numShift1, 
                      nscoord&        numShift2, 
                      nscoord&        numShift3)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     numShift1 = NSToCoordRound(676.508f/430.556f * xHeight);
     numShift2 = NSToCoordRound(393.732f/430.556f * xHeight);
     numShift3 = NSToCoordRound(443.731f/430.556f * xHeight);
   }
 
   static void
-  GetDenominatorShifts(nsIFontMetrics* fm, 
+  GetDenominatorShifts(nsFontMetrics* fm, 
                        nscoord&        denShift1, 
                        nscoord&        denShift2)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     denShift1 = NSToCoordRound(685.951f/430.556f * xHeight);
     denShift2 = NSToCoordRound(344.841f/430.556f * xHeight);
   }
 
   static void
-  GetEmHeight(nsIFontMetrics* fm,
+  GetEmHeight(nsFontMetrics* fm,
               nscoord&        emHeight)
   {
-#if 0 
+#if 0
     // should switch to this API in order to scale with changes of TextZoom
-    fm->GetEmHeight(emHeight);
+    emHeight = fm->EmHeight();
 #else
     emHeight = NSToCoordRound(float(fm->Font().size));
 #endif
   }
 
   static void
-  GetAxisHeight (nsIFontMetrics* fm,
+  GetAxisHeight (nsFontMetrics* fm,
                  nscoord&        axisHeight)
   {
-    fm->GetXHeight (axisHeight);
-    axisHeight = NSToCoordRound(250.000f/430.556f * axisHeight);
+    axisHeight = NSToCoordRound(250.000f/430.556f * fm->XHeight());
   }
 
   static void
-  GetBigOpSpacings(nsIFontMetrics* fm, 
+  GetBigOpSpacings(nsFontMetrics* fm, 
                    nscoord&        bigOpSpacing1,
                    nscoord&        bigOpSpacing2,
                    nscoord&        bigOpSpacing3,
                    nscoord&        bigOpSpacing4,
                    nscoord&        bigOpSpacing5)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     bigOpSpacing1 = NSToCoordRound(111.111f/430.556f * xHeight);
     bigOpSpacing2 = NSToCoordRound(166.667f/430.556f * xHeight);
     bigOpSpacing3 = NSToCoordRound(200.000f/430.556f * xHeight);
     bigOpSpacing4 = NSToCoordRound(600.000f/430.556f * xHeight);
     bigOpSpacing5 = NSToCoordRound(100.000f/430.556f * xHeight);
   }
 
   static void
-  GetRuleThickness(nsIFontMetrics* fm,
+  GetRuleThickness(nsFontMetrics* fm,
                    nscoord&        ruleThickness)
   {
-    nscoord xHeight;
-    fm->GetXHeight(xHeight);
+    nscoord xHeight = fm->XHeight();
     ruleThickness = NSToCoordRound(40.000f/430.556f * xHeight);
   }
 
   // Some parameters are not accurately obtained using the x-height.
   // Here are some slower variants to obtain the desired metrics
   // by actually measuring some characters
   static void
   GetRuleThickness(nsRenderingContext& aRenderingContext, 
-                   nsIFontMetrics*      aFontMetrics,
+                   nsFontMetrics*      aFontMetrics,
                    nscoord&             aRuleThickness);
 
   static void
   GetAxisHeight(nsRenderingContext& aRenderingContext, 
-                nsIFontMetrics*      aFontMetrics,
+                nsFontMetrics*      aFontMetrics,
                 nscoord&             aAxisHeight);
 
 protected:
 #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
   nsresult DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder,
                                   nsIFrame* aFrame, const nsPoint& aPt,
                                   const nsBoundingMetrics& aMetrics,
                                   const nsDisplayListSet& aLists);
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -37,17 +37,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 #include "nsContentUtils.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsMathMLTokenFrame.h"
 
 nsIFrame*
 NS_NewMathMLTokenFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsMathMLTokenFrame(aContext);
@@ -205,21 +204,20 @@ nsMathMLTokenFrame::Place(nsRenderingCon
        childFrame = childFrame->GetNextSibling()) {
     nsHTMLReflowMetrics childSize;
     GetReflowAndBoundingMetricsFor(childFrame, childSize,
                                    childSize.mBoundingMetrics, nsnull);
     // compute and cache the bounding metrics
     mBoundingMetrics += childSize.mBoundingMetrics;
   }
 
-  nsCOMPtr<nsIFontMetrics> fm =
+  nsRefPtr<nsFontMetrics> fm =
     PresContext()->GetMetricsFor(GetStyleFont()->mFont);
-  nscoord ascent, descent;
-  fm->GetMaxAscent(ascent);
-  fm->GetMaxDescent(descent);
+  nscoord ascent = fm->MaxAscent();
+  nscoord descent = fm->MaxDescent();
 
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   aDesiredSize.width = mBoundingMetrics.width;
   aDesiredSize.ascent = NS_MAX(mBoundingMetrics.ascent, ascent);
   aDesiredSize.height = aDesiredSize.ascent +
                         NS_MAX(mBoundingMetrics.descent, descent);
 
   if (aPlaceOrigin) {
--- a/layout/mathml/nsMathMLmactionFrame.cpp
+++ b/layout/mathml/nsMathMLmactionFrame.cpp
@@ -37,17 +37,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsINameSpaceManager.h"
-#include "nsIFontMetrics.h"
 
 #include "nsCSSRendering.h"
 #include "prprf.h"         // For PR_snprintf()
 
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsIInterfaceRequestor.h"
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -43,17 +43,16 @@
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 #include "nsWhitespaceTokenizer.h"
 
 #include "nsMathMLmencloseFrame.h"
 #include "nsDisplayList.h"
 #include "gfxContext.h"
 
 //
 // <menclose> -- enclose content with a stretching symbol such
@@ -373,17 +372,17 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
 
   ///////////////
   // Thickness of bars and font metrics
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   nscoord mEmHeight;
   aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
   GetRuleThickness(aRenderingContext, fm, mRuleThickness);
   GetEmHeight(fm, mEmHeight);
 
   PRUnichar one = '1';
   nsBoundingMetrics bmOne = aRenderingContext.GetBoundingMetrics(&one, 1);
 
   ///////////////
   // General rules: the menclose element takes the size of the enclosed content.
@@ -395,17 +394,17 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
   if (delta)
     padding += onePixel - delta; // round up
 
   if (IsToDraw(NOTATION_LONGDIV) || IsToDraw(NOTATION_RADICAL)) {
       nscoord phi;
       // Rule 11, App. G, TeXbook
       // psi = clearance between rule and content
       if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags))
-        fm->GetXHeight(phi);
+        phi = fm->XHeight();
       else
         phi = mRuleThickness;
       psi = mRuleThickness + phi / 4;
 
       delta = psi % onePixel;
       if (delta)
         psi += onePixel - delta; // round up
     }
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -41,17 +41,16 @@
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmfencedFrame.h"
 
 //
 // <mfenced> -- surround content with a pair of fences
 //
 
 nsIFrame*
@@ -240,17 +239,17 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   aDesiredSize.width = aDesiredSize.height = 0;
   aDesiredSize.ascent = 0;
   aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
 
   PRInt32 i;
   const nsStyleFont* font = GetStyleFont();
   aReflowState.rendContext->SetFont(font->mFont,
                                     aPresContext->GetUserFontSet());
-  nsIFontMetrics* fm = aReflowState.rendContext->FontMetrics();
+  nsFontMetrics* fm = aReflowState.rendContext->FontMetrics();
   nscoord axisHeight, em;
   GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
   GetEmHeight(fm, em);
   // leading to be left at the top and the bottom of stretched chars
   nscoord leading = NSToCoordRound(0.2f * em); 
 
   /////////////
   // Reflow children
@@ -265,20 +264,21 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   // refactored to use nsMathMLContainerFrame::Reflow() at some stage.
 
   nsReflowStatus childStatus;
   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
   nsIFrame* firstChild = GetFirstChild(nsnull);
   nsIFrame* childFrame = firstChild;
   nscoord ascent = 0, descent = 0;
   if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) {
-    // We use the ASCII metrics to get our minimum height. This way, if we have
-    // borders or a background, they will fit better with other elements on the line
-    fm->GetMaxAscent(ascent);
-    fm->GetMaxDescent(descent);
+    // We use the ASCII metrics to get our minimum height. This way,
+    // if we have borders or a background, they will fit better with
+    // other elements on the line.
+    ascent = fm->MaxAscent();
+    descent = fm->MaxDescent();
   }
   while (childFrame) {
     nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                        childFrame, availSize);
     rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
                      childReflowState, childStatus);
@@ -585,17 +585,17 @@ GetMaxCharWidth(nsPresContext*       aPr
 
 /* virtual */ nscoord
 nsMathMLmfencedFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
 {
   nscoord width = 0;
 
   nsPresContext* presContext = PresContext();
   const nsStyleFont* font = GetStyleFont();
-  nsCOMPtr<nsIFontMetrics> fm = presContext->GetMetricsFor(font->mFont);
+  nsRefPtr<nsFontMetrics> fm = presContext->GetMetricsFor(font->mFont);
   nscoord em;
   GetEmHeight(fm, em);
 
   if (mOpenChar) {
     width +=
       GetMaxCharWidth(presContext, aRenderingContext, mOpenChar,
                       NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, em);
   }
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -41,17 +41,16 @@
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmfracFrame.h"
 #include "nsDisplayList.h"
 #include "gfxContext.h"
 
 //
 // <mfrac> -- form a fraction from two subexpressions - implementation
 //
@@ -265,17 +264,17 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
   GetReflowAndBoundingMetricsFor(frameNum, sizeNum, bmNum);
   GetReflowAndBoundingMetricsFor(frameDen, sizeDen, bmDen);
 
   nsPresContext* presContext = PresContext();
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   aRenderingContext.SetFont(GetStyleFont()->mFont,
                             presContext->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
   nscoord defaultRuleThickness, axisHeight;
   GetRuleThickness(aRenderingContext, fm, defaultRuleThickness);
   GetAxisHeight(aRenderingContext, fm, axisHeight);
 
   nsEmbellishData coreData;
   GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData);
 
@@ -432,18 +431,17 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
     }
   } else {
     nscoord numShift = 0.0;
     nscoord denShift = 0.0;
     nscoord padding = 3 * defaultRuleThickness;
     nscoord slashRatio = 3;
 
     // Define the constant used in the expression of the maximum width
-    nscoord em;
-    fm->GetEmHeight(em);
+    nscoord em = fm->EmHeight();
     nscoord slashMaxWidthConstant = 2 * em;
 
     // For large line thicknesses the minimum slash height is limited to the
     // largest expected height of a fraction
     nscoord slashMinHeight = slashRatio *
       NS_MIN(2 * mLineThickness, slashMaxWidthConstant);
 
     nscoord leftSpace = NS_MAX(padding, coreData.leftSpace);
@@ -473,18 +471,17 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
     }
 
     if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
       delta = NS_MIN(bmDen.ascent + bmDen.descent,
                      bmNum.ascent + bmNum.descent) / 2;
       numShift += delta;
       denShift += delta;
     } else {
-      nscoord xHeight = 0;
-      fm->GetXHeight (xHeight);
+      nscoord xHeight = fm->XHeight();
       numShift += xHeight / 2;
       denShift += xHeight / 4;
     }
    
     // Set the ascent/descent of our BoundingMetrics.
     mBoundingMetrics.ascent = bmNum.ascent + numShift;
     mBoundingMetrics.descent = bmDen.descent + denShift;
 
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -40,17 +40,16 @@
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmmultiscriptsFrame.h"
 
 //
 // <mmultiscripts> -- attach prescripts and tensor indices to a base - implementation
 //
 
 nsIFrame*
@@ -158,20 +157,19 @@ nsMathMLmmultiscriptsFrame::Place(nsRend
   ////////////////////////////////////////
 
   ProcessAttributes();
 
   // get x-height (an ex)
   const nsStyleFont* font = GetStyleFont();
   aRenderingContext.SetFont(font->mFont,
                             PresContext()->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
-  nscoord xHeight;
-  fm->GetXHeight (xHeight);
+  nscoord xHeight = fm->XHeight();
 
   nscoord ruleSize;
   GetRuleThickness (aRenderingContext, fm, ruleSize);
 
   // scriptspace from TeX for extra spacing after sup/subscript (0.5pt in plain TeX)
   // forced to be at least 1 pixel here
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
   nscoord scriptSpace = NS_MAX(nsPresContext::CSSPointsToAppUnits(0.5f), onePixel);
--- a/layout/mathml/nsMathMLmoFrame.cpp
+++ b/layout/mathml/nsMathMLmoFrame.cpp
@@ -41,17 +41,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 #include "nsContentUtils.h"
 
 #include "nsIDOMText.h"
 
 #include "nsMathMLmoFrame.h"
 
 //
 // <mo> -- operator, fence, or separator - implementation
@@ -389,17 +388,17 @@ nsMathMLmoFrame::ProcessOperatorData()
     float rspace = 0.0f;
     nsAutoString data;
     mMathMLChar.GetData(data);
     PRBool found = nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace);
     if (found && (lspace || rspace)) {
       // cache the default values of lspace & rspace that we get from the dictionary.
       // since these values are relative to the 'em' unit, convert to twips now
       nscoord em;
-      nsCOMPtr<nsIFontMetrics> fm =
+      nsRefPtr<nsFontMetrics> fm =
 	presContext->GetMetricsFor(GetStyleFont()->mFont);
       GetEmHeight(fm, em);
 
       mEmbellishData.leftSpace = NSToCoordRound(lspace * em);
       mEmbellishData.rightSpace = NSToCoordRound(rspace * em);
 
       // tuning if we don't want too much extra space when we are a script.
       // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0.
@@ -635,17 +634,17 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
   }
   mPresentationData.flags |= NS_MATHML_STRETCH_DONE;
 
   nsIFrame* firstChild = mFrames.FirstChild();
 
   // get the axis height;
   aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
   nscoord axisHeight, height;
   GetAxisHeight(aRenderingContext, fm, axisHeight);
 
   // get the leading to be left at the top and the bottom of the stretched char
   // this seems more reliable than using fm->GetLeading() on suspicious fonts
   nscoord em;
   GetEmHeight(fm, em);
   nscoord leading = NSToCoordRound(0.2f * em);
@@ -850,19 +849,18 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
     // see bug 188467 for what is going on here
     nscoord dy = aDesiredStretchSize.ascent - (mBoundingMetrics.ascent + leading);
     aDesiredStretchSize.ascent = mBoundingMetrics.ascent + leading;
     aDesiredStretchSize.height = aDesiredStretchSize.ascent + mBoundingMetrics.descent;
 
     firstChild->SetPosition(firstChild->GetPosition() - nsPoint(0, dy));
   }
   else if (useMathMLChar) {
-    nscoord ascent, descent;
-    fm->GetMaxAscent(ascent);
-    fm->GetMaxDescent(descent);
+    nscoord ascent = fm->MaxAscent();
+    nscoord descent = fm->MaxDescent();
     aDesiredStretchSize.ascent = NS_MAX(mBoundingMetrics.ascent + leading, ascent);
     aDesiredStretchSize.height = aDesiredStretchSize.ascent +
                                  NS_MAX(mBoundingMetrics.descent + leading, descent);
   }
   aDesiredStretchSize.width = mBoundingMetrics.width;
   aDesiredStretchSize.mBoundingMetrics = mBoundingMetrics;
   mReference.x = 0;
   mReference.y = aDesiredStretchSize.ascent;
--- a/layout/mathml/nsMathMLmoverFrame.cpp
+++ b/layout/mathml/nsMathMLmoverFrame.cpp
@@ -42,17 +42,16 @@
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsINameSpaceManager.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmoverFrame.h"
 #include "nsMathMLmsupFrame.h"
 
 //
 // <mover> -- attach an overscript to a base - implementation
 //
 
@@ -279,20 +278,19 @@ nsMathMLmoverFrame::Place(nsRenderingCon
 
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   ////////////////////
   // Place Children
 
   aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
-  nscoord xHeight = 0;
-  fm->GetXHeight (xHeight);
+  nscoord xHeight = fm->XHeight();
 
   nscoord ruleThickness;
   GetRuleThickness (aRenderingContext, fm, ruleThickness);
 
   // there are 2 different types of placement depending on 
   // whether we want an accented overscript or not
 
   nscoord correction = 0;
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -40,17 +40,16 @@
 
 
 #include "nsCOMPtr.h"
 #include "nsCRT.h"  // to get NS_IS_SPACE
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmpaddedFrame.h"
 
 //
 // <mpadded> -- adjust space around content - implementation
 //
 
 #define NS_MATHML_SIGN_INVALID           -1 // if the attribute is not there
--- a/layout/mathml/nsMathMLmphantomFrame.cpp
+++ b/layout/mathml/nsMathMLmphantomFrame.cpp
@@ -37,17 +37,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmphantomFrame.h"
 
 //
 // <mphantom> -- make content invisible but preserve its size
 //
 
 nsIFrame*
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -41,17 +41,16 @@
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmrootFrame.h"
 
 //
 // <msqrt> and <mroot> -- form a radical - implementation
 //
 
 //NOTE:
@@ -151,24 +150,23 @@ nsMathMLmrootFrame::BuildDisplayList(nsD
 #endif
   }
 
   return rv;
 }
 
 static void
 GetRadicalXOffsets(nscoord aIndexWidth, nscoord aSqrWidth,
-                   nsIFontMetrics* aFontMetrics,
+                   nsFontMetrics* aFontMetrics,
                    nscoord* aIndexOffset, nscoord* aSqrOffset)
 {
   // The index is tucked in closer to the radical while making sure
   // that the kern does not make the index and radical collide
   nscoord dxIndex, dxSqr;
-  nscoord xHeight = 0;
-  aFontMetrics->GetXHeight(xHeight);
+  nscoord xHeight = aFontMetrics->XHeight();
   nscoord indexRadicalKern = NSToCoordRound(1.35f * xHeight);
   if (indexRadicalKern > aIndexWidth) {
     dxIndex = indexRadicalKern - aIndexWidth;
     dxSqr = 0;
   }
   else {
     dxIndex = 0;
     dxSqr = aIndexWidth - indexRadicalKern;
@@ -256,17 +254,17 @@ nsMathMLmrootFrame::Reflow(nsPresContext
     return rv;
   }
 
   ////////////
   // Prepare the radical symbol and the overline bar
 
   renderingContext.SetFont(GetStyleFont()->mFont,
                            aPresContext->GetUserFontSet());
-  nsIFontMetrics* fm = renderingContext.FontMetrics();
+  nsFontMetrics* fm = renderingContext.FontMetrics();
 
   // For radical glyphs from TeX fonts and some of the radical glyphs from
   // Mathematica fonts, the thickness of the overline can be obtained from the
   // ascent of the glyph.  Most fonts however have radical glyphs above the
   // baseline so no assumption can be made about the meaning of the ascent.
   nscoord ruleThickness, leading, em;
   GetRuleThickness(renderingContext, fm, ruleThickness);
 
@@ -277,17 +275,17 @@ nsMathMLmrootFrame::Reflow(nsPresContext
   // this seems more reliable than using fm->GetLeading() on suspicious fonts
   GetEmHeight(fm, em);
   leading = nscoord(0.2f * em); 
 
   // Rule 11, App. G, TeXbook
   // psi = clearance between rule and content
   nscoord phi = 0, psi = 0;
   if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags))
-    fm->GetXHeight(phi);
+    phi = fm->XHeight();
   else
     phi = ruleThickness;
   psi = ruleThickness + phi/4;
 
   // built-in: adjust clearance psi to emulate \mathstrut using '1' (TexBook, p.131)
   if (bmOne.ascent > bmBase.ascent)
     psi += bmOne.ascent - bmBase.ascent;
 
--- a/layout/mathml/nsMathMLmrowFrame.cpp
+++ b/layout/mathml/nsMathMLmrowFrame.cpp
@@ -37,17 +37,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmrowFrame.h"
 
 //
 // <mrow> -- horizontally group any number of subexpressions - implementation
 //
 
 nsIFrame*
--- a/layout/mathml/nsMathMLmspaceFrame.cpp
+++ b/layout/mathml/nsMathMLmspaceFrame.cpp
@@ -37,17 +37,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmspaceFrame.h"
 
 
 //
 // <mspace> -- space - implementation
 //
 
--- a/layout/mathml/nsMathMLmstyleFrame.cpp
+++ b/layout/mathml/nsMathMLmstyleFrame.cpp
@@ -38,17 +38,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsINameSpaceManager.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmstyleFrame.h"
 
 //
 // <mstyle> -- style change
 //
 
 nsIFrame*
--- a/layout/mathml/nsMathMLmsubFrame.cpp
+++ b/layout/mathml/nsMathMLmsubFrame.cpp
@@ -39,17 +39,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmsubFrame.h"
 
 //
 // <msub> -- attach a subscript to a base - implementation
 //
 
 nsIFrame*
@@ -149,20 +148,20 @@ nsMathMLmsubFrame::PlaceSubScript (nsPre
   nscoord minSubScriptShift = bmBase.descent + subDrop;
 
   //////////////////
   // Place Children
   
   // get min subscript shift limit from x-height
   // = h(x) - 4/5 * sigma_5, Rule 18b, App. G, TeXbook
   nscoord xHeight = 0;
-  nsCOMPtr<nsIFontMetrics> fm =
+  nsRefPtr<nsFontMetrics> fm =
     aPresContext->GetMetricsFor(baseFrame->GetStyleFont()->mFont);
 
-  fm->GetXHeight (xHeight);
+  xHeight = fm->XHeight();
   nscoord minShiftFromXHeight = (nscoord) 
     (bmSubScript.ascent - (4.0f/5.0f) * xHeight);
 
   // subScriptShift
   // = minimum amount to shift the subscript down set by user or from the font
   // = sub1 in TeX
   // = subscriptshift attribute * x-height
   nscoord subScriptShift, dummy;
--- a/layout/mathml/nsMathMLmsubsupFrame.cpp
+++ b/layout/mathml/nsMathMLmsubsupFrame.cpp
@@ -40,17 +40,16 @@
 
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmsubsupFrame.h"
 
 //
 // <msubsup> -- attach a subscript-superscript pair to a base - implementation
 //
 
 nsIFrame*
@@ -191,21 +190,20 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(
   // subScriptShift{1,2}
   // = minimum amount to shift the subscript down
   // = sub{1,2} in TeXbook
   // subScriptShift1 = subscriptshift attribute * x-height
   nscoord subScriptShift1, subScriptShift2;
 
   aRenderingContext.SetFont(baseFrame->GetStyleFont()->mFont,
                             aPresContext->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
   // get x-height (an ex)
-  nscoord xHeight;
-  fm->GetXHeight (xHeight);
+  nscoord xHeight = fm->XHeight();
 
   nscoord ruleSize;
   GetRuleThickness (aRenderingContext, fm, ruleSize);
 
   // Get subScriptShift{1,2} default from font
   GetSubScriptShifts (fm, subScriptShift1, subScriptShift2);
 
   if (0 < aUserSubScriptShift) {
--- a/layout/mathml/nsMathMLmsupFrame.cpp
+++ b/layout/mathml/nsMathMLmsupFrame.cpp
@@ -38,17 +38,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmsupFrame.h"
 
 //
 // <msup> -- attach a superscript to a base - implementation
 //
 
 nsIFrame*
@@ -150,20 +149,20 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPr
   nscoord minSupScriptShift = bmBase.ascent - supDrop;
 
   //////////////////
   // Place Children 
   
   // get min supscript shift limit from x-height
   // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
   nscoord xHeight = 0;
-  nsCOMPtr<nsIFontMetrics> fm =
+  nsRefPtr<nsFontMetrics> fm =
     aPresContext->GetMetricsFor(baseFrame->GetStyleFont()->mFont);
 
-  fm->GetXHeight (xHeight);
+  xHeight = fm->XHeight();
   nscoord minShiftFromXHeight = (nscoord) 
     (bmSupScript.descent + (1.0f/4.0f) * xHeight);
   nscoord italicCorrection;
   GetItalicCorrection(bmBase, italicCorrection);
 
   // supScriptShift{1,2,3}
   // = minimum amount to shift the supscript up
   // = sup{1,2,3} in TeX
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -39,17 +39,16 @@
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsBlockFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsINameSpaceManager.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsTArray.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsTableOuterFrame.h"
 #include "nsTableFrame.h"
 #include "nsTableCellFrame.h"
 #include "celldata.h"
 
--- a/layout/mathml/nsMathMLmunderFrame.cpp
+++ b/layout/mathml/nsMathMLmunderFrame.cpp
@@ -42,17 +42,16 @@
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsINameSpaceManager.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmunderFrame.h"
 #include "nsMathMLmsubFrame.h"
 
 //
 // <munder> -- attach an underscript to a base - implementation
 //
 
@@ -276,20 +275,19 @@ nsMathMLmunderFrame::Place(nsRenderingCo
 
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   ////////////////////
   // Place Children
 
   aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
-  nscoord xHeight = 0;
-  fm->GetXHeight (xHeight);
+  nscoord xHeight = fm->XHeight();
 
   nscoord ruleThickness;
   GetRuleThickness (aRenderingContext, fm, ruleThickness);
 
   // there are 2 different types of placement depending on 
   // whether we want an accented under or not
 
   nscoord correction = 0;
--- a/layout/mathml/nsMathMLmunderoverFrame.cpp
+++ b/layout/mathml/nsMathMLmunderoverFrame.cpp
@@ -42,17 +42,16 @@
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsINameSpaceManager.h"
 #include "nsRenderingContext.h"
-#include "nsIFontMetrics.h"
 
 #include "nsMathMLmunderoverFrame.h"
 #include "nsMathMLmsubsupFrame.h"
 
 //
 // <munderover> -- attach an underscript-overscript pair to a base - implementation
 //
 
@@ -318,20 +317,19 @@ nsMathMLmunderoverFrame::Place(nsRenderi
 
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   ////////////////////
   // Place Children
 
   aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
-  nsIFontMetrics* fm = aRenderingContext.FontMetrics();
+  nsFontMetrics* fm = aRenderingContext.FontMetrics();
 
-  nscoord xHeight = 0;
-  fm->GetXHeight (xHeight);
+  nscoord xHeight = fm->XHeight();
 
   nscoord ruleThickness;
   GetRuleThickness (aRenderingContext, fm, ruleThickness);
 
   nscoord correction = 0;
   GetItalicCorrection (bmBase, correction);
 
   // there are 2 different types of placement depending on 
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -52,17 +52,16 @@
 #include "nsIURL.h"
 #include "nsIDocument.h"
 #include "nsIDeviceContext.h"
 #include "nsIAtom.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsStyleConsts.h"
 #include "nsStyleUtil.h"
-#include "nsIFontMetrics.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsICSSStyleRuleDOMWrapper.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsINameSpaceManager.h"
 #include "nsXMLNameSpaceMap.h"
 #include "nsILookAndFeel.h"
 #include "nsRuleNode.h"
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -51,17 +51,17 @@
 
 #include "nsRuleNode.h"
 #include "nscore.h"
 #include "nsIServiceManager.h"
 #include "nsIDeviceContext.h"
 #include "nsIWidget.h"
 #include "nsILookAndFeel.h"
 #include "nsIPresShell.h"
-#include "nsIThebesFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "gfxFont.h"
 #include "nsStyleUtil.h"
 #include "nsCSSPseudoElements.h"
 #include "nsThemeConstants.h"
 #include "nsITheme.h"
 #include "pldhash.h"
 #include "nsStyleContext.h"
 #include "nsStyleSet.h"
@@ -303,29 +303,26 @@ static nscoord CalcLengthWith(const nsCS
     }
     case eCSSUnit_EM: {
       return ScaleCoord(aValue, float(aFontSize));
       // XXX scale against font metrics height instead?
     }
     case eCSSUnit_XHeight: {
       nsFont font = styleFont->mFont;
       font.size = aFontSize;
-      nsCOMPtr<nsIFontMetrics> fm =
+      nsRefPtr<nsFontMetrics> fm =
         aPresContext->GetMetricsFor(font, aUseUserFontSet);
-      nscoord xHeight;
-      fm->GetXHeight(xHeight);
-      return ScaleCoord(aValue, float(xHeight));
+      return ScaleCoord(aValue, float(fm->XHeight()));
     }
     case eCSSUnit_Char: {
       nsFont font = styleFont->mFont;
       font.size = aFontSize;
-      nsCOMPtr<nsIFontMetrics> fm =
+      nsRefPtr<nsFontMetrics> fm =
         aPresContext->GetMetricsFor(font, aUseUserFontSet);
-      nsCOMPtr<nsIThebesFontMetrics> tfm(do_QueryInterface(fm));
-      gfxFloat zeroWidth = (tfm->GetThebesFontGroup()->GetFontAt(0)
+      gfxFloat zeroWidth = (fm->GetThebesFontGroup()->GetFontAt(0)
                             ->GetMetrics().zeroOrAveCharWidth);
 
       return ScaleCoord(aValue, NS_ceil(aPresContext->AppUnitsPerDevPixel() *
                                         zeroWidth));
     }
     // For properties for which lengths are the *only* units accepted in
     // calc(), we can handle calc() here and just compute a final
     // result.  We ensure that we don't get to this code for other
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -73,17 +73,16 @@
 #include "nsSVGGeometryFrame.h"
 #include "nsIScriptError.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxRect.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "nsSVGForeignObjectFrame.h"
-#include "nsIFontMetrics.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsSVGEffects.h"
 #include "nsMathUtils.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGGeometryFrame.h"
 #include "nsComputedDOMStyle.h"
 #include "nsSVGPathGeometryFrame.h"
@@ -283,28 +282,27 @@ nsSVGUtils::GetFontXHeight(nsIFrame *aFr
 float
 nsSVGUtils::GetFontXHeight(nsStyleContext *aStyleContext)
 {
   NS_ABORT_IF_FALSE(aStyleContext, "NULL style context in GetFontXHeight");
 
   nsPresContext *presContext = aStyleContext->PresContext();
   NS_ABORT_IF_FALSE(presContext, "NULL pres context in GetFontXHeight");
 
-  nsCOMPtr<nsIFontMetrics> fontMetrics;
+  nsRefPtr<nsFontMetrics> fontMetrics;
   nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext,
                                                getter_AddRefs(fontMetrics));
 
   if (!fontMetrics) {
     // ReportToConsole
     NS_WARNING("no FontMetrics in GetFontXHeight()");
     return 1.0f;
   }
 
-  nscoord xHeight;
-  fontMetrics->GetXHeight(xHeight);
+  nscoord xHeight = fontMetrics->XHeight();
   return nsPresContext::AppUnitsToFloatCSSPixels(xHeight) /
          presContext->TextZoom();
 }
 
 void
 nsSVGUtils::UnPremultiplyImageDataAlpha(PRUint8 *data, 
                                         PRInt32 stride,
                                         const nsIntRect &rect)
--- a/layout/xul/base/src/nsImageBoxFrame.cpp
+++ b/layout/xul/base/src/nsImageBoxFrame.cpp
@@ -39,17 +39,16 @@
 // Eric Vaughan
 // Netscape Communications
 //
 // See documentation in associated header file
 //
 
 #include "nsImageBoxFrame.h"
 #include "nsIDeviceContext.h"
-#include "nsIFontMetrics.h"
 #include "nsGkAtoms.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsCOMPtr.h"
 #include "nsPresContext.h"
 #include "nsBoxLayoutState.h"
 
 #include "nsHTMLParts.h"
@@ -60,17 +59,16 @@
 #include "nsIHTMLDocument.h"
 #include "nsStyleConsts.h"
 #include "nsImageMap.h"
 #include "nsILinkHandler.h"
 #include "nsIURL.h"
 #include "nsILoadGroup.h"
 #include "nsHTMLContainerFrame.h"
 #include "prprf.h"
-#include "nsIFontMetrics.h"
 #include "nsCSSRendering.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDeviceContext.h"
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsIDOMHTMLMapElement.h"
 #include "nsBoxLayoutState.h"
 #include "nsIDOMDocument.h"
--- a/layout/xul/base/src/nsLeafBoxFrame.cpp
+++ b/layout/xul/base/src/nsLeafBoxFrame.cpp
@@ -41,17 +41,16 @@
 //
 // See documentation in associated header file
 //
 
 #include "nsLeafBoxFrame.h"
 #include "nsBoxFrame.h"
 #include "nsCOMPtr.h"
 #include "nsIDeviceContext.h"
-#include "nsIFontMetrics.h"
 #include "nsGkAtoms.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsIContent.h"
 #include "nsINameSpaceManager.h"
 #include "nsBoxLayoutState.h"
 #include "nsWidgetsCID.h"
 #include "nsIViewManager.h"
--- a/layout/xul/base/src/nsListBoxBodyFrame.cpp
+++ b/layout/xul/base/src/nsListBoxBodyFrame.cpp
@@ -54,17 +54,17 @@
 #include "nsIDOMNodeList.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsIScrollableFrame.h"
 #include "nsIScrollbarFrame.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsStyleContext.h"
 #include "nsIDeviceContext.h"
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsITimer.h"
 #include "nsAutoPtr.h"
 #include "nsStyleSet.h"
 #include "nsIDOMNSDocument.h"
 #include "nsPIBoxObject.h"
 #include "nsINodeInfo.h"
 #include "nsLayoutUtils.h"
 #include "nsPIListBoxObject.h"
@@ -220,19 +220,19 @@ nsListBoxBodyFrame::Init(nsIContent*    
   nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(this);
   if (scrollFrame) {
     nsIBox* verticalScrollbar = scrollFrame->GetScrollbarBox(PR_TRUE);
     if (verticalScrollbar) {
       nsIScrollbarFrame* scrollbarFrame = do_QueryFrame(verticalScrollbar);
       scrollbarFrame->SetScrollbarMediatorContent(GetContent());
     }
   }
-  nsCOMPtr<nsIFontMetrics> fm;
+  nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
-  fm->GetHeight(mRowHeight);
+  mRowHeight = fm->MaxHeight();
 
   return rv;
 }
 
 void
 nsListBoxBodyFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // make sure we cancel any posted callbacks.
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -1776,27 +1776,16 @@ nsMenuPopupFrame::AttributeChanged(PRInt
         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, title);
         if (!title.IsEmpty()) {
           widget->SetTitle(title);
         }
       }
     }
   }
 
-  // accessibility needs this to ensure the frames get constructed when the
-  // menugenerated attribute is set, see bug 279703 comment 42 for discussion
-  if (aAttribute == nsGkAtoms::menugenerated &&
-      mFrames.IsEmpty() && !mGeneratedChildren) {
-    EnsureWidget();
-
-    // indicate that the children have been generated and then generate them
-    mGeneratedChildren = PR_TRUE;
-    PresContext()->PresShell()->FrameConstructor()->GenerateChildFrames(this);
-  }
-
   return rv;
 }
 
 void
 nsMenuPopupFrame::MoveToAttributePosition()
 {
   // Move the widget around when the user sets the |left| and |top| attributes. 
   // Note that this is not the best way to move the widget, as it results in lots
--- a/layout/xul/base/src/nsTextBoxFrame.cpp
+++ b/layout/xul/base/src/nsTextBoxFrame.cpp
@@ -44,17 +44,16 @@
 //
 // See documentation in associated header file
 //
 
 #include "nsReadableUtils.h"
 #include "nsTextBoxFrame.h"
 #include "nsCOMPtr.h"
 #include "nsIDeviceContext.h"
-#include "nsIFontMetrics.h"
 #include "nsGkAtoms.h"
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
 #include "nsStyleContext.h"
 #include "nsIContent.h"
 #include "nsINameSpaceManager.h"
 #include "nsBoxLayoutState.h"
 #include "nsMenuBarListener.h"
@@ -67,17 +66,16 @@
 #include "nsIEventStateManager.h"
 #include "nsITheme.h"
 #include "nsUnicharUtils.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 #include "nsCSSRendering.h"
 #include "nsIReflowCallback.h"
 #include "nsBoxFrame.h"
-#include "nsIThebesFontMetrics.h"
 
 #ifdef IBMBIDI
 #include "nsBidiUtils.h"
 #include "nsBidiPresUtils.h"
 #endif // IBMBIDI
 
 #define CROP_LEFT   "left"
 #define CROP_RIGHT  "right"
@@ -473,23 +471,22 @@ nsTextBoxFrame::DrawText(nsRenderingCont
       if (0 != decorMask) {
         context = context->GetParent();
         if (context) {
           hasDecorations = context->HasTextDecorations();
         }
       }
     } while (context && hasDecorations && (0 != decorMask));
 
-    nsCOMPtr<nsIFontMetrics> fontMet;
+    nsRefPtr<nsFontMetrics> fontMet;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
 
     nscoord offset;
     nscoord size;
-    nscoord ascent;
-    fontMet->GetMaxAscent(ascent);
+    nscoord ascent = fontMet->MaxAscent();
 
     nscoord baseline =
       presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent);
     nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
     gfxPoint pt(presContext->AppUnitsToGfxUnits(aTextRect.x),
                 presContext->AppUnitsToGfxUnits(aTextRect.y));
     gfxFloat width = presContext->AppUnitsToGfxUnits(aTextRect.width);
     gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent);
@@ -569,19 +566,19 @@ nsTextBoxFrame::DrawText(nsRenderingCont
            if (mAccessKeyInfo->mAccesskeyIndex > 0)
                mAccessKeyInfo->mBeforeWidth =
                    refContext->GetWidth(mCroppedTitle.get(),
                                         mAccessKeyInfo->mAccesskeyIndex);
            else
                mAccessKeyInfo->mBeforeWidth = 0;
        }
 
-       nsIThebesFontMetrics* fm = static_cast<nsIThebesFontMetrics*>(fontMet.get());
-       fm->DrawString(mCroppedTitle.get(), mCroppedTitle.Length(),
-                      aTextRect.x, baseline, &aRenderingContext, refContext.get());
+       fontMet->DrawString(mCroppedTitle.get(), mCroppedTitle.Length(),
+                           aTextRect.x, baseline, &aRenderingContext,
+                           refContext.get());
     }
 
     if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
         aRenderingContext.FillRect(aTextRect.x + mAccessKeyInfo->mBeforeWidth,
                                    aTextRect.y + mAccessKeyInfo->mAccessOffset,
                                    mAccessKeyInfo->mAccessWidth,
                                    mAccessKeyInfo->mAccessUnderlineSize);
     }
@@ -652,19 +649,19 @@ nsTextBoxFrame::CalculateUnderline(nsRen
          // are the same for both BiDi and non-BiDi frames.
          const PRUnichar *titleString = mCroppedTitle.get();
          aRenderingContext.SetTextRunRTL(PR_FALSE);
          mAccessKeyInfo->mAccessWidth =
              aRenderingContext.GetWidth(titleString[mAccessKeyInfo->
                                                     mAccesskeyIndex]);
 
          nscoord offset, baseline;
-         nsIFontMetrics* metrics = aRenderingContext.FontMetrics();
+         nsFontMetrics* metrics = aRenderingContext.FontMetrics();
          metrics->GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize);
-         metrics->GetMaxAscent(baseline);
+         baseline = metrics->MaxAscent();
          mAccessKeyInfo->mAccessOffset = baseline - offset;
     }
 }
 
 nscoord
 nsTextBoxFrame::CalculateTitleForWidth(nsPresContext*      aPresContext,
                                        nsRenderingContext& aRenderingContext,
                                        nscoord              aWidth)
@@ -993,26 +990,29 @@ nsTextBoxFrame::ComputesOwnOverflowArea(
 /* virtual */ void
 nsTextBoxFrame::MarkIntrinsicWidthsDirty()
 {
     mNeedsRecalc = PR_TRUE;
     nsTextBoxFrameSuper::MarkIntrinsicWidthsDirty();
 }
 
 void
-nsTextBoxFrame::GetTextSize(nsPresContext* aPresContext, nsRenderingContext& aRenderingContext,
-                                const nsString& aString, nsSize& aSize, nscoord& aAscent)
+nsTextBoxFrame::GetTextSize(nsPresContext* aPresContext,
+                            nsRenderingContext& aRenderingContext,
+                            const nsString& aString,
+                            nsSize& aSize, nscoord& aAscent)
 {
-    nsCOMPtr<nsIFontMetrics> fontMet;
+    nsRefPtr<nsFontMetrics> fontMet;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
-    fontMet->GetHeight(aSize.height);
+    aSize.height = fontMet->MaxHeight();
     aRenderingContext.SetFont(fontMet);
     aSize.width =
-      nsLayoutUtils::GetStringWidth(this, &aRenderingContext, aString.get(), aString.Length());
-    fontMet->GetMaxAscent(aAscent);
+      nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
+                                    aString.get(), aString.Length());
+    aAscent = fontMet->MaxAscent();
 }
 
 void
 nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState)
 {
     if (mNeedsRecalc)
     {
         nsSize size;
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -71,17 +71,16 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMNSDocument.h"
 #include "nsIDOMDocumentEvent.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocument.h"
 #include "nsIContent.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsCSSRendering.h"
-#include "nsIFontMetrics.h"
 #include "nsIDeviceContext.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsXPIDLString.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsWidgetsCID.h"
 #include "nsBoxFrame.h"
@@ -1257,21 +1256,20 @@ nsTreeBodyFrame::GetCoordsForCellItem(PR
     nsRect textRect(cellX, cellRect.y, remainWidth, cellRect.height);
 
     // Measure the width of the text. If the width of the text is greater than 
     // the remaining width available, then we just assume that the text has 
     // been cropped and use the remaining rect as the text Rect. Otherwise,
     // we add in borders and padding to the text dimension and give that back. 
     nsStyleContext* textContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreecelltext);
 
-    nsCOMPtr<nsIFontMetrics> fm;
+    nsRefPtr<nsFontMetrics> fm;
     nsLayoutUtils::GetFontMetricsForStyleContext(textContext,
                                                  getter_AddRefs(fm));
-    nscoord height;
-    fm->GetHeight(height);
+    nscoord height = fm->MaxHeight();
 
     nsMargin textMargin;
     textContext->GetStyleMargin()->GetMargin(textMargin);
     textRect.Deflate(textMargin);
 
     // Center the text. XXX Obey vertical-align style prop?
     if (height < textRect.height) {
       textRect.y += (textRect.height - height) / 2;
@@ -3564,23 +3562,22 @@ nsTreeBodyFrame::PaintText(PRInt32      
   textRect.Deflate(textMargin);
 
   // Adjust the rect for its border and padding.
   nsMargin bp(0,0,0,0);
   GetBorderPadding(textContext, bp);
   textRect.Deflate(bp);
 
   // Compute our text size.
-  nsCOMPtr<nsIFontMetrics> fontMet;
+  nsRefPtr<nsFontMetrics> fontMet;
   nsLayoutUtils::GetFontMetricsForStyleContext(textContext,
                                                getter_AddRefs(fontMet));
 
-  nscoord height, baseline;
-  fontMet->GetHeight(height);
-  fontMet->GetMaxAscent(baseline);
+  nscoord height = fontMet->MaxHeight();
+  nscoord baseline = fontMet->MaxAscent();
 
   // Center the text. XXX Obey vertical-align style prop?
   if (height < textRect.height) {
     textRect.y += (textRect.height - height)/2;
     textRect.height = height;
   }
 
   // Set our font.
--- a/mobile/app/profile/extensions/Makefile.in
+++ b/mobile/app/profile/extensions/Makefile.in
@@ -39,17 +39,17 @@ DEPTH		= ../../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/rules.mk
 
-ifeq (beta,$(MOZ_UPDATE_CHANNEL))
+ifneq (,$(filter aurora beta,$(MOZ_UPDATE_CHANNEL)))
 EXTENSIONS = \
   feedback@mobile.mozilla.org \
   $(NULL)
 
 ABS_DIST = $(call core_abspath,$(DIST))
 
 define _PACKAGE_EXTENSIONS
 rm -f $(ABS_DIST)/bin/extensions/$(dir).xpi
--- a/mobile/app/profile/extensions/feedback@mobile.mozilla.org/install.rdf
+++ b/mobile/app/profile/extensions/feedback@mobile.mozilla.org/install.rdf
@@ -8,17 +8,17 @@
     <em:type>2</em:type>
 
     <!-- Target Application this extension can install into, 
          with minimum and maximum supported versions. --> 
     <em:targetApplication>
       <Description>
         <em:id>{a23983c0-fd0e-11dc-95ff-0800200c9a66}</em:id>
         <em:minVersion>2.0b1pre</em:minVersion>
-        <em:maxVersion>4.*</em:maxVersion>
+        <em:maxVersion>6.*</em:maxVersion>
       </Description>
     </em:targetApplication>
    
     <!-- Front End MetaData -->
     <em:name>Feedback</em:name>
     <em:description>Help make Firefox better by giving feedback.</em:description>
     <em:creator>Mozilla Corporation</em:creator>
     <em:iconURL>chrome://feedback/skin/dino-32.png</em:iconURL>
--- a/mobile/chrome/content/bindings.xml
+++ b/mobile/chrome/content/bindings.xml
@@ -869,17 +869,17 @@
         </xul:vbox>
       </xul:hbox>
 
       <xul:hbox anonid="bookmark-manage" class="bookmark-manage" hidden="true" flex="1">
         <xul:image xbl:inherits="src"/>
         <xul:vbox flex="1">
           <xul:vbox flex="1">
             <xul:textbox anonid="name" xbl:inherits="value=title" class="prompt-edit" flex="1"/>
-            <xul:textbox anonid="uri" xbl:inherits="value=uri" class="prompt-edit" flex="1"/>
+            <xul:textbox anonid="uri" xbl:inherits="value=uri" type="url" class="uri-element" class="prompt-edit" flex="1"/>
             <xul:textbox anonid="tags" xbl:inherits="value=tags" emptytext="&editBookmarkTags.label;" class="prompt-edit" flex="1"/>
           </xul:vbox>
 
          <xul:hbox class="bookmark-controls" align="center">
             <xul:spacer flex="1"/>
             <xul:button anonid="done-button" class="bookmark-done" label="&editBookmarkDone.label;"
                         oncommand="document.getBindingParent(this).stopEditing(true)"/>
           </xul:hbox>
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -52,18 +52,16 @@ let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 let Cr = Components.results;
 
 function getBrowser() {
   return Browser.selectedBrowser;
 }
 
-const kBrowserFormZoomLevelMin = 0.8;
-const kBrowserFormZoomLevelMax = 2.0;
 const kBrowserViewZoomLevelPrecision = 10000;
 
 const kDefaultBrowserWidth = 800;
 const kFallbackBrowserWidth = 980;
 const kDefaultMetadata = { autoSize: false, allowZoom: true, autoScale: true };
 
 // Override sizeToContent in the main window. It breaks things (bug 565887)
 window.sizeToContent = function() {
@@ -1434,18 +1432,18 @@ Browser.WebProgress.prototype = {
       if (getBrowser() == browser) {
         let json = aMessage.json;
         browser.getRootView().scrollTo(Math.floor(json.x * browser.scale),
                                        Math.floor(json.y * browser.scale));
         Browser.pageScrollboxScroller.scrollTo(0, 0);
       }
 
       aTab.scrolledAreaChanged();
-      if (browser.currentURI.spec != "about:blank")
-        aTab.updateThumbnail();
+      aTab.updateThumbnail();
+
       browser.messageManager.addMessageListener("MozScrolledAreaChanged", aTab.scrolledAreaChanged);
     });
   }
 };
 
 
 function nsBrowserAccess() { }
 
--- a/mobile/chrome/content/common-ui.js
+++ b/mobile/chrome/content/common-ui.js
@@ -1,9 +1,49 @@
 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
+/*
+ * ***** 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 Mozilla Mobile Browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+const kBrowserFormZoomLevelMin = 0.8;
+const kBrowserFormZoomLevelMax = 2.0;
+
 var BrowserSearch = {
   get _popup() {
     delete this._popup;
     return this._popup = document.getElementById("search-engines-popup");
   },
 
   get _list() {
     delete this._list;
@@ -558,17 +598,21 @@ var FindHelperUI = {
 
   _zoom: function _findHelperZoom(aElementRect) {
     let autozoomEnabled = Services.prefs.getBoolPref("findhelper.autozoom");
     if (!aElementRect || !autozoomEnabled)
       return;
 
     if (Browser.selectedTab.allowZoom) {
       let zoomLevel = Browser._getZoomLevelForRect(aElementRect);
-      zoomLevel = Math.min(Math.max(kBrowserFormZoomLevelMin, zoomLevel), kBrowserFormZoomLevelMax);
+
+      // Clamp the zoom level relatively to the default zoom level of the page
+      let defaultZoomLevel = Browser.selectedTab.getDefaultZoomLevel();
+      zoomLevel = Util.clamp(zoomLevel, (defaultZoomLevel * kBrowserFormZoomLevelMin),
+                                        (defaultZoomLevel * kBrowserFormZoomLevelMax));
       zoomLevel = Browser.selectedTab.clampZoomLevel(zoomLevel);
 
       let zoomRect = Browser._getZoomRectForPoint(aElementRect.center().x, aElementRect.y, zoomLevel);
       AnimatedZoom.animateTo(zoomRect);
     } else {
       // Even if zooming is disabled we could need to reposition the view in
       // order to keep the element on-screen
       let zoomRect = Browser._getZoomRectForPoint(aElementRect.center().x, aElementRect.y, getBrowser().scale);
@@ -1145,17 +1189,21 @@ var FormHelperUI = {
     getBrowser().scale = restore.scale;
     Browser.contentScrollboxScroller.scrollTo(restore.contentScrollOffset.x, restore.contentScrollOffset.y);
     Browser.pageScrollboxScroller.scrollTo(restore.pageScrollOffset.x, restore.pageScrollOffset.y);
   },
 
   _getZoomLevelForRect: function _getZoomLevelForRect(aRect) {
     const margin = 30;
     let zoomLevel = getBrowser().getBoundingClientRect().width / (aRect.width + margin);
-    return Util.clamp(zoomLevel, kBrowserFormZoomLevelMin, kBrowserFormZoomLevelMax);
+
+    // Clamp the zoom level relatively to the default zoom level of the page
+    let defaultZoomLevel = Browser.selectedTab.getDefaultZoomLevel();
+    return Util.clamp(zoomLevel, (defaultZoomLevel * kBrowserFormZoomLevelMin),
+                                 (defaultZoomLevel * kBrowserFormZoomLevelMax));
   },
 
   _getOffsetForCaret: function _formHelperGetOffsetForCaret(aCaretRect, aRect) {
     // Determine if we need to move left or right to bring the caret into view
     let deltaX = 0;
     if (aCaretRect.right > aRect.right)
       deltaX = aCaretRect.right - aRect.right;
     if (aCaretRect.left < aRect.left)
--- a/mobile/chrome/content/preferences.js
+++ b/mobile/chrome/content/preferences.js
@@ -34,17 +34,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 var PreferencesView = {
   _currentLocale: null,
   _languages: null,
   _msg: null,
-  _restartCount: 0,
 
   _messageActions: function pv__messageActions(aData) {
     if (aData == "prefs-restart-app") {
       // Notify all windows that an application quit has been requested
       var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
       Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
 
       // If nothing aborted, quit the app
@@ -73,29 +72,25 @@ var PreferencesView = {
         }
       } ];
     }
 
     this._msg.appendNotification(aMsg, aValue, "", this._msg.PRIORITY_WARNING_LOW, buttons).hideclose = !aShowCloseButton;
   },
 
   showRestart: function ev_showRestart() {
-    // Increment the count in case the view is not completely initialized
-    this._restartCount++;
-
     if (this._msg) {
       let strings = Strings.browser;
       this.showMessage(strings.GetStringFromName("notificationRestart.normal"), "restart-app",
                        strings.GetStringFromName("notificationRestart.button"), false, "prefs-restart-app");
     }
   },
 
   hideRestart: function ev_hideRestart() {
-    this._restartCount--;
-    if (this._restartCount == 0 && this._msg) {
+    if (this._msg) {
       let notification = this._msg.getNotificationWithValue("restart-app");
       if (notification)
         notification.close();
     }
   },
 
   delayedInit: function pv__delayedInit() {
     if (this._languages)
@@ -107,20 +102,20 @@ var PreferencesView = {
 
     this._loadHomePage();
   },
 
   _loadLocales: function _loadLocales() {
     // Query available and selected locales
     let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
     chrome.QueryInterface(Ci.nsIToolkitChromeRegistry);
-    
+
     let selectedLocale = chrome.getSelectedLocale("browser");
     let availableLocales = chrome.getLocalesForPackage("browser");
-    
+
     let strings = Services.strings.createBundle("chrome://browser/content/languages.properties");
 
     // Render locale menulist by iterating through the query result from getLocalesForPackage()
     let selectedItem = null;
     let localeCount = 0;
     while (availableLocales.hasMore()) {
       let locale = availableLocales.getNext();
       try {
@@ -137,25 +132,25 @@ var PreferencesView = {
     }
 
     // Are we using auto-detection?
     let autoDetect = false;
     try {
       autoDetect = Services.prefs.getBoolPref("intl.locale.matchOS");
     }
     catch (e) {}
-    
+
     // Highlight current locale (or auto-detect entry)
     if (autoDetect) {
       this._languages.selectedItem = document.getElementById("prefs-languages-auto");
       this._currentLocale = "auto";
     } else {
       this._languages.selectedItem = selectedItem;
     }
-    
+
     // Hide the setting if we only have one locale
     if (localeCount == 1)
       document.getElementById("prefs-uilanguage").hidden = true;
   },
 
   updateLocale: function updateLocale() {
     // Which locale did the user select?
     let newLocale = this._languages.selectedItem.value;
--- a/mobile/themes/core/aboutHome.css
+++ b/mobile/themes/core/aboutHome.css
@@ -120,17 +120,18 @@ html {
   color: black;
 }
 
 body[dir="ltr"] .section-box .openall {
   text-align: right;
 }
 
 .section-box .version {
-  -moz-margin-start: 12px;
+  /* The addon title is not localized, so keep the margin on the left side */
+  margin-left: 12px;
   font-size: 18px;
   color: gray;
 }
 
 .section-box .inner {
   pointer-events: none;
 }
 
--- a/mobile/themes/core/browser.css
+++ b/mobile/themes/core/browser.css
@@ -651,16 +651,21 @@ placeitem > .bookmark-manage .bookmark-c
 placeitem[ui="manage"] {
   border-bottom: 0;
 }
 
 placeitem[ui="manage"] > .bookmark-manage > image {
   visibility: collapse;
 }
 
+/* making the url textbox right-aligned for rtl locales */
+placeitem[ui="manage"] > .bookmark-manage textbox[anonid="uri"]:-moz-locale-dir(rtl) {
+  text-align: right;
+}
+
 /* autocomplete-items */
 .autocomplete-items {
   background-color: white;
 }
 
 autocompleteresult,
 placeitem {
   -moz-user-focus: ignore;
--- a/mobile/themes/core/config.css
+++ b/mobile/themes/core/config.css
@@ -55,17 +55,17 @@ richlistitem .preftitle {
 richlistitem[default="false"] .preftitle {
   font-weight: bold;
 }
 
 richlistitem .prefvalue {
   min-width: 200px;
   pointer-events: none;
   -moz-box-flex: 4;
-  text-align: right;
+  text-align: end;
   color: grey;
 }
 
 /* Editor */
 #editor-row {
   padding: 0;
   background: #E9E9E9;
 }
@@ -109,12 +109,20 @@ richlistitem .prefvalue {
 #editor-setting[type="string"] .setting-input {
   -moz-box-flex: 4;
 }
 
 #editor-setting[type="string"] .setting-input > textbox {
   -moz-box-flex: 1;
 }
 
+/* bug 647650: keep 'text-align: right' here instead of using start/end since 
+ * the field should looks like ltr as much as possible
+ */
+#editor-setting[type="string"] .setting-input > textbox:-moz-locale-dir(rtl) {
+  direction: ltr;
+  text-align: right;
+}
+
 #editor-buttons {
   margin: 2px;
 }
 
--- a/modules/plugin/test/testplugin/Makefile.in
+++ b/modules/plugin/test/testplugin/Makefile.in
@@ -51,19 +51,22 @@ STL_FLAGS =
 
 # must link statically with the CRT; nptest isn't Gecko code
 USE_STATIC_LIBS = 1
 
 # Need to custom install plugins
 NO_DIST_INSTALL	= 1
 NO_INSTALL = 1
 
+VPATH += $(topsrcdir)/build
+
 CPPSRCS   =  \
   nptest.cpp \
   nptest_utils.cpp \
+  $(STDCXX_COMPAT) \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 CMMSRCS = nptest_macosx.mm
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 CPPSRCS += nptest_gtk2.cpp
--- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp
+++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp
@@ -121,16 +121,34 @@ nsMIMEHeaderParamImpl::GetParameter(cons
 
     if (aTryLocaleCharset && !NS_IsNativeUTF8()) 
       return NS_CopyNativeToUnicode(str1, aResult);
 
     CopyASCIItoUTF16(str1, aResult);
     return NS_OK;
 }
 
+// remove backslash-encoded sequences from quoted-strings
+// modifies string in place, potentially shortening it
+void RemoveQuotedStringEscapes(char *src)
+{
+  char *dst = src;
+
+  for (char *c = src; *c; ++c)
+  {
+    if (c[0] == '\\' && c[1])
+    {
+      // skip backslash if not at end
+      ++c;
+    }
+    *dst++ = *c;
+  }
+  *dst = 0;
+}
+
 // moved almost verbatim from mimehdrs.cpp
 // char *
 // MimeHeaders_get_parameter (const char *header_value, const char *parm_name,
 //                            char **charset, char **language)
 //
 // The format of these header lines  is
 // <token> [ ';' <token> '=' <token-or-quoted-string> ]*
 NS_IMETHODIMP 
@@ -211,29 +229,33 @@ nsMIMEHeaderParamImpl::GetParameterInter
       ;
     tokenEnd = str;
 
     // Skip over whitespace, '=', and whitespace
     while (nsCRT::IsAsciiSpace(*str)) ++str;
     if (*str == '=') ++str;
     while (nsCRT::IsAsciiSpace(*str)) ++str;
 
+    PRBool needUnquote = PR_FALSE;
+    
     if (*str != '"')
     {
       // The value is a token, not a quoted string.
       valueStart = str;
       for (valueEnd = str;
            *valueEnd && !nsCRT::IsAsciiSpace (*valueEnd) && *valueEnd != ';';
            valueEnd++)
         ;
       str = valueEnd;
     }
     else
     {
-      // The value is a quoted string. 
+      // The value is a quoted string.
+      needUnquote = PR_TRUE;
+      
       ++str;
       valueStart = str;
       for (valueEnd = str; *valueEnd; ++valueEnd)
       {
         if (*valueEnd == '\\')
           ++valueEnd;
         else if (*valueEnd == '"')
           break;
@@ -246,18 +268,24 @@ nsMIMEHeaderParamImpl::GetParameterInter
     // If so, copy it and return.
     if (tokenEnd - tokenStart == paramLen &&
         !nsCRT::strncasecmp(tokenStart, aParamName, paramLen))
     {
       // if the parameter spans across multiple lines we have to strip out the
       //     line continuation -- jht 4/29/98 
       nsCAutoString tempStr(valueStart, valueEnd - valueStart);
       tempStr.StripChars("\r\n");
-      *aResult = ToNewCString(tempStr);
-      NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
+      char *res = ToNewCString(tempStr);
+      NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY);
+      
+      if (needUnquote)
+        RemoveQuotedStringEscapes(res);
+            
+      *aResult = res;
+      
       // keep going, we may find a RFC 2231 encoded alternative
     }
     // case B, C, and D
     else if (tokenEnd - tokenStart > paramLen &&
              !nsCRT::strncasecmp(tokenStart, aParamName, paramLen) &&
              *(tokenStart + paramLen) == '*')
     {
       const char *cp = tokenStart + paramLen + 1; // 1st char pass '*'
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug588389.js
@@ -0,0 +1,39 @@
+/**
+ * Test for bug 588389: unescaping backslashes in quoted string parameters
+ */
+
+var BS = '\\';
+var DQUOTE = '"'; 
+ 
+var reference = [
+                 [ // '\"', should be parsed as '"'
+                  "Content-Disposition: attachment; foobar=" + DQUOTE + (BS + DQUOTE) + DQUOTE, 
+                  DQUOTE],
+                 [ // 'a\"b', should be parsed as 'a"b'
+                  "Content-Disposition: attachment; foobar=" + DQUOTE + 'a' + (BS + DQUOTE) + 'b' + DQUOTE, 
+                  'a' + DQUOTE + 'b'],
+                 [ // '\x', should be parsed as 'x'
+                  "Content-Disposition: attachment; foobar=" + DQUOTE + (BS + "x") + DQUOTE, 
+                  "x"],
+                 [ // test empty param (quoted-string)
+                  "Content-Disposition: attachment; foobar=" + DQUOTE + DQUOTE, 
+                  ""],
+                 [ // test empty param
+                  "Content-Disposition: attachment; foobar=", 
+                  ""],
+                ];
+
+function run_test() {
+
+  var mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
+                      .getService(Components.interfaces.nsIMIMEHeaderParam);
+
+  var unused = { value : null };
+
+  for (var i = 0; i < reference.length; ++i) {
+    dump("Testing " + reference[i] + "\n");
+    do_check_eq(mhp.getParameter(reference[i][0], "foobar", "UTF-8", true, unused),
+                reference[i][1]);
+  }
+}
+
--- a/toolkit/components/search/Makefile.in
+++ b/toolkit/components/search/Makefile.in
@@ -44,9 +44,13 @@ VPATH     = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 EXTRA_COMPONENTS = toolkitsearch.manifest
 EXTRA_PP_COMPONENTS = nsSearchService.js \
 	nsSearchSuggestions.js
 
 DEFINES += -DMOZ_DISTRIBUTION_ID=$(MOZ_DISTRIBUTION_ID)
 
+ifdef ENABLE_TESTS
+DIRS += tests
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -2863,17 +2863,17 @@ SearchService.prototype = {
 
     rootURIs.forEach(function (root) {
       // Find the underlying JAR file for this chrome package (_loadEngines uses
       // it to determine whether it needs to invalidate the cache)
       let chromeFile;
       try {
         let chromeURI = gChromeReg.convertChromeURL(makeURI(root));
         let fileURI = chromeURI; // flat packaging
-        if (fileURI instanceof Ci.nsIJARURI)
+        while (fileURI instanceof Ci.nsIJARURI)
           fileURI = fileURI.JARFile; // JAR packaging
         fileURI.QueryInterface(Ci.nsIFileURL);
         chromeFile = fileURI.file;
       } catch (ex) {
         LOG("_findJAREngines: failed to get chromeFile for " + root + ": " + ex);
       }
 
       if (!chromeFile)
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/Makefile.in
@@ -0,0 +1,49 @@
+# ***** 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 mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla.org.
+# Portions created by the Initial Developer are Copyright (C) 2005
+# 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 *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir = toolkit/components/search/tests
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= test_searchservice
+
+XPCSHELL_TESTS = xpcshell
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/data/chrome.manifest
@@ -0,0 +1,1 @@
+locale testsearchplugin ar jar:jar:searchTest.jar!/chrome/searchTest.jar!/
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3882ae938f1df50ea037fbc17b1be2331a5b2da2
GIT binary patch
literal 776
zc$^FHW@h1HW&ncUb9?O=kN`UnCubDp=ceih02PS<6>%_p2P&FzJ^q&x69dB`AQnX^
zDo#x-O3nyLEiTc^N-V0Kl<N}|C~^F~Xh8W<x6iq}v$k#g6)=nEY)e>RSW*71SXGma
zPrdop?N%w%FFmgAc{)yjYZfni^lFpEnROi3W9kev58Y!+p0;+a;KtUdHK~ikQl`(j
zdF(~~w>NV(|2<b<J@3DxAe(R!!<MwSccUBYw>0T3+WD|zvR8BV)EkCL$#c#wyZOcb
zO>w{R7Fm{t-<k{ud=sR%p7K>)`ZV>Z>lCT?#`c*rHJ-ics%yVyQ?_H%1AQ%C>tL?u
zqOX4b43D>+aQB??^}9Mft`CKc7cI72y!xH*jlE{;y&2!HJ*v6-!<>&IN@eraN>*n0
z^4{OCm$7<A&3eJlJ&nJb&u(`(>b)WAdnHS)$+3wMWl_Ep?*@7^N56gi?Z@x)3GYr9
zZ&g|onl7h$JzAFS{Ir)RLfDUmc}2$;_vY{V)wz>D&a>g=I+v%+I}GFX%sv!VZT_aQ
z;8^za<1C?vR#vHLi|yKN@P^}4EPv=G?i;VPZ&_s(Ki}=+=-Rl&*r?a+Y<Td)34eZh
z*8l2%*O1S#?alkbO>s8DOG9PlEUfjm#79|1^m*{7ez@c|Pe@nxaB6wVyqjiwwaoWC
z?s%Vca?h^U4)34b{<v`K?OQqXH#j;!UC$cu;quIl{U%e}k`EMlcvXFfPxra6@JnX>
zotA@-B^<>jiu^QZ;BY-KCC6>kgy}~z|7$P`-4VO5#$D^l`quo5^uPbCV!e~hH|AVn
zSIg#fjaXUO<*3iUm;K<6x8?!fj7%cTxYHg42sFHPWI#@dAWgW_A_OQjENN85l`;do
RS=m5}n1HYXNLMj|cmNsFKCu7*
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/head_search.js
@@ -0,0 +1,92 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** 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 Initial Developer of the Original Code is POTI Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
+const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");
+
+var gXULAppInfo = null;
+
+/**
+ * Creates an nsIXULAppInfo
+ * @param   id
+ *          The ID of the test application
+ * @param   name
+ *          A name for the test application
+ * @param   version
+ *          The version of the application
+ * @param   platformVersion
+ *          The gecko version of the application
+ */
+function createAppInfo(id, name, version, platformVersion)
+{
+  gXULAppInfo = {
+    vendor: "Mozilla",
+    name: name,
+    ID: id,
+    version: version,
+    appBuildID: "2007010101",
+    platformVersion: platformVersion,
+    platformBuildID: "2007010101",
+    inSafeMode: false,
+    logConsoleErrors: true,
+    OS: "XPCShell",
+    XPCOMABI: "noarch-spidermonkey",
+    invalidateCachesOnRestart: function invalidateCachesOnRestart() {},
+
+    QueryInterface: function QueryInterface(iid) {
+      if (iid.equals(Components.interfaces.nsIXULAppInfo)
+       || iid.equals(Components.interfaces.nsIXULRuntime)
+       || iid.equals(Components.interfaces.nsISupports))
+        return this;
+
+      throw Components.results.NS_ERROR_NO_INTERFACE;
+    }
+  };
+
+  var XULAppInfoFactory = {
+    createInstance: function (outer, iid) {
+      if (outer != null)
+        throw Components.results.NS_ERROR_NO_AGGREGATION;
+      return gXULAppInfo.QueryInterface(iid);
+    }
+  };
+  var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
+  registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo",
+                            XULAPPINFO_CONTRACTID, XULAppInfoFactory);
+}
+
+// Need to create and register a profile folder.
+var gProfD = do_get_profile();
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/test_645970.js
@@ -0,0 +1,62 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** 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 Initial Developer of the Original Code is POTI Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+let Cc = Components.classes;
+let Ci = Components.interfaces;
+
+var gPrefService = Cc["@mozilla.org/preferences-service;1"]
+                    .getService(Ci.nsIPrefService)
+                    .QueryInterface(Ci.nsIPrefBranch);
+/**
+ * Test nsSearchService with nested jar: uris
+ */
+function run_test() {
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2");
+
+  do_load_manifest("data/chrome.manifest");
+
+  let url  = "chrome://testsearchplugin/locale/searchplugins/";
+  gPrefService.setCharPref("browser.search.jarURIs", url);
+
+  gPrefService.setBoolPref("browser.search.loadFromJars", true);
+
+  // The search service needs to be started after the jarURIs pref has been
+  // set in order to initiate it correctly
+  let searchService = Cc["@mozilla.org/browser/search-service;1"]
+                       .getService(Ci.nsIBrowserSearchService);
+  let engine = searchService.getEngineByName("bug645970");
+  do_check_neq(engine, null);
+}
+
--- a/toolkit/crashreporter/client/Makefile.in
+++ b/toolkit/crashreporter/client/Makefile.in
@@ -53,17 +53,22 @@ STL_FLAGS =
 
 ifneq ($(OS_TARGET),Android)
 PROGRAM = crashreporter$(BIN_SUFFIX)
 DIST_PROGRAM = crashreporter$(BIN_SUFFIX)
 endif
 
 LOCAL_INCLUDES = -I$(srcdir)/../google-breakpad/src
 
-CPPSRCS = crashreporter.cpp
+VPATH += $(topsrcdir)/build/
+
+CPPSRCS = \
+  crashreporter.cpp \
+  $(STDCXX_COMPAT) \
+  $(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 CPPSRCS += crashreporter_win.cpp
 LIBS += \
   $(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/windows/sender/$(LIB_PREFIX)crash_report_sender_s.$(LIB_SUFFIX) \
   $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/windows/$(LIB_PREFIX)breakpad_windows_common_s.$(LIB_SUFFIX) \
   $(NULL)
 LOCAL_INCLUDES += -I$(srcdir)
--- a/toolkit/crashreporter/test/Makefile.in
+++ b/toolkit/crashreporter/test/Makefile.in
@@ -47,25 +47,27 @@ MODULE = crashreporter_test
 XPCSHELL_TESTS = unit
 
 LIBRARY_NAME = testcrasher
 NO_DIST_INSTALL = 1
 
 VPATH += \
   $(srcdir)/../google-breakpad/src/processor/ \
   $(srcdir)/../google-breakpad/src/common/ \
+  $(topsrcdir)/build/ \
   $(NULL)
 
 CPPSRCS = \
   nsTestCrasher.cpp \
   dumputils.cpp \
   basic_code_modules.cc \
   logging.cc \
   minidump.cc \
   pathname_stripper.cc \
+  $(STDCXX_COMPAT) \
   $(NULL)
 
 LOCAL_INCLUDES += \
   -I$(XPIDL_GEN_DIR) \
   -I$(srcdir)/../google-breakpad/src/ \
   $(NULL)
 EXTRA_DSO_LIBS += xpcom
 EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(MOZ_COMPONENT_LIBS)
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -58,16 +58,18 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 # "libxul.dylib"
 LIBRARY_NAME=XUL
 # Setting MAKE_FRAMEWORK makes DLL_PREFIX and DLL_SUFFIX be ignored when
 # setting SHARED_LIBRARY; we need to leave DLL_PREFIX and DLL_SUFFIX
 # as-is so that dependencies of the form -ltracemalloc still work.
 MAKE_FRAMEWORK=1
 endif
 
+VPATH += $(topsrcdir)/build/
+CPPSRCS += $(STDCXX_COMPAT)
 
 ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
 CPPSRCS += dlldeps-xul.cpp
 endif
 
 ifeq ($(OS_ARCH),WINCE)
 CPPSRCS += dlldeps-xul.cpp
 endif
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -53,17 +53,17 @@
 #include "nsNativeWidget.h"
 #include "nsWidgetInitData.h"
 #include "nsTArray.h"
 #include "nsXULAppAPI.h"
 
 // forward declarations
 class   nsIAppShell;
 class   nsIToolkit;
-class   nsIFontMetrics;
+class   nsFontMetrics;
 class   nsRenderingContext;
 class   nsIDeviceContext;
 struct  nsFont;
 class   nsIRollupListener;
 class   nsIMenuRollup;
 class   nsGUIEvent;
 class   imgIContainer;
 class   gfxASurface;
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -53,17 +53,17 @@
 
 #include "nsObjCExceptions.h"
 #include "nsCOMPtr.h"
 #include "nsToolkit.h"
 #include "nsCRT.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsIDeviceContext.h"
 #include "nsIRegion.h"
 #include "nsIRollupListener.h"
 #include "nsIViewManager.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIServiceManager.h"
 #include "nsILocalFile.h"
 #include "nsILocalFileMac.h"
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -131,17 +131,17 @@
 #include "nsIFile.h"
 #include "nsIRollupListener.h"
 #include "nsIMenuRollup.h"
 #include "nsIRegion.h"
 #include "nsIServiceManager.h"
 #include "nsIClipboard.h"
 #include "nsIMM32Handler.h"
 #include "nsILocalFile.h"
-#include "nsIFontMetrics.h"
+#include "nsFontMetrics.h"
 #include "nsIFontEnumerator.h"
 #include "nsIDeviceContext.h"
 #include "nsILookAndFeel.h"
 #include "nsGUIEvent.h"
 #include "nsFont.h"
 #include "nsRect.h"
 #include "nsThreadUtils.h"
 #include "nsNativeCharsetUtils.h"
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -59,30 +59,32 @@ DIRS		= external component
 ifeq ($(OS_ARCH),WINNT)
 DIRS		+= windows
 endif
 
 ifdef DEHYDRA_PATH
 DIRS += static-checker
 endif
 
+VPATH += $(topsrcdir)/build
 
-CPPSRCS		= \
-		nsIFileEnumerator.cpp \
-		TestCallTemplates.cpp \
-		TestINIParser.cpp \
-		TestRacingServiceManager.cpp \
-		TestRegistrationOrder.cpp \
-		TestThreadPoolListener.cpp \
-		TestTimers.cpp \
-		TestBlockingProcess.cpp \
-		TestQuickReturn.cpp \
-		TestArguments.cpp \
-		TestUnicodeArguments.cpp \
-		$(NULL)
+CPPSRCS = \
+  nsIFileEnumerator.cpp \
+  TestCallTemplates.cpp \
+  TestINIParser.cpp \
+  TestRacingServiceManager.cpp \
+  TestRegistrationOrder.cpp \
+  TestThreadPoolListener.cpp \
+  TestTimers.cpp \
+  TestBlockingProcess.cpp \
+  TestQuickReturn.cpp \
+  TestArguments.cpp \
+  TestUnicodeArguments.cpp \
+  $(STDCPPFLAGS) \
+  $(NULL)
 
 ifdef WRAP_STL_INCLUDES
 CPPSRCS += TestSTLWrappers.cpp
 endif
 
 SIMPLE_PROGRAMS	:= $(CPPSRCS:.cpp=$(BIN_SUFFIX))
 
 CPP_UNIT_TESTS = \
@@ -219,8 +221,13 @@ check::
 		exit 1; \
 	fi
 	$(RM_DIST) $(DIST_PATH)components/compreg.dat; \
 	$(DOCOPY) \
 	XPCOM_DEBUG_BREAK=stack-and-abort $(RUN_TEST_PROGRAM) \
 	  $(DIST)/bin/TestRegistrationOrder$(BIN_SUFFIX) $(regOrderDir)
 
 GARBAGE += TestScriptable.h
+
+ifdef STDCXX_COMPAT
+TestCheckedInt: $(STDCXX_COMPAT:.cpp=.$(OBJ_SUFFIX))
+TestCheckedInt: LIBS += $(STDCXX_COMPAT:.cpp=.$(OBJ_SUFFIX))
+endif