* net/tramp-adb.el (tramp-adb-handle-process-file): Do not raise
[emacs.git] / src / macfont.m
blob9e3c7e05f3fc020cf5ad51403478ab2a676e7877
1 /* Font driver on Mac OSX Core text.
2    Copyright (C) 2009-2014 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
22 #include <config.h>
24 #include "lisp.h"
25 #include "dispextern.h"
26 #include "frame.h"
27 #include "blockinput.h"
28 #include "character.h"
29 #include "charset.h"
30 #include "composite.h"
31 #include "fontset.h"
32 #include "font.h"
33 #include "termchar.h"
34 #include "nsgui.h"
35 #include "nsterm.h"
36 #include "macfont.h"
37 #include "macuvs.h"
39 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
41 #include <libkern/OSByteOrder.h>
43 static struct font_driver macfont_driver;
45 /* Core Text, for Mac OS X 10.5 and later.  */
46 static Lisp_Object Qmac_ct;
48 static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
49 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
50 static CFArrayRef mac_ctfont_create_available_families (void);
51 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
52 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
53                                                               CTFontRef);
54 static CFComparisonResult mac_font_family_compare (const void *,
55                                                    const void *, void *);
56 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
57                                                          CFArrayRef);
58 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
59 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
60                                  struct mac_glyph_layout *, CFIndex);
61 static CFArrayRef
62 mac_font_copy_default_descriptors_for_language (CFStringRef language);
64 static CFStringRef
65 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
66                                                       CFArrayRef languages);
68 #if USE_CT_GLYPH_INFO
69 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
70                                              CTCharacterCollection,
71                                              CGFontIndex);
72 #endif
74 /* The font property key specifying the font design destination.  The
75    value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
76    text.  (See the documentation of X Logical Font Description
77    Conventions.)  In the Mac font driver, 1 means the screen font is
78    used for calculating some glyph metrics.  You can see the
79    difference with Monaco 8pt or 9pt, for example.  */
80 static Lisp_Object QCdestination;
82 /* The boolean-valued font property key specifying the use of
83    leading.  */
84 static Lisp_Object QCminspace;
86 struct macfont_metrics;
88 /* The actual structure for Mac font that can be cast to struct font.  */
90 struct macfont_info
92   struct font font;
93   FontRef macfont;
94   CGFontRef cgfont;
95   ScreenFontRef screen_font;
96   struct macfont_cache *cache;
97   struct macfont_metrics **metrics;
98   short metrics_nrows;
99   bool_bf synthetic_italic_p : 1;
100   bool_bf synthetic_bold_p : 1;
101   unsigned spacing : 2;
102   unsigned antialias : 2;
103   bool_bf color_bitmap_p : 1;
106 /* Values for the `spacing' member in `struct macfont_info'.  */
108 enum
109   {
110     MACFONT_SPACING_PROPORTIONAL,
111     MACFONT_SPACING_MONO,
112     MACFONT_SPACING_SYNTHETIC_MONO,
113   };
115 /* Values for the `antialias' member in `struct macfont_info'.  */
117 enum
118   {
119     MACFONT_ANTIALIAS_DEFAULT,
120     MACFONT_ANTIALIAS_OFF,
121     MACFONT_ANTIALIAS_ON,
122   };
124 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
125 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200};  /* FC_WEIGHT_BOLD */
126 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
128 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
129 static const CGFloat synthetic_bold_factor = 0.024;
131 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
132                                                         FontSymbolicTraits *);
133 static void macfont_store_descriptor_attributes (FontDescriptorRef,
134                                                  Lisp_Object);
135 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
136                                               Lisp_Object,
137                                               FontSymbolicTraits);
138 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
139 static int macfont_glyph_extents (struct font *, CGGlyph,
140                                   struct font_metrics *, CGFloat *, int);
141 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
142 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
143                                                          CFCharacterSetRef,
144                                                          Lisp_Object,
145                                                          CFArrayRef);
146 static CFIndex macfont_closest_traits_index (CFArrayRef,
147                                              FontSymbolicTraits);
148 static CFDataRef mac_font_copy_uvs_table (FontRef);
149 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
150                                               const UTF32Char [],
151                                               CGGlyph [], CFIndex);
153 /* From CFData to a lisp string.  Always returns a unibyte string.  */
155 static Lisp_Object
156 cfdata_to_lisp (CFDataRef data)
158   CFIndex len = CFDataGetLength (data);
159   Lisp_Object result = make_uninit_string (len);
161   CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
163   return result;
168 /* From CFString to a lisp string.  Returns a unibyte string
169    containing a UTF-8 byte sequence.  */
171 static Lisp_Object
172 cfstring_to_lisp_nodecode (CFStringRef string)
174   Lisp_Object result = Qnil;
175   CFDataRef data;
176   const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
178   if (s)
179     {
180       CFIndex i, length = CFStringGetLength (string);
182       for (i = 0; i < length; i++)
183         if (CFStringGetCharacterAtIndex (string, i) == 0)
184           break;
186       if (i == length)
187         return make_unibyte_string (s, strlen (s));
188     }
190   data = CFStringCreateExternalRepresentation (NULL, string,
191                                                kCFStringEncodingUTF8, '?');
192   if (data)
193     {
194       result = cfdata_to_lisp (data);
195       CFRelease (data);
196     }
198   return result;
201 /* Lisp string containing a UTF-8 byte sequence to CFString.  Unlike
202    cfstring_create_with_utf8_cstring, this function preserves NUL
203    characters.  */
205 static CFStringRef
206 cfstring_create_with_string_noencode (Lisp_Object s)
208   CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
209                                                 kCFStringEncodingUTF8, false);
211   if (string == NULL)
212     /* Failed to interpret as UTF 8.  Fall back on Mac Roman.  */
213     string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
214                                       kCFStringEncodingMacRoman, false);
216   return string;
219 static CGFloat
220 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
222   NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
224   return advancement.width;
227 static CGGlyph
228 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
229                             CGFontIndex cid)
231 #if USE_CT_GLYPH_INFO
232   return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
233 #else
234   {
235     CGGlyph result = kCGFontIndexInvalid;
236     NSFont *nsFont = (NSFont *) font;
237     unichar characters[] = {0xfffd};
238     NSString *string =
239       [NSString stringWithCharacters:characters
240                               length:(sizeof (characters)
241                                       / sizeof (characters[0]))];
242     NSGlyphInfo *glyphInfo =
243       [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
244                                          collection:collection
245                                          baseString:string];
246     NSDictionary *attributes =
247       [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
248                     glyphInfo,NSGlyphInfoAttributeName,nil];
249     NSTextStorage *textStorage =
250       [[NSTextStorage alloc] initWithString:string
251                                  attributes:attributes];
252     NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
253     NSTextContainer *textContainer = [[NSTextContainer alloc] init];
254     NSFont *fontInTextStorage;
256     [layoutManager addTextContainer:textContainer];
257     [textContainer release];
258     [textStorage addLayoutManager:layoutManager];
259     [layoutManager release];
261     /* Force layout.  */
262     (void) [layoutManager glyphRangeForTextContainer:textContainer];
264     fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
265                                 effectiveRange:NULL];
266     if (fontInTextStorage == nsFont
267         || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
268       {
269         NSGlyph glyph = [layoutManager glyphAtIndex:0];
271         if (glyph < [nsFont numberOfGlyphs])
272           result = glyph;
273       }
275     [textStorage release];
277     return result;
278   }
280 #endif
282 static ScreenFontRef
283 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
285   NSFont *result, *font;
287   font = [NSFont fontWithName:((NSString *) name) size:size];
288   result = [font screenFont];
290   return (ScreenFontRef)[result retain];
294 static Boolean
295 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
296                              CGFloat *descent, CGFloat *leading)
298   NSFont *nsFont = [(NSFont *)font printerFont];
299   NSTextStorage *textStorage;
300   NSLayoutManager *layoutManager;
301   NSTextContainer *textContainer;
302   NSRect usedRect;
303   NSPoint spaceLocation;
304   CGFloat descender;
306   textStorage = [[NSTextStorage alloc] initWithString:@" "];
307   layoutManager = [[NSLayoutManager alloc] init];
308   textContainer = [[NSTextContainer alloc] init];
310   [textStorage setFont:nsFont];
311   [textContainer setLineFragmentPadding:0];
312   [layoutManager setUsesScreenFonts:YES];
314   [layoutManager addTextContainer:textContainer];
315   [textContainer release];
316   [textStorage addLayoutManager:layoutManager];
317   [layoutManager release];
319   if (!(textStorage && layoutManager && textContainer))
320     {
321       [textStorage release];
323       return false;
324     }
326   usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
327                                                  effectiveRange:NULL];
328   spaceLocation = [layoutManager locationForGlyphAtIndex:0];
329   [textStorage release];
331   *ascent = spaceLocation.y;
332   *descent = NSHeight (usedRect) - spaceLocation.y;
333   *leading = 0;
334   descender = [nsFont descender];
335   if (- descender < *descent)
336     {
337       *leading = *descent + descender;
338       *descent = - descender;
339     }
341   return true;
344 static CFIndex
345 mac_font_shape_1 (NSFont *font, NSString *string,
346                   struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
347                   BOOL screen_font_p)
349   NSUInteger i;
350   CFIndex result = 0;
351   NSTextStorage *textStorage;
352   NSLayoutManager *layoutManager;
353   NSTextContainer *textContainer;
354   NSUInteger stringLength;
355   NSPoint spaceLocation;
356   NSUInteger used, numberOfGlyphs;
358   textStorage = [[NSTextStorage alloc] initWithString:string];
359   layoutManager = [[NSLayoutManager alloc] init];
360   textContainer = [[NSTextContainer alloc] init];
362   /* Append a trailing space to measure baseline position.  */
363   [textStorage appendAttributedString:([[[NSAttributedString alloc]
364                                           initWithString:@" "] autorelease])];
365   [textStorage setFont:font];
366   [textContainer setLineFragmentPadding:0];
367   [layoutManager setUsesScreenFonts:screen_font_p];
369   [layoutManager addTextContainer:textContainer];
370   [textContainer release];
371   [textStorage addLayoutManager:layoutManager];
372   [layoutManager release];
374   if (!(textStorage && layoutManager && textContainer))
375     {
376       [textStorage release];
378       return 0;
379     }
381   stringLength = [string length];
383   /* Force layout.  */
384   (void) [layoutManager glyphRangeForTextContainer:textContainer];
386   spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
388   /* Remove the appended trailing space because otherwise it may
389      generate a wrong result for a right-to-left text.  */
390   [textStorage beginEditing];
391   [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
392   [textStorage endEditing];
393   (void) [layoutManager glyphRangeForTextContainer:textContainer];
395   i = 0;
396   while (i < stringLength)
397     {
398       NSRange range;
399       NSFont *fontInTextStorage =
400         [textStorage attribute:NSFontAttributeName atIndex:i
401                      longestEffectiveRange:&range
402                        inRange:(NSMakeRange (0, stringLength))];
404       if (!(fontInTextStorage == font
405             || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
406         break;
407       i = NSMaxRange (range);
408     }
409   if (i < stringLength)
410     /* Make the test `used <= glyph_len' below fail if textStorage
411        contained some fonts other than the specified one.  */
412     used = glyph_len + 1;
413   else
414     {
415       NSRange range = NSMakeRange (0, stringLength);
417       range = [layoutManager glyphRangeForCharacterRange:range
418                                     actualCharacterRange:NULL];
419       numberOfGlyphs = NSMaxRange (range);
420       used = numberOfGlyphs;
421       for (i = 0; i < numberOfGlyphs; i++)
422         if ([layoutManager notShownAttributeForGlyphAtIndex:i])
423           used--;
424     }
426   if (0 < used && used <= glyph_len)
427     {
428       NSUInteger glyphIndex, prevGlyphIndex;
429       unsigned char bidiLevel;
430       NSUInteger *permutation;
431       NSRange compRange, range;
432       CGFloat totalAdvance;
434       glyphIndex = 0;
435       while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
436         glyphIndex++;
438       /* For now we assume the direction is not changed within the
439          string.  */
440       [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
441                                glyphs:NULL characterIndexes:NULL
442                     glyphInscriptions:NULL elasticBits:NULL
443                            bidiLevels:&bidiLevel];
444       if (bidiLevel & 1)
445         permutation = xmalloc (sizeof (NSUInteger) * used);
446       else
447         permutation = NULL;
449 #define RIGHT_TO_LEFT_P permutation
451       /* Fill the `comp_range' member of struct mac_glyph_layout, and
452          setup a permutation for right-to-left text.  */
453       compRange = NSMakeRange (0, 0);
454       for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
455            range.length++)
456         {
457           struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
458           NSUInteger characterIndex =
459             [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
461           gl->string_index = characterIndex;
463           if (characterIndex >= NSMaxRange (compRange))
464             {
465               compRange.location = NSMaxRange (compRange);
466               do
467                 {
468                   NSRange characterRange =
469                     [string
470                       rangeOfComposedCharacterSequenceAtIndex:characterIndex];
472                   compRange.length =
473                     NSMaxRange (characterRange) - compRange.location;
474                   [layoutManager glyphRangeForCharacterRange:compRange
475                                         actualCharacterRange:&characterRange];
476                   characterIndex = NSMaxRange (characterRange) - 1;
477                 }
478               while (characterIndex >= NSMaxRange (compRange));
480               if (RIGHT_TO_LEFT_P)
481                 for (i = 0; i < range.length; i++)
482                   permutation[range.location + i] = NSMaxRange (range) - i - 1;
484               range = NSMakeRange (NSMaxRange (range), 0);
485             }
487           gl->comp_range.location = compRange.location;
488           gl->comp_range.length = compRange.length;
490           while (++glyphIndex < numberOfGlyphs)
491             if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
492               break;
493         }
494       if (RIGHT_TO_LEFT_P)
495         for (i = 0; i < range.length; i++)
496           permutation[range.location + i] = NSMaxRange (range) - i - 1;
498       /* Then fill the remaining members.  */
499       glyphIndex = prevGlyphIndex = 0;
500       while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
501         glyphIndex++;
503       if (!RIGHT_TO_LEFT_P)
504         totalAdvance = 0;
505       else
506         {
507           NSUInteger nrects;
508           NSRect *glyphRects =
509             [layoutManager
510               rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
511               withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
512                      inTextContainer:textContainer rectCount:&nrects];
514           totalAdvance = NSMaxX (glyphRects[0]);
515         }
517       for (i = 0; i < used; i++)
518         {
519           struct mac_glyph_layout *gl;
520           NSPoint location;
521           NSUInteger nextGlyphIndex;
522           NSRange glyphRange;
523           NSRect *glyphRects;
524           NSUInteger nrects;
526           if (!RIGHT_TO_LEFT_P)
527             gl = glyph_layouts + i;
528           else
529             {
530               NSUInteger dest = permutation[i];
532               gl = glyph_layouts + dest;
533               if (i < dest)
534                 {
535                   CFIndex tmp = gl->string_index;
537                   gl->string_index = glyph_layouts[i].string_index;
538                   glyph_layouts[i].string_index = tmp;
539                 }
540             }
541           gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
543           location = [layoutManager locationForGlyphAtIndex:glyphIndex];
544           gl->baseline_delta = spaceLocation.y - location.y;
546           for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
547                nextGlyphIndex++)
548             if (![layoutManager
549                    notShownAttributeForGlyphAtIndex:nextGlyphIndex])
550               break;
552           if (!RIGHT_TO_LEFT_P)
553             {
554               CGFloat maxX;
556               if (prevGlyphIndex == 0)
557                 glyphRange = NSMakeRange (0, nextGlyphIndex);
558               else
559                 glyphRange = NSMakeRange (glyphIndex,
560                                           nextGlyphIndex - glyphIndex);
561               glyphRects =
562                 [layoutManager
563                   rectArrayForGlyphRange:glyphRange
564                   withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
565                          inTextContainer:textContainer rectCount:&nrects];
566               maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
567               gl->advance_delta = location.x - totalAdvance;
568               gl->advance = maxX - totalAdvance;
569               totalAdvance = maxX;
570             }
571           else
572             {
573               CGFloat minX;
575               if (nextGlyphIndex == numberOfGlyphs)
576                 glyphRange = NSMakeRange (prevGlyphIndex,
577                                           numberOfGlyphs - prevGlyphIndex);
578               else
579                 glyphRange = NSMakeRange (prevGlyphIndex,
580                                           glyphIndex + 1 - prevGlyphIndex);
581               glyphRects =
582                 [layoutManager
583                   rectArrayForGlyphRange:glyphRange
584                   withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
585                          inTextContainer:textContainer rectCount:&nrects];
586               minX = min (NSMinX (glyphRects[0]), totalAdvance);
587               gl->advance = totalAdvance - minX;
588               totalAdvance = minX;
589               gl->advance_delta = location.x - totalAdvance;
590             }
592           prevGlyphIndex = glyphIndex + 1;
593           glyphIndex = nextGlyphIndex;
594         }
596       if (RIGHT_TO_LEFT_P)
597         xfree (permutation);
599 #undef RIGHT_TO_LEFT_P
601       result = used;
602    }
603  [textStorage release];
605   return result;
608 static CFIndex
609 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
610                        struct mac_glyph_layout *glyph_layouts,
611                        CFIndex glyph_len)
613   return mac_font_shape_1 ([(NSFont *)font printerFont],
614                            (NSString *) string,
615                            glyph_layouts, glyph_len, YES);
618 static CGColorRef
619 get_cgcolor(unsigned long idx, struct frame *f)
621   NSColor *nsColor = ns_lookup_indexed_color (idx, f);
622   [nsColor set];
623   CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
624   NSInteger noc = [nsColor numberOfComponents];
625   CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
626   CGColorRef cgColor;
628   [nsColor getComponents: components];
629   cgColor = CGColorCreate (colorSpace, components);
630   xfree (components);
631   return cgColor;
634 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f)        \
635   do {                                                                  \
636     CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f);    \
637     CGContextSetFillColorWithColor (context, refcol_) ;                 \
638     CGColorRelease (refcol_);                                           \
639   } while (0)
640 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f)        \
641   do {                                                                  \
642     CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f);    \
643     CGContextSetFillColorWithColor (context, refcol_);                  \
644     CGColorRelease (refcol_);                                           \
645   } while (0)
646 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f)      \
647   do {                                                                  \
648     CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f);    \
649     CGContextSetStrokeColorWithColor (context, refcol_);                \
650     CGColorRelease (refcol_);                                           \
651   } while (0)
654 /* Mac font driver.  */
656 static struct
658   /* registry name */
659   const char *name;
660   /* characters to distinguish the charset from the others */
661   int uniquifier[6];
662   /* additional constraint by language */
663   CFStringRef lang;
664   /* set on demand */
665   CFCharacterSetRef cf_charset;
666   CFStringRef cf_charset_string;
667 } cf_charset_table[] =
668   { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
669     { "iso8859-2", { 0x00A0, 0x010E }},
670     { "iso8859-3", { 0x00A0, 0x0108 }},
671     { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
672     { "iso8859-5", { 0x00A0, 0x0401 }},
673     { "iso8859-6", { 0x00A0, 0x060C }},
674     { "iso8859-7", { 0x00A0, 0x0384 }},
675     { "iso8859-8", { 0x00A0, 0x05D0 }},
676     { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
677     { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
678     { "iso8859-11", { 0x00A0, 0x0E01 }},
679     { "iso8859-13", { 0x00A0, 0x201C }},
680     { "iso8859-14", { 0x00A0, 0x0174 }},
681     { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
682     { "iso8859-16", { 0x00A0, 0x0218}},
683     { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
684     { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
685     { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
686     { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
687     { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
688     { "cns11643.1992-2", { 0x4E33, 0x7934 }},
689     { "cns11643.1992-3", { 0x201A9 }},
690     { "cns11643.1992-4", { 0x20057 }},
691     { "cns11643.1992-5", { 0x20000 }},
692     { "cns11643.1992-6", { 0x20003 }},
693     { "cns11643.1992-7", { 0x20055 }},
694     { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
695     { "jisx0212.1990-0", { 0x4E44 }},
696     { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
697     { "jisx0213.2000-2", { 0xFA49 }},
698     { "jisx0213.2004-1", { 0x20B9F }},
699     { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
700     { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
701     { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
702     { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
703     { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
704     { "unicode-sip", { 0x20000 }},
705     { NULL }
706   };
708 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
709 static const struct
711   CFStringRef language;
712   CFStringRef font_names[3];
713 } macfont_language_default_font_names[] = {
714   { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
715                     CFSTR ("HiraKakuPro-W3"),  /* 10.4 */
716                     NULL }},
717   { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
718                     CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
719                     NULL }},
720   { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
721                          CFSTR ("STXihei"),         /* 10.4 - 10.5 */
722                          NULL }},
723   { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
724                          CFSTR ("LiHeiPro"),        /* 10.4 - 10.5 */
725                          NULL }},
726   { NULL }
728 #endif
730 static CGFloat macfont_antialias_threshold;
732 void
733 macfont_update_antialias_threshold (void)
735   int threshold;
736   Boolean valid_p;
738   threshold =
739     CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
740                                      kCFPreferencesCurrentApplication,
741                                      &valid_p);
742   if (valid_p)
743     macfont_antialias_threshold = threshold;
746 static inline Lisp_Object
747 macfont_intern_prop_cfstring (CFStringRef cfstring)
749   Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
751   return font_intern_prop (SSDATA (string), SBYTES (string), 1);
754 static inline CFIndex
755 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
757   if (c < 0x10000)
758     {
759       unichars[0] = c;
761       return 1;
762     }
763   else
764     {
765       c -= 0x10000;
766       unichars[0] = (c >> 10) + 0xD800;
767       unichars[1] = (c & 0x3FF) + 0xDC00;
769       return 2;
770     }
773 static Boolean
774 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
775                                          FontSymbolicTraits *sym_traits)
777   SInt64 sint64_value;
779   /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
780      OS 10.6 when the value is greater than or equal to 1 << 31.  */
781   if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
782     {
783       *sym_traits = (FontSymbolicTraits) sint64_value;
785       return true;
786     }
788   return false;
791 static void
792 macfont_store_descriptor_attributes (FontDescriptorRef desc,
793                                      Lisp_Object spec_or_entity)
795   CFStringRef str;
796   CFDictionaryRef dict;
797   CFNumberRef num;
798   CGFloat floatval;
800   str = mac_font_descriptor_copy_attribute (desc,
801                                             MAC_FONT_FAMILY_NAME_ATTRIBUTE);
802   if (str)
803     {
804       ASET (spec_or_entity, FONT_FAMILY_INDEX,
805             macfont_intern_prop_cfstring (str));
806       CFRelease (str);
807     }
808   dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
809   if (dict)
810     {
811       struct {
812         enum font_property_index index;
813         CFStringRef trait;
814         CGPoint points[6];
815       } numeric_traits[] =
816           {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
817             {{-0.4, 50},        /* light */
818              {-0.24, 87.5},     /* (semi-light + normal) / 2 */
819              {0, 100},          /* normal */
820              {0.24, 140},       /* (semi-bold + normal) / 2 */
821              {0.4, 200},        /* bold */
822              {CGFLOAT_MAX, CGFLOAT_MAX}}},
823            {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
824             {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
825            {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
826             {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
827       int i;
829       for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
830         {
831           num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
832           if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
833             {
834               CGPoint *point = numeric_traits[i].points;
836               while (point->x < floatval)
837                 point++;
838               if (point == numeric_traits[i].points)
839                 point++;
840               else if (point->x == CGFLOAT_MAX)
841                 point--;
842               floatval = (point - 1)->y + ((floatval - (point - 1)->x)
843                                            * ((point->y - (point - 1)->y)
844                                               / (point->x - (point - 1)->x)));
845               FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
846                               make_number (lround (floatval)));
847             }
848         }
850       num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
851       if (num)
852         {
853           FontSymbolicTraits sym_traits;
854           int spacing;
856           cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
857           spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
858                      ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
859           ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
860         }
862       CFRelease (dict);
863     }
864   num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
865   if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
866     ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
867   else
868     ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
869   if (num)
870     CFRelease (num);
873 static Lisp_Object
874 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
875                            FontSymbolicTraits synth_sym_traits)
877   Lisp_Object entity;
878   CFDictionaryRef dict;
879   FontSymbolicTraits sym_traits = 0;
880   CFStringRef name;
882   entity = font_make_entity ();
884   ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
885   ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
887   macfont_store_descriptor_attributes (desc, entity);
889   dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
890   if (dict)
891     {
892       CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
894       if (num)
895         cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
896       CFRelease (dict);
897     }
898   if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
899     ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
900   ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
901   name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
902   font_put_extra (entity, QCfont_entity,
903                   make_save_ptr_int ((void *) name, sym_traits));
904   if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
905     FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
906                     make_number (FONT_SLANT_SYNTHETIC_ITALIC));
907   if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
908     FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
909                     make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
910   if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
911     ASET (entity, FONT_SPACING_INDEX,
912           make_number (FONT_SPACING_SYNTHETIC_MONO));
914   return entity;
917 static CFStringRef
918 macfont_create_family_with_symbol (Lisp_Object symbol)
920   static CFArrayRef families = NULL;
921   CFStringRef result = NULL, family_name;
922   int using_cache_p = 1;
923   CFComparatorFunction family_name_comparator;
925   family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
926   if (family_name == NULL)
927     return NULL;
929 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
930 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
931   if (CTFontManagerCompareFontFamilyNames != NULL)
932 #endif
933     {
934       family_name_comparator = CTFontManagerCompareFontFamilyNames;
935     }
936 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
937   else               /* CTFontManagerCompareFontFamilyNames == NULL */
938 #endif
939 #endif  /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
940 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
941     {
942       family_name_comparator = mac_font_family_compare;
943     }
944 #endif
946   if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
947       == kCFCompareEqualTo)
948     result = CFSTR ("LastResort");
949   else
950     while (1)
951       {
952         CFIndex i, count;
954         if (families == NULL)
955           {
956             families = mac_font_create_available_families ();
957             using_cache_p = 0;
958             if (families == NULL)
959               break;
960           }
962         count = CFArrayGetCount (families);
963         i = CFArrayBSearchValues (families, CFRangeMake (0, count),
964                                   (const void *) family_name,
965                                   family_name_comparator, NULL);
966         if (i < count)
967           {
968             CFStringRef name = CFArrayGetValueAtIndex (families, i);
970             if ((*family_name_comparator) (name, family_name, NULL)
971                 == kCFCompareEqualTo)
972               result = CFRetain (name);
973           }
975         if (result || !using_cache_p)
976           break;
977         else
978           {
979             CFRelease (families);
980             families = NULL;
981           }
982       }
984   CFRelease (family_name);
986   return result;
989 #define WIDTH_FRAC_BITS         (4)
990 #define WIDTH_FRAC_SCALE        (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
992 struct macfont_metrics
994   unsigned char lbearing_low, rbearing_low;
995   signed lbearing_high : 4, rbearing_high : 4;
996   unsigned char ascent_low, descent_low;
997   signed ascent_high : 4, descent_high : 4;
999   /* These two members are used for fixed-point representation of
1000      glyph width.  The `width_int' member is an integer that is
1001      closest to the width.  The `width_frac' member is the fractional
1002      adjustment representing a value in [-.5, .5], multiplied by
1003      WIDTH_FRAC_SCALE.  For synthetic monospace fonts, they represent
1004      the advance delta for centering instead of the glyph width.  */
1005   signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1008 #define METRICS_VALUE(metrics, member) \
1009   (((metrics)->member##_high << 8) | (metrics)->member##_low)
1010 #define METRICS_SET_VALUE(metrics, member, value) \
1011   do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1012       (metrics)->member##_high = tmp >> 8;} while (0)
1014 enum metrics_status
1015   {
1016     METRICS_INVALID = -1,    /* metrics entry is invalid */
1017     METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1018   };
1020 #define METRICS_STATUS(metrics) \
1021   (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1022 #define METRICS_SET_STATUS(metrics, status) \
1023   do {METRICS_SET_VALUE (metrics, ascent, 0); \
1024       METRICS_SET_VALUE (metrics, descent, status);} while (0)
1026 #define METRICS_NCOLS_PER_ROW   (128)
1027 #define LCD_FONT_SMOOTHING_LEFT_MARGIN  (0.396f)
1028 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1030 static int
1031 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1032                        struct font_metrics *metrics, CGFloat *advance_delta,
1033                        int force_integral_p)
1035   struct macfont_info *macfont_info = (struct macfont_info *) font;
1036   FontRef macfont = macfont_info->macfont;
1037   int row, col;
1038   struct macfont_metrics *cache;
1039   int width;
1041   row = glyph / METRICS_NCOLS_PER_ROW;
1042   col = glyph % METRICS_NCOLS_PER_ROW;
1043   if (row >= macfont_info->metrics_nrows)
1044     {
1045       macfont_info->metrics =
1046         xrealloc (macfont_info->metrics,
1047                   sizeof (struct macfont_metrics *) * (row + 1));
1048       memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1049               (sizeof (struct macfont_metrics *)
1050                * (row + 1 - macfont_info->metrics_nrows)));
1051       macfont_info->metrics_nrows = row + 1;
1052     }
1053   if (macfont_info->metrics[row] == NULL)
1054     {
1055       struct macfont_metrics *new;
1056       int i;
1058       new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1059       for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1060         METRICS_SET_STATUS (new + i, METRICS_INVALID);
1061       macfont_info->metrics[row] = new;
1062     }
1063   cache = macfont_info->metrics[row] + col;
1065   if (METRICS_STATUS (cache) == METRICS_INVALID)
1066     {
1067       CGFloat fwidth;
1069       if (macfont_info->screen_font)
1070         fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1071       else
1072         fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1074       /* For synthetic mono fonts, cache->width_{int,frac} holds the
1075          advance delta value.  */
1076       if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1077         fwidth = (font->pixel_size - fwidth) / 2;
1078       cache->width_int = lround (fwidth);
1079       cache->width_frac = lround ((fwidth - cache->width_int)
1080                                   * WIDTH_FRAC_SCALE);
1081       METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1082     }
1083   if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1084     width = font->pixel_size;
1085   else
1086     width = cache->width_int;
1088   if (metrics)
1089     {
1090       if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1091         {
1092           CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1094           if (macfont_info->synthetic_italic_p)
1095             {
1096               /* We assume the members a, b, c, and d in
1097                  synthetic_italic_atfm are non-negative.  */
1098               bounds.origin =
1099                 CGPointApplyAffineTransform (bounds.origin,
1100                                              synthetic_italic_atfm);
1101               bounds.size =
1102                 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1103             }
1104           if (macfont_info->synthetic_bold_p && ! force_integral_p)
1105             {
1106               CGFloat d =
1107                 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1109               bounds = CGRectInset (bounds, d, d);
1110             }
1111           switch (macfont_info->spacing)
1112             {
1113             case MACFONT_SPACING_PROPORTIONAL:
1114               bounds.origin.x += - (cache->width_frac
1115                                     / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1116               break;
1117             case MACFONT_SPACING_MONO:
1118               break;
1119             case MACFONT_SPACING_SYNTHETIC_MONO:
1120               bounds.origin.x += (cache->width_int
1121                                   + (cache->width_frac
1122                                      / (CGFloat) WIDTH_FRAC_SCALE));
1123               break;
1124             }
1125           if (bounds.size.width > 0)
1126             {
1127               bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1128               bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1129                                     + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1130             }
1131           bounds = CGRectIntegral (bounds);
1132           METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1133           METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1134           METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1135           METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1136         }
1137       metrics->lbearing = METRICS_VALUE (cache, lbearing);
1138       metrics->rbearing = METRICS_VALUE (cache, rbearing);
1139       metrics->width = width;
1140       metrics->ascent = METRICS_VALUE (cache, ascent);
1141       metrics->descent = METRICS_VALUE (cache, descent);
1142     }
1144   if (advance_delta)
1145     {
1146       switch (macfont_info->spacing)
1147         {
1148         case MACFONT_SPACING_PROPORTIONAL:
1149           *advance_delta = (force_integral_p ? 0
1150                             : - (cache->width_frac
1151                                  / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1152           break;
1153         case MACFONT_SPACING_MONO:
1154           *advance_delta = 0;
1155           break;
1156         case MACFONT_SPACING_SYNTHETIC_MONO:
1157           *advance_delta = (force_integral_p ? cache->width_int
1158                             : (cache->width_int
1159                                + (cache->width_frac
1160                                   / (CGFloat) WIDTH_FRAC_SCALE)));
1161           break;
1162         }
1163     }
1165   return width;
1168 static CFMutableDictionaryRef macfont_cache_dictionary;
1170 /* Threshold used in row_nkeys_or_perm.  This must be less than or
1171    equal to the number of rows that are invalid as BMP (i.e., from
1172    U+D800 to U+DFFF).  */
1173 #define ROW_PERM_OFFSET (8)
1175 /* The number of glyphs that can be stored in a value for a single
1176    entry of CFDictionary.  */
1177 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1179 struct macfont_cache
1181   int reference_count;
1182   CFCharacterSetRef cf_charset;
1183   struct {
1184     /* The cached glyph for a BMP character c is stored in
1185        matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1186        if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET.  */
1187     unsigned char row_nkeys_or_perm[256];
1188     CGGlyph **matrix;
1190     /* Number of rows for which the BMP cache is allocated so far.
1191        I.e., matrix[0] ... matrix[nrows - 1] are non-NULL.  */
1192     int nrows;
1194     /* The cached glyph for a character c is stored as the (c %
1195        NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1196        NGLYPHS_IN_VALUE).  However, the glyph for a BMP character c is
1197        not stored here if row_nkeys_or_perm[c / 256] >=
1198        ROW_PERM_OFFSET.  */
1199     CFMutableDictionaryRef dictionary;
1200   } glyph;
1202   struct {
1203     /* UVS (Unicode Variation Sequence) subtable data, which is of
1204        type CFDataRef if available.  NULL means it is not initialized
1205        yet.  kCFNull means the subtable is not found and there is no
1206        suitable fallback table for this font.  */
1207     CFTypeRef table;
1209     /* Character collection specifying the destination of the mapping
1210        provided by `table' above.  If `table' is obtained from the UVS
1211        subtable in the font cmap table, then the value of this member
1212        should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING.  */
1213     CharacterCollection collection;
1214   } uvs;
1217 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1218 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1219 static void macfont_release_cache (struct macfont_cache *);
1220 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1221 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1222 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1223 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1224                                           CharacterCollection, CGFontIndex);
1225 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1227 static struct macfont_cache *
1228 macfont_lookup_cache (CFStringRef key)
1230   struct macfont_cache *cache;
1232   if (macfont_cache_dictionary == NULL)
1233     {
1234       macfont_cache_dictionary =
1235         CFDictionaryCreateMutable (NULL, 0,
1236                                    &kCFTypeDictionaryKeyCallBacks, NULL);
1237       cache = NULL;
1238     }
1239   else
1240     cache = ((struct macfont_cache *)
1241              CFDictionaryGetValue (macfont_cache_dictionary, key));
1243   if (cache == NULL)
1244     {
1245       FontRef macfont = mac_font_create_with_name (key, 0);
1247       if (macfont)
1248         {
1249           cache = xzalloc (sizeof (struct macfont_cache));
1250           /* Treat the LastResort font as if it contained glyphs for
1251              all characters.  This may look too rough, but neither
1252              CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1253              for this font is correct for non-BMP characters on Mac OS
1254              X 10.5, anyway.  */
1255           if (CFStringCompare (key, CFSTR ("LastResort"), 0)
1256               == kCFCompareEqualTo)
1257             {
1258               CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1260               cache->cf_charset =
1261                 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1262             }
1263           if (cache->cf_charset == NULL)
1264             cache->cf_charset = mac_font_copy_character_set (macfont);
1265           CFDictionaryAddValue (macfont_cache_dictionary, key,
1266                                 (const void *) cache);
1267           CFRelease (macfont);
1268         }
1269     }
1271   return cache;
1274 static struct macfont_cache *
1275 macfont_retain_cache (struct macfont_cache *cache)
1277   cache->reference_count++;
1279   return cache;
1282 static void
1283 macfont_release_cache (struct macfont_cache *cache)
1285   if (--cache->reference_count == 0)
1286     {
1287       int i;
1289       for (i = 0; i < cache->glyph.nrows; i++)
1290         xfree (cache->glyph.matrix[i]);
1291       xfree (cache->glyph.matrix);
1292       if (cache->glyph.dictionary)
1293         CFRelease (cache->glyph.dictionary);
1294       memset (&cache->glyph, 0, sizeof (cache->glyph));
1295       if (cache->uvs.table)
1296         CFRelease (cache->uvs.table);
1297       memset (&cache->uvs, 0, sizeof (cache->uvs));
1298     }
1301 static CFCharacterSetRef
1302 macfont_get_cf_charset (struct font *font)
1304   struct macfont_info *macfont_info = (struct macfont_info *) font;
1306   return macfont_info->cache->cf_charset;
1309 static CFCharacterSetRef
1310 macfont_get_cf_charset_for_name (CFStringRef name)
1312   struct macfont_cache *cache = macfont_lookup_cache (name);
1314   return cache->cf_charset;
1317 static CGGlyph
1318 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1320   struct macfont_info *macfont_info = (struct macfont_info *) font;
1321   FontRef macfont = macfont_info->macfont;
1322   struct macfont_cache *cache = macfont_info->cache;
1324   if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1325     {
1326       int row = c / 256;
1327       int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1329       if (nkeys_or_perm < ROW_PERM_OFFSET)
1330         {
1331           UniChar unichars[256], ch;
1332           CGGlyph *glyphs;
1333           int i, len;
1334           int nrows;
1335 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1336           dispatch_queue_t queue;
1337           dispatch_group_t group = NULL;
1338 #else
1339           int nkeys;
1340 #endif
1342           if (row != 0)
1343             {
1344               CFMutableDictionaryRef dictionary;
1345               uintptr_t key, value;
1346               int nshifts;
1347               CGGlyph glyph;
1349               if (cache->glyph.dictionary == NULL)
1350                 cache->glyph.dictionary =
1351                   CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1352               dictionary = cache->glyph.dictionary;
1353               key = c / NGLYPHS_IN_VALUE;
1354               nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1355               value = ((uintptr_t)
1356                        CFDictionaryGetValue (dictionary, (const void *) key));
1357               glyph = (value >> nshifts);
1358               if (glyph)
1359                 return glyph;
1361               if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1362                 {
1363                   ch = c;
1364                   if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1365                                                            &glyph, 1)
1366                       || glyph == 0)
1367                     glyph = kCGFontIndexInvalid;
1369                   if (value == 0)
1370                     cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1371                   value |= ((uintptr_t) glyph << nshifts);
1372                   CFDictionarySetValue (dictionary, (const void *) key,
1373                                         (const void *) value);
1375                   return glyph;
1376                 }
1378 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1379               queue =
1380                 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1381               group = dispatch_group_create ();
1382               dispatch_group_async (group, queue, ^{
1383                   int nkeys;
1384                   uintptr_t key;
1385 #endif
1386                   nkeys = nkeys_or_perm;
1387                   for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1388                     if (CFDictionaryContainsKey (dictionary,
1389                                                  (const void *) key))
1390                       {
1391                         CFDictionaryRemoveValue (dictionary,
1392                                                  (const void *) key);
1393                         if (--nkeys == 0)
1394                           break;
1395                       }
1396 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1397                 });
1398 #endif
1399             }
1401           len = 0;
1402           for (i = 0; i < 256; i++)
1403             {
1404               ch = row * 256 + i;
1405               if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1406                 unichars[len++] = ch;
1407             }
1409           glyphs = xmalloc (sizeof (CGGlyph) * 256);
1410           if (len > 0)
1411             {
1412               mac_font_get_glyphs_for_characters (macfont, unichars,
1413                                                   glyphs, len);
1414               while (i > len)
1415                 {
1416                   int next = unichars[len - 1] % 256;
1418                   while (--i > next)
1419                     glyphs[i] = kCGFontIndexInvalid;
1421                   len--;
1422                   glyphs[i] = glyphs[len];
1423                   if (len == 0)
1424                     break;
1425                 }
1426             }
1427           if (i > len)
1428             while (i-- > 0)
1429               glyphs[i] = kCGFontIndexInvalid;
1431           nrows = cache->glyph.nrows;
1432           nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1433           cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1434           nrows++;
1435           cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1436                                           sizeof (CGGlyph *) * nrows);
1437           cache->glyph.matrix[nrows - 1] = glyphs;
1438           cache->glyph.nrows = nrows;
1440 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1441           if (group)
1442             {
1443               dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1444               dispatch_release (group);
1445             }
1446 #endif
1447         }
1449       return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1450     }
1451   else
1452     {
1453       uintptr_t key, value;
1454       int nshifts;
1455       CGGlyph glyph;
1457       if (cache->glyph.dictionary == NULL)
1458         cache->glyph.dictionary =
1459           CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1460       key = c / NGLYPHS_IN_VALUE;
1461       nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1462       value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1463                                                 (const void *) key);
1464       glyph = (value >> nshifts);
1465       if (glyph == 0)
1466         {
1467           UniChar unichars[2];
1468           CGGlyph glyphs[2];
1469           CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1471           if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1472                                                   count))
1473             glyph = glyphs[0];
1474           if (glyph == 0)
1475             glyph = kCGFontIndexInvalid;
1477           value |= ((uintptr_t) glyph << nshifts);
1478           CFDictionarySetValue (cache->glyph.dictionary,
1479                                 (const void *) key, (const void *) value);
1480         }
1482       return glyph;
1483     }
1486 static CGGlyph
1487 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1488                            CGFontIndex cid)
1490   struct macfont_info *macfont_info = (struct macfont_info *) font;
1491   FontRef macfont = macfont_info->macfont;
1493   /* Cache it? */
1494   return mac_font_get_glyph_for_cid (macfont, collection, cid);
1497 static CFDataRef
1498 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1500   struct macfont_info *macfont_info = (struct macfont_info *) font;
1501   FontRef macfont = macfont_info->macfont;
1502   struct macfont_cache *cache = macfont_info->cache;
1503   CFDataRef result = NULL;
1505   if (cache->uvs.table == NULL)
1506     {
1507       CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1508       CharacterCollection uvs_collection =
1509         MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1511       if (uvs_table == NULL
1512           && mac_font_get_glyph_for_cid (macfont,
1513                                          MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1514                                          6480) != kCGFontIndexInvalid)
1515         {
1516           /* If the glyph for U+4E55 is accessible via its CID 6480,
1517              then we use the Adobe-Japan1 UVS table, which maps a
1518              variation sequence to a CID, as a fallback.  */
1519           static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1521           if (mac_uvs_table_adobe_japan1 == NULL)
1522             mac_uvs_table_adobe_japan1 =
1523               CFDataCreateWithBytesNoCopy (NULL,
1524                                            mac_uvs_table_adobe_japan1_bytes,
1525                                            sizeof (mac_uvs_table_adobe_japan1_bytes),
1526                                            kCFAllocatorNull);
1527           if (mac_uvs_table_adobe_japan1)
1528             {
1529               uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1530               uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1531             }
1532         }
1533       if (uvs_table == NULL)
1534         cache->uvs.table = kCFNull;
1535       else
1536         cache->uvs.table = uvs_table;
1537       cache->uvs.collection = uvs_collection;
1538     }
1540   if (cache->uvs.table != kCFNull)
1541     {
1542       result = cache->uvs.table;
1543       *collection = cache->uvs.collection;
1544     }
1546   return result;
1549 static Lisp_Object macfont_get_cache (struct frame *);
1550 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1551 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1552 static Lisp_Object macfont_list_family (struct frame *);
1553 static void macfont_free_entity (Lisp_Object);
1554 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1555 static void macfont_close (struct font *);
1556 static int macfont_has_char (Lisp_Object, int);
1557 static unsigned macfont_encode_char (struct font *, int);
1558 static int macfont_text_extents (struct font *, unsigned int *, int,
1559                                  struct font_metrics *);
1560 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1561 static Lisp_Object macfont_shape (Lisp_Object);
1562 static int macfont_variation_glyphs (struct font *, int c,
1563                                      unsigned variations[256]);
1564 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1566 static struct font_driver macfont_driver =
1567   {
1568     LISP_INITIALLY_ZERO,        /* Qmac_ct */
1569     0,                          /* case insensitive */
1570     macfont_get_cache,
1571     macfont_list,
1572     macfont_match,
1573     macfont_list_family,
1574     macfont_free_entity,
1575     macfont_open,
1576     macfont_close,
1577     NULL,                       /* prepare_face */
1578     NULL,                       /* done_face */
1579     macfont_has_char,
1580     macfont_encode_char,
1581     macfont_text_extents,
1582     macfont_draw,
1583     NULL,                       /* get_bitmap */
1584     NULL,                       /* free_bitmap */
1585     NULL,                       /* get_outline */
1586     NULL,                       /* free_outline */
1587     NULL,                       /* anchor_point */
1588     NULL,                       /* otf_capability */
1589     NULL,                       /* otf_drive */
1590     NULL,                       /* start_for_frame */
1591     NULL,                       /* end_for_frame */
1592     macfont_shape,
1593     NULL,                       /* check */
1594     macfont_variation_glyphs,
1595     macfont_filter_properties,
1596   };
1598 static Lisp_Object
1599 macfont_get_cache (struct frame * f)
1601   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1603   return (dpyinfo->name_list_element);
1606 static int
1607 macfont_get_charset (Lisp_Object registry)
1609   char *str = SSDATA (SYMBOL_NAME (registry));
1610   char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1611   Lisp_Object regexp;
1612   int i, j;
1614   for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1615     {
1616       if (str[i] == '.')
1617         re[j++] = '\\';
1618       else if (str[i] == '*')
1619         re[j++] = '.';
1620       re[j] = str[i];
1621       if (re[j] == '?')
1622         re[j] = '.';
1623     }
1624   re[j] = '\0';
1625   regexp = make_unibyte_string (re, j);
1626   for (i = 0; cf_charset_table[i].name; i++)
1627     if (fast_c_string_match_ignore_case
1628         (regexp, cf_charset_table[i].name,
1629          strlen (cf_charset_table[i].name)) >= 0)
1630       break;
1631   if (! cf_charset_table[i].name)
1632     return -1;
1633   if (! cf_charset_table[i].cf_charset)
1634     {
1635       int *uniquifier = cf_charset_table[i].uniquifier;
1636       UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1637       CFIndex count = 0;
1638       CFStringRef string;
1639       CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1641       if (! charset)
1642         return -1;
1643       for (j = 0; uniquifier[j]; j++)
1644         {
1645           count += macfont_store_utf32char_to_unichars (uniquifier[j],
1646                                                         unichars + count);
1647           CFCharacterSetAddCharactersInRange (charset,
1648                                               CFRangeMake (uniquifier[j], 1));
1649         }
1651       string = CFStringCreateWithCharacters (NULL, unichars, count);
1652       if (! string)
1653         {
1654           CFRelease (charset);
1655           return -1;
1656         }
1657       cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1658                                                                  charset);
1659       CFRelease (charset);
1660       /* CFCharacterSetCreateWithCharactersInString does not handle
1661          surrogate pairs properly as of Mac OS X 10.5.  */
1662      cf_charset_table[i].cf_charset_string = string;
1663     }
1664   return i;
1667 struct OpenTypeSpec
1669   Lisp_Object script;
1670   unsigned int script_tag, langsys_tag;
1671   int nfeatures[2];
1672   unsigned int *features[2];
1675 #define OTF_SYM_TAG(SYM, TAG)                                   \
1676   do {                                                          \
1677     unsigned char *p = SDATA (SYMBOL_NAME (SYM));               \
1678     TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];     \
1679   } while (0)
1681 #define OTF_TAG_STR(TAG, P)                     \
1682   do {                                          \
1683     (P)[0] = (char) (TAG >> 24);                \
1684     (P)[1] = (char) ((TAG >> 16) & 0xFF);       \
1685     (P)[2] = (char) ((TAG >> 8) & 0xFF);        \
1686     (P)[3] = (char) (TAG & 0xFF);               \
1687     (P)[4] = '\0';                              \
1688   } while (0)
1690 static struct OpenTypeSpec *
1691 macfont_get_open_type_spec (Lisp_Object otf_spec)
1693   struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1694   Lisp_Object val;
1695   int i, j;
1696   bool negative;
1698   if (! spec)
1699     return NULL;
1700   spec->script = XCAR (otf_spec);
1701   if (! NILP (spec->script))
1702     {
1703       OTF_SYM_TAG (spec->script, spec->script_tag);
1704       val = assq_no_quit (spec->script, Votf_script_alist);
1705       if (CONSP (val) && SYMBOLP (XCDR (val)))
1706         spec->script = XCDR (val);
1707       else
1708         spec->script = Qnil;
1709     }
1710   else
1711     spec->script_tag = 0x44464C54;      /* "DFLT" */
1712   otf_spec = XCDR (otf_spec);
1713   spec->langsys_tag = 0;
1714   if (! NILP (otf_spec))
1715     {
1716       val = XCAR (otf_spec);
1717       if (! NILP (val))
1718         OTF_SYM_TAG (val, spec->langsys_tag);
1719       otf_spec = XCDR (otf_spec);
1720     }
1721   spec->nfeatures[0] = spec->nfeatures[1] = 0;
1722   for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1723     {
1724       Lisp_Object len;
1726       val = XCAR (otf_spec);
1727       if (NILP (val))
1728         continue;
1729       len = Flength (val);
1730       spec->features[i] =
1731         (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1732          ? 0
1733          : malloc (XINT (len) * sizeof *spec->features[i]));
1734       if (! spec->features[i])
1735         {
1736           if (i > 0 && spec->features[0])
1737             free (spec->features[0]);
1738           free (spec);
1739           return NULL;
1740         }
1741       for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1742         {
1743           if (NILP (XCAR (val)))
1744             negative = 1;
1745           else
1746             {
1747               unsigned int tag;
1749               OTF_SYM_TAG (XCAR (val), tag);
1750               spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1751             }
1752         }
1753       spec->nfeatures[i] = j;
1754     }
1755   return spec;
1758 static CFMutableDictionaryRef
1759 macfont_create_attributes_with_spec (Lisp_Object spec)
1761   Lisp_Object tmp, extra;
1762   CFMutableArrayRef langarray = NULL;
1763   CFCharacterSetRef charset = NULL;
1764   CFStringRef charset_string = NULL;
1765   CFMutableDictionaryRef attributes = NULL, traits = NULL;
1766   Lisp_Object script = Qnil;
1767   Lisp_Object registry;
1768   int cf_charset_idx, i;
1769   struct OpenTypeSpec *otspec = NULL;
1770   struct {
1771     enum font_property_index index;
1772     CFStringRef trait;
1773     CGPoint points[6];
1774   } numeric_traits[] =
1775       {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1776         {{-0.4, 50},            /* light */
1777          {-0.24, 87.5},         /* (semi-light + normal) / 2 */
1778          {0, 100},              /* normal */
1779          {0.24, 140},           /* (semi-bold + normal) / 2 */
1780          {0.4, 200},            /* bold */
1781          {CGFLOAT_MAX, CGFLOAT_MAX}}},
1782        {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1783         {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1784        {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1785         {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1787   registry = AREF (spec, FONT_REGISTRY_INDEX);
1788   if (NILP (registry)
1789       || EQ (registry, Qascii_0)
1790       || EQ (registry, Qiso10646_1)
1791       || EQ (registry, Qunicode_bmp))
1792     cf_charset_idx = -1;
1793   else
1794     {
1795       CFStringRef lang;
1797       cf_charset_idx = macfont_get_charset (registry);
1798       if (cf_charset_idx < 0)
1799         goto err;
1800       charset = cf_charset_table[cf_charset_idx].cf_charset;
1801       charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1802       lang = cf_charset_table[cf_charset_idx].lang;
1803       if (lang)
1804         {
1805           langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1806           if (! langarray)
1807             goto err;
1808           CFArrayAppendValue (langarray, lang);
1809         }
1810     }
1812   for (extra = AREF (spec, FONT_EXTRA_INDEX);
1813        CONSP (extra); extra = XCDR (extra))
1814     {
1815       Lisp_Object key, val;
1817       tmp = XCAR (extra);
1818       key = XCAR (tmp), val = XCDR (tmp);
1819       if (EQ (key, QClang))
1820         {
1821           if (! langarray)
1822             langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1823           if (! langarray)
1824             goto err;
1825           if (SYMBOLP (val))
1826             val = list1 (val);
1827           for (; CONSP (val); val = XCDR (val))
1828             if (SYMBOLP (XCAR (val)))
1829               {
1830                 CFStringRef lang =
1831                   cfstring_create_with_string_noencode (SYMBOL_NAME
1832                                                         (XCAR (val)));
1834                 if (lang == NULL)
1835                   goto err;
1836                 CFArrayAppendValue (langarray, lang);
1837                 CFRelease (lang);
1838               }
1839         }
1840       else if (EQ (key, QCotf))
1841         {
1842           otspec = macfont_get_open_type_spec (val);
1843           if (! otspec)
1844             goto err;
1845           script = otspec->script;
1846         }
1847       else if (EQ (key, QCscript))
1848         script = val;
1849     }
1851   if (! NILP (script) && ! charset)
1852     {
1853       Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1855       if (CONSP (chars) && CONSP (CDR (chars)))
1856         {
1857           CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1858           CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1860           if (! string || !cs)
1861             {
1862               if (string)
1863                 CFRelease (string);
1864               else if (cs)
1865                 CFRelease (cs);
1866               goto err;
1867             }
1868           for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1869             if (CHARACTERP (XCAR (chars)))
1870               {
1871                 UniChar unichars[2];
1872                 CFIndex count =
1873                   macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1874                                                        unichars);
1875                 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1877                 CFStringAppendCharacters (string, unichars, count);
1878                 CFCharacterSetAddCharactersInRange (cs, range);
1879               }
1880           charset = cs;
1881           /* CFCharacterSetCreateWithCharactersInString does not
1882              handle surrogate pairs properly as of Mac OS X 10.5.  */
1883           charset_string = string;
1884         }
1885     }
1887   attributes = CFDictionaryCreateMutable (NULL, 0,
1888                                           &kCFTypeDictionaryKeyCallBacks,
1889                                           &kCFTypeDictionaryValueCallBacks);
1890   if (! attributes)
1891     goto err;
1893   tmp = AREF (spec, FONT_FAMILY_INDEX);
1894   if (SYMBOLP (tmp) && ! NILP (tmp))
1895     {
1896       CFStringRef family = macfont_create_family_with_symbol (tmp);
1898       if (! family)
1899         goto err;
1900       CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1901                             family);
1902       CFRelease (family);
1903     }
1905   traits = CFDictionaryCreateMutable (NULL, 4,
1906                                       &kCFTypeDictionaryKeyCallBacks,
1907                                       &kCFTypeDictionaryValueCallBacks);
1908   if (! traits)
1909     goto err;
1911   for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
1912     {
1913       tmp = AREF (spec, numeric_traits[i].index);
1914       if (INTEGERP (tmp))
1915         {
1916           CGPoint *point = numeric_traits[i].points;
1917           CGFloat floatval = (XINT (tmp) >> 8); // XXX
1918           CFNumberRef num;
1920           while (point->y < floatval)
1921             point++;
1922           if (point == numeric_traits[i].points)
1923             point++;
1924           else if (point->y == CGFLOAT_MAX)
1925             point--;
1926           floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1927                                        * ((point->x - (point - 1)->x)
1928                                           / (point->y - (point - 1)->y)));
1929           if (floatval > 1.0)
1930             floatval = 1.0;
1931           else if (floatval < -1.0)
1932             floatval = -1.0;
1933           num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1934           if (! num)
1935             goto err;
1936           CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1937           CFRelease (num);
1938         }
1939     }
1940   if (CFDictionaryGetCount (traits))
1941     CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1943   if (charset)
1944     CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1945                           charset);
1946   if (charset_string)
1947     CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1948                           charset_string);
1949   if (langarray)
1950     CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1952   goto finish;
1954  err:
1955   if (attributes)
1956     {
1957       CFRelease (attributes);
1958       attributes = NULL;
1959     }
1961  finish:
1962   if (langarray) CFRelease (langarray);
1963   if (charset && cf_charset_idx < 0) CFRelease (charset);
1964   if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1965   if (traits) CFRelease (traits);
1966   if (otspec)
1967     {
1968       if (otspec->nfeatures[0] > 0)
1969         free (otspec->features[0]);
1970       if (otspec->nfeatures[1] > 0)
1971         free (otspec->features[1]);
1972       free (otspec);
1973     }
1975   return attributes;
1978 static Boolean
1979 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1980                                           CFCharacterSetRef charset,
1981                                           Lisp_Object chars,
1982                                           CFArrayRef languages)
1984   Boolean result = true;
1986   if (charset || VECTORP (chars))
1987     {
1988       CFCharacterSetRef desc_charset =
1989         mac_font_descriptor_copy_attribute (desc,
1990                                             MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1992       if (desc_charset == NULL)
1993         result = false;
1994       else
1995         {
1996           if (charset)
1997             result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1998           else                  /* VECTORP (chars) */
1999             {
2000               ptrdiff_t j;
2002               for (j = 0; j < ASIZE (chars); j++)
2003                 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2004                     && CFCharacterSetIsLongCharacterMember (desc_charset,
2005                                                             XFASTINT (AREF (chars, j))))
2006                   break;
2007               if (j == ASIZE (chars))
2008                 result = false;
2009             }
2010           CFRelease (desc_charset);
2011         }
2012     }
2013   if (result && languages)
2014     result = mac_font_descriptor_supports_languages (desc, languages);
2016   return result;
2019 static CFIndex
2020 macfont_closest_traits_index (CFArrayRef traits_array,
2021                               FontSymbolicTraits target)
2023   CFIndex i, result = -1, count = CFArrayGetCount (traits_array);
2024   int min_distance = (1 << 3);
2026   for (i = 0; i < count; i++)
2027     {
2028       FontSymbolicTraits traits, diff;
2029       int distance = 0;
2031       traits = ((FontSymbolicTraits) (uintptr_t)
2032                 CFArrayGetValueAtIndex (traits_array, i));
2033       diff = (target ^ traits);
2034       /* We prefer synthetic bold of italic to synthetic italic of
2035          bold when both bold and italic are available but bold-italic
2036          is not available.  */
2037       if (diff & MAC_FONT_TRAIT_BOLD)
2038         distance |= (1 << 0);
2039       if (diff & MAC_FONT_TRAIT_ITALIC)
2040         distance |= (1 << 1);
2041       if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2042         distance |= (1 << 2);
2043       if (distance < min_distance)
2044         {
2045           min_distance = distance;
2046           result = i;
2047         }
2048     }
2050   return result;
2053 static Lisp_Object
2054 macfont_list (struct frame *f, Lisp_Object spec)
2056   Lisp_Object val = Qnil, family, extra;
2057   int i, n;
2058   CFStringRef family_name = NULL;
2059   CFMutableDictionaryRef attributes = NULL, traits;
2060   Lisp_Object chars = Qnil;
2061   int spacing = -1;
2062   FontSymbolicTraits synth_sym_traits = 0;
2063   CFArrayRef families;
2064   CFIndex families_count;
2065   CFCharacterSetRef charset = NULL;
2066   CFArrayRef languages = NULL;
2068   block_input ();
2070   family = AREF (spec, FONT_FAMILY_INDEX);
2071   if (! NILP (family))
2072     {
2073       family_name = macfont_create_family_with_symbol (family);
2074       if (family_name == NULL)
2075         goto finish;
2076     }
2078   attributes = macfont_create_attributes_with_spec (spec);
2079   if (! attributes)
2080     goto finish;
2082   languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2084   if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2085     spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2087   traits = ((CFMutableDictionaryRef)
2088             CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2090   n = FONT_SLANT_NUMERIC (spec);
2091   if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2092     {
2093       synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2094       if (traits)
2095         CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2096     }
2098   n = FONT_WEIGHT_NUMERIC (spec);
2099   if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2100     {
2101       synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2102       if (traits)
2103         CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2104     }
2106   if (languages
2107       && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2108     {
2109       CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2111       if (CFStringHasPrefix (language, CFSTR ("ja"))
2112           || CFStringHasPrefix (language, CFSTR ("ko"))
2113           || CFStringHasPrefix (language, CFSTR ("zh")))
2114         synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2115     }
2117   /* Create array of families.  */
2118   if (family_name)
2119     families = CFArrayCreate (NULL, (const void **) &family_name,
2120                               1, &kCFTypeArrayCallBacks);
2121   else
2122     {
2123       CFStringRef pref_family;
2124       CFIndex families_count, pref_family_index = -1;
2126       families = mac_font_create_available_families ();
2127       if (families == NULL)
2128         goto err;
2130       families_count = CFArrayGetCount (families);
2132       /* Move preferred family to the front if exists.  */
2133       pref_family =
2134         mac_font_create_preferred_family_for_attributes (attributes);
2135       if (pref_family)
2136         {
2137           pref_family_index =
2138             CFArrayGetFirstIndexOfValue (families,
2139                                          CFRangeMake (0, families_count),
2140                                          pref_family);
2141           CFRelease (pref_family);
2142         }
2143       if (pref_family_index > 0)
2144         {
2145           CFMutableArrayRef mutable_families =
2146             CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2148           if (mutable_families)
2149             {
2150               CFArrayAppendValue (mutable_families,
2151                                   CFArrayGetValueAtIndex (families,
2152                                                           pref_family_index));
2153               CFArrayAppendArray (mutable_families, families,
2154                                   CFRangeMake (0, pref_family_index));
2155               if (pref_family_index + 1 < families_count)
2156                 CFArrayAppendArray (mutable_families, families,
2157                                     CFRangeMake (pref_family_index + 1,
2158                                                  families_count
2159                                                  - (pref_family_index + 1)));
2160               CFRelease (families);
2161               families = mutable_families;
2162             }
2163         }
2164     }
2166   charset = CFDictionaryGetValue (attributes,
2167                                   MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2168   if (charset)
2169     {
2170       CFRetain (charset);
2171       CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2172     }
2173   else
2174     {
2175       val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2176       if (! NILP (val))
2177         {
2178           val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2179           if (CONSP (val) && VECTORP (XCDR (val)))
2180             chars = XCDR (val);
2181         }
2182       val = Qnil;
2183     }
2185   if (languages)
2186     {
2187       CFRetain (languages);
2188       CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2189     }
2191   val = Qnil;
2192   extra = AREF (spec, FONT_EXTRA_INDEX);
2193   families_count = CFArrayGetCount (families);
2194   for (i = 0; i < families_count; i++)
2195     {
2196       CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2197       FontDescriptorRef pat_desc;
2198       CFArrayRef descs;
2199       CFIndex descs_count;
2200       CFMutableArrayRef filtered_descs, traits_array;
2201       Lisp_Object entity;
2202       int j;
2204       CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2205                             family_name);
2206       pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2207       if (! pat_desc)
2208         goto err;
2210       /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2211          10.7 returns NULL if pat_desc represents the LastResort font.
2212          So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2213          trailing "s") for such a font.  */
2214       if (CFStringCompare (family_name, CFSTR ("LastResort"), 0)
2215           != kCFCompareEqualTo)
2216         descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2217                                                                       NULL);
2218       else
2219         {
2220           FontDescriptorRef lr_desc =
2221             mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2222                                                                  NULL);
2223           if (lr_desc)
2224             {
2225               descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2226                                      &kCFTypeArrayCallBacks);
2227               CFRelease (lr_desc);
2228             }
2229           else
2230             descs = NULL;
2231         }
2232       CFRelease (pat_desc);
2233       if (! descs)
2234         goto err;
2236       descs_count = CFArrayGetCount (descs);
2237       if (descs_count == 0
2238           || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2239                                                         charset, chars,
2240                                                         languages))
2241         {
2242           CFRelease (descs);
2243           continue;
2244         }
2246       filtered_descs =
2247         CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2248       traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2249       for (j = 0; j < descs_count; j++)
2250         {
2251           FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2252           CFDictionaryRef dict;
2253           CFNumberRef num;
2254           FontSymbolicTraits sym_traits;
2256           dict = mac_font_descriptor_copy_attribute (desc,
2257                                                      MAC_FONT_TRAITS_ATTRIBUTE);
2258           if (dict == NULL)
2259             continue;
2261           num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2262           CFRelease (dict);
2263           if (num == NULL
2264               || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2265             continue;
2267           if (spacing >= 0
2268               && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2269               && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2270                   != (spacing >= FONT_SPACING_MONO)))
2271             continue;
2273           /* Don't use a color bitmap font unless its family is
2274              explicitly specified.  */
2275           if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2276             continue;
2278           if (j > 0
2279               && !macfont_supports_charset_and_languages_p (desc, charset,
2280                                                             chars, languages))
2281             continue;
2283           CFArrayAppendValue (filtered_descs, desc);
2284           CFArrayAppendValue (traits_array,
2285                               (const void *) (uintptr_t) sym_traits);
2286         }
2288       CFRelease (descs);
2289       descs = filtered_descs;
2290       descs_count = CFArrayGetCount (descs);
2292       for (j = 0; j < descs_count; j++)
2293         {
2294           FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2295           FontSymbolicTraits sym_traits =
2296             ((FontSymbolicTraits) (uintptr_t)
2297              CFArrayGetValueAtIndex (traits_array, j));
2298           FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2300           mask_min = ((synth_sym_traits ^ sym_traits)
2301                       & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2302           if (FONT_SLANT_NUMERIC (spec) < 0)
2303             mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2304           if (FONT_WEIGHT_NUMERIC (spec) < 0)
2305             mask_min &= ~MAC_FONT_TRAIT_BOLD;
2307           mask_max = (synth_sym_traits & ~sym_traits);
2308           /* Synthetic bold does not work for bitmap-only fonts on Mac
2309              OS X 10.6.  */
2310           if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2311             {
2312               CFNumberRef format =
2313                 mac_font_descriptor_copy_attribute (desc,
2314                                                     MAC_FONT_FORMAT_ATTRIBUTE);
2316               if (format)
2317                 {
2318                   uint32_t format_val;
2320                   if (CFNumberGetValue (format, kCFNumberSInt32Type,
2321                                         &format_val)
2322                       && format_val == MAC_FONT_FORMAT_BITMAP)
2323                     mask_max &= ~MAC_FONT_TRAIT_BOLD;
2324                 }
2325             }
2326           if (spacing >= 0)
2327             mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2329           for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2330                mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2331                mmask += MAC_FONT_TRAIT_MONO_SPACE)
2332             for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2333                  bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2334                  bmask += MAC_FONT_TRAIT_BOLD)
2335               for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2336                    imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2337                    imask += MAC_FONT_TRAIT_ITALIC)
2338                 {
2339                   FontSymbolicTraits synth = (imask | bmask | mmask);
2341                   if (synth == 0
2342                       || j == macfont_closest_traits_index (traits_array,
2343                                                             (sym_traits | synth)))
2344                     {
2345                       entity = macfont_descriptor_entity (desc, extra, synth);
2346                       if (! NILP (entity))
2347                         val = Fcons (entity, val);
2348                     }
2349                 }
2350         }
2352       CFRelease (traits_array);
2353       CFRelease (descs);
2354     }
2356   CFRelease (families);
2357   val = Fnreverse (val);
2358   goto finish;
2359  err:
2360   val = Qnil;
2362  finish:
2363   FONT_ADD_LOG ("macfont-list", spec, val);
2364   if (charset) CFRelease (charset);
2365   if (languages) CFRelease (languages);
2366   if (attributes) CFRelease (attributes);
2367   if (family_name) CFRelease (family_name);
2369   unblock_input ();
2371   return val;
2374 static Lisp_Object
2375 macfont_match (struct frame * frame, Lisp_Object spec)
2377   Lisp_Object entity = Qnil;
2378   CFMutableDictionaryRef attributes;
2379   FontDescriptorRef pat_desc = NULL, desc = NULL;
2381   block_input ();
2383   attributes = macfont_create_attributes_with_spec (spec);
2384   if (attributes)
2385     {
2386       pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2387       CFRelease (attributes);
2388     }
2389   if (pat_desc)
2390     {
2391       desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2392                                                                   NULL);
2393       CFRelease (pat_desc);
2394     }
2395   if (desc)
2396     {
2397       entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2398                                           0);
2399       CFRelease (desc);
2400     }
2401   unblock_input ();
2403   FONT_ADD_LOG ("macfont-match", spec, entity);
2404   return entity;
2407 static Lisp_Object
2408 macfont_list_family (struct frame *frame)
2410   Lisp_Object list = Qnil;
2411   CFArrayRef families;
2413   block_input ();
2415   families = mac_font_create_available_families ();
2416   if (families)
2417     {
2418       CFIndex i, count = CFArrayGetCount (families);
2420       for (i = 0; i < count; i++)
2421         list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2422       CFRelease (families);
2423     }
2425   unblock_input ();
2427   return list;
2430 static void
2431 macfont_free_entity (Lisp_Object entity)
2433   Lisp_Object val = assq_no_quit (QCfont_entity,
2434                                   AREF (entity, FONT_EXTRA_INDEX));
2435   CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2437   block_input ();
2438   CFRelease (name);
2439   unblock_input ();
2442 static Lisp_Object
2443 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2445   Lisp_Object val, font_object;
2446   CFStringRef font_name;
2447   struct macfont_info *macfont_info = NULL;
2448   struct font *font;
2449   int size;
2450   FontRef macfont;
2451   FontSymbolicTraits sym_traits;
2452   char name[256];
2453   int len, i, total_width;
2454   CGGlyph glyph;
2455   CGFloat ascent, descent, leading;
2457   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2458   if (! CONSP (val)
2459       || XTYPE (XCDR (val)) != Lisp_Misc
2460       || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2461     return Qnil;
2462   font_name = XSAVE_POINTER (XCDR (val), 0);
2463   sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2465   size = XINT (AREF (entity, FONT_SIZE_INDEX));
2466   if (size == 0)
2467     size = pixel_size;
2469   block_input ();
2470   macfont = mac_font_create_with_name (font_name, size);
2471   if (macfont)
2472     {
2473       int fontsize = (int) [((NSFont *) macfont) pointSize];
2474       if (fontsize != size) size = fontsize;
2475     }
2476   unblock_input ();
2477   if (! macfont)
2478     return Qnil;
2480   font_object = font_make_object (VECSIZE (struct macfont_info), entity, size);
2481   ASET (font_object, FONT_TYPE_INDEX, macfont_driver.type);
2482   len = font_unparse_xlfd (entity, size, name, 256);
2483   if (len > 0)
2484     ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
2485   len = font_unparse_fcname (entity, size, name, 256);
2486   if (len > 0)
2487     ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
2488   else
2489     ASET (font_object, FONT_FULLNAME_INDEX,
2490           AREF (font_object, FONT_NAME_INDEX));
2491   font = XFONT_OBJECT (font_object);
2492   font->pixel_size = size;
2493   font->driver = &macfont_driver;
2494   font->encoding_charset = font->repertory_charset = -1;
2496   block_input ();
2498   macfont_info = (struct macfont_info *) font;
2499   macfont_info->macfont = macfont;
2500   macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2502   val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2503   if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2504     macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2505                                                                   size);
2506   else
2507     macfont_info->screen_font = NULL;
2508   macfont_info->cache = macfont_lookup_cache (font_name);
2509   macfont_retain_cache (macfont_info->cache);
2510   macfont_info->metrics = NULL;
2511   macfont_info->metrics_nrows = 0;
2512   macfont_info->synthetic_italic_p = 0;
2513   macfont_info->synthetic_bold_p = 0;
2514   macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2515   macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2516   if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2517       && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2518     macfont_info->synthetic_italic_p = 1;
2519   if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2520       && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2521     macfont_info->synthetic_bold_p = 1;
2522   if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2523     macfont_info->spacing = MACFONT_SPACING_MONO;
2524   else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2525            && (XINT (AREF (entity, FONT_SPACING_INDEX))
2526                == FONT_SPACING_SYNTHETIC_MONO))
2527     macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2528   if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2529     macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2530   else
2531     {
2532       val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2533       if (CONSP (val))
2534         macfont_info->antialias =
2535           NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2536     }
2537   macfont_info->color_bitmap_p = 0;
2538   if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2539     macfont_info->color_bitmap_p = 1;
2541   glyph = macfont_get_glyph_for_character (font, ' ');
2542   if (glyph != kCGFontIndexInvalid)
2543     font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2544   else
2545     /* dirty workaround */
2546     font->space_width = pixel_size;
2548   total_width = font->space_width;
2549   for (i = 1; i < 95; i++)
2550     {
2551       glyph = macfont_get_glyph_for_character (font, ' ' + i);
2552       if (glyph == kCGFontIndexInvalid)
2553         break;
2554       total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2555     }
2556   if (i == 95)
2557     font->average_width = total_width / 95;
2558   else
2559     font->average_width = font->space_width; /* XXX */
2561   if (!(macfont_info->screen_font
2562         && mac_screen_font_get_metrics (macfont_info->screen_font,
2563                                         &ascent, &descent, &leading)))
2564     {
2565       CFStringRef family_name;
2567       ascent = mac_font_get_ascent (macfont);
2568       descent = mac_font_get_descent (macfont);
2569       leading = mac_font_get_leading (macfont);
2570       /* AppKit and WebKit do some adjustment to the heights of
2571          Courier, Helvetica, and Times.  */
2572       family_name = mac_font_copy_family_name (macfont);
2573       if (family_name)
2574         {
2575           if ((CFStringCompare (family_name, CFSTR ("Courier"), 0)
2576                == kCFCompareEqualTo)
2577               || (CFStringCompare (family_name, CFSTR ("Helvetica"), 0)
2578                   == kCFCompareEqualTo)
2579               || (CFStringCompare (family_name, CFSTR ("Times"), 0)
2580                   == kCFCompareEqualTo))
2581             ascent += (ascent + descent) * .15f;
2582           else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2583             {
2584               leading *= .25f;
2585               ascent += leading;
2586             }
2587           CFRelease (family_name);
2588         }
2589     }
2590   font->ascent = ascent + 0.5f;
2591   val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2592   if (CONSP (val) && !NILP (XCDR (val)))
2593     font->descent = descent + 0.5f;
2594   else
2595     font->descent = descent + leading + 0.5f;
2596   font->height = font->ascent + font->descent;
2598   font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2599   font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2601   unblock_input ();
2603   /* Unfortunately Xft doesn't provide a way to get minimum char
2604      width.  So, we use space_width instead.  */
2605   font->min_width = font->max_width = font->space_width; /* XXX */
2607   font->baseline_offset = 0;
2608   font->relative_compose = 0;
2609   font->default_ascent = 0;
2610   font->vertical_centering = 0;
2612   return font_object;
2615 static void
2616 macfont_close (struct font *font)
2618   struct macfont_info *macfont_info = (struct macfont_info *) font;
2620   if (macfont_info->cache)
2621     {
2622       int i;
2624       block_input ();
2625       CFRelease (macfont_info->macfont);
2626       CGFontRelease (macfont_info->cgfont);
2627       if (macfont_info->screen_font)
2628         CFRelease (macfont_info->screen_font);
2629       macfont_release_cache (macfont_info->cache);
2630       for (i = 0; i < macfont_info->metrics_nrows; i++)
2631         if (macfont_info->metrics[i])
2632           xfree (macfont_info->metrics[i]);
2633       if (macfont_info->metrics)
2634         xfree (macfont_info->metrics);
2635       macfont_info->cache = NULL;
2636       unblock_input ();
2637     }
2640 static int
2641 macfont_has_char (Lisp_Object font, int c)
2643   int result;
2644   CFCharacterSetRef charset;
2646   block_input ();
2647   if (FONT_ENTITY_P (font))
2648     {
2649       Lisp_Object val;
2650       CFStringRef name;
2652       val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2653       val = XCDR (val);
2654       name = XSAVE_POINTER (val, 0);
2655       charset = macfont_get_cf_charset_for_name (name);
2656     }
2657   else
2658     charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2660   result = CFCharacterSetIsLongCharacterMember (charset, c);
2661   unblock_input ();
2663   return result;
2666 static unsigned
2667 macfont_encode_char (struct font *font, int c)
2669   struct macfont_info *macfont_info = (struct macfont_info *) font;
2670   CGGlyph glyph;
2672   block_input ();
2673   glyph = macfont_get_glyph_for_character (font, c);
2674   unblock_input ();
2676   return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2679 static int
2680 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2681                       struct font_metrics *metrics)
2683   int width, i;
2685   block_input ();
2686   width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2687   for (i = 1; i < nglyphs; i++)
2688     {
2689       struct font_metrics m;
2690       int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2691                                      NULL, 0);
2693       if (metrics)
2694         {
2695           if (width + m.lbearing < metrics->lbearing)
2696             metrics->lbearing = width + m.lbearing;
2697           if (width + m.rbearing > metrics->rbearing)
2698             metrics->rbearing = width + m.rbearing;
2699           if (m.ascent > metrics->ascent)
2700             metrics->ascent = m.ascent;
2701           if (m.descent > metrics->descent)
2702             metrics->descent = m.descent;
2703         }
2704       width += w;
2705     }
2706   unblock_input ();
2708   if (metrics)
2709     metrics->width = width;
2711   return width;
2714 static int
2715 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2716               bool with_background)
2718   struct frame * f = s->f;
2719   struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2720   FontRef macfont = macfont_info->macfont;
2721   CGContextRef context;
2722   BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
2723   int end = isComposite ? s->cmp_to : s->nchars;
2724   int len = end - s->cmp_from;
2725   struct face *face = s->face;
2726   int i;
2728   block_input ();
2730   context = [[NSGraphicsContext currentContext] graphicsPort];
2731   CGContextSaveGState (context);
2733 #if 0
2734   if (s->num_clips > 0)
2735     {
2736       CGRect clips[2];
2738       for (i = 0; i < s->num_clips; i++)
2739         clips[i] = mac_rect_make (f, s->clip[i].left, s->clip[i].top,
2740                                   s->clip[i].right - s->clip[i].left,
2741                                   s->clip[i].bottom - s->clip[i].top);
2742       CGContextClipToRects (context, clips, s->num_clips);
2743     }
2744 #endif
2746   if (with_background)
2747     {
2748       if (s->hl == DRAW_MOUSE_FACE) 
2749         {
2750           face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2751           if (!face)
2752             face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2753         }
2755       CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2756       CGContextFillRect (context,
2757                          CGRectMake (x, y,
2758                                      s->width, FONT_HEIGHT (s->font)));
2759     }
2761   if (macfont_info->cgfont)
2762     {
2763       CGGlyph *glyphs = alloca (sizeof (CGGlyph) * len);
2764       CGPoint *positions = alloca (sizeof (CGPoint) * len);
2765       CGFloat total_width = 0;
2766       CGFloat font_size = mac_font_get_size (macfont);
2767       CGAffineTransform atfm;
2768       CGFloat advance_delta = 0;
2769       int y_draw = -s->ybase;
2770       int no_antialias_p =
2771         (NILP (ns_antialias_text)
2772          || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2773          || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2774              && font_size <= macfont_antialias_threshold));
2776       for (i = 0; i < len; i++)
2777         {
2778           int width;
2780           glyphs[i] = *(s->char2b + s->cmp_from + i);
2781           width = (s->padding_p ? 1
2782                    : macfont_glyph_extents (s->font, glyphs[i],
2783                                             NULL, &advance_delta,
2784                                             no_antialias_p));
2785           positions[i].x = total_width + advance_delta;
2786           positions[i].y = 0;
2787           total_width += width;
2788         }
2790       CGContextScaleCTM (context, 1, -1);
2791       CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2792       if (macfont_info->synthetic_italic_p)
2793         atfm = synthetic_italic_atfm;
2794       else
2795         atfm = CGAffineTransformIdentity;
2796       if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2797         {
2798           CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2799           CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2800           CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2801         }
2802       if (no_antialias_p)
2803         CGContextSetShouldAntialias (context, false);
2805       CGContextSetTextMatrix (context, atfm);
2806       CGContextSetTextPosition (context, x, y_draw);
2808 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2809       if (macfont_info->color_bitmap_p
2810 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2811           && CTFontDrawGlyphs != NULL
2812 #endif
2813           )
2814         {
2815           if (len > 0)
2816             {
2817               CTFontDrawGlyphs (macfont, glyphs, positions, len, context);
2818             }
2819         }
2820       else
2821 #endif  /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2822         {
2823           CGContextSetFont (context, macfont_info->cgfont);
2824           CGContextSetFontSize (context, font_size);
2825           CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2826         }
2827     }
2829   CGContextRestoreGState (context);
2831   unblock_input ();
2833   return len;
2836 static Lisp_Object
2837 macfont_shape (Lisp_Object lgstring)
2839   struct font *font;
2840   struct macfont_info *macfont_info;
2841   FontRef macfont;
2842   ptrdiff_t glyph_len, len, i, j;
2843   CFIndex nonbmp_len;
2844   UniChar *unichars;
2845   CFIndex *nonbmp_indices;
2846   CFStringRef string;
2847   CFIndex used = 0;
2848   struct mac_glyph_layout *glyph_layouts;
2850   CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2851   macfont_info = (struct macfont_info *) font;
2852   macfont = macfont_info->macfont;
2854   glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2855   nonbmp_len = 0;
2856   for (i = 0; i < glyph_len; i++)
2857     {
2858       Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2860       if (NILP (lglyph))
2861         break;
2862       if (LGLYPH_CHAR (lglyph) >= 0x10000)
2863         nonbmp_len++;
2864     }
2866   len = i;
2868   if (INT_MAX / 2 < len)
2869     memory_full (SIZE_MAX);
2871   unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2872   nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2873   for (i = j = 0; i < len; i++)
2874     {
2875       UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2877       if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2878         {
2879           nonbmp_indices[j] = i + j;
2880           j++;
2881         }
2882     }
2883   nonbmp_indices[j] = len + j;  /* sentinel */
2885   block_input ();
2887   string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2888                                                kCFAllocatorNull);
2889   if (string)
2890     {
2891       glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2892       if (macfont_info->screen_font)
2893         used = mac_screen_font_shape (macfont_info->screen_font, string,
2894                                       glyph_layouts, glyph_len);
2895       else
2896         used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2897       CFRelease (string);
2898     }
2900   unblock_input ();
2902   if (used == 0)
2903     return Qnil;
2905   block_input ();
2907   for (i = 0; i < used; i++)
2908     {
2909       Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2910       struct mac_glyph_layout *gl = glyph_layouts + i;
2911       EMACS_INT from, to;
2912       struct font_metrics metrics;
2913       int xoff, yoff, wadjust;
2915       if (NILP (lglyph))
2916         {
2917           lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2918           LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2919         }
2921       from = gl->comp_range.location;
2922       /* Convert UTF-16 index to UTF-32.  */
2923       j = 0;
2924       while (nonbmp_indices[j] < from)
2925         j++;
2926       from -= j;
2927       LGLYPH_SET_FROM (lglyph, from);
2929       to = gl->comp_range.location + gl->comp_range.length;
2930       /* Convert UTF-16 index to UTF-32.  */
2931       while (nonbmp_indices[j] < to)
2932         j++;
2933       to -= j;
2934       LGLYPH_SET_TO (lglyph, to - 1);
2936       /* LGLYPH_CHAR is used in `describe-char' for checking whether
2937          the composition is trivial.  */
2938       {
2939         UTF32Char c;
2941         if (unichars[gl->string_index] >= 0xD800
2942             && unichars[gl->string_index] < 0xDC00)
2943           c = (((unichars[gl->string_index] - 0xD800) << 10)
2944                + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2945         else
2946           c = unichars[gl->string_index];
2947         if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2948           c = 0;
2949         LGLYPH_SET_CHAR (lglyph, c);
2950       }
2952       {
2953         unsigned long cc = gl->glyph_id;
2954         LGLYPH_SET_CODE (lglyph, cc);
2955       }
2957       macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2958       LGLYPH_SET_WIDTH (lglyph, metrics.width);
2959       LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2960       LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2961       LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2962       LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2964       xoff = lround (gl->advance_delta);
2965       yoff = lround (- gl->baseline_delta);
2966       wadjust = lround (gl->advance);
2967       if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2968         {
2969           Lisp_Object vec;
2971           vec = Fmake_vector (make_number (3), Qnil);
2972           ASET (vec, 0, make_number (xoff));
2973           ASET (vec, 1, make_number (yoff));
2974           ASET (vec, 2, make_number (wadjust));
2975           LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2976         }
2977     }
2979   unblock_input ();
2981   return make_number (used);
2984 /* Structures for the UVS subtable (format 14) in the cmap table.  */
2985 typedef UInt8 UINT24[3];
2987 #pragma pack(push, 1)
2988 struct variation_selector_record
2990   UINT24 var_selector;
2991   UInt32 default_uvs_offset, non_default_uvs_offset;
2993 struct uvs_table
2995   UInt16 format;
2996   UInt32 length, num_var_selector_records;
2997   struct variation_selector_record variation_selector_records[1];
2999 #define SIZEOF_UVS_TABLE_HEADER \
3000   (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3002 struct unicode_value_range
3004   UINT24 start_unicode_value;
3005   UInt8 additional_count;
3007 struct default_uvs_table {
3008   UInt32 num_unicode_value_ranges;
3009   struct unicode_value_range unicode_value_ranges[1];
3011 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3012   (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3014 struct uvs_mapping
3016   UINT24 unicode_value;
3017   UInt16 glyph_id;
3019 struct non_default_uvs_table
3021   UInt32 num_uvs_mappings;
3022   struct uvs_mapping uvs_mappings[1];
3024 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3025   (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3026 #pragma pack(pop)
3028 /* Read big endian values.  The argument LVAL must be an lvalue.  */
3029 /* I suppose OSReadBigInt* takes care of unaligned data.  At least, we
3030    can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3031    OSReadBigInt16(cdb, 7);" in a sample code by Apple.  */
3032 #define BUINT8_VALUE(lval)      (*((UInt8 *) &(lval)))
3033 #define BUINT16_VALUE(lval)     OSReadBigInt16 (&(lval), 0)
3034 /* Succeeding one byte should also be accessible.  */
3035 #define BUINT24_VALUE(lval)     (OSReadBigInt32 (&(lval), 0) >> 8)
3036 #define BUINT32_VALUE(lval)     OSReadBigInt32 (&(lval), 0)
3038 /* Return UVS subtable for the specified FONT.  If the subtable is not
3039    found or ill-formatted, then return NULL.  */
3041 static CFDataRef
3042 mac_font_copy_uvs_table (FontRef font)
3044   CFDataRef cmap_table, uvs_table = NULL;
3046   cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3047   if (cmap_table)
3048     {
3049       sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3050       struct uvs_table *uvs;
3051       struct variation_selector_record *records;
3052       UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3054 #if __LP64__
3055       if (CFDataGetLength (cmap_table) > UINT32_MAX)
3056         goto finish;
3057 #endif
3059       cmap_len = CFDataGetLength (cmap_table);
3060       if (sizeof_sfntCMapHeader > cmap_len)
3061         goto finish;
3063       ntables = BUINT16_VALUE (cmap->numTables);
3064       if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3065                      / sizeof_sfntCMapEncoding))
3066         goto finish;
3068       for (i = 0; i < ntables; i++)
3069         if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3070              == kFontUnicodePlatform)
3071             && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3072                 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3073           {
3074             uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3075             break;
3076           }
3077       if (i == ntables
3078           || uvs_offset > cmap_len
3079           || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3080         goto finish;
3082       uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3083       uvs_len = BUINT32_VALUE (uvs->length);
3084       if (uvs_len > cmap_len - uvs_offset
3085           || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3086         goto finish;
3088       if (BUINT16_VALUE (uvs->format) != 14)
3089         goto finish;
3091       nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3092       if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3093                       / sizeof (struct variation_selector_record)))
3094         goto finish;
3096       records = uvs->variation_selector_records;
3097       for (i = 0; i < nrecords; i++)
3098         {
3099           UInt32 default_uvs_offset, non_default_uvs_offset;
3101           default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3102           if (default_uvs_offset)
3103             {
3104               struct default_uvs_table *default_uvs;
3105               UInt32 nranges;
3107               if (default_uvs_offset > uvs_len
3108                   || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3109                       > uvs_len - default_uvs_offset))
3110                 goto finish;
3112               default_uvs = ((struct default_uvs_table *)
3113                              ((UInt8 *) uvs + default_uvs_offset));
3114               nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3115               if (nranges > ((uvs_len - default_uvs_offset
3116                               - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3117                              / sizeof (struct unicode_value_range)))
3118                 goto finish;
3119               /* Now 2 * nranges can't overflow, so we can safely use
3120                  `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3121                  mac_font_get_glyphs_for_variants.  */
3122             }
3124           non_default_uvs_offset =
3125             BUINT32_VALUE (records[i].non_default_uvs_offset);
3126           if (non_default_uvs_offset)
3127             {
3128               struct non_default_uvs_table *non_default_uvs;
3129               UInt32 nmappings;
3131               if (non_default_uvs_offset > uvs_len
3132                   || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3133                       > uvs_len - non_default_uvs_offset))
3134                 goto finish;
3136               non_default_uvs = ((struct non_default_uvs_table *)
3137                                  ((UInt8 *) uvs + non_default_uvs_offset));
3138               nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3139               if (nmappings > ((uvs_len - non_default_uvs_offset
3140                                 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3141                                / sizeof (struct uvs_mapping)))
3142                 goto finish;
3143               /* Now 2 * nmappings can't overflow, so we can safely
3144                  use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3145                  in mac_font_get_glyphs_for_variants.  */
3146             }
3147         }
3149       uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3151     finish:
3152       CFRelease (cmap_table);
3153     }
3155   return uvs_table;
3158 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3159    sequence consisting of the given base character C and each
3160    variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3161    result (explained below) into the corresponding GLYPHS[i].  If the
3162    entry is found in the Default UVS Table, then the result is 0.  If
3163    the entry is found in the Non-Default UVS Table, then the result is
3164    the associated glyph ID.  Otherwise, kCGFontIndexInvalid.  The
3165    elements in SELECTORS must be sorted in strictly increasing
3166    order.  */
3168 static void
3169 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3170                                   const UTF32Char selectors[], CGGlyph glyphs[],
3171                                   CFIndex count)
3173   struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3174   struct variation_selector_record *records = uvs->variation_selector_records;
3175   CFIndex i;
3176   UInt32 ir, nrecords;
3177 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3178   dispatch_queue_t queue =
3179     dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3180   dispatch_group_t group = dispatch_group_create ();
3181 #endif
3183   nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3184   i = 0;
3185   ir = 0;
3186   while (i < count && ir < nrecords)
3187     {
3188       UInt32 default_uvs_offset, non_default_uvs_offset;
3190       if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3191         {
3192           glyphs[i++] = kCGFontIndexInvalid;
3193           continue;
3194         }
3195       else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3196         {
3197           ir++;
3198           continue;
3199         }
3201       /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3202       default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3203       non_default_uvs_offset =
3204         BUINT32_VALUE (records[ir].non_default_uvs_offset);
3205 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3206       dispatch_group_async (group, queue, ^{
3207 #endif
3208           glyphs[i] = kCGFontIndexInvalid;
3210           if (default_uvs_offset)
3211             {
3212               struct default_uvs_table *default_uvs =
3213                 (struct default_uvs_table *) ((UInt8 *) uvs
3214                                               + default_uvs_offset);
3215               struct unicode_value_range *ranges =
3216                 default_uvs->unicode_value_ranges;
3217               UInt32 lo, hi;
3219               lo = 0;
3220               hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3221               while (lo < hi)
3222                 {
3223                   UInt32 mid = (lo + hi) / 2;
3225                   if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3226                     hi = mid;
3227                   else
3228                     lo = mid + 1;
3229                 }
3230               if (hi > 0
3231                   && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3232                             + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3233                 glyphs[i] = 0;
3234             }
3236           if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3237             {
3238               struct non_default_uvs_table *non_default_uvs =
3239                 (struct non_default_uvs_table *) ((UInt8 *) uvs
3240                                                   + non_default_uvs_offset);
3241               struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3242               UInt32 lo, hi;
3244               lo = 0;
3245               hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3246               while (lo < hi)
3247                 {
3248                   UInt32 mid = (lo + hi) / 2;
3250                   if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3251                     hi = mid;
3252                   else
3253                     lo = mid + 1;
3254                 }
3255               if (hi > 0 &&
3256                   BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3257                 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3258             }
3259 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3260         });
3261 #endif
3262       i++;
3263       ir++;
3264     }
3265   while (i < count)
3266     glyphs[i++] = kCGFontIndexInvalid;
3267 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3268   dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3269   dispatch_release (group);
3270 #endif
3273 static int
3274 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3276   CFDataRef uvs_table;
3277   CharacterCollection uvs_collection;
3278   int i, n = 0;
3280   block_input ();
3281   uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3283   if (uvs_table)
3284     {
3285       UTF32Char selectors[256];
3286       CGGlyph glyphs[256];
3288       for (i = 0; i < 16; i++)
3289         selectors[i] = 0xFE00 + i;
3290       for (; i < 256; i++)
3291         selectors[i] = 0xE0100 + (i - 16);
3292       mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3293       for (i = 0; i < 256; i++)
3294         {
3295           CGGlyph glyph = glyphs[i];
3297           if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3298               && glyph != kCGFontIndexInvalid)
3299             glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3300           if (glyph == kCGFontIndexInvalid)
3301             variations[i] = 0;
3302           else
3303             {
3304               variations[i] = (glyph ? glyph
3305                                : macfont_get_glyph_for_character (font, c));
3306               n++;
3307             }
3308         }
3309     }
3310   unblock_input ();
3312   return n;
3315 static const char *const macfont_booleans[] = {
3316   ":antialias",
3317   ":minspace",
3318   NULL,
3321 static const char *const macfont_non_booleans[] = {
3322   ":lang",
3323   ":script",
3324   ":destination",
3325   NULL,
3328 static void
3329 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3331   font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3334 static Boolean
3335 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3336                                           CFArrayRef languages)
3338   Boolean result = true;
3339   CFArrayRef desc_languages =
3340     CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3342   if (desc_languages == NULL)
3343     result = false;
3344   else
3345     {
3346       CFIndex desc_languages_count, i, languages_count;
3348       desc_languages_count = CFArrayGetCount (desc_languages);
3349       languages_count = CFArrayGetCount (languages);
3350       for (i = 0; i < languages_count; i++)
3351         if (!CFArrayContainsValue (desc_languages,
3352                                    CFRangeMake (0, desc_languages_count),
3353                                    CFArrayGetValueAtIndex (languages, i)))
3354           {
3355             result = false;
3356             break;
3357           }
3358       CFRelease (desc_languages);
3359     }
3361   return result;
3364 static CFStringRef
3365 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3367   CFStringRef result = NULL;
3368   CFStringRef charset_string =
3369     CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3371   if (charset_string && CFStringGetLength (charset_string) > 0)
3372     {
3373       CFStringRef keys[] = {
3374 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3375         kCTLanguageAttributeName
3376 #else
3377         CFSTR ("NSLanguage")
3378 #endif
3379       };
3380       CFTypeRef values[] = {NULL};
3381       CFIndex num_values = 0;
3382       CFArrayRef languages
3383         = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3385       if (languages && CFArrayGetCount (languages) > 0)
3386         {
3387           if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3388             values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3389           else
3390             {
3391               CFCharacterSetRef charset =
3392                 CFDictionaryGetValue (attributes,
3393                                       MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3395               result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3396             }
3397         }
3398       if (result == NULL)
3399         {
3400           CFAttributedStringRef attr_string = NULL;
3401           CTLineRef ctline = NULL;
3402           CFDictionaryRef attrs
3403             = CFDictionaryCreate (NULL, (const void **) keys,
3404                                   (const void **) values, num_values,
3405                                   &kCFTypeDictionaryKeyCallBacks,
3406                                   &kCFTypeDictionaryValueCallBacks);
3408           if (attrs)
3409             {
3410               attr_string = CFAttributedStringCreate (NULL, charset_string,
3411                                                       attrs);
3412               CFRelease (attrs);
3413             }
3414           if (attr_string)
3415             {
3416               ctline = CTLineCreateWithAttributedString (attr_string);
3417               CFRelease (attr_string);
3418             }
3419           if (ctline)
3420             {
3421               CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3422               CFIndex i, nruns = CFArrayGetCount (runs);
3423               CTFontRef font;
3425               for (i = 0; i < nruns; i++)
3426                 {
3427                   CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3428                   CFDictionaryRef attributes = CTRunGetAttributes (run);
3429                   CTFontRef font_in_run;
3431                   if (attributes == NULL)
3432                     break;
3433                   font_in_run =
3434                     CFDictionaryGetValue (attributes, kCTFontAttributeName);
3435                   if (font_in_run == NULL)
3436                     break;
3437                   if (i == 0)
3438                     font = font_in_run;
3439                   else if (!mac_ctfont_equal_in_postscript_name (font,
3440                                                                  font_in_run))
3441                     break;
3442                 }
3443               if (nruns > 0 && i == nruns)
3444                 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3445               CFRelease (ctline);
3446             }
3447         }
3448     }
3450   return result;
3453 static inline double
3454 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3456   return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3457                                      &glyph, NULL, 1);
3460 static inline CGRect
3461 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3463   return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3464                                           &glyph, NULL, 1);
3467 static CFArrayRef
3468 mac_ctfont_create_available_families (void)
3470   CFMutableArrayRef families = NULL;
3472 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3473 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3474   if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3475 #endif
3476     {
3477       CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3479       if (orig_families)
3480         {
3481           CFIndex i, count = CFArrayGetCount (orig_families);
3483           families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3484           if (families)
3485             for (i = 0; i < count; i++)
3486               {
3487                 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3489                 if (!CFStringHasPrefix (family, CFSTR ("."))
3490                     && (CTFontManagerCompareFontFamilyNames (family,
3491                                                              CFSTR ("LastResort"),
3492                                                              NULL)
3493                         != kCFCompareEqualTo))
3494                   CFArrayAppendValue (families, family);
3495               }
3496           CFRelease (orig_families);
3497         }
3498     }
3499 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3500   else         /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3501 #endif
3502 #endif  /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3503 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3504     {
3505       CTFontCollectionRef collection;
3506       CFArrayRef descs = NULL;
3508       collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3509       if (collection)
3510         {
3511           descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3512           CFRelease (collection);
3513         }
3514       if (descs)
3515         {
3516           CFIndex i, count = CFArrayGetCount (descs);
3518           families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3519           if (families)
3520             for (i = 0; i < count; i++)
3521               {
3522                 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3523                 CFStringRef name =
3524                   mac_font_descriptor_copy_attribute (desc,
3525                                                       MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3527                 if (name)
3528                   {
3529                     CFIndex p, limit = CFArrayGetCount (families);
3531                     p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3532                                               (const void *) name,
3533                                               mac_font_family_compare, NULL);
3534                     if (p >= limit)
3535                       CFArrayAppendValue (families, name);
3536                     else if (mac_font_family_compare
3537                              (CFArrayGetValueAtIndex (families, p),
3538                               name, NULL) != kCFCompareEqualTo)
3539                       CFArrayInsertValueAtIndex (families, p, name);
3540                     CFRelease (name);
3541                   }
3542               }
3543           CFRelease (descs);
3544         }
3545     }
3546 #endif
3548   return families;
3551 static Boolean
3552 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3554   Boolean result;
3555   CFStringRef name1, name2;
3557   if (font1 == font2)
3558     return true;
3560   result = false;
3561   name1 = CTFontCopyPostScriptName (font1);
3562   if (name1)
3563     {
3564       name2 = CTFontCopyPostScriptName (font2);
3565       if (name2)
3566         {
3567           result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo);
3568           CFRelease (name2);
3569         }
3570       CFRelease (name1);
3571     }
3573   return result;
3576 static CTLineRef
3577 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3578                                              CTFontRef macfont)
3580   CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3581   CFTypeRef values[] = {NULL, NULL};
3582   CFDictionaryRef attributes = NULL;
3583   CFAttributedStringRef attr_string = NULL;
3584   CTLineRef ctline = NULL;
3585   float float_zero = 0.0f;
3587   values[0] = macfont;
3588   values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3589   if (values[1])
3590     {
3591       attributes = CFDictionaryCreate (NULL, (const void **) keys,
3592                                        (const void **) values,
3593                                        sizeof (keys) / sizeof (keys[0]),
3594                                        &kCFTypeDictionaryKeyCallBacks,
3595                                        &kCFTypeDictionaryValueCallBacks);
3596       CFRelease (values[1]);
3597     }
3598   if (attributes)
3599     {
3600       attr_string = CFAttributedStringCreate (NULL, string, attributes);
3601       CFRelease (attributes);
3602     }
3603   if (attr_string)
3604     {
3605       ctline = CTLineCreateWithAttributedString (attr_string);
3606       CFRelease (attr_string);
3607     }
3608   if (ctline)
3609     {
3610       /* Abandon if ctline contains some fonts other than the
3611          specified one.  */
3612       CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3613       CFIndex i, nruns = CFArrayGetCount (runs);
3615       for (i = 0; i < nruns; i++)
3616         {
3617           CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3618           CFDictionaryRef attributes = CTRunGetAttributes (run);
3619           CTFontRef font_in_run;
3621           if (attributes == NULL)
3622             break;
3623           font_in_run =
3624             CFDictionaryGetValue (attributes, kCTFontAttributeName);
3625           if (font_in_run == NULL)
3626             break;
3627           if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3628             break;
3629         }
3630       if (i < nruns)
3631         {
3632           CFRelease (ctline);
3633           ctline = NULL;
3634         }
3635     }
3637   return ctline;
3640 static CFIndex
3641 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3642                   struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3644   CFIndex used, result = 0;
3645   CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3647   if (ctline == NULL)
3648     return 0;
3650   used = CTLineGetGlyphCount (ctline);
3651   if (used <= glyph_len)
3652     {
3653       CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3654       CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3655       CGFloat total_advance = 0;
3656       CFIndex total_glyph_count = 0;
3658       for (k = 0; k < ctrun_count; k++)
3659         {
3660           CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3661           CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3662           struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3663           CFRange string_range, comp_range, range;
3664           CFIndex *permutation;
3666           if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3667             permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3668           else
3669             permutation = NULL;
3671 #define RIGHT_TO_LEFT_P permutation
3673           /* Now the `comp_range' member of struct mac_glyph_layout is
3674              temporarily used as a work area such that:
3675               glbuf[i].comp_range.location =
3676                 min {compRange[i + 1].location, ...,
3677                      compRange[glyph_count - 1].location,
3678                      maxRange (stringRangeForCTRun)}
3679               glbuf[i].comp_range.length = maxRange (compRange[i])
3680              where compRange[i] is the range of composed characters
3681              containing i-th glyph.  */
3682           string_range = CTRunGetStringRange (ctrun);
3683           min_location = string_range.location + string_range.length;
3684           for (i = 0; i < glyph_count; i++)
3685             {
3686               struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3687               CFIndex glyph_index;
3688               CFRange rng;
3690               if (!RIGHT_TO_LEFT_P)
3691                 glyph_index = glyph_count - i - 1;
3692               else
3693                 glyph_index = i;
3694               CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3695                                      &gl->string_index);
3696               rng =
3697                 CFStringGetRangeOfComposedCharactersAtIndex (string,
3698                                                              gl->string_index);
3699               gl->comp_range.location = min_location;
3700               gl->comp_range.length = rng.location + rng.length;
3701               if (rng.location < min_location)
3702                 min_location = rng.location;
3703             }
3705           /* Fill the `comp_range' member of struct mac_glyph_layout,
3706              and setup a permutation for right-to-left text.  */
3707           comp_range = CFRangeMake (string_range.location, 0);
3708           range = CFRangeMake (0, 0);
3709           while (1)
3710             {
3711               struct mac_glyph_layout *gl =
3712                 glbuf + range.location + range.length;
3714               if (gl->comp_range.length
3715                   > comp_range.location + comp_range.length)
3716                 comp_range.length = gl->comp_range.length - comp_range.location;
3717               min_location = gl->comp_range.location;
3718               range.length++;
3720               if (min_location >= comp_range.location + comp_range.length)
3721                 {
3722                   comp_range.length = min_location - comp_range.location;
3723                   for (i = 0; i < range.length; i++)
3724                     {
3725                       glbuf[range.location + i].comp_range = comp_range;
3726                       if (RIGHT_TO_LEFT_P)
3727                         permutation[range.location + i] =
3728                           range.location + range.length - i - 1;
3729                     }
3731                   comp_range = CFRangeMake (min_location, 0);
3732                   range.location += range.length;
3733                   range.length = 0;
3734                   if (range.location == glyph_count)
3735                     break;
3736                 }
3737             }
3739           /* Then fill the remaining members.  */
3740           for (range = CFRangeMake (0, 1); range.location < glyph_count;
3741                range.location++)
3742             {
3743               struct mac_glyph_layout *gl;
3744               CGPoint position;
3746               if (!RIGHT_TO_LEFT_P)
3747                 gl = glbuf + range.location;
3748               else
3749                 {
3750                   CFIndex src, dest;
3752                   src = glyph_count - 1 - range.location;
3753                   dest = permutation[src];
3754                   gl = glbuf + dest;
3755                   if (src < dest)
3756                     {
3757                       CFIndex tmp = gl->string_index;
3759                       gl->string_index = glbuf[src].string_index;
3760                       glbuf[src].string_index = tmp;
3761                     }
3762                 }
3763               CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3765               CTRunGetPositions (ctrun, range, &position);
3766               gl->advance_delta = position.x - total_advance;
3767               gl->baseline_delta = position.y;
3768               gl->advance = (gl->advance_delta
3769                              + CTRunGetTypographicBounds (ctrun, range,
3770                                                           NULL, NULL, NULL));
3771               total_advance += gl->advance;
3772             }
3774           if (RIGHT_TO_LEFT_P)
3775             xfree (permutation);
3777 #undef RIGHT_TO_LEFT_P
3779           total_glyph_count += glyph_count;
3780         }
3782       result = used;
3783     }
3784   CFRelease (ctline);
3786   return result;
3789 /* The function below seems to cause a memory leak for the CFString
3790    created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3791    10.6.3.  For now, we use the NSGlyphInfo version instead.  */
3792 #if USE_CT_GLYPH_INFO
3793 static CGGlyph
3794 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3795                               CGFontIndex cid)
3797   CGGlyph result = kCGFontIndexInvalid;
3798   UniChar characters[] = {0xfffd};
3799   CFStringRef string;
3800   CFAttributedStringRef attr_string = NULL;
3801   CTLineRef ctline = NULL;
3803   string = CFStringCreateWithCharacters (NULL, characters,
3804                                          sizeof (characters)
3805                                          / sizeof (characters[0]));
3806   if (string)
3807     {
3808       CTGlyphInfoRef glyph_info =
3809         CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3810       CFDictionaryRef attributes = NULL;
3812       if (glyph_info)
3813         {
3814           CFStringRef keys[] = {kCTFontAttributeName,
3815                                 kCTGlyphInfoAttributeName};
3816           CFTypeRef values[] = {font, glyph_info};
3818           attributes = CFDictionaryCreate (NULL, (const void **) keys,
3819                                            (const void **) values,
3820                                            sizeof (keys) / sizeof (keys[0]),
3821                                            &kCFTypeDictionaryKeyCallBacks,
3822                                            &kCFTypeDictionaryValueCallBacks);
3823           CFRelease (glyph_info);
3824         }
3825       if (attributes)
3826         {
3827           attr_string = CFAttributedStringCreate (NULL, string, attributes);
3828           CFRelease (attributes);
3829         }
3830       CFRelease (string);
3831     }
3832   if (attr_string)
3833     {
3834       ctline = CTLineCreateWithAttributedString (attr_string);
3835       CFRelease (attr_string);
3836     }
3837   if (ctline)
3838     {
3839       CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3841       if (CFArrayGetCount (runs) > 0)
3842         {
3843           CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3844           CFDictionaryRef attributes = CTRunGetAttributes (run);
3846           if (attributes)
3847             {
3848               CTFontRef font_in_run =
3849                 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3851               if (font_in_run
3852                   && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3853                 {
3854                   CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3855                   if (result >= CTFontGetGlyphCount (font))
3856                     result = kCGFontIndexInvalid;
3857                 }
3858             }
3859         }
3860       CFRelease (ctline);
3861     }
3863   return result;
3865 #endif
3867 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3868 static inline int
3869 mac_font_family_group (CFStringRef family)
3871   if (CFStringHasPrefix (family, CFSTR ("#")))
3872     return 2;
3873   else
3874     {
3875       CFRange range;
3877       range = CFStringFind (family, CFSTR ("Apple"),
3878                             kCFCompareCaseInsensitive | kCFCompareAnchored);
3879       if (range.location != kCFNotFound)
3880         return 1;
3882       return 0;
3883     }
3886 static CFComparisonResult
3887 mac_font_family_compare (const void *val1, const void *val2, void *context)
3889   CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3890   int group1, group2;
3892   group1 = mac_font_family_group (family1);
3893   group2 = mac_font_family_group (family2);
3894   if (group1 < group2)
3895     return kCFCompareLessThan;
3896   if (group1 > group2)
3897     return kCFCompareGreaterThan;
3898   return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3900 #endif  /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3902 static CFArrayRef
3903 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3905   CFArrayRef result = NULL;
3907 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3908 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3909   if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3910 #endif
3911     {
3912       CTFontRef user_font =
3913         CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3915       if (user_font)
3916         {
3917           CFArrayRef languages =
3918             CFArrayCreate (NULL, (const void **) &language, 1,
3919                            &kCFTypeArrayCallBacks);
3921           if (languages)
3922             {
3923               result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3924                                                                  languages);
3925               CFRelease (languages);
3926             }
3927           CFRelease (user_font);
3928         }
3929     }
3930 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3931   else          /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3932 #endif
3933 #endif  /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3934 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3935     {
3936       CFIndex i;
3938       for (i = 0; macfont_language_default_font_names[i].language; i++)
3939         {
3940           if (CFStringCompare (macfont_language_default_font_names[i].language,
3941                                language, 0) == kCFCompareEqualTo)
3942             {
3943               CFMutableArrayRef descriptors =
3944                 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3946               if (descriptors)
3947                 {
3948                   CFIndex j;
3950                   for (j = 0;
3951                        macfont_language_default_font_names[i].font_names[j];
3952                        j++)
3953                     {
3954                       CFDictionaryRef attributes =
3955                         CFDictionaryCreate (NULL,
3956                                             ((const void **)
3957                                              &MAC_FONT_NAME_ATTRIBUTE),
3958                                             ((const void **)
3959                                              &macfont_language_default_font_names[i].font_names[j]),
3960                                             1, &kCFTypeDictionaryKeyCallBacks,
3961                                             &kCFTypeDictionaryValueCallBacks);
3963                       if (attributes)
3964                         {
3965                           FontDescriptorRef pat_desc =
3966                             mac_font_descriptor_create_with_attributes (attributes);
3968                           if (pat_desc)
3969                             {
3970                               FontDescriptorRef descriptor =
3971                                 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3973                               if (descriptor)
3974                                 {
3975                                   CFArrayAppendValue (descriptors, descriptor);
3976                                   CFRelease (descriptor);
3977                                 }
3978                               CFRelease (pat_desc);
3979                             }
3980                           CFRelease (attributes);
3981                         }
3982                     }
3983                   result = descriptors;
3984                 }
3985               break;
3986             }
3987         }
3988     }
3989 #endif
3991   return result;
3994 static CFStringRef
3995 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3996                                                       CFArrayRef languages)
3998   CFStringRef result = NULL;
3999   CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
4000   CFArrayRef descriptors =
4001     mac_font_copy_default_descriptors_for_language (language);
4003   if (descriptors)
4004     {
4005       CFIndex i, count = CFArrayGetCount (descriptors);
4007       for (i = 0; i < count; i++)
4008         {
4009           FontDescriptorRef descriptor =
4010             CFArrayGetValueAtIndex (descriptors, i);
4012           if (macfont_supports_charset_and_languages_p (descriptor, charset,
4013                                                         Qnil, languages))
4014             {
4015               CFStringRef family =
4016                 mac_font_descriptor_copy_attribute (descriptor,
4017                                                     MAC_FONT_FAMILY_NAME_ATTRIBUTE);
4018               if (family)
4019                 {
4020                   if (!CFStringHasPrefix (family, CFSTR ("."))
4021                       && (CFStringCompare (family, CFSTR ("LastResort"), 0)
4022                           != kCFCompareEqualTo))
4023                     {
4024                       result = family;
4025                       break;
4026                     }
4027                   else
4028                     CFRelease (family);
4029                 }
4030             }
4031         }
4032       CFRelease (descriptors);
4033     }
4035   return result;
4038 void *
4039 macfont_get_nsctfont (struct font *font)
4041   struct macfont_info *macfont_info = (struct macfont_info *) font;
4042   FontRef macfont = macfont_info->macfont;
4044   return (void *) macfont;
4047 void
4048 mac_register_font_driver (struct frame *f)
4050   register_font_driver (&macfont_driver, f);
4053 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4056 void
4057 syms_of_macfont (void)
4059 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4060   static struct font_driver mac_font_driver;
4062   DEFSYM (Qmac_ct, "mac-ct");
4063   macfont_driver.type = Qmac_ct;
4064   register_font_driver (&macfont_driver, NULL);
4066   DEFSYM (QCdestination, ":destination");
4067   DEFSYM (QCminspace, ":minspace");
4068 #endif