Bug 1279962 - Fall back to getting the CGFontRef from NSFont to support hidden system fonts on 10.12. r=jfkthame
authorMarkus Stange <mstange@themasta.com>
Mon, 04 Jul 2016 15:13:34 -0400
changeset 331034 faf57f9dbeee9b688489b44b1a43af60591de815
parent 331033 440f999f965f4578e23a602b6cddfdf2ce0812ff
child 331035 77fea9f0a2a7c57d7c63f78af8f6af3bfcf8525e
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1279962
milestone50.0a1
Bug 1279962 - Fall back to getting the CGFontRef from NSFont to support hidden system fonts on 10.12. r=jfkthame MozReview-Commit-ID: pp9WC3twsl
gfx/thebes/gfxMacPlatformFontList.h
gfx/thebes/gfxMacPlatformFontList.mm
--- a/gfx/thebes/gfxMacPlatformFontList.h
+++ b/gfx/thebes/gfxMacPlatformFontList.h
@@ -24,17 +24,18 @@ class gfxMacPlatformFontList;
 
 // a single member of a font family (i.e. a single face, such as Times Italic)
 class MacOSFontEntry : public gfxFontEntry
 {
 public:
     friend class gfxMacPlatformFontList;
 
     MacOSFontEntry(const nsAString& aPostscriptName, int32_t aWeight,
-                   bool aIsStandardFace = false);
+                   bool aIsStandardFace = false,
+                   double aSizeHint = 0.0);
 
     // for use with data fonts
     MacOSFontEntry(const nsAString& aPostscriptName, CGFontRef aFontRef,
                    uint16_t aWeight, uint16_t aStretch, uint8_t aStyle,
                    bool aIsDataUserFont, bool aIsLocal);
 
     virtual ~MacOSFontEntry() {
         ::CGFontRelease(mFontRef);
@@ -59,16 +60,18 @@ protected:
     virtual gfxFont* CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) override;
 
     virtual bool HasFontTable(uint32_t aTableTag) override;
 
     static void DestroyBlobFunc(void* aUserData);
 
     CGFontRef mFontRef; // owning reference to the CGFont, released on destruction
 
+    double mSizeHint;
+
     bool mFontRefInitialized;
     bool mRequiresAAT;
     bool mIsCFF;
     bool mIsCFFInitialized;
     nsTHashtable<nsUint32HashKey> mAvailableTables;
 };
 
 class gfxMacPlatformFontList : public gfxPlatformFontList {
@@ -115,17 +118,17 @@ private:
 
     // initialize font lists
     nsresult InitFontList() override;
 
     // special case font faces treated as font families (set via prefs)
     void InitSingleFaceList();
 
     // initialize system fonts
-    void InitSystemFonts();
+    void InitSystemFontNames();
 
     // helper function to lookup in both hidden system fonts and normal fonts
     gfxFontFamily* FindSystemFontFamily(const nsAString& aFamily);
 
     static void RegisteredFontsChangedNotificationCallback(CFNotificationCenterRef center,
                                                            void *observer,
                                                            CFStringRef name,
                                                            const void *object,
@@ -164,13 +167,13 @@ private:
     // for different locales (e.g. .Helvetica Neue UI, .SF NS Text)
     FontFamilyTable mSystemFontFamilies;
 
     // font families that -apple-system maps to
     // Pre-10.11 this was always a single font family, such as Lucida Grande
     // or Helvetica Neue. For OSX 10.11, Apple uses pair of families
     // for the UI, one for text sizes and another for display sizes
     bool mUseSizeSensitiveSystemFont;
-    RefPtr<gfxFontFamily> mSystemTextFontFamily;
-    RefPtr<gfxFontFamily> mSystemDisplayFontFamily; // only used on OSX 10.11
+    nsString mSystemTextFontFamilyName;
+    nsString mSystemDisplayFontFamilyName; // only used on OSX 10.11
 };
 
 #endif /* gfxMacPlatformFontList_H_ */
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -250,35 +250,38 @@ MacOSFontEntry::IsCFF()
         mIsCFF = HasFontTable(TRUETYPE_TAG('C','F','F',' '));
     }
 
     return mIsCFF;
 }
 
 MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
                                int32_t aWeight,
-                               bool aIsStandardFace)
+                               bool aIsStandardFace,
+                               double aSizeHint)
     : gfxFontEntry(aPostscriptName, aIsStandardFace),
       mFontRef(NULL),
+      mSizeHint(aSizeHint),
       mFontRefInitialized(false),
       mRequiresAAT(false),
       mIsCFF(false),
       mIsCFFInitialized(false)
 {
     mWeight = aWeight;
 }
 
 MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
                                CGFontRef aFontRef,
                                uint16_t aWeight, uint16_t aStretch,
                                uint8_t aStyle,
                                bool aIsDataUserFont,
                                bool aIsLocalUserFont)
     : gfxFontEntry(aPostscriptName, false),
       mFontRef(NULL),
+      mSizeHint(0.0),
       mFontRefInitialized(false),
       mRequiresAAT(false),
       mIsCFF(false),
       mIsCFFInitialized(false)
 {
     mFontRef = aFontRef;
     mFontRefInitialized = true;
     ::CFRetain(mFontRef);
@@ -296,16 +299,29 @@ MacOSFontEntry::MacOSFontEntry(const nsA
 
 CGFontRef
 MacOSFontEntry::GetFontRef()
 {
     if (!mFontRefInitialized) {
         mFontRefInitialized = true;
         NSString *psname = GetNSStringForString(mName);
         mFontRef = ::CGFontCreateWithFontName(CFStringRef(psname));
+        if (!mFontRef) {
+            // This happens on macOS 10.12 for font entry names that start with
+            // .AppleSystemUIFont. For those fonts, we need to go through NSFont
+            // to get the correct CGFontRef.
+            // Both the Text and the Display variant of the display font use
+            // .AppleSystemUIFontSomethingSomething as their member names.
+            // That's why we're carrying along mSizeHint to this place so that
+            // we get the variant that we want for this family.
+            NSFont* font = [NSFont fontWithName:psname size:mSizeHint];
+            if (font) {
+                mFontRef = CTFontCopyGraphicsFont((CTFontRef)font, nullptr);
+            }
+        }
     }
     return mFontRef;
 }
 
 // For a logging build, we wrap the CFDataRef in a FontTableRec so that we can
 // use the MOZ_COUNT_[CD]TOR macros in it. A release build without logging
 // does not get this overhead.
 class FontTableRec {
@@ -394,25 +410,29 @@ MacOSFontEntry::AddSizeOfIncludingThis(M
 }
 
 /* gfxMacFontFamily */
 #pragma mark-
 
 class gfxMacFontFamily : public gfxFontFamily
 {
 public:
-    explicit gfxMacFontFamily(nsAString& aName) :
-        gfxFontFamily(aName)
+    explicit gfxMacFontFamily(nsAString& aName, double aSizeHint) :
+        gfxFontFamily(aName),
+        mSizeHint(aSizeHint)
     {}
 
     virtual ~gfxMacFontFamily() {}
 
     virtual void LocalizedName(nsAString& aLocalizedName);
 
     virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr);
+
+protected:
+    double mSizeHint;
 };
 
 void
 gfxMacFontFamily::LocalizedName(nsAString& aLocalizedName)
 {
     nsAutoreleasePool localPool;
 
     if (!HasOtherFamilyNames()) {
@@ -502,17 +522,17 @@ gfxMacFontFamily::FindStyleVariations(Fo
             [facename isEqualToString:@"Bold Italic"] ||
             [facename isEqualToString:@"Bold Oblique"])
         {
             isStandardFace = true;
         }
 
         // create a font entry
         MacOSFontEntry *fontEntry =
-            new MacOSFontEntry(postscriptFontName, cssWeight, isStandardFace);
+            new MacOSFontEntry(postscriptFontName, cssWeight, isStandardFace, mSizeHint);
         if (!fontEntry) {
             break;
         }
 
         // set additional properties based on the traits reported by Cocoa
         if (macTraits & (NSCondensedFontMask | NSNarrowFontMask | NSCompressedFontMask)) {
             fontEntry->mStretch = NS_FONT_STRETCH_CONDENSED;
         } else if (macTraits & NSExpandedFontMask) {
@@ -668,20 +688,26 @@ gfxMacPlatformFontList::AddFamily(CFStri
     bool hiddenSystemFont = [family hasPrefix:@"."];
 
     FontFamilyTable& table =
         hiddenSystemFont ? mSystemFontFamilies : mFontFamilies;
 
     nsAutoString familyName;
     nsCocoaUtils::GetStringForNSString(family, familyName);
 
+    double sizeHint = 0.0;
+    if (hiddenSystemFont && mUseSizeSensitiveSystemFont &&
+        mSystemDisplayFontFamilyName.Equals(familyName)) {
+        sizeHint = 128.0;
+    }
+
     nsAutoString key;
     ToLowerCase(familyName, key);
 
-    gfxFontFamily* familyEntry = new gfxMacFontFamily(familyName);
+    gfxFontFamily* familyEntry = new gfxMacFontFamily(familyName, sizeHint);
     table.Put(key, familyEntry);
 
     // check the bad underline blacklist
     if (mBadUnderlineFamilyNames.Contains(key)) {
         familyEntry->SetBadUnderlineFamily();
     }
 }
 
@@ -693,28 +719,28 @@ gfxMacPlatformFontList::InitFontList()
     Telemetry::AutoTimer<Telemetry::MAC_INITFONTLIST_TOTAL> timer;
 
     // reset font lists
     gfxPlatformFontList::InitFontList();
     mSystemFontFamilies.Clear();
     
     // iterate over available families
 
+    InitSystemFontNames();
+
     CFArrayRef familyNames = CTFontManagerCopyAvailableFontFamilyNames();
 
     for (NSString* familyName in (NSArray*)familyNames) {
         AddFamily((CFStringRef)familyName);
     }
 
     CFRelease(familyNames);
 
     InitSingleFaceList();
 
-    InitSystemFonts();
-
     // to avoid full search of font name tables, seed the other names table with localized names from
     // some of the prefs fonts which are accessed via their localized names.  changes in the pref fonts will only cause
     // a font lookup miss earlier. this is a simple optimization, it's not required for correctness
     PreloadNamesList();
 
     // start the delayed cmap loader
     GetPrefsAndStartLoader();
 
@@ -787,43 +813,40 @@ static NSString* GetRealFamilyName(NSFon
 // for text sizes and another for larger, display sizes. Each has a
 // different number of weights. There aren't efficient API's for looking
 // this information up, so hard code the logic here but confirm via
 // debug assertions that the logic is correct.
 
 const CGFloat kTextDisplayCrossover = 20.0; // use text family below this size
 
 void
-gfxMacPlatformFontList::InitSystemFonts()
+gfxMacPlatformFontList::InitSystemFontNames()
 {
     // system font under 10.11 are two distinct families for text/display sizes
     if (nsCocoaFeatures::OnElCapitanOrLater()) {
         mUseSizeSensitiveSystemFont = true;
     }
 
     // text font family
     NSFont* sys = [NSFont systemFontOfSize: 0.0];
     NSString* textFamilyName = GetRealFamilyName(sys);
     nsAutoString familyName;
     nsCocoaUtils::GetStringForNSString(textFamilyName, familyName);
-    mSystemTextFontFamily = FindSystemFontFamily(familyName);
-    NS_ASSERTION(mSystemTextFontFamily, "null system display font family");
+    mSystemTextFontFamilyName = familyName;
 
     // display font family, if on OSX 10.11
     if (mUseSizeSensitiveSystemFont) {
         NSFont* displaySys = [NSFont systemFontOfSize: 128.0];
         NSString* displayFamilyName = GetRealFamilyName(displaySys);
         nsCocoaUtils::GetStringForNSString(displayFamilyName, familyName);
-        mSystemDisplayFontFamily = FindSystemFontFamily(familyName);
-        NS_ASSERTION(mSystemDisplayFontFamily, "null system display font family");
+        mSystemDisplayFontFamilyName = familyName;
 
 #if DEBUG
         // confirm that the optical size switch is at 20.0
-        NS_ASSERTION(mSystemTextFontFamily && mSystemDisplayFontFamily &&
-                     [textFamilyName compare:displayFamilyName] != NSOrderedSame,
+        NS_ASSERTION([textFamilyName compare:displayFamilyName] != NSOrderedSame,
                      "system text/display fonts are the same!");
         NSString* fam19 = GetRealFamilyName([NSFont systemFontOfSize:
                                              (kTextDisplayCrossover - 1.0)]);
         NSString* fam20 = GetRealFamilyName([NSFont systemFontOfSize:
                                              kTextDisplayCrossover]);
         NS_ASSERTION(fam19 && fam20 && [fam19 compare:fam20] != NSOrderedSame,
                      "system text/display font size switch point is not as expected!");
 #endif
@@ -1105,20 +1128,20 @@ gfxMacPlatformFontList::FindAndAddFamili
                                            nsTArray<gfxFontFamily*>* aOutput,
                                            gfxFontStyle* aStyle,
                                            gfxFloat aDevToCssSize)
 {
     // search for special system font name, -apple-system
     if (aFamily.EqualsLiteral(kSystemFont_system)) {
         if (mUseSizeSensitiveSystemFont &&
             aStyle && (aStyle->size * aDevToCssSize) >= kTextDisplayCrossover) {
-            aOutput->AppendElement(mSystemDisplayFontFamily);
+            aOutput->AppendElement(FindSystemFontFamily(mSystemDisplayFontFamilyName));
             return true;
         }
-        aOutput->AppendElement(mSystemTextFontFamily);
+        aOutput->AppendElement(FindSystemFontFamily(mSystemTextFontFamilyName));
         return true;
     }
 
     return gfxPlatformFontList::FindAndAddFamilies(aFamily, aOutput, aStyle,
                                                    aDevToCssSize);
 }
 
 void