* src/profiler.c: Delete.
[bpt/emacs.git] / src / macfont.m
index 206a810..9b3cb2c 100644 (file)
@@ -1,5 +1,5 @@
 /* Font driver on Mac OSX Core text.
-   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+   Copyright (C) 2009-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -30,6 +30,7 @@ Original author: YAMAMOTO Mitsuharu
 #include "composite.h"
 #include "fontset.h"
 #include "font.h"
+#include "termchar.h"
 #include "nsgui.h"
 #include "nsterm.h"
 #include "macfont.h"
@@ -57,6 +58,13 @@ static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
 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);
+
 #if USE_CT_GLYPH_INFO
 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
                                             CTCharacterCollection,
@@ -64,7 +72,7 @@ static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
 #endif
 
 /* The font property key specifying the font design destination.  The
-   value is an unsigned integer code: 0 for WYSIWIG, and 1 for Video
+   value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
    text.  (See the documentation of X Logical Font Description
    Conventions.)  In the Mac font driver, 1 means the screen font is
    used for calculating some glyph metrics.  You can see the
@@ -77,7 +85,7 @@ static Lisp_Object QCminspace;
 
 struct macfont_metrics;
 
-/* The actual structure for Mac font that can be casted to struct font.  */
+/* The actual structure for Mac font that can be cast to struct font.  */
 
 struct macfont_info
 {
@@ -88,11 +96,11 @@ struct macfont_info
   struct macfont_cache *cache;
   struct macfont_metrics **metrics;
   short metrics_nrows;
-  unsigned synthetic_italic_p : 1;
-  unsigned synthetic_bold_p : 1;
+  bool_bf synthetic_italic_p : 1;
+  bool_bf synthetic_bold_p : 1;
   unsigned spacing : 2;
   unsigned antialias : 2;
-  unsigned color_bitmap_p : 1;
+  bool_bf color_bitmap_p : 1;
 };
 
 /* Values for the `spacing' member in `struct macfont_info'.  */
@@ -229,8 +237,7 @@ mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
     unichar characters[] = {0xfffd};
     NSString *string =
       [NSString stringWithCharacters:characters
-                             length:(sizeof (characters)
-                                     / sizeof (characters[0]))];
+                             length:ARRAYELTS (characters)];
     NSGlyphInfo *glyphInfo =
       [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
                                         collection:collection
@@ -366,7 +373,7 @@ mac_font_shape_1 (NSFont *font, NSString *string,
   if (!(textStorage && layoutManager && textContainer))
     {
       [textStorage release];
-      
+
       return 0;
     }
 
@@ -623,20 +630,24 @@ get_cgcolor(unsigned long idx, struct frame *f)
   return cgColor;
 }
 
-#define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, s)                \
-  CGContextSetFillColorWithColor (context,                              \
-                                  get_cgcolor (NS_FACE_FOREGROUND (s->face), \
-                                               s->f))
-
-#define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, s)                \
-  CGContextSetFillColorWithColor (context,                              \
-                                  get_cgcolor (NS_FACE_BACKGROUND (s->face), \
-                                               s->f))
-
-#define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, s)              \
-  CGContextSetStrokeColorWithColor (context,                            \
-                                    get_cgcolor (NS_FACE_FOREGROUND (s->face),\
-                                                 s->f))
+#define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f)        \
+  do {                                                                  \
+    CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f);    \
+    CGContextSetFillColorWithColor (context, refcol_) ;                 \
+    CGColorRelease (refcol_);                                           \
+  } while (0)
+#define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f)        \
+  do {                                                                  \
+    CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f);    \
+    CGContextSetFillColorWithColor (context, refcol_);                  \
+    CGColorRelease (refcol_);                                           \
+  } while (0)
+#define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f)      \
+  do {                                                                  \
+    CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f);    \
+    CGContextSetStrokeColorWithColor (context, refcol_);                \
+    CGColorRelease (refcol_);                                           \
+  } while (0)
 
 \f
 /* Mac font driver.  */
@@ -669,7 +680,7 @@ static struct
     { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
     { "iso8859-16", { 0x00A0, 0x0218}},
     { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
-    { "big5-0", { /* 0xF6B1 in ftfont.c */ 0xF7E5 }, CFSTR ("zh-Hant") },
+    { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
     { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
     { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
     { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
@@ -693,9 +704,31 @@ static struct
     { NULL }
   };
 
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
+static const struct
+{
+  CFStringRef language;
+  CFStringRef font_names[3];
+} macfont_language_default_font_names[] = {
+  { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
+                   CFSTR ("HiraKakuPro-W3"),  /* 10.4 */
+                   NULL }},
+  { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
+                   CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
+                   NULL }},
+  { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
+                        CFSTR ("STXihei"),         /* 10.4 - 10.5 */
+                        NULL }},
+  { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
+                        CFSTR ("LiHeiPro"),        /* 10.4 - 10.5 */
+                        NULL }},
+  { NULL }
+};
+#endif
+
 static CGFloat macfont_antialias_threshold;
 
-void
+static void
 macfont_update_antialias_threshold (void)
 {
   int threshold;
@@ -743,7 +776,7 @@ cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
   SInt64 sint64_value;
 
   /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
-     OS 10.6 when the value is greater than or equal to 1 << 31.  */
+     OS 10.6 when the value is greater than or equal to 1 << 31.  */
   if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
     {
       *sym_traits = (FontSymbolicTraits) sint64_value;
@@ -792,7 +825,7 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc,
            {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
       int i;
 
-      for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
+      for (i = 0; i < ARRAYELTS (numeric_traits); i++)
        {
          num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
          if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
@@ -1159,7 +1192,7 @@ struct macfont_cache
 
     /* The cached glyph for a character c is stored as the (c %
        NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
-       NGLYPHS_IN_VALUE).  However, the glyph for a BMP characrer c is
+       NGLYPHS_IN_VALUE).  However, the glyph for a BMP character c is
        not stored here if row_nkeys_or_perm[c / 256] >=
        ROW_PERM_OFFSET.  */
     CFMutableDictionaryRef dictionary;
@@ -1218,8 +1251,7 @@ macfont_lookup_cache (CFStringRef key)
             CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
             for this font is correct for non-BMP characters on Mac OS
             X 10.5, anyway.  */
-         if (CFStringCompare (key, CFSTR ("LastResort"), 0)
-             == kCFCompareEqualTo)
+         if (CFEqual (key, CFSTR ("LastResort")))
            {
              CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
 
@@ -1518,7 +1550,7 @@ static Lisp_Object macfont_match (struct frame *, Lisp_Object);
 static Lisp_Object macfont_list_family (struct frame *);
 static void macfont_free_entity (Lisp_Object);
 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
-static void macfont_close (struct frame *, struct font *);
+static void macfont_close (struct font *);
 static int macfont_has_char (Lisp_Object, int);
 static unsigned macfont_encode_char (struct font *, int);
 static int macfont_text_extents (struct font *, unsigned int *, int,
@@ -1874,7 +1906,7 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
   if (! traits)
     goto err;
 
-  for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
+  for (i = 0; i < ARRAYELTS (numeric_traits); i++)
     {
       tmp = AREF (spec, numeric_traits[i].index);
       if (INTEGERP (tmp))
@@ -2045,33 +2077,7 @@ macfont_list (struct frame *f, Lisp_Object spec)
   if (! attributes)
     goto finish;
 
-  charset = ((CFCharacterSetRef)
-            CFDictionaryGetValue (attributes,
-                                  MAC_FONT_CHARACTER_SET_ATTRIBUTE));
-  if (charset)
-    {
-      CFRetain (charset);
-      CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
-    }
-  else
-    {
-      val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
-      if (! NILP (val))
-       {
-         val = assq_no_quit (XCDR (val), Vscript_representative_chars);
-         if (CONSP (val) && VECTORP (XCDR (val)))
-           chars = XCDR (val);
-       }
-      val = Qnil;
-    }
-
-  languages = ((CFArrayRef)
-              CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE));
-  if (languages)
-    {
-      CFRetain (languages);
-      CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
-    }
+  languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
 
   if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
     spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
@@ -2155,6 +2161,31 @@ macfont_list (struct frame *f, Lisp_Object spec)
        }
     }
 
+  charset = CFDictionaryGetValue (attributes,
+                                 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
+  if (charset)
+    {
+      CFRetain (charset);
+      CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
+    }
+  else
+    {
+      val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
+      if (! NILP (val))
+       {
+         val = assq_no_quit (XCDR (val), Vscript_representative_chars);
+         if (CONSP (val) && VECTORP (XCDR (val)))
+           chars = XCDR (val);
+       }
+      val = Qnil;
+    }
+
+  if (languages)
+    {
+      CFRetain (languages);
+      CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
+    }
+
   val = Qnil;
   extra = AREF (spec, FONT_EXTRA_INDEX);
   families_count = CFArrayGetCount (families);
@@ -2178,27 +2209,26 @@ macfont_list (struct frame *f, Lisp_Object spec)
         10.7 returns NULL if pat_desc represents the LastResort font.
         So we use CTFontDescriptorCreateMatchingFontDescriptor (no
         trailing "s") for such a font.  */
-      if (CFStringCompare (family_name, CFSTR ("LastResort"), 0)
-         != kCFCompareEqualTo)
-       descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
-                                                                     NULL);
+      if (!CFEqual (family_name, CFSTR ("LastResort")))
+       descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
+                                                                     NULL);
       else
-       {
-         FontDescriptorRef lr_desc =
-           mac_font_descriptor_create_matching_font_descriptor (pat_desc,
-                                                                NULL);
-         if (lr_desc)
-           {
-             descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
-                                    &kCFTypeArrayCallBacks);
-             CFRelease (lr_desc);
-           }
-         else
-           descs = NULL;
-       }
+       {
+         FontDescriptorRef lr_desc =
+           mac_font_descriptor_create_matching_font_descriptor (pat_desc,
+                                                                NULL);
+         if (lr_desc)
+           {
+             descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
+                                    &kCFTypeArrayCallBacks);
+             CFRelease (lr_desc);
+           }
+         else
+           descs = NULL;
+       }
       CFRelease (pat_desc);
       if (! descs)
-       goto err;
+       goto err;
 
       descs_count = CFArrayGetCount (descs);
       if (descs_count == 0
@@ -2465,7 +2495,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);
-  
+
   val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
   if (CONSP (val) && EQ (XCDR (val), make_number (1)))
     macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
@@ -2539,12 +2569,9 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
       family_name = mac_font_copy_family_name (macfont);
       if (family_name)
        {
-         if ((CFStringCompare (family_name, CFSTR ("Courier"), 0)
-              == kCFCompareEqualTo)
-             || (CFStringCompare (family_name, CFSTR ("Helvetica"), 0)
-                 == kCFCompareEqualTo)
-             || (CFStringCompare (family_name, CFSTR ("Times"), 0)
-                 == kCFCompareEqualTo))
+         if (CFEqual (family_name, CFSTR ("Courier"))
+             || CFEqual (family_name, CFSTR ("Helvetica"))
+             || CFEqual (family_name, CFSTR ("Times")))
            ascent += (ascent + descent) * .15f;
          else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
            {
@@ -2580,7 +2607,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
 }
 
 static void
-macfont_close (struct frame * f, struct font *font)
+macfont_close (struct font *font)
 {
   struct macfont_info *macfont_info = (struct macfont_info *) font;
   int i;
@@ -2667,7 +2694,7 @@ macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
     }
   unblock_input ();
 
-  if (metrics) 
+  if (metrics)
     metrics->width = width;
 
   return width;
@@ -2679,69 +2706,70 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
 {
   struct frame * f = s->f;
   struct macfont_info *macfont_info = (struct macfont_info *) s->font;
-  FontRef macfont = macfont_info->macfont;
+  CGRect background_rect;
+  CGPoint text_position;
+  CGGlyph *glyphs;
+  CGPoint *positions;
+  CGFloat font_size = mac_font_get_size (macfont_info->macfont);
+  bool no_antialias_p =
+    (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
+     || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
+        && font_size <= macfont_antialias_threshold));
+  int len = to - from;
+  struct face *face = s->face;
   CGContextRef context;
-  BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
-  int end = isComposite ? s->cmp_to : s->nchars;
-  int len = end - s->cmp_from;
-  int i;
 
   block_input ();
 
+  if (with_background)
+    background_rect = CGRectMake (x, y - FONT_BASE (s->font),
+                                  s->width, FONT_HEIGHT (s->font));
+ else
+    background_rect = CGRectNull;
+  
+  text_position = CGPointMake (x, -y);
+  glyphs = xmalloc (sizeof (CGGlyph) * len);
+  {
+    CGFloat advance_delta;
+    int i;
+    CGFloat total_width = 0;
+
+    positions = xmalloc (sizeof (CGPoint) * len);
+    for (i = 0; i < len; i++)
+      {
+       int width;
+
+       glyphs[i] = s->char2b[from + i];
+       width = (s->padding_p ? 1
+                : macfont_glyph_extents (s->font, glyphs[i],
+                                         NULL, &advance_delta,
+                                         no_antialias_p));
+       positions[i].x = total_width + advance_delta;
+       positions[i].y = 0;
+       total_width += width;
+      }
+  }
+
   context = [[NSGraphicsContext currentContext] graphicsPort];
   CGContextSaveGState (context);
 
-#if 0
-  if (s->num_clips > 0)
+  if (!CGRectIsNull (background_rect))
     {
-      CGRect clips[2];
-
-      for (i = 0; i < s->num_clips; i++)
-       clips[i] = mac_rect_make (f, s->clip[i].left, s->clip[i].top,
-                                 s->clip[i].right - s->clip[i].left,
-                                 s->clip[i].bottom - s->clip[i].top);
-      CGContextClipToRects (context, clips, s->num_clips);
-    }
-#endif
-
-  if (with_background)
-    {
-      CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, s);
-      CGContextFillRect (context,
-                        CGRectMake (x, y,
-                                     s->width, FONT_HEIGHT (s->font)));
+      if (s->hl == DRAW_MOUSE_FACE) 
+        {
+          face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
+          if (!face)
+            face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+        }
+      CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
+      CGContextFillRects (context, &background_rect, 1);
     }
 
   if (macfont_info->cgfont)
     {
-      CGGlyph *glyphs = alloca (sizeof (CGGlyph) * len);
-      CGPoint *positions = alloca (sizeof (CGPoint) * len);
-      CGFloat total_width = 0;
-      CGFloat font_size = mac_font_get_size (macfont);
       CGAffineTransform atfm;
-      CGFloat advance_delta = 0;
-      int y_draw = -s->ybase;
-      int no_antialias_p =
-       (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
-        || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
-            && font_size <= macfont_antialias_threshold));
-
-      for (i = 0; i < len; i++)
-       {
-         int width;
-         glyphs[i] = *(s->char2b + s->cmp_from + i);
-         width = (s->padding_p ? 1
-                  : macfont_glyph_extents (s->font, glyphs[i],
-                                           NULL, &advance_delta,
-                                           no_antialias_p));
-         positions[i].x = total_width + advance_delta;
-         positions[i].y = 0;
-         total_width += width;
-       }
-
       CGContextScaleCTM (context, 1, -1);
-      CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, s);
+      CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
       if (macfont_info->synthetic_italic_p)
        atfm = synthetic_italic_atfm;
       else
@@ -2750,13 +2778,13 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
        {
          CGContextSetTextDrawingMode (context, kCGTextFillStroke);
          CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
-         CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, s);
+         CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
        }
       if (no_antialias_p)
        CGContextSetShouldAntialias (context, false);
 
       CGContextSetTextMatrix (context, atfm);
-      CGContextSetTextPosition (context, x, y_draw);
+      CGContextSetTextPosition (context, text_position.x, text_position.y);
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
       if (macfont_info->color_bitmap_p
@@ -2767,7 +2795,8 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
        {
          if (len > 0)
            {
-             CTFontDrawGlyphs (macfont, glyphs, positions, len, context);
+             CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
+                                context);
            }
        }
       else
@@ -2779,6 +2808,9 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
        }
     }
 
+
+  xfree (glyphs);
+  xfree (positions);
   CGContextRestoreGState (context);
 
   unblock_input ();
@@ -2786,7 +2818,7 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
   return len;
 }
 
-Lisp_Object
+static Lisp_Object
 macfont_shape (Lisp_Object lgstring)
 {
   struct font *font;
@@ -2817,7 +2849,6 @@ macfont_shape (Lisp_Object lgstring)
     }
 
   len = i;
-  assume (len <= TYPE_MAXIMUM (EMACS_INT) - 2);
 
   if (INT_MAX / 2 < len)
     memory_full (SIZE_MAX);
@@ -2990,7 +3021,7 @@ struct non_default_uvs_table
 #define BUINT32_VALUE(lval)    OSReadBigInt32 (&(lval), 0)
 
 /* Return UVS subtable for the specified FONT.  If the subtable is not
-   found or ill-formated, then return NULL.  */
+   found or ill-formatted, then return NULL.  */
 
 static CFDataRef
 mac_font_copy_uvs_table (FontRef font)
@@ -3324,49 +3355,80 @@ mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
 
   if (charset_string && CFStringGetLength (charset_string) > 0)
     {
-      CFAttributedStringRef attr_string = NULL;
-      CTLineRef ctline = NULL;
-      CFDictionaryRef attrs =
-       CFDictionaryCreate (NULL, NULL, NULL, 0,
-                           &kCFTypeDictionaryKeyCallBacks,
-                           &kCFTypeDictionaryValueCallBacks);
+      CFStringRef keys[] = {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
+       kCTLanguageAttributeName
+#else
+       CFSTR ("NSLanguage")
+#endif
+      };
+      CFTypeRef values[] = {NULL};
+      CFIndex num_values = 0;
+      CFArrayRef languages
+       = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
 
-      if (attrs)
+      if (languages && CFArrayGetCount (languages) > 0)
        {
-         attr_string = CFAttributedStringCreate (NULL, charset_string, attrs);
-         CFRelease (attrs);
-       }
-      if (attr_string)
-       {
-         ctline = CTLineCreateWithAttributedString (attr_string);
-         CFRelease (attr_string);
+         if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
+           values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
+         else
+           {
+             CFCharacterSetRef charset =
+               CFDictionaryGetValue (attributes,
+                                     MAC_FONT_CHARACTER_SET_ATTRIBUTE);
+
+             result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
+           }
        }
-      if (ctline)
+      if (result == NULL)
        {
-         CFArrayRef runs = CTLineGetGlyphRuns (ctline);
-         CFIndex i, nruns = CFArrayGetCount (runs);
-         CTFontRef font;
-
-         for (i = 0; i < nruns; i++)
+         CFAttributedStringRef attr_string = NULL;
+         CTLineRef ctline = NULL;
+         CFDictionaryRef attrs
+           = CFDictionaryCreate (NULL, (const void **) keys,
+                                 (const void **) values, num_values,
+                                 &kCFTypeDictionaryKeyCallBacks,
+                                 &kCFTypeDictionaryValueCallBacks);
+
+         if (attrs)
+           {
+             attr_string = CFAttributedStringCreate (NULL, charset_string,
+                                                     attrs);
+             CFRelease (attrs);
+           }
+         if (attr_string)
+           {
+             ctline = CTLineCreateWithAttributedString (attr_string);
+             CFRelease (attr_string);
+           }
+         if (ctline)
            {
-             CTRunRef run = CFArrayGetValueAtIndex (runs, i);
-             CFDictionaryRef attributes = CTRunGetAttributes (run);
-             CTFontRef font_in_run;
+             CFArrayRef runs = CTLineGetGlyphRuns (ctline);
+             CFIndex i, nruns = CFArrayGetCount (runs);
+             CTFontRef font;
 
-             if (attributes == NULL)
-               break;
-             font_in_run =
-               CFDictionaryGetValue (attributes, kCTFontAttributeName);
-             if (font_in_run == NULL)
-               break;
-             if (i == 0)
-               font = font_in_run;
-             else if (!mac_ctfont_equal_in_postscript_name (font, font_in_run))
-               break;
+             for (i = 0; i < nruns; i++)
+               {
+                 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
+                 CFDictionaryRef attributes = CTRunGetAttributes (run);
+                 CTFontRef font_in_run;
+
+                 if (attributes == NULL)
+                   break;
+                 font_in_run =
+                   CFDictionaryGetValue (attributes, kCTFontAttributeName);
+                 if (font_in_run == NULL)
+                   break;
+                 if (i == 0)
+                   font = font_in_run;
+                 else if (!mac_ctfont_equal_in_postscript_name (font,
+                                                                font_in_run))
+                   break;
+               }
+             if (nruns > 0 && i == nruns)
+               result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
+             CFRelease (ctline);
            }
-         if (nruns > 0 && i == nruns)
-           result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
-         CFRelease (ctline);
        }
     }
 
@@ -3487,7 +3549,7 @@ mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
       name2 = CTFontCopyPostScriptName (font2);
       if (name2)
        {
-         result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo);
+         result = CFEqual (name1, name2);
          CFRelease (name2);
        }
       CFRelease (name1);
@@ -3513,7 +3575,7 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string,
     {
       attributes = CFDictionaryCreate (NULL, (const void **) keys,
                                       (const void **) values,
-                                      sizeof (keys) / sizeof (keys[0]),
+                                       ARRAYELTS (keys),
                                       &kCFTypeDictionaryKeyCallBacks,
                                       &kCFTypeDictionaryValueCallBacks);
       CFRelease (values[1]);
@@ -3560,7 +3622,7 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string,
   return ctline;
 }
 
-CFIndex
+static CFIndex
 mac_ctfont_shape (CTFontRef font, CFStringRef string,
                  struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
 {
@@ -3713,7 +3775,7 @@ mac_ctfont_shape (CTFontRef font, CFStringRef string,
    created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
    10.6.3.  For now, we use the NSGlyphInfo version instead.  */
 #if USE_CT_GLYPH_INFO
-CGGlyph
+static CGGlyph
 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
                              CGFontIndex cid)
 {
@@ -3724,8 +3786,8 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
   CTLineRef ctline = NULL;
 
   string = CFStringCreateWithCharacters (NULL, characters,
-                                        sizeof (characters)
-                                        / sizeof (characters[0]));
+                                         ARRAYELTS (characters));
+
   if (string)
     {
       CTGlyphInfoRef glyph_info =
@@ -3740,7 +3802,7 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
 
          attributes = CFDictionaryCreate (NULL, (const void **) keys,
                                           (const void **) values,
-                                          sizeof (keys) / sizeof (keys[0]),
+                                           ARRAYELTS (keys),
                                           &kCFTypeDictionaryKeyCallBacks,
                                           &kCFTypeDictionaryValueCallBacks);
          CFRelease (glyph_info);
@@ -3806,7 +3868,7 @@ mac_font_family_group (CFStringRef family)
     }
 }
 
-CFComparisonResult
+static CFComparisonResult
 mac_font_family_compare (const void *val1, const void *val2, void *context)
 {
   CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
@@ -3822,6 +3884,141 @@ mac_font_family_compare (const void *val1, const void *val2, void *context)
 }
 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
 
+static CFArrayRef
+mac_font_copy_default_descriptors_for_language (CFStringRef language)
+{
+  CFArrayRef result = NULL;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
+  if (CTFontCopyDefaultCascadeListForLanguages != NULL)
+#endif
+    {
+      CTFontRef user_font =
+       CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
+
+      if (user_font)
+       {
+         CFArrayRef languages =
+           CFArrayCreate (NULL, (const void **) &language, 1,
+                          &kCFTypeArrayCallBacks);
+
+         if (languages)
+           {
+             result = CTFontCopyDefaultCascadeListForLanguages (user_font,
+                                                                languages);
+             CFRelease (languages);
+           }
+         CFRelease (user_font);
+       }
+    }
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
+  else         /* CTFontCopyDefaultCascadeListForLanguages == NULL */
+#endif
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
+    {
+      CFIndex i;
+
+      for (i = 0; macfont_language_default_font_names[i].language; i++)
+       {
+         if (CFEqual (macfont_language_default_font_names[i].language,
+                       language))
+           {
+             CFMutableArrayRef descriptors =
+               CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
+
+             if (descriptors)
+               {
+                 CFIndex j;
+
+                 for (j = 0;
+                      macfont_language_default_font_names[i].font_names[j];
+                      j++)
+                   {
+                     CFDictionaryRef attributes =
+                       CFDictionaryCreate (NULL,
+                                           ((const void **)
+                                            &MAC_FONT_NAME_ATTRIBUTE),
+                                           ((const void **)
+                                            &macfont_language_default_font_names[i].font_names[j]),
+                                           1, &kCFTypeDictionaryKeyCallBacks,
+                                           &kCFTypeDictionaryValueCallBacks);
+
+                     if (attributes)
+                       {
+                         FontDescriptorRef pat_desc =
+                           mac_font_descriptor_create_with_attributes (attributes);
+
+                         if (pat_desc)
+                           {
+                             FontDescriptorRef descriptor =
+                               mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
+
+                             if (descriptor)
+                               {
+                                 CFArrayAppendValue (descriptors, descriptor);
+                                 CFRelease (descriptor);
+                               }
+                             CFRelease (pat_desc);
+                           }
+                         CFRelease (attributes);
+                       }
+                   }
+                 result = descriptors;
+               }
+             break;
+           }
+       }
+    }
+#endif
+
+  return result;
+}
+
+static CFStringRef
+mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
+                                                     CFArrayRef languages)
+{
+  CFStringRef result = NULL;
+  CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
+  CFArrayRef descriptors =
+    mac_font_copy_default_descriptors_for_language (language);
+
+  if (descriptors)
+    {
+      CFIndex i, count = CFArrayGetCount (descriptors);
+
+      for (i = 0; i < count; i++)
+       {
+         FontDescriptorRef 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);
+             if (family)
+               {
+                 if (!CFStringHasPrefix (family, CFSTR ("."))
+                     && !CFEqual (family, CFSTR ("LastResort")))
+                    {
+                     result = family;
+                     break;
+                   }
+                 else
+                   CFRelease (family);
+               }
+           }
+       }
+      CFRelease (descriptors);
+    }
+
+  return result;
+}
+
 void *
 macfont_get_nsctfont (struct font *font)
 {