Bug 407059 - Part 4: Use gfxHarfbuzzShaper::GetGlyphHAdvance() for math operators. r=jfkthame
☠☠ backed out by 545be5328235 ☠ ☠
authorFrédéric Wang <fred.wang@free.fr>
Tue, 22 Apr 2014 08:44:04 -0400
changeset 179924 c940a2d399c435c2786db1cb740a15b0fe289711
parent 179923 77593dd1b044f171e967afb6c36e70da77048929
child 179925 21fee1261f2e1cbffd09d9c3d734ce50390b5cdd
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersjfkthame
bugs407059
milestone31.0a1
Bug 407059 - Part 4: Use gfxHarfbuzzShaper::GetGlyphHAdvance() for math operators. r=jfkthame
gfx/thebes/gfxFT2FontBase.cpp
gfx/thebes/gfxFT2Fonts.cpp
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxHarfBuzzShaper.cpp
gfx/thebes/gfxHarfBuzzShaper.h
gfx/thebes/gfxPangoFonts.cpp
layout/mathml/nsMathMLChar.cpp
--- a/gfx/thebes/gfxFT2FontBase.cpp
+++ b/gfx/thebes/gfxFT2FontBase.cpp
@@ -112,17 +112,19 @@ gfxFT2FontBase::GetMetrics()
 {
     if (mHasMetrics)
         return mMetrics;
 
     if (MOZ_UNLIKELY(GetStyle()->size <= 0.0)) {
         new(&mMetrics) gfxFont::Metrics(); // zero initialize
         mSpaceGlyph = 0;
     } else {
-        gfxFT2LockedFace(this).GetMetrics(&mMetrics, &mSpaceGlyph);
+        gfxFT2LockedFace face(this);
+        mFUnitsConvFactor = face.XScale();
+        face.GetMetrics(&mMetrics, &mSpaceGlyph);
     }
 
     SanitizeMetrics(&mMetrics, false);
 
 #if 0
     //    printf("font name: %s %f\n", NS_ConvertUTF16toUTF8(GetName()).get(), GetStyle()->size);
     //    printf ("pango font %s\n", pango_font_description_to_string (pango_font_describe (font)));
 
--- a/gfx/thebes/gfxFT2Fonts.cpp
+++ b/gfx/thebes/gfxFT2Fonts.cpp
@@ -421,19 +421,16 @@ gfxFT2Font::ShapeText(gfxContext      *a
             ok = mGraphiteShaper->ShapeText(aContext, aText,
                                             aOffset, aLength,
                                             aScript, aShapedText);
         }
     }
 
     if (!ok && gfxPlatform::GetPlatform()->UseHarfBuzzForScript(aScript)) {
         if (!mHarfBuzzShaper) {
-            gfxFT2LockedFace face(this);
-            mFUnitsConvFactor = face.XScale();
-
             mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
         }
         ok = mHarfBuzzShaper->ShapeText(aContext, aText,
                                         aOffset, aLength,
                                         aScript, aShapedText);
     }
 
     if (!ok) {
--- 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 "gfxHarfBuzzShaper.h"
 #include "gfxUserFontSet.h"
 #include "gfxPlatformFontList.h"
 #include "gfxScriptItemizer.h"
 #include "nsUnicodeProperties.h"
 #include "nsMathUtils.h"
 #include "nsBidiUtils.h"
 #include "nsUnicodeRange.h"
 #include "nsStyleConsts.h"
@@ -2022,16 +2023,38 @@ gfxFont::~gfxFont()
 
     mFontEntry->NotifyFontDestroyed(this);
 
     if (mGlyphChangeObservers) {
         mGlyphChangeObservers->EnumerateEntries(NotifyFontDestroyed, nullptr);
     }
 }
 
+gfxFloat
+gfxFont::GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID)
+{
+    if (ProvidesGlyphWidths()) {
+        return GetGlyphWidth(aCtx, aGID) / 65536.0;
+    }
+    if (mFUnitsConvFactor == 0.0f) {
+        GetMetrics();
+    }
+    NS_ASSERTION(mFUnitsConvFactor > 0.0f,
+                 "missing font unit conversion factor");
+    if (!mHarfBuzzShaper) {
+        mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
+    }
+    gfxHarfBuzzShaper* shaper =
+        static_cast<gfxHarfBuzzShaper*>(mHarfBuzzShaper.get());
+    if (!shaper->Initialize() || !SetupCairoFont(aCtx)) {
+        return 0;
+    }
+    return shaper->GetGlyphHAdvance(aCtx, aGID) / 65536.0;
+}
+
 /*static*/
 PLDHashOperator
 gfxFont::AgeCacheEntry(CacheHashEntry *aEntry, void *aUserData)
 {
     if (!aEntry->mShapedWord) {
         NS_ASSERTION(aEntry->mShapedWord, "cache entry has no gfxShapedWord!");
         return PL_DHASH_REMOVE;
     }
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -38,16 +38,18 @@ typedef struct gr_face            gr_fac
 #include <stdio.h>
 #endif
 
 class gfxContext;
 class gfxTextRun;
 class gfxFont;
 class gfxFontFamily;
 class gfxFontGroup;
+class gfxGraphiteShaper;
+class gfxHarfBuzzShaper;
 class gfxUserFontSet;
 class gfxUserFontData;
 class gfxShapedText;
 class gfxShapedWord;
 class gfxSVGGlyphs;
 class gfxMathTable;
 class gfxTextContextPaint;
 class FontInfoData;
@@ -1452,16 +1454,20 @@ public:
 
 protected:
     // the font this shaper is working with
     gfxFont * mFont;
 };
 
 /* a SPECIFIC single font family */
 class gfxFont {
+
+    friend class gfxHarfBuzzShaper;
+    friend class gfxGraphiteShaper;
+
 public:
     nsrefcnt AddRef(void) {
         NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
         if (mExpirationState.IsTracked()) {
             gfxFontCache::GetCache()->RemoveObject(this);
         }
         ++mRefCnt;
         NS_LOG_ADDREF(this, mRefCnt, "gfxFont", sizeof(*this));
@@ -1579,29 +1585,18 @@ public:
     virtual bool ProvidesGetGlyph() const {
         return false;
     }
     // Map unicode character to glyph ID.
     // Only used if ProvidesGetGlyph() returns true.
     virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector) {
         return 0;
     }
-
-    // subclasses may provide (possibly hinted) glyph widths (in font units);
-    // if they do not override this, harfbuzz will use unhinted widths
-    // derived from the font tables
-    virtual bool ProvidesGlyphWidths() {
-        return false;
-    }
-
-    // The return value is interpreted as a horizontal advance in 16.16 fixed
-    // point format.
-    virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) {
-        return -1;
-    }
+    // Return the horizontal advance of a glyph.
+    gfxFloat GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID);
 
     // Return Azure GlyphRenderingOptions for drawing this font.
     virtual mozilla::TemporaryRef<mozilla::gfx::GlyphRenderingOptions>
       GetGlyphRenderingOptions() { return nullptr; }
 
     gfxFloat SynthesizeSpaceWidth(uint32_t aCh);
 
     // Font metrics
@@ -1887,16 +1882,29 @@ public:
     }
 
     static void DestroySingletons() {
         delete sScriptTagToCode;
         delete sDefaultFeatures;
     }
 
 protected:
+    // subclasses may provide (possibly hinted) glyph widths (in font units);
+    // if they do not override this, harfbuzz will use unhinted widths
+    // derived from the font tables
+    virtual bool ProvidesGlyphWidths() {
+        return false;
+    }
+
+    // The return value is interpreted as a horizontal advance in 16.16 fixed
+    // point format.
+    virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) {
+        return -1;
+    }
+
     void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
     void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
 
     // whether font contains substitution lookups containing spaces
     bool HasSubstitutionRulesWithSpaceLookups(int32_t aRunScript);
 
     // do spaces participate in shaping rules? if so, can't used word cache
     bool SpaceMayParticipateInShaping(int32_t aRunScript);
--- a/gfx/thebes/gfxHarfBuzzShaper.cpp
+++ b/gfx/thebes/gfxHarfBuzzShaper.cpp
@@ -183,20 +183,16 @@ struct HMetrics {
 // the variable-length metrics[] array is immediately followed by:
 //  AutoSwap_PRUint16    leftSideBearing[];
 };
 
 hb_position_t
 gfxHarfBuzzShaper::GetGlyphHAdvance(gfxContext *aContext,
                                     hb_codepoint_t glyph) const
 {
-    if (mUseFontGlyphWidths) {
-        return mFont->GetGlyphWidth(aContext, glyph);
-    }
-
     // font did not implement GetHintedGlyphWidth, so get an unhinted value
     // directly from the font tables
 
     NS_ASSERTION((mNumLongMetrics > 0) && mHmtxTable != nullptr,
                  "font is lacking metrics, we shouldn't be here");
 
     if (glyph >= uint32_t(mNumLongMetrics)) {
         glyph = mNumLongMetrics - 1;
@@ -206,23 +202,29 @@ gfxHarfBuzzShaper::GetGlyphHAdvance(gfxC
     // that mNumLongMetrics is > 0, and that the hmtx table is large enough
     // to contain mNumLongMetrics records
     const HMetrics* hmtx =
         reinterpret_cast<const HMetrics*>(hb_blob_get_data(mHmtxTable, nullptr));
     return FloatToFixed(mFont->FUnitsToDevUnitsFactor() *
                         uint16_t(hmtx->metrics[glyph].advanceWidth));
 }
 
-static hb_position_t
-HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
-                   hb_codepoint_t glyph, void *user_data)
+/* static */
+hb_position_t
+gfxHarfBuzzShaper::HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
+                                      hb_codepoint_t glyph, void *user_data)
 {
     const gfxHarfBuzzShaper::FontCallbackData *fcd =
         static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
-    return fcd->mShaper->GetGlyphHAdvance(fcd->mContext, glyph);
+    gfxFont *gfxfont = fcd->mShaper->GetFont();
+    if (gfxfont->ProvidesGlyphWidths()) {
+        return gfxfont->GetGlyphWidth(fcd->mContext, glyph);
+    } else {
+        return fcd->mShaper->GetGlyphHAdvance(fcd->mContext, glyph);
+    }
 }
 
 static hb_bool_t
 HBGetContourPoint(hb_font_t *font, void *font_data,
                   unsigned int point_index, hb_codepoint_t glyph,
                   hb_position_t *x, hb_position_t *y,
                   void *user_data)
 {
@@ -813,143 +815,155 @@ AddOpenTypeFeature(const uint32_t& aTag,
  */
 
 static hb_font_funcs_t * sHBFontFuncs = nullptr;
 static hb_unicode_funcs_t * sHBUnicodeFuncs = nullptr;
 static const hb_script_t sMathScript =
     hb_ot_tag_to_script(HB_TAG('m','a','t','h'));
 
 bool
+gfxHarfBuzzShaper::Initialize()
+{
+    if (mInitialized) {
+        return mHBFont != nullptr;
+    }
+    mInitialized = true;
+    mCallbackData.mShaper = this;
+
+    mUseFontGlyphWidths = mFont->ProvidesGlyphWidths();
+
+    if (!sHBFontFuncs) {
+        // static function callback pointers, initialized by the first
+        // harfbuzz shaper used
+        sHBFontFuncs = hb_font_funcs_create();
+        hb_font_funcs_set_glyph_func(sHBFontFuncs, HBGetGlyph,
+                                     nullptr, nullptr);
+        hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs,
+                                               HBGetGlyphHAdvance,
+                                               nullptr, nullptr);
+        hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs,
+                                                   HBGetContourPoint,
+                                                   nullptr, nullptr);
+        hb_font_funcs_set_glyph_h_kerning_func(sHBFontFuncs,
+                                               HBGetHKerning,
+                                               nullptr, nullptr);
+
+        sHBUnicodeFuncs =
+            hb_unicode_funcs_create(hb_unicode_funcs_get_empty());
+        hb_unicode_funcs_set_mirroring_func(sHBUnicodeFuncs,
+                                            HBGetMirroring,
+                                            nullptr, nullptr);
+        hb_unicode_funcs_set_script_func(sHBUnicodeFuncs, HBGetScript,
+                                         nullptr, nullptr);
+        hb_unicode_funcs_set_general_category_func(sHBUnicodeFuncs,
+                                                   HBGetGeneralCategory,
+                                                   nullptr, nullptr);
+        hb_unicode_funcs_set_combining_class_func(sHBUnicodeFuncs,
+                                                  HBGetCombiningClass,
+                                                  nullptr, nullptr);
+        hb_unicode_funcs_set_eastasian_width_func(sHBUnicodeFuncs,
+                                                  HBGetEastAsianWidth,
+                                                  nullptr, nullptr);
+        hb_unicode_funcs_set_compose_func(sHBUnicodeFuncs,
+                                          HBUnicodeCompose,
+                                          nullptr, nullptr);
+        hb_unicode_funcs_set_decompose_func(sHBUnicodeFuncs,
+                                            HBUnicodeDecompose,
+                                            nullptr, nullptr);
+    }
+
+    gfxFontEntry *entry = mFont->GetFontEntry();
+    if (!mUseFontGetGlyph) {
+        // get the cmap table and find offset to our subtable
+        mCmapTable = entry->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
+        if (!mCmapTable) {
+            NS_WARNING("failed to load cmap, glyphs will be missing");
+            return false;
+        }
+        uint32_t len;
+        const uint8_t* data = (const uint8_t*)hb_blob_get_data(mCmapTable, &len);
+        bool symbol;
+        mCmapFormat = gfxFontUtils::
+            FindPreferredSubtable(data, len,
+                                  &mSubtableOffset, &mUVSTableOffset,
+                                  &symbol);
+        if (mCmapFormat <= 0) {
+            return false;
+        }
+    }
+
+    if (!mUseFontGlyphWidths) {
+        // if font doesn't implement GetGlyphWidth, we will be reading
+        // the hmtx table directly;
+        // read mNumLongMetrics from hhea table without caching its blob,
+        // and preload/cache the hmtx table
+        gfxFontEntry::AutoTable hheaTable(entry, TRUETYPE_TAG('h','h','e','a'));
+        if (hheaTable) {
+            uint32_t len;
+            const HMetricsHeader* hhea =
+                reinterpret_cast<const HMetricsHeader*>
+                (hb_blob_get_data(hheaTable, &len));
+            if (len >= sizeof(HMetricsHeader)) {
+                mNumLongMetrics = hhea->numberOfHMetrics;
+                if (mNumLongMetrics > 0 &&
+                    int16_t(hhea->metricDataFormat) == 0) {
+                    // no point reading hmtx if number of entries is zero!
+                    // in that case, we won't be able to use this font
+                    // (this method will return FALSE below if mHmtx is null)
+                    mHmtxTable =
+                        entry->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
+                    if (hb_blob_get_length(mHmtxTable) <
+                        mNumLongMetrics * sizeof(HLongMetric)) {
+                        // hmtx table is not large enough for the claimed
+                        // number of entries: invalid, do not use.
+                        hb_blob_destroy(mHmtxTable);
+                        mHmtxTable = nullptr;
+                    }
+                }
+            }
+        }
+        if (!mHmtxTable) {
+            return false;
+        }
+    }
+
+    mHBFont = hb_font_create(mHBFace);
+    hb_font_set_funcs(mHBFont, sHBFontFuncs, &mCallbackData, nullptr);
+    hb_font_set_ppem(mHBFont, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
+    uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
+    hb_font_set_scale(mHBFont, scale, scale);
+
+    return true;
+}
+
+bool
 gfxHarfBuzzShaper::ShapeText(gfxContext      *aContext,
                              const char16_t *aText,
                              uint32_t         aOffset,
                              uint32_t         aLength,
                              int32_t          aScript,
                              gfxShapedText   *aShapedText)
 {
     // some font back-ends require this in order to get proper hinted metrics
     if (!mFont->SetupCairoFont(aContext)) {
         return false;
     }
 
     mCallbackData.mContext = aContext;
-    gfxFontEntry *entry = mFont->GetFontEntry();
 
-    if (!mInitialized) {
-        mInitialized = true;
-        mCallbackData.mShaper = this;
-
-        mUseFontGlyphWidths = mFont->ProvidesGlyphWidths();
-
-        if (!sHBFontFuncs) {
-            // static function callback pointers, initialized by the first
-            // harfbuzz shaper used
-            sHBFontFuncs = hb_font_funcs_create();
-            hb_font_funcs_set_glyph_func(sHBFontFuncs, HBGetGlyph,
-                                         nullptr, nullptr);
-            hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs,
-                                                   HBGetGlyphHAdvance,
-                                                   nullptr, nullptr);
-            hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs,
-                                                       HBGetContourPoint,
-                                                       nullptr, nullptr);
-            hb_font_funcs_set_glyph_h_kerning_func(sHBFontFuncs,
-                                                   HBGetHKerning,
-                                                   nullptr, nullptr);
-
-            sHBUnicodeFuncs =
-                hb_unicode_funcs_create(hb_unicode_funcs_get_empty());
-            hb_unicode_funcs_set_mirroring_func(sHBUnicodeFuncs,
-                                                HBGetMirroring,
-                                                nullptr, nullptr);
-            hb_unicode_funcs_set_script_func(sHBUnicodeFuncs, HBGetScript,
-                                             nullptr, nullptr);
-            hb_unicode_funcs_set_general_category_func(sHBUnicodeFuncs,
-                                                       HBGetGeneralCategory,
-                                                       nullptr, nullptr);
-            hb_unicode_funcs_set_combining_class_func(sHBUnicodeFuncs,
-                                                      HBGetCombiningClass,
-                                                      nullptr, nullptr);
-            hb_unicode_funcs_set_eastasian_width_func(sHBUnicodeFuncs,
-                                                      HBGetEastAsianWidth,
-                                                      nullptr, nullptr);
-            hb_unicode_funcs_set_compose_func(sHBUnicodeFuncs,
-                                              HBUnicodeCompose,
-                                              nullptr, nullptr);
-            hb_unicode_funcs_set_decompose_func(sHBUnicodeFuncs,
-                                                HBUnicodeDecompose,
-                                                nullptr, nullptr);
-        }
-
-        if (!mUseFontGetGlyph) {
-            // get the cmap table and find offset to our subtable
-            mCmapTable = entry->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
-            if (!mCmapTable) {
-                NS_WARNING("failed to load cmap, glyphs will be missing");
-                return false;
-            }
-            uint32_t len;
-            const uint8_t* data = (const uint8_t*)hb_blob_get_data(mCmapTable, &len);
-            bool symbol;
-            mCmapFormat = gfxFontUtils::
-                FindPreferredSubtable(data, len,
-                                      &mSubtableOffset, &mUVSTableOffset,
-                                      &symbol);
-        }
-
-        if (!mUseFontGlyphWidths) {
-            // if font doesn't implement GetGlyphWidth, we will be reading
-            // the hmtx table directly;
-            // read mNumLongMetrics from hhea table without caching its blob,
-            // and preload/cache the hmtx table
-            gfxFontEntry::AutoTable hheaTable(entry, TRUETYPE_TAG('h','h','e','a'));
-            if (hheaTable) {
-                uint32_t len;
-                const HMetricsHeader* hhea =
-                    reinterpret_cast<const HMetricsHeader*>
-                        (hb_blob_get_data(hheaTable, &len));
-                if (len >= sizeof(HMetricsHeader)) {
-                    mNumLongMetrics = hhea->numberOfHMetrics;
-                    if (mNumLongMetrics > 0 &&
-                        int16_t(hhea->metricDataFormat) == 0) {
-                        // no point reading hmtx if number of entries is zero!
-                        // in that case, we won't be able to use this font
-                        // (this method will return FALSE below if mHmtx is null)
-                        mHmtxTable =
-                            entry->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
-                        if (hb_blob_get_length(mHmtxTable) <
-                            mNumLongMetrics * sizeof(HLongMetric)) {
-                            // hmtx table is not large enough for the claimed
-                            // number of entries: invalid, do not use.
-                            hb_blob_destroy(mHmtxTable);
-                            mHmtxTable = nullptr;
-                        }
-                    }
-                }
-            }
-        }
-
-        mHBFont = hb_font_create(mHBFace);
-        hb_font_set_funcs(mHBFont, sHBFontFuncs, &mCallbackData, nullptr);
-        hb_font_set_ppem(mHBFont, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
-        uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
-        hb_font_set_scale(mHBFont, scale, scale);
-    }
-
-    if ((!mUseFontGetGlyph && mCmapFormat <= 0) ||
-        (!mUseFontGlyphWidths && !mHmtxTable)) {
-        // unable to shape with this font
+    if (!Initialize()) {
         return false;
     }
 
     const gfxFontStyle *style = mFont->GetStyle();
 
     nsAutoTArray<hb_feature_t,20> features;
     nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
 
+    gfxFontEntry *entry = mFont->GetFontEntry();
     if (MergeFontFeatures(style,
                           entry->mFeatureSettings,
                           aShapedText->DisableLigatures(),
                           entry->FamilyName(),
                           mergedFeatures))
     {
         // enumerate result and insert into hb_feature array
         mergedFeatures.Enumerate(AddOpenTypeFeature, &features);
--- a/gfx/thebes/gfxHarfBuzzShaper.h
+++ b/gfx/thebes/gfxHarfBuzzShaper.h
@@ -19,16 +19,17 @@ public:
      * For HarfBuzz font callback functions, font_data is a ptr to a
      * FontCallbackData struct
      */
     struct FontCallbackData {
         gfxHarfBuzzShaper *mShaper;
         gfxContext        *mContext;
     };
 
+    bool Initialize();
     virtual bool ShapeText(gfxContext      *aContext,
                            const char16_t *aText,
                            uint32_t         aOffset,
                            uint32_t         aLength,
                            int32_t          aScript,
                            gfxShapedText   *aShapedText);
 
     // get a given font table in harfbuzz blob form
@@ -37,16 +38,21 @@ public:
     // map unicode character to glyph ID
     hb_codepoint_t GetGlyph(hb_codepoint_t unicode,
                             hb_codepoint_t variation_selector) const;
 
     // get harfbuzz glyph advance, in font design units
     hb_position_t GetGlyphHAdvance(gfxContext *aContext,
                                    hb_codepoint_t glyph) const;
 
+    // get harfbuzz horizontal advance in 16.16 fixed point format.
+    static hb_position_t
+    HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
+                       hb_codepoint_t glyph, void *user_data);
+
     hb_position_t GetHKerning(uint16_t aFirstGlyph,
                               uint16_t aSecondGlyph) const;
 
 protected:
     nsresult SetGlyphsFromRun(gfxContext      *aContext,
                               gfxShapedText   *aShapedText,
                               uint32_t         aOffset,
                               uint32_t         aLength,
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -1619,20 +1619,17 @@ gfxFcFont::ShapeText(gfxContext      *aC
             }
             ok = mGraphiteShaper->ShapeText(aContext, aText, aOffset, aLength,
                                             aScript, aShapedText);
         }
     }
 
     if (!ok) {
         if (!mHarfBuzzShaper) {
-            gfxFT2LockedFace face(this);
             mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
-            // Used by gfxHarfBuzzShaper, currently only for kerning
-            mFUnitsConvFactor = face.XScale();
         }
         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);
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -537,19 +537,20 @@ nsOpenTypeTable::MakeTextRun(gfxContext*
   gfxTextRunFactory::Parameters params = {
     aThebesContext, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel
   };
   gfxTextRun* textRun = gfxTextRun::Create(&params, 1, aFontGroup, 0);
   textRun->AddGlyphRun(aFontGroup->GetFontAt(0), gfxTextRange::kFontGroup, 0,
                        false);
   gfxTextRun::DetailedGlyph detailedGlyph;
   detailedGlyph.mGlyphID = aGlyph.glyphID;
-  // We set the advance width to zero and this will be fixed in MeasureTextRun.
-  // XXXfredw: We should use gfxHarfbuzzShaper::GetGlyphHAdvance()
-  detailedGlyph.mAdvance = 0;
+  detailedGlyph.mAdvance =
+    NSToCoordRound(aAppUnitsPerDevPixel *
+                   aFontGroup->GetFontAt(0)->
+                   GetGlyphHAdvance(aThebesContext, aGlyph.glyphID));
   detailedGlyph.mXOffset = detailedGlyph.mYOffset = 0;
   gfxShapedText::CompressedGlyph g;
   g.SetComplex(true, true, 1);
   textRun->SetGlyphs(0, g, &detailedGlyph);
 
   return textRun;
 }
 
@@ -1148,21 +1149,16 @@ MeasureTextRun(gfxContext* aThebesContex
                           aThebesContext, nullptr);
 
   nsBoundingMetrics bm;
   bm.leftBearing = NSToCoordFloor(metrics.mBoundingBox.X());
   bm.rightBearing = NSToCoordCeil(metrics.mBoundingBox.XMost());
   bm.ascent = NSToCoordCeil(-metrics.mBoundingBox.Y());
   bm.descent = NSToCoordCeil(metrics.mBoundingBox.YMost());
   bm.width = NSToCoordRound(metrics.mAdvanceWidth);
-  if (bm.width == 0) {
-    // The advance width was not set in nsGlyphTable::MakeTextRun, so we use
-    // the right bearing instead.
-    bm.width = bm.rightBearing;
-  }
 
   return bm;
 }
 
 class nsMathMLChar::StretchEnumContext {
 public:
   StretchEnumContext(nsMathMLChar*        aChar,
                      nsPresContext*       aPresContext,
@@ -1297,20 +1293,22 @@ StretchEnumContext::TryVariants(nsGlyphT
 
     nsAutoPtr<gfxTextRun> textRun;
     textRun = aGlyphTable->MakeTextRun(mThebesContext, oneDevPixel,
                                        *aFontGroup, ch);
     nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun);
     if (ch.IsGlyphID()) {
       gfxFont* mathFont = aFontGroup->get()->GetFontAt(0);
       if (mathFont->GetFontEntry()->TryGetMathTable(mathFont)) {
-        // MeasureTextRun has set the advance width to the right bearing. We now
-        // subtract the italic correction, so that nsMathMLmmultiscripts will
-        // place the scripts correctly.
-        // Note that STIX-Word does not provide italic corrections
+        // 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
+        // advance widths do not match right bearings.
         // (http://sourceforge.net/p/stixfonts/tracking/50/)
         gfxFloat italicCorrection;
         if (mathFont->GetFontEntry()->
             GetMathItalicsCorrection(ch.glyphID, &italicCorrection)) {
           bm.width -=
             NSToCoordRound(italicCorrection *
                            mathFont->GetAdjustedSize() * oneDevPixel);
           if (bm.width < 0) {