bug 1018551 - clean up redundancy in the font/shaper code. r=jdaggett
authorJonathan Kew <jkew@mozilla.com>
Sat, 31 May 2014 08:12:40 +0100
changeset 191349 ee3e74ba96a96516a81da83b12307c4515ab01c0
parent 191348 6abd5ef709cc76f0fd9077fabc6eeb2a3cc19441
child 191350 f04ad92a05ead95c41ed69b9d425029bee753cad
push id27041
push userphilringnalda@gmail.com
push dateSun, 29 Jun 2014 00:39:21 +0000
treeherdermozilla-central@afa67a2f7905 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdaggett
bugs1018551
milestone33.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 1018551 - clean up redundancy in the font/shaper code. r=jdaggett
gfx/thebes/gfxDWriteFonts.cpp
gfx/thebes/gfxDWriteFonts.h
gfx/thebes/gfxFT2Fonts.cpp
gfx/thebes/gfxFT2Fonts.h
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxGDIFont.cpp
gfx/thebes/gfxGDIFont.h
gfx/thebes/gfxMacFont.cpp
gfx/thebes/gfxMacFont.h
gfx/thebes/gfxPangoFonts.cpp
--- a/gfx/thebes/gfxDWriteFonts.cpp
+++ b/gfx/thebes/gfxDWriteFonts.cpp
@@ -2,19 +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 "gfxDWriteFonts.h"
 
 #include "mozilla/MemoryReporting.h"
 
-#include "gfxHarfBuzzShaper.h"
 #include <algorithm>
-#include "gfxGraphiteShaper.h"
 #include "gfxDWriteFontList.h"
 #include "gfxContext.h"
 #include <dwrite.h>
 
 #include "harfbuzz/hb.h"
 
 // Chosen this as to resemble DWrite's own oblique face style.
 #define OBLIQUE_SKEW_FACTOR 0.3
@@ -101,24 +99,16 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntr
     rv = fe->CreateFontFace(getter_AddRefs(mFontFace), sims);
 
     if (NS_FAILED(rv)) {
         mIsValid = false;
         return;
     }
 
     ComputeMetrics(anAAOption);
-
-    if (FontCanSupportGraphite()) {
-        mGraphiteShaper = new gfxGraphiteShaper(this);
-    }
-
-    if (FontCanSupportHarfBuzz()) {
-        mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
-    }
 }
 
 gfxDWriteFont::~gfxDWriteFont()
 {
     if (mCairoFontFace) {
         cairo_font_face_destroy(mCairoFontFace);
     }
     if (mScaledFont) {
@@ -129,42 +119,16 @@ gfxDWriteFont::~gfxDWriteFont()
 
 gfxFont*
 gfxDWriteFont::CopyWithAntialiasOption(AntialiasOption anAAOption)
 {
     return new gfxDWriteFont(static_cast<gfxDWriteFontEntry*>(mFontEntry.get()),
                              &mStyle, mNeedsBold, anAAOption);
 }
 
-bool
-gfxDWriteFont::ShapeText(gfxContext      *aContext,
-                         const char16_t *aText,
-                         uint32_t         aOffset,
-                         uint32_t         aLength,
-                         int32_t          aScript,
-                         gfxShapedText   *aShapedText,
-                         bool             aPreferPlatformShaping)
-{
-    bool ok = false;
-
-    if (mGraphiteShaper && gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
-        ok = mGraphiteShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                        aScript, aShapedText);
-    }
-
-    if (!ok && mHarfBuzzShaper) {
-        ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                        aScript, aShapedText);
-    }
-
-    PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
-
-    return ok;
-}
-
 const gfxFont::Metrics&
 gfxDWriteFont::GetMetrics()
 {
     return *mMetrics;
 }
 
 bool
 gfxDWriteFont::GetFakeMetricsForArialBlack(DWRITE_FONT_METRICS *aFontMetrics)
--- a/gfx/thebes/gfxDWriteFonts.h
+++ b/gfx/thebes/gfxDWriteFonts.h
@@ -66,24 +66,16 @@ public:
 
     virtual FontType GetType() const { return FONT_TYPE_DWRITE; }
 
     virtual mozilla::TemporaryRef<mozilla::gfx::ScaledFont> GetScaledFont(mozilla::gfx::DrawTarget *aTarget);
 
     virtual cairo_scaled_font_t *GetCairoScaledFont();
 
 protected:
-    virtual bool ShapeText(gfxContext     *aContext,
-                           const char16_t *aText,
-                           uint32_t        aOffset,
-                           uint32_t        aLength,
-                           int32_t         aScript,
-                           gfxShapedText  *aShapedText,
-                           bool            aPreferPlatformShaping = false);
-
     bool GetFakeMetricsForArialBlack(DWRITE_FONT_METRICS *aFontMetrics);
 
     void ComputeMetrics(AntialiasOption anAAOption);
 
     bool HasBitmapStrikeForSize(uint32_t aSize);
 
     cairo_font_face_t *CairoFontFace();
 
--- a/gfx/thebes/gfxFT2Fonts.cpp
+++ b/gfx/thebes/gfxFT2Fonts.cpp
@@ -19,18 +19,16 @@
 #endif
 
 #include "gfxTypes.h"
 #include "gfxFT2Fonts.h"
 #include "gfxFT2FontBase.h"
 #include "gfxFT2Utils.h"
 #include "gfxFT2FontList.h"
 #include <locale.h>
-#include "gfxHarfBuzzShaper.h"
-#include "gfxGraphiteShaper.h"
 #include "nsGkAtoms.h"
 #include "nsTArray.h"
 #include "nsUnicodeRange.h"
 #include "nsCRT.h"
 #include "nsXULAppAPI.h"
 
 #include "prlog.h"
 #include "prinit.h"
@@ -39,52 +37,30 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/gfx/2D.h"
 
 /**
  * gfxFT2Font
  */
 
 bool
-gfxFT2Font::ShapeText(gfxContext      *aContext,
+gfxFT2Font::ShapeText(gfxContext     *aContext,
                       const char16_t *aText,
-                      uint32_t         aOffset,
-                      uint32_t         aLength,
-                      int32_t          aScript,
-                      gfxShapedText   *aShapedText,
-                      bool             aPreferPlatformShaping)
+                      uint32_t        aOffset,
+                      uint32_t        aLength,
+                      int32_t         aScript,
+                      gfxShapedText  *aShapedText)
 {
-    bool ok = false;
-
-    if (FontCanSupportGraphite()) {
-        if (gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
-            if (!mGraphiteShaper) {
-                mGraphiteShaper = new gfxGraphiteShaper(this);
-            }
-            ok = mGraphiteShaper->ShapeText(aContext, aText,
-                                            aOffset, aLength,
-                                            aScript, aShapedText);
-        }
+    if (!gfxFont::ShapeText(aContext, aText, aOffset, aLength, aScript,
+                            aShapedText)) {
+        // harfbuzz must have failed(?!), just render raw glyphs
+        AddRange(aText, aOffset, aLength, aShapedText);
+        PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
     }
 
-    if (!ok) {
-        if (!mHarfBuzzShaper) {
-            mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
-        }
-        ok = mHarfBuzzShaper->ShapeText(aContext, aText,
-                                        aOffset, aLength,
-                                        aScript, aShapedText);
-    }
-
-    if (!ok) {
-        AddRange(aText, aOffset, aLength, aShapedText);
-    }
-
-    PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
-
     return true;
 }
 
 void
 gfxFT2Font::AddRange(const char16_t *aText, uint32_t aOffset,
                      uint32_t aLength, gfxShapedText *aShapedText)
 {
     const uint32_t appUnitsPerDevUnit = aShapedText->GetAppUnitsPerDevUnit();
--- a/gfx/thebes/gfxFT2Fonts.h
+++ b/gfx/thebes/gfxFT2Fonts.h
@@ -72,18 +72,17 @@ public: // new functions
 #endif
 
 protected:
     virtual bool ShapeText(gfxContext      *aContext,
                            const char16_t *aText,
                            uint32_t         aOffset,
                            uint32_t         aLength,
                            int32_t          aScript,
-                           gfxShapedText   *aShapedText,
-                           bool             aPreferPlatformShaping);
+                           gfxShapedText   *aShapedText);
 
     void FillGlyphDataForChar(uint32_t ch, CachedGlyphData *gd);
 
     void AddRange(const char16_t *aText,
                   uint32_t         aOffset,
                   uint32_t         aLength,
                   gfxShapedText   *aShapedText);
 
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -18,16 +18,17 @@
 
 #include "gfxFont.h"
 #include "gfxPlatform.h"
 #include "nsGkAtoms.h"
 
 #include "gfxTypes.h"
 #include "gfxContext.h"
 #include "gfxFontMissingGlyphs.h"
+#include "gfxGraphiteShaper.h"
 #include "gfxHarfBuzzShaper.h"
 #include "gfxUserFontSet.h"
 #include "gfxPlatformFontList.h"
 #include "gfxScriptItemizer.h"
 #include "nsSpecialCasingData.h"
 #include "nsTextRunTransformations.h"
 #include "nsUnicodeProperties.h"
 #include "nsMathUtils.h"
@@ -4069,59 +4070,57 @@ gfxFont::CacheHashEntry::KeyEquals(const
 }
 
 bool
 gfxFont::ShapeText(gfxContext    *aContext,
                    const uint8_t *aText,
                    uint32_t       aOffset,
                    uint32_t       aLength,
                    int32_t        aScript,
-                   gfxShapedText *aShapedText,
-                   bool           aPreferPlatformShaping)
+                   gfxShapedText *aShapedText)
 {
     nsDependentCSubstring ascii((const char*)aText, aLength);
     nsAutoString utf16;
     AppendASCIItoUTF16(ascii, utf16);
     if (utf16.Length() != aLength) {
         return false;
     }
     return ShapeText(aContext, utf16.BeginReading(), aOffset, aLength,
-                     aScript, aShapedText, aPreferPlatformShaping);
+                     aScript, aShapedText);
 }
 
 bool
 gfxFont::ShapeText(gfxContext      *aContext,
                    const char16_t *aText,
                    uint32_t         aOffset,
                    uint32_t         aLength,
                    int32_t          aScript,
-                   gfxShapedText   *aShapedText,
-                   bool             aPreferPlatformShaping)
+                   gfxShapedText   *aShapedText)
 {
     bool ok = false;
 
-    if (mGraphiteShaper && gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
-        ok = mGraphiteShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                        aScript, aShapedText);
-    }
-
-    if (!ok && mHarfBuzzShaper && !aPreferPlatformShaping) {
-        ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                        aScript, aShapedText);
+    if (FontCanSupportGraphite()) {
+        if (gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
+            if (!mGraphiteShaper) {
+                mGraphiteShaper = new gfxGraphiteShaper(this);
+            }
+            ok = mGraphiteShaper->ShapeText(aContext, aText, aOffset, aLength,
+                                            aScript, aShapedText);
+        }
     }
 
     if (!ok) {
-        if (!mPlatformShaper) {
-            CreatePlatformShaper();
-        }
-        if (mPlatformShaper) {
-            ok = mPlatformShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                            aScript, aShapedText);
-        }
-    }
+        if (!mHarfBuzzShaper) {
+            mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
+        }
+        ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
+                                        aScript, aShapedText);
+    }
+
+    NS_WARN_IF_FALSE(ok, "shaper failed, expect scrambled or missing text");
 
     PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
 
     return ok;
 }
 
 void
 gfxFont::PostShapingFixup(gfxContext      *aContext,
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1474,22 +1474,22 @@ public:
         NS_ASSERTION(aFont, "shaper requires a valid font!");
     }
 
     virtual ~gfxFontShaper() { }
 
     // Shape a piece of text and store the resulting glyph data into
     // aShapedText. Parameters aOffset/aLength indicate the range of
     // aShapedText to be updated; aLength is also the length of aText.
-    virtual bool ShapeText(gfxContext      *aContext,
+    virtual bool ShapeText(gfxContext     *aContext,
                            const char16_t *aText,
-                           uint32_t         aOffset,
-                           uint32_t         aLength,
-                           int32_t          aScript,
-                           gfxShapedText   *aShapedText) = 0;
+                           uint32_t        aOffset,
+                           uint32_t        aLength,
+                           int32_t         aScript,
+                           gfxShapedText  *aShapedText) = 0;
 
     gfxFont *GetFont() const { return mFont; }
 
     // returns true if features exist in output, false otherwise
     static bool
     MergeFontFeatures(const gfxFontStyle *aStyle,
                       const nsTArray<gfxFontFeature>& aFontFeatures,
                       bool aDisableLigatures,
@@ -1991,28 +1991,26 @@ protected:
     bool SpaceMayParticipateInShaping(int32_t aRunScript);
 
     // For 8-bit text, expand to 16-bit and then call the following method.
     bool ShapeText(gfxContext    *aContext,
                    const uint8_t *aText,
                    uint32_t       aOffset, // dest offset in gfxShapedText
                    uint32_t       aLength,
                    int32_t        aScript,
-                   gfxShapedText *aShapedText, // where to store the result
-                   bool           aPreferPlatformShaping = false);
+                   gfxShapedText *aShapedText); // where to store the result
 
     // Call the appropriate shaper to generate glyphs for aText and store
     // them into aShapedText.
     virtual bool ShapeText(gfxContext      *aContext,
                            const char16_t *aText,
                            uint32_t         aOffset,
                            uint32_t         aLength,
                            int32_t          aScript,
-                           gfxShapedText   *aShapedText,
-                           bool             aPreferPlatformShaping = false);
+                           gfxShapedText   *aShapedText);
 
     // Helper to adjust for synthetic bold and set character-type flags
     // in the shaped text; implementations of ShapeText should call this
     // after glyph shaping has been completed.
     void PostShapingFixup(gfxContext      *aContext,
                           const char16_t *aText,
                           uint32_t         aOffset, // position within aShapedText
                           uint32_t         aLength,
@@ -2161,29 +2159,24 @@ protected:
 
     // the AA setting requested for this font - may affect glyph bounds
     AntialiasOption            mAntialiasOption;
 
     // a copy of the font without antialiasing, if needed for separate
     // measurement by mathml code
     nsAutoPtr<gfxFont>         mNonAAFont;
 
-    // we may switch between these shapers on the fly, based on the script
-    // of the text run being shaped
-    nsAutoPtr<gfxFontShaper>   mPlatformShaper;
+    // we create either or both of these shapers when needed, depending
+    // whether the font has graphite tables, and whether graphite shaping
+    // is actually enabled
     nsAutoPtr<gfxFontShaper>   mHarfBuzzShaper;
     nsAutoPtr<gfxFontShaper>   mGraphiteShaper;
 
     mozilla::RefPtr<mozilla::gfx::ScaledFont> mAzureScaledFont;
 
-    // Create a default platform text shaper for this font.
-    // (TODO: This should become pure virtual once all font backends have
-    // been updated.)
-    virtual void CreatePlatformShaper() { }
-
     // Helper for subclasses that want to initialize standard metrics from the
     // tables of sfnt (TrueType/OpenType) fonts.
     // This will use mFUnitsConvFactor if it is already set, else compute it
     // from mAdjustedSize and the unitsPerEm in the font's 'head' table.
     // Returns TRUE and sets mIsValid=TRUE if successful;
     // Returns TRUE but leaves mIsValid=FALSE if the font seems to be broken.
     // Returns FALSE if the font does not appear to be an sfnt at all,
     // and should be handled (if possible) using other APIs.
--- a/gfx/thebes/gfxGDIFont.cpp
+++ b/gfx/thebes/gfxGDIFont.cpp
@@ -3,19 +3,17 @@
  * 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 "gfxGDIFont.h"
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/WindowsVersion.h"
 
-#include "gfxHarfBuzzShaper.h"
 #include <algorithm>
-#include "gfxGraphiteShaper.h"
 #include "gfxWindowsPlatform.h"
 #include "gfxContext.h"
 #include "mozilla/Preferences.h"
 #include "nsUnicodeProperties.h"
 #include "gfxFontConstants.h"
 
 #include "cairo-win32.h"
 
@@ -47,20 +45,16 @@ gfxGDIFont::gfxGDIFont(GDIFontEntry *aFo
     : gfxFont(aFontEntry, aFontStyle, anAAOption),
       mFont(nullptr),
       mFontFace(nullptr),
       mMetrics(nullptr),
       mSpaceGlyph(0),
       mNeedsBold(aNeedsBold),
       mScriptCache(nullptr)
 {
-    if (FontCanSupportGraphite()) {
-        mGraphiteShaper = new gfxGraphiteShaper(this);
-    }
-    mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
 }
 
 gfxGDIFont::~gfxGDIFont()
 {
     if (mScaledFont) {
         cairo_scaled_font_destroy(mScaledFont);
     }
     if (mFontFace) {
@@ -78,23 +72,22 @@ gfxGDIFont::~gfxGDIFont()
 gfxFont*
 gfxGDIFont::CopyWithAntialiasOption(AntialiasOption anAAOption)
 {
     return new gfxGDIFont(static_cast<GDIFontEntry*>(mFontEntry.get()),
                           &mStyle, mNeedsBold, anAAOption);
 }
 
 bool
-gfxGDIFont::ShapeText(gfxContext      *aContext,
+gfxGDIFont::ShapeText(gfxContext     *aContext,
                       const char16_t *aText,
-                      uint32_t         aOffset,
-                      uint32_t         aLength,
-                      int32_t          aScript,
-                      gfxShapedText   *aShapedText,
-                      bool             aPreferPlatformShaping)
+                      uint32_t        aOffset,
+                      uint32_t        aLength,
+                      int32_t         aScript,
+                      gfxShapedText  *aShapedText)
 {
     if (!mMetrics) {
         Initialize();
     }
     if (!mIsValid) {
         NS_WARNING("invalid font! expect incorrect text rendering");
         return false;
     }
@@ -103,17 +96,17 @@ gfxGDIFont::ShapeText(gfxContext      *a
     // creating a "toy" font internally (see bug 544617).
     // We must check that this succeeded, otherwise we risk cairo creating the
     // wrong kind of font internally as a fallback (bug 744480).
     if (!SetupCairoFont(aContext)) {
         return false;
     }
 
     return gfxFont::ShapeText(aContext, aText, aOffset, aLength, aScript,
-                              aShapedText, aPreferPlatformShaping);
+                              aShapedText);
 }
 
 const gfxFont::Metrics&
 gfxGDIFont::GetMetrics()
 {
     if (!mMetrics) {
         Initialize();
     }
--- a/gfx/thebes/gfxGDIFont.h
+++ b/gfx/thebes/gfxGDIFont.h
@@ -67,23 +67,22 @@ public:
                                         FontCacheSizes* aSizes) const;
     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontCacheSizes* aSizes) const;
 
     virtual FontType GetType() const { return FONT_TYPE_GDI; }
 
 protected:
     /* override to ensure the cairo font is set up properly */
-    virtual bool ShapeText(gfxContext      *aContext,
+    virtual bool ShapeText(gfxContext     *aContext,
                            const char16_t *aText,
-                           uint32_t         aOffset,
-                           uint32_t         aLength,
-                           int32_t          aScript,
-                           gfxShapedText   *aShapedText,
-                           bool             aPreferPlatformShaping);
+                           uint32_t        aOffset,
+                           uint32_t        aLength,
+                           int32_t         aScript,
+                           gfxShapedText  *aShapedText);
 
     void Initialize(); // creates metrics and Cairo fonts
 
     // Fill the given LOGFONT record according to our style, but don't adjust
     // the lfItalic field if we're going to use a cairo transform for fake
     // italics.
     void FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize, bool aUseGDIFakeItalic);
 
--- a/gfx/thebes/gfxMacFont.cpp
+++ b/gfx/thebes/gfxMacFont.cpp
@@ -3,19 +3,17 @@
  * 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 "gfxMacFont.h"
 
 #include "mozilla/MemoryReporting.h"
 
 #include "gfxCoreTextShaper.h"
-#include "gfxHarfBuzzShaper.h"
 #include <algorithm>
-#include "gfxGraphiteShaper.h"
 #include "gfxPlatformMac.h"
 #include "gfxContext.h"
 #include "gfxFontUtils.h"
 #include "gfxMacPlatformFontList.h"
 #include "gfxFontConstants.h"
 
 #include "cairo-quartz.h"
 
@@ -102,59 +100,54 @@ gfxMacFont::gfxMacFont(MacOSFontEntry *a
         mIsValid = false;
 #ifdef DEBUG
         char warnBuf[1024];
         sprintf(warnBuf, "Failed to create scaled font: %s status: %d",
                 NS_ConvertUTF16toUTF8(GetName()).get(), cairoerr);
         NS_WARNING(warnBuf);
 #endif
     }
-
-    if (FontCanSupportGraphite()) {
-        mGraphiteShaper = new gfxGraphiteShaper(this);
-    }
-    if (FontCanSupportHarfBuzz()) {
-        mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
-    }
 }
 
 gfxMacFont::~gfxMacFont()
 {
     if (mScaledFont) {
         cairo_scaled_font_destroy(mScaledFont);
     }
     if (mFontFace) {
         cairo_font_face_destroy(mFontFace);
     }
 }
 
 bool
-gfxMacFont::ShapeText(gfxContext      *aContext,
+gfxMacFont::ShapeText(gfxContext     *aContext,
                       const char16_t *aText,
-                      uint32_t         aOffset,
-                      uint32_t         aLength,
-                      int32_t          aScript,
-                      gfxShapedText   *aShapedText,
-                      bool             aPreferPlatformShaping)
+                      uint32_t        aOffset,
+                      uint32_t        aLength,
+                      int32_t         aScript,
+                      gfxShapedText  *aShapedText)
 {
     if (!mIsValid) {
         NS_WARNING("invalid font! expect incorrect text rendering");
         return false;
     }
 
-    bool requiresAAT =
-        static_cast<MacOSFontEntry*>(GetFontEntry())->RequiresAATLayout();
-    return gfxFont::ShapeText(aContext, aText, aOffset, aLength,
-                              aScript, aShapedText, requiresAAT);
-}
+    if (static_cast<MacOSFontEntry*>(GetFontEntry())->RequiresAATLayout()) {
+        if (!mCoreTextShaper) {
+            mCoreTextShaper = new gfxCoreTextShaper(this);
+        }
+        if (mCoreTextShaper->ShapeText(aContext, aText, aOffset, aLength,
+                                       aScript, aShapedText)) {
+            PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
+            return true;
+        }
+    }
 
-void
-gfxMacFont::CreatePlatformShaper()
-{
-    mPlatformShaper = new gfxCoreTextShaper(this);
+    return gfxFont::ShapeText(aContext, aText, aOffset, aLength, aScript,
+                              aShapedText);
 }
 
 bool
 gfxMacFont::SetupCairoFont(gfxContext *aContext)
 {
     if (cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
         // Don't cairo_set_scaled_font as that would propagate the error to
         // the cairo_t, precluding any further drawing.
--- a/gfx/thebes/gfxMacFont.h
+++ b/gfx/thebes/gfxMacFont.h
@@ -46,38 +46,37 @@ public:
     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontCacheSizes* aSizes) const;
     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontCacheSizes* aSizes) const;
 
     virtual FontType GetType() const { return FONT_TYPE_MAC; }
 
 protected:
-    virtual void CreatePlatformShaper();
-
     // override to prefer CoreText shaping with fonts that depend on AAT
-    virtual bool ShapeText(gfxContext      *aContext,
+    virtual bool ShapeText(gfxContext     *aContext,
                            const char16_t *aText,
-                           uint32_t         aOffset,
-                           uint32_t         aLength,
-                           int32_t          aScript,
-                           gfxShapedText   *aShapedText,
-                           bool             aPreferPlatformShaping = false);
+                           uint32_t        aOffset,
+                           uint32_t        aLength,
+                           int32_t         aScript,
+                           gfxShapedText  *aShapedText);
 
     void InitMetrics();
     void InitMetricsFromPlatform();
 
     // Get width and glyph ID for a character; uses aConvFactor
     // to convert font units as returned by CG to actual dimensions
     gfxFloat GetCharWidth(CFDataRef aCmap, char16_t aUniChar,
                           uint32_t *aGlyphID, gfxFloat aConvFactor);
 
     // a weak reference to the CoreGraphics font: this is owned by the
     // MacOSFontEntry, it is not retained or released by gfxMacFont
     CGFontRef             mCGFont;
 
     cairo_font_face_t    *mFontFace;
 
+    nsAutoPtr<gfxFontShaper> mCoreTextShaper;
+
     Metrics               mMetrics;
     uint32_t              mSpaceGlyph;
 };
 
 #endif /* GFX_MACFONT_H */
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -15,18 +15,16 @@
 #ifdef MOZ_WIDGET_QT
 #include "gfxQtPlatform.h"
 #endif
 #include "gfxPangoFonts.h"
 #include "gfxFT2FontBase.h"
 #include "gfxFT2Utils.h"
 #include "harfbuzz/hb.h"
 #include "harfbuzz/hb-ot.h"
-#include "gfxHarfBuzzShaper.h"
-#include "gfxGraphiteShaper.h"
 #include "nsUnicodeProperties.h"
 #include "nsUnicodeScriptCodes.h"
 #include "gfxFontconfigUtils.h"
 #include "gfxUserFontSet.h"
 #include "gfxFontConstants.h"
 
 #include <cairo.h>
 #include <cairo-ft.h>
@@ -658,24 +656,16 @@ public:
 
 #ifdef USE_SKIA
     virtual mozilla::TemporaryRef<mozilla::gfx::GlyphRenderingOptions> GetGlyphRenderingOptions();
 #endif
 
 protected:
     virtual already_AddRefed<gfxFont> GetSmallCapsFont();
 
-    virtual bool ShapeText(gfxContext      *aContext,
-                           const char16_t *aText,
-                           uint32_t         aOffset,
-                           uint32_t         aLength,
-                           int32_t          aScript,
-                           gfxShapedText   *aShapedText,
-                           bool             aPreferPlatformShaping);
-
 private:
     gfxFcFont(cairo_scaled_font_t *aCairoFont, gfxFcFontEntry *aFontEntry,
               const gfxFontStyle *aFontStyle);
 
     // key for locating a gfxFcFont corresponding to a cairo_scaled_font
     static cairo_user_data_key_t sGfxFontKey;
 };
 
@@ -1559,52 +1549,16 @@ gfxFcFont::GetSmallCapsFont()
 
     font = new gfxFcFont(smallFont, fe, &style);
     gfxFontCache::GetCache()->AddNew(font);
     cairo_scaled_font_destroy(smallFont);
 
     return font.forget();
 }
 
-bool
-gfxFcFont::ShapeText(gfxContext      *aContext,
-                     const char16_t *aText,
-                     uint32_t         aOffset,
-                     uint32_t         aLength,
-                     int32_t          aScript,
-                     gfxShapedText   *aShapedText,
-                     bool             aPreferPlatformShaping)
-{
-    bool ok = false;
-
-    if (FontCanSupportGraphite()) {
-        if (gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
-            if (!mGraphiteShaper) {
-                mGraphiteShaper = new gfxGraphiteShaper(this);
-            }
-            ok = mGraphiteShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                            aScript, aShapedText);
-        }
-    }
-
-    if (!ok) {
-        if (!mHarfBuzzShaper) {
-            mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
-        }
-        ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
-                                        aScript, aShapedText);
-    }
-
-    NS_WARN_IF_FALSE(ok, "shaper failed, expect scrambled or missing text");
-
-    PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
-
-    return ok;
-}
-
 /* static */ void
 gfxPangoFontGroup::Shutdown()
 {
     // Resetting gFTLibrary in case this is wanted again after a
     // cairo_debug_reset_static_data.
     gFTLibrary = nullptr;
 }