Bug 1315752 - Avoid using LookupLocalFont to find the Osaka-Mono face in InitSingleFaceList, so we don't risk triggering a font-download prompt. r=mstange a=gchang
authorJonathan Kew <jkew@mozilla.com>
Mon, 13 Feb 2017 21:47:16 +0000
changeset 378580 6e46b6455cae726e8a791f5b321a9ce262916feb
parent 378579 92cff1713ab8c4f6b8483b5d2e7a186ce4e9ddc0
child 378581 a4dd9746a71219c06fb2b178c4938d90f1ac4317
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, gchang
bugs1315752
milestone53.0a2
Bug 1315752 - Avoid using LookupLocalFont to find the Osaka-Mono face in InitSingleFaceList, so we don't risk triggering a font-download prompt. r=mstange a=gchang The issue is that with Osaka becoming a downloadable asset rather than a universally pre-installed font, it's possible for a user's system to be in a state where the Osaka-Regular face is present (and therefore the Osaka family shows up in the main font family list), but Osaka-Mono has still not been downloaded. Until recently, I wasn't aware that the family could be in that partially-installed state, but apparently it does happen (perhaps depending on how the download was originally triggered). The download prompt then occurs when we use LookupLocalFont() to find the Osaka-Mono face, because that calls CGFontCreateWithFontName, which is aware of the downloadable font assets; so when it is asked for Osaka-Mono, and sees that it hasn't been downloaded, it offers to help out. We tried to avoid this by checking for the presence of the Osaka family before calling LookupLocalFont(), and that solved things for most users (where the Osaka family was either fully installed or not installed at all), but it fails in the case where the Regular face is present but Mono isn't. So this patch works around that by avoiding LookupLocalFont (and therefore CGFontCreateWithFontName) altogether, and instead searching the faces actually present in the main Osaka family. If Osaka-Mono is installed, it will be found there and we can then duplicate its font entry and create the separate Osaka-Mono family; and if not, we safely (and silently) ignore it.
gfx/thebes/gfxMacPlatformFontList.mm
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -824,53 +824,80 @@ gfxMacPlatformFontList::InitFontListForP
 }
 
 void
 gfxMacPlatformFontList::InitSingleFaceList()
 {
     AutoTArray<nsString, 10> singleFaceFonts;
     gfxFontUtils::GetPrefsFontList("font.single-face-list", singleFaceFonts);
 
-    uint32_t numFonts = singleFaceFonts.Length();
-    for (uint32_t i = 0; i < numFonts; i++) {
+    for (const auto& singleFaceFamily : singleFaceFonts) {
         LOG_FONTLIST(("(fontlist-singleface) face name: %s\n",
-                      NS_ConvertUTF16toUTF8(singleFaceFonts[i]).get()));
-        nsAutoString familyName(singleFaceFonts[i]);
+                      NS_ConvertUTF16toUTF8(singleFaceFamily).get()));
+        // Each entry in the "single face families" list is expected to be a
+        // colon-separated pair of FaceName:Family,
+        // where FaceName is the individual face name (psname) of a font
+        // that should be exposed as a separate family name,
+        // and Family is the standard family to which that face belongs.
+        // The only such face listed by default is
+        //    Osaka-Mono:Osaka
+        nsAutoString familyName(singleFaceFamily);
         auto colon = familyName.FindChar(':');
-        if (colon != kNotFound) {
-            nsAutoString key(Substring(familyName, colon + 1));
-            ToLowerCase(key);
-            if (!mFontFamilies.GetWeak(key)) {
-                continue;
-            }
-            familyName.Truncate(colon);
+        if (colon == kNotFound) {
+            continue;
+        }
+
+        // Look for the parent family in the main font family list,
+        // and ensure we have loaded its list of available faces.
+        nsAutoString key(Substring(familyName, colon + 1));
+        ToLowerCase(key);
+        gfxFontFamily* family = mFontFamilies.GetWeak(key);
+        if (!family) {
+            continue;
         }
-        gfxFontEntry *fontEntry = LookupLocalFont(familyName,
-                                                  400, 0,
-                                                  NS_FONT_STYLE_NORMAL);
-        if (fontEntry) {
-            nsAutoString key;
-            GenerateFontListKey(familyName, key);
-            LOG_FONTLIST(("(fontlist-singleface) family name: %s, key: %s\n",
+        family->FindStyleVariations();
+
+        // Truncate the entry from prefs at the colon, so now it is just the
+        // desired single-face-family name.
+        familyName.Truncate(colon);
+
+        // Look through the family's faces to see if this one is present.
+        const gfxFontEntry* fe = nullptr;
+        for (const auto& face : family->GetFontList()) {
+            if (face->Name().Equals(familyName)) {
+                fe = face;
+                break;
+            }
+        }
+        if (!fe) {
+            continue;
+        }
+
+        // We found the correct face, so create the single-face family record.
+        GenerateFontListKey(familyName, key);
+        LOG_FONTLIST(("(fontlist-singleface) family name: %s, key: %s\n",
+                      NS_ConvertUTF16toUTF8(familyName).get(),
+                      NS_ConvertUTF16toUTF8(key).get()));
+
+        // add only if doesn't exist already
+        if (!mFontFamilies.GetWeak(key)) {
+            RefPtr<gfxFontFamily> familyEntry =
+                new gfxSingleFaceMacFontFamily(familyName);
+            // We need a separate font entry, because its family name will
+            // differ from the one we found in the main list.
+            MacOSFontEntry* fontEntry =
+                new MacOSFontEntry(fe->Name(), fe->mWeight, true,
+                                   static_cast<const MacOSFontEntry*>(fe)->
+                                       mSizeHint);
+            familyEntry->AddFontEntry(fontEntry);
+            familyEntry->SetHasStyles(true);
+            mFontFamilies.Put(key, familyEntry);
+            LOG_FONTLIST(("(fontlist-singleface) added new family\n",
                           NS_ConvertUTF16toUTF8(familyName).get(),
                           NS_ConvertUTF16toUTF8(key).get()));
-
-            // add only if doesn't exist already
-            if (!mFontFamilies.GetWeak(key)) {
-                RefPtr<gfxFontFamily> familyEntry =
-                    new gfxSingleFaceMacFontFamily(familyName);
-                // LookupLocalFont sets this, need to clear
-                fontEntry->mIsLocalUserFont = false;
-                familyEntry->AddFontEntry(fontEntry);
-                familyEntry->SetHasStyles(true);
-                mFontFamilies.Put(key, familyEntry);
-                LOG_FONTLIST(("(fontlist-singleface) added new family\n",
-                              NS_ConvertUTF16toUTF8(familyName).get(),
-                              NS_ConvertUTF16toUTF8(key).get()));
-            }
         }
     }
 }
 
 // System fonts under OSX may contain weird "meta" names but if we create
 // a new font using just the Postscript name, the NSFont api returns an object
 // with the actual real family name. For example, under OSX 10.11:
 //