Bug 1088625, part 2 - Pass nsFontMetrics objects through to code that needs it instead of storing it on the nsRenderingContext. r=mstange
authorJonathan Watt <jwatt@jwatt.org>
Fri, 24 Oct 2014 16:28:14 +0100
changeset 236569 36f87acce2f9edacd33300c0acc3ea3b7f742d04
parent 236568 6d6117a79a0ef2de724404d23f27389203e2e2e2
child 236570 d0ab048707562b3a34c218dd31436c616986ba47
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1088625
milestone36.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
Bug 1088625, part 2 - Pass nsFontMetrics objects through to code that needs it instead of storing it on the nsRenderingContext. r=mstange
layout/base/nsBidiPresUtils.cpp
layout/base/nsBidiPresUtils.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/TextOverflow.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsImageFrame.h
layout/generic/nsPageFrame.cpp
layout/generic/nsPageFrame.h
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLFrame.cpp
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmfencedFrame.cpp
layout/mathml/nsMathMLmfencedFrame.h
layout/mathml/nsMathMLmrootFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/xul/nsListBoxBodyFrame.cpp
layout/xul/nsTextBoxFrame.cpp
layout/xul/nsTextBoxFrame.h
layout/xul/tree/nsTreeBodyFrame.cpp
layout/xul/tree/nsTreeBodyFrame.h
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -2050,72 +2050,84 @@ nsresult nsBidiPresUtils::ProcessText(co
   } // for
 
   if (aWidth) {
     *aWidth = totalWidth;
   }
   return NS_OK;
 }
 
-class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor : public nsBidiPresUtils::BidiProcessor {
+class MOZ_STACK_CLASS nsIRenderingContextBidiProcessor MOZ_FINAL
+  : public nsBidiPresUtils::BidiProcessor
+{
 public:
   nsIRenderingContextBidiProcessor(nsRenderingContext* aCtx,
                                    nsRenderingContext* aTextRunConstructionContext,
+                                   nsFontMetrics* aFontMetrics,
                                    const nsPoint&       aPt)
-    : mCtx(aCtx), mTextRunConstructionContext(aTextRunConstructionContext), mPt(aPt) { }
+    : mCtx(aCtx)
+    , mTextRunConstructionContext(aTextRunConstructionContext)
+    , mFontMetrics(aFontMetrics)
+    , mPt(aPt)
+  {}
 
   ~nsIRenderingContextBidiProcessor()
   {
-    mCtx->SetTextRunRTL(false);
+    mFontMetrics->SetTextRunRTL(false);
   }
 
   virtual void SetText(const char16_t* aText,
                        int32_t          aLength,
                        nsBidiDirection  aDirection) MOZ_OVERRIDE
   {
-    mTextRunConstructionContext->SetTextRunRTL(aDirection==NSBIDI_RTL);
+    mFontMetrics->SetTextRunRTL(aDirection==NSBIDI_RTL);
     mText = aText;
     mLength = aLength;
   }
 
   virtual nscoord GetWidth() MOZ_OVERRIDE
   {
-    return nsLayoutUtils::AppUnitWidthOfString(mText, mLength,
+    return nsLayoutUtils::AppUnitWidthOfString(mText, mLength, *mFontMetrics,
                                                *mTextRunConstructionContext);
   }
 
   virtual void DrawText(nscoord aXOffset,
                         nscoord) MOZ_OVERRIDE
   {
-    mCtx->FontMetrics()->DrawString(mText, mLength, mPt.x + aXOffset, mPt.y,
-                                    mCtx, mTextRunConstructionContext);
+    mFontMetrics->DrawString(mText, mLength, mPt.x + aXOffset, mPt.y,
+                             mCtx, mTextRunConstructionContext);
   }
 
 private:
   nsRenderingContext* mCtx;
   nsRenderingContext* mTextRunConstructionContext;
+  nsFontMetrics* mFontMetrics;
   nsPoint mPt;
   const char16_t* mText;
   int32_t mLength;
 };
 
 nsresult nsBidiPresUtils::ProcessTextForRenderingContext(const char16_t*       aText,
                                                          int32_t                aLength,
                                                          nsBidiLevel            aBaseLevel,
                                                          nsPresContext*         aPresContext,
                                                          nsRenderingContext&   aRenderingContext,
                                                          nsRenderingContext&   aTextRunConstructionContext,
+                                                         nsFontMetrics&         aFontMetrics,
                                                          Mode                   aMode,
                                                          nscoord                aX,
                                                          nscoord                aY,
                                                          nsBidiPositionResolve* aPosResolve,
                                                          int32_t                aPosResolveCount,
                                                          nscoord*               aWidth)
 {
-  nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY));
+  nsIRenderingContextBidiProcessor processor(&aRenderingContext,
+                                             &aTextRunConstructionContext,
+                                             &aFontMetrics,
+                                             nsPoint(aX, aY));
   nsBidi bidiEngine;
   return ProcessText(aText, aLength, aBaseLevel, aPresContext, processor,
                      aMode, aPosResolve, aPosResolveCount, aWidth, &bidiEngine);
 }
 
 /* static */
 void nsBidiPresUtils::WriteReverse(const char16_t* aSrc,
                                    uint32_t aSrcLength,
--- a/layout/base/nsBidiPresUtils.h
+++ b/layout/base/nsBidiPresUtils.h
@@ -13,16 +13,17 @@
 #include "nsCoord.h"
 
 #ifdef DrawText
 #undef DrawText
 #endif
 
 struct BidiParagraphData;
 struct BidiLineData;
+class nsFontMetrics;
 class nsIFrame;
 class nsBlockFrame;
 class nsPresContext;
 class nsRenderingContext;
 class nsBlockInFlowLineIterator;
 class nsStyleContext;
 template<class T> class nsTHashtable;
 namespace mozilla { class WritingMode; }
@@ -201,34 +202,39 @@ public:
    * @param aPosResolveCount number of items in the aPosResolve array
    */
   static nsresult RenderText(const char16_t*       aText,
                              int32_t                aLength,
                              nsBidiLevel            aBaseLevel,
                              nsPresContext*         aPresContext,
                              nsRenderingContext&    aRenderingContext,
                              nsRenderingContext&    aTextRunConstructionContext,
+                             nsFontMetrics&         aFontMetrics,
                              nscoord                aX,
                              nscoord                aY,
                              nsBidiPositionResolve* aPosResolve = nullptr,
                              int32_t                aPosResolveCount = 0)
   {
     return ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext, aRenderingContext,
-                                          aTextRunConstructionContext, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
+                                          aTextRunConstructionContext,
+                                          aFontMetrics,
+                                          MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
   }
   
   static nscoord MeasureTextWidth(const char16_t*     aText,
                                   int32_t              aLength,
                                   nsBidiLevel          aBaseLevel,
                                   nsPresContext*       aPresContext,
-                                  nsRenderingContext&  aRenderingContext)
+                                  nsRenderingContext&  aRenderingContext,
+                                  nsFontMetrics&       aFontMetrics)
   {
     nscoord length;
     nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext,
                                                  aRenderingContext, aRenderingContext,
+                                                 aFontMetrics,
                                                  MODE_MEASURE, 0, 0, nullptr, 0, &length);
     return NS_SUCCEEDED(rv) ? length : 0;
   }
 
   /**
    * Check if a line is reordered, i.e., if the child frames are not
    * all laid out left-to-right.
    * @param aFirstFrameOnLine : first frame of the line to be tested
@@ -355,16 +361,17 @@ public:
 private:
   static nsresult
   ProcessTextForRenderingContext(const char16_t*       aText,
                                  int32_t                aLength,
                                  nsBidiLevel            aBaseLevel,
                                  nsPresContext*         aPresContext,
                                  nsRenderingContext&    aRenderingContext,
                                  nsRenderingContext&    aTextRunConstructionContext,
+                                 nsFontMetrics&         aFontMetrics,
                                  Mode                   aMode,
                                  nscoord                aX, // DRAW only
                                  nscoord                aY, // DRAW only
                                  nsBidiPositionResolve* aPosResolve,  /* may be null */
                                  int32_t                aPosResolveCount,
                                  nscoord*               aWidth /* may be null */);
 
   /**
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3182,55 +3182,62 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
  * of the text that has already been measured, and aBaseInx contains
  * the index of the text that has already been measured.
  *
  * @param aTextWidth returns the (in twips) the length of the text that falls
  * before the cursor aIndex contains the index of the text where the cursor falls
  */
 bool
 nsLayoutUtils::BinarySearchForPosition(nsRenderingContext* aRendContext,
+                                       nsFontMetrics& aFontMetrics,
                         const char16_t* aText,
                         int32_t    aBaseWidth,
                         int32_t    aBaseInx,
                         int32_t    aStartInx,
                         int32_t    aEndInx,
                         int32_t    aCursorPos,
                         int32_t&   aIndex,
                         int32_t&   aTextWidth)
 {
   int32_t range = aEndInx - aStartInx;
   if ((range == 1) || (range == 2 && NS_IS_HIGH_SURROGATE(aText[aStartInx]))) {
     aIndex   = aStartInx + aBaseInx;
     aTextWidth = nsLayoutUtils::AppUnitWidthOfString(aText, aIndex,
+                                                     aFontMetrics,
                                                      *aRendContext);
     return true;
   }
 
   int32_t inx = aStartInx + (range / 2);
 
   // Make sure we don't leave a dangling low surrogate
   if (NS_IS_HIGH_SURROGATE(aText[inx-1]))
     inx++;
 
   int32_t textWidth = nsLayoutUtils::AppUnitWidthOfString(aText, inx,
+                                                          aFontMetrics,
                                                           *aRendContext);
 
   int32_t fullWidth = aBaseWidth + textWidth;
   if (fullWidth == aCursorPos) {
     aTextWidth = textWidth;
     aIndex = inx;
     return true;
   } else if (aCursorPos < fullWidth) {
     aTextWidth = aBaseWidth;
-    if (BinarySearchForPosition(aRendContext, aText, aBaseWidth, aBaseInx, aStartInx, inx, aCursorPos, aIndex, aTextWidth)) {
+    if (BinarySearchForPosition(aRendContext, aFontMetrics, aText, aBaseWidth,
+                                aBaseInx, aStartInx, inx, aCursorPos, aIndex,
+                                aTextWidth)) {
       return true;
     }
   } else {
     aTextWidth = fullWidth;
-    if (BinarySearchForPosition(aRendContext, aText, aBaseWidth, aBaseInx, inx, aEndInx, aCursorPos, aIndex, aTextWidth)) {
+    if (BinarySearchForPosition(aRendContext, aFontMetrics, aText, aBaseWidth,
+                                aBaseInx, inx, aEndInx, aCursorPos, aIndex,
+                                aTextWidth)) {
       return true;
     }
   }
   return false;
 }
 
 static void
 AddBoxesForFrame(nsIFrame* aFrame,
@@ -4661,142 +4668,151 @@ static int32_t FindSafeLength(const char
 
 static int32_t GetMaxChunkLength(nsFontMetrics& aFontMetrics)
 {
   return std::min(aFontMetrics.GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
 }
 
 nscoord
 nsLayoutUtils::AppUnitWidthOfString(const nsString& aString,
+                                    nsFontMetrics& aFontMetrics,
                                     nsRenderingContext& aContext)
 {
-  return AppUnitWidthOfString(aString.get(), aString.Length(), aContext);
+  return AppUnitWidthOfString(aString.get(), aString.Length(),
+                              aFontMetrics, aContext);
 }
 
 nscoord
 nsLayoutUtils::AppUnitWidthOfString(const char16_t *aString,
                                     uint32_t aLength,
+                                    nsFontMetrics& aFontMetrics,
                                     nsRenderingContext& aContext)
 {
-  uint32_t maxChunkLength = GetMaxChunkLength(*aContext.FontMetrics());
+  uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
   nscoord width = 0;
   while (aLength > 0) {
     int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
-    width += aContext.FontMetrics()->GetWidth(aString, len, &aContext);
+    width += aFontMetrics.GetWidth(aString, len, &aContext);
     aLength -= len;
     aString += len;
   }
   return width;
 }
 
 nsBoundingMetrics
 nsLayoutUtils::AppUnitBoundsOfString(const char16_t* aString,
                                      uint32_t aLength,
+                                     nsFontMetrics& aFontMetrics,
                                      nsRenderingContext& aContext)
 {
-  uint32_t maxChunkLength = GetMaxChunkLength(*aContext.FontMetrics());
+  uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
   int32_t 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 =
-    aContext.FontMetrics()->GetBoundingMetrics(aString, len, &aContext);
+    aFontMetrics.GetBoundingMetrics(aString, len, &aContext);
   aLength -= len;
   aString += len;
 
   while (aLength > 0) {
     len = FindSafeLength(aString, aLength, maxChunkLength);
     nsBoundingMetrics metrics =
-      aContext.FontMetrics()->GetBoundingMetrics(aString, len, &aContext);
+      aFontMetrics.GetBoundingMetrics(aString, len, &aContext);
     totalMetrics += metrics;
     aLength -= len;
     aString += len;
   }
   return totalMetrics;
 }
 
 void
 nsLayoutUtils::DrawString(const nsIFrame*       aFrame,
+                          nsFontMetrics&        aFontMetrics,
                           nsRenderingContext*   aContext,
                           const char16_t*      aString,
                           int32_t               aLength,
                           nsPoint               aPoint,
                           nsStyleContext*       aStyleContext)
 {
   nsresult rv = NS_ERROR_FAILURE;
   nsPresContext* presContext = aFrame->PresContext();
   if (presContext->BidiEnabled()) {
     nsBidiLevel level =
       nsBidiPresUtils::BidiLevelFromStyle(aStyleContext ?
                                           aStyleContext : aFrame->StyleContext());
     rv = nsBidiPresUtils::RenderText(aString, aLength, level,
                                      presContext, *aContext, *aContext,
+                                     aFontMetrics,
                                      aPoint.x, aPoint.y);
   }
   if (NS_FAILED(rv))
   {
-    aContext->SetTextRunRTL(false);
-    DrawUniDirString(aString, aLength, aPoint, *aContext);
+    aFontMetrics.SetTextRunRTL(false);
+    DrawUniDirString(aString, aLength, aPoint, aFontMetrics, *aContext);
   }
 }
 
 void
 nsLayoutUtils::DrawUniDirString(const char16_t* aString,
                                 uint32_t aLength,
                                 nsPoint aPoint,
+                                nsFontMetrics& aFontMetrics,
                                 nsRenderingContext& aContext)
 {
   nscoord x = aPoint.x;
   nscoord y = aPoint.y;
 
-  nsFontMetrics* fm = aContext.FontMetrics();
-
-  uint32_t maxChunkLength = GetMaxChunkLength(*aContext.FontMetrics());
+  uint32_t maxChunkLength = GetMaxChunkLength(aFontMetrics);
   if (aLength <= maxChunkLength) {
-    fm->DrawString(aString, aLength, x, y, &aContext, &aContext);
+    aFontMetrics.DrawString(aString, aLength, x, y, &aContext, &aContext);
     return;
   }
 
-  bool isRTL = fm->GetTextRunRTL();
+  bool isRTL = aFontMetrics.GetTextRunRTL();
 
   // If we're drawing right to left, we must start at the end.
   if (isRTL) {
-    x += nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aContext);
+    x += nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aFontMetrics,
+                                             aContext);
   }
 
   while (aLength > 0) {
     int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
-    nscoord width = fm->GetWidth(aString, len, &aContext);
+    nscoord width = aFontMetrics.GetWidth(aString, len, &aContext);
     if (isRTL) {
       x -= width;
     }
-    fm->DrawString(aString, len, x, y, &aContext, &aContext);
+    aFontMetrics.DrawString(aString, len, x, y, &aContext, &aContext);
     if (!isRTL) {
       x += width;
     }
     aLength -= len;
     aString += len;
   }
 }
 
 nscoord
 nsLayoutUtils::GetStringWidth(const nsIFrame*      aFrame,
                               nsRenderingContext* aContext,
+                              nsFontMetrics&      aFontMetrics,
                               const char16_t*     aString,
                               int32_t              aLength)
 {
   nsPresContext* presContext = aFrame->PresContext();
   if (presContext->BidiEnabled()) {
     nsBidiLevel level =
       nsBidiPresUtils::BidiLevelFromStyle(aFrame->StyleContext());
     return nsBidiPresUtils::MeasureTextWidth(aString, aLength,
-                                             level, presContext, *aContext);
-  }
-  aContext->SetTextRunRTL(false);
-  return nsLayoutUtils::AppUnitWidthOfString(aString, aLength, *aContext);
+                                             level, presContext, *aContext,
+                                             aFontMetrics);
+  }
+  aFontMetrics.SetTextRunRTL(false);
+  return nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aFontMetrics,
+                                             *aContext);
 }
 
 /* static */ void
 nsLayoutUtils::PaintTextShadow(const nsIFrame* aFrame,
                                nsRenderingContext* aContext,
                                const nsRect& aTextRect,
                                const nsRect& aDirtyRect,
                                const nscolor& aForegroundColor,
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -954,16 +954,17 @@ public:
    * the index of the text that has already been measured.
    *
    * @param aTextWidth returns (in twips) the length of the text that falls
    * before the cursor aIndex contains the index of the text where the cursor
    * falls.
    */
   static bool
   BinarySearchForPosition(nsRenderingContext* acx,
+                          nsFontMetrics& aFontMetrics,
                           const char16_t* aText,
                           int32_t    aBaseWidth,
                           int32_t    aBaseInx,
                           int32_t    aStartInx,
                           int32_t    aEndInx,
                           int32_t    aCursorPos,
                           int32_t&   aIndex,
                           int32_t&   aTextWidth);
@@ -1314,45 +1315,52 @@ public:
   // Get a suitable foreground color for painting aProperty for aFrame.
   static nscolor GetColor(nsIFrame* aFrame, nsCSSProperty aProperty);
 
   // Get a baseline y position in app units that is snapped to device pixels.
   static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
                                       nscoord aY, nscoord aAscent);
 
   static nscoord AppUnitWidthOfString(char16_t aC,
+                                      nsFontMetrics& aFontMetrics,
                                       nsRenderingContext& aContext) {
-    return AppUnitWidthOfString(&aC, 1, aContext);
+    return AppUnitWidthOfString(&aC, 1, aFontMetrics, aContext);
   }
   static nscoord AppUnitWidthOfString(const nsString& aString,
+                                      nsFontMetrics& aFontMetrics,
                                       nsRenderingContext& aContext);
   static nscoord AppUnitWidthOfString(const char16_t *aString,
                                       uint32_t aLength,
+                                      nsFontMetrics& aFontMetrics,
                                       nsRenderingContext& aContext);
   static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString,
                                                  uint32_t aLength,
+                                                 nsFontMetrics& aFontMetrics,
                                                  nsRenderingContext& aContext);
 
   static void DrawString(const nsIFrame*       aFrame,
+                         nsFontMetrics&        aFontMetrics,
                          nsRenderingContext*   aContext,
                          const char16_t*      aString,
                          int32_t               aLength,
                          nsPoint               aPoint,
                          nsStyleContext*       aStyleContext = nullptr);
 
   /**
    * Supports only LTR or RTL. Bidi (mixed direction) is not supported.
    */
   static void DrawUniDirString(const char16_t* aString,
                                uint32_t aLength,
                                nsPoint aPoint,
+                               nsFontMetrics& aFontMetrics,
                                nsRenderingContext& aContext);
 
   static nscoord GetStringWidth(const nsIFrame*      aFrame,
                                 nsRenderingContext* aContext,
+                                nsFontMetrics&      aFontMetrics,
                                 const char16_t*     aString,
                                 int32_t              aLength);
 
   /**
    * Helper function for drawing text-shadow. The callback's job
    * is to draw whatever needs to be blurred onto the given context.
    */
   typedef void (* TextShadowCallback)(nsRenderingContext* aCtx,
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -235,17 +235,17 @@ nsDisplayTextOverflowMarker::PaintTextTo
       textRun->Draw(aCtx->ThebesContext(), gfxPt, DrawMode::GLYPH_FILL,
                     0, textRun->GetLength(), nullptr, nullptr, nullptr);
     }
   } else {
     nsRefPtr<nsFontMetrics> fm;
     nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm),
       nsLayoutUtils::FontSizeInflationFor(mFrame));
     aCtx->SetFont(fm);
-    nsLayoutUtils::DrawString(mFrame, aCtx, mStyle->mString.get(),
+    nsLayoutUtils::DrawString(mFrame, *fm, aCtx, mStyle->mString.get(),
                               mStyle->mString.Length(), pt);
   }
 }
 
 void
 TextOverflow::Init(nsDisplayListBuilder*   aBuilder,
                    nsIFrame*               aBlockFrame)
 {
@@ -760,17 +760,18 @@ TextOverflow::Marker::SetupString(nsIFra
     }
   } else {
     nsRefPtr<nsRenderingContext> rc =
       aFrame->PresContext()->PresShell()->CreateReferenceRenderingContext();
     nsRefPtr<nsFontMetrics> fm;
     nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm),
       nsLayoutUtils::FontSizeInflationFor(aFrame));
     rc->SetFont(fm);
-    mWidth = nsLayoutUtils::GetStringWidth(aFrame, rc, mStyle->mString.get(),
+    mWidth = nsLayoutUtils::GetStringWidth(aFrame, rc, *fm,
+                                           mStyle->mString.get(),
                                            mStyle->mString.Length());
   }
   mIntrinsicISize = mWidth;
   mInitialized = true;
 }
 
 }  // namespace css
 }  // namespace mozilla
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -433,17 +433,17 @@ nsBulletFrame::PaintBullet(nsRenderingCo
     nscoord ascent = fm->MaxAscent();
     aPt.MoveBy(padding.left, padding.top);
     aPt.y = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineY(
             this, aRenderingContext.ThebesContext(), aPt.y, ascent));
     nsPresContext* presContext = PresContext();
     if (!presContext->BidiEnabled() && HasRTLChars(text)) {
       presContext->SetBidiEnabled();
     }
-    nsLayoutUtils::DrawString(this, &aRenderingContext,
+    nsLayoutUtils::DrawString(this, *fm, &aRenderingContext,
                               text.get(), text.Length(), aPt);
     break;
   }
 }
 
 int32_t
 nsBulletFrame::SetListItemOrdinal(int32_t aNextOrdinal,
                                   bool* aChanged,
@@ -599,17 +599,17 @@ nsBulletFrame::GetDesiredSize(nsPresCont
       AppendSpacingToPadding(fm);
       break;
 
     default:
       GetListItemText(text);
       finalSize.BSize(wm) = fm->MaxHeight();
       aRenderingContext->SetFont(fm);
       finalSize.ISize(wm) =
-        nsLayoutUtils::GetStringWidth(this, aRenderingContext,
+        nsLayoutUtils::GetStringWidth(this, aRenderingContext, *fm,
                                       text.get(), text.Length());
       aMetrics.SetBlockStartAscent(fm->MaxAscent());
       break;
   }
   aMetrics.SetSize(wm, finalSize);
 }
 
 void
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1008,38 +1008,39 @@ nsImageFrame::ReflowCallbackCanceled()
 // The number of characters that fit within the maximum width are returned in
 // aMaxFit. NOTE: it is assumed that the fontmetrics have already been selected
 // into the rendering context before this is called (for performance). MMP
 nscoord
 nsImageFrame::MeasureString(const char16_t*     aString,
                             int32_t              aLength,
                             nscoord              aMaxWidth,
                             uint32_t&            aMaxFit,
-                            nsRenderingContext& aContext)
+                            nsRenderingContext& aContext,
+                            nsFontMetrics& aFontMetrics)
 {
   nscoord totalWidth = 0;
-  aContext.FontMetrics()->SetTextRunRTL(false);
-  nscoord spaceWidth = aContext.FontMetrics()->SpaceWidth();
+  aFontMetrics.SetTextRunRTL(false);
+  nscoord spaceWidth = aFontMetrics.SpaceWidth();
 
   aMaxFit = 0;
   while (aLength > 0) {
     // Find the next place we can line break
     uint32_t  len = aLength;
     bool      trailingSpace = false;
     for (int32_t i = 0; i < aLength; i++) {
       if (dom::IsSpaceCharacter(aString[i]) && (i > 0)) {
         len = i;  // don't include the space when measuring
         trailingSpace = true;
         break;
       }
     }
   
     // Measure this chunk of text, and see if it fits
     nscoord width =
-      nsLayoutUtils::GetStringWidth(this, &aContext, aString, len);
+      nsLayoutUtils::GetStringWidth(this, &aContext, aFontMetrics, aString, len);
     bool    fits = (totalWidth + width) <= aMaxWidth;
 
     // If it fits on the line, or it's the first word we've processed then
     // include it
     if (fits || (0 == totalWidth)) {
       // New piece fits
       totalWidth += width;
 
@@ -1101,37 +1102,37 @@ nsImageFrame::DisplayAltText(nsPresConte
   }
 
   // Always show the first line, even if we have to clip it below
   bool firstLine = true;
   while ((strLen > 0) && (firstLine || (y + maxDescent) < aRect.YMost())) {
     // Determine how much of the text to display on this line
     uint32_t  maxFit;  // number of characters that fit
     nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
-                                     aRenderingContext);
+                                     aRenderingContext, *fm);
     
     // Display the text
     nsresult rv = NS_ERROR_FAILURE;
 
     if (aPresContext->BidiEnabled()) {
       const nsStyleVisibility* vis = StyleVisibility();
       if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
         rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
                                          aPresContext, aRenderingContext,
-                                         aRenderingContext,
+                                         aRenderingContext, *fm,
                                          aRect.XMost() - strWidth, y + maxAscent);
       else
         rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
                                          aPresContext, aRenderingContext,
-                                         aRenderingContext,
+                                         aRenderingContext, *fm,
                                          aRect.x, y + maxAscent);
     }
     if (NS_FAILED(rv)) {
       nsLayoutUtils::DrawUniDirString(str, maxFit,
-                                      nsPoint(aRect.x, y + maxAscent),
+                                      nsPoint(aRect.x, y + maxAscent), *fm,
                                       aRenderingContext);
     }
 
     // Move to the next line
     str += maxFit;
     strLen -= maxFit;
     y += height;
     firstLine = false;
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -16,16 +16,17 @@
 
 #include "nsDisplayList.h"
 #include "imgIContainer.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "nsIReflowCallback.h"
 #include "nsTObserverArray.h"
 
+class nsFontMetrics;
 class nsImageMap;
 class nsIURI;
 class nsILoadGroup;
 struct nsHTMLReflowState;
 class nsHTMLReflowMetrics;
 class nsDisplayImage;
 class nsPresContext;
 class nsImageFrame;
@@ -200,17 +201,18 @@ protected:
    * @param out aMaxFit length of the string that fits within aMaxWidth
    *            in PRUnichars
    * @return width of the string that fits within aMaxWidth
    */
   nscoord MeasureString(const char16_t*     aString,
                         int32_t              aLength,
                         nscoord              aMaxWidth,
                         uint32_t&            aMaxFit,
-                        nsRenderingContext& aContext);
+                        nsRenderingContext& aContext,
+                        nsFontMetrics&      aFontMetrics);
 
   void DisplayAltText(nsPresContext*      aPresContext,
                       nsRenderingContext& aRenderingContext,
                       const nsString&      aAltText,
                       const nsRect&        aRect);
 
   void PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
                   const nsRect& aDirtyRect, imgIContainer* aImage,
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -232,22 +232,24 @@ nsPageFrame::ProcessSpecialCodes(const n
     char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat.get(), mTotNumPages);
     aNewStr.ReplaceSubstring(kPageTotal.get(), uStr);
     nsMemory::Free(uStr);
   }
 }
 
 
 //------------------------------------------------------------------------------
-nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext, 
+nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
+                                  nsFontMetrics&       aFontMetrics,
                                   const nsRect&        aRect, 
                                   int32_t              aJust,
                                   const nsString&      aStr)
 {
   nscoord width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
+                                                aFontMetrics,
                                                 aStr.get(), aStr.Length());
 
   nscoord x = aRect.x;
   switch (aJust) {
     case nsIPrintSettings::kJustLeft:
       x += mPD->mEdgePaperMargin.left;
       break;
 
@@ -269,16 +271,17 @@ nscoord nsPageFrame::GetXPosition(nsRend
 // @param aStrLeft - string for the left header or footer; can be empty
 // @param aStrCenter - string for the center header or footer; can be empty
 // @param aStrRight - string for the right header or footer; can be empty
 // @param aRect - the rect of the page
 // @param aAscent - the ascent of the font
 // @param aHeight - the height of the font
 void
 nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
+                              nsFontMetrics&       aFontMetrics,
                               nsHeaderFooterEnum   aHeaderFooter,
                               const nsString&      aStrLeft,
                               const nsString&      aStrCenter,
                               const nsString&      aStrRight,
                               const nsRect&        aRect,
                               nscoord              aAscent,
                               nscoord              aHeight)
 {
@@ -286,43 +289,44 @@ nsPageFrame::DrawHeaderFooter(nsRenderin
   if (!aStrLeft.IsEmpty()) numStrs++;
   if (!aStrCenter.IsEmpty()) numStrs++;
   if (!aStrRight.IsEmpty()) numStrs++;
 
   if (numStrs == 0) return;
   nscoord strSpace = aRect.width / numStrs;
 
   if (!aStrLeft.IsEmpty()) {
-    DrawHeaderFooter(aRenderingContext, aHeaderFooter,
+    DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
                      nsIPrintSettings::kJustLeft, aStrLeft, aRect, aAscent,
                      aHeight, strSpace);
   }
   if (!aStrCenter.IsEmpty()) {
-    DrawHeaderFooter(aRenderingContext, aHeaderFooter,
+    DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
                      nsIPrintSettings::kJustCenter, aStrCenter, aRect, aAscent,
                      aHeight, strSpace);
   }
   if (!aStrRight.IsEmpty()) {
-    DrawHeaderFooter(aRenderingContext, aHeaderFooter,
+    DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
                      nsIPrintSettings::kJustRight, aStrRight, aRect, aAscent,
                      aHeight, strSpace);
   }
 }
 
 // Draw a header or footer string
 // @param aRenderingContext - rendering context to draw into
 // @param aHeaderFooter - indicates whether it is a header or footer
 // @param aJust - indicates where the string is located within the header/footer
 // @param aStr - the string to be drawn
 // @param aRect - the rect of the page
 // @param aHeight - the height of the font
 // @param aAscent - the ascent of the font
 // @param aWidth - available width for the string
 void
 nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
+                              nsFontMetrics&       aFontMetrics,
                               nsHeaderFooterEnum   aHeaderFooter,
                               int32_t              aJust,
                               const nsString&      aStr,
                               const nsRect&        aRect,
                               nscoord              aAscent,
                               nscoord              aHeight,
                               nscoord              aWidth)
 {
@@ -338,17 +342,18 @@ nsPageFrame::DrawHeaderFooter(nsRenderin
     int32_t textWidth = 0;
     const char16_t* text = str.get();
 
     int32_t len = (int32_t)str.Length();
     if (len == 0) {
       return; // bail is empty string
     }
     // find how much text fits, the "position" is the size of the available area
-    if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext, text, 0, 0, 0, len,
+    if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext, aFontMetrics,
+                                               text, 0, 0, 0, len,
                                 int32_t(contentWidth), indx, textWidth)) {
       if (indx < len-1 ) {
         // we can't fit in all the text
         if (indx > 3) {
           // But we can fit in at least 4 chars.  Show all but 3 of them, then
           // an ellipsis.
           // XXXbz for non-plane0 text, this may be cutting things in the
           // middle of a codepoint!  Also, we have no guarantees that the three
@@ -365,33 +370,35 @@ nsPageFrame::DrawHeaderFooter(nsRenderin
       return; // bail if couldn't find the correct length
     }
     
     if (HasRTLChars(str)) {
       PresContext()->SetBidiEnabled();
     }
 
     // cacl the x and y positions of the text
-    nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str);
+    nscoord x = GetXPosition(aRenderingContext, aFontMetrics, aRect, aJust, str);
     nscoord y;
     if (aHeaderFooter == eHeader) {
       y = aRect.y + mPD->mEdgePaperMargin.top;
     } else {
       y = aRect.YMost() - aHeight - mPD->mEdgePaperMargin.bottom;
     }
 
     DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     gfxContext* gfx = aRenderingContext.ThebesContext();
 
     // set up new clip and draw the text
     gfx->Save();
     gfx->Clip(NSRectToSnappedRect(aRect, PresContext()->AppUnitsPerDevPixel(),
                                   *drawTarget));
     aRenderingContext.ThebesContext()->SetColor(NS_RGB(0,0,0));
-    nsLayoutUtils::DrawString(this, &aRenderingContext, str.get(), str.Length(), nsPoint(x, y + aAscent));
+    nsLayoutUtils::DrawString(this, aFontMetrics, &aRenderingContext,
+                              str.get(), str.Length(),
+                              nsPoint(x, y + aAscent));
     gfx->Restore();
   }
 }
 
 /**
  * Remove all leaf display items that are not for descendants of
  * aBuilder->GetReferenceFrame() from aList.
  * @param aPage the page we're constructing the display list for
@@ -607,25 +614,25 @@ nsPageFrame::PaintHeaderFooter(nsRenderi
     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,
+  DrawHeaderFooter(aRenderingContext, *fontMet, eHeader,
                    headerLeft, headerCenter, headerRight,
                    rect, ascent, visibleHeight);
 
   nsXPIDLString footerLeft, footerCenter, footerRight;
   mPD->mPrintSettings->GetFooterStrLeft(getter_Copies(footerLeft));
   mPD->mPrintSettings->GetFooterStrCenter(getter_Copies(footerCenter));
   mPD->mPrintSettings->GetFooterStrRight(getter_Copies(footerRight));
-  DrawHeaderFooter(aRenderingContext, eFooter,
+  DrawHeaderFooter(aRenderingContext, *fontMet, eFooter,
                    footerLeft, footerCenter, footerRight,
                    rect, ascent, visibleHeight);
 }
 
 void
 nsPageFrame::SetSharedPageData(nsSharedPageData* aPD) 
 { 
   mPD = aPD;
--- a/layout/generic/nsPageFrame.h
+++ b/layout/generic/nsPageFrame.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsPageFrame_h___
 #define nsPageFrame_h___
 
 #include "mozilla/Attributes.h"
 #include "nsContainerFrame.h"
 #include "nsLeafFrame.h"
 
+class nsFontMetrics;
 class nsSharedPageData;
 
 // Page frame class used by the simple page sequence frame
 class nsPageFrame MOZ_FINAL : public nsContainerFrame {
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
@@ -60,31 +61,34 @@ protected:
   explicit nsPageFrame(nsStyleContext* aContext);
   virtual ~nsPageFrame();
 
   typedef enum {
     eHeader,
     eFooter
   } nsHeaderFooterEnum;
 
-  nscoord GetXPosition(nsRenderingContext& aRenderingContext, 
+  nscoord GetXPosition(nsRenderingContext& aRenderingContext,
+                       nsFontMetrics&       aFontMetrics,
                        const nsRect&        aRect, 
                        int32_t              aJust,
                        const nsString&      aStr);
 
   void DrawHeaderFooter(nsRenderingContext& aRenderingContext,
+                        nsFontMetrics&       aFontMetrics,
                         nsHeaderFooterEnum   aHeaderFooter,
                         int32_t              aJust,
                         const nsString&      sStr,
                         const nsRect&        aRect,
                         nscoord              aHeight,
                         nscoord              aAscent,
                         nscoord              aWidth);
 
   void DrawHeaderFooter(nsRenderingContext& aRenderingContext,
+                        nsFontMetrics&       aFontMetrics,
                         nsHeaderFooterEnum   aHeaderFooter,
                         const nsString&      aStrLeft,
                         const nsString&      aStrRight,
                         const nsString&      aStrCenter,
                         const nsRect&        aRect,
                         nscoord              aAscent,
                         nscoord              aHeight);
 
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -54,17 +54,17 @@ nsMathMLContainerFrame::ReflowError(nsRe
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   aRenderingContext.SetFont(fm);
 
   // bounding metrics
   nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
   mBoundingMetrics =
     nsLayoutUtils::AppUnitBoundsOfString(errorMsg.get(), errorMsg.Length(),
-                                         aRenderingContext);
+                                         *fm, aRenderingContext);
 
   // reflow metrics
   WritingMode wm = aDesiredSize.GetWritingMode();
   aDesiredSize.SetBlockStartAscent(fm->MaxAscent());
   nscoord descent = fm->MaxDescent();
   aDesiredSize.BSize(wm) = aDesiredSize.BlockStartAscent() + descent;
   aDesiredSize.ISize(wm) = mBoundingMetrics.width;
 
@@ -104,22 +104,20 @@ void nsDisplayMathMLError::Paint(nsDispl
   DrawTarget* drawTarget = aCtx->GetDrawTarget();
   Rect rect = NSRectToSnappedRect(nsRect(pt, mFrame->GetSize()),
                                   appUnitsPerDevPixel,
                                   *drawTarget);
   ColorPattern red(ToDeviceColor(Color(1.f, 0.f, 0.f, 1.f)));
   drawTarget->FillRect(rect, red);
 
   aCtx->ThebesContext()->SetColor(NS_RGB(255,255,255));
-  nscoord ascent = aCtx->FontMetrics()->MaxAscent();
+  nscoord ascent = fm->MaxAscent();
   NS_NAMED_LITERAL_STRING(errorMsg, "invalid-markup");
-  nsLayoutUtils::DrawUniDirString(errorMsg.get(),
-                                  uint32_t(errorMsg.Length()),
-                                  nsPoint(pt.x, pt.y + ascent),
-                                  *aCtx);
+  nsLayoutUtils::DrawUniDirString(errorMsg.get(), uint32_t(errorMsg.Length()),
+                                  nsPoint(pt.x, pt.y + ascent), *fm, *aCtx);
 }
 
 /* /////////////
  * nsIMathMLFrame - support methods for stretchy elements
  * =============================================================================
  */
 
 static bool
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -176,17 +176,18 @@ nsMathMLFrame::GetRuleThickness(nsRender
   // 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->XHeight();
   char16_t overBar = 0x00AF;
   nsBoundingMetrics bm =
-    nsLayoutUtils::AppUnitBoundsOfString(&overBar, 1, aRenderingContext);
+    nsLayoutUtils::AppUnitBoundsOfString(&overBar, 1, *aFontMetrics,
+                                         aRenderingContext);
   aRuleThickness = bm.ascent + bm.descent;
   if (aRuleThickness <= 0 || aRuleThickness >= xHeight) {
     // fall-back to the other version
     GetRuleThickness(aFontMetrics, aRuleThickness);
   }
 }
 
 /* static */ void
@@ -206,17 +207,18 @@ nsMathMLFrame::GetAxisHeight(nsRendering
   // 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->XHeight();
   char16_t minus = 0x2212; // not '-', but official Unicode minus sign
   nsBoundingMetrics bm =
-    nsLayoutUtils::AppUnitBoundsOfString(&minus, 1, aRenderingContext);
+    nsLayoutUtils::AppUnitBoundsOfString(&minus, 1, *aFontMetrics,
+                                         aRenderingContext);
   aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2;
   if (aAxisHeight <= 0 || aAxisHeight >= xHeight) {
     // fall-back to the other version
     GetAxisHeight(aFontMetrics, aAxisHeight);
   }
 }
 
 /* static */ nscoord
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -348,17 +348,17 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
   aRenderingContext.SetFont(fm);
   GetRuleThickness(aRenderingContext, fm, mRuleThickness);
   if (mRuleThickness < onePixel) {
     mRuleThickness = onePixel;
   }
 
   char16_t one = '1';
   nsBoundingMetrics bmOne =
-    nsLayoutUtils::AppUnitBoundsOfString(&one, 1, aRenderingContext);
+    nsLayoutUtils::AppUnitBoundsOfString(&one, 1, *fm, aRenderingContext);
 
   ///////////////
   // General rules: the menclose element takes the size of the enclosed content.
   // We add a padding when needed.
 
   // determine padding & psi
   nscoord padding = 3 * mRuleThickness;
   nscoord delta = padding % onePixel;
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -335,29 +335,29 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   // we need to center around the axis
   nscoord delta = std::max(containerSize.ascent - axisHeight, 
                          containerSize.descent + axisHeight);
   containerSize.ascent = delta + axisHeight;
   containerSize.descent = delta - axisHeight;
 
   /////////////////
   // opening fence ...
-  ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar,
+  ReflowChar(aPresContext, *aReflowState.rendContext, *fm, mOpenChar,
              NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, 
              axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   /////////////////
   // separators ...
   for (i = 0; i < mSeparatorsCount; i++) {
-    ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i],
+    ReflowChar(aPresContext, *aReflowState.rendContext, *fm, &mSeparatorsChar[i],
                NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
                axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   }
   /////////////////
   // closing fence ...
-  ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar,
+  ReflowChar(aPresContext, *aReflowState.rendContext, *fm, mCloseChar,
              NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
              axisHeight, leading, em, containerSize, ascent, descent, isRTL);
 
   //////////////////
   // Adjust the origins of each child.
   // and update our bounding metrics
 
   i = 0;
@@ -465,16 +465,17 @@ GetCharSpacing(nsMathMLChar*        aMat
   aLeftSpace = NSToCoordRound(lspace * em);
   aRightSpace = NSToCoordRound(rspace * em);
 }
 
 // helper functions to perform the common task of formatting our chars
 /*static*/ nsresult
 nsMathMLmfencedFrame::ReflowChar(nsPresContext*      aPresContext,
                                  nsRenderingContext& aRenderingContext,
+                                 nsFontMetrics&       aFontMetrics,
                                  nsMathMLChar*        aMathMLChar,
                                  nsOperatorFlags      aForm,
                                  int32_t              aScriptLevel,
                                  nscoord              axisHeight,
                                  nscoord              leading,
                                  nscoord              em,
                                  nsBoundingMetrics&   aContainerSize,
                                  nscoord&             aAscent,
@@ -503,17 +504,17 @@ nsMathMLmfencedFrame::ReflowChar(nsPresC
       // either it hasn't changed or stretching the char failed (i.e.,
       // nsLayoutUtils::AppUnitBoundsOfString failed)
       leading = 0;
       if (NS_FAILED(res)) {
         nsAutoString data;
         aMathMLChar->GetData(data);
         nsBoundingMetrics metrics =
           nsLayoutUtils::AppUnitBoundsOfString(data.get(), data.Length(),
-                                               aRenderingContext);
+                                               aFontMetrics, aRenderingContext);
         charSize.ascent = metrics.ascent;
         charSize.descent = metrics.descent;
         charSize.width = metrics.width;
         // Set this as the bounding metrics of the MathMLChar to leave
         // the necessary room to paint the char.
         aMathMLChar->SetBoundingMetrics(charSize);
       }
     }
--- a/layout/mathml/nsMathMLmfencedFrame.h
+++ b/layout/mathml/nsMathMLmfencedFrame.h
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsMathMLmfencedFrame_h
 #define nsMathMLmfencedFrame_h
 
 #include "mozilla/Attributes.h"
 #include "nsMathMLContainerFrame.h"
 
+class nsFontMetrics;
+
 //
 // <mfenced> -- surround content with a pair of fences
 //
 
 class nsMathMLmfencedFrame MOZ_FINAL : public nsMathMLContainerFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
@@ -58,16 +60,17 @@ public:
   // override the base method so that we can deal with fences and separators
   virtual nscoord
   FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE;
 
   // helper routines to format the MathMLChars involved here
   static nsresult
   ReflowChar(nsPresContext*      aPresContext,
              nsRenderingContext& aRenderingContext,
+             nsFontMetrics&       aFontMetrics,
              nsMathMLChar*        aMathMLChar,
              nsOperatorFlags      aForm,
              int32_t              aScriptLevel,
              nscoord              axisHeight,
              nscoord              leading,
              nscoord              em,
              nsBoundingMetrics&   aContainerSize,
              nscoord&             aAscent,
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -230,17 +230,17 @@ nsMathMLmrootFrame::Reflow(nsPresContext
   nscoord ruleThickness, leading, psi;
   GetRadicalParameters(fm, StyleFont()->mMathDisplay ==
                        NS_MATHML_DISPLAYSTYLE_BLOCK,
                        ruleThickness, leading, psi);
 
   // built-in: adjust clearance psi to emulate \mathstrut using '1' (TexBook, p.131)
   char16_t one = '1';
   nsBoundingMetrics bmOne =
-    nsLayoutUtils::AppUnitBoundsOfString(&one, 1, renderingContext);
+    nsLayoutUtils::AppUnitBoundsOfString(&one, 1, *fm, renderingContext);
   if (bmOne.ascent > bmBase.ascent)
     psi += bmOne.ascent - bmBase.ascent;
 
   // make sure that the rule appears on on screen
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
   if (ruleThickness < onePixel) {
     ruleThickness = onePixel;
   }
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -854,19 +854,17 @@ nsMathMLmtableOuterFrame::Reflow(nsPresC
       break;
     case eAlign_axis:
     default: {
       // XXX should instead use style data from the row of reference here ?
       nsRefPtr<nsFontMetrics> fm;
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
       aReflowState.rendContext->SetFont(fm);
       nscoord axisHeight;
-      GetAxisHeight(*aReflowState.rendContext,
-                    aReflowState.rendContext->FontMetrics(),
-                    axisHeight);
+      GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
       if (rowFrame) {
         // anchor the table on the axis of the row of reference
         // XXX fallback to baseline because it is a hard problem
         // XXX need to fetch the axis of the row; would need rowalign=axis to work better
         nscoord rowAscent = ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent();
         if (rowAscent) { // the row has at least one cell with 'vertical-align: baseline'
           aDesiredSize.SetBlockStartAscent(dy + rowAscent);
           break;
--- a/layout/xul/nsListBoxBodyFrame.cpp
+++ b/layout/xul/nsListBoxBodyFrame.cpp
@@ -723,17 +723,18 @@ nsListBoxBodyFrame::ComputeIntrinsicISiz
           }
 
           nsRefPtr<nsFontMetrics> fm;
           nsLayoutUtils::GetFontMetricsForStyleContext(styleContext,
                                                        getter_AddRefs(fm));
           rendContext->SetFont(fm);
 
           nscoord textWidth =
-            nsLayoutUtils::GetStringWidth(this, rendContext, value.get(), value.Length());
+            nsLayoutUtils::GetStringWidth(this, rendContext, *fm,
+                                          value.get(), value.Length());
           textWidth += width;
 
           if (textWidth > largestWidth) 
             largestWidth = textWidth;
         }
       }
     }
   }
--- a/layout/xul/nsTextBoxFrame.cpp
+++ b/layout/xul/nsTextBoxFrame.cpp
@@ -499,17 +499,17 @@ nsTextBoxFrame::DrawText(nsRenderingCont
     }
 
     nsRefPtr<nsRenderingContext> refContext =
         PresContext()->PresShell()->CreateReferenceRenderingContext();
 
     aRenderingContext.SetFont(fontMet);
     refContext->SetFont(fontMet);
 
-    CalculateUnderline(*refContext);
+    CalculateUnderline(*refContext, *fontMet);
 
     nscolor c = aOverrideColor ? *aOverrideColor : StyleColor()->mColor;
     ColorPattern color(ToDeviceColor(c));
     aRenderingContext.ThebesContext()->SetColor(c);
 
     nsresult rv = NS_ERROR_FAILURE;
 
     if (mState & NS_FRAME_IS_BIDI) {
@@ -517,43 +517,43 @@ nsTextBoxFrame::DrawText(nsRenderingCont
       nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(StyleContext());
       if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
           // We let the RenderText function calculate the mnemonic's
           // underline position for us.
           nsBidiPositionResolve posResolve;
           posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex;
           rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level,
                                            presContext, aRenderingContext,
-                                           *refContext,
+                                           *refContext, *fontMet,
                                            aTextRect.x, baseline,
                                            &posResolve,
                                            1);
           mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips;
           mAccessKeyInfo->mAccessWidth = posResolve.visualWidth;
       }
       else
       {
           rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level,
                                            presContext, aRenderingContext,
-                                           *refContext,
+                                           *refContext, *fontMet,
                                            aTextRect.x, baseline);
       }
     }
     if (NS_FAILED(rv)) {
-       aRenderingContext.SetTextRunRTL(false);
+       fontMet->SetTextRunRTL(false);
 
        if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
            // In the simple (non-BiDi) case, we calculate the mnemonic's
            // underline position by getting the text metric.
            // XXX are attribute values always two byte?
            if (mAccessKeyInfo->mAccesskeyIndex > 0)
                mAccessKeyInfo->mBeforeWidth = nsLayoutUtils::
                    AppUnitWidthOfString(mCroppedTitle.get(),
                                         mAccessKeyInfo->mAccesskeyIndex,
-                                        *refContext);
+                                        *fontMet, *refContext);
            else
                mAccessKeyInfo->mBeforeWidth = 0;
        }
 
        fontMet->DrawString(mCroppedTitle.get(), mCroppedTitle.Length(),
                            aTextRect.x, baseline, &aRenderingContext,
                            refContext.get());
     }
@@ -578,31 +578,31 @@ nsTextBoxFrame::DrawText(nsRenderingCont
       nsCSSRendering::PaintDecorationLine(this, ctx, dirtyRect, strikeColor,
                         pt, xInFrame, gfxSize(width, sizePixel), ascentPixel,
                         offsetPixel, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
                         strikeStyle, vertical);
     }
 }
 
 void
-nsTextBoxFrame::CalculateUnderline(nsRenderingContext& aRenderingContext)
+nsTextBoxFrame::CalculateUnderline(nsRenderingContext& aRenderingContext,
+                                   nsFontMetrics& aFontMetrics)
 {
     if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
          // Calculate all fields of mAccessKeyInfo which
          // are the same for both BiDi and non-BiDi frames.
          const char16_t *titleString = mCroppedTitle.get();
-         aRenderingContext.SetTextRunRTL(false);
+         aFontMetrics.SetTextRunRTL(false);
          mAccessKeyInfo->mAccessWidth = nsLayoutUtils::
              AppUnitWidthOfString(titleString[mAccessKeyInfo->mAccesskeyIndex],
-                                  aRenderingContext);
+                                  aFontMetrics, aRenderingContext);
 
          nscoord offset, baseline;
-         nsFontMetrics* metrics = aRenderingContext.FontMetrics();
-         metrics->GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize);
-         baseline = metrics->MaxAscent();
+         aFontMetrics.GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize);
+         baseline = aFontMetrics.MaxAscent();
          mAccessKeyInfo->mAccessOffset = baseline - offset;
     }
 }
 
 nscoord
 nsTextBoxFrame::CalculateTitleForWidth(nsPresContext*      aPresContext,
                                        nsRenderingContext& aRenderingContext,
                                        nscoord              aWidth)
@@ -613,34 +613,35 @@ nsTextBoxFrame::CalculateTitleForWidth(n
     }
 
     nsRefPtr<nsFontMetrics> fm;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
     aRenderingContext.SetFont(fm);
 
     // see if the text will completely fit in the width given
     nscoord titleWidth = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
+                                                       *fm,
                                                        mTitle.get(), mTitle.Length());
 
     if (titleWidth <= aWidth) {
         mCroppedTitle = mTitle;
         if (HasRTLChars(mTitle)) {
             mState |= NS_FRAME_IS_BIDI;
         }
         return titleWidth;  // fits, done.
     }
 
     const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
     // start with an ellipsis
     mCroppedTitle.Assign(kEllipsis);
 
     // see if the width is even smaller than the ellipsis
     // if so, clear the text (XXX set as many '.' as we can?).
-    aRenderingContext.SetTextRunRTL(false);
-    titleWidth = nsLayoutUtils::AppUnitWidthOfString(kEllipsis,
+    fm->SetTextRunRTL(false);
+    titleWidth = nsLayoutUtils::AppUnitWidthOfString(kEllipsis, *fm,
                                                      aRenderingContext);
 
     if (titleWidth > aWidth) {
         mCroppedTitle.SetLength(0);
         return 0;
     }
 
     // if the ellipsis fits perfectly, no use in trying to insert
@@ -659,18 +660,18 @@ nsTextBoxFrame::CalculateTitleForWidth(n
         {
             nscoord cwidth;
             nscoord twidth = 0;
             int length = mTitle.Length();
             int i;
             for (i = 0; i < length; ++i) {
                 char16_t ch = mTitle.CharAt(i);
                 // still in LTR mode
-                cwidth =
-                    nsLayoutUtils::AppUnitWidthOfString(ch, aRenderingContext);
+                cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
+                                                             aRenderingContext);
                 if (twidth + cwidth > aWidth)
                     break;
 
                 twidth += cwidth;
                 if (UCS2_CHAR_IS_BIDI(ch) ) {
                   mState |= NS_FRAME_IS_BIDI;
                 }
             }
@@ -688,18 +689,18 @@ nsTextBoxFrame::CalculateTitleForWidth(n
         case CropLeft:
         {
             nscoord cwidth;
             nscoord twidth = 0;
             int length = mTitle.Length();
             int i;
             for (i=length-1; i >= 0; --i) {
                 char16_t ch = mTitle.CharAt(i);
-                cwidth =
-                    nsLayoutUtils::AppUnitWidthOfString(ch, aRenderingContext);
+                cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
+                                                             aRenderingContext);
                 if (twidth + cwidth > aWidth)
                     break;
 
                 twidth += cwidth;
                 if (UCS2_CHAR_IS_BIDI(ch) ) {
                   mState |= NS_FRAME_IS_BIDI;
                 }
             }
@@ -711,53 +712,53 @@ nsTextBoxFrame::CalculateTitleForWidth(n
             mTitle.Right(copy, length-1-i);
             mCroppedTitle += copy;
         }
         break;
 
         case CropCenter:
         {
             nscoord stringWidth =
-                nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
+                nsLayoutUtils::GetStringWidth(this, &aRenderingContext, *fm,
                                               mTitle.get(), mTitle.Length());
             if (stringWidth <= aWidth) {
                 // the entire string will fit in the maximum width
                 mCroppedTitle.Insert(mTitle, 0);
                 break;
             }
 
             // determine how much of the string will fit in the max width
             nscoord charWidth = 0;
             nscoord totalWidth = 0;
             char16_t ch;
             int leftPos, rightPos;
             nsAutoString leftString, rightString;
 
             rightPos = mTitle.Length() - 1;
-            aRenderingContext.SetTextRunRTL(false);
+            fm->SetTextRunRTL(false);
             for (leftPos = 0; leftPos <= rightPos;) {
                 // look at the next character on the left end
                 ch = mTitle.CharAt(leftPos);
-                charWidth =
-                    nsLayoutUtils::AppUnitWidthOfString(ch, aRenderingContext);
+                charWidth = nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
+                                                                aRenderingContext);
                 totalWidth += charWidth;
                 if (totalWidth > aWidth)
                     // greater than the allowable width
                     break;
                 leftString.Insert(ch, leftString.Length());
 
                 if (UCS2_CHAR_IS_BIDI(ch))
                     mState |= NS_FRAME_IS_BIDI;
 
                 // look at the next character on the right end
                 if (rightPos > leftPos) {
                     // haven't looked at this character yet
                     ch = mTitle.CharAt(rightPos);
                     charWidth =
-                        nsLayoutUtils::AppUnitWidthOfString(ch,
+                        nsLayoutUtils::AppUnitWidthOfString(ch, *fm,
                                                             aRenderingContext);
                     totalWidth += charWidth;
                     if (totalWidth > aWidth)
                         // greater than the allowable width
                         break;
                     rightString.Insert(ch, 0);
 
                     if (UCS2_CHAR_IS_BIDI(ch))
@@ -769,17 +770,17 @@ nsTextBoxFrame::CalculateTitleForWidth(n
                 rightPos--;
             }
 
             mCroppedTitle = leftString + kEllipsis + rightString;
         }
         break;
     }
 
-    return nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
+    return nsLayoutUtils::GetStringWidth(this, &aRenderingContext, *fm,
                                          mCroppedTitle.get(), mCroppedTitle.Length());
 }
 
 #define OLD_ELLIPSIS NS_LITERAL_STRING("...")
 
 // the following block is to append the accesskey to mTitle if there is an accesskey
 // but the mTitle doesn't have the character
 void
@@ -999,17 +1000,17 @@ nsTextBoxFrame::GetTextSize(nsPresContex
                             const nsString& aString,
                             nsSize& aSize, nscoord& aAscent)
 {
     nsRefPtr<nsFontMetrics> fontMet;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
     aSize.height = fontMet->MaxHeight();
     aRenderingContext.SetFont(fontMet);
     aSize.width =
-      nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
+      nsLayoutUtils::GetStringWidth(this, &aRenderingContext, *fontMet,
                                     aString.get(), aString.Length());
     aAscent = fontMet->MaxAscent();
 }
 
 void
 nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState)
 {
     if (mNeedsRecalc)
--- a/layout/xul/nsTextBoxFrame.h
+++ b/layout/xul/nsTextBoxFrame.h
@@ -5,16 +5,17 @@
 #ifndef nsTextBoxFrame_h___
 #define nsTextBoxFrame_h___
 
 #include "mozilla/Attributes.h"
 #include "nsLeafBoxFrame.h"
 
 class nsAccessKeyInfo;
 class nsAsyncAccesskeyUpdate;
+class nsFontMetrics;
 
 typedef nsLeafBoxFrame nsTextBoxFrameSuper;
 class nsTextBoxFrame : public nsTextBoxFrameSuper
 {
 public:
   NS_DECL_QUERYFRAME_TARGET(nsTextBoxFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
@@ -79,17 +80,18 @@ protected:
   // account text-transform.
   void RecomputeTitle();
 
   // REVIEW: SORRY! Couldn't resist devirtualizing these
   void LayoutTitle(nsPresContext*      aPresContext,
                    nsRenderingContext& aRenderingContext,
                    const nsRect&        aRect);
 
-  void CalculateUnderline(nsRenderingContext& aRenderingContext);
+  void CalculateUnderline(nsRenderingContext& aRenderingContext,
+                          nsFontMetrics& aFontMetrics);
 
   void CalcTextSize(nsBoxLayoutState& aBoxLayoutState);
 
   void CalcDrawRect(nsRenderingContext &aRenderingContext);
 
   nsTextBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext);
 
   nscoord CalculateTitleForWidth(nsPresContext*      aPresContext,
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -1265,17 +1265,17 @@ nsTreeBodyFrame::GetCoordsForCellItem(in
       textRect.height = height;
     }
 
     nsMargin bp(0,0,0,0);
     GetBorderPadding(textContext, bp);
     textRect.height += bp.top + bp.bottom;
 
     rc->SetFont(fm);
-    AdjustForCellText(cellText, aRow, currCol, *rc, textRect);
+    AdjustForCellText(cellText, aRow, currCol, *rc, *fm, textRect);
 
     theRect = textRect;
   }
 
   if (isRTL)
     theRect.x = mInnerBox.width - theRect.x - theRect.width;
 
   *aX = nsPresContext::AppUnitsToIntCSSPixels(theRect.x);
@@ -1310,22 +1310,24 @@ nsTreeBodyFrame::CheckTextForBidi(nsAuto
     PresContext()->SetBidiEnabled();
   }
 }
 
 void
 nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText,
                                    int32_t aRowIndex,  nsTreeColumn* aColumn,
                                    nsRenderingContext& aRenderingContext,
+                                   nsFontMetrics& aFontMetrics,
                                    nsRect& aTextRect)
 {
   NS_PRECONDITION(aColumn && aColumn->GetFrame(), "invalid column passed");
 
   nscoord width =
-    nsLayoutUtils::GetStringWidth(this, &aRenderingContext, aText.get(), aText.Length());
+    nsLayoutUtils::GetStringWidth(this, &aRenderingContext, aFontMetrics,
+                                  aText.get(), aText.Length());
   nscoord maxWidth = aTextRect.width;
 
   if (aColumn->Overflow()) {
     DebugOnly<nsresult> rv;
     nsTreeColumn* nextColumn = aColumn->GetNext();
     while (nextColumn && width > maxWidth) {
       while (nextColumn) {
         nscoord width;
@@ -1359,19 +1361,20 @@ nsTreeBodyFrame::AdjustForCellText(nsAut
       }
     }
   }
 
   if (width > maxWidth) {
     // See if the width is even smaller than the ellipsis
     // If so, clear the text completely.
     const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
-    aRenderingContext.SetTextRunRTL(false);
+    aFontMetrics.SetTextRunRTL(false);
     nscoord ellipsisWidth =
-      nsLayoutUtils::AppUnitWidthOfString(kEllipsis, aRenderingContext);
+      nsLayoutUtils::AppUnitWidthOfString(kEllipsis, aFontMetrics,
+                                          aRenderingContext);
 
     width = maxWidth;
     if (ellipsisWidth > width)
       aText.SetLength(0);
     else if (ellipsisWidth == width)
       aText.Assign(kEllipsis);
     else {
       // We will be drawing an ellipsis, thank you very much.
@@ -1386,18 +1389,18 @@ nsTreeBodyFrame::AdjustForCellText(nsAut
           // Crop right.
           nscoord cwidth;
           nscoord twidth = 0;
           uint32_t length = aText.Length();
           uint32_t i;
           for (i = 0; i < length; ++i) {
             char16_t ch = aText[i];
             // XXX this is horrible and doesn't handle clusters
-            cwidth =
-              nsLayoutUtils::AppUnitWidthOfString(ch, aRenderingContext);
+            cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
+                                                         aRenderingContext);
             if (twidth + cwidth > width)
               break;
             twidth += cwidth;
           }
           aText.Truncate(i);
           aText.Append(kEllipsis);
         }
         break;
@@ -1405,17 +1408,18 @@ nsTreeBodyFrame::AdjustForCellText(nsAut
         case 2: {
           // Crop left.
           nscoord cwidth;
           nscoord twidth = 0;
           int32_t length = aText.Length();
           int32_t i;
           for (i=length-1; i >= 0; --i) {
             char16_t ch = aText[i];
-            cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aRenderingContext);
+            cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
+                                                         aRenderingContext);
             if (twidth + cwidth > width)
               break;
             twidth += cwidth;
           }
 
           nsAutoString copy;
           aText.Right(copy, length-1-i);
           aText.Assign(kEllipsis);
@@ -1427,39 +1431,43 @@ nsTreeBodyFrame::AdjustForCellText(nsAut
         {
           // Crop center.
           nsAutoString leftStr, rightStr;
           nscoord cwidth, twidth = 0;
           int32_t length = aText.Length();
           int32_t rightPos = length - 1;
           for (int32_t leftPos = 0; leftPos < rightPos; ++leftPos) {
             char16_t ch = aText[leftPos];
-            cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aRenderingContext);
+            cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
+                                                         aRenderingContext);
             twidth += cwidth;
             if (twidth > width)
               break;
             leftStr.Append(ch);
 
             ch = aText[rightPos];
-            cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aRenderingContext);
+            cwidth = nsLayoutUtils::AppUnitWidthOfString(ch, aFontMetrics,
+                                                         aRenderingContext);
             twidth += cwidth;
             if (twidth > width)
               break;
             rightStr.Insert(ch, 0);
             --rightPos;
           }
           aText = leftStr;
           aText.Append(kEllipsis);
           aText += rightStr;
         }
         break;
       }
     }
 
-    width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext, aText.get(), aText.Length());
+    width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
+                                          aFontMetrics, aText.get(),
+                                          aText.Length());
   }
 
   switch (aColumn->GetTextAlignment()) {
     case NS_STYLE_TEXT_ALIGN_RIGHT: {
       aTextRect.x += aTextRect.width - width;
     }
     break;
     case NS_STYLE_TEXT_ALIGN_CENTER: {
@@ -1609,17 +1617,17 @@ nsTreeBodyFrame::GetItemWithinCellAt(nsc
 
   AdjustForBorderPadding(textContext, textRect);
 
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForStyleContext(textContext,
                                                getter_AddRefs(fm));
   rc->SetFont(fm);
 
-  AdjustForCellText(cellText, aRowIndex, aColumn, *rc, textRect);
+  AdjustForCellText(cellText, aRowIndex, aColumn, *rc, *fm, textRect);
 
   if (aX >= textRect.x && aX < textRect.x + textRect.width)
     return nsCSSAnonBoxes::moztreecelltext;
   else
     return nsCSSAnonBoxes::moztreecell;
 }
 
 void
@@ -1741,17 +1749,18 @@ nsTreeBodyFrame::GetCellWidth(int32_t aR
 
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForStyleContext(textContext,
                                                getter_AddRefs(fm));
   aRenderingContext->SetFont(fm);
 
   // Get the width of the text itself
   nscoord width =
-    nsLayoutUtils::GetStringWidth(this, aRenderingContext, cellText.get(), cellText.Length());
+    nsLayoutUtils::GetStringWidth(this, aRenderingContext, *fm,
+                                  cellText.get(), cellText.Length());
   nscoord totalTextWidth = width + bp.left + bp.right;
   aDesiredSize += totalTextWidth;
   return NS_OK;
 }
 
 nsresult
 nsTreeBodyFrame::IsCellCropped(int32_t aRow, nsITreeColumn* aCol, bool *_retval)
 {  
@@ -3603,17 +3612,17 @@ nsTreeBodyFrame::PaintText(int32_t      
   if (height < textRect.height) {
     textRect.y += (textRect.height - height)/2;
     textRect.height = height;
   }
 
   // Set our font.
   aRenderingContext.SetFont(fontMet);
 
-  AdjustForCellText(text, aRowIndex, aColumn, aRenderingContext, textRect);
+  AdjustForCellText(text, aRowIndex, aColumn, aRenderingContext, *fontMet, textRect);
   textRect.Inflate(bp);
 
   // Subtract out the remaining width.
   if (!isRTL)
     aCurrX += textRect.width + textMargin.LeftRight();
 
   PaintBackgroundLayer(textContext, aPresContext, aRenderingContext, textRect, aDirtyRect);
 
@@ -3654,18 +3663,20 @@ nsTreeBodyFrame::PaintText(int32_t      
   nsStyleContext* cellContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreecell);
 
   gfxContext* ctx = aRenderingContext.ThebesContext();
   if (opacity != 1.0f) {
     ctx->PushGroup(gfxContentType::COLOR_ALPHA);
   }
 
   ctx->SetColor(textContext->StyleColor()->mColor);
-  nsLayoutUtils::DrawString(this, &aRenderingContext, text.get(), text.Length(),
-                            textRect.TopLeft() + nsPoint(0, baseline), cellContext);
+  nsLayoutUtils::DrawString(this, *fontMet, &aRenderingContext, text.get(),
+                            text.Length(),
+                            textRect.TopLeft() + nsPoint(0, baseline),
+                            cellContext);
 
   if (opacity != 1.0f) {
     ctx->PopGroupToSource();
     ctx->Paint(opacity);
   }
 
 }
 
--- a/layout/xul/tree/nsTreeBodyFrame.h
+++ b/layout/xul/tree/nsTreeBodyFrame.h
@@ -20,16 +20,17 @@
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "imgIRequest.h"
 #include "imgINotificationObserver.h"
 #include "nsScrollbarFrame.h"
 #include "nsThreadUtils.h"
 #include "mozilla/LookAndFeel.h"
 
+class nsFontMetrics;
 class nsOverflowChecker;
 class nsTreeImageListener;
 
 namespace mozilla {
 namespace layout {
 class ScrollbarActivity;
 }
 }
@@ -291,16 +292,17 @@ protected:
 
   // Check for bidi characters in the text, and if there are any, ensure
   // that the prescontext is in bidi mode.
   void CheckTextForBidi(nsAutoString& aText);
 
   void AdjustForCellText(nsAutoString& aText,
                          int32_t aRowIndex,  nsTreeColumn* aColumn,
                          nsRenderingContext& aRenderingContext,
+                         nsFontMetrics& aFontMetrics,
                          nsRect& aTextRect);
 
   // A helper used when hit testing.
   nsIAtom* GetItemWithinCellAt(nscoord aX, const nsRect& aCellRect,
                                int32_t aRowIndex, nsTreeColumn* aColumn);
 
   // An internal hit test.  aX and aY are expected to be in twips in the
   // coordinate system of this frame.