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))
948 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
950 h = XHASH_TABLE (macfont_family_cache);
951 i = hash_lookup (h, symbol, &hash);
952 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
955 Lisp_Object old_value = HASH_VALUE (h, i);
957 if (SAVE_VALUEP (old_value))
958 CFRelease (XSAVE_POINTER (old_value, 0));
959 set_hash_value_slot (h, i, value);
962 hash_put (h, symbol, value, hash);
965 /* Cache of all the available font family names except "LastResort"
966 and those start with ".". NULL means the cache has been invalidated.
967 Otherwise, the value is CFArray of CFStrings and the elements are
968 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
969 OS X 10.6 and later). */
971 static CFArrayRef macfont_available_families_cache = NULL;
974 macfont_invalidate_available_families_cache (void)
976 if (macfont_available_families_cache)
978 CFRelease (macfont_available_families_cache);
979 macfont_available_families_cache = NULL;
984 macfont_handle_font_change_notification (CFNotificationCenterRef center,
986 CFStringRef name, const void *object,
987 CFDictionaryRef userInfo)
989 macfont_invalidate_family_cache ();
990 macfont_invalidate_available_families_cache ();
994 macfont_init_font_change_handler (void)
996 static bool initialized = false;
1002 CFNotificationCenterAddObserver
1003 (CFNotificationCenterGetLocalCenter (), NULL,
1004 macfont_handle_font_change_notification,
1005 kCTFontManagerRegisteredFontsChangedNotification,
1006 NULL, CFNotificationSuspensionBehaviorCoalesce);
1010 macfont_copy_available_families_cache (void)
1012 macfont_init_font_change_handler ();
1014 if (macfont_available_families_cache == NULL)
1015 macfont_available_families_cache = mac_font_create_available_families ();
1017 return (macfont_available_families_cache
1018 ? CFRetain (macfont_available_families_cache) : NULL);
1022 macfont_create_family_with_symbol (Lisp_Object symbol)
1024 CFStringRef result = NULL, family_name;
1025 CFDictionaryRef attributes = NULL;
1026 CTFontDescriptorRef pat_desc = NULL;
1028 if (macfont_get_family_cache_if_present (symbol, &result))
1029 return result ? CFRetain (result) : NULL;
1031 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1035 CFDictionaryCreate (NULL,
1036 (const void **) &kCTFontFamilyNameAttribute,
1037 (const void **) &family_name, 1,
1038 &kCFTypeDictionaryKeyCallBacks,
1039 &kCFTypeDictionaryValueCallBacks);
1040 CFRelease (family_name);
1044 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1045 CFRelease (attributes);
1049 CTFontDescriptorRef desc =
1050 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1055 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1058 macfont_set_family_cache (symbol, result);
1059 CFRelease (pat_desc);
1065 #define WIDTH_FRAC_BITS (4)
1066 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1068 struct macfont_metrics
1070 unsigned char lbearing_low, rbearing_low;
1071 signed lbearing_high : 4, rbearing_high : 4;
1072 unsigned char ascent_low, descent_low;
1073 signed ascent_high : 4, descent_high : 4;
1075 /* These two members are used for fixed-point representation of
1076 glyph width. The `width_int' member is an integer that is
1077 closest to the width. The `width_frac' member is the fractional
1078 adjustment representing a value in [-.5, .5], multiplied by
1079 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1080 the advance delta for centering instead of the glyph width. */
1081 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1084 #define METRICS_VALUE(metrics, member) \
1085 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1086 #define METRICS_SET_VALUE(metrics, member, value) \
1087 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1088 (metrics)->member##_high = tmp >> 8;} while (0)
1092 METRICS_INVALID = -1, /* metrics entry is invalid */
1093 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1096 #define METRICS_STATUS(metrics) \
1097 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1098 #define METRICS_SET_STATUS(metrics, status) \
1099 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1100 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1102 #define METRICS_NCOLS_PER_ROW (128)
1103 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1104 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1107 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1108 struct font_metrics *metrics, CGFloat *advance_delta,
1109 int force_integral_p)
1111 struct macfont_info *macfont_info = (struct macfont_info *) font;
1112 CTFontRef macfont = macfont_info->macfont;
1114 struct macfont_metrics *cache;
1117 row = glyph / METRICS_NCOLS_PER_ROW;
1118 col = glyph % METRICS_NCOLS_PER_ROW;
1119 if (row >= macfont_info->metrics_nrows)
1121 macfont_info->metrics =
1122 xrealloc (macfont_info->metrics,
1123 sizeof (struct macfont_metrics *) * (row + 1));
1124 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1125 (sizeof (struct macfont_metrics *)
1126 * (row + 1 - macfont_info->metrics_nrows)));
1127 macfont_info->metrics_nrows = row + 1;
1129 if (macfont_info->metrics[row] == NULL)
1131 struct macfont_metrics *new;
1134 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1135 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1136 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1137 macfont_info->metrics[row] = new;
1139 cache = macfont_info->metrics[row] + col;
1141 if (METRICS_STATUS (cache) == METRICS_INVALID)
1145 if (macfont_info->screen_font)
1146 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1148 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1150 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1151 advance delta value. */
1152 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1153 fwidth = (font->pixel_size - fwidth) / 2;
1154 cache->width_int = lround (fwidth);
1155 cache->width_frac = lround ((fwidth - cache->width_int)
1156 * WIDTH_FRAC_SCALE);
1157 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1159 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1160 width = font->pixel_size;
1162 width = cache->width_int;
1166 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1168 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1170 if (macfont_info->synthetic_italic_p)
1172 /* We assume the members a, b, c, and d in
1173 synthetic_italic_atfm are non-negative. */
1175 CGPointApplyAffineTransform (bounds.origin,
1176 synthetic_italic_atfm);
1178 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1180 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1182 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1184 bounds = CGRectInset (bounds, d, d);
1186 switch (macfont_info->spacing)
1188 case MACFONT_SPACING_PROPORTIONAL:
1189 bounds.origin.x += - (cache->width_frac
1190 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1192 case MACFONT_SPACING_MONO:
1194 case MACFONT_SPACING_SYNTHETIC_MONO:
1195 bounds.origin.x += (cache->width_int
1196 + (cache->width_frac
1197 / (CGFloat) WIDTH_FRAC_SCALE));
1200 if (bounds.size.width > 0)
1202 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1203 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1204 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1206 bounds = CGRectIntegral (bounds);
1207 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1208 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1209 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1210 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1212 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1213 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1214 metrics->width = width;
1215 metrics->ascent = METRICS_VALUE (cache, ascent);
1216 metrics->descent = METRICS_VALUE (cache, descent);
1221 switch (macfont_info->spacing)
1223 case MACFONT_SPACING_PROPORTIONAL:
1224 *advance_delta = (force_integral_p ? 0
1225 : - (cache->width_frac
1226 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1228 case MACFONT_SPACING_MONO:
1231 case MACFONT_SPACING_SYNTHETIC_MONO:
1232 *advance_delta = (force_integral_p ? cache->width_int
1234 + (cache->width_frac
1235 / (CGFloat) WIDTH_FRAC_SCALE)));
1243 static CFMutableDictionaryRef macfont_cache_dictionary;
1245 /* Threshold used in row_nkeys_or_perm. This must be less than or
1246 equal to the number of rows that are invalid as BMP (i.e., from
1247 U+D800 to U+DFFF). */
1248 #define ROW_PERM_OFFSET (8)
1250 /* The number of glyphs that can be stored in a value for a single
1251 entry of CFDictionary. */
1252 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1254 struct macfont_cache
1256 int reference_count;
1257 CFCharacterSetRef cf_charset;
1259 /* The cached glyph for a BMP character c is stored in
1260 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1261 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1262 unsigned char row_nkeys_or_perm[256];
1265 /* Number of rows for which the BMP cache is allocated so far.
1266 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1269 /* The cached glyph for a character c is stored as the (c %
1270 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1271 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1272 not stored here if row_nkeys_or_perm[c / 256] >=
1274 CFMutableDictionaryRef dictionary;
1278 /* UVS (Unicode Variation Sequence) subtable data, which is of
1279 type CFDataRef if available. NULL means it is not initialized
1280 yet. kCFNull means the subtable is not found and there is no
1281 suitable fallback table for this font. */
1284 /* Character collection specifying the destination of the mapping
1285 provided by `table' above. If `table' is obtained from the UVS
1286 subtable in the font cmap table, then the value of this member
1287 should be kCTCharacterCollectionIdentityMapping. */
1288 CTCharacterCollection collection;
1292 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1293 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1294 static void macfont_release_cache (struct macfont_cache *);
1295 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1296 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1297 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1298 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1299 CTCharacterCollection, CGFontIndex);
1300 static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
1302 static struct macfont_cache *
1303 macfont_lookup_cache (CFStringRef key)
1305 struct macfont_cache *cache;
1307 if (macfont_cache_dictionary == NULL)
1309 macfont_cache_dictionary =
1310 CFDictionaryCreateMutable (NULL, 0,
1311 &kCFTypeDictionaryKeyCallBacks, NULL);
1315 cache = ((struct macfont_cache *)
1316 CFDictionaryGetValue (macfont_cache_dictionary, key));
1320 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1324 cache = xzalloc (sizeof (struct macfont_cache));
1325 /* Treat the LastResort font as if it contained glyphs for
1326 all characters. This may look too rough, but neither
1327 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1328 for this font is correct for non-BMP characters on Mac OS
1330 if (CFEqual (key, CFSTR ("LastResort")))
1332 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1335 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1337 if (cache->cf_charset == NULL)
1338 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1339 CFDictionaryAddValue (macfont_cache_dictionary, key,
1340 (const void *) cache);
1341 CFRelease (macfont);
1348 static struct macfont_cache *
1349 macfont_retain_cache (struct macfont_cache *cache)
1351 cache->reference_count++;
1357 macfont_release_cache (struct macfont_cache *cache)
1359 if (--cache->reference_count == 0)
1363 for (i = 0; i < cache->glyph.nrows; i++)
1364 xfree (cache->glyph.matrix[i]);
1365 xfree (cache->glyph.matrix);
1366 if (cache->glyph.dictionary)
1367 CFRelease (cache->glyph.dictionary);
1368 memset (&cache->glyph, 0, sizeof (cache->glyph));
1369 if (cache->uvs.table)
1370 CFRelease (cache->uvs.table);
1371 memset (&cache->uvs, 0, sizeof (cache->uvs));
1375 static CFCharacterSetRef
1376 macfont_get_cf_charset (struct font *font)
1378 struct macfont_info *macfont_info = (struct macfont_info *) font;
1380 return macfont_info->cache->cf_charset;
1383 static CFCharacterSetRef
1384 macfont_get_cf_charset_for_name (CFStringRef name)
1386 struct macfont_cache *cache = macfont_lookup_cache (name);
1388 return cache->cf_charset;
1392 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1394 struct macfont_info *macfont_info = (struct macfont_info *) font;
1395 CTFontRef macfont = macfont_info->macfont;
1396 struct macfont_cache *cache = macfont_info->cache;
1398 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1401 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1403 if (nkeys_or_perm < ROW_PERM_OFFSET)
1405 UniChar unichars[256], ch;
1409 dispatch_queue_t queue;
1410 dispatch_group_t group = NULL;
1414 CFMutableDictionaryRef dictionary;
1415 uintptr_t key, value;
1419 if (cache->glyph.dictionary == NULL)
1420 cache->glyph.dictionary =
1421 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1422 dictionary = cache->glyph.dictionary;
1423 key = c / NGLYPHS_IN_VALUE;
1424 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1425 value = ((uintptr_t)
1426 CFDictionaryGetValue (dictionary, (const void *) key));
1427 glyph = (value >> nshifts);
1431 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1434 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1436 glyph = kCGFontIndexInvalid;
1439 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1440 value |= ((uintptr_t) glyph << nshifts);
1441 CFDictionarySetValue (dictionary, (const void *) key,
1442 (const void *) value);
1448 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1449 group = dispatch_group_create ();
1450 dispatch_group_async (group, queue, ^{
1453 nkeys = nkeys_or_perm;
1454 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1455 if (CFDictionaryContainsKey (dictionary,
1456 (const void *) key))
1458 CFDictionaryRemoveValue (dictionary,
1459 (const void *) key);
1467 for (i = 0; i < 256; i++)
1470 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1471 unichars[len++] = ch;
1474 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1477 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1480 int next = unichars[len - 1] % 256;
1483 glyphs[i] = kCGFontIndexInvalid;
1486 glyphs[i] = glyphs[len];
1493 glyphs[i] = kCGFontIndexInvalid;
1495 nrows = cache->glyph.nrows;
1496 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1497 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1499 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1500 sizeof (CGGlyph *) * nrows);
1501 cache->glyph.matrix[nrows - 1] = glyphs;
1502 cache->glyph.nrows = nrows;
1506 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1507 dispatch_release (group);
1511 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1515 uintptr_t key, value;
1519 if (cache->glyph.dictionary == NULL)
1520 cache->glyph.dictionary =
1521 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1522 key = c / NGLYPHS_IN_VALUE;
1523 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1524 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1525 (const void *) key);
1526 glyph = (value >> nshifts);
1529 UniChar unichars[2];
1531 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1533 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1536 glyph = kCGFontIndexInvalid;
1538 value |= ((uintptr_t) glyph << nshifts);
1539 CFDictionarySetValue (cache->glyph.dictionary,
1540 (const void *) key, (const void *) value);
1548 macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1551 struct macfont_info *macfont_info = (struct macfont_info *) font;
1552 CTFontRef macfont = macfont_info->macfont;
1555 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1559 macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1561 struct macfont_info *macfont_info = (struct macfont_info *) font;
1562 CTFontRef macfont = macfont_info->macfont;
1563 struct macfont_cache *cache = macfont_info->cache;
1564 CFDataRef result = NULL;
1566 if (cache->uvs.table == NULL)
1568 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1569 CTCharacterCollection uvs_collection =
1570 kCTCharacterCollectionIdentityMapping;
1572 if (uvs_table == NULL
1573 && mac_font_get_glyph_for_cid (macfont,
1574 kCTCharacterCollectionAdobeJapan1,
1575 6480) != kCGFontIndexInvalid)
1577 /* If the glyph for U+4E55 is accessible via its CID 6480,
1578 then we use the Adobe-Japan1 UVS table, which maps a
1579 variation sequence to a CID, as a fallback. */
1580 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1582 if (mac_uvs_table_adobe_japan1 == NULL)
1583 mac_uvs_table_adobe_japan1 =
1584 CFDataCreateWithBytesNoCopy (NULL,
1585 mac_uvs_table_adobe_japan1_bytes,
1586 sizeof (mac_uvs_table_adobe_japan1_bytes),
1588 if (mac_uvs_table_adobe_japan1)
1590 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1591 uvs_collection = kCTCharacterCollectionAdobeJapan1;
1594 if (uvs_table == NULL)
1595 cache->uvs.table = kCFNull;
1597 cache->uvs.table = uvs_table;
1598 cache->uvs.collection = uvs_collection;
1601 if (cache->uvs.table != kCFNull)
1603 result = cache->uvs.table;
1604 *collection = cache->uvs.collection;
1610 static Lisp_Object macfont_get_cache (struct frame *);
1611 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1612 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1613 static Lisp_Object macfont_list_family (struct frame *);
1614 static void macfont_free_entity (Lisp_Object);
1615 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1616 static void macfont_close (struct font *);
1617 static int macfont_has_char (Lisp_Object, int);
1618 static unsigned macfont_encode_char (struct font *, int);
1619 static void macfont_text_extents (struct font *, unsigned int *, int,
1620 struct font_metrics *);
1621 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1622 static Lisp_Object macfont_shape (Lisp_Object);
1623 static int macfont_variation_glyphs (struct font *, int c,
1624 unsigned variations[256]);
1625 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1627 static struct font_driver macfont_driver =
1629 LISP_INITIALLY_ZERO, /* Qmac_ct */
1630 0, /* case insensitive */
1634 macfont_list_family,
1635 macfont_free_entity,
1638 NULL, /* prepare_face */
1639 NULL, /* done_face */
1641 macfont_encode_char,
1642 macfont_text_extents,
1644 NULL, /* get_bitmap */
1645 NULL, /* free_bitmap */
1646 NULL, /* anchor_point */
1647 NULL, /* otf_capability */
1648 NULL, /* otf_drive */
1649 NULL, /* start_for_frame */
1650 NULL, /* end_for_frame */
1653 macfont_variation_glyphs,
1654 macfont_filter_properties,
1658 macfont_get_cache (struct frame * f)
1660 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1662 return (dpyinfo->name_list_element);
1666 macfont_get_charset (Lisp_Object registry)
1668 char *str = SSDATA (SYMBOL_NAME (registry));
1669 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1673 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1677 else if (str[i] == '*')
1684 regexp = make_unibyte_string (re, j);
1685 for (i = 0; cf_charset_table[i].name; i++)
1686 if (fast_c_string_match_ignore_case
1687 (regexp, cf_charset_table[i].name,
1688 strlen (cf_charset_table[i].name)) >= 0)
1690 if (! cf_charset_table[i].name)
1692 if (! cf_charset_table[i].cf_charset)
1694 int *uniquifier = cf_charset_table[i].uniquifier;
1695 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1698 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1702 for (j = 0; uniquifier[j]; j++)
1704 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1706 CFCharacterSetAddCharactersInRange (charset,
1707 CFRangeMake (uniquifier[j], 1));
1710 string = CFStringCreateWithCharacters (NULL, unichars, count);
1713 CFRelease (charset);
1716 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1718 CFRelease (charset);
1719 /* CFCharacterSetCreateWithCharactersInString does not handle
1720 surrogate pairs properly as of Mac OS X 10.5. */
1721 cf_charset_table[i].cf_charset_string = string;
1729 unsigned int script_tag, langsys_tag;
1731 unsigned int *features[2];
1734 #define OTF_SYM_TAG(SYM, TAG) \
1736 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1737 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1740 #define OTF_TAG_STR(TAG, P) \
1742 (P)[0] = (char) (TAG >> 24); \
1743 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1744 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1745 (P)[3] = (char) (TAG & 0xFF); \
1749 static struct OpenTypeSpec *
1750 macfont_get_open_type_spec (Lisp_Object otf_spec)
1752 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1759 spec->script = XCAR (otf_spec);
1760 if (! NILP (spec->script))
1762 OTF_SYM_TAG (spec->script, spec->script_tag);
1763 val = assq_no_quit (spec->script, Votf_script_alist);
1764 if (CONSP (val) && SYMBOLP (XCDR (val)))
1765 spec->script = XCDR (val);
1767 spec->script = Qnil;
1770 spec->script_tag = 0x44464C54; /* "DFLT" */
1771 otf_spec = XCDR (otf_spec);
1772 spec->langsys_tag = 0;
1773 if (! NILP (otf_spec))
1775 val = XCAR (otf_spec);
1777 OTF_SYM_TAG (val, spec->langsys_tag);
1778 otf_spec = XCDR (otf_spec);
1780 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1781 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1785 val = XCAR (otf_spec);
1788 len = Flength (val);
1790 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1792 : malloc (XINT (len) * sizeof *spec->features[i]));
1793 if (! spec->features[i])
1795 if (i > 0 && spec->features[0])
1796 free (spec->features[0]);
1800 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1802 if (NILP (XCAR (val)))
1808 OTF_SYM_TAG (XCAR (val), tag);
1809 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1812 spec->nfeatures[i] = j;
1817 static CFMutableDictionaryRef
1818 macfont_create_attributes_with_spec (Lisp_Object spec)
1820 Lisp_Object tmp, extra;
1821 CFMutableArrayRef langarray = NULL;
1822 CFCharacterSetRef charset = NULL;
1823 CFStringRef charset_string = NULL;
1824 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1825 Lisp_Object script = Qnil;
1826 Lisp_Object registry;
1827 int cf_charset_idx, i;
1828 struct OpenTypeSpec *otspec = NULL;
1830 enum font_property_index index;
1833 } numeric_traits[] =
1834 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1835 {{-0.4, 50}, /* light */
1836 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1837 {0, 100}, /* normal */
1838 {0.24, 140}, /* (semi-bold + normal) / 2 */
1839 {0.4, 200}, /* bold */
1840 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1841 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1842 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1843 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1844 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1846 registry = AREF (spec, FONT_REGISTRY_INDEX);
1848 || EQ (registry, Qascii_0)
1849 || EQ (registry, Qiso10646_1)
1850 || EQ (registry, Qunicode_bmp))
1851 cf_charset_idx = -1;
1856 cf_charset_idx = macfont_get_charset (registry);
1857 if (cf_charset_idx < 0)
1859 charset = cf_charset_table[cf_charset_idx].cf_charset;
1860 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1861 lang = cf_charset_table[cf_charset_idx].lang;
1864 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1867 CFArrayAppendValue (langarray, lang);
1871 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1872 CONSP (extra); extra = XCDR (extra))
1874 Lisp_Object key, val;
1877 key = XCAR (tmp), val = XCDR (tmp);
1878 if (EQ (key, QClang))
1881 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1886 for (; CONSP (val); val = XCDR (val))
1887 if (SYMBOLP (XCAR (val)))
1890 cfstring_create_with_string_noencode (SYMBOL_NAME
1895 CFArrayAppendValue (langarray, lang);
1899 else if (EQ (key, QCotf))
1901 otspec = macfont_get_open_type_spec (val);
1904 script = otspec->script;
1906 else if (EQ (key, QCscript))
1910 if (! NILP (script) && ! charset)
1912 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1914 if (CONSP (chars) && CONSP (CDR (chars)))
1916 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1917 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1919 if (! string || !cs)
1927 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1928 if (CHARACTERP (XCAR (chars)))
1930 UniChar unichars[2];
1932 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1934 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1936 CFStringAppendCharacters (string, unichars, count);
1937 CFCharacterSetAddCharactersInRange (cs, range);
1940 /* CFCharacterSetCreateWithCharactersInString does not
1941 handle surrogate pairs properly as of Mac OS X 10.5. */
1942 charset_string = string;
1946 attributes = CFDictionaryCreateMutable (NULL, 0,
1947 &kCFTypeDictionaryKeyCallBacks,
1948 &kCFTypeDictionaryValueCallBacks);
1952 tmp = AREF (spec, FONT_FAMILY_INDEX);
1953 if (SYMBOLP (tmp) && ! NILP (tmp))
1955 CFStringRef family = macfont_create_family_with_symbol (tmp);
1959 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1964 traits = CFDictionaryCreateMutable (NULL, 4,
1965 &kCFTypeDictionaryKeyCallBacks,
1966 &kCFTypeDictionaryValueCallBacks);
1970 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1972 tmp = AREF (spec, numeric_traits[i].index);
1975 CGPoint *point = numeric_traits[i].points;
1976 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1979 while (point->y < floatval)
1981 if (point == numeric_traits[i].points)
1983 else if (point->y == CGFLOAT_MAX)
1985 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1986 * ((point->x - (point - 1)->x)
1987 / (point->y - (point - 1)->y)));
1990 else if (floatval < -1.0)
1992 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1995 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1999 if (CFDictionaryGetCount (traits))
2000 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2003 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2006 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2009 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2016 CFRelease (attributes);
2021 if (langarray) CFRelease (langarray);
2022 if (charset && cf_charset_idx < 0) CFRelease (charset);
2023 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2024 if (traits) CFRelease (traits);
2027 if (otspec->nfeatures[0] > 0)
2028 free (otspec->features[0]);
2029 if (otspec->nfeatures[1] > 0)
2030 free (otspec->features[1]);
2038 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2039 CFCharacterSetRef charset,
2041 CFArrayRef languages)
2043 Boolean result = true;
2045 if (charset || VECTORP (chars))
2047 CFCharacterSetRef desc_charset =
2048 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2050 if (desc_charset == NULL)
2055 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2056 else /* VECTORP (chars) */
2060 for (j = 0; j < ASIZE (chars); j++)
2061 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2062 && CFCharacterSetIsLongCharacterMember (desc_charset,
2063 XFASTINT (AREF (chars, j))))
2065 if (j == ASIZE (chars))
2068 CFRelease (desc_charset);
2071 if (result && languages)
2072 result = mac_font_descriptor_supports_languages (desc, languages);
2078 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2079 CTFontSymbolicTraits sym_traits2)
2081 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2084 /* We prefer synthetic bold of italic to synthetic italic of bold
2085 when both bold and italic are available but bold-italic is not
2087 if (diff & kCTFontTraitBold)
2088 distance |= (1 << 0);
2089 if (diff & kCTFontTraitItalic)
2090 distance |= (1 << 1);
2091 if (diff & kCTFontTraitMonoSpace)
2092 distance |= (1 << 2);
2098 macfont_closest_traits_index_p (CFArrayRef traits_array,
2099 CTFontSymbolicTraits target,
2102 CFIndex i, count = CFArrayGetCount (traits_array);
2103 CTFontSymbolicTraits traits;
2106 traits = ((CTFontSymbolicTraits) (uintptr_t)
2107 CFArrayGetValueAtIndex (traits_array, index));
2108 my_distance = macfont_traits_distance (target, traits);
2110 for (i = 0; i < count; i++)
2113 traits = ((CTFontSymbolicTraits) (uintptr_t)
2114 CFArrayGetValueAtIndex (traits_array, i));
2115 if (macfont_traits_distance (target, traits) < my_distance)
2123 macfont_list (struct frame *f, Lisp_Object spec)
2125 Lisp_Object val = Qnil, family, extra;
2127 CFStringRef family_name = NULL;
2128 CFMutableDictionaryRef attributes = NULL, traits;
2129 Lisp_Object chars = Qnil;
2131 CTFontSymbolicTraits synth_sym_traits = 0;
2132 CFArrayRef families;
2133 CFIndex families_count;
2134 CFCharacterSetRef charset = NULL;
2135 CFArrayRef languages = NULL;
2139 family = AREF (spec, FONT_FAMILY_INDEX);
2140 if (! NILP (family))
2142 family_name = macfont_create_family_with_symbol (family);
2143 if (family_name == NULL)
2147 attributes = macfont_create_attributes_with_spec (spec);
2151 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2153 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2154 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2156 traits = ((CFMutableDictionaryRef)
2157 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2159 n = FONT_SLANT_NUMERIC (spec);
2160 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2162 synth_sym_traits |= kCTFontTraitItalic;
2164 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2167 n = FONT_WEIGHT_NUMERIC (spec);
2168 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2170 synth_sym_traits |= kCTFontTraitBold;
2172 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2176 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2178 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2180 if (CFStringHasPrefix (language, CFSTR ("ja"))
2181 || CFStringHasPrefix (language, CFSTR ("ko"))
2182 || CFStringHasPrefix (language, CFSTR ("zh")))
2183 synth_sym_traits |= kCTFontTraitMonoSpace;
2186 /* Create array of families. */
2188 families = CFArrayCreate (NULL, (const void **) &family_name,
2189 1, &kCFTypeArrayCallBacks);
2192 CFStringRef pref_family;
2193 CFIndex families_count, pref_family_index = -1;
2195 families = macfont_copy_available_families_cache ();
2196 if (families == NULL)
2199 families_count = CFArrayGetCount (families);
2201 /* Move preferred family to the front if exists. */
2203 mac_font_create_preferred_family_for_attributes (attributes);
2207 CFArrayGetFirstIndexOfValue (families,
2208 CFRangeMake (0, families_count),
2210 CFRelease (pref_family);
2212 if (pref_family_index > 0)
2214 CFMutableArrayRef mutable_families =
2215 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2217 if (mutable_families)
2219 CFArrayAppendValue (mutable_families,
2220 CFArrayGetValueAtIndex (families,
2221 pref_family_index));
2222 CFArrayAppendArray (mutable_families, families,
2223 CFRangeMake (0, pref_family_index));
2224 if (pref_family_index + 1 < families_count)
2225 CFArrayAppendArray (mutable_families, families,
2226 CFRangeMake (pref_family_index + 1,
2228 - (pref_family_index + 1)));
2229 CFRelease (families);
2230 families = mutable_families;
2235 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2239 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2243 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2246 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2247 if (CONSP (val) && VECTORP (XCDR (val)))
2255 CFRetain (languages);
2256 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2260 extra = AREF (spec, FONT_EXTRA_INDEX);
2261 families_count = CFArrayGetCount (families);
2262 for (i = 0; i < families_count; i++)
2264 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2265 CTFontDescriptorRef pat_desc;
2267 CFIndex descs_count;
2268 CFMutableArrayRef filtered_descs, traits_array;
2272 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2274 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2278 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2279 10.7 returns NULL if pat_desc represents the LastResort font.
2280 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2281 trailing "s") for such a font. */
2282 if (!CFEqual (family_name, CFSTR ("LastResort")))
2283 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2286 CTFontDescriptorRef lr_desc =
2287 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2290 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2291 &kCFTypeArrayCallBacks);
2292 CFRelease (lr_desc);
2297 CFRelease (pat_desc);
2301 descs_count = CFArrayGetCount (descs);
2302 if (descs_count == 0
2303 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2312 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2313 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2314 for (j = 0; j < descs_count; j++)
2316 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2317 CFDictionaryRef dict;
2319 CTFontSymbolicTraits sym_traits;
2321 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2325 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2328 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2332 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2333 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2334 != (spacing >= FONT_SPACING_MONO)))
2337 /* Don't use a color bitmap font unless its family is
2338 explicitly specified. */
2339 if ((sym_traits & kCTFontTraitColorGlyphs) && NILP (family))
2343 && !macfont_supports_charset_and_languages_p (desc, charset,
2347 CFArrayAppendValue (filtered_descs, desc);
2348 CFArrayAppendValue (traits_array,
2349 (const void *) (uintptr_t) sym_traits);
2353 descs = filtered_descs;
2354 descs_count = CFArrayGetCount (descs);
2356 for (j = 0; j < descs_count; j++)
2358 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2359 CTFontSymbolicTraits sym_traits =
2360 ((CTFontSymbolicTraits) (uintptr_t)
2361 CFArrayGetValueAtIndex (traits_array, j));
2362 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2364 mask_min = ((synth_sym_traits ^ sym_traits)
2365 & (kCTFontTraitItalic | kCTFontTraitBold));
2366 if (FONT_SLANT_NUMERIC (spec) < 0)
2367 mask_min &= ~kCTFontTraitItalic;
2368 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2369 mask_min &= ~kCTFontTraitBold;
2371 mask_max = (synth_sym_traits & ~sym_traits);
2372 /* Synthetic bold does not work for bitmap-only fonts on Mac
2374 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2376 CFNumberRef format =
2377 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2381 uint32_t format_val;
2383 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2385 && format_val == kCTFontFormatBitmap)
2386 mask_max &= ~kCTFontTraitBold;
2390 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2392 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2393 mmask <= (mask_max & kCTFontTraitMonoSpace);
2394 mmask += kCTFontTraitMonoSpace)
2395 for (bmask = (mask_min & kCTFontTraitBold);
2396 bmask <= (mask_max & kCTFontTraitBold);
2397 bmask += kCTFontTraitBold)
2398 for (imask = (mask_min & kCTFontTraitItalic);
2399 imask <= (mask_max & kCTFontTraitItalic);
2400 imask += kCTFontTraitItalic)
2402 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2405 || macfont_closest_traits_index_p (traits_array,
2406 (sym_traits | synth),
2409 entity = macfont_descriptor_entity (desc, extra, synth);
2410 if (! NILP (entity))
2411 val = Fcons (entity, val);
2416 CFRelease (traits_array);
2420 CFRelease (families);
2421 val = Fnreverse (val);
2427 FONT_ADD_LOG ("macfont-list", spec, val);
2428 if (charset) CFRelease (charset);
2429 if (languages) CFRelease (languages);
2430 if (attributes) CFRelease (attributes);
2431 if (family_name) CFRelease (family_name);
2439 macfont_match (struct frame * frame, Lisp_Object spec)
2441 Lisp_Object entity = Qnil;
2442 CFMutableDictionaryRef attributes;
2443 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2447 attributes = macfont_create_attributes_with_spec (spec);
2450 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2451 CFRelease (attributes);
2455 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2456 CFRelease (pat_desc);
2460 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2466 FONT_ADD_LOG ("macfont-match", spec, entity);
2471 macfont_list_family (struct frame *frame)
2473 Lisp_Object list = Qnil;
2474 CFArrayRef families;
2478 families = macfont_copy_available_families_cache ();
2481 CFIndex i, count = CFArrayGetCount (families);
2483 for (i = 0; i < count; i++)
2484 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2485 CFRelease (families);
2494 macfont_free_entity (Lisp_Object entity)
2496 Lisp_Object val = assq_no_quit (QCfont_entity,
2497 AREF (entity, FONT_EXTRA_INDEX));
2498 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2506 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2508 Lisp_Object val, font_object;
2509 CFStringRef font_name;
2510 struct macfont_info *macfont_info = NULL;
2514 CTFontSymbolicTraits sym_traits;
2516 int len, i, total_width;
2518 CGFloat ascent, descent, leading;
2520 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2522 || XTYPE (XCDR (val)) != Lisp_Misc
2523 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2525 font_name = XSAVE_POINTER (XCDR (val), 0);
2526 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2528 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2533 macfont = CTFontCreateWithName (font_name, size, NULL);
2536 int fontsize = (int) [((NSFont *) macfont) pointSize];
2537 if (fontsize != size) size = fontsize;
2543 font_object = font_build_object (VECSIZE (struct macfont_info),
2544 Qmac_ct, entity, size);
2545 font = XFONT_OBJECT (font_object);
2546 font->pixel_size = size;
2547 font->driver = &macfont_driver;
2548 font->encoding_charset = font->repertory_charset = -1;
2552 macfont_info = (struct macfont_info *) font;
2553 macfont_info->macfont = macfont;
2554 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2556 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2557 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2558 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2561 macfont_info->screen_font = NULL;
2562 macfont_info->cache = macfont_lookup_cache (font_name);
2563 macfont_retain_cache (macfont_info->cache);
2564 macfont_info->metrics = NULL;
2565 macfont_info->metrics_nrows = 0;
2566 macfont_info->synthetic_italic_p = 0;
2567 macfont_info->synthetic_bold_p = 0;
2568 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2569 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2570 if (!(sym_traits & kCTFontTraitItalic)
2571 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2572 macfont_info->synthetic_italic_p = 1;
2573 if (!(sym_traits & kCTFontTraitBold)
2574 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2575 macfont_info->synthetic_bold_p = 1;
2576 if (sym_traits & kCTFontTraitMonoSpace)
2577 macfont_info->spacing = MACFONT_SPACING_MONO;
2578 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2579 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2580 == FONT_SPACING_SYNTHETIC_MONO))
2581 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2582 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2583 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2586 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2588 macfont_info->antialias =
2589 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2591 macfont_info->color_bitmap_p = 0;
2592 if (sym_traits & kCTFontTraitColorGlyphs)
2593 macfont_info->color_bitmap_p = 1;
2595 glyph = macfont_get_glyph_for_character (font, ' ');
2596 if (glyph != kCGFontIndexInvalid)
2597 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2599 /* dirty workaround */
2600 font->space_width = pixel_size;
2602 total_width = font->space_width;
2603 for (i = 1; i < 95; i++)
2605 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2606 if (glyph == kCGFontIndexInvalid)
2608 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2611 font->average_width = total_width / 95;
2613 font->average_width = font->space_width; /* XXX */
2615 if (!(macfont_info->screen_font
2616 && mac_screen_font_get_metrics (macfont_info->screen_font,
2617 &ascent, &descent, &leading)))
2619 CFStringRef family_name;
2621 ascent = CTFontGetAscent (macfont);
2622 descent = CTFontGetDescent (macfont);
2623 leading = CTFontGetLeading (macfont);
2624 /* AppKit and WebKit do some adjustment to the heights of
2625 Courier, Helvetica, and Times. */
2626 family_name = CTFontCopyFamilyName (macfont);
2629 if (CFEqual (family_name, CFSTR ("Courier"))
2630 || CFEqual (family_name, CFSTR ("Helvetica"))
2631 || CFEqual (family_name, CFSTR ("Times")))
2632 ascent += (ascent + descent) * .15f;
2633 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2638 CFRelease (family_name);
2641 font->ascent = ascent + 0.5f;
2642 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2643 if (CONSP (val) && !NILP (XCDR (val)))
2644 font->descent = descent + 0.5f;
2646 font->descent = descent + leading + 0.5f;
2647 font->height = font->ascent + font->descent;
2649 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2650 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2654 /* Unfortunately Xft doesn't provide a way to get minimum char
2655 width. So, we use space_width instead. */
2656 font->min_width = font->max_width = font->space_width; /* XXX */
2658 font->baseline_offset = 0;
2659 font->relative_compose = 0;
2660 font->default_ascent = 0;
2661 font->vertical_centering = 0;
2667 macfont_close (struct font *font)
2669 struct macfont_info *macfont_info = (struct macfont_info *) font;
2671 if (macfont_info->cache)
2676 CFRelease (macfont_info->macfont);
2677 CGFontRelease (macfont_info->cgfont);
2678 if (macfont_info->screen_font)
2679 CFRelease (macfont_info->screen_font);
2680 macfont_release_cache (macfont_info->cache);
2681 for (i = 0; i < macfont_info->metrics_nrows; i++)
2682 if (macfont_info->metrics[i])
2683 xfree (macfont_info->metrics[i]);
2684 if (macfont_info->metrics)
2685 xfree (macfont_info->metrics);
2686 macfont_info->cache = NULL;
2692 macfont_has_char (Lisp_Object font, int c)
2695 CFCharacterSetRef charset;
2698 if (FONT_ENTITY_P (font))
2703 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2705 name = XSAVE_POINTER (val, 0);
2706 charset = macfont_get_cf_charset_for_name (name);
2709 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2711 result = CFCharacterSetIsLongCharacterMember (charset, c);
2718 macfont_encode_char (struct font *font, int c)
2720 struct macfont_info *macfont_info = (struct macfont_info *) font;
2724 glyph = macfont_get_glyph_for_character (font, c);
2727 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2731 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2732 struct font_metrics *metrics)
2737 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2738 for (i = 1; i < nglyphs; i++)
2740 struct font_metrics m;
2741 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2746 if (width + m.lbearing < metrics->lbearing)
2747 metrics->lbearing = width + m.lbearing;
2748 if (width + m.rbearing > metrics->rbearing)
2749 metrics->rbearing = width + m.rbearing;
2750 if (m.ascent > metrics->ascent)
2751 metrics->ascent = m.ascent;
2752 if (m.descent > metrics->descent)
2753 metrics->descent = m.descent;
2760 metrics->width = width;
2764 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2765 bool with_background)
2767 struct frame * f = s->f;
2768 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2769 CGRect background_rect;
2770 CGPoint text_position;
2773 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2774 bool no_antialias_p =
2775 (NILP (ns_antialias_text)
2776 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2777 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2778 && font_size <= macfont_antialias_threshold));
2779 int len = to - from;
2780 struct face *face = s->face;
2781 CGContextRef context;
2785 if (with_background)
2786 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2787 s->width, FONT_HEIGHT (s->font));
2789 background_rect = CGRectNull;
2791 text_position = CGPointMake (x, -y);
2792 glyphs = xmalloc (sizeof (CGGlyph) * len);
2794 CGFloat advance_delta = 0;
2796 CGFloat total_width = 0;
2798 positions = xmalloc (sizeof (CGPoint) * len);
2799 for (i = 0; i < len; i++)
2803 glyphs[i] = s->char2b[from + i];
2804 width = (s->padding_p ? 1
2805 : macfont_glyph_extents (s->font, glyphs[i],
2806 NULL, &advance_delta,
2808 positions[i].x = total_width + advance_delta;
2810 total_width += width;
2814 context = [[NSGraphicsContext currentContext] graphicsPort];
2815 CGContextSaveGState (context);
2817 if (!CGRectIsNull (background_rect))
2819 if (s->hl == DRAW_MOUSE_FACE)
2821 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2823 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2825 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2826 CGContextFillRects (context, &background_rect, 1);
2829 if (macfont_info->cgfont)
2831 CGAffineTransform atfm;
2833 CGContextScaleCTM (context, 1, -1);
2834 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2835 if (macfont_info->synthetic_italic_p)
2836 atfm = synthetic_italic_atfm;
2838 atfm = CGAffineTransformIdentity;
2839 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2841 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2842 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2843 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2846 CGContextSetShouldAntialias (context, false);
2848 CGContextSetTextMatrix (context, atfm);
2849 CGContextSetTextPosition (context, text_position.x, text_position.y);
2851 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2852 if (macfont_info->color_bitmap_p
2853 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2854 && CTFontDrawGlyphs != NULL
2860 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2865 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2867 CGContextSetFont (context, macfont_info->cgfont);
2868 CGContextSetFontSize (context, font_size);
2869 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2876 CGContextRestoreGState (context);
2884 macfont_shape (Lisp_Object lgstring)
2886 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2887 struct macfont_info *macfont_info = (struct macfont_info *) font;
2888 CTFontRef macfont = macfont_info->macfont;
2889 ptrdiff_t glyph_len, len, i, j;
2892 CFIndex *nonbmp_indices;
2895 struct mac_glyph_layout *glyph_layouts;
2897 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2899 for (i = 0; i < glyph_len; i++)
2901 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2905 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2911 if (INT_MAX / 2 < len)
2912 memory_full (SIZE_MAX);
2914 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2915 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2916 for (i = j = 0; i < len; i++)
2918 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2920 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2922 nonbmp_indices[j] = i + j;
2926 nonbmp_indices[j] = len + j; /* sentinel */
2930 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2934 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2935 if (macfont_info->screen_font)
2936 used = mac_screen_font_shape (macfont_info->screen_font, string,
2937 glyph_layouts, glyph_len);
2939 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2950 for (i = 0; i < used; i++)
2952 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2953 struct mac_glyph_layout *gl = glyph_layouts + i;
2955 struct font_metrics metrics;
2956 int xoff, yoff, wadjust;
2960 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2961 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2964 from = gl->comp_range.location;
2965 /* Convert UTF-16 index to UTF-32. */
2967 while (nonbmp_indices[j] < from)
2970 LGLYPH_SET_FROM (lglyph, from);
2972 to = gl->comp_range.location + gl->comp_range.length;
2973 /* Convert UTF-16 index to UTF-32. */
2974 while (nonbmp_indices[j] < to)
2977 LGLYPH_SET_TO (lglyph, to - 1);
2979 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2980 the composition is trivial. */
2984 if (unichars[gl->string_index] >= 0xD800
2985 && unichars[gl->string_index] < 0xDC00)
2986 c = (((unichars[gl->string_index] - 0xD800) << 10)
2987 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2989 c = unichars[gl->string_index];
2990 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2992 LGLYPH_SET_CHAR (lglyph, c);
2996 unsigned long cc = gl->glyph_id;
2997 LGLYPH_SET_CODE (lglyph, cc);
3000 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3001 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3002 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3003 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3004 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3005 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3007 xoff = lround (gl->advance_delta);
3008 yoff = lround (- gl->baseline_delta);
3009 wadjust = lround (gl->advance);
3010 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3014 vec = Fmake_vector (make_number (3), Qnil);
3015 ASET (vec, 0, make_number (xoff));
3016 ASET (vec, 1, make_number (yoff));
3017 ASET (vec, 2, make_number (wadjust));
3018 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3024 return make_number (used);
3027 /* Structures for the UVS subtable (format 14) in the cmap table. */
3028 typedef UInt8 UINT24[3];
3030 #pragma pack(push, 1)
3031 struct variation_selector_record
3033 UINT24 var_selector;
3034 UInt32 default_uvs_offset, non_default_uvs_offset;
3039 UInt32 length, num_var_selector_records;
3040 struct variation_selector_record variation_selector_records[1];
3042 #define SIZEOF_UVS_TABLE_HEADER \
3043 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3045 struct unicode_value_range
3047 UINT24 start_unicode_value;
3048 UInt8 additional_count;
3050 struct default_uvs_table {
3051 UInt32 num_unicode_value_ranges;
3052 struct unicode_value_range unicode_value_ranges[1];
3054 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3055 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3059 UINT24 unicode_value;
3062 struct non_default_uvs_table
3064 UInt32 num_uvs_mappings;
3065 struct uvs_mapping uvs_mappings[1];
3067 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3068 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3071 /* Read big endian values. The argument LVAL must be an lvalue. */
3072 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3073 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3074 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3075 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3076 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3077 /* Succeeding one byte should also be accessible. */
3078 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3079 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3081 /* Return UVS subtable for the specified FONT. If the subtable is not
3082 found or ill-formatted, then return NULL. */
3085 mac_font_copy_uvs_table (CTFontRef font)
3087 CFDataRef cmap_table, uvs_table = NULL;
3089 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3090 kCTFontTableOptionNoOptions);
3093 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3094 struct uvs_table *uvs;
3095 struct variation_selector_record *records;
3096 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3099 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3103 cmap_len = CFDataGetLength (cmap_table);
3104 if (sizeof_sfntCMapHeader > cmap_len)
3107 ntables = BUINT16_VALUE (cmap->numTables);
3108 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3109 / sizeof_sfntCMapEncoding))
3112 for (i = 0; i < ntables; i++)
3113 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3114 == kFontUnicodePlatform)
3115 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3116 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3118 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3122 || uvs_offset > cmap_len
3123 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3126 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3127 uvs_len = BUINT32_VALUE (uvs->length);
3128 if (uvs_len > cmap_len - uvs_offset
3129 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3132 if (BUINT16_VALUE (uvs->format) != 14)
3135 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3136 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3137 / sizeof (struct variation_selector_record)))
3140 records = uvs->variation_selector_records;
3141 for (i = 0; i < nrecords; i++)
3143 UInt32 default_uvs_offset, non_default_uvs_offset;
3145 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3146 if (default_uvs_offset)
3148 struct default_uvs_table *default_uvs;
3151 if (default_uvs_offset > uvs_len
3152 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3153 > uvs_len - default_uvs_offset))
3156 default_uvs = ((struct default_uvs_table *)
3157 ((UInt8 *) uvs + default_uvs_offset));
3158 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3159 if (nranges > ((uvs_len - default_uvs_offset
3160 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3161 / sizeof (struct unicode_value_range)))
3163 /* Now 2 * nranges can't overflow, so we can safely use
3164 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3165 mac_font_get_glyphs_for_variants. */
3168 non_default_uvs_offset =
3169 BUINT32_VALUE (records[i].non_default_uvs_offset);
3170 if (non_default_uvs_offset)
3172 struct non_default_uvs_table *non_default_uvs;
3175 if (non_default_uvs_offset > uvs_len
3176 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3177 > uvs_len - non_default_uvs_offset))
3180 non_default_uvs = ((struct non_default_uvs_table *)
3181 ((UInt8 *) uvs + non_default_uvs_offset));
3182 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3183 if (nmappings > ((uvs_len - non_default_uvs_offset
3184 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3185 / sizeof (struct uvs_mapping)))
3187 /* Now 2 * nmappings can't overflow, so we can safely
3188 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3189 in mac_font_get_glyphs_for_variants. */
3193 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3196 CFRelease (cmap_table);
3202 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3203 sequence consisting of the given base character C and each
3204 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3205 result (explained below) into the corresponding GLYPHS[i]. If the
3206 entry is found in the Default UVS Table, then the result is 0. If
3207 the entry is found in the Non-Default UVS Table, then the result is
3208 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3209 elements in SELECTORS must be sorted in strictly increasing
3213 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3214 const UTF32Char selectors[], CGGlyph glyphs[],
3217 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3218 struct variation_selector_record *records = uvs->variation_selector_records;
3220 UInt32 ir, nrecords;
3221 dispatch_queue_t queue =
3222 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3223 dispatch_group_t group = dispatch_group_create ();
3225 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3228 while (i < count && ir < nrecords)
3230 UInt32 default_uvs_offset, non_default_uvs_offset;
3232 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3234 glyphs[i++] = kCGFontIndexInvalid;
3237 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3243 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3244 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3245 non_default_uvs_offset =
3246 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3247 dispatch_group_async (group, queue, ^{
3248 glyphs[i] = kCGFontIndexInvalid;
3250 if (default_uvs_offset)
3252 struct default_uvs_table *default_uvs =
3253 (struct default_uvs_table *) ((UInt8 *) uvs
3254 + default_uvs_offset);
3255 struct unicode_value_range *ranges =
3256 default_uvs->unicode_value_ranges;
3260 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3263 UInt32 mid = (lo + hi) / 2;
3265 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3271 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3272 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3276 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3278 struct non_default_uvs_table *non_default_uvs =
3279 (struct non_default_uvs_table *) ((UInt8 *) uvs
3280 + non_default_uvs_offset);
3281 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3285 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3288 UInt32 mid = (lo + hi) / 2;
3290 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3296 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3297 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3304 glyphs[i++] = kCGFontIndexInvalid;
3305 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3306 dispatch_release (group);
3310 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3312 CFDataRef uvs_table;
3313 CTCharacterCollection uvs_collection;
3317 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3321 UTF32Char selectors[256];
3322 CGGlyph glyphs[256];
3324 for (i = 0; i < 16; i++)
3325 selectors[i] = 0xFE00 + i;
3326 for (; i < 256; i++)
3327 selectors[i] = 0xE0100 + (i - 16);
3328 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3329 for (i = 0; i < 256; i++)
3331 CGGlyph glyph = glyphs[i];
3333 if (uvs_collection != kCTCharacterCollectionIdentityMapping
3334 && glyph != kCGFontIndexInvalid)
3335 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3336 if (glyph == kCGFontIndexInvalid)
3340 variations[i] = (glyph ? glyph
3341 : macfont_get_glyph_for_character (font, c));
3351 static const char *const macfont_booleans[] = {
3357 static const char *const macfont_non_booleans[] = {
3365 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3367 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3371 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3372 CFArrayRef languages)
3374 Boolean result = true;
3375 CFArrayRef desc_languages =
3376 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3378 if (desc_languages == NULL)
3382 CFIndex desc_languages_count, i, languages_count;
3384 desc_languages_count = CFArrayGetCount (desc_languages);
3385 languages_count = CFArrayGetCount (languages);
3386 for (i = 0; i < languages_count; i++)
3387 if (!CFArrayContainsValue (desc_languages,
3388 CFRangeMake (0, desc_languages_count),
3389 CFArrayGetValueAtIndex (languages, i)))
3394 CFRelease (desc_languages);
3401 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3403 CFStringRef result = NULL;
3404 CFStringRef charset_string =
3405 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3407 if (charset_string && CFStringGetLength (charset_string) > 0)
3409 CFStringRef keys[] = {
3410 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3411 kCTLanguageAttributeName
3413 CFSTR ("NSLanguage")
3416 CFTypeRef values[] = {NULL};
3417 CFIndex num_values = 0;
3418 CFArrayRef languages
3419 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3421 if (languages && CFArrayGetCount (languages) > 0)
3423 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3424 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3427 CFCharacterSetRef charset =
3428 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3430 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3435 CFAttributedStringRef attr_string = NULL;
3436 CTLineRef ctline = NULL;
3437 CFDictionaryRef attrs
3438 = CFDictionaryCreate (NULL, (const void **) keys,
3439 (const void **) values, num_values,
3440 &kCFTypeDictionaryKeyCallBacks,
3441 &kCFTypeDictionaryValueCallBacks);
3445 attr_string = CFAttributedStringCreate (NULL, charset_string,
3451 ctline = CTLineCreateWithAttributedString (attr_string);
3452 CFRelease (attr_string);
3456 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3457 CFIndex i, nruns = CFArrayGetCount (runs);
3460 for (i = 0; i < nruns; i++)
3462 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3463 CFDictionaryRef attributes = CTRunGetAttributes (run);
3464 CTFontRef font_in_run;
3466 if (attributes == NULL)
3469 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3470 if (font_in_run == NULL)
3474 else if (!mac_font_equal_in_postscript_name (font,
3478 if (nruns > 0 && i == nruns)
3479 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3488 static inline double
3489 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3491 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3495 static inline CGRect
3496 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3498 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3503 mac_font_create_available_families (void)
3505 CFMutableArrayRef families = NULL;
3506 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3510 CFIndex i, count = CFArrayGetCount (orig_families);
3512 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3514 for (i = 0; i < count; i++)
3516 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3518 if (!CFStringHasPrefix (family, CFSTR ("."))
3519 && (CTFontManagerCompareFontFamilyNames (family,
3520 CFSTR ("LastResort"),
3522 != kCFCompareEqualTo))
3523 CFArrayAppendValue (families, family);
3525 CFRelease (orig_families);
3532 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3535 CFStringRef name1, name2;
3541 name1 = CTFontCopyPostScriptName (font1);
3544 name2 = CTFontCopyPostScriptName (font2);
3547 result = CFEqual (name1, name2);
3557 mac_font_create_line_with_string_and_font (CFStringRef string,
3560 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3561 CFTypeRef values[] = {NULL, NULL};
3562 CFDictionaryRef attributes = NULL;
3563 CFAttributedStringRef attr_string = NULL;
3564 CTLineRef ctline = NULL;
3565 float float_zero = 0.0f;
3567 values[0] = macfont;
3568 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3571 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3572 (const void **) values,
3574 &kCFTypeDictionaryKeyCallBacks,
3575 &kCFTypeDictionaryValueCallBacks);
3576 CFRelease (values[1]);
3580 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3581 CFRelease (attributes);
3585 ctline = CTLineCreateWithAttributedString (attr_string);
3586 CFRelease (attr_string);
3590 /* Abandon if ctline contains some fonts other than the
3592 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3593 CFIndex i, nruns = CFArrayGetCount (runs);
3595 for (i = 0; i < nruns; i++)
3597 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3598 CFDictionaryRef attributes = CTRunGetAttributes (run);
3599 CTFontRef font_in_run;
3601 if (attributes == NULL)
3604 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3605 if (font_in_run == NULL)
3607 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3621 mac_font_shape (CTFontRef font, CFStringRef string,
3622 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3624 CFIndex used, result = 0;
3625 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3630 used = CTLineGetGlyphCount (ctline);
3631 if (used <= glyph_len)
3633 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3634 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3635 CGFloat total_advance = 0;
3636 CFIndex total_glyph_count = 0;
3638 for (k = 0; k < ctrun_count; k++)
3640 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3641 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3642 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3643 CFRange string_range, comp_range, range;
3644 CFIndex *permutation;
3646 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3647 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3651 #define RIGHT_TO_LEFT_P permutation
3653 /* Now the `comp_range' member of struct mac_glyph_layout is
3654 temporarily used as a work area such that:
3655 glbuf[i].comp_range.location =
3656 min {compRange[i + 1].location, ...,
3657 compRange[glyph_count - 1].location,
3658 maxRange (stringRangeForCTRun)}
3659 glbuf[i].comp_range.length = maxRange (compRange[i])
3660 where compRange[i] is the range of composed characters
3661 containing i-th glyph. */
3662 string_range = CTRunGetStringRange (ctrun);
3663 min_location = string_range.location + string_range.length;
3664 for (i = 0; i < glyph_count; i++)
3666 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3667 CFIndex glyph_index;
3670 if (!RIGHT_TO_LEFT_P)
3671 glyph_index = glyph_count - i - 1;
3674 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3677 CFStringGetRangeOfComposedCharactersAtIndex (string,
3679 gl->comp_range.location = min_location;
3680 gl->comp_range.length = rng.location + rng.length;
3681 if (rng.location < min_location)
3682 min_location = rng.location;
3685 /* Fill the `comp_range' member of struct mac_glyph_layout,
3686 and setup a permutation for right-to-left text. */
3687 comp_range = CFRangeMake (string_range.location, 0);
3688 range = CFRangeMake (0, 0);
3691 struct mac_glyph_layout *gl =
3692 glbuf + range.location + range.length;
3694 if (gl->comp_range.length
3695 > comp_range.location + comp_range.length)
3696 comp_range.length = gl->comp_range.length - comp_range.location;
3697 min_location = gl->comp_range.location;
3700 if (min_location >= comp_range.location + comp_range.length)
3702 comp_range.length = min_location - comp_range.location;
3703 for (i = 0; i < range.length; i++)
3705 glbuf[range.location + i].comp_range = comp_range;
3706 if (RIGHT_TO_LEFT_P)
3707 permutation[range.location + i] =
3708 range.location + range.length - i - 1;
3711 comp_range = CFRangeMake (min_location, 0);
3712 range.location += range.length;
3714 if (range.location == glyph_count)
3719 /* Then fill the remaining members. */
3720 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3723 struct mac_glyph_layout *gl;
3726 if (!RIGHT_TO_LEFT_P)
3727 gl = glbuf + range.location;
3732 src = glyph_count - 1 - range.location;
3733 dest = permutation[src];
3737 CFIndex tmp = gl->string_index;
3739 gl->string_index = glbuf[src].string_index;
3740 glbuf[src].string_index = tmp;
3743 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3745 CTRunGetPositions (ctrun, range, &position);
3746 gl->advance_delta = position.x - total_advance;
3747 gl->baseline_delta = position.y;
3748 gl->advance = (gl->advance_delta
3749 + CTRunGetTypographicBounds (ctrun, range,
3751 total_advance += gl->advance;
3754 if (RIGHT_TO_LEFT_P)
3755 xfree (permutation);
3757 #undef RIGHT_TO_LEFT_P
3759 total_glyph_count += glyph_count;
3769 /* The function below seems to cause a memory leak for the CFString
3770 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3771 10.6.3. For now, we use the NSGlyphInfo version instead. */
3772 #if USE_CT_GLYPH_INFO
3774 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3777 CGGlyph result = kCGFontIndexInvalid;
3778 UniChar characters[] = {0xfffd};
3780 CFAttributedStringRef attr_string = NULL;
3781 CTLineRef ctline = NULL;
3783 string = CFStringCreateWithCharacters (NULL, characters,
3784 ARRAYELTS (characters));
3788 CTGlyphInfoRef glyph_info =
3789 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3790 CFDictionaryRef attributes = NULL;
3794 CFStringRef keys[] = {kCTFontAttributeName,
3795 kCTGlyphInfoAttributeName};
3796 CFTypeRef values[] = {font, glyph_info};
3798 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3799 (const void **) values,
3801 &kCFTypeDictionaryKeyCallBacks,
3802 &kCFTypeDictionaryValueCallBacks);
3803 CFRelease (glyph_info);
3807 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3808 CFRelease (attributes);
3814 ctline = CTLineCreateWithAttributedString (attr_string);
3815 CFRelease (attr_string);
3819 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3821 if (CFArrayGetCount (runs) > 0)
3823 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3824 CFDictionaryRef attributes = CTRunGetAttributes (run);
3828 CTFontRef font_in_run =
3829 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3832 && mac_font_equal_in_postscript_name (font_in_run, font))
3834 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3835 if (result >= CTFontGetGlyphCount (font))
3836 result = kCGFontIndexInvalid;
3848 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3850 CFArrayRef result = NULL;
3852 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3853 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3854 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3857 CTFontRef user_font =
3858 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3862 CFArrayRef languages =
3863 CFArrayCreate (NULL, (const void **) &language, 1,
3864 &kCFTypeArrayCallBacks);
3868 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3870 CFRelease (languages);
3872 CFRelease (user_font);
3875 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3876 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3878 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3879 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3883 for (i = 0; macfont_language_default_font_names[i].language; i++)
3885 if (CFEqual (macfont_language_default_font_names[i].language,
3888 CFMutableArrayRef descriptors =
3889 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3896 macfont_language_default_font_names[i].font_names[j];
3899 CFDictionaryRef attributes =
3900 CFDictionaryCreate (NULL,
3902 &kCTFontNameAttribute),
3904 &macfont_language_default_font_names[i].font_names[j]),
3905 1, &kCFTypeDictionaryKeyCallBacks,
3906 &kCFTypeDictionaryValueCallBacks);
3910 CTFontDescriptorRef pat_desc =
3911 CTFontDescriptorCreateWithAttributes (attributes);
3915 CTFontDescriptorRef descriptor =
3916 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3920 CFArrayAppendValue (descriptors, descriptor);
3921 CFRelease (descriptor);
3923 CFRelease (pat_desc);
3925 CFRelease (attributes);
3928 result = descriptors;
3940 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3941 CFArrayRef languages)
3943 CFStringRef result = NULL;
3944 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3945 CFArrayRef descriptors =
3946 mac_font_copy_default_descriptors_for_language (language);
3950 CFIndex i, count = CFArrayGetCount (descriptors);
3952 for (i = 0; i < count; i++)
3954 CTFontDescriptorRef descriptor =
3955 CFArrayGetValueAtIndex (descriptors, i);
3957 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3960 CFStringRef family =
3961 CTFontDescriptorCopyAttribute (descriptor,
3962 kCTFontFamilyNameAttribute);
3965 if (!CFStringHasPrefix (family, CFSTR ("."))
3966 && !CFEqual (family, CFSTR ("LastResort")))
3976 CFRelease (descriptors);
3983 macfont_get_nsctfont (struct font *font)
3985 struct macfont_info *macfont_info = (struct macfont_info *) font;
3986 CTFontRef macfont = macfont_info->macfont;
3988 return (void *) macfont;
3992 mac_register_font_driver (struct frame *f)
3994 register_font_driver (&macfont_driver, f);
3999 syms_of_macfont (void)
4001 static struct font_driver mac_font_driver;
4003 /* Core Text, for Mac OS X. */
4004 DEFSYM (Qmac_ct, "mac-ct");
4005 macfont_driver.type = Qmac_ct;
4006 register_font_driver (&macfont_driver, NULL);
4008 /* The font property key specifying the font design destination. The
4009 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4010 text. (See the documentation of X Logical Font Description
4011 Conventions.) In the Mac font driver, 1 means the screen font is
4012 used for calculating some glyph metrics. You can see the
4013 difference with Monaco 8pt or 9pt, for example. */
4014 DEFSYM (QCdestination, ":destination");
4016 /* The boolean-valued font property key specifying the use of leading. */
4017 DEFSYM (QCminspace, ":minspace");
4019 macfont_family_cache = Qnil;
4020 staticpro (&macfont_family_cache);