* net/tramp-sh.el (tramp-histfile-override): Clarify docstring.
[emacs.git] / src / macfont.m
blob705483905837cef249c2e0b1c734a8c92bb7db7f
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 #include <libkern/OSByteOrder.h>
41 static struct font_driver macfont_driver;
43 /* Core Text, for Mac OS X.  */
44 static Lisp_Object Qmac_ct;
46 static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
47 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
48 static CFArrayRef mac_ctfont_create_available_families (void);
49 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
50 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
51                                                               CTFontRef);
52 static CFComparisonResult mac_font_family_compare (const void *,
53                                                    const void *, void *);
54 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
55                                                          CFArrayRef);
56 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
57 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
58                                  struct mac_glyph_layout *, CFIndex);
59 static CFArrayRef
60 mac_font_copy_default_descriptors_for_language (CFStringRef language);
62 static CFStringRef
63 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
64                                                       CFArrayRef languages);
66 #if USE_CT_GLYPH_INFO
67 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
68                                              CTCharacterCollection,
69                                              CGFontIndex);
70 #endif
72 /* The font property key specifying the font design destination.  The
73    value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
74    text.  (See the documentation of X Logical Font Description
75    Conventions.)  In the Mac font driver, 1 means the screen font is
76    used for calculating some glyph metrics.  You can see the
77    difference with Monaco 8pt or 9pt, for example.  */
78 static Lisp_Object QCdestination;
80 /* The boolean-valued font property key specifying the use of
81    leading.  */
82 static Lisp_Object QCminspace;
84 struct macfont_metrics;
86 /* The actual structure for Mac font that can be cast to struct font.  */
88 struct macfont_info
90   struct font font;
91   FontRef macfont;
92   CGFontRef cgfont;
93   ScreenFontRef screen_font;
94   struct macfont_cache *cache;
95   struct macfont_metrics **metrics;
96   short metrics_nrows;
97   bool_bf synthetic_italic_p : 1;
98   bool_bf synthetic_bold_p : 1;
99   unsigned spacing : 2;
100   unsigned antialias : 2;
101   bool_bf color_bitmap_p : 1;
104 /* Values for the `spacing' member in `struct macfont_info'.  */
106 enum
107   {
108     MACFONT_SPACING_PROPORTIONAL,
109     MACFONT_SPACING_MONO,
110     MACFONT_SPACING_SYNTHETIC_MONO,
111   };
113 /* Values for the `antialias' member in `struct macfont_info'.  */
115 enum
116   {
117     MACFONT_ANTIALIAS_DEFAULT,
118     MACFONT_ANTIALIAS_OFF,
119     MACFONT_ANTIALIAS_ON,
120   };
122 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
123 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200};  /* FC_WEIGHT_BOLD */
124 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
126 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
127 static const CGFloat synthetic_bold_factor = 0.024;
129 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
130                                                         FontSymbolicTraits *);
131 static void macfont_store_descriptor_attributes (FontDescriptorRef,
132                                                  Lisp_Object);
133 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
134                                               Lisp_Object,
135                                               FontSymbolicTraits);
136 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
137 static int macfont_glyph_extents (struct font *, CGGlyph,
138                                   struct font_metrics *, CGFloat *, int);
139 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
140 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
141                                                          CFCharacterSetRef,
142                                                          Lisp_Object,
143                                                          CFArrayRef);
144 static Boolean macfont_closest_traits_index_p (CFArrayRef, FontSymbolicTraits,
145                                                CFIndex);
146 static CFDataRef mac_font_copy_uvs_table (FontRef);
147 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
148                                               const UTF32Char [],
149                                               CGGlyph [], CFIndex);
151 /* From CFData to a lisp string.  Always returns a unibyte string.  */
153 static Lisp_Object
154 cfdata_to_lisp (CFDataRef data)
156   CFIndex len = CFDataGetLength (data);
157   Lisp_Object result = make_uninit_string (len);
159   CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
161   return result;
166 /* From CFString to a lisp string.  Returns a unibyte string
167    containing a UTF-8 byte sequence.  */
169 static Lisp_Object
170 cfstring_to_lisp_nodecode (CFStringRef string)
172   Lisp_Object result = Qnil;
173   CFDataRef data;
174   const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
176   if (s)
177     {
178       CFIndex i, length = CFStringGetLength (string);
180       for (i = 0; i < length; i++)
181         if (CFStringGetCharacterAtIndex (string, i) == 0)
182           break;
184       if (i == length)
185         return make_unibyte_string (s, strlen (s));
186     }
188   data = CFStringCreateExternalRepresentation (NULL, string,
189                                                kCFStringEncodingUTF8, '?');
190   if (data)
191     {
192       result = cfdata_to_lisp (data);
193       CFRelease (data);
194     }
196   return result;
199 /* Lisp string containing a UTF-8 byte sequence to CFString.  Unlike
200    cfstring_create_with_utf8_cstring, this function preserves NUL
201    characters.  */
203 static CFStringRef
204 cfstring_create_with_string_noencode (Lisp_Object s)
206   CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
207                                                 kCFStringEncodingUTF8, false);
209   if (string == NULL)
210     /* Failed to interpret as UTF 8.  Fall back on Mac Roman.  */
211     string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
212                                       kCFStringEncodingMacRoman, false);
214   return string;
217 static CGFloat
218 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
220   NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
222   return advancement.width;
225 static CGGlyph
226 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
227                             CGFontIndex cid)
229 #if USE_CT_GLYPH_INFO
230   return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
231 #else
232   {
233     CGGlyph result = kCGFontIndexInvalid;
234     NSFont *nsFont = (NSFont *) font;
235     unichar characters[] = {0xfffd};
236     NSString *string =
237       [NSString stringWithCharacters:characters
238                               length:ARRAYELTS (characters)];
239     NSGlyphInfo *glyphInfo =
240       [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
241                                          collection:collection
242                                          baseString:string];
243     NSDictionary *attributes =
244       [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
245                     glyphInfo,NSGlyphInfoAttributeName,nil];
246     NSTextStorage *textStorage =
247       [[NSTextStorage alloc] initWithString:string
248                                  attributes:attributes];
249     NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
250     NSTextContainer *textContainer = [[NSTextContainer alloc] init];
251     NSFont *fontInTextStorage;
253     [layoutManager addTextContainer:textContainer];
254     [textContainer release];
255     [textStorage addLayoutManager:layoutManager];
256     [layoutManager release];
258     /* Force layout.  */
259     (void) [layoutManager glyphRangeForTextContainer:textContainer];
261     fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
262                                 effectiveRange:NULL];
263     if (fontInTextStorage == nsFont
264         || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
265       {
266         NSGlyph glyph = [layoutManager glyphAtIndex:0];
268         if (glyph < [nsFont numberOfGlyphs])
269           result = glyph;
270       }
272     [textStorage release];
274     return result;
275   }
277 #endif
279 static ScreenFontRef
280 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
282   NSFont *result, *font;
284   font = [NSFont fontWithName:((NSString *) name) size:size];
285   result = [font screenFont];
287   return (ScreenFontRef)[result retain];
291 static Boolean
292 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
293                              CGFloat *descent, CGFloat *leading)
295   NSFont *nsFont = [(NSFont *)font printerFont];
296   NSTextStorage *textStorage;
297   NSLayoutManager *layoutManager;
298   NSTextContainer *textContainer;
299   NSRect usedRect;
300   NSPoint spaceLocation;
301   CGFloat descender;
303   textStorage = [[NSTextStorage alloc] initWithString:@" "];
304   layoutManager = [[NSLayoutManager alloc] init];
305   textContainer = [[NSTextContainer alloc] init];
307   [textStorage setFont:nsFont];
308   [textContainer setLineFragmentPadding:0];
309   [layoutManager setUsesScreenFonts:YES];
311   [layoutManager addTextContainer:textContainer];
312   [textContainer release];
313   [textStorage addLayoutManager:layoutManager];
314   [layoutManager release];
316   if (!(textStorage && layoutManager && textContainer))
317     {
318       [textStorage release];
320       return false;
321     }
323   usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
324                                                  effectiveRange:NULL];
325   spaceLocation = [layoutManager locationForGlyphAtIndex:0];
326   [textStorage release];
328   *ascent = spaceLocation.y;
329   *descent = NSHeight (usedRect) - spaceLocation.y;
330   *leading = 0;
331   descender = [nsFont descender];
332   if (- descender < *descent)
333     {
334       *leading = *descent + descender;
335       *descent = - descender;
336     }
338   return true;
341 static CFIndex
342 mac_font_shape_1 (NSFont *font, NSString *string,
343                   struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
344                   BOOL screen_font_p)
346   NSUInteger i;
347   CFIndex result = 0;
348   NSTextStorage *textStorage;
349   NSLayoutManager *layoutManager;
350   NSTextContainer *textContainer;
351   NSUInteger stringLength;
352   NSPoint spaceLocation;
353   NSUInteger used, numberOfGlyphs;
355   textStorage = [[NSTextStorage alloc] initWithString:string];
356   layoutManager = [[NSLayoutManager alloc] init];
357   textContainer = [[NSTextContainer alloc] init];
359   /* Append a trailing space to measure baseline position.  */
360   [textStorage appendAttributedString:([[[NSAttributedString alloc]
361                                           initWithString:@" "] autorelease])];
362   [textStorage setFont:font];
363   [textContainer setLineFragmentPadding:0];
364   [layoutManager setUsesScreenFonts:screen_font_p];
366   [layoutManager addTextContainer:textContainer];
367   [textContainer release];
368   [textStorage addLayoutManager:layoutManager];
369   [layoutManager release];
371   if (!(textStorage && layoutManager && textContainer))
372     {
373       [textStorage release];
375       return 0;
376     }
378   stringLength = [string length];
380   /* Force layout.  */
381   (void) [layoutManager glyphRangeForTextContainer:textContainer];
383   spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
385   /* Remove the appended trailing space because otherwise it may
386      generate a wrong result for a right-to-left text.  */
387   [textStorage beginEditing];
388   [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
389   [textStorage endEditing];
390   (void) [layoutManager glyphRangeForTextContainer:textContainer];
392   i = 0;
393   while (i < stringLength)
394     {
395       NSRange range;
396       NSFont *fontInTextStorage =
397         [textStorage attribute:NSFontAttributeName atIndex:i
398                      longestEffectiveRange:&range
399                        inRange:(NSMakeRange (0, stringLength))];
401       if (!(fontInTextStorage == font
402             || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
403         break;
404       i = NSMaxRange (range);
405     }
406   if (i < stringLength)
407     /* Make the test `used <= glyph_len' below fail if textStorage
408        contained some fonts other than the specified one.  */
409     used = glyph_len + 1;
410   else
411     {
412       NSRange range = NSMakeRange (0, stringLength);
414       range = [layoutManager glyphRangeForCharacterRange:range
415                                     actualCharacterRange:NULL];
416       numberOfGlyphs = NSMaxRange (range);
417       used = numberOfGlyphs;
418       for (i = 0; i < numberOfGlyphs; i++)
419         if ([layoutManager notShownAttributeForGlyphAtIndex:i])
420           used--;
421     }
423   if (0 < used && used <= glyph_len)
424     {
425       NSUInteger glyphIndex, prevGlyphIndex;
426       unsigned char bidiLevel;
427       NSUInteger *permutation;
428       NSRange compRange, range;
429       CGFloat totalAdvance;
431       glyphIndex = 0;
432       while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
433         glyphIndex++;
435       /* For now we assume the direction is not changed within the
436          string.  */
437       [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
438                                glyphs:NULL characterIndexes:NULL
439                     glyphInscriptions:NULL elasticBits:NULL
440                            bidiLevels:&bidiLevel];
441       if (bidiLevel & 1)
442         permutation = xmalloc (sizeof (NSUInteger) * used);
443       else
444         permutation = NULL;
446 #define RIGHT_TO_LEFT_P permutation
448       /* Fill the `comp_range' member of struct mac_glyph_layout, and
449          setup a permutation for right-to-left text.  */
450       compRange = NSMakeRange (0, 0);
451       for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
452            range.length++)
453         {
454           struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
455           NSUInteger characterIndex =
456             [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
458           gl->string_index = characterIndex;
460           if (characterIndex >= NSMaxRange (compRange))
461             {
462               compRange.location = NSMaxRange (compRange);
463               do
464                 {
465                   NSRange characterRange =
466                     [string
467                       rangeOfComposedCharacterSequenceAtIndex:characterIndex];
469                   compRange.length =
470                     NSMaxRange (characterRange) - compRange.location;
471                   [layoutManager glyphRangeForCharacterRange:compRange
472                                         actualCharacterRange:&characterRange];
473                   characterIndex = NSMaxRange (characterRange) - 1;
474                 }
475               while (characterIndex >= NSMaxRange (compRange));
477               if (RIGHT_TO_LEFT_P)
478                 for (i = 0; i < range.length; i++)
479                   permutation[range.location + i] = NSMaxRange (range) - i - 1;
481               range = NSMakeRange (NSMaxRange (range), 0);
482             }
484           gl->comp_range.location = compRange.location;
485           gl->comp_range.length = compRange.length;
487           while (++glyphIndex < numberOfGlyphs)
488             if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
489               break;
490         }
491       if (RIGHT_TO_LEFT_P)
492         for (i = 0; i < range.length; i++)
493           permutation[range.location + i] = NSMaxRange (range) - i - 1;
495       /* Then fill the remaining members.  */
496       glyphIndex = prevGlyphIndex = 0;
497       while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
498         glyphIndex++;
500       if (!RIGHT_TO_LEFT_P)
501         totalAdvance = 0;
502       else
503         {
504           NSUInteger nrects;
505           NSRect *glyphRects =
506             [layoutManager
507               rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
508               withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
509                      inTextContainer:textContainer rectCount:&nrects];
511           totalAdvance = NSMaxX (glyphRects[0]);
512         }
514       for (i = 0; i < used; i++)
515         {
516           struct mac_glyph_layout *gl;
517           NSPoint location;
518           NSUInteger nextGlyphIndex;
519           NSRange glyphRange;
520           NSRect *glyphRects;
521           NSUInteger nrects;
523           if (!RIGHT_TO_LEFT_P)
524             gl = glyph_layouts + i;
525           else
526             {
527               NSUInteger dest = permutation[i];
529               gl = glyph_layouts + dest;
530               if (i < dest)
531                 {
532                   CFIndex tmp = gl->string_index;
534                   gl->string_index = glyph_layouts[i].string_index;
535                   glyph_layouts[i].string_index = tmp;
536                 }
537             }
538           gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
540           location = [layoutManager locationForGlyphAtIndex:glyphIndex];
541           gl->baseline_delta = spaceLocation.y - location.y;
543           for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
544                nextGlyphIndex++)
545             if (![layoutManager
546                    notShownAttributeForGlyphAtIndex:nextGlyphIndex])
547               break;
549           if (!RIGHT_TO_LEFT_P)
550             {
551               CGFloat maxX;
553               if (prevGlyphIndex == 0)
554                 glyphRange = NSMakeRange (0, nextGlyphIndex);
555               else
556                 glyphRange = NSMakeRange (glyphIndex,
557                                           nextGlyphIndex - glyphIndex);
558               glyphRects =
559                 [layoutManager
560                   rectArrayForGlyphRange:glyphRange
561                   withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
562                          inTextContainer:textContainer rectCount:&nrects];
563               maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
564               gl->advance_delta = location.x - totalAdvance;
565               gl->advance = maxX - totalAdvance;
566               totalAdvance = maxX;
567             }
568           else
569             {
570               CGFloat minX;
572               if (nextGlyphIndex == numberOfGlyphs)
573                 glyphRange = NSMakeRange (prevGlyphIndex,
574                                           numberOfGlyphs - prevGlyphIndex);
575               else
576                 glyphRange = NSMakeRange (prevGlyphIndex,
577                                           glyphIndex + 1 - prevGlyphIndex);
578               glyphRects =
579                 [layoutManager
580                   rectArrayForGlyphRange:glyphRange
581                   withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
582                          inTextContainer:textContainer rectCount:&nrects];
583               minX = min (NSMinX (glyphRects[0]), totalAdvance);
584               gl->advance = totalAdvance - minX;
585               totalAdvance = minX;
586               gl->advance_delta = location.x - totalAdvance;
587             }
589           prevGlyphIndex = glyphIndex + 1;
590           glyphIndex = nextGlyphIndex;
591         }
593       if (RIGHT_TO_LEFT_P)
594         xfree (permutation);
596 #undef RIGHT_TO_LEFT_P
598       result = used;
599     }
600   [textStorage release];
602   return result;
605 static CFIndex
606 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
607                        struct mac_glyph_layout *glyph_layouts,
608                        CFIndex glyph_len)
610   return mac_font_shape_1 ([(NSFont *)font printerFont],
611                            (NSString *) string,
612                            glyph_layouts, glyph_len, YES);
615 static CGColorRef
616 get_cgcolor(unsigned long idx, struct frame *f)
618   NSColor *nsColor = ns_lookup_indexed_color (idx, f);
619   [nsColor set];
620   CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
621   NSInteger noc = [nsColor numberOfComponents];
622   CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
623   CGColorRef cgColor;
625   [nsColor getComponents: components];
626   cgColor = CGColorCreate (colorSpace, components);
627   xfree (components);
628   return cgColor;
631 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f)        \
632   do {                                                                  \
633     CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f);    \
634     CGContextSetFillColorWithColor (context, refcol_) ;                 \
635     CGColorRelease (refcol_);                                           \
636   } while (0)
637 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f)        \
638   do {                                                                  \
639     CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f);    \
640     CGContextSetFillColorWithColor (context, refcol_);                  \
641     CGColorRelease (refcol_);                                           \
642   } while (0)
643 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f)      \
644   do {                                                                  \
645     CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f);    \
646     CGContextSetStrokeColorWithColor (context, refcol_);                \
647     CGColorRelease (refcol_);                                           \
648   } while (0)
652 /* Mac font driver.  */
654 static struct
656   /* registry name */
657   const char *name;
658   /* characters to distinguish the charset from the others */
659   int uniquifier[6];
660   /* additional constraint by language */
661   CFStringRef lang;
662   /* set on demand */
663   CFCharacterSetRef cf_charset;
664   CFStringRef cf_charset_string;
665 } cf_charset_table[] =
666   { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
667     { "iso8859-2", { 0x00A0, 0x010E }},
668     { "iso8859-3", { 0x00A0, 0x0108 }},
669     { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
670     { "iso8859-5", { 0x00A0, 0x0401 }},
671     { "iso8859-6", { 0x00A0, 0x060C }},
672     { "iso8859-7", { 0x00A0, 0x0384 }},
673     { "iso8859-8", { 0x00A0, 0x05D0 }},
674     { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
675     { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
676     { "iso8859-11", { 0x00A0, 0x0E01 }},
677     { "iso8859-13", { 0x00A0, 0x201C }},
678     { "iso8859-14", { 0x00A0, 0x0174 }},
679     { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
680     { "iso8859-16", { 0x00A0, 0x0218}},
681     { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
682     { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
683     { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
684     { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
685     { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
686     { "cns11643.1992-2", { 0x4E33, 0x7934 }},
687     { "cns11643.1992-3", { 0x201A9 }},
688     { "cns11643.1992-4", { 0x20057 }},
689     { "cns11643.1992-5", { 0x20000 }},
690     { "cns11643.1992-6", { 0x20003 }},
691     { "cns11643.1992-7", { 0x20055 }},
692     { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
693     { "jisx0212.1990-0", { 0x4E44 }},
694     { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
695     { "jisx0213.2000-2", { 0xFA49 }},
696     { "jisx0213.2004-1", { 0x20B9F }},
697     { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
698     { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
699     { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
700     { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
701     { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
702     { "unicode-sip", { 0x20000 }},
703     { NULL }
704   };
706 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
707 static const struct
709   CFStringRef language;
710   CFStringRef font_names[3];
711 } macfont_language_default_font_names[] = {
712   { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
713                     CFSTR ("HiraKakuPro-W3"),  /* 10.4 */
714                     NULL }},
715   { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
716                     CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
717                     NULL }},
718   { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
719                          CFSTR ("STXihei"),         /* 10.4 - 10.5 */
720                          NULL }},
721   { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
722                          CFSTR ("LiHeiPro"),        /* 10.4 - 10.5 */
723                          NULL }},
724   { NULL }
726 #endif
728 static CGFloat macfont_antialias_threshold;
730 void
731 macfont_update_antialias_threshold (void)
733   int threshold;
734   Boolean valid_p;
736   threshold =
737     CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
738                                      kCFPreferencesCurrentApplication,
739                                      &valid_p);
740   if (valid_p)
741     macfont_antialias_threshold = threshold;
744 static inline Lisp_Object
745 macfont_intern_prop_cfstring (CFStringRef cfstring)
747   Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
749   return font_intern_prop (SSDATA (string), SBYTES (string), 1);
752 static inline CFIndex
753 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
755   if (c < 0x10000)
756     {
757       unichars[0] = c;
759       return 1;
760     }
761   else
762     {
763       c -= 0x10000;
764       unichars[0] = (c >> 10) + 0xD800;
765       unichars[1] = (c & 0x3FF) + 0xDC00;
767       return 2;
768     }
771 static Boolean
772 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
773                                          FontSymbolicTraits *sym_traits)
775   SInt64 sint64_value;
777   /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
778      OS X 10.6 when the value is greater than or equal to 1 << 31.  */
779   if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
780     {
781       *sym_traits = (FontSymbolicTraits) sint64_value;
783       return true;
784     }
786   return false;
789 static void
790 macfont_store_descriptor_attributes (FontDescriptorRef desc,
791                                      Lisp_Object spec_or_entity)
793   CFStringRef str;
794   CFDictionaryRef dict;
795   CFNumberRef num;
796   CGFloat floatval;
798   str = mac_font_descriptor_copy_attribute (desc,
799                                             MAC_FONT_FAMILY_NAME_ATTRIBUTE);
800   if (str)
801     {
802       ASET (spec_or_entity, FONT_FAMILY_INDEX,
803             macfont_intern_prop_cfstring (str));
804       CFRelease (str);
805     }
806   dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
807   if (dict)
808     {
809       struct {
810         enum font_property_index index;
811         CFStringRef trait;
812         CGPoint points[6];
813       } numeric_traits[] =
814           {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
815             {{-0.4, 50},        /* light */
816              {-0.24, 87.5},     /* (semi-light + normal) / 2 */
817              {0, 100},          /* normal */
818              {0.24, 140},       /* (semi-bold + normal) / 2 */
819              {0.4, 200},        /* bold */
820              {CGFLOAT_MAX, CGFLOAT_MAX}}},
821            {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
822             {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
823            {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
824             {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
825       int i;
827       for (i = 0; i < ARRAYELTS (numeric_traits); i++)
828         {
829           num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
830           if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
831             {
832               CGPoint *point = numeric_traits[i].points;
834               while (point->x < floatval)
835                 point++;
836               if (point == numeric_traits[i].points)
837                 point++;
838               else if (point->x == CGFLOAT_MAX)
839                 point--;
840               floatval = (point - 1)->y + ((floatval - (point - 1)->x)
841                                            * ((point->y - (point - 1)->y)
842                                               / (point->x - (point - 1)->x)));
843               FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
844                               make_number (lround (floatval)));
845             }
846         }
848       num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
849       if (num)
850         {
851           FontSymbolicTraits sym_traits;
852           int spacing;
854           cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
855           spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
856                      ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
857           ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
858         }
860       CFRelease (dict);
861     }
862   num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
863   if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
864     ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
865   else
866     ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
867   if (num)
868     CFRelease (num);
871 static Lisp_Object
872 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
873                            FontSymbolicTraits synth_sym_traits)
875   Lisp_Object entity;
876   CFDictionaryRef dict;
877   FontSymbolicTraits sym_traits = 0;
878   CFStringRef name;
880   entity = font_make_entity ();
882   ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
883   ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
885   macfont_store_descriptor_attributes (desc, entity);
887   dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
888   if (dict)
889     {
890       CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
892       if (num)
893         cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
894       CFRelease (dict);
895     }
896   if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
897     ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
898   ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
899   name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
900   font_put_extra (entity, QCfont_entity,
901                   make_save_ptr_int ((void *) name, sym_traits));
902   if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
903     FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
904                     make_number (FONT_SLANT_SYNTHETIC_ITALIC));
905   if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
906     FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
907                     make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
908   if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
909     ASET (entity, FONT_SPACING_INDEX,
910           make_number (FONT_SPACING_SYNTHETIC_MONO));
912   return entity;
915 static CFStringRef
916 macfont_create_family_with_symbol (Lisp_Object symbol)
918   static CFArrayRef families = NULL;
919   CFStringRef result = NULL, family_name;
920   int using_cache_p = 1;
921   CFComparatorFunction family_name_comparator;
923   family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
924   if (family_name == NULL)
925     return NULL;
927     {
928       family_name_comparator = CTFontManagerCompareFontFamilyNames;
929     }
931   if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
932       == kCFCompareEqualTo)
933     result = CFSTR ("LastResort");
934   else
935     while (1)
936       {
937         CFIndex i, count;
939         if (families == NULL)
940           {
941             families = mac_font_create_available_families ();
942             using_cache_p = 0;
943             if (families == NULL)
944               break;
945           }
947         count = CFArrayGetCount (families);
948         i = CFArrayBSearchValues (families, CFRangeMake (0, count),
949                                   (const void *) family_name,
950                                   family_name_comparator, NULL);
951         if (i < count)
952           {
953             CFStringRef name = CFArrayGetValueAtIndex (families, i);
955             if ((*family_name_comparator) (name, family_name, NULL)
956                 == kCFCompareEqualTo)
957               result = CFRetain (name);
958           }
960         if (result || !using_cache_p)
961           break;
962         else
963           {
964             CFRelease (families);
965             families = NULL;
966           }
967       }
969   CFRelease (family_name);
971   return result;
974 #define WIDTH_FRAC_BITS         (4)
975 #define WIDTH_FRAC_SCALE        (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
977 struct macfont_metrics
979   unsigned char lbearing_low, rbearing_low;
980   signed lbearing_high : 4, rbearing_high : 4;
981   unsigned char ascent_low, descent_low;
982   signed ascent_high : 4, descent_high : 4;
984   /* These two members are used for fixed-point representation of
985      glyph width.  The `width_int' member is an integer that is
986      closest to the width.  The `width_frac' member is the fractional
987      adjustment representing a value in [-.5, .5], multiplied by
988      WIDTH_FRAC_SCALE.  For synthetic monospace fonts, they represent
989      the advance delta for centering instead of the glyph width.  */
990   signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
993 #define METRICS_VALUE(metrics, member)                          \
994   (((metrics)->member##_high << 8) | (metrics)->member##_low)
995 #define METRICS_SET_VALUE(metrics, member, value)                   \
996   do {short tmp = (value); (metrics)->member##_low = tmp & 0xff;    \
997     (metrics)->member##_high = tmp >> 8;} while (0)
999 enum metrics_status
1001   METRICS_INVALID = -1,    /* metrics entry is invalid */
1002   METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1005 #define METRICS_STATUS(metrics)                                         \
1006   (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1007 #define METRICS_SET_STATUS(metrics, status)                     \
1008   do {METRICS_SET_VALUE (metrics, ascent, 0);                   \
1009     METRICS_SET_VALUE (metrics, descent, status);} while (0)
1011 #define METRICS_NCOLS_PER_ROW   (128)
1012 #define LCD_FONT_SMOOTHING_LEFT_MARGIN  (0.396f)
1013 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1015 static int
1016 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1017                        struct font_metrics *metrics, CGFloat *advance_delta,
1018                        int force_integral_p)
1020   struct macfont_info *macfont_info = (struct macfont_info *) font;
1021   FontRef macfont = macfont_info->macfont;
1022   int row, col;
1023   struct macfont_metrics *cache;
1024   int width;
1026   row = glyph / METRICS_NCOLS_PER_ROW;
1027   col = glyph % METRICS_NCOLS_PER_ROW;
1028   if (row >= macfont_info->metrics_nrows)
1029     {
1030       macfont_info->metrics =
1031         xrealloc (macfont_info->metrics,
1032                   sizeof (struct macfont_metrics *) * (row + 1));
1033       memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1034               (sizeof (struct macfont_metrics *)
1035                * (row + 1 - macfont_info->metrics_nrows)));
1036       macfont_info->metrics_nrows = row + 1;
1037     }
1038   if (macfont_info->metrics[row] == NULL)
1039     {
1040       struct macfont_metrics *new;
1041       int i;
1043       new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1044       for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1045         METRICS_SET_STATUS (new + i, METRICS_INVALID);
1046       macfont_info->metrics[row] = new;
1047     }
1048   cache = macfont_info->metrics[row] + col;
1050   if (METRICS_STATUS (cache) == METRICS_INVALID)
1051     {
1052       CGFloat fwidth;
1054       if (macfont_info->screen_font)
1055         fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1056       else
1057         fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1059       /* For synthetic mono fonts, cache->width_{int,frac} holds the
1060          advance delta value.  */
1061       if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1062         fwidth = (font->pixel_size - fwidth) / 2;
1063       cache->width_int = lround (fwidth);
1064       cache->width_frac = lround ((fwidth - cache->width_int)
1065                                   * WIDTH_FRAC_SCALE);
1066       METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1067     }
1068   if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1069     width = font->pixel_size;
1070   else
1071     width = cache->width_int;
1073   if (metrics)
1074     {
1075       if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1076         {
1077           CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1079           if (macfont_info->synthetic_italic_p)
1080             {
1081               /* We assume the members a, b, c, and d in
1082                  synthetic_italic_atfm are non-negative.  */
1083               bounds.origin =
1084                 CGPointApplyAffineTransform (bounds.origin,
1085                                              synthetic_italic_atfm);
1086               bounds.size =
1087                 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1088             }
1089           if (macfont_info->synthetic_bold_p && ! force_integral_p)
1090             {
1091               CGFloat d =
1092                 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1094                 bounds = CGRectInset (bounds, d, d);
1095             }
1096           switch (macfont_info->spacing)
1097             {
1098             case MACFONT_SPACING_PROPORTIONAL:
1099               bounds.origin.x += - (cache->width_frac
1100                                     / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1101               break;
1102             case MACFONT_SPACING_MONO:
1103               break;
1104             case MACFONT_SPACING_SYNTHETIC_MONO:
1105               bounds.origin.x += (cache->width_int
1106                                   + (cache->width_frac
1107                                      / (CGFloat) WIDTH_FRAC_SCALE));
1108               break;
1109             }
1110           if (bounds.size.width > 0)
1111             {
1112               bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1113               bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1114                                     + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1115             }
1116           bounds = CGRectIntegral (bounds);
1117           METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1118           METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1119           METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1120           METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1121         }
1122       metrics->lbearing = METRICS_VALUE (cache, lbearing);
1123       metrics->rbearing = METRICS_VALUE (cache, rbearing);
1124       metrics->width = width;
1125       metrics->ascent = METRICS_VALUE (cache, ascent);
1126       metrics->descent = METRICS_VALUE (cache, descent);
1127     }
1129   if (advance_delta)
1130     {
1131       switch (macfont_info->spacing)
1132         {
1133         case MACFONT_SPACING_PROPORTIONAL:
1134           *advance_delta = (force_integral_p ? 0
1135                             : - (cache->width_frac
1136                                  / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1137           break;
1138         case MACFONT_SPACING_MONO:
1139           *advance_delta = 0;
1140           break;
1141         case MACFONT_SPACING_SYNTHETIC_MONO:
1142           *advance_delta = (force_integral_p ? cache->width_int
1143                             : (cache->width_int
1144                                + (cache->width_frac
1145                                   / (CGFloat) WIDTH_FRAC_SCALE)));
1146           break;
1147         }
1148     }
1150   return width;
1153 static CFMutableDictionaryRef macfont_cache_dictionary;
1155 /* Threshold used in row_nkeys_or_perm.  This must be less than or
1156    equal to the number of rows that are invalid as BMP (i.e., from
1157    U+D800 to U+DFFF).  */
1158 #define ROW_PERM_OFFSET (8)
1160 /* The number of glyphs that can be stored in a value for a single
1161    entry of CFDictionary.  */
1162 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1164 struct macfont_cache
1166   int reference_count;
1167   CFCharacterSetRef cf_charset;
1168   struct {
1169     /* The cached glyph for a BMP character c is stored in
1170        matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1171        if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET.  */
1172     unsigned char row_nkeys_or_perm[256];
1173     CGGlyph **matrix;
1175     /* Number of rows for which the BMP cache is allocated so far.
1176        I.e., matrix[0] ... matrix[nrows - 1] are non-NULL.  */
1177     int nrows;
1179     /* The cached glyph for a character c is stored as the (c %
1180        NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1181        NGLYPHS_IN_VALUE).  However, the glyph for a BMP character c is
1182        not stored here if row_nkeys_or_perm[c / 256] >=
1183        ROW_PERM_OFFSET.  */
1184     CFMutableDictionaryRef dictionary;
1185   } glyph;
1187   struct {
1188     /* UVS (Unicode Variation Sequence) subtable data, which is of
1189        type CFDataRef if available.  NULL means it is not initialized
1190        yet.  kCFNull means the subtable is not found and there is no
1191        suitable fallback table for this font.  */
1192     CFTypeRef table;
1194     /* Character collection specifying the destination of the mapping
1195        provided by `table' above.  If `table' is obtained from the UVS
1196        subtable in the font cmap table, then the value of this member
1197        should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING.  */
1198     CharacterCollection collection;
1199   } uvs;
1202 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1203 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1204 static void macfont_release_cache (struct macfont_cache *);
1205 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1206 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1207 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1208 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1209                                           CharacterCollection, CGFontIndex);
1210 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1212 static struct macfont_cache *
1213 macfont_lookup_cache (CFStringRef key)
1215   struct macfont_cache *cache;
1217   if (macfont_cache_dictionary == NULL)
1218     {
1219       macfont_cache_dictionary =
1220         CFDictionaryCreateMutable (NULL, 0,
1221                                    &kCFTypeDictionaryKeyCallBacks, NULL);
1222       cache = NULL;
1223     }
1224   else
1225     cache = ((struct macfont_cache *)
1226              CFDictionaryGetValue (macfont_cache_dictionary, key));
1228   if (cache == NULL)
1229     {
1230       FontRef macfont = mac_font_create_with_name (key, 0);
1232       if (macfont)
1233         {
1234           cache = xzalloc (sizeof (struct macfont_cache));
1235           /* Treat the LastResort font as if it contained glyphs for
1236              all characters.  This may look too rough, but neither
1237              CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1238              for this font is correct for non-BMP characters on Mac OS
1239              X 10.5, anyway.  */
1240           if (CFEqual (key, CFSTR ("LastResort")))
1241             {
1242               CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1244               cache->cf_charset =
1245                 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1246             }
1247           if (cache->cf_charset == NULL)
1248             cache->cf_charset = mac_font_copy_character_set (macfont);
1249           CFDictionaryAddValue (macfont_cache_dictionary, key,
1250                                 (const void *) cache);
1251           CFRelease (macfont);
1252         }
1253     }
1255   return cache;
1258 static struct macfont_cache *
1259 macfont_retain_cache (struct macfont_cache *cache)
1261   cache->reference_count++;
1263   return cache;
1266 static void
1267 macfont_release_cache (struct macfont_cache *cache)
1269   if (--cache->reference_count == 0)
1270     {
1271       int i;
1273       for (i = 0; i < cache->glyph.nrows; i++)
1274         xfree (cache->glyph.matrix[i]);
1275       xfree (cache->glyph.matrix);
1276       if (cache->glyph.dictionary)
1277         CFRelease (cache->glyph.dictionary);
1278       memset (&cache->glyph, 0, sizeof (cache->glyph));
1279       if (cache->uvs.table)
1280         CFRelease (cache->uvs.table);
1281       memset (&cache->uvs, 0, sizeof (cache->uvs));
1282     }
1285 static CFCharacterSetRef
1286 macfont_get_cf_charset (struct font *font)
1288   struct macfont_info *macfont_info = (struct macfont_info *) font;
1290   return macfont_info->cache->cf_charset;
1293 static CFCharacterSetRef
1294 macfont_get_cf_charset_for_name (CFStringRef name)
1296   struct macfont_cache *cache = macfont_lookup_cache (name);
1298   return cache->cf_charset;
1301 static CGGlyph
1302 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1304   struct macfont_info *macfont_info = (struct macfont_info *) font;
1305   FontRef macfont = macfont_info->macfont;
1306   struct macfont_cache *cache = macfont_info->cache;
1308   if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1309     {
1310       int row = c / 256;
1311       int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1313       if (nkeys_or_perm < ROW_PERM_OFFSET)
1314         {
1315           UniChar unichars[256], ch;
1316           CGGlyph *glyphs;
1317           int i, len;
1318           int nrows;
1319           dispatch_queue_t queue;
1320           dispatch_group_t group = NULL;
1322           if (row != 0)
1323             {
1324               CFMutableDictionaryRef dictionary;
1325               uintptr_t key, value;
1326               int nshifts;
1327               CGGlyph glyph;
1329               if (cache->glyph.dictionary == NULL)
1330                 cache->glyph.dictionary =
1331                   CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1332               dictionary = cache->glyph.dictionary;
1333               key = c / NGLYPHS_IN_VALUE;
1334               nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1335               value = ((uintptr_t)
1336                        CFDictionaryGetValue (dictionary, (const void *) key));
1337               glyph = (value >> nshifts);
1338               if (glyph)
1339                 return glyph;
1341               if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1342                 {
1343                   ch = c;
1344                   if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1345                                                            &glyph, 1)
1346                       || glyph == 0)
1347                     glyph = kCGFontIndexInvalid;
1349                   if (value == 0)
1350                     cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1351                   value |= ((uintptr_t) glyph << nshifts);
1352                   CFDictionarySetValue (dictionary, (const void *) key,
1353                                         (const void *) value);
1355                   return glyph;
1356                 }
1358               queue =
1359                 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1360               group = dispatch_group_create ();
1361               dispatch_group_async (group, queue, ^{
1362                   int nkeys;
1363                   uintptr_t key;
1364                   nkeys = nkeys_or_perm;
1365                   for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1366                     if (CFDictionaryContainsKey (dictionary,
1367                                                  (const void *) key))
1368                       {
1369                         CFDictionaryRemoveValue (dictionary,
1370                                                  (const void *) key);
1371                         if (--nkeys == 0)
1372                           break;
1373                       }
1374                 });
1375             }
1377           len = 0;
1378           for (i = 0; i < 256; i++)
1379             {
1380               ch = row * 256 + i;
1381               if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1382                 unichars[len++] = ch;
1383             }
1385           glyphs = xmalloc (sizeof (CGGlyph) * 256);
1386           if (len > 0)
1387             {
1388               mac_font_get_glyphs_for_characters (macfont, unichars,
1389                                                   glyphs, len);
1390               while (i > len)
1391                 {
1392                   int next = unichars[len - 1] % 256;
1394                   while (--i > next)
1395                     glyphs[i] = kCGFontIndexInvalid;
1397                   len--;
1398                   glyphs[i] = glyphs[len];
1399                   if (len == 0)
1400                     break;
1401                 }
1402             }
1403           if (i > len)
1404             while (i-- > 0)
1405               glyphs[i] = kCGFontIndexInvalid;
1407           nrows = cache->glyph.nrows;
1408           nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1409           cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1410           nrows++;
1411           cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1412                                           sizeof (CGGlyph *) * nrows);
1413           cache->glyph.matrix[nrows - 1] = glyphs;
1414           cache->glyph.nrows = nrows;
1416           if (group)
1417             {
1418               dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1419               dispatch_release (group);
1420             }
1421         }
1423       return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1424     }
1425   else
1426     {
1427       uintptr_t key, value;
1428       int nshifts;
1429       CGGlyph glyph;
1431       if (cache->glyph.dictionary == NULL)
1432         cache->glyph.dictionary =
1433           CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1434       key = c / NGLYPHS_IN_VALUE;
1435       nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1436       value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1437                                                 (const void *) key);
1438       glyph = (value >> nshifts);
1439       if (glyph == 0)
1440         {
1441           UniChar unichars[2];
1442           CGGlyph glyphs[2];
1443           CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1445           if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1446                                                   count))
1447             glyph = glyphs[0];
1448           if (glyph == 0)
1449             glyph = kCGFontIndexInvalid;
1451           value |= ((uintptr_t) glyph << nshifts);
1452           CFDictionarySetValue (cache->glyph.dictionary,
1453                                 (const void *) key, (const void *) value);
1454         }
1456       return glyph;
1457     }
1460 static CGGlyph
1461 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1462                            CGFontIndex cid)
1464   struct macfont_info *macfont_info = (struct macfont_info *) font;
1465   FontRef macfont = macfont_info->macfont;
1467   /* Cache it? */
1468   return mac_font_get_glyph_for_cid (macfont, collection, cid);
1471 static CFDataRef
1472 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1474   struct macfont_info *macfont_info = (struct macfont_info *) font;
1475   FontRef macfont = macfont_info->macfont;
1476   struct macfont_cache *cache = macfont_info->cache;
1477   CFDataRef result = NULL;
1479   if (cache->uvs.table == NULL)
1480     {
1481       CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1482       CharacterCollection uvs_collection =
1483         MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1485       if (uvs_table == NULL
1486           && mac_font_get_glyph_for_cid (macfont,
1487                                          MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1488                                          6480) != kCGFontIndexInvalid)
1489         {
1490           /* If the glyph for U+4E55 is accessible via its CID 6480,
1491              then we use the Adobe-Japan1 UVS table, which maps a
1492              variation sequence to a CID, as a fallback.  */
1493           static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1495           if (mac_uvs_table_adobe_japan1 == NULL)
1496             mac_uvs_table_adobe_japan1 =
1497               CFDataCreateWithBytesNoCopy (NULL,
1498                                            mac_uvs_table_adobe_japan1_bytes,
1499                                            sizeof (mac_uvs_table_adobe_japan1_bytes),
1500                                            kCFAllocatorNull);
1501           if (mac_uvs_table_adobe_japan1)
1502             {
1503               uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1504               uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1505             }
1506         }
1507       if (uvs_table == NULL)
1508         cache->uvs.table = kCFNull;
1509       else
1510         cache->uvs.table = uvs_table;
1511       cache->uvs.collection = uvs_collection;
1512     }
1514   if (cache->uvs.table != kCFNull)
1515     {
1516       result = cache->uvs.table;
1517       *collection = cache->uvs.collection;
1518     }
1520   return result;
1523 static Lisp_Object macfont_get_cache (struct frame *);
1524 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1525 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1526 static Lisp_Object macfont_list_family (struct frame *);
1527 static void macfont_free_entity (Lisp_Object);
1528 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1529 static void macfont_close (struct font *);
1530 static int macfont_has_char (Lisp_Object, int);
1531 static unsigned macfont_encode_char (struct font *, int);
1532 static void macfont_text_extents (struct font *, unsigned int *, int,
1533                                   struct font_metrics *);
1534 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1535 static Lisp_Object macfont_shape (Lisp_Object);
1536 static int macfont_variation_glyphs (struct font *, int c,
1537                                      unsigned variations[256]);
1538 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1540 static struct font_driver macfont_driver =
1541   {
1542     LISP_INITIALLY_ZERO,        /* Qmac_ct */
1543     0,                          /* case insensitive */
1544     macfont_get_cache,
1545     macfont_list,
1546     macfont_match,
1547     macfont_list_family,
1548     macfont_free_entity,
1549     macfont_open,
1550     macfont_close,
1551     NULL,                       /* prepare_face */
1552     NULL,                       /* done_face */
1553     macfont_has_char,
1554     macfont_encode_char,
1555     macfont_text_extents,
1556     macfont_draw,
1557     NULL,                       /* get_bitmap */
1558     NULL,                       /* free_bitmap */
1559     NULL,                       /* anchor_point */
1560     NULL,                       /* otf_capability */
1561     NULL,                       /* otf_drive */
1562     NULL,                       /* start_for_frame */
1563     NULL,                       /* end_for_frame */
1564     macfont_shape,
1565     NULL,                       /* check */
1566     macfont_variation_glyphs,
1567     macfont_filter_properties,
1568   };
1570 static Lisp_Object
1571 macfont_get_cache (struct frame * f)
1573   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1575   return (dpyinfo->name_list_element);
1578 static int
1579 macfont_get_charset (Lisp_Object registry)
1581   char *str = SSDATA (SYMBOL_NAME (registry));
1582   char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1583   Lisp_Object regexp;
1584   int i, j;
1586   for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1587     {
1588       if (str[i] == '.')
1589         re[j++] = '\\';
1590       else if (str[i] == '*')
1591         re[j++] = '.';
1592       re[j] = str[i];
1593       if (re[j] == '?')
1594         re[j] = '.';
1595     }
1596   re[j] = '\0';
1597   regexp = make_unibyte_string (re, j);
1598   for (i = 0; cf_charset_table[i].name; i++)
1599     if (fast_c_string_match_ignore_case
1600         (regexp, cf_charset_table[i].name,
1601          strlen (cf_charset_table[i].name)) >= 0)
1602       break;
1603   if (! cf_charset_table[i].name)
1604     return -1;
1605   if (! cf_charset_table[i].cf_charset)
1606     {
1607       int *uniquifier = cf_charset_table[i].uniquifier;
1608       UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1609       CFIndex count = 0;
1610       CFStringRef string;
1611       CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1613       if (! charset)
1614         return -1;
1615       for (j = 0; uniquifier[j]; j++)
1616         {
1617           count += macfont_store_utf32char_to_unichars (uniquifier[j],
1618                                                         unichars + count);
1619           CFCharacterSetAddCharactersInRange (charset,
1620                                               CFRangeMake (uniquifier[j], 1));
1621         }
1623       string = CFStringCreateWithCharacters (NULL, unichars, count);
1624       if (! string)
1625         {
1626           CFRelease (charset);
1627           return -1;
1628         }
1629       cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1630                                                                  charset);
1631       CFRelease (charset);
1632       /* CFCharacterSetCreateWithCharactersInString does not handle
1633          surrogate pairs properly as of Mac OS X 10.5.  */
1634       cf_charset_table[i].cf_charset_string = string;
1635     }
1636   return i;
1639 struct OpenTypeSpec
1641   Lisp_Object script;
1642   unsigned int script_tag, langsys_tag;
1643   int nfeatures[2];
1644   unsigned int *features[2];
1647 #define OTF_SYM_TAG(SYM, TAG)                               \
1648   do {                                                      \
1649     unsigned char *p = SDATA (SYMBOL_NAME (SYM));           \
1650     TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];     \
1651   } while (0)
1653 #define OTF_TAG_STR(TAG, P)                     \
1654   do {                                          \
1655     (P)[0] = (char) (TAG >> 24);                \
1656     (P)[1] = (char) ((TAG >> 16) & 0xFF);       \
1657     (P)[2] = (char) ((TAG >> 8) & 0xFF);        \
1658     (P)[3] = (char) (TAG & 0xFF);               \
1659     (P)[4] = '\0';                              \
1660   } while (0)
1662 static struct OpenTypeSpec *
1663 macfont_get_open_type_spec (Lisp_Object otf_spec)
1665   struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1666   Lisp_Object val;
1667   int i, j;
1668   bool negative;
1670   if (! spec)
1671     return NULL;
1672   spec->script = XCAR (otf_spec);
1673   if (! NILP (spec->script))
1674     {
1675       OTF_SYM_TAG (spec->script, spec->script_tag);
1676       val = assq_no_quit (spec->script, Votf_script_alist);
1677       if (CONSP (val) && SYMBOLP (XCDR (val)))
1678         spec->script = XCDR (val);
1679       else
1680         spec->script = Qnil;
1681     }
1682   else
1683     spec->script_tag = 0x44464C54;      /* "DFLT" */
1684   otf_spec = XCDR (otf_spec);
1685   spec->langsys_tag = 0;
1686   if (! NILP (otf_spec))
1687     {
1688       val = XCAR (otf_spec);
1689       if (! NILP (val))
1690         OTF_SYM_TAG (val, spec->langsys_tag);
1691       otf_spec = XCDR (otf_spec);
1692     }
1693   spec->nfeatures[0] = spec->nfeatures[1] = 0;
1694   for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1695     {
1696       Lisp_Object len;
1698       val = XCAR (otf_spec);
1699       if (NILP (val))
1700         continue;
1701       len = Flength (val);
1702       spec->features[i] =
1703         (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1704          ? 0
1705          : malloc (XINT (len) * sizeof *spec->features[i]));
1706       if (! spec->features[i])
1707         {
1708           if (i > 0 && spec->features[0])
1709             free (spec->features[0]);
1710           free (spec);
1711           return NULL;
1712         }
1713       for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1714         {
1715           if (NILP (XCAR (val)))
1716             negative = 1;
1717           else
1718             {
1719               unsigned int tag;
1721               OTF_SYM_TAG (XCAR (val), tag);
1722               spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1723             }
1724         }
1725       spec->nfeatures[i] = j;
1726     }
1727   return spec;
1730 static CFMutableDictionaryRef
1731 macfont_create_attributes_with_spec (Lisp_Object spec)
1733   Lisp_Object tmp, extra;
1734   CFMutableArrayRef langarray = NULL;
1735   CFCharacterSetRef charset = NULL;
1736   CFStringRef charset_string = NULL;
1737   CFMutableDictionaryRef attributes = NULL, traits = NULL;
1738   Lisp_Object script = Qnil;
1739   Lisp_Object registry;
1740   int cf_charset_idx, i;
1741   struct OpenTypeSpec *otspec = NULL;
1742   struct {
1743     enum font_property_index index;
1744     CFStringRef trait;
1745     CGPoint points[6];
1746   } numeric_traits[] =
1747       {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1748         {{-0.4, 50},            /* light */
1749          {-0.24, 87.5},         /* (semi-light + normal) / 2 */
1750          {0, 100},              /* normal */
1751          {0.24, 140},           /* (semi-bold + normal) / 2 */
1752          {0.4, 200},            /* bold */
1753          {CGFLOAT_MAX, CGFLOAT_MAX}}},
1754        {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1755         {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1756        {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1757         {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1759   registry = AREF (spec, FONT_REGISTRY_INDEX);
1760   if (NILP (registry)
1761       || EQ (registry, Qascii_0)
1762       || EQ (registry, Qiso10646_1)
1763       || EQ (registry, Qunicode_bmp))
1764     cf_charset_idx = -1;
1765   else
1766     {
1767       CFStringRef lang;
1769       cf_charset_idx = macfont_get_charset (registry);
1770       if (cf_charset_idx < 0)
1771         goto err;
1772       charset = cf_charset_table[cf_charset_idx].cf_charset;
1773       charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1774       lang = cf_charset_table[cf_charset_idx].lang;
1775       if (lang)
1776         {
1777           langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1778           if (! langarray)
1779             goto err;
1780           CFArrayAppendValue (langarray, lang);
1781         }
1782     }
1784   for (extra = AREF (spec, FONT_EXTRA_INDEX);
1785        CONSP (extra); extra = XCDR (extra))
1786     {
1787       Lisp_Object key, val;
1789       tmp = XCAR (extra);
1790       key = XCAR (tmp), val = XCDR (tmp);
1791       if (EQ (key, QClang))
1792         {
1793           if (! langarray)
1794             langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1795           if (! langarray)
1796             goto err;
1797           if (SYMBOLP (val))
1798             val = list1 (val);
1799           for (; CONSP (val); val = XCDR (val))
1800             if (SYMBOLP (XCAR (val)))
1801               {
1802                 CFStringRef lang =
1803                   cfstring_create_with_string_noencode (SYMBOL_NAME
1804                                                         (XCAR (val)));
1806                 if (lang == NULL)
1807                   goto err;
1808                 CFArrayAppendValue (langarray, lang);
1809                 CFRelease (lang);
1810               }
1811         }
1812       else if (EQ (key, QCotf))
1813         {
1814           otspec = macfont_get_open_type_spec (val);
1815           if (! otspec)
1816             goto err;
1817           script = otspec->script;
1818         }
1819       else if (EQ (key, QCscript))
1820         script = val;
1821     }
1823   if (! NILP (script) && ! charset)
1824     {
1825       Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1827       if (CONSP (chars) && CONSP (CDR (chars)))
1828         {
1829           CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1830           CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1832           if (! string || !cs)
1833             {
1834               if (string)
1835                 CFRelease (string);
1836               else if (cs)
1837                 CFRelease (cs);
1838               goto err;
1839             }
1840           for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1841             if (CHARACTERP (XCAR (chars)))
1842               {
1843                 UniChar unichars[2];
1844                 CFIndex count =
1845                   macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1846                                                        unichars);
1847                 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1849                 CFStringAppendCharacters (string, unichars, count);
1850                 CFCharacterSetAddCharactersInRange (cs, range);
1851               }
1852           charset = cs;
1853           /* CFCharacterSetCreateWithCharactersInString does not
1854              handle surrogate pairs properly as of Mac OS X 10.5.  */
1855           charset_string = string;
1856         }
1857     }
1859   attributes = CFDictionaryCreateMutable (NULL, 0,
1860                                           &kCFTypeDictionaryKeyCallBacks,
1861                                           &kCFTypeDictionaryValueCallBacks);
1862   if (! attributes)
1863     goto err;
1865   tmp = AREF (spec, FONT_FAMILY_INDEX);
1866   if (SYMBOLP (tmp) && ! NILP (tmp))
1867     {
1868       CFStringRef family = macfont_create_family_with_symbol (tmp);
1870       if (! family)
1871         goto err;
1872       CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1873                             family);
1874       CFRelease (family);
1875     }
1877   traits = CFDictionaryCreateMutable (NULL, 4,
1878                                       &kCFTypeDictionaryKeyCallBacks,
1879                                       &kCFTypeDictionaryValueCallBacks);
1880   if (! traits)
1881     goto err;
1883   for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1884     {
1885       tmp = AREF (spec, numeric_traits[i].index);
1886       if (INTEGERP (tmp))
1887         {
1888           CGPoint *point = numeric_traits[i].points;
1889           CGFloat floatval = (XINT (tmp) >> 8); // XXX
1890           CFNumberRef num;
1892           while (point->y < floatval)
1893             point++;
1894           if (point == numeric_traits[i].points)
1895             point++;
1896           else if (point->y == CGFLOAT_MAX)
1897             point--;
1898           floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1899                                        * ((point->x - (point - 1)->x)
1900                                           / (point->y - (point - 1)->y)));
1901           if (floatval > 1.0)
1902             floatval = 1.0;
1903           else if (floatval < -1.0)
1904             floatval = -1.0;
1905           num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1906           if (! num)
1907             goto err;
1908           CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1909           CFRelease (num);
1910         }
1911     }
1912   if (CFDictionaryGetCount (traits))
1913     CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1915   if (charset)
1916     CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1917                           charset);
1918   if (charset_string)
1919     CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1920                           charset_string);
1921   if (langarray)
1922     CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1924   goto finish;
1926  err:
1927   if (attributes)
1928     {
1929       CFRelease (attributes);
1930       attributes = NULL;
1931     }
1933  finish:
1934   if (langarray) CFRelease (langarray);
1935   if (charset && cf_charset_idx < 0) CFRelease (charset);
1936   if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1937   if (traits) CFRelease (traits);
1938   if (otspec)
1939     {
1940       if (otspec->nfeatures[0] > 0)
1941         free (otspec->features[0]);
1942       if (otspec->nfeatures[1] > 0)
1943         free (otspec->features[1]);
1944       free (otspec);
1945     }
1947   return attributes;
1950 static Boolean
1951 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1952                                           CFCharacterSetRef charset,
1953                                           Lisp_Object chars,
1954                                           CFArrayRef languages)
1956   Boolean result = true;
1958   if (charset || VECTORP (chars))
1959     {
1960       CFCharacterSetRef desc_charset =
1961         mac_font_descriptor_copy_attribute (desc,
1962                                             MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1964       if (desc_charset == NULL)
1965         result = false;
1966       else
1967         {
1968           if (charset)
1969             result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1970           else                  /* VECTORP (chars) */
1971             {
1972               ptrdiff_t j;
1974               for (j = 0; j < ASIZE (chars); j++)
1975                 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
1976                     && CFCharacterSetIsLongCharacterMember (desc_charset,
1977                                                             XFASTINT (AREF (chars, j))))
1978                   break;
1979               if (j == ASIZE (chars))
1980                 result = false;
1981             }
1982           CFRelease (desc_charset);
1983         }
1984     }
1985   if (result && languages)
1986     result = mac_font_descriptor_supports_languages (desc, languages);
1988   return result;
1991 static int
1992 macfont_traits_distance (FontSymbolicTraits sym_traits1,
1993                          FontSymbolicTraits sym_traits2)
1995   FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
1996   int distance = 0;
1998   /* We prefer synthetic bold of italic to synthetic italic of bold
1999      when both bold and italic are available but bold-italic is not
2000      available.  */
2001   if (diff & MAC_FONT_TRAIT_BOLD)
2002     distance |= (1 << 0);
2003   if (diff & MAC_FONT_TRAIT_ITALIC)
2004     distance |= (1 << 1);
2005   if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2006     distance |= (1 << 2);
2008   return distance;
2011 static Boolean
2012 macfont_closest_traits_index_p (CFArrayRef traits_array,
2013                                 FontSymbolicTraits target,
2014                                 CFIndex index)
2016   CFIndex i, count = CFArrayGetCount (traits_array);
2017   FontSymbolicTraits traits;
2018   int my_distance;
2020   traits = ((FontSymbolicTraits) (uintptr_t)
2021             CFArrayGetValueAtIndex (traits_array, index));
2022   my_distance = macfont_traits_distance (target, traits);
2024   for (i = 0; i < count; i++)
2025     if (i != index)
2026       {
2027         traits = ((FontSymbolicTraits) (uintptr_t)
2028                   CFArrayGetValueAtIndex (traits_array, i));
2029         if (macfont_traits_distance (target, traits) < my_distance)
2030           return false;
2031       }
2033   return true;
2036 static Lisp_Object
2037 macfont_list (struct frame *f, Lisp_Object spec)
2039   Lisp_Object val = Qnil, family, extra;
2040   int i, n;
2041   CFStringRef family_name = NULL;
2042   CFMutableDictionaryRef attributes = NULL, traits;
2043   Lisp_Object chars = Qnil;
2044   int spacing = -1;
2045   FontSymbolicTraits synth_sym_traits = 0;
2046   CFArrayRef families;
2047   CFIndex families_count;
2048   CFCharacterSetRef charset = NULL;
2049   CFArrayRef languages = NULL;
2051   block_input ();
2053   family = AREF (spec, FONT_FAMILY_INDEX);
2054   if (! NILP (family))
2055     {
2056       family_name = macfont_create_family_with_symbol (family);
2057       if (family_name == NULL)
2058         goto finish;
2059     }
2061   attributes = macfont_create_attributes_with_spec (spec);
2062   if (! attributes)
2063     goto finish;
2065   languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2067   if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2068     spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2070   traits = ((CFMutableDictionaryRef)
2071             CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2073   n = FONT_SLANT_NUMERIC (spec);
2074   if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2075     {
2076       synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2077       if (traits)
2078         CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2079     }
2081   n = FONT_WEIGHT_NUMERIC (spec);
2082   if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2083     {
2084       synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2085       if (traits)
2086         CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2087     }
2089   if (languages
2090       && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2091     {
2092       CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2094       if (CFStringHasPrefix (language, CFSTR ("ja"))
2095           || CFStringHasPrefix (language, CFSTR ("ko"))
2096           || CFStringHasPrefix (language, CFSTR ("zh")))
2097         synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2098     }
2100   /* Create array of families.  */
2101   if (family_name)
2102     families = CFArrayCreate (NULL, (const void **) &family_name,
2103                               1, &kCFTypeArrayCallBacks);
2104   else
2105     {
2106       CFStringRef pref_family;
2107       CFIndex families_count, pref_family_index = -1;
2109       families = mac_font_create_available_families ();
2110       if (families == NULL)
2111         goto err;
2113       families_count = CFArrayGetCount (families);
2115       /* Move preferred family to the front if exists.  */
2116       pref_family =
2117         mac_font_create_preferred_family_for_attributes (attributes);
2118       if (pref_family)
2119         {
2120           pref_family_index =
2121             CFArrayGetFirstIndexOfValue (families,
2122                                          CFRangeMake (0, families_count),
2123                                          pref_family);
2124           CFRelease (pref_family);
2125         }
2126       if (pref_family_index > 0)
2127         {
2128           CFMutableArrayRef mutable_families =
2129             CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2131           if (mutable_families)
2132             {
2133               CFArrayAppendValue (mutable_families,
2134                                   CFArrayGetValueAtIndex (families,
2135                                                           pref_family_index));
2136               CFArrayAppendArray (mutable_families, families,
2137                                   CFRangeMake (0, pref_family_index));
2138               if (pref_family_index + 1 < families_count)
2139                 CFArrayAppendArray (mutable_families, families,
2140                                     CFRangeMake (pref_family_index + 1,
2141                                                  families_count
2142                                                  - (pref_family_index + 1)));
2143               CFRelease (families);
2144               families = mutable_families;
2145             }
2146         }
2147     }
2149   charset = CFDictionaryGetValue (attributes,
2150                                   MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2151   if (charset)
2152     {
2153       CFRetain (charset);
2154       CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2155     }
2156   else
2157     {
2158       val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2159       if (! NILP (val))
2160         {
2161           val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2162           if (CONSP (val) && VECTORP (XCDR (val)))
2163             chars = XCDR (val);
2164         }
2165       val = Qnil;
2166     }
2168   if (languages)
2169     {
2170       CFRetain (languages);
2171       CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2172     }
2174   val = Qnil;
2175   extra = AREF (spec, FONT_EXTRA_INDEX);
2176   families_count = CFArrayGetCount (families);
2177   for (i = 0; i < families_count; i++)
2178     {
2179       CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2180       FontDescriptorRef pat_desc;
2181       CFArrayRef descs;
2182       CFIndex descs_count;
2183       CFMutableArrayRef filtered_descs, traits_array;
2184       Lisp_Object entity;
2185       int j;
2187       CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2188                             family_name);
2189       pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2190       if (! pat_desc)
2191         goto err;
2193       /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2194          10.7 returns NULL if pat_desc represents the LastResort font.
2195          So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2196          trailing "s") for such a font.  */
2197       if (!CFEqual (family_name, CFSTR ("LastResort")))
2198         descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2199                                                                       NULL);
2200       else
2201         {
2202           FontDescriptorRef lr_desc =
2203             mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2204                                                                  NULL);
2205           if (lr_desc)
2206             {
2207               descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2208                                      &kCFTypeArrayCallBacks);
2209               CFRelease (lr_desc);
2210             }
2211           else
2212             descs = NULL;
2213         }
2214       CFRelease (pat_desc);
2215       if (! descs)
2216         goto err;
2218       descs_count = CFArrayGetCount (descs);
2219       if (descs_count == 0
2220           || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2221                                                         charset, chars,
2222                                                         languages))
2223         {
2224           CFRelease (descs);
2225           continue;
2226         }
2228       filtered_descs =
2229         CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2230       traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2231       for (j = 0; j < descs_count; j++)
2232         {
2233           FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2234           CFDictionaryRef dict;
2235           CFNumberRef num;
2236           FontSymbolicTraits sym_traits;
2238           dict = mac_font_descriptor_copy_attribute (desc,
2239                                                      MAC_FONT_TRAITS_ATTRIBUTE);
2240           if (dict == NULL)
2241             continue;
2243           num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2244           CFRelease (dict);
2245           if (num == NULL
2246               || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2247             continue;
2249           if (spacing >= 0
2250               && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2251               && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2252                   != (spacing >= FONT_SPACING_MONO)))
2253             continue;
2255           /* Don't use a color bitmap font unless its family is
2256              explicitly specified.  */
2257           if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2258             continue;
2260           if (j > 0
2261               && !macfont_supports_charset_and_languages_p (desc, charset,
2262                                                             chars, languages))
2263             continue;
2265           CFArrayAppendValue (filtered_descs, desc);
2266           CFArrayAppendValue (traits_array,
2267                               (const void *) (uintptr_t) sym_traits);
2268         }
2270       CFRelease (descs);
2271       descs = filtered_descs;
2272       descs_count = CFArrayGetCount (descs);
2274       for (j = 0; j < descs_count; j++)
2275         {
2276           FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2277           FontSymbolicTraits sym_traits =
2278             ((FontSymbolicTraits) (uintptr_t)
2279              CFArrayGetValueAtIndex (traits_array, j));
2280           FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2282           mask_min = ((synth_sym_traits ^ sym_traits)
2283                       & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2284           if (FONT_SLANT_NUMERIC (spec) < 0)
2285             mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2286           if (FONT_WEIGHT_NUMERIC (spec) < 0)
2287             mask_min &= ~MAC_FONT_TRAIT_BOLD;
2289           mask_max = (synth_sym_traits & ~sym_traits);
2290           /* Synthetic bold does not work for bitmap-only fonts on Mac
2291              OS X 10.6.  */
2292           if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2293             {
2294               CFNumberRef format =
2295                 mac_font_descriptor_copy_attribute (desc,
2296                                                     MAC_FONT_FORMAT_ATTRIBUTE);
2298               if (format)
2299                 {
2300                   uint32_t format_val;
2302                   if (CFNumberGetValue (format, kCFNumberSInt32Type,
2303                                         &format_val)
2304                       && format_val == MAC_FONT_FORMAT_BITMAP)
2305                     mask_max &= ~MAC_FONT_TRAIT_BOLD;
2306                 }
2307             }
2308           if (spacing >= 0)
2309             mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2311           for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2312                mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2313                mmask += MAC_FONT_TRAIT_MONO_SPACE)
2314             for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2315                  bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2316                  bmask += MAC_FONT_TRAIT_BOLD)
2317               for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2318                    imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2319                    imask += MAC_FONT_TRAIT_ITALIC)
2320                 {
2321                   FontSymbolicTraits synth = (imask | bmask | mmask);
2323                   if (synth == 0
2324                       || macfont_closest_traits_index_p (traits_array,
2325                                                          (sym_traits | synth),
2326                                                          j))
2327                     {
2328                       entity = macfont_descriptor_entity (desc, extra, synth);
2329                       if (! NILP (entity))
2330                         val = Fcons (entity, val);
2331                     }
2332                 }
2333         }
2335       CFRelease (traits_array);
2336       CFRelease (descs);
2337     }
2339   CFRelease (families);
2340   val = Fnreverse (val);
2341   goto finish;
2342  err:
2343   val = Qnil;
2345  finish:
2346   FONT_ADD_LOG ("macfont-list", spec, val);
2347   if (charset) CFRelease (charset);
2348   if (languages) CFRelease (languages);
2349   if (attributes) CFRelease (attributes);
2350   if (family_name) CFRelease (family_name);
2352   unblock_input ();
2354   return val;
2357 static Lisp_Object
2358 macfont_match (struct frame * frame, Lisp_Object spec)
2360   Lisp_Object entity = Qnil;
2361   CFMutableDictionaryRef attributes;
2362   FontDescriptorRef pat_desc = NULL, desc = NULL;
2364   block_input ();
2366   attributes = macfont_create_attributes_with_spec (spec);
2367   if (attributes)
2368     {
2369       pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2370       CFRelease (attributes);
2371     }
2372   if (pat_desc)
2373     {
2374       desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2375                                                                   NULL);
2376       CFRelease (pat_desc);
2377     }
2378   if (desc)
2379     {
2380       entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2381                                           0);
2382       CFRelease (desc);
2383     }
2384   unblock_input ();
2386   FONT_ADD_LOG ("macfont-match", spec, entity);
2387   return entity;
2390 static Lisp_Object
2391 macfont_list_family (struct frame *frame)
2393   Lisp_Object list = Qnil;
2394   CFArrayRef families;
2396   block_input ();
2398   families = mac_font_create_available_families ();
2399   if (families)
2400     {
2401       CFIndex i, count = CFArrayGetCount (families);
2403       for (i = 0; i < count; i++)
2404         list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2405       CFRelease (families);
2406     }
2408   unblock_input ();
2410   return list;
2413 static void
2414 macfont_free_entity (Lisp_Object entity)
2416   Lisp_Object val = assq_no_quit (QCfont_entity,
2417                                   AREF (entity, FONT_EXTRA_INDEX));
2418   CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2420   block_input ();
2421   CFRelease (name);
2422   unblock_input ();
2425 static Lisp_Object
2426 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2428   Lisp_Object val, font_object;
2429   CFStringRef font_name;
2430   struct macfont_info *macfont_info = NULL;
2431   struct font *font;
2432   int size;
2433   FontRef macfont;
2434   FontSymbolicTraits sym_traits;
2435   char name[256];
2436   int len, i, total_width;
2437   CGGlyph glyph;
2438   CGFloat ascent, descent, leading;
2440   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2441   if (! CONSP (val)
2442       || XTYPE (XCDR (val)) != Lisp_Misc
2443       || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2444     return Qnil;
2445   font_name = XSAVE_POINTER (XCDR (val), 0);
2446   sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2448   size = XINT (AREF (entity, FONT_SIZE_INDEX));
2449   if (size == 0)
2450     size = pixel_size;
2452   block_input ();
2453   macfont = mac_font_create_with_name (font_name, size);
2454   if (macfont)
2455     {
2456       int fontsize = (int) [((NSFont *) macfont) pointSize];
2457       if (fontsize != size) size = fontsize;
2458     }
2459   unblock_input ();
2460   if (! macfont)
2461     return Qnil;
2463   font_object = font_build_object (VECSIZE (struct macfont_info),
2464                                    Qmac_ct, entity, size);
2465   font = XFONT_OBJECT (font_object);
2466   font->pixel_size = size;
2467   font->driver = &macfont_driver;
2468   font->encoding_charset = font->repertory_charset = -1;
2470   block_input ();
2472   macfont_info = (struct macfont_info *) font;
2473   macfont_info->macfont = macfont;
2474   macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2476   val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2477   if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2478     macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2479                                                                   size);
2480   else
2481     macfont_info->screen_font = NULL;
2482   macfont_info->cache = macfont_lookup_cache (font_name);
2483   macfont_retain_cache (macfont_info->cache);
2484   macfont_info->metrics = NULL;
2485   macfont_info->metrics_nrows = 0;
2486   macfont_info->synthetic_italic_p = 0;
2487   macfont_info->synthetic_bold_p = 0;
2488   macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2489   macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2490   if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2491       && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2492     macfont_info->synthetic_italic_p = 1;
2493   if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2494       && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2495     macfont_info->synthetic_bold_p = 1;
2496   if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2497     macfont_info->spacing = MACFONT_SPACING_MONO;
2498   else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2499            && (XINT (AREF (entity, FONT_SPACING_INDEX))
2500                == FONT_SPACING_SYNTHETIC_MONO))
2501     macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2502   if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2503     macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2504   else
2505     {
2506       val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2507       if (CONSP (val))
2508         macfont_info->antialias =
2509           NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2510     }
2511   macfont_info->color_bitmap_p = 0;
2512   if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2513     macfont_info->color_bitmap_p = 1;
2515   glyph = macfont_get_glyph_for_character (font, ' ');
2516   if (glyph != kCGFontIndexInvalid)
2517     font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2518   else
2519     /* dirty workaround */
2520     font->space_width = pixel_size;
2522   total_width = font->space_width;
2523   for (i = 1; i < 95; i++)
2524     {
2525       glyph = macfont_get_glyph_for_character (font, ' ' + i);
2526       if (glyph == kCGFontIndexInvalid)
2527         break;
2528       total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2529     }
2530   if (i == 95)
2531     font->average_width = total_width / 95;
2532   else
2533     font->average_width = font->space_width; /* XXX */
2535   if (!(macfont_info->screen_font
2536         && mac_screen_font_get_metrics (macfont_info->screen_font,
2537                                         &ascent, &descent, &leading)))
2538     {
2539       CFStringRef family_name;
2541       ascent = mac_font_get_ascent (macfont);
2542       descent = mac_font_get_descent (macfont);
2543       leading = mac_font_get_leading (macfont);
2544       /* AppKit and WebKit do some adjustment to the heights of
2545          Courier, Helvetica, and Times.  */
2546       family_name = mac_font_copy_family_name (macfont);
2547       if (family_name)
2548         {
2549           if (CFEqual (family_name, CFSTR ("Courier"))
2550               || CFEqual (family_name, CFSTR ("Helvetica"))
2551               || CFEqual (family_name, CFSTR ("Times")))
2552             ascent += (ascent + descent) * .15f;
2553           else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2554             {
2555               leading *= .25f;
2556               ascent += leading;
2557             }
2558           CFRelease (family_name);
2559         }
2560     }
2561   font->ascent = ascent + 0.5f;
2562   val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2563   if (CONSP (val) && !NILP (XCDR (val)))
2564     font->descent = descent + 0.5f;
2565   else
2566     font->descent = descent + leading + 0.5f;
2567   font->height = font->ascent + font->descent;
2569   font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2570   font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2572   unblock_input ();
2574   /* Unfortunately Xft doesn't provide a way to get minimum char
2575      width.  So, we use space_width instead.  */
2576   font->min_width = font->max_width = font->space_width; /* XXX */
2578   font->baseline_offset = 0;
2579   font->relative_compose = 0;
2580   font->default_ascent = 0;
2581   font->vertical_centering = 0;
2583   return font_object;
2586 static void
2587 macfont_close (struct font *font)
2589   struct macfont_info *macfont_info = (struct macfont_info *) font;
2591   if (macfont_info->cache)
2592     {
2593       int i;
2595       block_input ();
2596       CFRelease (macfont_info->macfont);
2597       CGFontRelease (macfont_info->cgfont);
2598       if (macfont_info->screen_font)
2599         CFRelease (macfont_info->screen_font);
2600       macfont_release_cache (macfont_info->cache);
2601       for (i = 0; i < macfont_info->metrics_nrows; i++)
2602         if (macfont_info->metrics[i])
2603           xfree (macfont_info->metrics[i]);
2604       if (macfont_info->metrics)
2605         xfree (macfont_info->metrics);
2606       macfont_info->cache = NULL;
2607       unblock_input ();
2608     }
2611 static int
2612 macfont_has_char (Lisp_Object font, int c)
2614   int result;
2615   CFCharacterSetRef charset;
2617   block_input ();
2618   if (FONT_ENTITY_P (font))
2619     {
2620       Lisp_Object val;
2621       CFStringRef name;
2623       val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2624       val = XCDR (val);
2625       name = XSAVE_POINTER (val, 0);
2626       charset = macfont_get_cf_charset_for_name (name);
2627     }
2628   else
2629     charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2631   result = CFCharacterSetIsLongCharacterMember (charset, c);
2632   unblock_input ();
2634   return result;
2637 static unsigned
2638 macfont_encode_char (struct font *font, int c)
2640   struct macfont_info *macfont_info = (struct macfont_info *) font;
2641   CGGlyph glyph;
2643   block_input ();
2644   glyph = macfont_get_glyph_for_character (font, c);
2645   unblock_input ();
2647   return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2650 static void
2651 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2652                       struct font_metrics *metrics)
2654   int width, i;
2656   block_input ();
2657   width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2658   for (i = 1; i < nglyphs; i++)
2659     {
2660       struct font_metrics m;
2661       int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2662                                      NULL, 0);
2664       if (metrics)
2665         {
2666           if (width + m.lbearing < metrics->lbearing)
2667             metrics->lbearing = width + m.lbearing;
2668           if (width + m.rbearing > metrics->rbearing)
2669             metrics->rbearing = width + m.rbearing;
2670           if (m.ascent > metrics->ascent)
2671             metrics->ascent = m.ascent;
2672           if (m.descent > metrics->descent)
2673             metrics->descent = m.descent;
2674         }
2675       width += w;
2676     }
2677   unblock_input ();
2679   if (metrics)
2680     metrics->width = width;
2683 static int
2684 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2685               bool with_background)
2687   struct frame * f = s->f;
2688   struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2689   CGRect background_rect;
2690   CGPoint text_position;
2691   CGGlyph *glyphs;
2692   CGPoint *positions;
2693   CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2694   bool no_antialias_p =
2695     (NILP (ns_antialias_text)
2696      || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2697      || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2698          && font_size <= macfont_antialias_threshold));
2699   int len = to - from;
2700   struct face *face = s->face;
2701   CGContextRef context;
2703   block_input ();
2705   if (with_background)
2706     background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2707                                   s->width, FONT_HEIGHT (s->font));
2708   else
2709     background_rect = CGRectNull;
2711   text_position = CGPointMake (x, -y);
2712   glyphs = xmalloc (sizeof (CGGlyph) * len);
2713   {
2714     CGFloat advance_delta = 0;
2715     int i;
2716     CGFloat total_width = 0;
2718     positions = xmalloc (sizeof (CGPoint) * len);
2719     for (i = 0; i < len; i++)
2720       {
2721         int width;
2723         glyphs[i] = s->char2b[from + i];
2724         width = (s->padding_p ? 1
2725                  : macfont_glyph_extents (s->font, glyphs[i],
2726                                           NULL, &advance_delta,
2727                                           no_antialias_p));
2728         positions[i].x = total_width + advance_delta;
2729         positions[i].y = 0;
2730         total_width += width;
2731       }
2732   }
2734   context = [[NSGraphicsContext currentContext] graphicsPort];
2735   CGContextSaveGState (context);
2737   if (!CGRectIsNull (background_rect))
2738     {
2739       if (s->hl == DRAW_MOUSE_FACE)
2740         {
2741           face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2742           if (!face)
2743             face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2744         }
2745       CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2746       CGContextFillRects (context, &background_rect, 1);
2747     }
2749   if (macfont_info->cgfont)
2750     {
2751       CGAffineTransform atfm;
2753       CGContextScaleCTM (context, 1, -1);
2754       CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2755       if (macfont_info->synthetic_italic_p)
2756         atfm = synthetic_italic_atfm;
2757       else
2758         atfm = CGAffineTransformIdentity;
2759       if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2760         {
2761           CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2762           CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2763           CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2764         }
2765       if (no_antialias_p)
2766         CGContextSetShouldAntialias (context, false);
2768       CGContextSetTextMatrix (context, atfm);
2769       CGContextSetTextPosition (context, text_position.x, text_position.y);
2771 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2772       if (macfont_info->color_bitmap_p
2773 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2774           && CTFontDrawGlyphs != NULL
2775 #endif
2776           )
2777         {
2778           if (len > 0)
2779             {
2780               CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2781                                 context);
2782             }
2783         }
2784       else
2785 #endif  /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2786         {
2787           CGContextSetFont (context, macfont_info->cgfont);
2788           CGContextSetFontSize (context, font_size);
2789           CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2790         }
2791     }
2794   xfree (glyphs);
2795   xfree (positions);
2796   CGContextRestoreGState (context);
2798   unblock_input ();
2800   return len;
2803 static Lisp_Object
2804 macfont_shape (Lisp_Object lgstring)
2806   struct font *font;
2807   struct macfont_info *macfont_info;
2808   FontRef macfont;
2809   ptrdiff_t glyph_len, len, i, j;
2810   CFIndex nonbmp_len;
2811   UniChar *unichars;
2812   CFIndex *nonbmp_indices;
2813   CFStringRef string;
2814   CFIndex used = 0;
2815   struct mac_glyph_layout *glyph_layouts;
2817   CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2818   macfont_info = (struct macfont_info *) font;
2819   macfont = macfont_info->macfont;
2821   glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2822   nonbmp_len = 0;
2823   for (i = 0; i < glyph_len; i++)
2824     {
2825       Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2827       if (NILP (lglyph))
2828         break;
2829       if (LGLYPH_CHAR (lglyph) >= 0x10000)
2830         nonbmp_len++;
2831     }
2833   len = i;
2835   if (INT_MAX / 2 < len)
2836     memory_full (SIZE_MAX);
2838   unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2839   nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2840   for (i = j = 0; i < len; i++)
2841     {
2842       UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2844       if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2845         {
2846           nonbmp_indices[j] = i + j;
2847           j++;
2848         }
2849     }
2850   nonbmp_indices[j] = len + j;  /* sentinel */
2852   block_input ();
2854   string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2855                                                kCFAllocatorNull);
2856   if (string)
2857     {
2858       glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2859       if (macfont_info->screen_font)
2860         used = mac_screen_font_shape (macfont_info->screen_font, string,
2861                                       glyph_layouts, glyph_len);
2862       else
2863         used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2864       CFRelease (string);
2865     }
2867   unblock_input ();
2869   if (used == 0)
2870     return Qnil;
2872   block_input ();
2874   for (i = 0; i < used; i++)
2875     {
2876       Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2877       struct mac_glyph_layout *gl = glyph_layouts + i;
2878       EMACS_INT from, to;
2879       struct font_metrics metrics;
2880       int xoff, yoff, wadjust;
2882       if (NILP (lglyph))
2883         {
2884           lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2885           LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2886         }
2888       from = gl->comp_range.location;
2889       /* Convert UTF-16 index to UTF-32.  */
2890       j = 0;
2891       while (nonbmp_indices[j] < from)
2892         j++;
2893       from -= j;
2894       LGLYPH_SET_FROM (lglyph, from);
2896       to = gl->comp_range.location + gl->comp_range.length;
2897       /* Convert UTF-16 index to UTF-32.  */
2898       while (nonbmp_indices[j] < to)
2899         j++;
2900       to -= j;
2901       LGLYPH_SET_TO (lglyph, to - 1);
2903       /* LGLYPH_CHAR is used in `describe-char' for checking whether
2904          the composition is trivial.  */
2905       {
2906         UTF32Char c;
2908         if (unichars[gl->string_index] >= 0xD800
2909             && unichars[gl->string_index] < 0xDC00)
2910           c = (((unichars[gl->string_index] - 0xD800) << 10)
2911                + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2912         else
2913           c = unichars[gl->string_index];
2914         if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2915           c = 0;
2916         LGLYPH_SET_CHAR (lglyph, c);
2917       }
2919       {
2920         unsigned long cc = gl->glyph_id;
2921         LGLYPH_SET_CODE (lglyph, cc);
2922       }
2924       macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2925       LGLYPH_SET_WIDTH (lglyph, metrics.width);
2926       LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2927       LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2928       LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2929       LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2931       xoff = lround (gl->advance_delta);
2932       yoff = lround (- gl->baseline_delta);
2933       wadjust = lround (gl->advance);
2934       if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2935         {
2936           Lisp_Object vec;
2938           vec = Fmake_vector (make_number (3), Qnil);
2939           ASET (vec, 0, make_number (xoff));
2940           ASET (vec, 1, make_number (yoff));
2941           ASET (vec, 2, make_number (wadjust));
2942           LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2943         }
2944     }
2946   unblock_input ();
2948   return make_number (used);
2951 /* Structures for the UVS subtable (format 14) in the cmap table.  */
2952 typedef UInt8 UINT24[3];
2954 #pragma pack(push, 1)
2955 struct variation_selector_record
2957   UINT24 var_selector;
2958   UInt32 default_uvs_offset, non_default_uvs_offset;
2960 struct uvs_table
2962   UInt16 format;
2963   UInt32 length, num_var_selector_records;
2964   struct variation_selector_record variation_selector_records[1];
2966 #define SIZEOF_UVS_TABLE_HEADER                                         \
2967   (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2969 struct unicode_value_range
2971   UINT24 start_unicode_value;
2972   UInt8 additional_count;
2974 struct default_uvs_table {
2975   UInt32 num_unicode_value_ranges;
2976   struct unicode_value_range unicode_value_ranges[1];
2978 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER                                 \
2979   (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2981 struct uvs_mapping
2983   UINT24 unicode_value;
2984   UInt16 glyph_id;
2986 struct non_default_uvs_table
2988   UInt32 num_uvs_mappings;
2989   struct uvs_mapping uvs_mappings[1];
2991 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER                             \
2992   (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2993 #pragma pack(pop)
2995 /* Read big endian values.  The argument LVAL must be an lvalue.  */
2996 /* I suppose OSReadBigInt* takes care of unaligned data.  At least, we
2997    can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
2998    OSReadBigInt16(cdb, 7);" in a sample code by Apple.  */
2999 #define BUINT8_VALUE(lval)      (*((UInt8 *) &(lval)))
3000 #define BUINT16_VALUE(lval)     OSReadBigInt16 (&(lval), 0)
3001 /* Succeeding one byte should also be accessible.  */
3002 #define BUINT24_VALUE(lval)     (OSReadBigInt32 (&(lval), 0) >> 8)
3003 #define BUINT32_VALUE(lval)     OSReadBigInt32 (&(lval), 0)
3005 /* Return UVS subtable for the specified FONT.  If the subtable is not
3006    found or ill-formatted, then return NULL.  */
3008 static CFDataRef
3009 mac_font_copy_uvs_table (FontRef font)
3011   CFDataRef cmap_table, uvs_table = NULL;
3013   cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3014   if (cmap_table)
3015     {
3016       sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3017       struct uvs_table *uvs;
3018       struct variation_selector_record *records;
3019       UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3021 #if __LP64__
3022       if (CFDataGetLength (cmap_table) > UINT32_MAX)
3023         goto finish;
3024 #endif
3026       cmap_len = CFDataGetLength (cmap_table);
3027       if (sizeof_sfntCMapHeader > cmap_len)
3028         goto finish;
3030       ntables = BUINT16_VALUE (cmap->numTables);
3031       if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3032                      / sizeof_sfntCMapEncoding))
3033         goto finish;
3035       for (i = 0; i < ntables; i++)
3036         if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3037              == kFontUnicodePlatform)
3038             && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3039                 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3040           {
3041             uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3042             break;
3043           }
3044       if (i == ntables
3045           || uvs_offset > cmap_len
3046           || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3047         goto finish;
3049       uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3050       uvs_len = BUINT32_VALUE (uvs->length);
3051       if (uvs_len > cmap_len - uvs_offset
3052           || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3053         goto finish;
3055       if (BUINT16_VALUE (uvs->format) != 14)
3056         goto finish;
3058       nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3059       if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3060                       / sizeof (struct variation_selector_record)))
3061         goto finish;
3063       records = uvs->variation_selector_records;
3064       for (i = 0; i < nrecords; i++)
3065         {
3066           UInt32 default_uvs_offset, non_default_uvs_offset;
3068           default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3069           if (default_uvs_offset)
3070             {
3071               struct default_uvs_table *default_uvs;
3072               UInt32 nranges;
3074               if (default_uvs_offset > uvs_len
3075                   || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3076                       > uvs_len - default_uvs_offset))
3077                 goto finish;
3079               default_uvs = ((struct default_uvs_table *)
3080                              ((UInt8 *) uvs + default_uvs_offset));
3081               nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3082               if (nranges > ((uvs_len - default_uvs_offset
3083                               - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3084                              / sizeof (struct unicode_value_range)))
3085                 goto finish;
3086               /* Now 2 * nranges can't overflow, so we can safely use
3087                  `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3088                  mac_font_get_glyphs_for_variants.  */
3089             }
3091           non_default_uvs_offset =
3092             BUINT32_VALUE (records[i].non_default_uvs_offset);
3093           if (non_default_uvs_offset)
3094             {
3095               struct non_default_uvs_table *non_default_uvs;
3096               UInt32 nmappings;
3098               if (non_default_uvs_offset > uvs_len
3099                   || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3100                       > uvs_len - non_default_uvs_offset))
3101                 goto finish;
3103               non_default_uvs = ((struct non_default_uvs_table *)
3104                                  ((UInt8 *) uvs + non_default_uvs_offset));
3105               nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3106               if (nmappings > ((uvs_len - non_default_uvs_offset
3107                                 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3108                                / sizeof (struct uvs_mapping)))
3109                 goto finish;
3110               /* Now 2 * nmappings can't overflow, so we can safely
3111                  use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3112                  in mac_font_get_glyphs_for_variants.  */
3113             }
3114         }
3116       uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3118     finish:
3119       CFRelease (cmap_table);
3120     }
3122   return uvs_table;
3125 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3126    sequence consisting of the given base character C and each
3127    variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3128    result (explained below) into the corresponding GLYPHS[i].  If the
3129    entry is found in the Default UVS Table, then the result is 0.  If
3130    the entry is found in the Non-Default UVS Table, then the result is
3131    the associated glyph ID.  Otherwise, kCGFontIndexInvalid.  The
3132    elements in SELECTORS must be sorted in strictly increasing
3133    order.  */
3135 static void
3136 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3137                                   const UTF32Char selectors[], CGGlyph glyphs[],
3138                                   CFIndex count)
3140   struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3141   struct variation_selector_record *records = uvs->variation_selector_records;
3142   CFIndex i;
3143   UInt32 ir, nrecords;
3144   dispatch_queue_t queue =
3145     dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3146   dispatch_group_t group = dispatch_group_create ();
3148   nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3149   i = 0;
3150   ir = 0;
3151   while (i < count && ir < nrecords)
3152     {
3153       UInt32 default_uvs_offset, non_default_uvs_offset;
3155       if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3156         {
3157           glyphs[i++] = kCGFontIndexInvalid;
3158           continue;
3159         }
3160       else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3161         {
3162           ir++;
3163           continue;
3164         }
3166       /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3167       default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3168       non_default_uvs_offset =
3169         BUINT32_VALUE (records[ir].non_default_uvs_offset);
3170       dispatch_group_async (group, queue, ^{
3171           glyphs[i] = kCGFontIndexInvalid;
3173           if (default_uvs_offset)
3174             {
3175               struct default_uvs_table *default_uvs =
3176                 (struct default_uvs_table *) ((UInt8 *) uvs
3177                                               + default_uvs_offset);
3178               struct unicode_value_range *ranges =
3179                 default_uvs->unicode_value_ranges;
3180               UInt32 lo, hi;
3182               lo = 0;
3183               hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3184               while (lo < hi)
3185                 {
3186                   UInt32 mid = (lo + hi) / 2;
3188                   if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3189                     hi = mid;
3190                   else
3191                     lo = mid + 1;
3192                 }
3193               if (hi > 0
3194                   && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3195                             + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3196                 glyphs[i] = 0;
3197             }
3199           if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3200             {
3201               struct non_default_uvs_table *non_default_uvs =
3202                 (struct non_default_uvs_table *) ((UInt8 *) uvs
3203                                                   + non_default_uvs_offset);
3204               struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3205               UInt32 lo, hi;
3207               lo = 0;
3208               hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3209               while (lo < hi)
3210                 {
3211                   UInt32 mid = (lo + hi) / 2;
3213                   if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3214                     hi = mid;
3215                   else
3216                     lo = mid + 1;
3217                 }
3218               if (hi > 0 &&
3219                   BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3220                 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3221             }
3222         });
3223       i++;
3224       ir++;
3225     }
3226   while (i < count)
3227     glyphs[i++] = kCGFontIndexInvalid;
3228   dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3229   dispatch_release (group);
3232 static int
3233 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3235   CFDataRef uvs_table;
3236   CharacterCollection uvs_collection;
3237   int i, n = 0;
3239   block_input ();
3240   uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3242   if (uvs_table)
3243     {
3244       UTF32Char selectors[256];
3245       CGGlyph glyphs[256];
3247       for (i = 0; i < 16; i++)
3248         selectors[i] = 0xFE00 + i;
3249       for (; i < 256; i++)
3250         selectors[i] = 0xE0100 + (i - 16);
3251       mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3252       for (i = 0; i < 256; i++)
3253         {
3254           CGGlyph glyph = glyphs[i];
3256           if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3257               && glyph != kCGFontIndexInvalid)
3258             glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3259           if (glyph == kCGFontIndexInvalid)
3260             variations[i] = 0;
3261           else
3262             {
3263               variations[i] = (glyph ? glyph
3264                                : macfont_get_glyph_for_character (font, c));
3265               n++;
3266             }
3267         }
3268     }
3269   unblock_input ();
3271   return n;
3274 static const char *const macfont_booleans[] = {
3275   ":antialias",
3276   ":minspace",
3277   NULL,
3280 static const char *const macfont_non_booleans[] = {
3281   ":lang",
3282   ":script",
3283   ":destination",
3284   NULL,
3287 static void
3288 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3290   font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3293 static Boolean
3294 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3295                                           CFArrayRef languages)
3297   Boolean result = true;
3298   CFArrayRef desc_languages =
3299     CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3301   if (desc_languages == NULL)
3302     result = false;
3303   else
3304     {
3305       CFIndex desc_languages_count, i, languages_count;
3307       desc_languages_count = CFArrayGetCount (desc_languages);
3308       languages_count = CFArrayGetCount (languages);
3309       for (i = 0; i < languages_count; i++)
3310         if (!CFArrayContainsValue (desc_languages,
3311                                    CFRangeMake (0, desc_languages_count),
3312                                    CFArrayGetValueAtIndex (languages, i)))
3313           {
3314             result = false;
3315             break;
3316           }
3317       CFRelease (desc_languages);
3318     }
3320   return result;
3323 static CFStringRef
3324 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3326   CFStringRef result = NULL;
3327   CFStringRef charset_string =
3328     CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3330   if (charset_string && CFStringGetLength (charset_string) > 0)
3331     {
3332       CFStringRef keys[] = {
3333 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3334         kCTLanguageAttributeName
3335 #else
3336         CFSTR ("NSLanguage")
3337 #endif
3338       };
3339       CFTypeRef values[] = {NULL};
3340       CFIndex num_values = 0;
3341       CFArrayRef languages
3342         = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3344       if (languages && CFArrayGetCount (languages) > 0)
3345         {
3346           if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3347             values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3348           else
3349             {
3350               CFCharacterSetRef charset =
3351                 CFDictionaryGetValue (attributes,
3352                                       MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3354               result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3355             }
3356         }
3357       if (result == NULL)
3358         {
3359           CFAttributedStringRef attr_string = NULL;
3360           CTLineRef ctline = NULL;
3361           CFDictionaryRef attrs
3362             = CFDictionaryCreate (NULL, (const void **) keys,
3363                                   (const void **) values, num_values,
3364                                   &kCFTypeDictionaryKeyCallBacks,
3365                                   &kCFTypeDictionaryValueCallBacks);
3367           if (attrs)
3368             {
3369               attr_string = CFAttributedStringCreate (NULL, charset_string,
3370                                                       attrs);
3371               CFRelease (attrs);
3372             }
3373           if (attr_string)
3374             {
3375               ctline = CTLineCreateWithAttributedString (attr_string);
3376               CFRelease (attr_string);
3377             }
3378           if (ctline)
3379             {
3380               CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3381               CFIndex i, nruns = CFArrayGetCount (runs);
3382               CTFontRef font;
3384               for (i = 0; i < nruns; i++)
3385                 {
3386                   CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3387                   CFDictionaryRef attributes = CTRunGetAttributes (run);
3388                   CTFontRef font_in_run;
3390                   if (attributes == NULL)
3391                     break;
3392                   font_in_run =
3393                     CFDictionaryGetValue (attributes, kCTFontAttributeName);
3394                   if (font_in_run == NULL)
3395                     break;
3396                   if (i == 0)
3397                     font = font_in_run;
3398                   else if (!mac_ctfont_equal_in_postscript_name (font,
3399                                                                  font_in_run))
3400                     break;
3401                 }
3402               if (nruns > 0 && i == nruns)
3403                 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3404               CFRelease (ctline);
3405             }
3406         }
3407     }
3409   return result;
3412 static inline double
3413 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3415   return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3416                                      &glyph, NULL, 1);
3419 static inline CGRect
3420 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3422   return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3423                                           &glyph, NULL, 1);
3426 static CFArrayRef
3427 mac_ctfont_create_available_families (void)
3429   CFMutableArrayRef families = NULL;
3431     {
3432       CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3434       if (orig_families)
3435         {
3436           CFIndex i, count = CFArrayGetCount (orig_families);
3438           families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3439           if (families)
3440             for (i = 0; i < count; i++)
3441               {
3442                 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3444                 if (!CFStringHasPrefix (family, CFSTR ("."))
3445                     && (CTFontManagerCompareFontFamilyNames (family,
3446                                                              CFSTR ("LastResort"),
3447                                                              NULL)
3448                         != kCFCompareEqualTo))
3449                   CFArrayAppendValue (families, family);
3450               }
3451           CFRelease (orig_families);
3452         }
3453     }
3455     return families;
3458 static Boolean
3459 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3461   Boolean result;
3462   CFStringRef name1, name2;
3464   if (font1 == font2)
3465     return true;
3467   result = false;
3468   name1 = CTFontCopyPostScriptName (font1);
3469   if (name1)
3470     {
3471       name2 = CTFontCopyPostScriptName (font2);
3472       if (name2)
3473         {
3474           result = CFEqual (name1, name2);
3475           CFRelease (name2);
3476         }
3477       CFRelease (name1);
3478     }
3480   return result;
3483 static CTLineRef
3484 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3485                                              CTFontRef macfont)
3487   CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3488   CFTypeRef values[] = {NULL, NULL};
3489   CFDictionaryRef attributes = NULL;
3490   CFAttributedStringRef attr_string = NULL;
3491   CTLineRef ctline = NULL;
3492   float float_zero = 0.0f;
3494   values[0] = macfont;
3495   values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3496   if (values[1])
3497     {
3498       attributes = CFDictionaryCreate (NULL, (const void **) keys,
3499                                        (const void **) values,
3500                                        ARRAYELTS (keys),
3501                                        &kCFTypeDictionaryKeyCallBacks,
3502                                        &kCFTypeDictionaryValueCallBacks);
3503       CFRelease (values[1]);
3504     }
3505   if (attributes)
3506     {
3507       attr_string = CFAttributedStringCreate (NULL, string, attributes);
3508       CFRelease (attributes);
3509     }
3510   if (attr_string)
3511     {
3512       ctline = CTLineCreateWithAttributedString (attr_string);
3513       CFRelease (attr_string);
3514     }
3515   if (ctline)
3516     {
3517       /* Abandon if ctline contains some fonts other than the
3518          specified one.  */
3519       CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3520       CFIndex i, nruns = CFArrayGetCount (runs);
3522       for (i = 0; i < nruns; i++)
3523         {
3524           CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3525           CFDictionaryRef attributes = CTRunGetAttributes (run);
3526           CTFontRef font_in_run;
3528           if (attributes == NULL)
3529             break;
3530           font_in_run =
3531             CFDictionaryGetValue (attributes, kCTFontAttributeName);
3532           if (font_in_run == NULL)
3533             break;
3534           if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3535             break;
3536         }
3537       if (i < nruns)
3538         {
3539           CFRelease (ctline);
3540           ctline = NULL;
3541         }
3542     }
3544   return ctline;
3547 static CFIndex
3548 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3549                   struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3551   CFIndex used, result = 0;
3552   CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3554   if (ctline == NULL)
3555     return 0;
3557   used = CTLineGetGlyphCount (ctline);
3558   if (used <= glyph_len)
3559     {
3560       CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3561       CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3562       CGFloat total_advance = 0;
3563       CFIndex total_glyph_count = 0;
3565       for (k = 0; k < ctrun_count; k++)
3566         {
3567           CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3568           CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3569           struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3570           CFRange string_range, comp_range, range;
3571           CFIndex *permutation;
3573           if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3574             permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3575           else
3576             permutation = NULL;
3578 #define RIGHT_TO_LEFT_P permutation
3580           /* Now the `comp_range' member of struct mac_glyph_layout is
3581              temporarily used as a work area such that:
3582              glbuf[i].comp_range.location =
3583              min {compRange[i + 1].location, ...,
3584                      compRange[glyph_count - 1].location,
3585                      maxRange (stringRangeForCTRun)}
3586              glbuf[i].comp_range.length = maxRange (compRange[i])
3587              where compRange[i] is the range of composed characters
3588              containing i-th glyph.  */
3589           string_range = CTRunGetStringRange (ctrun);
3590           min_location = string_range.location + string_range.length;
3591           for (i = 0; i < glyph_count; i++)
3592             {
3593               struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3594               CFIndex glyph_index;
3595               CFRange rng;
3597               if (!RIGHT_TO_LEFT_P)
3598                 glyph_index = glyph_count - i - 1;
3599               else
3600                 glyph_index = i;
3601               CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3602                                      &gl->string_index);
3603               rng =
3604                 CFStringGetRangeOfComposedCharactersAtIndex (string,
3605                                                              gl->string_index);
3606               gl->comp_range.location = min_location;
3607               gl->comp_range.length = rng.location + rng.length;
3608               if (rng.location < min_location)
3609                 min_location = rng.location;
3610             }
3612           /* Fill the `comp_range' member of struct mac_glyph_layout,
3613              and setup a permutation for right-to-left text.  */
3614           comp_range = CFRangeMake (string_range.location, 0);
3615           range = CFRangeMake (0, 0);
3616           while (1)
3617             {
3618               struct mac_glyph_layout *gl =
3619                 glbuf + range.location + range.length;
3621               if (gl->comp_range.length
3622                   > comp_range.location + comp_range.length)
3623                 comp_range.length = gl->comp_range.length - comp_range.location;
3624               min_location = gl->comp_range.location;
3625               range.length++;
3627               if (min_location >= comp_range.location + comp_range.length)
3628                 {
3629                   comp_range.length = min_location - comp_range.location;
3630                   for (i = 0; i < range.length; i++)
3631                     {
3632                       glbuf[range.location + i].comp_range = comp_range;
3633                       if (RIGHT_TO_LEFT_P)
3634                         permutation[range.location + i] =
3635                           range.location + range.length - i - 1;
3636                     }
3638                   comp_range = CFRangeMake (min_location, 0);
3639                   range.location += range.length;
3640                   range.length = 0;
3641                   if (range.location == glyph_count)
3642                     break;
3643                 }
3644             }
3646           /* Then fill the remaining members.  */
3647           for (range = CFRangeMake (0, 1); range.location < glyph_count;
3648                range.location++)
3649             {
3650               struct mac_glyph_layout *gl;
3651               CGPoint position;
3653               if (!RIGHT_TO_LEFT_P)
3654                 gl = glbuf + range.location;
3655               else
3656                 {
3657                   CFIndex src, dest;
3659                   src = glyph_count - 1 - range.location;
3660                   dest = permutation[src];
3661                   gl = glbuf + dest;
3662                   if (src < dest)
3663                     {
3664                       CFIndex tmp = gl->string_index;
3666                       gl->string_index = glbuf[src].string_index;
3667                       glbuf[src].string_index = tmp;
3668                     }
3669                 }
3670               CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3672               CTRunGetPositions (ctrun, range, &position);
3673               gl->advance_delta = position.x - total_advance;
3674               gl->baseline_delta = position.y;
3675               gl->advance = (gl->advance_delta
3676                              + CTRunGetTypographicBounds (ctrun, range,
3677                                                           NULL, NULL, NULL));
3678               total_advance += gl->advance;
3679             }
3681           if (RIGHT_TO_LEFT_P)
3682             xfree (permutation);
3684 #undef RIGHT_TO_LEFT_P
3686           total_glyph_count += glyph_count;
3687         }
3689       result = used;
3690     }
3691   CFRelease (ctline);
3693   return result;
3696 /* The function below seems to cause a memory leak for the CFString
3697    created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3698    10.6.3.  For now, we use the NSGlyphInfo version instead.  */
3699 #if USE_CT_GLYPH_INFO
3700 static CGGlyph
3701 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3702                               CGFontIndex cid)
3704   CGGlyph result = kCGFontIndexInvalid;
3705   UniChar characters[] = {0xfffd};
3706   CFStringRef string;
3707   CFAttributedStringRef attr_string = NULL;
3708   CTLineRef ctline = NULL;
3710   string = CFStringCreateWithCharacters (NULL, characters,
3711                                          ARRAYELTS (characters));
3713   if (string)
3714     {
3715       CTGlyphInfoRef glyph_info =
3716         CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3717       CFDictionaryRef attributes = NULL;
3719       if (glyph_info)
3720         {
3721           CFStringRef keys[] = {kCTFontAttributeName,
3722                                 kCTGlyphInfoAttributeName};
3723           CFTypeRef values[] = {font, glyph_info};
3725           attributes = CFDictionaryCreate (NULL, (const void **) keys,
3726                                            (const void **) values,
3727                                            ARRAYELTS (keys),
3728                                            &kCFTypeDictionaryKeyCallBacks,
3729                                            &kCFTypeDictionaryValueCallBacks);
3730           CFRelease (glyph_info);
3731         }
3732       if (attributes)
3733         {
3734           attr_string = CFAttributedStringCreate (NULL, string, attributes);
3735           CFRelease (attributes);
3736         }
3737       CFRelease (string);
3738     }
3739   if (attr_string)
3740     {
3741       ctline = CTLineCreateWithAttributedString (attr_string);
3742       CFRelease (attr_string);
3743     }
3744   if (ctline)
3745     {
3746       CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3748       if (CFArrayGetCount (runs) > 0)
3749         {
3750           CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3751           CFDictionaryRef attributes = CTRunGetAttributes (run);
3753           if (attributes)
3754             {
3755               CTFontRef font_in_run =
3756                 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3758               if (font_in_run
3759                   && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3760                 {
3761                   CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3762                   if (result >= CTFontGetGlyphCount (font))
3763                     result = kCGFontIndexInvalid;
3764                 }
3765             }
3766         }
3767       CFRelease (ctline);
3768     }
3770   return result;
3772 #endif
3774 static CFArrayRef
3775 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3777   CFArrayRef result = NULL;
3779 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3780 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3781   if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3782 #endif
3783     {
3784       CTFontRef user_font =
3785         CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3787       if (user_font)
3788         {
3789           CFArrayRef languages =
3790             CFArrayCreate (NULL, (const void **) &language, 1,
3791                            &kCFTypeArrayCallBacks);
3793           if (languages)
3794             {
3795               result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3796                                                                  languages);
3797               CFRelease (languages);
3798             }
3799           CFRelease (user_font);
3800         }
3801     }
3802 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3803   else          /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3804 #endif
3805 #endif  /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3806 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3807     {
3808       CFIndex i;
3810       for (i = 0; macfont_language_default_font_names[i].language; i++)
3811         {
3812           if (CFEqual (macfont_language_default_font_names[i].language,
3813                        language))
3814             {
3815               CFMutableArrayRef descriptors =
3816                 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3818               if (descriptors)
3819                 {
3820                   CFIndex j;
3822                   for (j = 0;
3823                        macfont_language_default_font_names[i].font_names[j];
3824                        j++)
3825                     {
3826                       CFDictionaryRef attributes =
3827                         CFDictionaryCreate (NULL,
3828                                             ((const void **)
3829                                              &MAC_FONT_NAME_ATTRIBUTE),
3830                                             ((const void **)
3831                                              &macfont_language_default_font_names[i].font_names[j]),
3832                                             1, &kCFTypeDictionaryKeyCallBacks,
3833                                             &kCFTypeDictionaryValueCallBacks);
3835                       if (attributes)
3836                         {
3837                           FontDescriptorRef pat_desc =
3838                             mac_font_descriptor_create_with_attributes (attributes);
3840                           if (pat_desc)
3841                             {
3842                               FontDescriptorRef descriptor =
3843                                 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3845                               if (descriptor)
3846                                 {
3847                                   CFArrayAppendValue (descriptors, descriptor);
3848                                   CFRelease (descriptor);
3849                                 }
3850                               CFRelease (pat_desc);
3851                             }
3852                           CFRelease (attributes);
3853                         }
3854                     }
3855                   result = descriptors;
3856                 }
3857               break;
3858             }
3859         }
3860     }
3861 #endif
3863   return result;
3866 static CFStringRef
3867 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3868                                                       CFArrayRef languages)
3870   CFStringRef result = NULL;
3871   CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3872   CFArrayRef descriptors =
3873     mac_font_copy_default_descriptors_for_language (language);
3875   if (descriptors)
3876     {
3877       CFIndex i, count = CFArrayGetCount (descriptors);
3879       for (i = 0; i < count; i++)
3880         {
3881           FontDescriptorRef descriptor =
3882             CFArrayGetValueAtIndex (descriptors, i);
3884           if (macfont_supports_charset_and_languages_p (descriptor, charset,
3885                                                         Qnil, languages))
3886             {
3887               CFStringRef family =
3888                 mac_font_descriptor_copy_attribute (descriptor,
3889                                                     MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3890               if (family)
3891                 {
3892                   if (!CFStringHasPrefix (family, CFSTR ("."))
3893                       && !CFEqual (family, CFSTR ("LastResort")))
3894                     {
3895                       result = family;
3896                       break;
3897                     }
3898                   else
3899                     CFRelease (family);
3900                 }
3901             }
3902         }
3903       CFRelease (descriptors);
3904     }
3906   return result;
3909 void *
3910 macfont_get_nsctfont (struct font *font)
3912   struct macfont_info *macfont_info = (struct macfont_info *) font;
3913   FontRef macfont = macfont_info->macfont;
3915   return (void *) macfont;
3918 void
3919 mac_register_font_driver (struct frame *f)
3921   register_font_driver (&macfont_driver, f);
3925 void
3926 syms_of_macfont (void)
3928   static struct font_driver mac_font_driver;
3930   DEFSYM (Qmac_ct, "mac-ct");
3931   macfont_driver.type = Qmac_ct;
3932   register_font_driver (&macfont_driver, NULL);
3934   DEFSYM (QCdestination, ":destination");
3935   DEFSYM (QCminspace, ":minspace");