]> code.delx.au - gnu-emacs/blobdiff - src/macfont.m
Rework C source files to avoid ^(
[gnu-emacs] / src / macfont.m
index cbf1b07bc94370c8db11b9b40f0487f430a3ca9e..c9082a58415cb58392c7029fdc8b301eebb0b95f 100644 (file)
@@ -1,12 +1,12 @@
 /* Font driver on Mac OSX Core text.
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -40,29 +40,21 @@ Original author: YAMAMOTO Mitsuharu
 
 static struct font_driver macfont_driver;
 
-static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
-static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
-static CFArrayRef mac_ctfont_create_available_families (void);
-static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
-static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
-                                                              CTFontRef);
-static CFComparisonResult mac_font_family_compare (const void *,
-                                                   const void *, void *);
-static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
-                                                         CFArrayRef);
-static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
-static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
-                                 struct mac_glyph_layout *, CFIndex);
-static CFArrayRef
-mac_font_copy_default_descriptors_for_language (CFStringRef language);
-
-static CFStringRef
-mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
-                                                      CFArrayRef languages);
-
+static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
+static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
+static CFArrayRef mac_font_create_available_families (void);
+static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
+static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
+                                                           CTFontRef);
+static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
+                                                      CFArrayRef);
+static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
+static CFIndex mac_font_shape (CTFontRef, CFStringRef,
+                              struct mac_glyph_layout *, CFIndex);
+static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
+static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
 #if USE_CT_GLYPH_INFO
-static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
-                                             CTCharacterCollection,
+static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
                                              CGFontIndex);
 #endif
 
@@ -73,7 +65,7 @@ struct macfont_metrics;
 struct macfont_info
 {
   struct font font;
-  FontRef macfont;
+  CTFontRef macfont;
   CGFontRef cgfont;
   ScreenFontRef screen_font;
   struct macfont_cache *cache;
@@ -112,23 +104,22 @@ static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
 static const CGFloat synthetic_bold_factor = 0.024;
 
 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
-                                                        FontSymbolicTraits *);
-static void macfont_store_descriptor_attributes (FontDescriptorRef,
+                                                        CTFontSymbolicTraits *);
+static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
                                                  Lisp_Object);
-static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
-                                              Lisp_Object,
-                                              FontSymbolicTraits);
+static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
+                                              CTFontSymbolicTraits);
 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
 static int macfont_glyph_extents (struct font *, CGGlyph,
                                   struct font_metrics *, CGFloat *, int);
 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
-static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
+static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
                                                          CFCharacterSetRef,
                                                          Lisp_Object,
                                                          CFArrayRef);
-static Boolean macfont_closest_traits_index_p (CFArrayRef, FontSymbolicTraits,
+static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
                                                CFIndex);
-static CFDataRef mac_font_copy_uvs_table (FontRef);
+static CFDataRef mac_font_copy_uvs_table (CTFontRef);
 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
                                               const UTF32Char [],
                                               CGGlyph [], CFIndex);
@@ -199,6 +190,14 @@ cfstring_create_with_string_noencode (Lisp_Object s)
   return string;
 }
 
+static CFIndex
+mac_font_get_weight (CTFontRef font)
+{
+  NSFont *nsFont = (NSFont *) font;
+
+  return [[NSFontManager sharedFontManager] weightOfFont:nsFont];
+}
+
 static CGFloat
 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
 {
@@ -207,57 +206,53 @@ mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
   return advancement.width;
 }
 
+#if !USE_CT_GLYPH_INFO
 static CGGlyph
-mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
+mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
                             CGFontIndex cid)
 {
-#if USE_CT_GLYPH_INFO
-  return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
-#else
-  {
-    CGGlyph result = kCGFontIndexInvalid;
-    NSFont *nsFont = (NSFont *) font;
-    unichar characters[] = {0xfffd};
-    NSString *string =
-      [NSString stringWithCharacters:characters
-                              length:ARRAYELTS (characters)];
-    NSGlyphInfo *glyphInfo =
-      [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
-                                         collection:collection
-                                         baseString:string];
-    NSDictionary *attributes =
-      [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
-                    glyphInfo,NSGlyphInfoAttributeName,nil];
-    NSTextStorage *textStorage =
-      [[NSTextStorage alloc] initWithString:string
-                                 attributes:attributes];
-    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
-    NSTextContainer *textContainer = [[NSTextContainer alloc] init];
-    NSFont *fontInTextStorage;
-
-    [layoutManager addTextContainer:textContainer];
-    [textContainer release];
-    [textStorage addLayoutManager:layoutManager];
-    [layoutManager release];
-
-    /* Force layout.  */
-    (void) [layoutManager glyphRangeForTextContainer:textContainer];
-
-    fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
-                                effectiveRange:NULL];
-    if (fontInTextStorage == nsFont
-        || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
-      {
-        NSGlyph glyph = [layoutManager glyphAtIndex:0];
+  CGGlyph result = kCGFontIndexInvalid;
+  NSFont *nsFont = (NSFont *) font;
+  unichar characters[] = {0xfffd};
+  NSString *string =
+    [NSString stringWithCharacters:characters
+                           length:ARRAYELTS (characters)];
+  NSGlyphInfo *glyphInfo =
+    [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
+                                      collection:collection
+                                      baseString:string];
+  NSDictionary *attributes =
+    [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
+                 glyphInfo,NSGlyphInfoAttributeName,nil];
+  NSTextStorage *textStorage =
+    [[NSTextStorage alloc] initWithString:string
+                              attributes:attributes];
+  NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
+  NSTextContainer *textContainer = [[NSTextContainer alloc] init];
+  NSFont *fontInTextStorage;
 
-        if (glyph < [nsFont numberOfGlyphs])
-          result = glyph;
-      }
+  [layoutManager addTextContainer:textContainer];
+  [textContainer release];
+  [textStorage addLayoutManager:layoutManager];
+  [layoutManager release];
 
-    [textStorage release];
+  /* Force layout.  */
+  (void) [layoutManager glyphRangeForTextContainer:textContainer];
 
-    return result;
-  }
+  fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
+                             effectiveRange:NULL];
+  if (fontInTextStorage == nsFont
+      || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
+    {
+      NSGlyph glyph = [layoutManager glyphAtIndex:0];
+
+      if (glyph < [nsFont numberOfGlyphs])
+       result = glyph;
+    }
+
+  [textStorage release];
+
+  return result;
 }
 #endif
 
@@ -755,7 +750,7 @@ macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
 
 static Boolean
 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
-                                         FontSymbolicTraits *sym_traits)
+                                         CTFontSymbolicTraits *sym_traits)
 {
   SInt64 sint64_value;
 
@@ -763,7 +758,7 @@ cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
      OS X 10.6 when the value is greater than or equal to 1 << 31.  */
   if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
     {
-      *sym_traits = (FontSymbolicTraits) sint64_value;
+      *sym_traits = (CTFontSymbolicTraits) sint64_value;
 
       return true;
     }
@@ -771,8 +766,39 @@ cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
   return false;
 }
 
+static CGFloat
+mac_font_descriptor_get_adjusted_weight (CTFontDescriptorRef desc, CGFloat val)
+{
+  long percent_val = lround (val * 100);
+
+  if (percent_val == -40)
+    {
+      CTFontRef font = NULL;
+      CFStringRef name =
+       CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
+
+      if (name)
+       {
+         font = CTFontCreateWithName (name, 0, NULL);
+         CFRelease (name);
+       }
+      if (font)
+       {
+         CFIndex weight = mac_font_get_weight (font);
+
+         /* Workaround for crash when displaying Oriya characters
+            with Arial Unicode MS on OS X 10.11.  */
+         if (weight == 5)
+           val = 0;
+         CFRelease (font);
+       }
+    }
+
+  return val;
+}
+
 static void
-macfont_store_descriptor_attributes (FontDescriptorRef desc,
+macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
                                      Lisp_Object spec_or_entity)
 {
   CFStringRef str;
@@ -780,33 +806,34 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc,
   CFNumberRef num;
   CGFloat floatval;
 
-  str = mac_font_descriptor_copy_attribute (desc,
-                                            MAC_FONT_FAMILY_NAME_ATTRIBUTE);
+  str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
   if (str)
     {
       ASET (spec_or_entity, FONT_FAMILY_INDEX,
             macfont_intern_prop_cfstring (str));
       CFRelease (str);
     }
-  dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
+  dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
   if (dict)
     {
       struct {
         enum font_property_index index;
         CFStringRef trait;
         CGPoint points[6];
+       CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
       } numeric_traits[] =
-          {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
+          {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
             {{-0.4, 50},       /* light */
              {-0.24, 87.5},    /* (semi-light + normal) / 2 */
              {0, 100},         /* normal */
              {0.24, 140},      /* (semi-bold + normal) / 2 */
              {0.4, 200},       /* bold */
-             {CGFLOAT_MAX, CGFLOAT_MAX}}},
-           {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
-            {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
-           {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
-            {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
+             {CGFLOAT_MAX, CGFLOAT_MAX}},
+           mac_font_descriptor_get_adjusted_weight},
+           {FONT_SLANT_INDEX, kCTFontSlantTrait,
+            {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
+           {FONT_WIDTH_INDEX, kCTFontWidthTrait,
+            {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
       int i;
 
       for (i = 0; i < ARRAYELTS (numeric_traits); i++)
@@ -816,6 +843,8 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc,
             {
               CGPoint *point = numeric_traits[i].points;
 
+             if (numeric_traits[i].adjust_func)
+               floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
               while (point->x < floatval)
                 point++;
               if (point == numeric_traits[i].points)
@@ -830,21 +859,21 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc,
             }
         }
 
-      num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
+      num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
       if (num)
         {
-          FontSymbolicTraits sym_traits;
+          CTFontSymbolicTraits sym_traits;
           int spacing;
 
           cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
-          spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
+          spacing = (sym_traits & kCTFontTraitMonoSpace
                      ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
           ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
         }
 
       CFRelease (dict);
     }
-  num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
+  num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
   if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
     ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
   else
@@ -854,12 +883,12 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc,
 }
 
 static Lisp_Object
-macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
-                           FontSymbolicTraits synth_sym_traits)
+macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
+                           CTFontSymbolicTraits synth_sym_traits)
 {
   Lisp_Object entity;
   CFDictionaryRef dict;
-  FontSymbolicTraits sym_traits = 0;
+  CTFontSymbolicTraits sym_traits = 0;
   CFStringRef name;
 
   entity = font_make_entity ();
@@ -869,10 +898,10 @@ macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
 
   macfont_store_descriptor_attributes (desc, entity);
 
-  dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
+  dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
   if (dict)
     {
-      CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
+      CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
 
       if (num)
         cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
@@ -881,77 +910,193 @@ macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
   if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
     ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
   ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
-  name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
+  name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
   font_put_extra (entity, QCfont_entity,
                   make_save_ptr_int ((void *) name, sym_traits));
-  if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
+  if (synth_sym_traits & kCTFontTraitItalic)
     FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
                     make_number (FONT_SLANT_SYNTHETIC_ITALIC));
-  if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
+  if (synth_sym_traits & kCTFontTraitBold)
     FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
                     make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
-  if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
+  if (synth_sym_traits & kCTFontTraitMonoSpace)
     ASET (entity, FONT_SPACING_INDEX,
           make_number (FONT_SPACING_SYNTHETIC_MONO));
 
   return entity;
 }
 
-static CFStringRef
-macfont_create_family_with_symbol (Lisp_Object symbol)
+/* Cache for font family name symbols vs CFStrings.  A value of nil
+means the cache has been invalidated.  Otherwise the value is a Lisp
+hash table whose keys are symbols and the value for a key is either
+nil (no corresponding family name) or a Lisp save value wrapping the
+corresponding family name in CFString.  */
+
+static Lisp_Object macfont_family_cache;
+
+static void
+macfont_invalidate_family_cache (void)
 {
-  static CFArrayRef families = NULL;
-  CFStringRef result = NULL, family_name;
-  int using_cache_p = 1;
-  CFComparatorFunction family_name_comparator;
+  if (HASH_TABLE_P (macfont_family_cache))
+    {
+      struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
+      ptrdiff_t i, size = HASH_TABLE_SIZE (h);
 
-  family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
-  if (family_name == NULL)
-    return NULL;
+      for (i = 0; i < size; ++i)
+       if (!NILP (HASH_HASH (h, i)))
+         {
+           Lisp_Object value = HASH_VALUE (h, i);
 
+           if (SAVE_VALUEP (value))
+             CFRelease (XSAVE_POINTER (value, 0));
+         }
+      macfont_family_cache = Qnil;
+    }
+}
+
+static bool
+macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
+{
+  if (HASH_TABLE_P (macfont_family_cache))
     {
-      family_name_comparator = CTFontManagerCompareFontFamilyNames;
+      struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
+      ptrdiff_t i = hash_lookup (h, symbol, NULL);
+
+      if (i >= 0)
+       {
+         Lisp_Object value = HASH_VALUE (h, i);
+
+         *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
+
+         return true;
+       }
     }
 
-  if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
-      == kCFCompareEqualTo)
-    result = CFSTR ("LastResort");
+  return false;
+}
+
+static void
+macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
+{
+  struct Lisp_Hash_Table *h;
+  ptrdiff_t i;
+  EMACS_UINT hash;
+  Lisp_Object value;
+
+  if (!HASH_TABLE_P (macfont_family_cache))
+    macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
+
+  h = XHASH_TABLE (macfont_family_cache);
+  i = hash_lookup (h, symbol, &hash);
+  value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
+  if (i >= 0)
+    {
+      Lisp_Object old_value = HASH_VALUE (h, i);
+
+      if (SAVE_VALUEP (old_value))
+       CFRelease (XSAVE_POINTER (old_value, 0));
+      set_hash_value_slot (h, i, value);
+    }
   else
-    while (1)
-      {
-        CFIndex i, count;
+    hash_put (h, symbol, value, hash);
+}
 
-        if (families == NULL)
-          {
-            families = mac_font_create_available_families ();
-            using_cache_p = 0;
-            if (families == NULL)
-              break;
-          }
+/* Cache of all the available font family names except "LastResort"
+and those start with ".".  NULL means the cache has been invalidated.
+Otherwise, the value is CFArray of CFStrings and the elements are
+sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
+OS X 10.6 and later).  */
 
-        count = CFArrayGetCount (families);
-        i = CFArrayBSearchValues (families, CFRangeMake (0, count),
-                                  (const void *) family_name,
-                                  family_name_comparator, NULL);
-        if (i < count)
-          {
-            CFStringRef name = CFArrayGetValueAtIndex (families, i);
+static CFArrayRef macfont_available_families_cache = NULL;
 
-            if ((*family_name_comparator) (name, family_name, NULL)
-                == kCFCompareEqualTo)
-              result = CFRetain (name);
-          }
+static void
+macfont_invalidate_available_families_cache (void)
+{
+  if (macfont_available_families_cache)
+    {
+      CFRelease (macfont_available_families_cache);
+      macfont_available_families_cache = NULL;
+    }
+}
 
-        if (result || !using_cache_p)
-          break;
-        else
-          {
-            CFRelease (families);
-            families = NULL;
-          }
-      }
+static void
+macfont_handle_font_change_notification (CFNotificationCenterRef center,
+                                        void *observer,
+                                        CFStringRef name, const void *object,
+                                        CFDictionaryRef userInfo)
+{
+  macfont_invalidate_family_cache ();
+  macfont_invalidate_available_families_cache ();
+}
+
+static void
+macfont_init_font_change_handler (void)
+{
+  static bool initialized = false;
+
+  if (initialized)
+    return;
+
+  initialized = true;
+  CFNotificationCenterAddObserver
+    (CFNotificationCenterGetLocalCenter (), NULL,
+     macfont_handle_font_change_notification,
+     kCTFontManagerRegisteredFontsChangedNotification,
+     NULL, CFNotificationSuspensionBehaviorCoalesce);
+}
+
+static CFArrayRef
+macfont_copy_available_families_cache (void)
+{
+  macfont_init_font_change_handler ();
+
+  if (macfont_available_families_cache == NULL)
+    macfont_available_families_cache = mac_font_create_available_families ();
+
+  return (macfont_available_families_cache
+         ? CFRetain (macfont_available_families_cache) : NULL);
+}
 
-  CFRelease (family_name);
+static CFStringRef
+macfont_create_family_with_symbol (Lisp_Object symbol)
+{
+  CFStringRef result = NULL, family_name;
+  CFDictionaryRef attributes = NULL;
+  CTFontDescriptorRef pat_desc = NULL;
+
+  if (macfont_get_family_cache_if_present (symbol, &result))
+    return result ? CFRetain (result) : NULL;
+
+  family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
+  if (family_name)
+    {
+      attributes =
+       CFDictionaryCreate (NULL,
+                           (const void **) &kCTFontFamilyNameAttribute,
+                           (const void **) &family_name, 1,
+                           &kCFTypeDictionaryKeyCallBacks,
+                           &kCFTypeDictionaryValueCallBacks);
+      CFRelease (family_name);
+    }
+  if (attributes)
+    {
+      pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
+      CFRelease (attributes);
+    }
+  if (pat_desc)
+    {
+      CTFontDescriptorRef desc =
+       CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
+
+      if (desc)
+       {
+         result =
+           CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
+         CFRelease (desc);
+       }
+      macfont_set_family_cache (symbol, result);
+      CFRelease (pat_desc);
+    }
 
   return result;
 }
@@ -1003,7 +1148,7 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
                        int force_integral_p)
 {
   struct macfont_info *macfont_info = (struct macfont_info *) font;
-  FontRef macfont = macfont_info->macfont;
+  CTFontRef macfont = macfont_info->macfont;
   int row, col;
   struct macfont_metrics *cache;
   int width;
@@ -1073,10 +1218,9 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
             }
           if (macfont_info->synthetic_bold_p && ! force_integral_p)
             {
-              CGFloat d =
-                - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
+              CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
 
-                bounds = CGRectInset (bounds, d, d);
+             bounds = CGRectInset (bounds, d, d);
             }
           switch (macfont_info->spacing)
             {
@@ -1179,8 +1323,8 @@ struct macfont_cache
     /* Character collection specifying the destination of the mapping
        provided by `table' above.  If `table' is obtained from the UVS
        subtable in the font cmap table, then the value of this member
-       should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING.  */
-    CharacterCollection collection;
+       should be kCTCharacterCollectionIdentityMapping.  */
+    CTCharacterCollection collection;
   } uvs;
 };
 
@@ -1191,8 +1335,8 @@ static CFCharacterSetRef macfont_get_cf_charset (struct font *);
 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
-                                          CharacterCollection, CGFontIndex);
-static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
+                                          CTCharacterCollection, CGFontIndex);
+static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
 
 static struct macfont_cache *
 macfont_lookup_cache (CFStringRef key)
@@ -1212,7 +1356,7 @@ macfont_lookup_cache (CFStringRef key)
 
   if (cache == NULL)
     {
-      FontRef macfont = mac_font_create_with_name (key, 0);
+      CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
 
       if (macfont)
         {
@@ -1230,7 +1374,7 @@ macfont_lookup_cache (CFStringRef key)
                 CFCharacterSetCreateWithCharactersInRange (NULL, range);
             }
           if (cache->cf_charset == NULL)
-            cache->cf_charset = mac_font_copy_character_set (macfont);
+            cache->cf_charset = CTFontCopyCharacterSet (macfont);
           CFDictionaryAddValue (macfont_cache_dictionary, key,
                                 (const void *) cache);
           CFRelease (macfont);
@@ -1287,7 +1431,7 @@ static CGGlyph
 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
 {
   struct macfont_info *macfont_info = (struct macfont_info *) font;
-  FontRef macfont = macfont_info->macfont;
+  CTFontRef macfont = macfont_info->macfont;
   struct macfont_cache *cache = macfont_info->cache;
 
   if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
@@ -1326,8 +1470,7 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
               if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
                 {
                   ch = c;
-                  if (!mac_font_get_glyphs_for_characters (macfont, &ch,
-                                                           &glyph, 1)
+                  if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
                       || glyph == 0)
                     glyph = kCGFontIndexInvalid;
 
@@ -1370,8 +1513,7 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
           glyphs = xmalloc (sizeof (CGGlyph) * 256);
           if (len > 0)
             {
-              mac_font_get_glyphs_for_characters (macfont, unichars,
-                                                  glyphs, len);
+              CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
               while (i > len)
                 {
                   int next = unichars[len - 1] % 256;
@@ -1427,8 +1569,7 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
           CGGlyph glyphs[2];
           CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
 
-          if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
-                                                  count))
+          if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
             glyph = glyphs[0];
           if (glyph == 0)
             glyph = kCGFontIndexInvalid;
@@ -1443,33 +1584,33 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
 }
 
 static CGGlyph
-macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
+macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
                            CGFontIndex cid)
 {
   struct macfont_info *macfont_info = (struct macfont_info *) font;
-  FontRef macfont = macfont_info->macfont;
+  CTFontRef macfont = macfont_info->macfont;
 
   /* Cache it? */
   return mac_font_get_glyph_for_cid (macfont, collection, cid);
 }
 
 static CFDataRef
-macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
+macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
 {
   struct macfont_info *macfont_info = (struct macfont_info *) font;
-  FontRef macfont = macfont_info->macfont;
+  CTFontRef macfont = macfont_info->macfont;
   struct macfont_cache *cache = macfont_info->cache;
   CFDataRef result = NULL;
 
   if (cache->uvs.table == NULL)
     {
       CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
-      CharacterCollection uvs_collection =
-        MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
+      CTCharacterCollection uvs_collection =
+        kCTCharacterCollectionIdentityMapping;
 
       if (uvs_table == NULL
           && mac_font_get_glyph_for_cid (macfont,
-                                         MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
+                                         kCTCharacterCollectionAdobeJapan1,
                                          6480) != kCGFontIndexInvalid)
         {
           /* If the glyph for U+4E55 is accessible via its CID 6480,
@@ -1486,7 +1627,7 @@ macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
           if (mac_uvs_table_adobe_japan1)
             {
               uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
-              uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
+              uvs_collection = kCTCharacterCollectionAdobeJapan1;
             }
         }
       if (uvs_table == NULL)
@@ -1729,16 +1870,16 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
     CFStringRef trait;
     CGPoint points[6];
   } numeric_traits[] =
-      {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
+      {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
         {{-0.4, 50},           /* light */
          {-0.24, 87.5},                /* (semi-light + normal) / 2 */
          {0, 100},             /* normal */
          {0.24, 140},          /* (semi-bold + normal) / 2 */
          {0.4, 200},           /* bold */
          {CGFLOAT_MAX, CGFLOAT_MAX}}},
-       {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
+       {FONT_SLANT_INDEX, kCTFontSlantTrait,
         {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
-       {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
+       {FONT_WIDTH_INDEX, kCTFontWidthTrait,
         {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
 
   registry = AREF (spec, FONT_REGISTRY_INDEX);
@@ -1854,7 +1995,7 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
 
       if (! family)
         goto err;
-      CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
+      CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
                             family);
       CFRelease (family);
     }
@@ -1895,16 +2036,16 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
         }
     }
   if (CFDictionaryGetCount (traits))
-    CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
+    CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
 
   if (charset)
-    CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
+    CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
                           charset);
   if (charset_string)
     CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
                           charset_string);
   if (langarray)
-    CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
+    CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
 
   goto finish;
 
@@ -1933,7 +2074,7 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
 }
 
 static Boolean
-macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
+macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
                                           CFCharacterSetRef charset,
                                           Lisp_Object chars,
                                           CFArrayRef languages)
@@ -1943,8 +2084,7 @@ macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
   if (charset || VECTORP (chars))
     {
       CFCharacterSetRef desc_charset =
-        mac_font_descriptor_copy_attribute (desc,
-                                            MAC_FONT_CHARACTER_SET_ATTRIBUTE);
+        CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
 
       if (desc_charset == NULL)
         result = false;
@@ -1974,20 +2114,20 @@ macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
 }
 
 static int
-macfont_traits_distance (FontSymbolicTraits sym_traits1,
-                         FontSymbolicTraits sym_traits2)
+macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
+                         CTFontSymbolicTraits sym_traits2)
 {
-  FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
+  CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
   int distance = 0;
 
   /* We prefer synthetic bold of italic to synthetic italic of bold
      when both bold and italic are available but bold-italic is not
      available.  */
-  if (diff & MAC_FONT_TRAIT_BOLD)
+  if (diff & kCTFontTraitBold)
     distance |= (1 << 0);
-  if (diff & MAC_FONT_TRAIT_ITALIC)
+  if (diff & kCTFontTraitItalic)
     distance |= (1 << 1);
-  if (diff & MAC_FONT_TRAIT_MONO_SPACE)
+  if (diff & kCTFontTraitMonoSpace)
     distance |= (1 << 2);
 
   return distance;
@@ -1995,21 +2135,21 @@ macfont_traits_distance (FontSymbolicTraits sym_traits1,
 
 static Boolean
 macfont_closest_traits_index_p (CFArrayRef traits_array,
-                                FontSymbolicTraits target,
+                                CTFontSymbolicTraits target,
                                 CFIndex index)
 {
   CFIndex i, count = CFArrayGetCount (traits_array);
-  FontSymbolicTraits traits;
+  CTFontSymbolicTraits traits;
   int my_distance;
 
-  traits = ((FontSymbolicTraits) (uintptr_t)
+  traits = ((CTFontSymbolicTraits) (uintptr_t)
             CFArrayGetValueAtIndex (traits_array, index));
   my_distance = macfont_traits_distance (target, traits);
 
   for (i = 0; i < count; i++)
     if (i != index)
       {
-        traits = ((FontSymbolicTraits) (uintptr_t)
+        traits = ((CTFontSymbolicTraits) (uintptr_t)
                   CFArrayGetValueAtIndex (traits_array, i));
         if (macfont_traits_distance (target, traits) < my_distance)
           return false;
@@ -2027,7 +2167,7 @@ macfont_list (struct frame *f, Lisp_Object spec)
   CFMutableDictionaryRef attributes = NULL, traits;
   Lisp_Object chars = Qnil;
   int spacing = -1;
-  FontSymbolicTraits synth_sym_traits = 0;
+  CTFontSymbolicTraits synth_sym_traits = 0;
   CFArrayRef families;
   CFIndex families_count;
   CFCharacterSetRef charset = NULL;
@@ -2047,28 +2187,28 @@ macfont_list (struct frame *f, Lisp_Object spec)
   if (! attributes)
     goto finish;
 
-  languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
+  languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
 
   if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
     spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
 
   traits = ((CFMutableDictionaryRef)
-            CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
+            CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
 
   n = FONT_SLANT_NUMERIC (spec);
   if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
     {
-      synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
+      synth_sym_traits |= kCTFontTraitItalic;
       if (traits)
-        CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
+        CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
     }
 
   n = FONT_WEIGHT_NUMERIC (spec);
   if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
     {
-      synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
+      synth_sym_traits |= kCTFontTraitBold;
       if (traits)
-        CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
+        CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
     }
 
   if (languages
@@ -2079,7 +2219,7 @@ macfont_list (struct frame *f, Lisp_Object spec)
       if (CFStringHasPrefix (language, CFSTR ("ja"))
           || CFStringHasPrefix (language, CFSTR ("ko"))
           || CFStringHasPrefix (language, CFSTR ("zh")))
-        synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
+        synth_sym_traits |= kCTFontTraitMonoSpace;
     }
 
   /* Create array of families.  */
@@ -2091,7 +2231,7 @@ macfont_list (struct frame *f, Lisp_Object spec)
       CFStringRef pref_family;
       CFIndex families_count, pref_family_index = -1;
 
-      families = mac_font_create_available_families ();
+      families = macfont_copy_available_families_cache ();
       if (families == NULL)
         goto err;
 
@@ -2131,12 +2271,11 @@ macfont_list (struct frame *f, Lisp_Object spec)
         }
     }
 
-  charset = CFDictionaryGetValue (attributes,
-                                  MAC_FONT_CHARACTER_SET_ATTRIBUTE);
+  charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
   if (charset)
     {
       CFRetain (charset);
-      CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
+      CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
     }
   else
     {
@@ -2153,7 +2292,7 @@ macfont_list (struct frame *f, Lisp_Object spec)
   if (languages)
     {
       CFRetain (languages);
-      CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
+      CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
     }
 
   val = Qnil;
@@ -2162,16 +2301,16 @@ macfont_list (struct frame *f, Lisp_Object spec)
   for (i = 0; i < families_count; i++)
     {
       CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
-      FontDescriptorRef pat_desc;
+      CTFontDescriptorRef pat_desc;
       CFArrayRef descs;
       CFIndex descs_count;
       CFMutableArrayRef filtered_descs, traits_array;
       Lisp_Object entity;
       int j;
 
-      CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
+      CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
                             family_name);
-      pat_desc = mac_font_descriptor_create_with_attributes (attributes);
+      pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
       if (! pat_desc)
         goto err;
 
@@ -2180,13 +2319,11 @@ macfont_list (struct frame *f, Lisp_Object spec)
          So we use CTFontDescriptorCreateMatchingFontDescriptor (no
          trailing "s") for such a font.  */
       if (!CFEqual (family_name, CFSTR ("LastResort")))
-        descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
-                                                                      NULL);
+        descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
       else
         {
-          FontDescriptorRef lr_desc =
-            mac_font_descriptor_create_matching_font_descriptor (pat_desc,
-                                                                 NULL);
+          CTFontDescriptorRef lr_desc =
+            CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
           if (lr_desc)
             {
               descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
@@ -2198,7 +2335,7 @@ macfont_list (struct frame *f, Lisp_Object spec)
         }
       CFRelease (pat_desc);
       if (! descs)
-        goto err;
+        continue;
 
       descs_count = CFArrayGetCount (descs);
       if (descs_count == 0
@@ -2215,31 +2352,30 @@ macfont_list (struct frame *f, Lisp_Object spec)
       traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
       for (j = 0; j < descs_count; j++)
         {
-          FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
+          CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
           CFDictionaryRef dict;
           CFNumberRef num;
-          FontSymbolicTraits sym_traits;
+          CTFontSymbolicTraits sym_traits;
 
-          dict = mac_font_descriptor_copy_attribute (desc,
-                                                     MAC_FONT_TRAITS_ATTRIBUTE);
+          dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
           if (dict == NULL)
             continue;
 
-          num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
+          num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
           CFRelease (dict);
           if (num == NULL
               || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
             continue;
 
           if (spacing >= 0
-              && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
-              && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
+              && !(synth_sym_traits & kCTFontTraitMonoSpace)
+              && (((sym_traits & kCTFontTraitMonoSpace) != 0)
                   != (spacing >= FONT_SPACING_MONO)))
             continue;
 
           /* Don't use a color bitmap font unless its family is
              explicitly specified.  */
-          if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
+          if ((sym_traits & kCTFontTraitColorGlyphs) && NILP (family))
             continue;
 
           if (j > 0
@@ -2258,27 +2394,26 @@ macfont_list (struct frame *f, Lisp_Object spec)
 
       for (j = 0; j < descs_count; j++)
         {
-          FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
-          FontSymbolicTraits sym_traits =
-            ((FontSymbolicTraits) (uintptr_t)
+          CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
+          CTFontSymbolicTraits sym_traits =
+            ((CTFontSymbolicTraits) (uintptr_t)
              CFArrayGetValueAtIndex (traits_array, j));
-          FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
+          CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
 
           mask_min = ((synth_sym_traits ^ sym_traits)
-                      & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
+                      & (kCTFontTraitItalic | kCTFontTraitBold));
           if (FONT_SLANT_NUMERIC (spec) < 0)
-            mask_min &= ~MAC_FONT_TRAIT_ITALIC;
+            mask_min &= ~kCTFontTraitItalic;
           if (FONT_WEIGHT_NUMERIC (spec) < 0)
-            mask_min &= ~MAC_FONT_TRAIT_BOLD;
+            mask_min &= ~kCTFontTraitBold;
 
           mask_max = (synth_sym_traits & ~sym_traits);
           /* Synthetic bold does not work for bitmap-only fonts on Mac
              OS X 10.6.  */
-          if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
+          if ((mask_min ^ mask_max) & kCTFontTraitBold)
             {
               CFNumberRef format =
-                mac_font_descriptor_copy_attribute (desc,
-                                                    MAC_FONT_FORMAT_ATTRIBUTE);
+                CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
 
               if (format)
                 {
@@ -2286,24 +2421,24 @@ macfont_list (struct frame *f, Lisp_Object spec)
 
                   if (CFNumberGetValue (format, kCFNumberSInt32Type,
                                         &format_val)
-                      && format_val == MAC_FONT_FORMAT_BITMAP)
-                    mask_max &= ~MAC_FONT_TRAIT_BOLD;
+                      && format_val == kCTFontFormatBitmap)
+                    mask_max &= ~kCTFontTraitBold;
                 }
             }
           if (spacing >= 0)
-            mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
-
-          for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
-               mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
-               mmask += MAC_FONT_TRAIT_MONO_SPACE)
-            for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
-                 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
-                 bmask += MAC_FONT_TRAIT_BOLD)
-              for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
-                   imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
-                   imask += MAC_FONT_TRAIT_ITALIC)
+            mask_min |= (mask_max & kCTFontTraitMonoSpace);
+
+          for (mmask = (mask_min & kCTFontTraitMonoSpace);
+               mmask <= (mask_max & kCTFontTraitMonoSpace);
+               mmask += kCTFontTraitMonoSpace)
+            for (bmask = (mask_min & kCTFontTraitBold);
+                 bmask <= (mask_max & kCTFontTraitBold);
+                 bmask += kCTFontTraitBold)
+              for (imask = (mask_min & kCTFontTraitItalic);
+                   imask <= (mask_max & kCTFontTraitItalic);
+                   imask += kCTFontTraitItalic)
                 {
-                  FontSymbolicTraits synth = (imask | bmask | mmask);
+                  CTFontSymbolicTraits synth = (imask | bmask | mmask);
 
                   if (synth == 0
                       || macfont_closest_traits_index_p (traits_array,
@@ -2344,20 +2479,19 @@ macfont_match (struct frame * frame, Lisp_Object spec)
 {
   Lisp_Object entity = Qnil;
   CFMutableDictionaryRef attributes;
-  FontDescriptorRef pat_desc = NULL, desc = NULL;
+  CTFontDescriptorRef pat_desc = NULL, desc = NULL;
 
   block_input ();
 
   attributes = macfont_create_attributes_with_spec (spec);
   if (attributes)
     {
-      pat_desc = mac_font_descriptor_create_with_attributes (attributes);
+      pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
       CFRelease (attributes);
     }
   if (pat_desc)
     {
-      desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
-                                                                  NULL);
+      desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
       CFRelease (pat_desc);
     }
   if (desc)
@@ -2380,7 +2514,7 @@ macfont_list_family (struct frame *frame)
 
   block_input ();
 
-  families = mac_font_create_available_families ();
+  families = macfont_copy_available_families_cache ();
   if (families)
     {
       CFIndex i, count = CFArrayGetCount (families);
@@ -2415,8 +2549,8 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
   struct macfont_info *macfont_info = NULL;
   struct font *font;
   int size;
-  FontRef macfont;
-  FontSymbolicTraits sym_traits;
+  CTFontRef macfont;
+  CTFontSymbolicTraits sym_traits;
   char name[256];
   int len, i, total_width;
   CGGlyph glyph;
@@ -2435,7 +2569,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
     size = pixel_size;
 
   block_input ();
-  macfont = mac_font_create_with_name (font_name, size);
+  macfont = CTFontCreateWithName (font_name, size, NULL);
   if (macfont)
     {
       int fontsize = (int) [((NSFont *) macfont) pointSize];
@@ -2456,7 +2590,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
 
   macfont_info = (struct macfont_info *) font;
   macfont_info->macfont = macfont;
-  macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
+  macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
 
   val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
   if (CONSP (val) && EQ (XCDR (val), make_number (1)))
@@ -2472,13 +2606,13 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
   macfont_info->synthetic_bold_p = 0;
   macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
   macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
-  if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
+  if (!(sym_traits & kCTFontTraitItalic)
       && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
     macfont_info->synthetic_italic_p = 1;
-  if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
+  if (!(sym_traits & kCTFontTraitBold)
       && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
     macfont_info->synthetic_bold_p = 1;
-  if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
+  if (sym_traits & kCTFontTraitMonoSpace)
     macfont_info->spacing = MACFONT_SPACING_MONO;
   else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
            && (XINT (AREF (entity, FONT_SPACING_INDEX))
@@ -2494,7 +2628,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
           NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
     }
   macfont_info->color_bitmap_p = 0;
-  if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
+  if (sym_traits & kCTFontTraitColorGlyphs)
     macfont_info->color_bitmap_p = 1;
 
   glyph = macfont_get_glyph_for_character (font, ' ');
@@ -2523,12 +2657,12 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
     {
       CFStringRef family_name;
 
-      ascent = mac_font_get_ascent (macfont);
-      descent = mac_font_get_descent (macfont);
-      leading = mac_font_get_leading (macfont);
+      ascent = CTFontGetAscent (macfont);
+      descent = CTFontGetDescent (macfont);
+      leading = CTFontGetLeading (macfont);
       /* AppKit and WebKit do some adjustment to the heights of
          Courier, Helvetica, and Times.  */
-      family_name = mac_font_copy_family_name (macfont);
+      family_name = CTFontCopyFamilyName (macfont);
       if (family_name)
         {
           if (CFEqual (family_name, CFSTR ("Courier"))
@@ -2551,8 +2685,8 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
     font->descent = descent + leading + 0.5f;
   font->height = font->ascent + font->descent;
 
-  font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
-  font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
+  font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
+  font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
 
   unblock_input ();
 
@@ -2622,7 +2756,6 @@ macfont_has_char (Lisp_Object font, int c)
 static unsigned
 macfont_encode_char (struct font *font, int c)
 {
-  struct macfont_info *macfont_info = (struct macfont_info *) font;
   CGGlyph glyph;
 
   block_input ();
@@ -2675,7 +2808,7 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
   CGPoint text_position;
   CGGlyph *glyphs;
   CGPoint *positions;
-  CGFloat font_size = mac_font_get_size (macfont_info->macfont);
+  CGFloat font_size = CTFontGetSize (macfont_info->macfont);
   bool no_antialias_p =
     (NILP (ns_antialias_text)
      || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
@@ -2790,7 +2923,7 @@ macfont_shape (Lisp_Object lgstring)
 {
   struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
   struct macfont_info *macfont_info = (struct macfont_info *) font;
-  FontRef macfont = macfont_info->macfont;
+  CTFontRef macfont = macfont_info->macfont;
   ptrdiff_t glyph_len, len, i, j;
   CFIndex nonbmp_len;
   UniChar *unichars;
@@ -2987,11 +3120,12 @@ struct non_default_uvs_table
    found or ill-formatted, then return NULL.  */
 
 static CFDataRef
-mac_font_copy_uvs_table (FontRef font)
+mac_font_copy_uvs_table (CTFontRef font)
 {
   CFDataRef cmap_table, uvs_table = NULL;
 
-  cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
+  cmap_table = CTFontCopyTable (font, cmapFontTableTag,
+                               kCTFontTableOptionNoOptions);
   if (cmap_table)
     {
       sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
@@ -3214,7 +3348,7 @@ static int
 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
 {
   CFDataRef uvs_table;
-  CharacterCollection uvs_collection;
+  CTCharacterCollection uvs_collection;
   int i, n = 0;
 
   block_input ();
@@ -3234,7 +3368,7 @@ macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
         {
           CGGlyph glyph = glyphs[i];
 
-          if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
+          if (uvs_collection != kCTCharacterCollectionIdentityMapping
               && glyph != kCGFontIndexInvalid)
             glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
           if (glyph == kCGFontIndexInvalid)
@@ -3272,8 +3406,8 @@ macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
 }
 
 static Boolean
-mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
-                                          CFArrayRef languages)
+mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
+                                       CFArrayRef languages)
 {
   Boolean result = true;
   CFArrayRef desc_languages =
@@ -3283,18 +3417,24 @@ mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
     result = false;
   else
     {
-      CFIndex desc_languages_count, i, languages_count;
+      CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
+      CFIndex i, languages_count = CFArrayGetCount (languages);
 
-      desc_languages_count = CFArrayGetCount (desc_languages);
-      languages_count = CFArrayGetCount (languages);
       for (i = 0; i < languages_count; i++)
-        if (!CFArrayContainsValue (desc_languages,
-                                   CFRangeMake (0, desc_languages_count),
-                                   CFArrayGetValueAtIndex (languages, i)))
-          {
-            result = false;
-            break;
-          }
+       {
+         CFStringRef language = CFArrayGetValueAtIndex (languages, i);
+
+         if (!CFArrayContainsValue (desc_languages, range, language)
+             /* PingFang SC contains "zh" and "zh-Hant" as covered
+                languages, but does not contain "zh-Hans".  */
+             && !(CFEqual (language, CFSTR ("zh-Hans"))
+                  && CFArrayContainsValue (desc_languages, range,
+                                           CFSTR ("zh"))))
+           {
+             result = false;
+             break;
+           }
+       }
       CFRelease (desc_languages);
     }
 
@@ -3302,7 +3442,7 @@ mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
 }
 
 static CFStringRef
-mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
+mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
 {
   CFStringRef result = NULL;
   CFStringRef charset_string =
@@ -3320,7 +3460,7 @@ mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
       CFTypeRef values[] = {NULL};
       CFIndex num_values = 0;
       CFArrayRef languages
-        = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
+        = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
 
       if (languages && CFArrayGetCount (languages) > 0)
         {
@@ -3329,8 +3469,7 @@ mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
           else
             {
               CFCharacterSetRef charset =
-                CFDictionaryGetValue (attributes,
-                                      MAC_FONT_CHARACTER_SET_ATTRIBUTE);
+                CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
 
               result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
             }
@@ -3376,8 +3515,8 @@ mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
                     break;
                   if (i == 0)
                     font = font_in_run;
-                  else if (!mac_ctfont_equal_in_postscript_name (font,
-                                                                 font_in_run))
+                  else if (!mac_font_equal_in_postscript_name (font,
+                                                              font_in_run))
                     break;
                 }
               if (nruns > 0 && i == nruns)
@@ -3391,53 +3530,50 @@ mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
 }
 
 static inline double
-mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
+mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
 {
-  return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
-                                     &glyph, NULL, 1);
+  return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
+                                    &glyph, NULL, 1);
 }
 
 static inline CGRect
-mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
+mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
 {
-  return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
-                                          &glyph, NULL, 1);
+  return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
+                                         &glyph, NULL, 1);
 }
 
 static CFArrayRef
-mac_ctfont_create_available_families (void)
+mac_font_create_available_families (void)
 {
   CFMutableArrayRef families = NULL;
+  CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
 
+  if (orig_families)
     {
-      CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
+      CFIndex i, count = CFArrayGetCount (orig_families);
 
-      if (orig_families)
-        {
-          CFIndex i, count = CFArrayGetCount (orig_families);
+      families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
+      if (families)
+       for (i = 0; i < count; i++)
+         {
+           CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
 
-          families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
-          if (families)
-            for (i = 0; i < count; i++)
-              {
-                CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
-
-                if (!CFStringHasPrefix (family, CFSTR ("."))
-                    && (CTFontManagerCompareFontFamilyNames (family,
-                                                             CFSTR ("LastResort"),
-                                                             NULL)
-                        != kCFCompareEqualTo))
-                  CFArrayAppendValue (families, family);
-              }
-          CFRelease (orig_families);
-        }
+           if (!CFStringHasPrefix (family, CFSTR ("."))
+               && (CTFontManagerCompareFontFamilyNames (family,
+                                                        CFSTR ("LastResort"),
+                                                        NULL)
+                   != kCFCompareEqualTo))
+             CFArrayAppendValue (families, family);
+         }
+      CFRelease (orig_families);
     }
 
-    return families;
+  return families;
 }
 
 static Boolean
-mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
+mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
 {
   Boolean result;
   CFStringRef name1, name2;
@@ -3462,8 +3598,8 @@ mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
 }
 
 static CTLineRef
-mac_ctfont_create_line_with_string_and_font (CFStringRef string,
-                                             CTFontRef macfont)
+mac_font_create_line_with_string_and_font (CFStringRef string,
+                                          CTFontRef macfont)
 {
   CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
   CFTypeRef values[] = {NULL, NULL};
@@ -3512,7 +3648,7 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string,
             CFDictionaryGetValue (attributes, kCTFontAttributeName);
           if (font_in_run == NULL)
             break;
-          if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
+          if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
             break;
         }
       if (i < nruns)
@@ -3526,11 +3662,11 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string,
 }
 
 static CFIndex
-mac_ctfont_shape (CTFontRef font, CFStringRef string,
-                  struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
+mac_font_shape (CTFontRef font, CFStringRef string,
+               struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
 {
   CFIndex used, result = 0;
-  CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
+  CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
 
   if (ctline == NULL)
     return 0;
@@ -3737,7 +3873,7 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
                 CFDictionaryGetValue (attributes, kCTFontAttributeName);
 
               if (font_in_run
-                  && mac_ctfont_equal_in_postscript_name (font_in_run, font))
+                  && mac_font_equal_in_postscript_name (font_in_run, font))
                 {
                   CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
                   if (result >= CTFontGetGlyphCount (font))
@@ -3763,7 +3899,7 @@ mac_font_copy_default_descriptors_for_language (CFStringRef language)
 #endif
     {
       CTFontRef user_font =
-        CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
+       CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
 
       if (user_font)
         {
@@ -3807,7 +3943,7 @@ mac_font_copy_default_descriptors_for_language (CFStringRef language)
                       CFDictionaryRef attributes =
                         CFDictionaryCreate (NULL,
                                             ((const void **)
-                                             &MAC_FONT_NAME_ATTRIBUTE),
+                                             &kCTFontNameAttribute),
                                             ((const void **)
                                              &macfont_language_default_font_names[i].font_names[j]),
                                             1, &kCFTypeDictionaryKeyCallBacks,
@@ -3815,13 +3951,13 @@ mac_font_copy_default_descriptors_for_language (CFStringRef language)
 
                       if (attributes)
                         {
-                          FontDescriptorRef pat_desc =
-                            mac_font_descriptor_create_with_attributes (attributes);
+                          CTFontDescriptorRef pat_desc =
+                            CTFontDescriptorCreateWithAttributes (attributes);
 
                           if (pat_desc)
                             {
-                              FontDescriptorRef descriptor =
-                                mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
+                              CTFontDescriptorRef descriptor =
+                                CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
 
                               if (descriptor)
                                 {
@@ -3859,15 +3995,15 @@ mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
 
       for (i = 0; i < count; i++)
         {
-          FontDescriptorRef descriptor =
+          CTFontDescriptorRef descriptor =
             CFArrayGetValueAtIndex (descriptors, i);
 
           if (macfont_supports_charset_and_languages_p (descriptor, charset,
                                                         Qnil, languages))
             {
               CFStringRef family =
-                mac_font_descriptor_copy_attribute (descriptor,
-                                                    MAC_FONT_FAMILY_NAME_ATTRIBUTE);
+                CTFontDescriptorCopyAttribute (descriptor,
+                                              kCTFontFamilyNameAttribute);
               if (family)
                 {
                   if (!CFStringHasPrefix (family, CFSTR ("."))
@@ -3891,7 +4027,7 @@ void *
 macfont_get_nsctfont (struct font *font)
 {
   struct macfont_info *macfont_info = (struct macfont_info *) font;
-  FontRef macfont = macfont_info->macfont;
+  CTFontRef macfont = macfont_info->macfont;
 
   return (void *) macfont;
 }
@@ -3906,8 +4042,6 @@ mac_register_font_driver (struct frame *f)
 void
 syms_of_macfont (void)
 {
-  static struct font_driver mac_font_driver;
-
   /* Core Text, for Mac OS X.  */
   DEFSYM (Qmac_ct, "mac-ct");
   macfont_driver.type = Qmac_ct;
@@ -3923,4 +4057,7 @@ syms_of_macfont (void)
 
   /* The boolean-valued font property key specifying the use of leading.  */
   DEFSYM (QCminspace, ":minspace");
+
+  macfont_family_cache = Qnil;
+  staticpro (&macfont_family_cache);
 }