Bug 1265459 - Replace uses of nsAutoPtr<gfxTextRun> with UniquePtr, and let MakeTextRun and similar methods return a UniquePtr. r=jrmuizel
authorJonathan Kew <jkew@mozilla.com>
Tue, 19 Apr 2016 17:13:28 +0100
changeset 331789 3e61ba81ac8c2cb687dc905298b4390086ce2f83
parent 331788 1d5416c99477d004ade3de1bc4a7171b613acd0f
child 331790 6205def774ab4f149bce2f66d2fe935c29a92535
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1265459
milestone48.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 1265459 - Replace uses of nsAutoPtr<gfxTextRun> with UniquePtr, and let MakeTextRun and similar methods return a UniquePtr. r=jrmuizel
dom/canvas/CanvasRenderingContext2D.cpp
gfx/src/nsFontMetrics.cpp
gfx/tests/gtest/gfxFontSelectionTest.cpp
gfx/tests/gtest/gfxTextRunPerfTest.cpp
gfx/tests/gtest/gfxWordCacheTest.cpp
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxTextRun.h
layout/generic/MathMLTextRunFactory.cpp
layout/generic/nsTextFrame.cpp
layout/generic/nsTextRunTransformations.cpp
layout/generic/nsTextRunTransformations.h
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLChar.h
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3768,17 +3768,17 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
           target->Stroke(path, patForStyle, strokeOpts, drawOpts);
           buffer.mGlyphs++;
         }
       }
     }
   }
 
   // current text run
-  nsAutoPtr<gfxTextRun> mTextRun;
+  UniquePtr<gfxTextRun> mTextRun;
 
   // pointer to a screen reference context used to measure text and such
   RefPtr<DrawTarget> mDrawTarget;
 
   // Pointer to the draw target we should fill our text to
   CanvasRenderingContext2D *mCtx;
 
   // position of the left side of the string, alphabetic baseline
--- a/gfx/src/nsFontMetrics.cpp
+++ b/gfx/src/nsFontMetrics.cpp
@@ -29,33 +29,33 @@ namespace {
 
 class AutoTextRun {
 public:
     typedef mozilla::gfx::DrawTarget DrawTarget;
 
     AutoTextRun(nsFontMetrics* aMetrics, DrawTarget* aDrawTarget,
                 const char* aString, int32_t aLength)
     {
-        mTextRun.reset(aMetrics->GetThebesFontGroup()->MakeTextRun(
+        mTextRun = aMetrics->GetThebesFontGroup()->MakeTextRun(
             reinterpret_cast<const uint8_t*>(aString), aLength,
             aDrawTarget,
             aMetrics->AppUnitsPerDevPixel(),
             ComputeFlags(aMetrics),
-            nullptr));
+            nullptr);
     }
 
     AutoTextRun(nsFontMetrics* aMetrics, DrawTarget* aDrawTarget,
                 const char16_t* aString, int32_t aLength)
     {
-        mTextRun.reset(aMetrics->GetThebesFontGroup()->MakeTextRun(
+        mTextRun = aMetrics->GetThebesFontGroup()->MakeTextRun(
             aString, aLength,
             aDrawTarget,
             aMetrics->AppUnitsPerDevPixel(),
             ComputeFlags(aMetrics),
-            nullptr));
+            nullptr);
     }
 
     gfxTextRun *get() { return mTextRun.get(); }
     gfxTextRun *operator->() { return mTextRun.get(); }
 
 private:
     static uint32_t ComputeFlags(nsFontMetrics* aMetrics) {
         uint32_t flags = 0;
--- a/gfx/tests/gtest/gfxFontSelectionTest.cpp
+++ b/gfx/tests/gtest/gfxFontSelectionTest.cpp
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsString.h"
 #include "nsDependentString.h"
 
 #include "mozilla/Preferences.h"
 
 #include "gfxContext.h"
@@ -246,29 +247,30 @@ DumpTestExpect (TestEntry *test) {
 void SetupTests(nsTArray<TestEntry>& testList);
 
 static bool
 RunTest (TestEntry *test, gfxContext *ctx) {
     RefPtr<gfxFontGroup> fontGroup;
 
     fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle, nullptr, nullptr, 1.0);
 
-    nsAutoPtr<gfxTextRun> textRun;
+    UniquePtr<gfxTextRun> textRun;
     gfxTextRunFactory::Parameters params = {
       ctx, nullptr, nullptr, nullptr, 0, 60
     };
     uint32_t flags = gfxTextRunFactory::TEXT_IS_PERSISTENT;
     if (test->isRTL) {
         flags |= gfxTextRunFactory::TEXT_IS_RTL;
     }
     uint32_t length;
     if (test->stringType == S_ASCII) {
         flags |= gfxTextRunFactory::TEXT_IS_ASCII | gfxTextRunFactory::TEXT_IS_8BIT;
         length = strlen(test->string);
-        textRun = fontGroup->MakeTextRun(reinterpret_cast<const uint8_t*>(test->string), length, &params, flags);
+        textRun = fontGroup->MakeTextRun(
+            reinterpret_cast<const uint8_t*>(test->string), length, &params, flags);
     } else {
         NS_ConvertUTF8toUTF16 str(nsDependentCString(test->string));
         length = str.Length();
         textRun = fontGroup->MakeTextRun(str.get(), length, &params, flags);
     }
 
     gfxFontTestStore::NewStore();
     textRun->Draw(ctx, gfxPoint(0,0), DrawMode::GLYPH_FILL, 0, length, nullptr, nullptr, nullptr);
--- a/gfx/tests/gtest/gfxTextRunPerfTest.cpp
+++ b/gfx/tests/gtest/gfxTextRunPerfTest.cpp
@@ -61,17 +61,17 @@ RunTest (TestEntry *test, gfxContext *ct
                                               NS_Atomize(NS_LITERAL_STRING("en")),
                                               0.0,
                                               false, false,
                                               NS_LITERAL_STRING(""));
 
         fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nullptr, nullptr, 1.0);
     }
 
-    nsAutoPtr<gfxTextRun> textRun;
+    UniquePtr<gfxTextRun> textRun;
     uint32_t i;
     bool isASCII = true;
     for (i = 0; test->mString[i]; ++i) {
         if (test->mString[i] & 0x80) {
             isASCII = false;
         }
     }
     gfxTextRunFactory::Parameters params = {
@@ -79,17 +79,18 @@ RunTest (TestEntry *test, gfxContext *ct
     };
     uint32_t flags = gfxTextRunFactory::TEXT_IS_PERSISTENT;
     uint32_t length;
     gfxFontTestStore::NewStore();
     if (isASCII) {
         flags |= gfxTextRunFactory::TEXT_IS_ASCII |
                  gfxTextRunFactory::TEXT_IS_8BIT;
         length = strlen(test->mString);
-        textRun = fontGroup->MakeTextRun(reinterpret_cast<const uint8_t*>(test->mString), length, &params, flags);
+        textRun = fontGroup->MakeTextRun(
+            reinterpret_cast<const uint8_t*>(test->mString), length, &params, flags);
     } else {
         NS_ConvertUTF8toUTF16 str(nsDependentCString(test->mString));
         length = str.Length();
         textRun = fontGroup->MakeTextRun(str.get(), length, &params, flags);
     }
 
     // Should we test drawing?
     // textRun->Draw(ctx, gfxPoint(0,0), 0, length, nullptr, nullptr, nullptr);
--- a/gfx/tests/gtest/gfxWordCacheTest.cpp
+++ b/gfx/tests/gtest/gfxWordCacheTest.cpp
@@ -55,35 +55,35 @@ public:
     delete aTextRun;
   }
 };
 
 static gfxTextRun *
 MakeTextRun(const char16_t *aText, uint32_t aLength, gfxFontGroup *aFontGroup,
             const gfxFontGroup::Parameters* aParams, uint32_t aFlags)
 {
-  nsAutoPtr<gfxTextRun> textRun;
+  UniquePtr<gfxTextRun> textRun;
   if (aLength == 0) {
     abort();
     //textRun = aFontGroup->MakeEmptyTextRun(aParams, aFlags);
   } else if (aLength == 1 && aText[0] == ' ') {
     abort();
     //textRun = aFontGroup->MakeSpaceTextRun(aParams, aFlags);
   } else {
     textRun = aFontGroup->MakeTextRun(aText, aLength, aParams, aFlags);
   }
   if (!textRun) {
     return nullptr;
   }
-  nsresult rv = gTextRuns->AddObject(textRun);
+  nsresult rv = gTextRuns->AddObject(textRun.get());
   if (NS_FAILED(rv)) {
-    gTextRuns->RemoveFromCache(textRun);
+    gTextRuns->RemoveFromCache(textRun.get());
     return nullptr;
   }
-  return textRun.forget();
+  return textRun.release();
 }
 
 static already_AddRefed<DrawTarget>
 MakeDrawTarget()
 {
   const int size = 200;
 
   RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -126,26 +126,27 @@ gfxTextRun::AllocateStorageForTextRun(si
 
     // Initialize the glyph storage (beyond aSize) to zero
     memset(reinterpret_cast<char*>(storage) + aSize, 0,
            aLength * sizeof(CompressedGlyph));
 
     return storage;
 }
 
-gfxTextRun *
+UniquePtr<gfxTextRun>
 gfxTextRun::Create(const gfxTextRunFactory::Parameters *aParams,
                    uint32_t aLength, gfxFontGroup *aFontGroup, uint32_t aFlags)
 {
     void *storage = AllocateStorageForTextRun(sizeof(gfxTextRun), aLength);
     if (!storage) {
         return nullptr;
     }
 
-    return new (storage) gfxTextRun(aParams, aLength, aFontGroup, aFlags);
+    return UniquePtr<gfxTextRun>(new (storage) gfxTextRun(aParams, aLength,
+                                                          aFontGroup, aFlags));
 }
 
 gfxTextRun::gfxTextRun(const gfxTextRunFactory::Parameters *aParams,
                        uint32_t aLength, gfxFontGroup *aFontGroup, uint32_t aFlags)
     : gfxShapedText(aLength, aFlags, aParams->mAppUnitsPerDevUnit)
     , mUserData(aParams->mUserData)
     , mFontGroup(aFontGroup)
     , mReleasedFontGroup(false)
@@ -1956,29 +1957,30 @@ gfxFontGroup::IsInvalidChar(char16_t ch)
     if (ch <= 0x9f) {
         return true;
     }
     return (((ch & 0xFF00) == 0x2000 /* Unicode control character */ &&
              (ch == 0x200B/*ZWSP*/ || ch == 0x2028/*LSEP*/ || ch == 0x2029/*PSEP*/)) ||
             IsBidiControl(ch));
 }
 
-gfxTextRun *
+UniquePtr<gfxTextRun>
 gfxFontGroup::MakeEmptyTextRun(const Parameters *aParams, uint32_t aFlags)
 {
     aFlags |= TEXT_IS_8BIT | TEXT_IS_ASCII | TEXT_IS_PERSISTENT;
     return gfxTextRun::Create(aParams, 0, this, aFlags);
 }
 
-gfxTextRun *
+UniquePtr<gfxTextRun>
 gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags)
 {
     aFlags |= TEXT_IS_8BIT | TEXT_IS_ASCII | TEXT_IS_PERSISTENT;
 
-    gfxTextRun *textRun = gfxTextRun::Create(aParams, 1, this, aFlags);
+    UniquePtr<gfxTextRun> textRun =
+        gfxTextRun::Create(aParams, 1, this, aFlags);
     if (!textRun) {
         return nullptr;
     }
 
     uint16_t orientation = aFlags & TEXT_ORIENT_MASK;
     if (orientation == TEXT_ORIENT_VERTICAL_MIXED) {
         orientation = TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
     }
@@ -2012,36 +2014,36 @@ gfxFontGroup::MakeSpaceTextRun(const Par
     }
 
     // Note that the gfxGlyphExtents glyph bounds storage for the font will
     // always contain an entry for the font's space glyph, so we don't have
     // to call FetchGlyphExtents here.
     return textRun;
 }
 
-gfxTextRun *
+UniquePtr<gfxTextRun>
 gfxFontGroup::MakeBlankTextRun(uint32_t aLength,
                                const Parameters *aParams, uint32_t aFlags)
 {
-    gfxTextRun *textRun =
+    UniquePtr<gfxTextRun> textRun =
         gfxTextRun::Create(aParams, aLength, this, aFlags);
     if (!textRun) {
         return nullptr;
     }
 
     uint16_t orientation = aFlags & TEXT_ORIENT_MASK;
     if (orientation == TEXT_ORIENT_VERTICAL_MIXED) {
         orientation = TEXT_ORIENT_VERTICAL_UPRIGHT;
     }
     textRun->AddGlyphRun(GetFirstValidFont(), gfxTextRange::kFontGroup, 0, false,
                          orientation);
     return textRun;
 }
 
-gfxTextRun *
+UniquePtr<gfxTextRun>
 gfxFontGroup::MakeHyphenTextRun(DrawTarget* aDrawTarget,
                                 uint32_t aAppUnitsPerDevUnit)
 {
     // only use U+2010 if it is supported by the first font in the group;
     // it's better to use ASCII '-' from the primary font than to fall back to
     // U+2010 from some other, possibly poorly-matching face
     static const char16_t hyphen = 0x2010;
     gfxFont *font = GetFirstValidFont(uint32_t(hyphen));
@@ -2065,17 +2067,17 @@ gfxFontGroup::GetHyphenWidth(gfxTextRun:
                 hyphRun(MakeHyphenTextRun(dt,
                                           aProvider->GetAppUnitsPerDevUnit()));
             mHyphenWidth = hyphRun.get() ? hyphRun->GetAdvanceWidth() : 0;
         }
     }
     return mHyphenWidth;
 }
 
-gfxTextRun *
+UniquePtr<gfxTextRun>
 gfxFontGroup::MakeTextRun(const uint8_t *aString, uint32_t aLength,
                           const Parameters *aParams, uint32_t aFlags,
                           gfxMissingFontRecorder *aMFR)
 {
     if (aLength == 0) {
         return MakeEmptyTextRun(aParams, aFlags);
     }
     if (aLength == 1 && aString[0] == ' ') {
@@ -2087,52 +2089,52 @@ gfxFontGroup::MakeTextRun(const uint8_t 
     if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
         MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
         // Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
         // them, and always create at least size 1 fonts, i.e. they still
         // render something for size 0 fonts.
         return MakeBlankTextRun(aLength, aParams, aFlags);
     }
 
-    gfxTextRun *textRun = gfxTextRun::Create(aParams, aLength,
-                                             this, aFlags);
+    UniquePtr<gfxTextRun> textRun = gfxTextRun::Create(aParams, aLength,
+                                                       this, aFlags);
     if (!textRun) {
         return nullptr;
     }
 
-    InitTextRun(aParams->mDrawTarget, textRun, aString, aLength, aMFR);
+    InitTextRun(aParams->mDrawTarget, textRun.get(), aString, aLength, aMFR);
 
     textRun->FetchGlyphExtents(aParams->mDrawTarget);
 
     return textRun;
 }
 
-gfxTextRun *
+UniquePtr<gfxTextRun>
 gfxFontGroup::MakeTextRun(const char16_t *aString, uint32_t aLength,
                           const Parameters *aParams, uint32_t aFlags,
                           gfxMissingFontRecorder *aMFR)
 {
     if (aLength == 0) {
         return MakeEmptyTextRun(aParams, aFlags);
     }
     if (aLength == 1 && aString[0] == ' ') {
         return MakeSpaceTextRun(aParams, aFlags);
     }
     if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
         MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
         return MakeBlankTextRun(aLength, aParams, aFlags);
     }
 
-    gfxTextRun *textRun = gfxTextRun::Create(aParams, aLength,
-                                             this, aFlags);
+    UniquePtr<gfxTextRun> textRun = gfxTextRun::Create(aParams, aLength,
+                                                       this, aFlags);
     if (!textRun) {
         return nullptr;
     }
 
-    InitTextRun(aParams->mDrawTarget, textRun, aString, aLength, aMFR);
+    InitTextRun(aParams->mDrawTarget, textRun.get(), aString, aLength, aMFR);
 
     textRun->FetchGlyphExtents(aParams->mDrawTarget);
 
     return textRun;
 }
 
 template<typename T>
 void
@@ -2559,26 +2561,26 @@ gfxFontGroup::GetEllipsisTextRun(int32_t
                             ArrayLength(kEllipsisChar) - 1)
         : nsDependentString(kASCIIPeriodsChar,
                             ArrayLength(kASCIIPeriodsChar) - 1);
 
     RefPtr<DrawTarget> refDT = aRefDrawTargetGetter.GetRefDrawTarget();
     Parameters params = {
         refDT, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel
     };
-    gfxTextRun* textRun =
+    mCachedEllipsisTextRun =
         MakeTextRun(ellipsis.get(), ellipsis.Length(), &params,
                     aFlags | TEXT_IS_PERSISTENT, nullptr);
-    if (!textRun) {
+    if (!mCachedEllipsisTextRun) {
         return nullptr;
     }
-    mCachedEllipsisTextRun.reset(textRun);
-    textRun->ReleaseFontGroup(); // don't let the presence of a cached ellipsis
-                                 // textrun prolong the fontgroup's life
-    return textRun;
+    // don't let the presence of a cached ellipsis textrun prolong the
+    // fontgroup's life
+    mCachedEllipsisTextRun->ReleaseFontGroup();
+    return mCachedEllipsisTextRun.get();
 }
 
 already_AddRefed<gfxFont>
 gfxFontGroup::FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh,
                                       int32_t aRunScript)
 {
     GlobalFontMatch data(aCh, aRunScript, &mStyle);
     aFamily->SearchAllFontsForChar(&data);
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -429,19 +429,20 @@ public:
       mFlags &= ~aFlags;
     }
     const gfxSkipChars& GetSkipChars() const { return mSkipChars; }
     gfxFontGroup *GetFontGroup() const { return mFontGroup; }
 
 
     // Call this, don't call "new gfxTextRun" directly. This does custom
     // allocation and initialization
-    static gfxTextRun *Create(const gfxTextRunFactory::Parameters *aParams,
-                              uint32_t aLength, gfxFontGroup *aFontGroup,
-                              uint32_t aFlags);
+    static mozilla::UniquePtr<gfxTextRun>
+    Create(const gfxTextRunFactory::Parameters *aParams,
+           uint32_t aLength, gfxFontGroup *aFontGroup,
+           uint32_t aFlags);
 
     // The text is divided into GlyphRuns as necessary
     struct GlyphRun {
         RefPtr<gfxFont> mFont;   // never null
         uint32_t          mCharacterOffset; // into original UTF16 string
         uint8_t           mMatchType;
         uint16_t          mOrientation; // gfxTextRunFactory::TEXT_ORIENT_* value
     };
@@ -792,39 +793,42 @@ public:
     static bool IsInvalidChar(char16_t ch);
 
     /**
      * Make a textrun for a given string.
      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
      * textrun will copy it.
      * This calls FetchGlyphExtents on the textrun.
      */
-    virtual gfxTextRun *MakeTextRun(const char16_t *aString, uint32_t aLength,
-                                    const Parameters *aParams, uint32_t aFlags,
-                                    gfxMissingFontRecorder *aMFR);
+    virtual mozilla::UniquePtr<gfxTextRun>
+    MakeTextRun(const char16_t *aString, uint32_t aLength,
+                const Parameters *aParams, uint32_t aFlags,
+                gfxMissingFontRecorder *aMFR);
     /**
      * Make a textrun for a given string.
      * If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
      * textrun will copy it.
      * This calls FetchGlyphExtents on the textrun.
      */
-    virtual gfxTextRun *MakeTextRun(const uint8_t *aString, uint32_t aLength,
-                                    const Parameters *aParams, uint32_t aFlags,
-                                    gfxMissingFontRecorder *aMFR);
+    virtual mozilla::UniquePtr<gfxTextRun>
+    MakeTextRun(const uint8_t *aString, uint32_t aLength,
+                const Parameters *aParams, uint32_t aFlags,
+                gfxMissingFontRecorder *aMFR);
 
     /**
      * Textrun creation helper for clients that don't want to pass
      * a full Parameters record.
      */
     template<typename T>
-    gfxTextRun* MakeTextRun(const T* aString, uint32_t aLength,
-                            DrawTarget* aRefDrawTarget,
-                            int32_t aAppUnitsPerDevUnit,
-                            uint32_t aFlags,
-                            gfxMissingFontRecorder *aMFR)
+    mozilla::UniquePtr<gfxTextRun>
+    MakeTextRun(const T* aString, uint32_t aLength,
+                DrawTarget* aRefDrawTarget,
+                int32_t aAppUnitsPerDevUnit,
+                uint32_t aFlags,
+                gfxMissingFontRecorder *aMFR)
     {
         gfxTextRunFactory::Parameters params = {
             aRefDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevUnit
         };
         return MakeTextRun(aString, aLength, &params, aFlags, aMFR);
     }
 
     /**
@@ -837,18 +841,18 @@ public:
 
     /**
      * Make a text run representing a single hyphen character.
      * This will use U+2010 HYPHEN if available in the first font,
      * otherwise fall back to U+002D HYPHEN-MINUS.
      * The caller is responsible for deleting the returned text run
      * when no longer required.
      */
-    gfxTextRun* MakeHyphenTextRun(DrawTarget* aDrawTarget,
-                                  uint32_t aAppUnitsPerDevUnit);
+    mozilla::UniquePtr<gfxTextRun>
+    MakeHyphenTextRun(DrawTarget* aDrawTarget, uint32_t aAppUnitsPerDevUnit);
 
     /**
      * Check whether a given font (specified by its gfxFontEntry)
      * is already in the fontgroup's list of actual fonts
      */
     bool HasFont(const gfxFontEntry *aFontEntry);
 
     // This returns the preferred underline for this font group.
@@ -1091,20 +1095,25 @@ protected:
 
     // xxx - gfxPangoFontGroup skips UpdateUserFonts
     bool                    mSkipUpdateUserFonts;
 
     /**
      * Textrun creation short-cuts for special cases where we don't need to
      * call a font shaper to generate glyphs.
      */
-    gfxTextRun *MakeEmptyTextRun(const Parameters *aParams, uint32_t aFlags);
-    gfxTextRun *MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags);
-    gfxTextRun *MakeBlankTextRun(uint32_t aLength,
-                                 const Parameters *aParams, uint32_t aFlags);
+    mozilla::UniquePtr<gfxTextRun>
+    MakeEmptyTextRun(const Parameters *aParams, uint32_t aFlags);
+
+    mozilla::UniquePtr<gfxTextRun>
+    MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags);
+
+    mozilla::UniquePtr<gfxTextRun>
+    MakeBlankTextRun(uint32_t aLength, const Parameters *aParams,
+                     uint32_t aFlags);
 
     // Initialize the list of fonts
     void BuildFontList();
 
     // Get the font at index i within the fontlist.
     // Will initiate userfont load if not already loaded.
     // May return null if userfont not loaded or if font invalid
     virtual gfxFont* GetFontAt(int32_t i, uint32_t aCh = 0x20);
--- a/layout/generic/MathMLTextRunFactory.cpp
+++ b/layout/generic/MathMLTextRunFactory.cpp
@@ -709,18 +709,18 @@ MathMLTextRunFactory::RebuildTextRun(nsT
       canBreakBeforeArray.AppendElement(false);
     }
   }
 
   uint32_t flags;
   gfxTextRunFactory::Parameters innerParams =
       GetParametersForInner(aTextRun, &flags, aRefDrawTarget);
 
-  nsAutoPtr<nsTransformedTextRun> transformedChild;
-  nsAutoPtr<gfxTextRun> cachedChild;
+  UniquePtr<nsTransformedTextRun> transformedChild;
+  UniquePtr<gfxTextRun> cachedChild;
   gfxTextRun* child;
 
   if (mathVar == NS_MATHML_MATHVARIANT_BOLD && doMathvariantStyling) {
     font.style = NS_FONT_STYLE_NORMAL;
     font.weight = NS_FONT_WEIGHT_BOLD;
   } else if (mathVar == NS_MATHML_MATHVARIANT_ITALIC && doMathvariantStyling) {
     font.style = NS_FONT_STYLE_ITALIC;
     font.weight = NS_FONT_WEIGHT_NORMAL;
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -585,36 +585,35 @@ public:
     RemoveFromCache(aTextRun);
     delete aTextRun;
   }
 };
 
 // Helper to create a textrun and remember it in the textframe cache,
 // for either 8-bit or 16-bit text strings
 template<typename T>
-gfxTextRun *
+UniquePtr<gfxTextRun>
 MakeTextRun(const T *aText, uint32_t aLength,
             gfxFontGroup *aFontGroup, const gfxFontGroup::Parameters* aParams,
             uint32_t aFlags, gfxMissingFontRecorder *aMFR)
 {
-    nsAutoPtr<gfxTextRun> textRun(aFontGroup->MakeTextRun(aText, aLength,
-                                                          aParams, aFlags,
-                                                          aMFR));
+    UniquePtr<gfxTextRun> textRun =
+        aFontGroup->MakeTextRun(aText, aLength, aParams, aFlags, aMFR);
     if (!textRun) {
         return nullptr;
     }
-    nsresult rv = gTextRuns->AddObject(textRun);
+    nsresult rv = gTextRuns->AddObject(textRun.get());
     if (NS_FAILED(rv)) {
-        gTextRuns->RemoveFromCache(textRun);
+        gTextRuns->RemoveFromCache(textRun.get());
         return nullptr;
     }
 #ifdef NOISY_BIDI
     printf("Created textrun\n");
 #endif
-    return textRun.forget();
+    return textRun;
 }
 
 void
 nsTextFrameTextRunCache::Init() {
     gTextRuns = new FrameTextRunCache();
 }
 
 void
@@ -1852,20 +1851,17 @@ static already_AddRefed<DrawTarget>
 CreateReferenceDrawTarget(nsTextFrame* aTextFrame)
 {
   RefPtr<gfxContext> ctx =
     aTextFrame->PresContext()->PresShell()->CreateReferenceRenderingContext();
   RefPtr<DrawTarget> dt = ctx->GetDrawTarget();
   return dt.forget();
 }
 
-/**
- * The returned textrun must be deleted when no longer needed.
- */
-static gfxTextRun*
+static UniquePtr<gfxTextRun>
 GetHyphenTextRun(gfxTextRun* aTextRun, DrawTarget* aDrawTarget,
                  nsTextFrame* aTextFrame)
 {
   RefPtr<DrawTarget> dt = aDrawTarget;
   if (!dt) {
     dt = CreateReferenceDrawTarget(aTextFrame);
     if (!dt) {
       return nullptr;
@@ -2222,17 +2218,17 @@ BuildTextRunsScanner::BuildTextRunForFra
         }
       }
     }
     textFlags |= nsTextFrameUtils::TEXT_IS_TRANSFORMED;
     NS_ASSERTION(iter.GetSkippedOffset() == transformedLength,
                  "We didn't cover all the characters in the text run!");
   }
 
-  gfxTextRun* textRun;
+  UniquePtr<gfxTextRun> textRun;
   gfxTextRunFactory::Parameters params =
       { mDrawTarget, finalUserData, &skipChars,
         textBreakPointsAfterTransform.Elements(),
         uint32_t(textBreakPointsAfterTransform.Length()),
         int32_t(firstFrame->PresContext()->AppUnitsPerDevPixel())};
 
   if (mDoubleByteText) {
     const char16_t* text = static_cast<const char16_t*>(textPtr);
@@ -2268,42 +2264,42 @@ BuildTextRunsScanner::BuildTextRunForFra
     DestroyUserData(userDataToDestroy);
     return nullptr;
   }
 
   // We have to set these up after we've created the textrun, because
   // the breaks may be stored in the textrun during this very call.
   // This is a bit annoying because it requires another loop over the frames
   // making up the textrun, but I don't see a way to avoid this.
-  SetupBreakSinksForTextRun(textRun, textPtr);
+  SetupBreakSinksForTextRun(textRun.get(), textPtr);
 
   if (anyTextEmphasis) {
-    SetupTextEmphasisForTextRun(textRun, textPtr);
+    SetupTextEmphasisForTextRun(textRun.get(), textPtr);
   }
 
   if (mSkipIncompleteTextRuns) {
     mSkipIncompleteTextRuns = !TextContainsLineBreakerWhiteSpace(textPtr,
         transformedLength, mDoubleByteText);
-    // Arrange for this textrun to be deleted the next time the linebreaker
-    // is flushed out
-    mTextRunsToDelete.AppendElement(textRun);
     // Since we're doing to destroy the user data now, avoid a dangling
     // pointer. Strictly speaking we don't need to do this since it should
     // not be used (since this textrun will not be used and will be
     // itself deleted soon), but it's always better to not have dangling
     // pointers around.
     textRun->SetUserData(nullptr);
     DestroyUserData(userDataToDestroy);
+    // Arrange for this textrun to be deleted the next time the linebreaker
+    // is flushed out
+    mTextRunsToDelete.AppendElement(textRun.release());
     return nullptr;
   }
 
   // Actually wipe out the textruns associated with the mapped frames and associate
   // those frames with this text run.
-  AssignTextRun(textRun, fontInflation);
-  return textRun;
+  AssignTextRun(textRun.get(), fontInflation);
+  return textRun.release();
 }
 
 // This is a cut-down version of BuildTextRunForFrames used to set up
 // context for the line-breaker, when the textrun has already been created.
 // So it does the same walk over the mMappedFlows, but doesn't actually
 // build a new textrun.
 bool
 BuildTextRunsScanner::SetupLineBreakerContext(gfxTextRun *aTextRun)
@@ -5165,24 +5161,24 @@ GetInflationForTextDecorations(nsIFrame*
     return
       static_cast<const SVGTextFrame*>(container)->GetFontSizeScaleFactor();
   }
   return nsLayoutUtils::FontSizeInflationInner(aFrame, aInflationMinFontSize);
 }
 
 struct EmphasisMarkInfo
 {
-  nsAutoPtr<gfxTextRun> textRun;
+  UniquePtr<gfxTextRun> textRun;
   gfxFloat advance;
   gfxFloat baselineOffset;
 };
 
 NS_DECLARE_FRAME_PROPERTY_DELETABLE(EmphasisMarkProperty, EmphasisMarkInfo)
 
-static gfxTextRun*
+UniquePtr<gfxTextRun>
 GenerateTextRunForEmphasisMarks(nsTextFrame* aFrame, nsFontMetrics* aFontMetrics,
                                 WritingMode aWM, const nsStyleText* aStyleText)
 {
   const nsString& emphasisString = aStyleText->mTextEmphasisStyleString;
   RefPtr<DrawTarget> dt = CreateReferenceDrawTarget(aFrame);
   auto appUnitsPerDevUnit = aFrame->PresContext()->AppUnitsPerDevPixel();
   uint32_t flags = nsLayoutUtils::
     GetTextRunOrientFlagsForStyle(aFrame->StyleContext());
@@ -5840,20 +5836,21 @@ bool SelectionIterator::GetNextSegment(g
 
 static void
 AddHyphenToMetrics(nsTextFrame* aTextFrame, gfxTextRun* aBaseTextRun,
                    gfxTextRun::Metrics* aMetrics,
                    gfxFont::BoundingBoxType aBoundingBoxType,
                    DrawTarget* aDrawTarget)
 {
   // Fix up metrics to include hyphen
-  nsAutoPtr<gfxTextRun> hyphenTextRun(
-    GetHyphenTextRun(aBaseTextRun, aDrawTarget, aTextFrame));
-  if (!hyphenTextRun.get())
+  UniquePtr<gfxTextRun> hyphenTextRun =
+    GetHyphenTextRun(aBaseTextRun, aDrawTarget, aTextFrame);
+  if (!hyphenTextRun) {
     return;
+  }
 
   gfxTextRun::Metrics hyphenMetrics =
     hyphenTextRun->MeasureText(aBoundingBoxType, aDrawTarget);
   if (aTextFrame->GetWritingMode().IsLineInverted()) {
     hyphenMetrics.mBoundingBox.y = -hyphenMetrics.mBoundingBox.YMost();
   }
   aMetrics->CombineWith(hyphenMetrics, aBaseTextRun->IsRightToLeft());
 }
@@ -6242,17 +6239,17 @@ nsTextFrame::DrawEmphasisMarks(gfxContex
     pt.y += info->baselineOffset;
   } else {
     if (aWM.IsVerticalRL()) {
       pt.x -= info->baselineOffset;
     } else {
       pt.x += info->baselineOffset;
     }
   }
-  mTextRun->DrawEmphasisMarks(aContext, info->textRun, info->advance,
+  mTextRun->DrawEmphasisMarks(aContext, info->textRun.get(), info->advance,
                               pt, aRange, aProvider);
 }
 
 nscolor
 nsTextFrame::GetCaretColorAt(int32_t aOffset)
 {
   NS_PRECONDITION(aOffset >= 0, "aOffset must be positive");
 
@@ -6649,18 +6646,19 @@ nsTextFrame::DrawTextRun(Range aRange, c
                          const DrawTextRunParams& aParams)
 {
   MOZ_ASSERT(aParams.advanceWidth, "Must provide advanceWidth");
   ::DrawTextRun(mTextRun, aTextBaselinePt, aRange, aParams);
 
   if (aParams.drawSoftHyphen) {
     // Don't use ctx as the context, because we need a reference context here,
     // ctx may be transformed.
-    nsAutoPtr<gfxTextRun> hyphenTextRun(GetHyphenTextRun(mTextRun, nullptr, this));
-    if (hyphenTextRun.get()) {
+    UniquePtr<gfxTextRun> hyphenTextRun =
+      GetHyphenTextRun(mTextRun, nullptr, this);
+    if (hyphenTextRun) {
       // For right-to-left text runs, the soft-hyphen is positioned at the left
       // of the text, minus its own width
       gfxFloat hyphenBaselineX = aTextBaselinePt.x +
         mTextRun->GetDirection() * (*aParams.advanceWidth) -
         (mTextRun->IsRightToLeft() ? hyphenTextRun->GetAdvanceWidth() : 0);
       DrawTextRunParams params = aParams;
       params.provider = nullptr;
       params.advanceWidth = nullptr;
--- a/layout/generic/nsTextRunTransformations.cpp
+++ b/layout/generic/nsTextRunTransformations.cpp
@@ -27,37 +27,37 @@ using namespace mozilla;
 
 // Greek sigma needs custom handling for the lowercase transform; for details
 // see comments under "case NS_STYLE_TEXT_TRANSFORM_LOWERCASE" within
 // nsCaseTransformTextRunFactory::RebuildTextRun(), and bug 740120.
 #define GREEK_CAPITAL_LETTER_SIGMA             0x03A3
 #define GREEK_SMALL_LETTER_FINAL_SIGMA         0x03C2
 #define GREEK_SMALL_LETTER_SIGMA               0x03C3
 
-nsTransformedTextRun *
+UniquePtr<nsTransformedTextRun>
 nsTransformedTextRun::Create(const gfxTextRunFactory::Parameters* aParams,
                              nsTransformingTextRunFactory* aFactory,
                              gfxFontGroup* aFontGroup,
                              const char16_t* aString, uint32_t aLength,
                              const uint32_t aFlags,
                              nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
                              bool aOwnsFactory)
 {
   NS_ASSERTION(!(aFlags & gfxTextRunFactory::TEXT_IS_8BIT),
                "didn't expect text to be marked as 8-bit here");
 
   void *storage = AllocateStorageForTextRun(sizeof(nsTransformedTextRun), aLength);
   if (!storage) {
     return nullptr;
   }
 
-  return new (storage) nsTransformedTextRun(aParams, aFactory, aFontGroup,
-                                            aString, aLength,
-                                            aFlags, Move(aStyles),
-                                            aOwnsFactory);
+  return UniquePtr<nsTransformedTextRun>(
+    new (storage) nsTransformedTextRun(aParams, aFactory, aFontGroup,
+                                       aString, aLength, aFlags,
+                                       Move(aStyles), aOwnsFactory));
 }
 
 void
 nsTransformedTextRun::SetCapitalization(uint32_t aStart, uint32_t aLength,
                                         bool* aCapitalization)
 {
   if (mCapitalize.IsEmpty()) {
     if (!mCapitalize.AppendElements(GetLength()))
@@ -93,29 +93,29 @@ nsTransformedTextRun::SizeOfExcludingThi
 }
 
 size_t
 nsTransformedTextRun::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
 
-nsTransformedTextRun*
+UniquePtr<nsTransformedTextRun>
 nsTransformingTextRunFactory::MakeTextRun(const char16_t* aString, uint32_t aLength,
                                           const gfxTextRunFactory::Parameters* aParams,
                                           gfxFontGroup* aFontGroup, uint32_t aFlags,
                                           nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
                                           bool aOwnsFactory)
 {
   return nsTransformedTextRun::Create(aParams, this, aFontGroup,
                                       aString, aLength, aFlags, Move(aStyles),
                                       aOwnsFactory);
 }
 
-nsTransformedTextRun*
+UniquePtr<nsTransformedTextRun>
 nsTransformingTextRunFactory::MakeTextRun(const uint8_t* aString, uint32_t aLength,
                                           const gfxTextRunFactory::Parameters* aParams,
                                           gfxFontGroup* aFontGroup, uint32_t aFlags,
                                           nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
                                           bool aOwnsFactory)
 {
   // We'll only have a Unicode code path to minimize the amount of code needed
   // for these rarely used features
@@ -620,18 +620,18 @@ nsCaseTransformTextRunFactory::RebuildTe
                                      &canBreakBeforeArray,
                                      &styleArray);
 
   uint32_t flags;
   gfxTextRunFactory::Parameters innerParams =
     GetParametersForInner(aTextRun, &flags, aRefDrawTarget);
   gfxFontGroup* fontGroup = aTextRun->GetFontGroup();
 
-  nsAutoPtr<nsTransformedTextRun> transformedChild;
-  nsAutoPtr<gfxTextRun> cachedChild;
+  UniquePtr<nsTransformedTextRun> transformedChild;
+  UniquePtr<gfxTextRun> cachedChild;
   gfxTextRun* child;
 
   if (mInnerTransformingTextRunFactory) {
     transformedChild = mInnerTransformingTextRunFactory->MakeTextRun(
         convertedString.BeginReading(), convertedString.Length(),
         &innerParams, fontGroup, flags, Move(styleArray), false);
     child = transformedChild.get();
   } else {
--- a/layout/generic/nsTextRunTransformations.h
+++ b/layout/generic/nsTextRunTransformations.h
@@ -39,26 +39,29 @@ private:
   nsTransformedCharStyle& operator=(const nsTransformedCharStyle& aOther) = delete;
 };
 
 class nsTransformingTextRunFactory {
 public:
   virtual ~nsTransformingTextRunFactory() {}
 
   // Default 8-bit path just transforms to Unicode and takes that path
-  nsTransformedTextRun* MakeTextRun(const uint8_t* aString, uint32_t aLength,
-                                    const gfxFontGroup::Parameters* aParams,
-                                    gfxFontGroup* aFontGroup, uint32_t aFlags,
-                                    nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
-                                    bool aOwnsFactory);
-  nsTransformedTextRun* MakeTextRun(const char16_t* aString, uint32_t aLength,
-                                    const gfxFontGroup::Parameters* aParams,
-                                    gfxFontGroup* aFontGroup, uint32_t aFlags,
-                                    nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
-                                    bool aOwnsFactory);
+  mozilla::UniquePtr<nsTransformedTextRun>
+  MakeTextRun(const uint8_t* aString, uint32_t aLength,
+              const gfxFontGroup::Parameters* aParams,
+              gfxFontGroup* aFontGroup, uint32_t aFlags,
+              nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
+              bool aOwnsFactory);
+
+  mozilla::UniquePtr<nsTransformedTextRun>
+  MakeTextRun(const char16_t* aString, uint32_t aLength,
+              const gfxFontGroup::Parameters* aParams,
+              gfxFontGroup* aFontGroup, uint32_t aFlags,
+              nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
+              bool aOwnsFactory);
 
   virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
                               mozilla::gfx::DrawTarget* aRefDrawTarget,
                               gfxMissingFontRecorder* aMFR) = 0;
 };
 
 /**
  * Builds textruns that transform the text in some way (e.g., capitalize)
@@ -109,23 +112,24 @@ protected:
 
 /**
  * So that we can reshape as necessary, we store enough information
  * to fully rebuild the textrun contents.
  */
 class nsTransformedTextRun final : public gfxTextRun {
 public:
 
-  static nsTransformedTextRun *Create(const gfxTextRunFactory::Parameters* aParams,
-                                      nsTransformingTextRunFactory* aFactory,
-                                      gfxFontGroup* aFontGroup,
-                                      const char16_t* aString, uint32_t aLength,
-                                      const uint32_t aFlags,
-                                      nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
-                                      bool aOwnsFactory);
+  static mozilla::UniquePtr<nsTransformedTextRun>
+  Create(const gfxTextRunFactory::Parameters* aParams,
+         nsTransformingTextRunFactory* aFactory,
+         gfxFontGroup* aFontGroup,
+         const char16_t* aString, uint32_t aLength,
+         const uint32_t aFlags,
+         nsTArray<RefPtr<nsTransformedCharStyle>>&& aStyles,
+         bool aOwnsFactory);
 
   ~nsTransformedTextRun() {
     if (mOwnsFactory) {
       delete mFactory;
     }
   }
   
   void SetCapitalization(uint32_t aStart, uint32_t aLength,
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -102,20 +102,21 @@ public:
 
   // True if this table contains parts to render this char
   virtual bool HasPartsOf(DrawTarget*   aDrawTarget,
                           int32_t       aAppUnitsPerDevPixel,
                           gfxFontGroup* aFontGroup,
                           char16_t      aChar,
                           bool          aVertical) = 0;
 
-  virtual gfxTextRun* MakeTextRun(DrawTarget*        aDrawTarget,
-                                  int32_t            aAppUnitsPerDevPixel,
-                                  gfxFontGroup*      aFontGroup,
-                                  const nsGlyphCode& aGlyph) = 0;
+  virtual UniquePtr<gfxTextRun>
+  MakeTextRun(DrawTarget*        aDrawTarget,
+              int32_t            aAppUnitsPerDevPixel,
+              gfxFontGroup*      aFontGroup,
+              const nsGlyphCode& aGlyph) = 0;
 protected:
   nsGlyphTable() : mCharCache(0) {}
   // For speedy re-use, we always cache the last data used in the table.
   // mCharCache is the Unicode point of the last char that was queried in this
   // table.
   char16_t mCharCache;
 };
 
@@ -223,20 +224,21 @@ public:
             ElementAt(aDrawTarget, aAppUnitsPerDevPixel, aFontGroup,
                       aChar, aVertical, 1).Exists() ||
             ElementAt(aDrawTarget, aAppUnitsPerDevPixel, aFontGroup,
                       aChar, aVertical, 2).Exists() ||
             ElementAt(aDrawTarget, aAppUnitsPerDevPixel, aFontGroup,
                       aChar, aVertical, 3).Exists());
   }
 
-  virtual gfxTextRun* MakeTextRun(DrawTarget*        aDrawTarget,
-                                  int32_t            aAppUnitsPerDevPixel,
-                                  gfxFontGroup*      aFontGroup,
-                                  const nsGlyphCode& aGlyph) override;
+  virtual UniquePtr<gfxTextRun>
+  MakeTextRun(DrawTarget*        aDrawTarget,
+              int32_t            aAppUnitsPerDevPixel,
+              gfxFontGroup*      aFontGroup,
+              const nsGlyphCode& aGlyph) override;
 private:
 
   // mGlyphCodeFonts[0] is the primary font associated to this table. The
   // others are possible "external" fonts for glyphs not in the primary font
   // but which are needed to stretch certain characters in the table
   nsTArray<FontFamilyName> mGlyphCodeFonts;
 
   // Tri-state variable for error/empty/ready
@@ -375,17 +377,17 @@ nsPropertiesTable::ElementAt(DrawTarget*
   nsGlyphCode ch;
   ch.code[0] = mGlyphCache.CharAt(index);
   ch.code[1] = mGlyphCache.CharAt(index + 1);
   ch.font = mGlyphCache.CharAt(index + 2);
   return ch.code[0] == char16_t(0xFFFD) ? kNullGlyph : ch;
 }
 
 /* virtual */
-gfxTextRun*
+UniquePtr<gfxTextRun>
 nsPropertiesTable::MakeTextRun(DrawTarget*        aDrawTarget,
                                int32_t            aAppUnitsPerDevPixel,
                                gfxFontGroup*      aFontGroup,
                                const nsGlyphCode& aGlyph)
 {
   NS_ASSERTION(!aGlyph.IsGlyphID(),
                "nsPropertiesTable can only access glyphs by code point");
   return aFontGroup->
@@ -424,20 +426,21 @@ public:
 
   const FontFamilyName&
   FontNameFor(const nsGlyphCode& aGlyphCode) const override {
     NS_ASSERTION(aGlyphCode.IsGlyphID(),
                  "nsOpenTypeTable can only access glyphs by id");
     return mFontFamilyName;
   }
 
-  virtual gfxTextRun* MakeTextRun(DrawTarget*        aDrawTarget,
-                                  int32_t            aAppUnitsPerDevPixel,
-                                  gfxFontGroup*      aFontGroup,
-                                  const nsGlyphCode& aGlyph) override;
+  virtual UniquePtr<gfxTextRun>
+  MakeTextRun(DrawTarget*        aDrawTarget,
+              int32_t            aAppUnitsPerDevPixel,
+              gfxFontGroup*      aFontGroup,
+              const nsGlyphCode& aGlyph) override;
 
   // This returns a new OpenTypeTable instance to give access to OpenType MATH
   // table or nullptr if the font does not have such table. Ownership is passed
   // to the caller.
   static nsOpenTypeTable* Create(gfxFont* aFont)
   {
     if (!aFont->GetFontEntry()->TryGetMathTable()) {
       return nullptr;
@@ -464,18 +467,17 @@ private:
 
 void
 nsOpenTypeTable::UpdateCache(DrawTarget*   aDrawTarget,
                              int32_t       aAppUnitsPerDevPixel,
                              gfxFontGroup* aFontGroup,
                              char16_t      aChar)
 {
   if (mCharCache != aChar) {
-    nsAutoPtr<gfxTextRun> textRun;
-    textRun = aFontGroup->
+    UniquePtr<gfxTextRun> textRun = aFontGroup->
       MakeTextRun(&aChar, 1, aDrawTarget, aAppUnitsPerDevPixel, 0, nullptr);
     const gfxTextRun::CompressedGlyph& data = textRun->GetCharacterGlyphs()[0];
     if (data.IsSimpleGlyph()) {
       mGlyphID = data.GetSimpleGlyph();
     } else if (data.GetGlyphCount() == 1) {
       mGlyphID = textRun->GetDetailedGlyphs(0)->mGlyphID;
     } else {
       mGlyphID = 0;
@@ -547,29 +549,30 @@ nsOpenTypeTable::HasPartsOf(DrawTarget* 
   if (!mFontEntry->GetMathVariantsParts(mGlyphID, aVertical, parts)) {
     return false;
   }
 
   return parts[0] || parts[1] || parts[2] || parts[3];
 }
 
 /* virtual */
-gfxTextRun*
+UniquePtr<gfxTextRun>
 nsOpenTypeTable::MakeTextRun(DrawTarget*        aDrawTarget,
                              int32_t            aAppUnitsPerDevPixel,
                              gfxFontGroup*      aFontGroup,
                              const nsGlyphCode& aGlyph)
 {
   NS_ASSERTION(aGlyph.IsGlyphID(),
                "nsOpenTypeTable can only access glyphs by id");
 
   gfxTextRunFactory::Parameters params = {
     aDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel
   };
-  gfxTextRun* textRun = gfxTextRun::Create(&params, 1, aFontGroup, 0);
+  UniquePtr<gfxTextRun> textRun =
+    gfxTextRun::Create(&params, 1, aFontGroup, 0);
   textRun->AddGlyphRun(aFontGroup->GetFirstValidFont(),
                        gfxTextRange::kFontGroup, 0,
                        false, gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL);
                               // We don't care about CSS writing mode here;
                               // math runs are assumed to be horizontal.
   gfxTextRun::DetailedGlyph detailedGlyph;
   detailedGlyph.mGlyphID = aGlyph.glyphID;
   detailedGlyph.mAdvance =
@@ -1127,20 +1130,19 @@ StretchEnumContext::TryVariants(nsGlyphT
       gfxFont* mathFont = aFontGroup->get()->GetFirstMathFont();
       // For OpenType MATH fonts, we will rely on the DisplayOperatorMinHeight
       // to select the right size variant. Note that the value is sometimes too
       // small so we use kLargeOpFactor/kIntegralFactor as a minimum value.
       if (mathFont) {
         displayOperatorMinHeight =
           mathFont->GetMathConstant(gfxFontEntry::DisplayOperatorMinHeight,
                                     oneDevPixel);
-        nsAutoPtr<gfxTextRun> textRun;
-        textRun = aGlyphTable->MakeTextRun(mDrawTarget, oneDevPixel,
-                                           *aFontGroup, ch);
-        nsBoundingMetrics bm = MeasureTextRun(mDrawTarget, textRun);
+        UniquePtr<gfxTextRun> textRun =
+          aGlyphTable->MakeTextRun(mDrawTarget, oneDevPixel, *aFontGroup, ch);
+        nsBoundingMetrics bm = MeasureTextRun(mDrawTarget, textRun.get());
         float largeopFactor = kLargeOpFactor;
         if (NS_STRETCH_INTEGRAL & mStretchHint) {
           // integrals are drawn taller
           largeopFactor = kIntegralFactor;
         }
         nscoord minHeight = largeopFactor * (bm.ascent + bm.descent);
         if (displayOperatorMinHeight < minHeight) {
           displayOperatorMinHeight = minHeight;
@@ -1158,20 +1160,19 @@ StretchEnumContext::TryVariants(nsGlyphT
     if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamilyList, font,
                               aFontGroup)) {
       // if largeopOnly is set, break now
       if (largeopOnly) break;
       ++size;
       continue;
     }
 
-    nsAutoPtr<gfxTextRun> textRun;
-    textRun = aGlyphTable->MakeTextRun(mDrawTarget, oneDevPixel,
-                                       *aFontGroup, ch);
-    nsBoundingMetrics bm = MeasureTextRun(mDrawTarget, textRun);
+    UniquePtr<gfxTextRun> textRun =
+      aGlyphTable->MakeTextRun(mDrawTarget, oneDevPixel, *aFontGroup, ch);
+    nsBoundingMetrics bm = MeasureTextRun(mDrawTarget, textRun.get());
     if (ch.IsGlyphID()) {
       gfxFont* mathFont = aFontGroup->get()->GetFirstMathFont();
       if (mathFont) {
         // MeasureTextRun should have set the advance width to the right
         // bearing for OpenType MATH fonts. We now subtract the italic
         // correction, so that nsMathMLmmultiscripts will place the scripts
         // correctly.
         // Note that STIX-Word does not provide italic corrections but its
@@ -1208,17 +1209,17 @@ StretchEnumContext::TryVariants(nsGlyphT
           mBoundingMetrics.rightBearing = bm.rightBearing;
         // Continue to check other sizes unless largeopOnly
         haveBetter = largeopOnly;
       }
       else {
         mBoundingMetrics = bm;
         haveBetter = true;
         bestSize = charSize;
-        mChar->mGlyphs[0] = textRun;
+        mChar->mGlyphs[0] = Move(textRun);
         mChar->mDraw = DRAW_VARIANT;
       }
 #ifdef NOISY_SEARCH
       printf("    size:%d Current best\n", size);
 #endif
     }
     else {
 #ifdef NOISY_SEARCH
@@ -1247,17 +1248,17 @@ nsMathMLChar::StretchEnumContext::TryPar
                                            RefPtr<gfxFontGroup>* aFontGroup,
                                            const FontFamilyList& aFamilyList)
 {
   // Use our stretchy style context now that stretching is in progress
   nsFont font = mChar->mStyleContext->StyleFont()->mFont;
   NormalizeDefaultFont(font, mFontSizeInflation);
 
   // Compute the bounding metrics of all partial glyphs
-  nsAutoPtr<gfxTextRun> textRun[4];
+  UniquePtr<gfxTextRun> textRun[4];
   nsGlyphCode chdata[4];
   nsBoundingMetrics bmdata[4];
   nscoord sizedata[4];
 
   bool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL);
   nscoord oneDevPixel = mPresContext->AppUnitsPerDevPixel();
   char16_t uchar = mChar->mData[0];
   bool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0;
@@ -1271,17 +1272,17 @@ nsMathMLChar::StretchEnumContext::TryPar
     chdata[i] = ch;
     if (ch.Exists()) {
       if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamilyList, font,
                                 aFontGroup))
         return false;
 
       textRun[i] = aGlyphTable->MakeTextRun(mDrawTarget, oneDevPixel,
                                             *aFontGroup, ch);
-      nsBoundingMetrics bm = MeasureTextRun(mDrawTarget, textRun[i]);
+      nsBoundingMetrics bm = MeasureTextRun(mDrawTarget, textRun[i].get());
       bmdata[i] = bm;
       sizedata[i] = isVertical ? bm.ascent + bm.descent
                                : bm.rightBearing - bm.leftBearing;
     } else {
       // Null glue indicates that a rule will be drawn, which can stretch to
       // fill any space.
       textRun[i] = nullptr;
       bmdata[i] = nsBoundingMetrics();
@@ -1398,17 +1399,17 @@ nsMathMLChar::StretchEnumContext::TryPar
   }
   mGlyphFound = true;
   if (maxWidth)
     return false; // Continue to check other sizes
 
   // reset
   mChar->mDraw = DRAW_PARTS;
   for (int32_t i = 0; i < 4; i++) {
-    mChar->mGlyphs[i] = textRun[i];
+    mChar->mGlyphs[i] = Move(textRun[i]);
     mChar->mBmData[i] = bmdata[i];
   }
 
   return IsSizeOK(computedSize, mTargetSize, mStretchHint);
 }
 
 // This is called for each family, whether it exists or not
 bool
@@ -1534,23 +1535,21 @@ nsMathMLChar::StretchInternal(nsPresCont
   nsFontMetrics::Params params;
   params.language = styleFont->mLanguage;
   params.explicitLanguage = styleFont->mExplicitLanguage;
   params.userFontSet = aPresContext->GetUserFontSet();
   params.textPerf = aPresContext->GetTextPerfMetrics();
   RefPtr<nsFontMetrics> fm =
     aPresContext->DeviceContext()->GetMetricsFor(font, params);
   uint32_t len = uint32_t(mData.Length());
-  nsAutoPtr<gfxTextRun> textRun;
-  textRun = fm->GetThebesFontGroup()->
+  mGlyphs[0] = fm->GetThebesFontGroup()->
     MakeTextRun(static_cast<const char16_t*>(mData.get()), len, aDrawTarget,
                 aPresContext->AppUnitsPerDevPixel(), 0,
                 aPresContext->MissingFontRecorder());
-  aDesiredStretchSize = MeasureTextRun(aDrawTarget, textRun);
-  mGlyphs[0] = textRun;
+  aDesiredStretchSize = MeasureTextRun(aDrawTarget, mGlyphs[0].get());
 
   bool maxWidth = (NS_STRETCH_MAXWIDTH & aStretchHint) != 0;
   if (!maxWidth) {
     mUnscaledAscent = aDesiredStretchSize.ascent;
   }
 
   //////////////////////////////////////////////////////////////////////////////
   // 1. Check the common situations where stretching is not actually needed
@@ -2138,17 +2137,17 @@ nsMathMLChar::PaintForeground(nsPresCont
 
   switch(mDraw)
   {
     case DRAW_NORMAL:
     case DRAW_VARIANT:
       // draw a single glyph (base size or size variant)
       // XXXfredw verify if mGlyphs[0] is non-null to workaround bug 973322.
       if (mGlyphs[0]) {
-        mGlyphs[0]->Draw(Range(mGlyphs[0]), gfxPoint(0.0, mUnscaledAscent),
+        mGlyphs[0]->Draw(Range(mGlyphs[0].get()), gfxPoint(0.0, mUnscaledAscent),
                          gfxTextRun::DrawParams(thebesContext));
       }
       break;
     case DRAW_PARTS: {
       // paint by parts
       if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
         PaintVertically(aPresContext, thebesContext, r, fgColor);
       else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
@@ -2296,17 +2295,17 @@ nsMathMLChar::PaintVertically(nsPresCont
         }
         else { // middle
           clipRect.y = start[i];
           clipRect.height = end[i] - start[i];
         }
       }
       if (!clipRect.IsEmpty()) {
         AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
-        mGlyphs[i]->Draw(Range(mGlyphs[i]), gfxPoint(dx, dy), params);
+        mGlyphs[i]->Draw(Range(mGlyphs[i].get()), gfxPoint(dx, dy), params);
       }
     }
   }
 
   ///////////////
   // fill the gap between top and middle, and between middle and bottom.
   if (!mGlyphs[3]) { // null glue : draw a rule
     // figure out the dimensions of the rule to be drawn :
@@ -2362,17 +2361,17 @@ nsMathMLChar::PaintVertically(nsPresCont
       // Make sure not to draw outside the character
       nscoord dy = std::max(end[i], aRect.y);
       nscoord fillEnd = std::min(start[i+1], aRect.YMost());
       while (dy < fillEnd) {
         clipRect.y = dy;
         clipRect.height = std::min(bm.ascent + bm.descent, fillEnd - dy);
         AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
         dy += bm.ascent;
-        mGlyphs[3]->Draw(Range(mGlyphs[3]), gfxPoint(dx, dy), params);
+        mGlyphs[3]->Draw(Range(mGlyphs[3].get()), gfxPoint(dx, dy), params);
         dy += bm.descent;
       }
     }
   }
 #ifdef DEBUG
   else {
     for (i = 0; i < 2; ++i) {
       NS_ASSERTION(end[i] >= start[i+1],
@@ -2466,17 +2465,17 @@ nsMathMLChar::PaintHorizontally(nsPresCo
         }
         else { // middle
           clipRect.x = start[i];
           clipRect.width = end[i] - start[i];
         }
       }
       if (!clipRect.IsEmpty()) {
         AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
-        mGlyphs[i]->Draw(Range(mGlyphs[i]), gfxPoint(dx, dy), params);
+        mGlyphs[i]->Draw(Range(mGlyphs[i].get()), gfxPoint(dx, dy), params);
       }
     }
   }
 
   ////////////////
   // fill the gap between left and middle, and between middle and right.
   if (!mGlyphs[3]) { // null glue : draw a rule
     // figure out the dimensions of the rule to be drawn :
@@ -2530,17 +2529,17 @@ nsMathMLChar::PaintHorizontally(nsPresCo
       // Make sure not to draw outside the character
       nscoord dx = std::max(end[i], aRect.x);
       nscoord fillEnd = std::min(start[i+1], aRect.XMost());
       while (dx < fillEnd) {
         clipRect.x = dx;
         clipRect.width = std::min(bm.rightBearing - bm.leftBearing, fillEnd - dx);
         AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
         dx -= bm.leftBearing;
-        mGlyphs[3]->Draw(Range(mGlyphs[3]), gfxPoint(dx, dy), params);
+        mGlyphs[3]->Draw(Range(mGlyphs[3].get()), gfxPoint(dx, dy), params);
         dx += bm.rightBearing;
       }
     }
   }
 #ifdef DEBUG
   else { // no glue
     for (i = 0; i < 2; ++i) {
       NS_ASSERTION(end[i] >= start[i+1],
--- a/layout/mathml/nsMathMLChar.h
+++ b/layout/mathml/nsMathMLChar.h
@@ -202,17 +202,17 @@ protected:
 
 private:
   nsRect             mRect;
   nsStretchDirection mDirection;
   nsBoundingMetrics  mBoundingMetrics;
   nsStyleContext*    mStyleContext;
   // mGlyphs/mBmData are arrays describing the glyphs used to draw the operator.
   // See the drawing methods below.
-  nsAutoPtr<gfxTextRun> mGlyphs[4];
+  mozilla::UniquePtr<gfxTextRun> mGlyphs[4];
   nsBoundingMetrics     mBmData[4];
   // mUnscaledAscent is the actual ascent of the char.
   nscoord            mUnscaledAscent;
   // mScaleX, mScaleY are the factors by which we scale the char.
   float              mScaleX, mScaleY;
 
   // mDraw indicates how we draw the stretchy operator:
   // - DRAW_NORMAL: we render the mData string normally.