Bug 1427641 - patch 7 - Work around buggy FreeType metrics APIs when using variation fonts with FT versions prior to 2.8.2. r=lsalzman
authorJonathan Kew <jkew@mozilla.com>
Tue, 02 Jan 2018 13:29:48 +0000
changeset 449889 944248bbe7adaaf6eea61d22d163309fd99057a7
parent 449888 89faa23196eaf6bef55e712663bb0f01f8247f18
child 449890 a85c5795cc6f0db71e13288e849ef47b2f225270
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1427641
milestone59.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 1427641 - patch 7 - Work around buggy FreeType metrics APIs when using variation fonts with FT versions prior to 2.8.2. r=lsalzman
gfx/thebes/gfxFT2FontBase.cpp
--- a/gfx/thebes/gfxFT2FontBase.cpp
+++ b/gfx/thebes/gfxFT2FontBase.cpp
@@ -499,23 +499,42 @@ gfxFT2FontBase::GetGlyphWidth(DrawTarget
     }
 
     int32_t width;
     if (mGlyphWidths->Get(aGID, &width)) {
         return width;
     }
 
     gfxFT2LockedFace face(this);
-    int32_t flags = gfxPlatform::GetPlatform()->FontHintingEnabled()
-                    ? FT_LOAD_DEFAULT
-                    : FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
+    int32_t flags =
+        gfxPlatform::GetPlatform()->FontHintingEnabled()
+            ? FT_LOAD_ADVANCE_ONLY
+            : FT_LOAD_ADVANCE_ONLY | FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
     FT_Fixed advance = 0;
-    mozilla::DebugOnly<FT_Error> ftError =
-        FT_Get_Advance(face.get(), aGID, flags, &advance);
-    MOZ_ASSERT(!ftError);
+    // FT_Get_Advance is not reliable with variations until FreeType 2.8.2,
+    // so fall back to calling FT_Load_Glyph and reading the glyph slot's
+    // linearHoriAdvance.
+    // See https://savannah.nongnu.org/bugs/index.php?52683.
+    static uint32_t sFTVersion = 0;
+    if (!sFTVersion) {
+        FT_Int major, minor, patch;
+        FT_Library_Version(face.get()->glyph->library, &major, &minor, &patch);
+        sFTVersion = (major << 16) | (minor << 8) | patch;
+    }
+    if (sFTVersion < 0x020802 &&
+        (face.get()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
+        mozilla::DebugOnly<FT_Error> ftError =
+            FT_Load_Glyph(face.get(), aGID, flags);
+        MOZ_ASSERT(!ftError);
+        advance = face.get()->glyph->linearHoriAdvance;
+    } else {
+        mozilla::DebugOnly<FT_Error> ftError =
+            FT_Get_Advance(face.get(), aGID, flags, &advance);
+        MOZ_ASSERT(!ftError);
+    }
 
     // If freetype emboldening is being used, and it's not a zero-width glyph,
     // adjust the advance to account for the increased width.
     if (mEmbolden && advance > 0) {
         // This is the embolden "strength" used by FT_GlyphSlot_Embolden,
         // converted from 26.6 to 16.16
         FT_Fixed strength = 1024 *
             FT_MulFix(face.get()->units_per_EM,