1 /* Font driver on Mac OSX Core text.
2 Copyright (C) 2009-2015 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
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #include <libkern/OSByteOrder.h>
41 static struct font_driver macfont_driver;
43 static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
44 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
45 static CFArrayRef mac_font_create_available_families (void);
46 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
47 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
49 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
51 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
52 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
53 struct mac_glyph_layout *, CFIndex);
54 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
55 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
57 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
61 struct macfont_metrics;
63 /* The actual structure for Mac font that can be cast to struct font. */
70 ScreenFontRef screen_font;
71 struct macfont_cache *cache;
72 struct macfont_metrics **metrics;
74 bool_bf synthetic_italic_p : 1;
75 bool_bf synthetic_bold_p : 1;
77 unsigned antialias : 2;
78 bool_bf color_bitmap_p : 1;
81 /* Values for the `spacing' member in `struct macfont_info'. */
85 MACFONT_SPACING_PROPORTIONAL,
87 MACFONT_SPACING_SYNTHETIC_MONO,
90 /* Values for the `antialias' member in `struct macfont_info'. */
94 MACFONT_ANTIALIAS_DEFAULT,
95 MACFONT_ANTIALIAS_OFF,
99 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
100 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
101 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
103 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
104 static const CGFloat synthetic_bold_factor = 0.024;
106 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
107 CTFontSymbolicTraits *);
108 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
110 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
111 CTFontSymbolicTraits);
112 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
113 static int macfont_glyph_extents (struct font *, CGGlyph,
114 struct font_metrics *, CGFloat *, int);
115 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
116 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
120 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
122 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
123 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
125 CGGlyph [], CFIndex);
127 /* From CFData to a lisp string. Always returns a unibyte string. */
130 cfdata_to_lisp (CFDataRef data)
132 CFIndex len = CFDataGetLength (data);
133 Lisp_Object result = make_uninit_string (len);
135 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
142 /* From CFString to a lisp string. Returns a unibyte string
143 containing a UTF-8 byte sequence. */
146 cfstring_to_lisp_nodecode (CFStringRef string)
148 Lisp_Object result = Qnil;
150 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
154 CFIndex i, length = CFStringGetLength (string);
156 for (i = 0; i < length; i++)
157 if (CFStringGetCharacterAtIndex (string, i) == 0)
161 return make_unibyte_string (s, strlen (s));
164 data = CFStringCreateExternalRepresentation (NULL, string,
165 kCFStringEncodingUTF8, '?');
168 result = cfdata_to_lisp (data);
175 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
176 cfstring_create_with_utf8_cstring, this function preserves NUL
180 cfstring_create_with_string_noencode (Lisp_Object s)
182 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
183 kCFStringEncodingUTF8, false);
186 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
187 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
188 kCFStringEncodingMacRoman, false);
194 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
196 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
198 return advancement.width;
202 mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
205 #if USE_CT_GLYPH_INFO
206 return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
209 CGGlyph result = kCGFontIndexInvalid;
210 NSFont *nsFont = (NSFont *) font;
211 unichar characters[] = {0xfffd};
213 [NSString stringWithCharacters:characters
214 length:ARRAYELTS (characters)];
215 NSGlyphInfo *glyphInfo =
216 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
217 collection:collection
219 NSDictionary *attributes =
220 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
221 glyphInfo,NSGlyphInfoAttributeName,nil];
222 NSTextStorage *textStorage =
223 [[NSTextStorage alloc] initWithString:string
224 attributes:attributes];
225 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
226 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
227 NSFont *fontInTextStorage;
229 [layoutManager addTextContainer:textContainer];
230 [textContainer release];
231 [textStorage addLayoutManager:layoutManager];
232 [layoutManager release];
235 (void) [layoutManager glyphRangeForTextContainer:textContainer];
237 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
238 effectiveRange:NULL];
239 if (fontInTextStorage == nsFont
240 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
242 NSGlyph glyph = [layoutManager glyphAtIndex:0];
244 if (glyph < [nsFont numberOfGlyphs])
248 [textStorage release];
256 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
258 NSFont *result, *font;
260 font = [NSFont fontWithName:((NSString *) name) size:size];
261 result = [font screenFont];
263 return (ScreenFontRef)[result retain];
268 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
269 CGFloat *descent, CGFloat *leading)
271 NSFont *nsFont = [(NSFont *)font printerFont];
272 NSTextStorage *textStorage;
273 NSLayoutManager *layoutManager;
274 NSTextContainer *textContainer;
276 NSPoint spaceLocation;
279 textStorage = [[NSTextStorage alloc] initWithString:@" "];
280 layoutManager = [[NSLayoutManager alloc] init];
281 textContainer = [[NSTextContainer alloc] init];
283 [textStorage setFont:nsFont];
284 [textContainer setLineFragmentPadding:0];
285 [layoutManager setUsesScreenFonts:YES];
287 [layoutManager addTextContainer:textContainer];
288 [textContainer release];
289 [textStorage addLayoutManager:layoutManager];
290 [layoutManager release];
292 if (!(textStorage && layoutManager && textContainer))
294 [textStorage release];
299 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
300 effectiveRange:NULL];
301 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
302 [textStorage release];
304 *ascent = spaceLocation.y;
305 *descent = NSHeight (usedRect) - spaceLocation.y;
307 descender = [nsFont descender];
308 if (- descender < *descent)
310 *leading = *descent + descender;
311 *descent = - descender;
318 mac_font_shape_1 (NSFont *font, NSString *string,
319 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
324 NSTextStorage *textStorage;
325 NSLayoutManager *layoutManager;
326 NSTextContainer *textContainer;
327 NSUInteger stringLength;
328 NSPoint spaceLocation;
329 NSUInteger used, numberOfGlyphs;
331 textStorage = [[NSTextStorage alloc] initWithString:string];
332 layoutManager = [[NSLayoutManager alloc] init];
333 textContainer = [[NSTextContainer alloc] init];
335 /* Append a trailing space to measure baseline position. */
336 [textStorage appendAttributedString:([[[NSAttributedString alloc]
337 initWithString:@" "] autorelease])];
338 [textStorage setFont:font];
339 [textContainer setLineFragmentPadding:0];
340 [layoutManager setUsesScreenFonts:screen_font_p];
342 [layoutManager addTextContainer:textContainer];
343 [textContainer release];
344 [textStorage addLayoutManager:layoutManager];
345 [layoutManager release];
347 if (!(textStorage && layoutManager && textContainer))
349 [textStorage release];
354 stringLength = [string length];
357 (void) [layoutManager glyphRangeForTextContainer:textContainer];
359 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
361 /* Remove the appended trailing space because otherwise it may
362 generate a wrong result for a right-to-left text. */
363 [textStorage beginEditing];
364 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
365 [textStorage endEditing];
366 (void) [layoutManager glyphRangeForTextContainer:textContainer];
369 while (i < stringLength)
372 NSFont *fontInTextStorage =
373 [textStorage attribute:NSFontAttributeName atIndex:i
374 longestEffectiveRange:&range
375 inRange:(NSMakeRange (0, stringLength))];
377 if (!(fontInTextStorage == font
378 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
380 i = NSMaxRange (range);
382 if (i < stringLength)
383 /* Make the test `used <= glyph_len' below fail if textStorage
384 contained some fonts other than the specified one. */
385 used = glyph_len + 1;
388 NSRange range = NSMakeRange (0, stringLength);
390 range = [layoutManager glyphRangeForCharacterRange:range
391 actualCharacterRange:NULL];
392 numberOfGlyphs = NSMaxRange (range);
393 used = numberOfGlyphs;
394 for (i = 0; i < numberOfGlyphs; i++)
395 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
399 if (0 < used && used <= glyph_len)
401 NSUInteger glyphIndex, prevGlyphIndex;
402 unsigned char bidiLevel;
403 NSUInteger *permutation;
404 NSRange compRange, range;
405 CGFloat totalAdvance;
408 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
411 /* For now we assume the direction is not changed within the
413 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
414 glyphs:NULL characterIndexes:NULL
415 glyphInscriptions:NULL elasticBits:NULL
416 bidiLevels:&bidiLevel];
418 permutation = xmalloc (sizeof (NSUInteger) * used);
422 #define RIGHT_TO_LEFT_P permutation
424 /* Fill the `comp_range' member of struct mac_glyph_layout, and
425 setup a permutation for right-to-left text. */
426 compRange = NSMakeRange (0, 0);
427 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
430 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
431 NSUInteger characterIndex =
432 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
434 gl->string_index = characterIndex;
436 if (characterIndex >= NSMaxRange (compRange))
438 compRange.location = NSMaxRange (compRange);
441 NSRange characterRange =
443 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
446 NSMaxRange (characterRange) - compRange.location;
447 [layoutManager glyphRangeForCharacterRange:compRange
448 actualCharacterRange:&characterRange];
449 characterIndex = NSMaxRange (characterRange) - 1;
451 while (characterIndex >= NSMaxRange (compRange));
454 for (i = 0; i < range.length; i++)
455 permutation[range.location + i] = NSMaxRange (range) - i - 1;
457 range = NSMakeRange (NSMaxRange (range), 0);
460 gl->comp_range.location = compRange.location;
461 gl->comp_range.length = compRange.length;
463 while (++glyphIndex < numberOfGlyphs)
464 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
468 for (i = 0; i < range.length; i++)
469 permutation[range.location + i] = NSMaxRange (range) - i - 1;
471 /* Then fill the remaining members. */
472 glyphIndex = prevGlyphIndex = 0;
473 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
476 if (!RIGHT_TO_LEFT_P)
483 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
484 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
485 inTextContainer:textContainer rectCount:&nrects];
487 totalAdvance = NSMaxX (glyphRects[0]);
490 for (i = 0; i < used; i++)
492 struct mac_glyph_layout *gl;
494 NSUInteger nextGlyphIndex;
499 if (!RIGHT_TO_LEFT_P)
500 gl = glyph_layouts + i;
503 NSUInteger dest = permutation[i];
505 gl = glyph_layouts + dest;
508 CFIndex tmp = gl->string_index;
510 gl->string_index = glyph_layouts[i].string_index;
511 glyph_layouts[i].string_index = tmp;
514 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
516 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
517 gl->baseline_delta = spaceLocation.y - location.y;
519 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
522 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
525 if (!RIGHT_TO_LEFT_P)
529 if (prevGlyphIndex == 0)
530 glyphRange = NSMakeRange (0, nextGlyphIndex);
532 glyphRange = NSMakeRange (glyphIndex,
533 nextGlyphIndex - glyphIndex);
536 rectArrayForGlyphRange:glyphRange
537 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
538 inTextContainer:textContainer rectCount:&nrects];
539 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
540 gl->advance_delta = location.x - totalAdvance;
541 gl->advance = maxX - totalAdvance;
548 if (nextGlyphIndex == numberOfGlyphs)
549 glyphRange = NSMakeRange (prevGlyphIndex,
550 numberOfGlyphs - prevGlyphIndex);
552 glyphRange = NSMakeRange (prevGlyphIndex,
553 glyphIndex + 1 - prevGlyphIndex);
556 rectArrayForGlyphRange:glyphRange
557 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
558 inTextContainer:textContainer rectCount:&nrects];
559 minX = min (NSMinX (glyphRects[0]), totalAdvance);
560 gl->advance = totalAdvance - minX;
562 gl->advance_delta = location.x - totalAdvance;
565 prevGlyphIndex = glyphIndex + 1;
566 glyphIndex = nextGlyphIndex;
572 #undef RIGHT_TO_LEFT_P
576 [textStorage release];
582 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
583 struct mac_glyph_layout *glyph_layouts,
586 return mac_font_shape_1 ([(NSFont *)font printerFont],
588 glyph_layouts, glyph_len, YES);
592 get_cgcolor(unsigned long idx, struct frame *f)
594 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
596 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
597 NSInteger noc = [nsColor numberOfComponents];
598 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
601 [nsColor getComponents: components];
602 cgColor = CGColorCreate (colorSpace, components);
607 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
609 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
610 CGContextSetFillColorWithColor (context, refcol_) ; \
611 CGColorRelease (refcol_); \
613 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
615 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
616 CGContextSetFillColorWithColor (context, refcol_); \
617 CGColorRelease (refcol_); \
619 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
621 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
622 CGContextSetStrokeColorWithColor (context, refcol_); \
623 CGColorRelease (refcol_); \
628 /* Mac font driver. */
634 /* characters to distinguish the charset from the others */
636 /* additional constraint by language */
639 CFCharacterSetRef cf_charset;
640 CFStringRef cf_charset_string;
641 } cf_charset_table[] =
642 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
643 { "iso8859-2", { 0x00A0, 0x010E }},
644 { "iso8859-3", { 0x00A0, 0x0108 }},
645 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
646 { "iso8859-5", { 0x00A0, 0x0401 }},
647 { "iso8859-6", { 0x00A0, 0x060C }},
648 { "iso8859-7", { 0x00A0, 0x0384 }},
649 { "iso8859-8", { 0x00A0, 0x05D0 }},
650 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
651 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
652 { "iso8859-11", { 0x00A0, 0x0E01 }},
653 { "iso8859-13", { 0x00A0, 0x201C }},
654 { "iso8859-14", { 0x00A0, 0x0174 }},
655 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
656 { "iso8859-16", { 0x00A0, 0x0218}},
657 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
658 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
659 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
660 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
661 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
662 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
663 { "cns11643.1992-3", { 0x201A9 }},
664 { "cns11643.1992-4", { 0x20057 }},
665 { "cns11643.1992-5", { 0x20000 }},
666 { "cns11643.1992-6", { 0x20003 }},
667 { "cns11643.1992-7", { 0x20055 }},
668 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
669 { "jisx0212.1990-0", { 0x4E44 }},
670 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
671 { "jisx0213.2000-2", { 0xFA49 }},
672 { "jisx0213.2004-1", { 0x20B9F }},
673 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
674 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
675 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
676 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
677 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
678 { "unicode-sip", { 0x20000 }},
682 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
685 CFStringRef language;
686 CFStringRef font_names[3];
687 } macfont_language_default_font_names[] = {
688 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
689 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
691 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
692 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
694 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
695 CFSTR ("STXihei"), /* 10.4 - 10.5 */
697 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
698 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
704 static CGFloat macfont_antialias_threshold;
707 macfont_update_antialias_threshold (void)
713 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
714 kCFPreferencesCurrentApplication,
717 macfont_antialias_threshold = threshold;
720 static inline Lisp_Object
721 macfont_intern_prop_cfstring (CFStringRef cfstring)
723 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
725 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
728 static inline CFIndex
729 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
740 unichars[0] = (c >> 10) + 0xD800;
741 unichars[1] = (c & 0x3FF) + 0xDC00;
748 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
749 CTFontSymbolicTraits *sym_traits)
753 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
754 OS X 10.6 when the value is greater than or equal to 1 << 31. */
755 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
757 *sym_traits = (CTFontSymbolicTraits) sint64_value;
766 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
767 Lisp_Object spec_or_entity)
770 CFDictionaryRef dict;
774 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
777 ASET (spec_or_entity, FONT_FAMILY_INDEX,
778 macfont_intern_prop_cfstring (str));
781 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
785 enum font_property_index index;
789 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
790 {{-0.4, 50}, /* light */
791 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
792 {0, 100}, /* normal */
793 {0.24, 140}, /* (semi-bold + normal) / 2 */
794 {0.4, 200}, /* bold */
795 {CGFLOAT_MAX, CGFLOAT_MAX}}},
796 {FONT_SLANT_INDEX, kCTFontSlantTrait,
797 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
798 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
799 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
802 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
804 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
805 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
807 CGPoint *point = numeric_traits[i].points;
809 while (point->x < floatval)
811 if (point == numeric_traits[i].points)
813 else if (point->x == CGFLOAT_MAX)
815 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
816 * ((point->y - (point - 1)->y)
817 / (point->x - (point - 1)->x)));
818 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
819 make_number (lround (floatval)));
823 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
826 CTFontSymbolicTraits sym_traits;
829 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
830 spacing = (sym_traits & kCTFontTraitMonoSpace
831 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
832 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
837 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
838 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
839 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
841 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
847 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
848 CTFontSymbolicTraits synth_sym_traits)
851 CFDictionaryRef dict;
852 CTFontSymbolicTraits sym_traits = 0;
855 entity = font_make_entity ();
857 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
858 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
860 macfont_store_descriptor_attributes (desc, entity);
862 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
865 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
868 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
871 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
872 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
873 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
874 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
875 font_put_extra (entity, QCfont_entity,
876 make_save_ptr_int ((void *) name, sym_traits));
877 if (synth_sym_traits & kCTFontTraitItalic)
878 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
879 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
880 if (synth_sym_traits & kCTFontTraitBold)
881 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
882 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
883 if (synth_sym_traits & kCTFontTraitMonoSpace)
884 ASET (entity, FONT_SPACING_INDEX,
885 make_number (FONT_SPACING_SYNTHETIC_MONO));
890 /* Cache for font family name symbols vs CFStrings. A value of nil
891 means the cache has been invalidated. Otherwise the value is a Lisp
892 hash table whose keys are symbols and the value for a key is either
893 nil (no corresponding family name) or a Lisp save value wrapping the
894 corresponding family name in CFString. */
896 static Lisp_Object macfont_family_cache;
899 macfont_invalidate_family_cache (void)
901 if (HASH_TABLE_P (macfont_family_cache))
903 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
904 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
906 for (i = 0; i < size; ++i)
907 if (!NILP (HASH_HASH (h, i)))
909 Lisp_Object value = HASH_VALUE (h, i);
911 if (SAVE_VALUEP (value))
912 CFRelease (XSAVE_POINTER (value, 0));
914 macfont_family_cache = Qnil;
919 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
921 if (HASH_TABLE_P (macfont_family_cache))
923 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
924 ptrdiff_t i = hash_lookup (h, symbol, NULL);
928 Lisp_Object value = HASH_VALUE (h, i);
930 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
940 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
942 struct Lisp_Hash_Table *h;
947 if (!HASH_TABLE_P (macfont_family_cache))
953 macfont_family_cache = Fmake_hash_table (2, args);
956 h = XHASH_TABLE (macfont_family_cache);
957 i = hash_lookup (h, symbol, &hash);
958 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
961 Lisp_Object old_value = HASH_VALUE (h, i);
963 if (SAVE_VALUEP (old_value))
964 CFRelease (XSAVE_POINTER (old_value, 0));
965 set_hash_value_slot (h, i, value);
968 hash_put (h, symbol, value, hash);
971 /* Cache of all the available font family names except "LastResort"
972 and those start with ".". NULL means the cache has been invalidated.
973 Otherwise, the value is CFArray of CFStrings and the elements are
974 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
975 OS X 10.6 and later). */
977 static CFArrayRef macfont_available_families_cache = NULL;
980 macfont_invalidate_available_families_cache (void)
982 if (macfont_available_families_cache)
984 CFRelease (macfont_available_families_cache);
985 macfont_available_families_cache = NULL;
990 macfont_handle_font_change_notification (CFNotificationCenterRef center,
992 CFStringRef name, const void *object,
993 CFDictionaryRef userInfo)
995 macfont_invalidate_family_cache ();
996 macfont_invalidate_available_families_cache ();
1000 macfont_init_font_change_handler (void)
1002 static bool initialized = false;
1008 CFNotificationCenterAddObserver
1009 (CFNotificationCenterGetLocalCenter (), NULL,
1010 macfont_handle_font_change_notification,
1011 kCTFontManagerRegisteredFontsChangedNotification,
1012 NULL, CFNotificationSuspensionBehaviorCoalesce);
1016 macfont_copy_available_families_cache (void)
1018 macfont_init_font_change_handler ();
1020 if (macfont_available_families_cache == NULL)
1021 macfont_available_families_cache = mac_font_create_available_families ();
1023 return (macfont_available_families_cache
1024 ? CFRetain (macfont_available_families_cache) : NULL);
1028 macfont_create_family_with_symbol (Lisp_Object symbol)
1030 CFStringRef result = NULL, family_name;
1031 CFDictionaryRef attributes = NULL;
1032 CTFontDescriptorRef pat_desc = NULL;
1034 if (macfont_get_family_cache_if_present (symbol, &result))
1035 return result ? CFRetain (result) : NULL;
1037 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1041 CFDictionaryCreate (NULL,
1042 (const void **) &kCTFontFamilyNameAttribute,
1043 (const void **) &family_name, 1,
1044 &kCFTypeDictionaryKeyCallBacks,
1045 &kCFTypeDictionaryValueCallBacks);
1046 CFRelease (family_name);
1050 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1051 CFRelease (attributes);
1055 CTFontDescriptorRef desc =
1056 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1061 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1064 macfont_set_family_cache (symbol, result);
1065 CFRelease (pat_desc);
1071 #define WIDTH_FRAC_BITS (4)
1072 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1074 struct macfont_metrics
1076 unsigned char lbearing_low, rbearing_low;
1077 signed lbearing_high : 4, rbearing_high : 4;
1078 unsigned char ascent_low, descent_low;
1079 signed ascent_high : 4, descent_high : 4;
1081 /* These two members are used for fixed-point representation of
1082 glyph width. The `width_int' member is an integer that is
1083 closest to the width. The `width_frac' member is the fractional
1084 adjustment representing a value in [-.5, .5], multiplied by
1085 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1086 the advance delta for centering instead of the glyph width. */
1087 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1090 #define METRICS_VALUE(metrics, member) \
1091 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1092 #define METRICS_SET_VALUE(metrics, member, value) \
1093 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1094 (metrics)->member##_high = tmp >> 8;} while (0)
1098 METRICS_INVALID = -1, /* metrics entry is invalid */
1099 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1102 #define METRICS_STATUS(metrics) \
1103 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1104 #define METRICS_SET_STATUS(metrics, status) \
1105 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1106 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1108 #define METRICS_NCOLS_PER_ROW (128)
1109 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1110 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1113 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1114 struct font_metrics *metrics, CGFloat *advance_delta,
1115 int force_integral_p)
1117 struct macfont_info *macfont_info = (struct macfont_info *) font;
1118 CTFontRef macfont = macfont_info->macfont;
1120 struct macfont_metrics *cache;
1123 row = glyph / METRICS_NCOLS_PER_ROW;
1124 col = glyph % METRICS_NCOLS_PER_ROW;
1125 if (row >= macfont_info->metrics_nrows)
1127 macfont_info->metrics =
1128 xrealloc (macfont_info->metrics,
1129 sizeof (struct macfont_metrics *) * (row + 1));
1130 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1131 (sizeof (struct macfont_metrics *)
1132 * (row + 1 - macfont_info->metrics_nrows)));
1133 macfont_info->metrics_nrows = row + 1;
1135 if (macfont_info->metrics[row] == NULL)
1137 struct macfont_metrics *new;
1140 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1141 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1142 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1143 macfont_info->metrics[row] = new;
1145 cache = macfont_info->metrics[row] + col;
1147 if (METRICS_STATUS (cache) == METRICS_INVALID)
1151 if (macfont_info->screen_font)
1152 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1154 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1156 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1157 advance delta value. */
1158 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1159 fwidth = (font->pixel_size - fwidth) / 2;
1160 cache->width_int = lround (fwidth);
1161 cache->width_frac = lround ((fwidth - cache->width_int)
1162 * WIDTH_FRAC_SCALE);
1163 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1165 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1166 width = font->pixel_size;
1168 width = cache->width_int;
1172 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1174 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1176 if (macfont_info->synthetic_italic_p)
1178 /* We assume the members a, b, c, and d in
1179 synthetic_italic_atfm are non-negative. */
1181 CGPointApplyAffineTransform (bounds.origin,
1182 synthetic_italic_atfm);
1184 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1186 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1188 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1190 bounds = CGRectInset (bounds, d, d);
1192 switch (macfont_info->spacing)
1194 case MACFONT_SPACING_PROPORTIONAL:
1195 bounds.origin.x += - (cache->width_frac
1196 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1198 case MACFONT_SPACING_MONO:
1200 case MACFONT_SPACING_SYNTHETIC_MONO:
1201 bounds.origin.x += (cache->width_int
1202 + (cache->width_frac
1203 / (CGFloat) WIDTH_FRAC_SCALE));
1206 if (bounds.size.width > 0)
1208 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1209 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1210 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1212 bounds = CGRectIntegral (bounds);
1213 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1214 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1215 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1216 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1218 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1219 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1220 metrics->width = width;
1221 metrics->ascent = METRICS_VALUE (cache, ascent);
1222 metrics->descent = METRICS_VALUE (cache, descent);
1227 switch (macfont_info->spacing)
1229 case MACFONT_SPACING_PROPORTIONAL:
1230 *advance_delta = (force_integral_p ? 0
1231 : - (cache->width_frac
1232 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1234 case MACFONT_SPACING_MONO:
1237 case MACFONT_SPACING_SYNTHETIC_MONO:
1238 *advance_delta = (force_integral_p ? cache->width_int
1240 + (cache->width_frac
1241 / (CGFloat) WIDTH_FRAC_SCALE)));
1249 static CFMutableDictionaryRef macfont_cache_dictionary;
1251 /* Threshold used in row_nkeys_or_perm. This must be less than or
1252 equal to the number of rows that are invalid as BMP (i.e., from
1253 U+D800 to U+DFFF). */
1254 #define ROW_PERM_OFFSET (8)
1256 /* The number of glyphs that can be stored in a value for a single
1257 entry of CFDictionary. */
1258 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1260 struct macfont_cache
1262 int reference_count;
1263 CFCharacterSetRef cf_charset;
1265 /* The cached glyph for a BMP character c is stored in
1266 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1267 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1268 unsigned char row_nkeys_or_perm[256];
1271 /* Number of rows for which the BMP cache is allocated so far.
1272 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1275 /* The cached glyph for a character c is stored as the (c %
1276 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1277 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1278 not stored here if row_nkeys_or_perm[c / 256] >=
1280 CFMutableDictionaryRef dictionary;
1284 /* UVS (Unicode Variation Sequence) subtable data, which is of
1285 type CFDataRef if available. NULL means it is not initialized
1286 yet. kCFNull means the subtable is not found and there is no
1287 suitable fallback table for this font. */
1290 /* Character collection specifying the destination of the mapping
1291 provided by `table' above. If `table' is obtained from the UVS
1292 subtable in the font cmap table, then the value of this member
1293 should be kCTCharacterCollectionIdentityMapping. */
1294 CTCharacterCollection collection;
1298 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1299 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1300 static void macfont_release_cache (struct macfont_cache *);
1301 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1302 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1303 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1304 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1305 CTCharacterCollection, CGFontIndex);
1306 static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
1308 static struct macfont_cache *
1309 macfont_lookup_cache (CFStringRef key)
1311 struct macfont_cache *cache;
1313 if (macfont_cache_dictionary == NULL)
1315 macfont_cache_dictionary =
1316 CFDictionaryCreateMutable (NULL, 0,
1317 &kCFTypeDictionaryKeyCallBacks, NULL);
1321 cache = ((struct macfont_cache *)
1322 CFDictionaryGetValue (macfont_cache_dictionary, key));
1326 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1330 cache = xzalloc (sizeof (struct macfont_cache));
1331 /* Treat the LastResort font as if it contained glyphs for
1332 all characters. This may look too rough, but neither
1333 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1334 for this font is correct for non-BMP characters on Mac OS
1336 if (CFEqual (key, CFSTR ("LastResort")))
1338 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1341 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1343 if (cache->cf_charset == NULL)
1344 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1345 CFDictionaryAddValue (macfont_cache_dictionary, key,
1346 (const void *) cache);
1347 CFRelease (macfont);
1354 static struct macfont_cache *
1355 macfont_retain_cache (struct macfont_cache *cache)
1357 cache->reference_count++;
1363 macfont_release_cache (struct macfont_cache *cache)
1365 if (--cache->reference_count == 0)
1369 for (i = 0; i < cache->glyph.nrows; i++)
1370 xfree (cache->glyph.matrix[i]);
1371 xfree (cache->glyph.matrix);
1372 if (cache->glyph.dictionary)
1373 CFRelease (cache->glyph.dictionary);
1374 memset (&cache->glyph, 0, sizeof (cache->glyph));
1375 if (cache->uvs.table)
1376 CFRelease (cache->uvs.table);
1377 memset (&cache->uvs, 0, sizeof (cache->uvs));
1381 static CFCharacterSetRef
1382 macfont_get_cf_charset (struct font *font)
1384 struct macfont_info *macfont_info = (struct macfont_info *) font;
1386 return macfont_info->cache->cf_charset;
1389 static CFCharacterSetRef
1390 macfont_get_cf_charset_for_name (CFStringRef name)
1392 struct macfont_cache *cache = macfont_lookup_cache (name);
1394 return cache->cf_charset;
1398 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1400 struct macfont_info *macfont_info = (struct macfont_info *) font;
1401 CTFontRef macfont = macfont_info->macfont;
1402 struct macfont_cache *cache = macfont_info->cache;
1404 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1407 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1409 if (nkeys_or_perm < ROW_PERM_OFFSET)
1411 UniChar unichars[256], ch;
1415 dispatch_queue_t queue;
1416 dispatch_group_t group = NULL;
1420 CFMutableDictionaryRef dictionary;
1421 uintptr_t key, value;
1425 if (cache->glyph.dictionary == NULL)
1426 cache->glyph.dictionary =
1427 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1428 dictionary = cache->glyph.dictionary;
1429 key = c / NGLYPHS_IN_VALUE;
1430 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1431 value = ((uintptr_t)
1432 CFDictionaryGetValue (dictionary, (const void *) key));
1433 glyph = (value >> nshifts);
1437 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1440 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1442 glyph = kCGFontIndexInvalid;
1445 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1446 value |= ((uintptr_t) glyph << nshifts);
1447 CFDictionarySetValue (dictionary, (const void *) key,
1448 (const void *) value);
1454 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1455 group = dispatch_group_create ();
1456 dispatch_group_async (group, queue, ^{
1459 nkeys = nkeys_or_perm;
1460 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1461 if (CFDictionaryContainsKey (dictionary,
1462 (const void *) key))
1464 CFDictionaryRemoveValue (dictionary,
1465 (const void *) key);
1473 for (i = 0; i < 256; i++)
1476 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1477 unichars[len++] = ch;
1480 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1483 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1486 int next = unichars[len - 1] % 256;
1489 glyphs[i] = kCGFontIndexInvalid;
1492 glyphs[i] = glyphs[len];
1499 glyphs[i] = kCGFontIndexInvalid;
1501 nrows = cache->glyph.nrows;
1502 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1503 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1505 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1506 sizeof (CGGlyph *) * nrows);
1507 cache->glyph.matrix[nrows - 1] = glyphs;
1508 cache->glyph.nrows = nrows;
1512 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1513 dispatch_release (group);
1517 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1521 uintptr_t key, value;
1525 if (cache->glyph.dictionary == NULL)
1526 cache->glyph.dictionary =
1527 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1528 key = c / NGLYPHS_IN_VALUE;
1529 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1530 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1531 (const void *) key);
1532 glyph = (value >> nshifts);
1535 UniChar unichars[2];
1537 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1539 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1542 glyph = kCGFontIndexInvalid;
1544 value |= ((uintptr_t) glyph << nshifts);
1545 CFDictionarySetValue (cache->glyph.dictionary,
1546 (const void *) key, (const void *) value);
1554 macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1557 struct macfont_info *macfont_info = (struct macfont_info *) font;
1558 CTFontRef macfont = macfont_info->macfont;
1561 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1565 macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1567 struct macfont_info *macfont_info = (struct macfont_info *) font;
1568 CTFontRef macfont = macfont_info->macfont;
1569 struct macfont_cache *cache = macfont_info->cache;
1570 CFDataRef result = NULL;
1572 if (cache->uvs.table == NULL)
1574 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1575 CTCharacterCollection uvs_collection =
1576 kCTCharacterCollectionIdentityMapping;
1578 if (uvs_table == NULL
1579 && mac_font_get_glyph_for_cid (macfont,
1580 kCTCharacterCollectionAdobeJapan1,
1581 6480) != kCGFontIndexInvalid)
1583 /* If the glyph for U+4E55 is accessible via its CID 6480,
1584 then we use the Adobe-Japan1 UVS table, which maps a
1585 variation sequence to a CID, as a fallback. */
1586 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1588 if (mac_uvs_table_adobe_japan1 == NULL)
1589 mac_uvs_table_adobe_japan1 =
1590 CFDataCreateWithBytesNoCopy (NULL,
1591 mac_uvs_table_adobe_japan1_bytes,
1592 sizeof (mac_uvs_table_adobe_japan1_bytes),
1594 if (mac_uvs_table_adobe_japan1)
1596 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1597 uvs_collection = kCTCharacterCollectionAdobeJapan1;
1600 if (uvs_table == NULL)
1601 cache->uvs.table = kCFNull;
1603 cache->uvs.table = uvs_table;
1604 cache->uvs.collection = uvs_collection;
1607 if (cache->uvs.table != kCFNull)
1609 result = cache->uvs.table;
1610 *collection = cache->uvs.collection;
1616 static Lisp_Object macfont_get_cache (struct frame *);
1617 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1618 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1619 static Lisp_Object macfont_list_family (struct frame *);
1620 static void macfont_free_entity (Lisp_Object);
1621 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1622 static void macfont_close (struct font *);
1623 static int macfont_has_char (Lisp_Object, int);
1624 static unsigned macfont_encode_char (struct font *, int);
1625 static void macfont_text_extents (struct font *, unsigned int *, int,
1626 struct font_metrics *);
1627 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1628 static Lisp_Object macfont_shape (Lisp_Object);
1629 static int macfont_variation_glyphs (struct font *, int c,
1630 unsigned variations[256]);
1631 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1633 static struct font_driver macfont_driver =
1635 LISP_INITIALLY_ZERO, /* Qmac_ct */
1636 0, /* case insensitive */
1640 macfont_list_family,
1641 macfont_free_entity,
1644 NULL, /* prepare_face */
1645 NULL, /* done_face */
1647 macfont_encode_char,
1648 macfont_text_extents,
1650 NULL, /* get_bitmap */
1651 NULL, /* free_bitmap */
1652 NULL, /* anchor_point */
1653 NULL, /* otf_capability */
1654 NULL, /* otf_drive */
1655 NULL, /* start_for_frame */
1656 NULL, /* end_for_frame */
1659 macfont_variation_glyphs,
1660 macfont_filter_properties,
1664 macfont_get_cache (struct frame * f)
1666 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1668 return (dpyinfo->name_list_element);
1672 macfont_get_charset (Lisp_Object registry)
1674 char *str = SSDATA (SYMBOL_NAME (registry));
1675 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1679 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1683 else if (str[i] == '*')
1690 regexp = make_unibyte_string (re, j);
1691 for (i = 0; cf_charset_table[i].name; i++)
1692 if (fast_c_string_match_ignore_case
1693 (regexp, cf_charset_table[i].name,
1694 strlen (cf_charset_table[i].name)) >= 0)
1696 if (! cf_charset_table[i].name)
1698 if (! cf_charset_table[i].cf_charset)
1700 int *uniquifier = cf_charset_table[i].uniquifier;
1701 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1704 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1708 for (j = 0; uniquifier[j]; j++)
1710 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1712 CFCharacterSetAddCharactersInRange (charset,
1713 CFRangeMake (uniquifier[j], 1));
1716 string = CFStringCreateWithCharacters (NULL, unichars, count);
1719 CFRelease (charset);
1722 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1724 CFRelease (charset);
1725 /* CFCharacterSetCreateWithCharactersInString does not handle
1726 surrogate pairs properly as of Mac OS X 10.5. */
1727 cf_charset_table[i].cf_charset_string = string;
1735 unsigned int script_tag, langsys_tag;
1737 unsigned int *features[2];
1740 #define OTF_SYM_TAG(SYM, TAG) \
1742 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1743 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1746 #define OTF_TAG_STR(TAG, P) \
1748 (P)[0] = (char) (TAG >> 24); \
1749 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1750 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1751 (P)[3] = (char) (TAG & 0xFF); \
1755 static struct OpenTypeSpec *
1756 macfont_get_open_type_spec (Lisp_Object otf_spec)
1758 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1765 spec->script = XCAR (otf_spec);
1766 if (! NILP (spec->script))
1768 OTF_SYM_TAG (spec->script, spec->script_tag);
1769 val = assq_no_quit (spec->script, Votf_script_alist);
1770 if (CONSP (val) && SYMBOLP (XCDR (val)))
1771 spec->script = XCDR (val);
1773 spec->script = Qnil;
1776 spec->script_tag = 0x44464C54; /* "DFLT" */
1777 otf_spec = XCDR (otf_spec);
1778 spec->langsys_tag = 0;
1779 if (! NILP (otf_spec))
1781 val = XCAR (otf_spec);
1783 OTF_SYM_TAG (val, spec->langsys_tag);
1784 otf_spec = XCDR (otf_spec);
1786 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1787 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1791 val = XCAR (otf_spec);
1794 len = Flength (val);
1796 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1798 : malloc (XINT (len) * sizeof *spec->features[i]));
1799 if (! spec->features[i])
1801 if (i > 0 && spec->features[0])
1802 free (spec->features[0]);
1806 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1808 if (NILP (XCAR (val)))
1814 OTF_SYM_TAG (XCAR (val), tag);
1815 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1818 spec->nfeatures[i] = j;
1823 static CFMutableDictionaryRef
1824 macfont_create_attributes_with_spec (Lisp_Object spec)
1826 Lisp_Object tmp, extra;
1827 CFMutableArrayRef langarray = NULL;
1828 CFCharacterSetRef charset = NULL;
1829 CFStringRef charset_string = NULL;
1830 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1831 Lisp_Object script = Qnil;
1832 Lisp_Object registry;
1833 int cf_charset_idx, i;
1834 struct OpenTypeSpec *otspec = NULL;
1836 enum font_property_index index;
1839 } numeric_traits[] =
1840 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1841 {{-0.4, 50}, /* light */
1842 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1843 {0, 100}, /* normal */
1844 {0.24, 140}, /* (semi-bold + normal) / 2 */
1845 {0.4, 200}, /* bold */
1846 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1847 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1848 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1849 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1850 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1852 registry = AREF (spec, FONT_REGISTRY_INDEX);
1854 || EQ (registry, Qascii_0)
1855 || EQ (registry, Qiso10646_1)
1856 || EQ (registry, Qunicode_bmp))
1857 cf_charset_idx = -1;
1862 cf_charset_idx = macfont_get_charset (registry);
1863 if (cf_charset_idx < 0)
1865 charset = cf_charset_table[cf_charset_idx].cf_charset;
1866 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1867 lang = cf_charset_table[cf_charset_idx].lang;
1870 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1873 CFArrayAppendValue (langarray, lang);
1877 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1878 CONSP (extra); extra = XCDR (extra))
1880 Lisp_Object key, val;
1883 key = XCAR (tmp), val = XCDR (tmp);
1884 if (EQ (key, QClang))
1887 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1892 for (; CONSP (val); val = XCDR (val))
1893 if (SYMBOLP (XCAR (val)))
1896 cfstring_create_with_string_noencode (SYMBOL_NAME
1901 CFArrayAppendValue (langarray, lang);
1905 else if (EQ (key, QCotf))
1907 otspec = macfont_get_open_type_spec (val);
1910 script = otspec->script;
1912 else if (EQ (key, QCscript))
1916 if (! NILP (script) && ! charset)
1918 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1920 if (CONSP (chars) && CONSP (CDR (chars)))
1922 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1923 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1925 if (! string || !cs)
1933 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1934 if (CHARACTERP (XCAR (chars)))
1936 UniChar unichars[2];
1938 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1940 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1942 CFStringAppendCharacters (string, unichars, count);
1943 CFCharacterSetAddCharactersInRange (cs, range);
1946 /* CFCharacterSetCreateWithCharactersInString does not
1947 handle surrogate pairs properly as of Mac OS X 10.5. */
1948 charset_string = string;
1952 attributes = CFDictionaryCreateMutable (NULL, 0,
1953 &kCFTypeDictionaryKeyCallBacks,
1954 &kCFTypeDictionaryValueCallBacks);
1958 tmp = AREF (spec, FONT_FAMILY_INDEX);
1959 if (SYMBOLP (tmp) && ! NILP (tmp))
1961 CFStringRef family = macfont_create_family_with_symbol (tmp);
1965 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1970 traits = CFDictionaryCreateMutable (NULL, 4,
1971 &kCFTypeDictionaryKeyCallBacks,
1972 &kCFTypeDictionaryValueCallBacks);
1976 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1978 tmp = AREF (spec, numeric_traits[i].index);
1981 CGPoint *point = numeric_traits[i].points;
1982 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1985 while (point->y < floatval)
1987 if (point == numeric_traits[i].points)
1989 else if (point->y == CGFLOAT_MAX)
1991 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1992 * ((point->x - (point - 1)->x)
1993 / (point->y - (point - 1)->y)));
1996 else if (floatval < -1.0)
1998 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2001 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2005 if (CFDictionaryGetCount (traits))
2006 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2009 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2012 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2015 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2022 CFRelease (attributes);
2027 if (langarray) CFRelease (langarray);
2028 if (charset && cf_charset_idx < 0) CFRelease (charset);
2029 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2030 if (traits) CFRelease (traits);
2033 if (otspec->nfeatures[0] > 0)
2034 free (otspec->features[0]);
2035 if (otspec->nfeatures[1] > 0)
2036 free (otspec->features[1]);
2044 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2045 CFCharacterSetRef charset,
2047 CFArrayRef languages)
2049 Boolean result = true;
2051 if (charset || VECTORP (chars))
2053 CFCharacterSetRef desc_charset =
2054 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2056 if (desc_charset == NULL)
2061 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2062 else /* VECTORP (chars) */
2066 for (j = 0; j < ASIZE (chars); j++)
2067 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2068 && CFCharacterSetIsLongCharacterMember (desc_charset,
2069 XFASTINT (AREF (chars, j))))
2071 if (j == ASIZE (chars))
2074 CFRelease (desc_charset);
2077 if (result && languages)
2078 result = mac_font_descriptor_supports_languages (desc, languages);
2084 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2085 CTFontSymbolicTraits sym_traits2)
2087 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2090 /* We prefer synthetic bold of italic to synthetic italic of bold
2091 when both bold and italic are available but bold-italic is not
2093 if (diff & kCTFontTraitBold)
2094 distance |= (1 << 0);
2095 if (diff & kCTFontTraitItalic)
2096 distance |= (1 << 1);
2097 if (diff & kCTFontTraitMonoSpace)
2098 distance |= (1 << 2);
2104 macfont_closest_traits_index_p (CFArrayRef traits_array,
2105 CTFontSymbolicTraits target,
2108 CFIndex i, count = CFArrayGetCount (traits_array);
2109 CTFontSymbolicTraits traits;
2112 traits = ((CTFontSymbolicTraits) (uintptr_t)
2113 CFArrayGetValueAtIndex (traits_array, index));
2114 my_distance = macfont_traits_distance (target, traits);
2116 for (i = 0; i < count; i++)
2119 traits = ((CTFontSymbolicTraits) (uintptr_t)
2120 CFArrayGetValueAtIndex (traits_array, i));
2121 if (macfont_traits_distance (target, traits) < my_distance)
2129 macfont_list (struct frame *f, Lisp_Object spec)
2131 Lisp_Object val = Qnil, family, extra;
2133 CFStringRef family_name = NULL;
2134 CFMutableDictionaryRef attributes = NULL, traits;
2135 Lisp_Object chars = Qnil;
2137 CTFontSymbolicTraits synth_sym_traits = 0;
2138 CFArrayRef families;
2139 CFIndex families_count;
2140 CFCharacterSetRef charset = NULL;
2141 CFArrayRef languages = NULL;
2145 family = AREF (spec, FONT_FAMILY_INDEX);
2146 if (! NILP (family))
2148 family_name = macfont_create_family_with_symbol (family);
2149 if (family_name == NULL)
2153 attributes = macfont_create_attributes_with_spec (spec);
2157 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2159 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2160 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2162 traits = ((CFMutableDictionaryRef)
2163 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2165 n = FONT_SLANT_NUMERIC (spec);
2166 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2168 synth_sym_traits |= kCTFontTraitItalic;
2170 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2173 n = FONT_WEIGHT_NUMERIC (spec);
2174 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2176 synth_sym_traits |= kCTFontTraitBold;
2178 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2182 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2184 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2186 if (CFStringHasPrefix (language, CFSTR ("ja"))
2187 || CFStringHasPrefix (language, CFSTR ("ko"))
2188 || CFStringHasPrefix (language, CFSTR ("zh")))
2189 synth_sym_traits |= kCTFontTraitMonoSpace;
2192 /* Create array of families. */
2194 families = CFArrayCreate (NULL, (const void **) &family_name,
2195 1, &kCFTypeArrayCallBacks);
2198 CFStringRef pref_family;
2199 CFIndex families_count, pref_family_index = -1;
2201 families = macfont_copy_available_families_cache ();
2202 if (families == NULL)
2205 families_count = CFArrayGetCount (families);
2207 /* Move preferred family to the front if exists. */
2209 mac_font_create_preferred_family_for_attributes (attributes);
2213 CFArrayGetFirstIndexOfValue (families,
2214 CFRangeMake (0, families_count),
2216 CFRelease (pref_family);
2218 if (pref_family_index > 0)
2220 CFMutableArrayRef mutable_families =
2221 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2223 if (mutable_families)
2225 CFArrayAppendValue (mutable_families,
2226 CFArrayGetValueAtIndex (families,
2227 pref_family_index));
2228 CFArrayAppendArray (mutable_families, families,
2229 CFRangeMake (0, pref_family_index));
2230 if (pref_family_index + 1 < families_count)
2231 CFArrayAppendArray (mutable_families, families,
2232 CFRangeMake (pref_family_index + 1,
2234 - (pref_family_index + 1)));
2235 CFRelease (families);
2236 families = mutable_families;
2241 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2245 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2249 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2252 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2253 if (CONSP (val) && VECTORP (XCDR (val)))
2261 CFRetain (languages);
2262 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2266 extra = AREF (spec, FONT_EXTRA_INDEX);
2267 families_count = CFArrayGetCount (families);
2268 for (i = 0; i < families_count; i++)
2270 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2271 CTFontDescriptorRef pat_desc;
2273 CFIndex descs_count;
2274 CFMutableArrayRef filtered_descs, traits_array;
2278 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2280 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2284 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2285 10.7 returns NULL if pat_desc represents the LastResort font.
2286 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2287 trailing "s") for such a font. */
2288 if (!CFEqual (family_name, CFSTR ("LastResort")))
2289 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2292 CTFontDescriptorRef lr_desc =
2293 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2296 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2297 &kCFTypeArrayCallBacks);
2298 CFRelease (lr_desc);
2303 CFRelease (pat_desc);
2307 descs_count = CFArrayGetCount (descs);
2308 if (descs_count == 0
2309 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2318 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2319 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2320 for (j = 0; j < descs_count; j++)
2322 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2323 CFDictionaryRef dict;
2325 CTFontSymbolicTraits sym_traits;
2327 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2331 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2334 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2338 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2339 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2340 != (spacing >= FONT_SPACING_MONO)))
2343 /* Don't use a color bitmap font unless its family is
2344 explicitly specified. */
2345 if ((sym_traits & kCTFontTraitColorGlyphs) && NILP (family))
2349 && !macfont_supports_charset_and_languages_p (desc, charset,
2353 CFArrayAppendValue (filtered_descs, desc);
2354 CFArrayAppendValue (traits_array,
2355 (const void *) (uintptr_t) sym_traits);
2359 descs = filtered_descs;
2360 descs_count = CFArrayGetCount (descs);
2362 for (j = 0; j < descs_count; j++)
2364 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2365 CTFontSymbolicTraits sym_traits =
2366 ((CTFontSymbolicTraits) (uintptr_t)
2367 CFArrayGetValueAtIndex (traits_array, j));
2368 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2370 mask_min = ((synth_sym_traits ^ sym_traits)
2371 & (kCTFontTraitItalic | kCTFontTraitBold));
2372 if (FONT_SLANT_NUMERIC (spec) < 0)
2373 mask_min &= ~kCTFontTraitItalic;
2374 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2375 mask_min &= ~kCTFontTraitBold;
2377 mask_max = (synth_sym_traits & ~sym_traits);
2378 /* Synthetic bold does not work for bitmap-only fonts on Mac
2380 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2382 CFNumberRef format =
2383 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2387 uint32_t format_val;
2389 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2391 && format_val == kCTFontFormatBitmap)
2392 mask_max &= ~kCTFontTraitBold;
2396 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2398 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2399 mmask <= (mask_max & kCTFontTraitMonoSpace);
2400 mmask += kCTFontTraitMonoSpace)
2401 for (bmask = (mask_min & kCTFontTraitBold);
2402 bmask <= (mask_max & kCTFontTraitBold);
2403 bmask += kCTFontTraitBold)
2404 for (imask = (mask_min & kCTFontTraitItalic);
2405 imask <= (mask_max & kCTFontTraitItalic);
2406 imask += kCTFontTraitItalic)
2408 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2411 || macfont_closest_traits_index_p (traits_array,
2412 (sym_traits | synth),
2415 entity = macfont_descriptor_entity (desc, extra, synth);
2416 if (! NILP (entity))
2417 val = Fcons (entity, val);
2422 CFRelease (traits_array);
2426 CFRelease (families);
2427 val = Fnreverse (val);
2433 FONT_ADD_LOG ("macfont-list", spec, val);
2434 if (charset) CFRelease (charset);
2435 if (languages) CFRelease (languages);
2436 if (attributes) CFRelease (attributes);
2437 if (family_name) CFRelease (family_name);
2445 macfont_match (struct frame * frame, Lisp_Object spec)
2447 Lisp_Object entity = Qnil;
2448 CFMutableDictionaryRef attributes;
2449 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2453 attributes = macfont_create_attributes_with_spec (spec);
2456 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2457 CFRelease (attributes);
2461 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2462 CFRelease (pat_desc);
2466 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2472 FONT_ADD_LOG ("macfont-match", spec, entity);
2477 macfont_list_family (struct frame *frame)
2479 Lisp_Object list = Qnil;
2480 CFArrayRef families;
2484 families = macfont_copy_available_families_cache ();
2487 CFIndex i, count = CFArrayGetCount (families);
2489 for (i = 0; i < count; i++)
2490 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2491 CFRelease (families);
2500 macfont_free_entity (Lisp_Object entity)
2502 Lisp_Object val = assq_no_quit (QCfont_entity,
2503 AREF (entity, FONT_EXTRA_INDEX));
2504 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2512 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2514 Lisp_Object val, font_object;
2515 CFStringRef font_name;
2516 struct macfont_info *macfont_info = NULL;
2520 CTFontSymbolicTraits sym_traits;
2522 int len, i, total_width;
2524 CGFloat ascent, descent, leading;
2526 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2528 || XTYPE (XCDR (val)) != Lisp_Misc
2529 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2531 font_name = XSAVE_POINTER (XCDR (val), 0);
2532 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2534 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2539 macfont = CTFontCreateWithName (font_name, size, NULL);
2542 int fontsize = (int) [((NSFont *) macfont) pointSize];
2543 if (fontsize != size) size = fontsize;
2549 font_object = font_build_object (VECSIZE (struct macfont_info),
2550 Qmac_ct, entity, size);
2551 font = XFONT_OBJECT (font_object);
2552 font->pixel_size = size;
2553 font->driver = &macfont_driver;
2554 font->encoding_charset = font->repertory_charset = -1;
2558 macfont_info = (struct macfont_info *) font;
2559 macfont_info->macfont = macfont;
2560 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2562 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2563 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2564 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2567 macfont_info->screen_font = NULL;
2568 macfont_info->cache = macfont_lookup_cache (font_name);
2569 macfont_retain_cache (macfont_info->cache);
2570 macfont_info->metrics = NULL;
2571 macfont_info->metrics_nrows = 0;
2572 macfont_info->synthetic_italic_p = 0;
2573 macfont_info->synthetic_bold_p = 0;
2574 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2575 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2576 if (!(sym_traits & kCTFontTraitItalic)
2577 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2578 macfont_info->synthetic_italic_p = 1;
2579 if (!(sym_traits & kCTFontTraitBold)
2580 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2581 macfont_info->synthetic_bold_p = 1;
2582 if (sym_traits & kCTFontTraitMonoSpace)
2583 macfont_info->spacing = MACFONT_SPACING_MONO;
2584 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2585 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2586 == FONT_SPACING_SYNTHETIC_MONO))
2587 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2588 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2589 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2592 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2594 macfont_info->antialias =
2595 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2597 macfont_info->color_bitmap_p = 0;
2598 if (sym_traits & kCTFontTraitColorGlyphs)
2599 macfont_info->color_bitmap_p = 1;
2601 glyph = macfont_get_glyph_for_character (font, ' ');
2602 if (glyph != kCGFontIndexInvalid)
2603 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2605 /* dirty workaround */
2606 font->space_width = pixel_size;
2608 total_width = font->space_width;
2609 for (i = 1; i < 95; i++)
2611 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2612 if (glyph == kCGFontIndexInvalid)
2614 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2617 font->average_width = total_width / 95;
2619 font->average_width = font->space_width; /* XXX */
2621 if (!(macfont_info->screen_font
2622 && mac_screen_font_get_metrics (macfont_info->screen_font,
2623 &ascent, &descent, &leading)))
2625 CFStringRef family_name;
2627 ascent = CTFontGetAscent (macfont);
2628 descent = CTFontGetDescent (macfont);
2629 leading = CTFontGetLeading (macfont);
2630 /* AppKit and WebKit do some adjustment to the heights of
2631 Courier, Helvetica, and Times. */
2632 family_name = CTFontCopyFamilyName (macfont);
2635 if (CFEqual (family_name, CFSTR ("Courier"))
2636 || CFEqual (family_name, CFSTR ("Helvetica"))
2637 || CFEqual (family_name, CFSTR ("Times")))
2638 ascent += (ascent + descent) * .15f;
2639 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2644 CFRelease (family_name);
2647 font->ascent = ascent + 0.5f;
2648 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2649 if (CONSP (val) && !NILP (XCDR (val)))
2650 font->descent = descent + 0.5f;
2652 font->descent = descent + leading + 0.5f;
2653 font->height = font->ascent + font->descent;
2655 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2656 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2660 /* Unfortunately Xft doesn't provide a way to get minimum char
2661 width. So, we use space_width instead. */
2662 font->min_width = font->max_width = font->space_width; /* XXX */
2664 font->baseline_offset = 0;
2665 font->relative_compose = 0;
2666 font->default_ascent = 0;
2667 font->vertical_centering = 0;
2673 macfont_close (struct font *font)
2675 struct macfont_info *macfont_info = (struct macfont_info *) font;
2677 if (macfont_info->cache)
2682 CFRelease (macfont_info->macfont);
2683 CGFontRelease (macfont_info->cgfont);
2684 if (macfont_info->screen_font)
2685 CFRelease (macfont_info->screen_font);
2686 macfont_release_cache (macfont_info->cache);
2687 for (i = 0; i < macfont_info->metrics_nrows; i++)
2688 if (macfont_info->metrics[i])
2689 xfree (macfont_info->metrics[i]);
2690 if (macfont_info->metrics)
2691 xfree (macfont_info->metrics);
2692 macfont_info->cache = NULL;
2698 macfont_has_char (Lisp_Object font, int c)
2701 CFCharacterSetRef charset;
2704 if (FONT_ENTITY_P (font))
2709 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2711 name = XSAVE_POINTER (val, 0);
2712 charset = macfont_get_cf_charset_for_name (name);
2715 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2717 result = CFCharacterSetIsLongCharacterMember (charset, c);
2724 macfont_encode_char (struct font *font, int c)
2726 struct macfont_info *macfont_info = (struct macfont_info *) font;
2730 glyph = macfont_get_glyph_for_character (font, c);
2733 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2737 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2738 struct font_metrics *metrics)
2743 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2744 for (i = 1; i < nglyphs; i++)
2746 struct font_metrics m;
2747 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2752 if (width + m.lbearing < metrics->lbearing)
2753 metrics->lbearing = width + m.lbearing;
2754 if (width + m.rbearing > metrics->rbearing)
2755 metrics->rbearing = width + m.rbearing;
2756 if (m.ascent > metrics->ascent)
2757 metrics->ascent = m.ascent;
2758 if (m.descent > metrics->descent)
2759 metrics->descent = m.descent;
2766 metrics->width = width;
2770 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2771 bool with_background)
2773 struct frame * f = s->f;
2774 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2775 CGRect background_rect;
2776 CGPoint text_position;
2779 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2780 bool no_antialias_p =
2781 (NILP (ns_antialias_text)
2782 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2783 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2784 && font_size <= macfont_antialias_threshold));
2785 int len = to - from;
2786 struct face *face = s->face;
2787 CGContextRef context;
2791 if (with_background)
2792 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2793 s->width, FONT_HEIGHT (s->font));
2795 background_rect = CGRectNull;
2797 text_position = CGPointMake (x, -y);
2798 glyphs = xmalloc (sizeof (CGGlyph) * len);
2800 CGFloat advance_delta = 0;
2802 CGFloat total_width = 0;
2804 positions = xmalloc (sizeof (CGPoint) * len);
2805 for (i = 0; i < len; i++)
2809 glyphs[i] = s->char2b[from + i];
2810 width = (s->padding_p ? 1
2811 : macfont_glyph_extents (s->font, glyphs[i],
2812 NULL, &advance_delta,
2814 positions[i].x = total_width + advance_delta;
2816 total_width += width;
2820 context = [[NSGraphicsContext currentContext] graphicsPort];
2821 CGContextSaveGState (context);
2823 if (!CGRectIsNull (background_rect))
2825 if (s->hl == DRAW_MOUSE_FACE)
2827 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2829 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2831 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2832 CGContextFillRects (context, &background_rect, 1);
2835 if (macfont_info->cgfont)
2837 CGAffineTransform atfm;
2839 CGContextScaleCTM (context, 1, -1);
2840 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2841 if (macfont_info->synthetic_italic_p)
2842 atfm = synthetic_italic_atfm;
2844 atfm = CGAffineTransformIdentity;
2845 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2847 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2848 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2849 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2852 CGContextSetShouldAntialias (context, false);
2854 CGContextSetTextMatrix (context, atfm);
2855 CGContextSetTextPosition (context, text_position.x, text_position.y);
2857 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2858 if (macfont_info->color_bitmap_p
2859 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2860 && CTFontDrawGlyphs != NULL
2866 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2871 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2873 CGContextSetFont (context, macfont_info->cgfont);
2874 CGContextSetFontSize (context, font_size);
2875 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2882 CGContextRestoreGState (context);
2890 macfont_shape (Lisp_Object lgstring)
2892 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2893 struct macfont_info *macfont_info = (struct macfont_info *) font;
2894 CTFontRef macfont = macfont_info->macfont;
2895 ptrdiff_t glyph_len, len, i, j;
2898 CFIndex *nonbmp_indices;
2901 struct mac_glyph_layout *glyph_layouts;
2903 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2905 for (i = 0; i < glyph_len; i++)
2907 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2911 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2917 if (INT_MAX / 2 < len)
2918 memory_full (SIZE_MAX);
2920 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2921 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2922 for (i = j = 0; i < len; i++)
2924 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2926 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2928 nonbmp_indices[j] = i + j;
2932 nonbmp_indices[j] = len + j; /* sentinel */
2936 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2940 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2941 if (macfont_info->screen_font)
2942 used = mac_screen_font_shape (macfont_info->screen_font, string,
2943 glyph_layouts, glyph_len);
2945 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2956 for (i = 0; i < used; i++)
2958 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2959 struct mac_glyph_layout *gl = glyph_layouts + i;
2961 struct font_metrics metrics;
2962 int xoff, yoff, wadjust;
2966 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2967 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2970 from = gl->comp_range.location;
2971 /* Convert UTF-16 index to UTF-32. */
2973 while (nonbmp_indices[j] < from)
2976 LGLYPH_SET_FROM (lglyph, from);
2978 to = gl->comp_range.location + gl->comp_range.length;
2979 /* Convert UTF-16 index to UTF-32. */
2980 while (nonbmp_indices[j] < to)
2983 LGLYPH_SET_TO (lglyph, to - 1);
2985 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2986 the composition is trivial. */
2990 if (unichars[gl->string_index] >= 0xD800
2991 && unichars[gl->string_index] < 0xDC00)
2992 c = (((unichars[gl->string_index] - 0xD800) << 10)
2993 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2995 c = unichars[gl->string_index];
2996 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2998 LGLYPH_SET_CHAR (lglyph, c);
3002 unsigned long cc = gl->glyph_id;
3003 LGLYPH_SET_CODE (lglyph, cc);
3006 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3007 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3008 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3009 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3010 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3011 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3013 xoff = lround (gl->advance_delta);
3014 yoff = lround (- gl->baseline_delta);
3015 wadjust = lround (gl->advance);
3016 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3020 vec = Fmake_vector (make_number (3), Qnil);
3021 ASET (vec, 0, make_number (xoff));
3022 ASET (vec, 1, make_number (yoff));
3023 ASET (vec, 2, make_number (wadjust));
3024 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3030 return make_number (used);
3033 /* Structures for the UVS subtable (format 14) in the cmap table. */
3034 typedef UInt8 UINT24[3];
3036 #pragma pack(push, 1)
3037 struct variation_selector_record
3039 UINT24 var_selector;
3040 UInt32 default_uvs_offset, non_default_uvs_offset;
3045 UInt32 length, num_var_selector_records;
3046 struct variation_selector_record variation_selector_records[1];
3048 #define SIZEOF_UVS_TABLE_HEADER \
3049 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3051 struct unicode_value_range
3053 UINT24 start_unicode_value;
3054 UInt8 additional_count;
3056 struct default_uvs_table {
3057 UInt32 num_unicode_value_ranges;
3058 struct unicode_value_range unicode_value_ranges[1];
3060 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3061 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3065 UINT24 unicode_value;
3068 struct non_default_uvs_table
3070 UInt32 num_uvs_mappings;
3071 struct uvs_mapping uvs_mappings[1];
3073 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3074 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3077 /* Read big endian values. The argument LVAL must be an lvalue. */
3078 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3079 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3080 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3081 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3082 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3083 /* Succeeding one byte should also be accessible. */
3084 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3085 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3087 /* Return UVS subtable for the specified FONT. If the subtable is not
3088 found or ill-formatted, then return NULL. */
3091 mac_font_copy_uvs_table (CTFontRef font)
3093 CFDataRef cmap_table, uvs_table = NULL;
3095 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3096 kCTFontTableOptionNoOptions);
3099 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3100 struct uvs_table *uvs;
3101 struct variation_selector_record *records;
3102 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3105 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3109 cmap_len = CFDataGetLength (cmap_table);
3110 if (sizeof_sfntCMapHeader > cmap_len)
3113 ntables = BUINT16_VALUE (cmap->numTables);
3114 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3115 / sizeof_sfntCMapEncoding))
3118 for (i = 0; i < ntables; i++)
3119 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3120 == kFontUnicodePlatform)
3121 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3122 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3124 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3128 || uvs_offset > cmap_len
3129 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3132 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3133 uvs_len = BUINT32_VALUE (uvs->length);
3134 if (uvs_len > cmap_len - uvs_offset
3135 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3138 if (BUINT16_VALUE (uvs->format) != 14)
3141 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3142 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3143 / sizeof (struct variation_selector_record)))
3146 records = uvs->variation_selector_records;
3147 for (i = 0; i < nrecords; i++)
3149 UInt32 default_uvs_offset, non_default_uvs_offset;
3151 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3152 if (default_uvs_offset)
3154 struct default_uvs_table *default_uvs;
3157 if (default_uvs_offset > uvs_len
3158 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3159 > uvs_len - default_uvs_offset))
3162 default_uvs = ((struct default_uvs_table *)
3163 ((UInt8 *) uvs + default_uvs_offset));
3164 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3165 if (nranges > ((uvs_len - default_uvs_offset
3166 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3167 / sizeof (struct unicode_value_range)))
3169 /* Now 2 * nranges can't overflow, so we can safely use
3170 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3171 mac_font_get_glyphs_for_variants. */
3174 non_default_uvs_offset =
3175 BUINT32_VALUE (records[i].non_default_uvs_offset);
3176 if (non_default_uvs_offset)
3178 struct non_default_uvs_table *non_default_uvs;
3181 if (non_default_uvs_offset > uvs_len
3182 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3183 > uvs_len - non_default_uvs_offset))
3186 non_default_uvs = ((struct non_default_uvs_table *)
3187 ((UInt8 *) uvs + non_default_uvs_offset));
3188 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3189 if (nmappings > ((uvs_len - non_default_uvs_offset
3190 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3191 / sizeof (struct uvs_mapping)))
3193 /* Now 2 * nmappings can't overflow, so we can safely
3194 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3195 in mac_font_get_glyphs_for_variants. */
3199 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3202 CFRelease (cmap_table);
3208 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3209 sequence consisting of the given base character C and each
3210 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3211 result (explained below) into the corresponding GLYPHS[i]. If the
3212 entry is found in the Default UVS Table, then the result is 0. If
3213 the entry is found in the Non-Default UVS Table, then the result is
3214 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3215 elements in SELECTORS must be sorted in strictly increasing
3219 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3220 const UTF32Char selectors[], CGGlyph glyphs[],
3223 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3224 struct variation_selector_record *records = uvs->variation_selector_records;
3226 UInt32 ir, nrecords;
3227 dispatch_queue_t queue =
3228 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3229 dispatch_group_t group = dispatch_group_create ();
3231 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3234 while (i < count && ir < nrecords)
3236 UInt32 default_uvs_offset, non_default_uvs_offset;
3238 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3240 glyphs[i++] = kCGFontIndexInvalid;
3243 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3249 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3250 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3251 non_default_uvs_offset =
3252 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3253 dispatch_group_async (group, queue, ^{
3254 glyphs[i] = kCGFontIndexInvalid;
3256 if (default_uvs_offset)
3258 struct default_uvs_table *default_uvs =
3259 (struct default_uvs_table *) ((UInt8 *) uvs
3260 + default_uvs_offset);
3261 struct unicode_value_range *ranges =
3262 default_uvs->unicode_value_ranges;
3266 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3269 UInt32 mid = (lo + hi) / 2;
3271 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3277 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3278 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3282 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3284 struct non_default_uvs_table *non_default_uvs =
3285 (struct non_default_uvs_table *) ((UInt8 *) uvs
3286 + non_default_uvs_offset);
3287 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3291 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3294 UInt32 mid = (lo + hi) / 2;
3296 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3302 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3303 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3310 glyphs[i++] = kCGFontIndexInvalid;
3311 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3312 dispatch_release (group);
3316 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3318 CFDataRef uvs_table;
3319 CTCharacterCollection uvs_collection;
3323 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3327 UTF32Char selectors[256];
3328 CGGlyph glyphs[256];
3330 for (i = 0; i < 16; i++)
3331 selectors[i] = 0xFE00 + i;
3332 for (; i < 256; i++)
3333 selectors[i] = 0xE0100 + (i - 16);
3334 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3335 for (i = 0; i < 256; i++)
3337 CGGlyph glyph = glyphs[i];
3339 if (uvs_collection != kCTCharacterCollectionIdentityMapping
3340 && glyph != kCGFontIndexInvalid)
3341 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3342 if (glyph == kCGFontIndexInvalid)
3346 variations[i] = (glyph ? glyph
3347 : macfont_get_glyph_for_character (font, c));
3357 static const char *const macfont_booleans[] = {
3363 static const char *const macfont_non_booleans[] = {
3371 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3373 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3377 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3378 CFArrayRef languages)
3380 Boolean result = true;
3381 CFArrayRef desc_languages =
3382 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3384 if (desc_languages == NULL)
3388 CFIndex desc_languages_count, i, languages_count;
3390 desc_languages_count = CFArrayGetCount (desc_languages);
3391 languages_count = CFArrayGetCount (languages);
3392 for (i = 0; i < languages_count; i++)
3393 if (!CFArrayContainsValue (desc_languages,
3394 CFRangeMake (0, desc_languages_count),
3395 CFArrayGetValueAtIndex (languages, i)))
3400 CFRelease (desc_languages);
3407 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3409 CFStringRef result = NULL;
3410 CFStringRef charset_string =
3411 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3413 if (charset_string && CFStringGetLength (charset_string) > 0)
3415 CFStringRef keys[] = {
3416 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3417 kCTLanguageAttributeName
3419 CFSTR ("NSLanguage")
3422 CFTypeRef values[] = {NULL};
3423 CFIndex num_values = 0;
3424 CFArrayRef languages
3425 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3427 if (languages && CFArrayGetCount (languages) > 0)
3429 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3430 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3433 CFCharacterSetRef charset =
3434 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3436 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3441 CFAttributedStringRef attr_string = NULL;
3442 CTLineRef ctline = NULL;
3443 CFDictionaryRef attrs
3444 = CFDictionaryCreate (NULL, (const void **) keys,
3445 (const void **) values, num_values,
3446 &kCFTypeDictionaryKeyCallBacks,
3447 &kCFTypeDictionaryValueCallBacks);
3451 attr_string = CFAttributedStringCreate (NULL, charset_string,
3457 ctline = CTLineCreateWithAttributedString (attr_string);
3458 CFRelease (attr_string);
3462 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3463 CFIndex i, nruns = CFArrayGetCount (runs);
3466 for (i = 0; i < nruns; i++)
3468 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3469 CFDictionaryRef attributes = CTRunGetAttributes (run);
3470 CTFontRef font_in_run;
3472 if (attributes == NULL)
3475 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3476 if (font_in_run == NULL)
3480 else if (!mac_font_equal_in_postscript_name (font,
3484 if (nruns > 0 && i == nruns)
3485 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3494 static inline double
3495 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3497 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3501 static inline CGRect
3502 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3504 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3509 mac_font_create_available_families (void)
3511 CFMutableArrayRef families = NULL;
3512 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3516 CFIndex i, count = CFArrayGetCount (orig_families);
3518 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3520 for (i = 0; i < count; i++)
3522 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3524 if (!CFStringHasPrefix (family, CFSTR ("."))
3525 && (CTFontManagerCompareFontFamilyNames (family,
3526 CFSTR ("LastResort"),
3528 != kCFCompareEqualTo))
3529 CFArrayAppendValue (families, family);
3531 CFRelease (orig_families);
3538 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3541 CFStringRef name1, name2;
3547 name1 = CTFontCopyPostScriptName (font1);
3550 name2 = CTFontCopyPostScriptName (font2);
3553 result = CFEqual (name1, name2);
3563 mac_font_create_line_with_string_and_font (CFStringRef string,
3566 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3567 CFTypeRef values[] = {NULL, NULL};
3568 CFDictionaryRef attributes = NULL;
3569 CFAttributedStringRef attr_string = NULL;
3570 CTLineRef ctline = NULL;
3571 float float_zero = 0.0f;
3573 values[0] = macfont;
3574 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3577 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3578 (const void **) values,
3580 &kCFTypeDictionaryKeyCallBacks,
3581 &kCFTypeDictionaryValueCallBacks);
3582 CFRelease (values[1]);
3586 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3587 CFRelease (attributes);
3591 ctline = CTLineCreateWithAttributedString (attr_string);
3592 CFRelease (attr_string);
3596 /* Abandon if ctline contains some fonts other than the
3598 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3599 CFIndex i, nruns = CFArrayGetCount (runs);
3601 for (i = 0; i < nruns; i++)
3603 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3604 CFDictionaryRef attributes = CTRunGetAttributes (run);
3605 CTFontRef font_in_run;
3607 if (attributes == NULL)
3610 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3611 if (font_in_run == NULL)
3613 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3627 mac_font_shape (CTFontRef font, CFStringRef string,
3628 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3630 CFIndex used, result = 0;
3631 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3636 used = CTLineGetGlyphCount (ctline);
3637 if (used <= glyph_len)
3639 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3640 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3641 CGFloat total_advance = 0;
3642 CFIndex total_glyph_count = 0;
3644 for (k = 0; k < ctrun_count; k++)
3646 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3647 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3648 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3649 CFRange string_range, comp_range, range;
3650 CFIndex *permutation;
3652 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3653 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3657 #define RIGHT_TO_LEFT_P permutation
3659 /* Now the `comp_range' member of struct mac_glyph_layout is
3660 temporarily used as a work area such that:
3661 glbuf[i].comp_range.location =
3662 min {compRange[i + 1].location, ...,
3663 compRange[glyph_count - 1].location,
3664 maxRange (stringRangeForCTRun)}
3665 glbuf[i].comp_range.length = maxRange (compRange[i])
3666 where compRange[i] is the range of composed characters
3667 containing i-th glyph. */
3668 string_range = CTRunGetStringRange (ctrun);
3669 min_location = string_range.location + string_range.length;
3670 for (i = 0; i < glyph_count; i++)
3672 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3673 CFIndex glyph_index;
3676 if (!RIGHT_TO_LEFT_P)
3677 glyph_index = glyph_count - i - 1;
3680 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3683 CFStringGetRangeOfComposedCharactersAtIndex (string,
3685 gl->comp_range.location = min_location;
3686 gl->comp_range.length = rng.location + rng.length;
3687 if (rng.location < min_location)
3688 min_location = rng.location;
3691 /* Fill the `comp_range' member of struct mac_glyph_layout,
3692 and setup a permutation for right-to-left text. */
3693 comp_range = CFRangeMake (string_range.location, 0);
3694 range = CFRangeMake (0, 0);
3697 struct mac_glyph_layout *gl =
3698 glbuf + range.location + range.length;
3700 if (gl->comp_range.length
3701 > comp_range.location + comp_range.length)
3702 comp_range.length = gl->comp_range.length - comp_range.location;
3703 min_location = gl->comp_range.location;
3706 if (min_location >= comp_range.location + comp_range.length)
3708 comp_range.length = min_location - comp_range.location;
3709 for (i = 0; i < range.length; i++)
3711 glbuf[range.location + i].comp_range = comp_range;
3712 if (RIGHT_TO_LEFT_P)
3713 permutation[range.location + i] =
3714 range.location + range.length - i - 1;
3717 comp_range = CFRangeMake (min_location, 0);
3718 range.location += range.length;
3720 if (range.location == glyph_count)
3725 /* Then fill the remaining members. */
3726 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3729 struct mac_glyph_layout *gl;
3732 if (!RIGHT_TO_LEFT_P)
3733 gl = glbuf + range.location;
3738 src = glyph_count - 1 - range.location;
3739 dest = permutation[src];
3743 CFIndex tmp = gl->string_index;
3745 gl->string_index = glbuf[src].string_index;
3746 glbuf[src].string_index = tmp;
3749 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3751 CTRunGetPositions (ctrun, range, &position);
3752 gl->advance_delta = position.x - total_advance;
3753 gl->baseline_delta = position.y;
3754 gl->advance = (gl->advance_delta
3755 + CTRunGetTypographicBounds (ctrun, range,
3757 total_advance += gl->advance;
3760 if (RIGHT_TO_LEFT_P)
3761 xfree (permutation);
3763 #undef RIGHT_TO_LEFT_P
3765 total_glyph_count += glyph_count;
3775 /* The function below seems to cause a memory leak for the CFString
3776 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3777 10.6.3. For now, we use the NSGlyphInfo version instead. */
3778 #if USE_CT_GLYPH_INFO
3780 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3783 CGGlyph result = kCGFontIndexInvalid;
3784 UniChar characters[] = {0xfffd};
3786 CFAttributedStringRef attr_string = NULL;
3787 CTLineRef ctline = NULL;
3789 string = CFStringCreateWithCharacters (NULL, characters,
3790 ARRAYELTS (characters));
3794 CTGlyphInfoRef glyph_info =
3795 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3796 CFDictionaryRef attributes = NULL;
3800 CFStringRef keys[] = {kCTFontAttributeName,
3801 kCTGlyphInfoAttributeName};
3802 CFTypeRef values[] = {font, glyph_info};
3804 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3805 (const void **) values,
3807 &kCFTypeDictionaryKeyCallBacks,
3808 &kCFTypeDictionaryValueCallBacks);
3809 CFRelease (glyph_info);
3813 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3814 CFRelease (attributes);
3820 ctline = CTLineCreateWithAttributedString (attr_string);
3821 CFRelease (attr_string);
3825 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3827 if (CFArrayGetCount (runs) > 0)
3829 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3830 CFDictionaryRef attributes = CTRunGetAttributes (run);
3834 CTFontRef font_in_run =
3835 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3838 && mac_font_equal_in_postscript_name (font_in_run, font))
3840 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3841 if (result >= CTFontGetGlyphCount (font))
3842 result = kCGFontIndexInvalid;
3854 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3856 CFArrayRef result = NULL;
3858 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3859 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3860 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3863 CTFontRef user_font =
3864 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3868 CFArrayRef languages =
3869 CFArrayCreate (NULL, (const void **) &language, 1,
3870 &kCFTypeArrayCallBacks);
3874 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3876 CFRelease (languages);
3878 CFRelease (user_font);
3881 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3882 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3884 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3885 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3889 for (i = 0; macfont_language_default_font_names[i].language; i++)
3891 if (CFEqual (macfont_language_default_font_names[i].language,
3894 CFMutableArrayRef descriptors =
3895 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3902 macfont_language_default_font_names[i].font_names[j];
3905 CFDictionaryRef attributes =
3906 CFDictionaryCreate (NULL,
3908 &kCTFontNameAttribute),
3910 &macfont_language_default_font_names[i].font_names[j]),
3911 1, &kCFTypeDictionaryKeyCallBacks,
3912 &kCFTypeDictionaryValueCallBacks);
3916 CTFontDescriptorRef pat_desc =
3917 CTFontDescriptorCreateWithAttributes (attributes);
3921 CTFontDescriptorRef descriptor =
3922 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3926 CFArrayAppendValue (descriptors, descriptor);
3927 CFRelease (descriptor);
3929 CFRelease (pat_desc);
3931 CFRelease (attributes);
3934 result = descriptors;
3946 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3947 CFArrayRef languages)
3949 CFStringRef result = NULL;
3950 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3951 CFArrayRef descriptors =
3952 mac_font_copy_default_descriptors_for_language (language);
3956 CFIndex i, count = CFArrayGetCount (descriptors);
3958 for (i = 0; i < count; i++)
3960 CTFontDescriptorRef descriptor =
3961 CFArrayGetValueAtIndex (descriptors, i);
3963 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3966 CFStringRef family =
3967 CTFontDescriptorCopyAttribute (descriptor,
3968 kCTFontFamilyNameAttribute);
3971 if (!CFStringHasPrefix (family, CFSTR ("."))
3972 && !CFEqual (family, CFSTR ("LastResort")))
3982 CFRelease (descriptors);
3989 macfont_get_nsctfont (struct font *font)
3991 struct macfont_info *macfont_info = (struct macfont_info *) font;
3992 CTFontRef macfont = macfont_info->macfont;
3994 return (void *) macfont;
3998 mac_register_font_driver (struct frame *f)
4000 register_font_driver (&macfont_driver, f);
4005 syms_of_macfont (void)
4007 static struct font_driver mac_font_driver;
4009 /* Core Text, for Mac OS X. */
4010 DEFSYM (Qmac_ct, "mac-ct");
4011 macfont_driver.type = Qmac_ct;
4012 register_font_driver (&macfont_driver, NULL);
4014 /* The font property key specifying the font design destination. The
4015 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4016 text. (See the documentation of X Logical Font Description
4017 Conventions.) In the Mac font driver, 1 means the screen font is
4018 used for calculating some glyph metrics. You can see the
4019 difference with Monaco 8pt or 9pt, for example. */
4020 DEFSYM (QCdestination, ":destination");
4022 /* The boolean-valued font property key specifying the use of leading. */
4023 DEFSYM (QCminspace, ":minspace");
4025 macfont_family_cache = Qnil;
4026 staticpro (&macfont_family_cache);