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;
201 #if !USE_CT_GLYPH_INFO
203 mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
206 CGGlyph result = kCGFontIndexInvalid;
207 NSFont *nsFont = (NSFont *) font;
208 unichar characters[] = {0xfffd};
210 [NSString stringWithCharacters:characters
211 length:ARRAYELTS (characters)];
212 NSGlyphInfo *glyphInfo =
213 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
214 collection:collection
216 NSDictionary *attributes =
217 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
218 glyphInfo,NSGlyphInfoAttributeName,nil];
219 NSTextStorage *textStorage =
220 [[NSTextStorage alloc] initWithString:string
221 attributes:attributes];
222 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
223 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
224 NSFont *fontInTextStorage;
226 [layoutManager addTextContainer:textContainer];
227 [textContainer release];
228 [textStorage addLayoutManager:layoutManager];
229 [layoutManager release];
232 (void) [layoutManager glyphRangeForTextContainer:textContainer];
234 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
235 effectiveRange:NULL];
236 if (fontInTextStorage == nsFont
237 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
239 NSGlyph glyph = [layoutManager glyphAtIndex:0];
241 if (glyph < [nsFont numberOfGlyphs])
245 [textStorage release];
252 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
254 NSFont *result, *font;
256 font = [NSFont fontWithName:((NSString *) name) size:size];
257 result = [font screenFont];
259 return (ScreenFontRef)[result retain];
264 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
265 CGFloat *descent, CGFloat *leading)
267 NSFont *nsFont = [(NSFont *)font printerFont];
268 NSTextStorage *textStorage;
269 NSLayoutManager *layoutManager;
270 NSTextContainer *textContainer;
272 NSPoint spaceLocation;
275 textStorage = [[NSTextStorage alloc] initWithString:@" "];
276 layoutManager = [[NSLayoutManager alloc] init];
277 textContainer = [[NSTextContainer alloc] init];
279 [textStorage setFont:nsFont];
280 [textContainer setLineFragmentPadding:0];
281 [layoutManager setUsesScreenFonts:YES];
283 [layoutManager addTextContainer:textContainer];
284 [textContainer release];
285 [textStorage addLayoutManager:layoutManager];
286 [layoutManager release];
288 if (!(textStorage && layoutManager && textContainer))
290 [textStorage release];
295 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
296 effectiveRange:NULL];
297 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
298 [textStorage release];
300 *ascent = spaceLocation.y;
301 *descent = NSHeight (usedRect) - spaceLocation.y;
303 descender = [nsFont descender];
304 if (- descender < *descent)
306 *leading = *descent + descender;
307 *descent = - descender;
314 mac_font_shape_1 (NSFont *font, NSString *string,
315 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
320 NSTextStorage *textStorage;
321 NSLayoutManager *layoutManager;
322 NSTextContainer *textContainer;
323 NSUInteger stringLength;
324 NSPoint spaceLocation;
325 NSUInteger used, numberOfGlyphs;
327 textStorage = [[NSTextStorage alloc] initWithString:string];
328 layoutManager = [[NSLayoutManager alloc] init];
329 textContainer = [[NSTextContainer alloc] init];
331 /* Append a trailing space to measure baseline position. */
332 [textStorage appendAttributedString:([[[NSAttributedString alloc]
333 initWithString:@" "] autorelease])];
334 [textStorage setFont:font];
335 [textContainer setLineFragmentPadding:0];
336 [layoutManager setUsesScreenFonts:screen_font_p];
338 [layoutManager addTextContainer:textContainer];
339 [textContainer release];
340 [textStorage addLayoutManager:layoutManager];
341 [layoutManager release];
343 if (!(textStorage && layoutManager && textContainer))
345 [textStorage release];
350 stringLength = [string length];
353 (void) [layoutManager glyphRangeForTextContainer:textContainer];
355 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
357 /* Remove the appended trailing space because otherwise it may
358 generate a wrong result for a right-to-left text. */
359 [textStorage beginEditing];
360 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
361 [textStorage endEditing];
362 (void) [layoutManager glyphRangeForTextContainer:textContainer];
365 while (i < stringLength)
368 NSFont *fontInTextStorage =
369 [textStorage attribute:NSFontAttributeName atIndex:i
370 longestEffectiveRange:&range
371 inRange:(NSMakeRange (0, stringLength))];
373 if (!(fontInTextStorage == font
374 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
376 i = NSMaxRange (range);
378 if (i < stringLength)
379 /* Make the test `used <= glyph_len' below fail if textStorage
380 contained some fonts other than the specified one. */
381 used = glyph_len + 1;
384 NSRange range = NSMakeRange (0, stringLength);
386 range = [layoutManager glyphRangeForCharacterRange:range
387 actualCharacterRange:NULL];
388 numberOfGlyphs = NSMaxRange (range);
389 used = numberOfGlyphs;
390 for (i = 0; i < numberOfGlyphs; i++)
391 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
395 if (0 < used && used <= glyph_len)
397 NSUInteger glyphIndex, prevGlyphIndex;
398 unsigned char bidiLevel;
399 NSUInteger *permutation;
400 NSRange compRange, range;
401 CGFloat totalAdvance;
404 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
407 /* For now we assume the direction is not changed within the
409 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
410 glyphs:NULL characterIndexes:NULL
411 glyphInscriptions:NULL elasticBits:NULL
412 bidiLevels:&bidiLevel];
414 permutation = xmalloc (sizeof (NSUInteger) * used);
418 #define RIGHT_TO_LEFT_P permutation
420 /* Fill the `comp_range' member of struct mac_glyph_layout, and
421 setup a permutation for right-to-left text. */
422 compRange = NSMakeRange (0, 0);
423 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
426 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
427 NSUInteger characterIndex =
428 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
430 gl->string_index = characterIndex;
432 if (characterIndex >= NSMaxRange (compRange))
434 compRange.location = NSMaxRange (compRange);
437 NSRange characterRange =
439 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
442 NSMaxRange (characterRange) - compRange.location;
443 [layoutManager glyphRangeForCharacterRange:compRange
444 actualCharacterRange:&characterRange];
445 characterIndex = NSMaxRange (characterRange) - 1;
447 while (characterIndex >= NSMaxRange (compRange));
450 for (i = 0; i < range.length; i++)
451 permutation[range.location + i] = NSMaxRange (range) - i - 1;
453 range = NSMakeRange (NSMaxRange (range), 0);
456 gl->comp_range.location = compRange.location;
457 gl->comp_range.length = compRange.length;
459 while (++glyphIndex < numberOfGlyphs)
460 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
464 for (i = 0; i < range.length; i++)
465 permutation[range.location + i] = NSMaxRange (range) - i - 1;
467 /* Then fill the remaining members. */
468 glyphIndex = prevGlyphIndex = 0;
469 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
472 if (!RIGHT_TO_LEFT_P)
479 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
480 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
481 inTextContainer:textContainer rectCount:&nrects];
483 totalAdvance = NSMaxX (glyphRects[0]);
486 for (i = 0; i < used; i++)
488 struct mac_glyph_layout *gl;
490 NSUInteger nextGlyphIndex;
495 if (!RIGHT_TO_LEFT_P)
496 gl = glyph_layouts + i;
499 NSUInteger dest = permutation[i];
501 gl = glyph_layouts + dest;
504 CFIndex tmp = gl->string_index;
506 gl->string_index = glyph_layouts[i].string_index;
507 glyph_layouts[i].string_index = tmp;
510 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
512 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
513 gl->baseline_delta = spaceLocation.y - location.y;
515 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
518 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
521 if (!RIGHT_TO_LEFT_P)
525 if (prevGlyphIndex == 0)
526 glyphRange = NSMakeRange (0, nextGlyphIndex);
528 glyphRange = NSMakeRange (glyphIndex,
529 nextGlyphIndex - glyphIndex);
532 rectArrayForGlyphRange:glyphRange
533 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
534 inTextContainer:textContainer rectCount:&nrects];
535 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
536 gl->advance_delta = location.x - totalAdvance;
537 gl->advance = maxX - totalAdvance;
544 if (nextGlyphIndex == numberOfGlyphs)
545 glyphRange = NSMakeRange (prevGlyphIndex,
546 numberOfGlyphs - prevGlyphIndex);
548 glyphRange = NSMakeRange (prevGlyphIndex,
549 glyphIndex + 1 - prevGlyphIndex);
552 rectArrayForGlyphRange:glyphRange
553 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
554 inTextContainer:textContainer rectCount:&nrects];
555 minX = min (NSMinX (glyphRects[0]), totalAdvance);
556 gl->advance = totalAdvance - minX;
558 gl->advance_delta = location.x - totalAdvance;
561 prevGlyphIndex = glyphIndex + 1;
562 glyphIndex = nextGlyphIndex;
568 #undef RIGHT_TO_LEFT_P
572 [textStorage release];
578 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
579 struct mac_glyph_layout *glyph_layouts,
582 return mac_font_shape_1 ([(NSFont *)font printerFont],
584 glyph_layouts, glyph_len, YES);
588 get_cgcolor(unsigned long idx, struct frame *f)
590 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
592 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
593 NSInteger noc = [nsColor numberOfComponents];
594 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
597 [nsColor getComponents: components];
598 cgColor = CGColorCreate (colorSpace, components);
603 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
605 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
606 CGContextSetFillColorWithColor (context, refcol_) ; \
607 CGColorRelease (refcol_); \
609 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
611 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
612 CGContextSetFillColorWithColor (context, refcol_); \
613 CGColorRelease (refcol_); \
615 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
617 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
618 CGContextSetStrokeColorWithColor (context, refcol_); \
619 CGColorRelease (refcol_); \
624 /* Mac font driver. */
630 /* characters to distinguish the charset from the others */
632 /* additional constraint by language */
635 CFCharacterSetRef cf_charset;
636 CFStringRef cf_charset_string;
637 } cf_charset_table[] =
638 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
639 { "iso8859-2", { 0x00A0, 0x010E }},
640 { "iso8859-3", { 0x00A0, 0x0108 }},
641 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
642 { "iso8859-5", { 0x00A0, 0x0401 }},
643 { "iso8859-6", { 0x00A0, 0x060C }},
644 { "iso8859-7", { 0x00A0, 0x0384 }},
645 { "iso8859-8", { 0x00A0, 0x05D0 }},
646 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
647 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
648 { "iso8859-11", { 0x00A0, 0x0E01 }},
649 { "iso8859-13", { 0x00A0, 0x201C }},
650 { "iso8859-14", { 0x00A0, 0x0174 }},
651 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
652 { "iso8859-16", { 0x00A0, 0x0218}},
653 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
654 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
655 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
656 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
657 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
658 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
659 { "cns11643.1992-3", { 0x201A9 }},
660 { "cns11643.1992-4", { 0x20057 }},
661 { "cns11643.1992-5", { 0x20000 }},
662 { "cns11643.1992-6", { 0x20003 }},
663 { "cns11643.1992-7", { 0x20055 }},
664 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
665 { "jisx0212.1990-0", { 0x4E44 }},
666 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
667 { "jisx0213.2000-2", { 0xFA49 }},
668 { "jisx0213.2004-1", { 0x20B9F }},
669 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
670 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
671 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
672 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
673 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
674 { "unicode-sip", { 0x20000 }},
678 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
681 CFStringRef language;
682 CFStringRef font_names[3];
683 } macfont_language_default_font_names[] = {
684 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
685 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
687 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
688 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
690 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
691 CFSTR ("STXihei"), /* 10.4 - 10.5 */
693 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
694 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
700 static CGFloat macfont_antialias_threshold;
703 macfont_update_antialias_threshold (void)
709 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
710 kCFPreferencesCurrentApplication,
713 macfont_antialias_threshold = threshold;
716 static inline Lisp_Object
717 macfont_intern_prop_cfstring (CFStringRef cfstring)
719 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
721 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
724 static inline CFIndex
725 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
736 unichars[0] = (c >> 10) + 0xD800;
737 unichars[1] = (c & 0x3FF) + 0xDC00;
744 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
745 CTFontSymbolicTraits *sym_traits)
749 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
750 OS X 10.6 when the value is greater than or equal to 1 << 31. */
751 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
753 *sym_traits = (CTFontSymbolicTraits) sint64_value;
762 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
763 Lisp_Object spec_or_entity)
766 CFDictionaryRef dict;
770 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
773 ASET (spec_or_entity, FONT_FAMILY_INDEX,
774 macfont_intern_prop_cfstring (str));
777 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
781 enum font_property_index index;
785 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
786 {{-0.4, 50}, /* light */
787 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
788 {0, 100}, /* normal */
789 {0.24, 140}, /* (semi-bold + normal) / 2 */
790 {0.4, 200}, /* bold */
791 {CGFLOAT_MAX, CGFLOAT_MAX}}},
792 {FONT_SLANT_INDEX, kCTFontSlantTrait,
793 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
794 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
795 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
798 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
800 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
801 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
803 CGPoint *point = numeric_traits[i].points;
805 while (point->x < floatval)
807 if (point == numeric_traits[i].points)
809 else if (point->x == CGFLOAT_MAX)
811 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
812 * ((point->y - (point - 1)->y)
813 / (point->x - (point - 1)->x)));
814 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
815 make_number (lround (floatval)));
819 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
822 CTFontSymbolicTraits sym_traits;
825 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
826 spacing = (sym_traits & kCTFontTraitMonoSpace
827 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
828 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
833 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
834 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
835 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
837 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
843 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
844 CTFontSymbolicTraits synth_sym_traits)
847 CFDictionaryRef dict;
848 CTFontSymbolicTraits sym_traits = 0;
851 entity = font_make_entity ();
853 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
854 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
856 macfont_store_descriptor_attributes (desc, entity);
858 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
861 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
864 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
867 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
868 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
869 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
870 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
871 font_put_extra (entity, QCfont_entity,
872 make_save_ptr_int ((void *) name, sym_traits));
873 if (synth_sym_traits & kCTFontTraitItalic)
874 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
875 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
876 if (synth_sym_traits & kCTFontTraitBold)
877 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
878 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
879 if (synth_sym_traits & kCTFontTraitMonoSpace)
880 ASET (entity, FONT_SPACING_INDEX,
881 make_number (FONT_SPACING_SYNTHETIC_MONO));
886 /* Cache for font family name symbols vs CFStrings. A value of nil
887 means the cache has been invalidated. Otherwise the value is a Lisp
888 hash table whose keys are symbols and the value for a key is either
889 nil (no corresponding family name) or a Lisp save value wrapping the
890 corresponding family name in CFString. */
892 static Lisp_Object macfont_family_cache;
895 macfont_invalidate_family_cache (void)
897 if (HASH_TABLE_P (macfont_family_cache))
899 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
900 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
902 for (i = 0; i < size; ++i)
903 if (!NILP (HASH_HASH (h, i)))
905 Lisp_Object value = HASH_VALUE (h, i);
907 if (SAVE_VALUEP (value))
908 CFRelease (XSAVE_POINTER (value, 0));
910 macfont_family_cache = Qnil;
915 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
917 if (HASH_TABLE_P (macfont_family_cache))
919 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
920 ptrdiff_t i = hash_lookup (h, symbol, NULL);
924 Lisp_Object value = HASH_VALUE (h, i);
926 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
936 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
938 struct Lisp_Hash_Table *h;
943 if (!HASH_TABLE_P (macfont_family_cache))
944 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
946 h = XHASH_TABLE (macfont_family_cache);
947 i = hash_lookup (h, symbol, &hash);
948 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
951 Lisp_Object old_value = HASH_VALUE (h, i);
953 if (SAVE_VALUEP (old_value))
954 CFRelease (XSAVE_POINTER (old_value, 0));
955 set_hash_value_slot (h, i, value);
958 hash_put (h, symbol, value, hash);
961 /* Cache of all the available font family names except "LastResort"
962 and those start with ".". NULL means the cache has been invalidated.
963 Otherwise, the value is CFArray of CFStrings and the elements are
964 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
965 OS X 10.6 and later). */
967 static CFArrayRef macfont_available_families_cache = NULL;
970 macfont_invalidate_available_families_cache (void)
972 if (macfont_available_families_cache)
974 CFRelease (macfont_available_families_cache);
975 macfont_available_families_cache = NULL;
980 macfont_handle_font_change_notification (CFNotificationCenterRef center,
982 CFStringRef name, const void *object,
983 CFDictionaryRef userInfo)
985 macfont_invalidate_family_cache ();
986 macfont_invalidate_available_families_cache ();
990 macfont_init_font_change_handler (void)
992 static bool initialized = false;
998 CFNotificationCenterAddObserver
999 (CFNotificationCenterGetLocalCenter (), NULL,
1000 macfont_handle_font_change_notification,
1001 kCTFontManagerRegisteredFontsChangedNotification,
1002 NULL, CFNotificationSuspensionBehaviorCoalesce);
1006 macfont_copy_available_families_cache (void)
1008 macfont_init_font_change_handler ();
1010 if (macfont_available_families_cache == NULL)
1011 macfont_available_families_cache = mac_font_create_available_families ();
1013 return (macfont_available_families_cache
1014 ? CFRetain (macfont_available_families_cache) : NULL);
1018 macfont_create_family_with_symbol (Lisp_Object symbol)
1020 CFStringRef result = NULL, family_name;
1021 CFDictionaryRef attributes = NULL;
1022 CTFontDescriptorRef pat_desc = NULL;
1024 if (macfont_get_family_cache_if_present (symbol, &result))
1025 return result ? CFRetain (result) : NULL;
1027 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1031 CFDictionaryCreate (NULL,
1032 (const void **) &kCTFontFamilyNameAttribute,
1033 (const void **) &family_name, 1,
1034 &kCFTypeDictionaryKeyCallBacks,
1035 &kCFTypeDictionaryValueCallBacks);
1036 CFRelease (family_name);
1040 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1041 CFRelease (attributes);
1045 CTFontDescriptorRef desc =
1046 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1051 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1054 macfont_set_family_cache (symbol, result);
1055 CFRelease (pat_desc);
1061 #define WIDTH_FRAC_BITS (4)
1062 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1064 struct macfont_metrics
1066 unsigned char lbearing_low, rbearing_low;
1067 signed lbearing_high : 4, rbearing_high : 4;
1068 unsigned char ascent_low, descent_low;
1069 signed ascent_high : 4, descent_high : 4;
1071 /* These two members are used for fixed-point representation of
1072 glyph width. The `width_int' member is an integer that is
1073 closest to the width. The `width_frac' member is the fractional
1074 adjustment representing a value in [-.5, .5], multiplied by
1075 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1076 the advance delta for centering instead of the glyph width. */
1077 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1080 #define METRICS_VALUE(metrics, member) \
1081 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1082 #define METRICS_SET_VALUE(metrics, member, value) \
1083 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1084 (metrics)->member##_high = tmp >> 8;} while (0)
1088 METRICS_INVALID = -1, /* metrics entry is invalid */
1089 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1092 #define METRICS_STATUS(metrics) \
1093 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1094 #define METRICS_SET_STATUS(metrics, status) \
1095 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1096 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1098 #define METRICS_NCOLS_PER_ROW (128)
1099 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1100 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1103 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1104 struct font_metrics *metrics, CGFloat *advance_delta,
1105 int force_integral_p)
1107 struct macfont_info *macfont_info = (struct macfont_info *) font;
1108 CTFontRef macfont = macfont_info->macfont;
1110 struct macfont_metrics *cache;
1113 row = glyph / METRICS_NCOLS_PER_ROW;
1114 col = glyph % METRICS_NCOLS_PER_ROW;
1115 if (row >= macfont_info->metrics_nrows)
1117 macfont_info->metrics =
1118 xrealloc (macfont_info->metrics,
1119 sizeof (struct macfont_metrics *) * (row + 1));
1120 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1121 (sizeof (struct macfont_metrics *)
1122 * (row + 1 - macfont_info->metrics_nrows)));
1123 macfont_info->metrics_nrows = row + 1;
1125 if (macfont_info->metrics[row] == NULL)
1127 struct macfont_metrics *new;
1130 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1131 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1132 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1133 macfont_info->metrics[row] = new;
1135 cache = macfont_info->metrics[row] + col;
1137 if (METRICS_STATUS (cache) == METRICS_INVALID)
1141 if (macfont_info->screen_font)
1142 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1144 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1146 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1147 advance delta value. */
1148 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1149 fwidth = (font->pixel_size - fwidth) / 2;
1150 cache->width_int = lround (fwidth);
1151 cache->width_frac = lround ((fwidth - cache->width_int)
1152 * WIDTH_FRAC_SCALE);
1153 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1155 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1156 width = font->pixel_size;
1158 width = cache->width_int;
1162 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1164 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1166 if (macfont_info->synthetic_italic_p)
1168 /* We assume the members a, b, c, and d in
1169 synthetic_italic_atfm are non-negative. */
1171 CGPointApplyAffineTransform (bounds.origin,
1172 synthetic_italic_atfm);
1174 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1176 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1178 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1180 bounds = CGRectInset (bounds, d, d);
1182 switch (macfont_info->spacing)
1184 case MACFONT_SPACING_PROPORTIONAL:
1185 bounds.origin.x += - (cache->width_frac
1186 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1188 case MACFONT_SPACING_MONO:
1190 case MACFONT_SPACING_SYNTHETIC_MONO:
1191 bounds.origin.x += (cache->width_int
1192 + (cache->width_frac
1193 / (CGFloat) WIDTH_FRAC_SCALE));
1196 if (bounds.size.width > 0)
1198 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1199 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1200 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1202 bounds = CGRectIntegral (bounds);
1203 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1204 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1205 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1206 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1208 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1209 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1210 metrics->width = width;
1211 metrics->ascent = METRICS_VALUE (cache, ascent);
1212 metrics->descent = METRICS_VALUE (cache, descent);
1217 switch (macfont_info->spacing)
1219 case MACFONT_SPACING_PROPORTIONAL:
1220 *advance_delta = (force_integral_p ? 0
1221 : - (cache->width_frac
1222 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1224 case MACFONT_SPACING_MONO:
1227 case MACFONT_SPACING_SYNTHETIC_MONO:
1228 *advance_delta = (force_integral_p ? cache->width_int
1230 + (cache->width_frac
1231 / (CGFloat) WIDTH_FRAC_SCALE)));
1239 static CFMutableDictionaryRef macfont_cache_dictionary;
1241 /* Threshold used in row_nkeys_or_perm. This must be less than or
1242 equal to the number of rows that are invalid as BMP (i.e., from
1243 U+D800 to U+DFFF). */
1244 #define ROW_PERM_OFFSET (8)
1246 /* The number of glyphs that can be stored in a value for a single
1247 entry of CFDictionary. */
1248 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1250 struct macfont_cache
1252 int reference_count;
1253 CFCharacterSetRef cf_charset;
1255 /* The cached glyph for a BMP character c is stored in
1256 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1257 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1258 unsigned char row_nkeys_or_perm[256];
1261 /* Number of rows for which the BMP cache is allocated so far.
1262 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1265 /* The cached glyph for a character c is stored as the (c %
1266 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1267 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1268 not stored here if row_nkeys_or_perm[c / 256] >=
1270 CFMutableDictionaryRef dictionary;
1274 /* UVS (Unicode Variation Sequence) subtable data, which is of
1275 type CFDataRef if available. NULL means it is not initialized
1276 yet. kCFNull means the subtable is not found and there is no
1277 suitable fallback table for this font. */
1280 /* Character collection specifying the destination of the mapping
1281 provided by `table' above. If `table' is obtained from the UVS
1282 subtable in the font cmap table, then the value of this member
1283 should be kCTCharacterCollectionIdentityMapping. */
1284 CTCharacterCollection collection;
1288 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1289 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1290 static void macfont_release_cache (struct macfont_cache *);
1291 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1292 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1293 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1294 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1295 CTCharacterCollection, CGFontIndex);
1296 static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
1298 static struct macfont_cache *
1299 macfont_lookup_cache (CFStringRef key)
1301 struct macfont_cache *cache;
1303 if (macfont_cache_dictionary == NULL)
1305 macfont_cache_dictionary =
1306 CFDictionaryCreateMutable (NULL, 0,
1307 &kCFTypeDictionaryKeyCallBacks, NULL);
1311 cache = ((struct macfont_cache *)
1312 CFDictionaryGetValue (macfont_cache_dictionary, key));
1316 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1320 cache = xzalloc (sizeof (struct macfont_cache));
1321 /* Treat the LastResort font as if it contained glyphs for
1322 all characters. This may look too rough, but neither
1323 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1324 for this font is correct for non-BMP characters on Mac OS
1326 if (CFEqual (key, CFSTR ("LastResort")))
1328 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1331 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1333 if (cache->cf_charset == NULL)
1334 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1335 CFDictionaryAddValue (macfont_cache_dictionary, key,
1336 (const void *) cache);
1337 CFRelease (macfont);
1344 static struct macfont_cache *
1345 macfont_retain_cache (struct macfont_cache *cache)
1347 cache->reference_count++;
1353 macfont_release_cache (struct macfont_cache *cache)
1355 if (--cache->reference_count == 0)
1359 for (i = 0; i < cache->glyph.nrows; i++)
1360 xfree (cache->glyph.matrix[i]);
1361 xfree (cache->glyph.matrix);
1362 if (cache->glyph.dictionary)
1363 CFRelease (cache->glyph.dictionary);
1364 memset (&cache->glyph, 0, sizeof (cache->glyph));
1365 if (cache->uvs.table)
1366 CFRelease (cache->uvs.table);
1367 memset (&cache->uvs, 0, sizeof (cache->uvs));
1371 static CFCharacterSetRef
1372 macfont_get_cf_charset (struct font *font)
1374 struct macfont_info *macfont_info = (struct macfont_info *) font;
1376 return macfont_info->cache->cf_charset;
1379 static CFCharacterSetRef
1380 macfont_get_cf_charset_for_name (CFStringRef name)
1382 struct macfont_cache *cache = macfont_lookup_cache (name);
1384 return cache->cf_charset;
1388 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1390 struct macfont_info *macfont_info = (struct macfont_info *) font;
1391 CTFontRef macfont = macfont_info->macfont;
1392 struct macfont_cache *cache = macfont_info->cache;
1394 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1397 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1399 if (nkeys_or_perm < ROW_PERM_OFFSET)
1401 UniChar unichars[256], ch;
1405 dispatch_queue_t queue;
1406 dispatch_group_t group = NULL;
1410 CFMutableDictionaryRef dictionary;
1411 uintptr_t key, value;
1415 if (cache->glyph.dictionary == NULL)
1416 cache->glyph.dictionary =
1417 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1418 dictionary = cache->glyph.dictionary;
1419 key = c / NGLYPHS_IN_VALUE;
1420 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1421 value = ((uintptr_t)
1422 CFDictionaryGetValue (dictionary, (const void *) key));
1423 glyph = (value >> nshifts);
1427 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1430 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1432 glyph = kCGFontIndexInvalid;
1435 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1436 value |= ((uintptr_t) glyph << nshifts);
1437 CFDictionarySetValue (dictionary, (const void *) key,
1438 (const void *) value);
1444 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1445 group = dispatch_group_create ();
1446 dispatch_group_async (group, queue, ^{
1449 nkeys = nkeys_or_perm;
1450 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1451 if (CFDictionaryContainsKey (dictionary,
1452 (const void *) key))
1454 CFDictionaryRemoveValue (dictionary,
1455 (const void *) key);
1463 for (i = 0; i < 256; i++)
1466 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1467 unichars[len++] = ch;
1470 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1473 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1476 int next = unichars[len - 1] % 256;
1479 glyphs[i] = kCGFontIndexInvalid;
1482 glyphs[i] = glyphs[len];
1489 glyphs[i] = kCGFontIndexInvalid;
1491 nrows = cache->glyph.nrows;
1492 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1493 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1495 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1496 sizeof (CGGlyph *) * nrows);
1497 cache->glyph.matrix[nrows - 1] = glyphs;
1498 cache->glyph.nrows = nrows;
1502 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1503 dispatch_release (group);
1507 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1511 uintptr_t key, value;
1515 if (cache->glyph.dictionary == NULL)
1516 cache->glyph.dictionary =
1517 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1518 key = c / NGLYPHS_IN_VALUE;
1519 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1520 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1521 (const void *) key);
1522 glyph = (value >> nshifts);
1525 UniChar unichars[2];
1527 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1529 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1532 glyph = kCGFontIndexInvalid;
1534 value |= ((uintptr_t) glyph << nshifts);
1535 CFDictionarySetValue (cache->glyph.dictionary,
1536 (const void *) key, (const void *) value);
1544 macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1547 struct macfont_info *macfont_info = (struct macfont_info *) font;
1548 CTFontRef macfont = macfont_info->macfont;
1551 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1555 macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1557 struct macfont_info *macfont_info = (struct macfont_info *) font;
1558 CTFontRef macfont = macfont_info->macfont;
1559 struct macfont_cache *cache = macfont_info->cache;
1560 CFDataRef result = NULL;
1562 if (cache->uvs.table == NULL)
1564 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1565 CTCharacterCollection uvs_collection =
1566 kCTCharacterCollectionIdentityMapping;
1568 if (uvs_table == NULL
1569 && mac_font_get_glyph_for_cid (macfont,
1570 kCTCharacterCollectionAdobeJapan1,
1571 6480) != kCGFontIndexInvalid)
1573 /* If the glyph for U+4E55 is accessible via its CID 6480,
1574 then we use the Adobe-Japan1 UVS table, which maps a
1575 variation sequence to a CID, as a fallback. */
1576 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1578 if (mac_uvs_table_adobe_japan1 == NULL)
1579 mac_uvs_table_adobe_japan1 =
1580 CFDataCreateWithBytesNoCopy (NULL,
1581 mac_uvs_table_adobe_japan1_bytes,
1582 sizeof (mac_uvs_table_adobe_japan1_bytes),
1584 if (mac_uvs_table_adobe_japan1)
1586 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1587 uvs_collection = kCTCharacterCollectionAdobeJapan1;
1590 if (uvs_table == NULL)
1591 cache->uvs.table = kCFNull;
1593 cache->uvs.table = uvs_table;
1594 cache->uvs.collection = uvs_collection;
1597 if (cache->uvs.table != kCFNull)
1599 result = cache->uvs.table;
1600 *collection = cache->uvs.collection;
1606 static Lisp_Object macfont_get_cache (struct frame *);
1607 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1608 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1609 static Lisp_Object macfont_list_family (struct frame *);
1610 static void macfont_free_entity (Lisp_Object);
1611 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1612 static void macfont_close (struct font *);
1613 static int macfont_has_char (Lisp_Object, int);
1614 static unsigned macfont_encode_char (struct font *, int);
1615 static void macfont_text_extents (struct font *, unsigned int *, int,
1616 struct font_metrics *);
1617 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1618 static Lisp_Object macfont_shape (Lisp_Object);
1619 static int macfont_variation_glyphs (struct font *, int c,
1620 unsigned variations[256]);
1621 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1623 static struct font_driver macfont_driver =
1625 LISP_INITIALLY_ZERO, /* Qmac_ct */
1626 0, /* case insensitive */
1630 macfont_list_family,
1631 macfont_free_entity,
1634 NULL, /* prepare_face */
1635 NULL, /* done_face */
1637 macfont_encode_char,
1638 macfont_text_extents,
1640 NULL, /* get_bitmap */
1641 NULL, /* free_bitmap */
1642 NULL, /* anchor_point */
1643 NULL, /* otf_capability */
1644 NULL, /* otf_drive */
1645 NULL, /* start_for_frame */
1646 NULL, /* end_for_frame */
1649 macfont_variation_glyphs,
1650 macfont_filter_properties,
1654 macfont_get_cache (struct frame * f)
1656 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1658 return (dpyinfo->name_list_element);
1662 macfont_get_charset (Lisp_Object registry)
1664 char *str = SSDATA (SYMBOL_NAME (registry));
1665 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1669 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1673 else if (str[i] == '*')
1680 regexp = make_unibyte_string (re, j);
1681 for (i = 0; cf_charset_table[i].name; i++)
1682 if (fast_c_string_match_ignore_case
1683 (regexp, cf_charset_table[i].name,
1684 strlen (cf_charset_table[i].name)) >= 0)
1686 if (! cf_charset_table[i].name)
1688 if (! cf_charset_table[i].cf_charset)
1690 int *uniquifier = cf_charset_table[i].uniquifier;
1691 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1694 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1698 for (j = 0; uniquifier[j]; j++)
1700 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1702 CFCharacterSetAddCharactersInRange (charset,
1703 CFRangeMake (uniquifier[j], 1));
1706 string = CFStringCreateWithCharacters (NULL, unichars, count);
1709 CFRelease (charset);
1712 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1714 CFRelease (charset);
1715 /* CFCharacterSetCreateWithCharactersInString does not handle
1716 surrogate pairs properly as of Mac OS X 10.5. */
1717 cf_charset_table[i].cf_charset_string = string;
1725 unsigned int script_tag, langsys_tag;
1727 unsigned int *features[2];
1730 #define OTF_SYM_TAG(SYM, TAG) \
1732 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1733 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1736 #define OTF_TAG_STR(TAG, P) \
1738 (P)[0] = (char) (TAG >> 24); \
1739 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1740 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1741 (P)[3] = (char) (TAG & 0xFF); \
1745 static struct OpenTypeSpec *
1746 macfont_get_open_type_spec (Lisp_Object otf_spec)
1748 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1755 spec->script = XCAR (otf_spec);
1756 if (! NILP (spec->script))
1758 OTF_SYM_TAG (spec->script, spec->script_tag);
1759 val = assq_no_quit (spec->script, Votf_script_alist);
1760 if (CONSP (val) && SYMBOLP (XCDR (val)))
1761 spec->script = XCDR (val);
1763 spec->script = Qnil;
1766 spec->script_tag = 0x44464C54; /* "DFLT" */
1767 otf_spec = XCDR (otf_spec);
1768 spec->langsys_tag = 0;
1769 if (! NILP (otf_spec))
1771 val = XCAR (otf_spec);
1773 OTF_SYM_TAG (val, spec->langsys_tag);
1774 otf_spec = XCDR (otf_spec);
1776 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1777 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1781 val = XCAR (otf_spec);
1784 len = Flength (val);
1786 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1788 : malloc (XINT (len) * sizeof *spec->features[i]));
1789 if (! spec->features[i])
1791 if (i > 0 && spec->features[0])
1792 free (spec->features[0]);
1796 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1798 if (NILP (XCAR (val)))
1804 OTF_SYM_TAG (XCAR (val), tag);
1805 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1808 spec->nfeatures[i] = j;
1813 static CFMutableDictionaryRef
1814 macfont_create_attributes_with_spec (Lisp_Object spec)
1816 Lisp_Object tmp, extra;
1817 CFMutableArrayRef langarray = NULL;
1818 CFCharacterSetRef charset = NULL;
1819 CFStringRef charset_string = NULL;
1820 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1821 Lisp_Object script = Qnil;
1822 Lisp_Object registry;
1823 int cf_charset_idx, i;
1824 struct OpenTypeSpec *otspec = NULL;
1826 enum font_property_index index;
1829 } numeric_traits[] =
1830 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1831 {{-0.4, 50}, /* light */
1832 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1833 {0, 100}, /* normal */
1834 {0.24, 140}, /* (semi-bold + normal) / 2 */
1835 {0.4, 200}, /* bold */
1836 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1837 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1838 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1839 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1840 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1842 registry = AREF (spec, FONT_REGISTRY_INDEX);
1844 || EQ (registry, Qascii_0)
1845 || EQ (registry, Qiso10646_1)
1846 || EQ (registry, Qunicode_bmp))
1847 cf_charset_idx = -1;
1852 cf_charset_idx = macfont_get_charset (registry);
1853 if (cf_charset_idx < 0)
1855 charset = cf_charset_table[cf_charset_idx].cf_charset;
1856 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1857 lang = cf_charset_table[cf_charset_idx].lang;
1860 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1863 CFArrayAppendValue (langarray, lang);
1867 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1868 CONSP (extra); extra = XCDR (extra))
1870 Lisp_Object key, val;
1873 key = XCAR (tmp), val = XCDR (tmp);
1874 if (EQ (key, QClang))
1877 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1882 for (; CONSP (val); val = XCDR (val))
1883 if (SYMBOLP (XCAR (val)))
1886 cfstring_create_with_string_noencode (SYMBOL_NAME
1891 CFArrayAppendValue (langarray, lang);
1895 else if (EQ (key, QCotf))
1897 otspec = macfont_get_open_type_spec (val);
1900 script = otspec->script;
1902 else if (EQ (key, QCscript))
1906 if (! NILP (script) && ! charset)
1908 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1910 if (CONSP (chars) && CONSP (CDR (chars)))
1912 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1913 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1915 if (! string || !cs)
1923 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1924 if (CHARACTERP (XCAR (chars)))
1926 UniChar unichars[2];
1928 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1930 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1932 CFStringAppendCharacters (string, unichars, count);
1933 CFCharacterSetAddCharactersInRange (cs, range);
1936 /* CFCharacterSetCreateWithCharactersInString does not
1937 handle surrogate pairs properly as of Mac OS X 10.5. */
1938 charset_string = string;
1942 attributes = CFDictionaryCreateMutable (NULL, 0,
1943 &kCFTypeDictionaryKeyCallBacks,
1944 &kCFTypeDictionaryValueCallBacks);
1948 tmp = AREF (spec, FONT_FAMILY_INDEX);
1949 if (SYMBOLP (tmp) && ! NILP (tmp))
1951 CFStringRef family = macfont_create_family_with_symbol (tmp);
1955 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1960 traits = CFDictionaryCreateMutable (NULL, 4,
1961 &kCFTypeDictionaryKeyCallBacks,
1962 &kCFTypeDictionaryValueCallBacks);
1966 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1968 tmp = AREF (spec, numeric_traits[i].index);
1971 CGPoint *point = numeric_traits[i].points;
1972 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1975 while (point->y < floatval)
1977 if (point == numeric_traits[i].points)
1979 else if (point->y == CGFLOAT_MAX)
1981 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1982 * ((point->x - (point - 1)->x)
1983 / (point->y - (point - 1)->y)));
1986 else if (floatval < -1.0)
1988 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1991 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1995 if (CFDictionaryGetCount (traits))
1996 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
1999 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2002 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2005 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2012 CFRelease (attributes);
2017 if (langarray) CFRelease (langarray);
2018 if (charset && cf_charset_idx < 0) CFRelease (charset);
2019 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2020 if (traits) CFRelease (traits);
2023 if (otspec->nfeatures[0] > 0)
2024 free (otspec->features[0]);
2025 if (otspec->nfeatures[1] > 0)
2026 free (otspec->features[1]);
2034 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2035 CFCharacterSetRef charset,
2037 CFArrayRef languages)
2039 Boolean result = true;
2041 if (charset || VECTORP (chars))
2043 CFCharacterSetRef desc_charset =
2044 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2046 if (desc_charset == NULL)
2051 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2052 else /* VECTORP (chars) */
2056 for (j = 0; j < ASIZE (chars); j++)
2057 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2058 && CFCharacterSetIsLongCharacterMember (desc_charset,
2059 XFASTINT (AREF (chars, j))))
2061 if (j == ASIZE (chars))
2064 CFRelease (desc_charset);
2067 if (result && languages)
2068 result = mac_font_descriptor_supports_languages (desc, languages);
2074 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2075 CTFontSymbolicTraits sym_traits2)
2077 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2080 /* We prefer synthetic bold of italic to synthetic italic of bold
2081 when both bold and italic are available but bold-italic is not
2083 if (diff & kCTFontTraitBold)
2084 distance |= (1 << 0);
2085 if (diff & kCTFontTraitItalic)
2086 distance |= (1 << 1);
2087 if (diff & kCTFontTraitMonoSpace)
2088 distance |= (1 << 2);
2094 macfont_closest_traits_index_p (CFArrayRef traits_array,
2095 CTFontSymbolicTraits target,
2098 CFIndex i, count = CFArrayGetCount (traits_array);
2099 CTFontSymbolicTraits traits;
2102 traits = ((CTFontSymbolicTraits) (uintptr_t)
2103 CFArrayGetValueAtIndex (traits_array, index));
2104 my_distance = macfont_traits_distance (target, traits);
2106 for (i = 0; i < count; i++)
2109 traits = ((CTFontSymbolicTraits) (uintptr_t)
2110 CFArrayGetValueAtIndex (traits_array, i));
2111 if (macfont_traits_distance (target, traits) < my_distance)
2119 macfont_list (struct frame *f, Lisp_Object spec)
2121 Lisp_Object val = Qnil, family, extra;
2123 CFStringRef family_name = NULL;
2124 CFMutableDictionaryRef attributes = NULL, traits;
2125 Lisp_Object chars = Qnil;
2127 CTFontSymbolicTraits synth_sym_traits = 0;
2128 CFArrayRef families;
2129 CFIndex families_count;
2130 CFCharacterSetRef charset = NULL;
2131 CFArrayRef languages = NULL;
2135 family = AREF (spec, FONT_FAMILY_INDEX);
2136 if (! NILP (family))
2138 family_name = macfont_create_family_with_symbol (family);
2139 if (family_name == NULL)
2143 attributes = macfont_create_attributes_with_spec (spec);
2147 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2149 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2150 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2152 traits = ((CFMutableDictionaryRef)
2153 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2155 n = FONT_SLANT_NUMERIC (spec);
2156 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2158 synth_sym_traits |= kCTFontTraitItalic;
2160 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2163 n = FONT_WEIGHT_NUMERIC (spec);
2164 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2166 synth_sym_traits |= kCTFontTraitBold;
2168 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2172 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2174 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2176 if (CFStringHasPrefix (language, CFSTR ("ja"))
2177 || CFStringHasPrefix (language, CFSTR ("ko"))
2178 || CFStringHasPrefix (language, CFSTR ("zh")))
2179 synth_sym_traits |= kCTFontTraitMonoSpace;
2182 /* Create array of families. */
2184 families = CFArrayCreate (NULL, (const void **) &family_name,
2185 1, &kCFTypeArrayCallBacks);
2188 CFStringRef pref_family;
2189 CFIndex families_count, pref_family_index = -1;
2191 families = macfont_copy_available_families_cache ();
2192 if (families == NULL)
2195 families_count = CFArrayGetCount (families);
2197 /* Move preferred family to the front if exists. */
2199 mac_font_create_preferred_family_for_attributes (attributes);
2203 CFArrayGetFirstIndexOfValue (families,
2204 CFRangeMake (0, families_count),
2206 CFRelease (pref_family);
2208 if (pref_family_index > 0)
2210 CFMutableArrayRef mutable_families =
2211 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2213 if (mutable_families)
2215 CFArrayAppendValue (mutable_families,
2216 CFArrayGetValueAtIndex (families,
2217 pref_family_index));
2218 CFArrayAppendArray (mutable_families, families,
2219 CFRangeMake (0, pref_family_index));
2220 if (pref_family_index + 1 < families_count)
2221 CFArrayAppendArray (mutable_families, families,
2222 CFRangeMake (pref_family_index + 1,
2224 - (pref_family_index + 1)));
2225 CFRelease (families);
2226 families = mutable_families;
2231 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2235 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2239 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2242 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2243 if (CONSP (val) && VECTORP (XCDR (val)))
2251 CFRetain (languages);
2252 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2256 extra = AREF (spec, FONT_EXTRA_INDEX);
2257 families_count = CFArrayGetCount (families);
2258 for (i = 0; i < families_count; i++)
2260 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2261 CTFontDescriptorRef pat_desc;
2263 CFIndex descs_count;
2264 CFMutableArrayRef filtered_descs, traits_array;
2268 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2270 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2274 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2275 10.7 returns NULL if pat_desc represents the LastResort font.
2276 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2277 trailing "s") for such a font. */
2278 if (!CFEqual (family_name, CFSTR ("LastResort")))
2279 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2282 CTFontDescriptorRef lr_desc =
2283 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2286 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2287 &kCFTypeArrayCallBacks);
2288 CFRelease (lr_desc);
2293 CFRelease (pat_desc);
2297 descs_count = CFArrayGetCount (descs);
2298 if (descs_count == 0
2299 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2308 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2309 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2310 for (j = 0; j < descs_count; j++)
2312 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2313 CFDictionaryRef dict;
2315 CTFontSymbolicTraits sym_traits;
2317 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2321 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2324 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2328 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2329 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2330 != (spacing >= FONT_SPACING_MONO)))
2333 /* Don't use a color bitmap font unless its family is
2334 explicitly specified. */
2335 if ((sym_traits & kCTFontTraitColorGlyphs) && NILP (family))
2339 && !macfont_supports_charset_and_languages_p (desc, charset,
2343 CFArrayAppendValue (filtered_descs, desc);
2344 CFArrayAppendValue (traits_array,
2345 (const void *) (uintptr_t) sym_traits);
2349 descs = filtered_descs;
2350 descs_count = CFArrayGetCount (descs);
2352 for (j = 0; j < descs_count; j++)
2354 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2355 CTFontSymbolicTraits sym_traits =
2356 ((CTFontSymbolicTraits) (uintptr_t)
2357 CFArrayGetValueAtIndex (traits_array, j));
2358 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2360 mask_min = ((synth_sym_traits ^ sym_traits)
2361 & (kCTFontTraitItalic | kCTFontTraitBold));
2362 if (FONT_SLANT_NUMERIC (spec) < 0)
2363 mask_min &= ~kCTFontTraitItalic;
2364 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2365 mask_min &= ~kCTFontTraitBold;
2367 mask_max = (synth_sym_traits & ~sym_traits);
2368 /* Synthetic bold does not work for bitmap-only fonts on Mac
2370 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2372 CFNumberRef format =
2373 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2377 uint32_t format_val;
2379 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2381 && format_val == kCTFontFormatBitmap)
2382 mask_max &= ~kCTFontTraitBold;
2386 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2388 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2389 mmask <= (mask_max & kCTFontTraitMonoSpace);
2390 mmask += kCTFontTraitMonoSpace)
2391 for (bmask = (mask_min & kCTFontTraitBold);
2392 bmask <= (mask_max & kCTFontTraitBold);
2393 bmask += kCTFontTraitBold)
2394 for (imask = (mask_min & kCTFontTraitItalic);
2395 imask <= (mask_max & kCTFontTraitItalic);
2396 imask += kCTFontTraitItalic)
2398 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2401 || macfont_closest_traits_index_p (traits_array,
2402 (sym_traits | synth),
2405 entity = macfont_descriptor_entity (desc, extra, synth);
2406 if (! NILP (entity))
2407 val = Fcons (entity, val);
2412 CFRelease (traits_array);
2416 CFRelease (families);
2417 val = Fnreverse (val);
2423 FONT_ADD_LOG ("macfont-list", spec, val);
2424 if (charset) CFRelease (charset);
2425 if (languages) CFRelease (languages);
2426 if (attributes) CFRelease (attributes);
2427 if (family_name) CFRelease (family_name);
2435 macfont_match (struct frame * frame, Lisp_Object spec)
2437 Lisp_Object entity = Qnil;
2438 CFMutableDictionaryRef attributes;
2439 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2443 attributes = macfont_create_attributes_with_spec (spec);
2446 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2447 CFRelease (attributes);
2451 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2452 CFRelease (pat_desc);
2456 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2462 FONT_ADD_LOG ("macfont-match", spec, entity);
2467 macfont_list_family (struct frame *frame)
2469 Lisp_Object list = Qnil;
2470 CFArrayRef families;
2474 families = macfont_copy_available_families_cache ();
2477 CFIndex i, count = CFArrayGetCount (families);
2479 for (i = 0; i < count; i++)
2480 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2481 CFRelease (families);
2490 macfont_free_entity (Lisp_Object entity)
2492 Lisp_Object val = assq_no_quit (QCfont_entity,
2493 AREF (entity, FONT_EXTRA_INDEX));
2494 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2502 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2504 Lisp_Object val, font_object;
2505 CFStringRef font_name;
2506 struct macfont_info *macfont_info = NULL;
2510 CTFontSymbolicTraits sym_traits;
2512 int len, i, total_width;
2514 CGFloat ascent, descent, leading;
2516 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2518 || XTYPE (XCDR (val)) != Lisp_Misc
2519 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2521 font_name = XSAVE_POINTER (XCDR (val), 0);
2522 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2524 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2529 macfont = CTFontCreateWithName (font_name, size, NULL);
2532 int fontsize = (int) [((NSFont *) macfont) pointSize];
2533 if (fontsize != size) size = fontsize;
2539 font_object = font_build_object (VECSIZE (struct macfont_info),
2540 Qmac_ct, entity, size);
2541 font = XFONT_OBJECT (font_object);
2542 font->pixel_size = size;
2543 font->driver = &macfont_driver;
2544 font->encoding_charset = font->repertory_charset = -1;
2548 macfont_info = (struct macfont_info *) font;
2549 macfont_info->macfont = macfont;
2550 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2552 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2553 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2554 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2557 macfont_info->screen_font = NULL;
2558 macfont_info->cache = macfont_lookup_cache (font_name);
2559 macfont_retain_cache (macfont_info->cache);
2560 macfont_info->metrics = NULL;
2561 macfont_info->metrics_nrows = 0;
2562 macfont_info->synthetic_italic_p = 0;
2563 macfont_info->synthetic_bold_p = 0;
2564 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2565 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2566 if (!(sym_traits & kCTFontTraitItalic)
2567 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2568 macfont_info->synthetic_italic_p = 1;
2569 if (!(sym_traits & kCTFontTraitBold)
2570 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2571 macfont_info->synthetic_bold_p = 1;
2572 if (sym_traits & kCTFontTraitMonoSpace)
2573 macfont_info->spacing = MACFONT_SPACING_MONO;
2574 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2575 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2576 == FONT_SPACING_SYNTHETIC_MONO))
2577 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2578 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2579 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2582 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2584 macfont_info->antialias =
2585 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2587 macfont_info->color_bitmap_p = 0;
2588 if (sym_traits & kCTFontTraitColorGlyphs)
2589 macfont_info->color_bitmap_p = 1;
2591 glyph = macfont_get_glyph_for_character (font, ' ');
2592 if (glyph != kCGFontIndexInvalid)
2593 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2595 /* dirty workaround */
2596 font->space_width = pixel_size;
2598 total_width = font->space_width;
2599 for (i = 1; i < 95; i++)
2601 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2602 if (glyph == kCGFontIndexInvalid)
2604 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2607 font->average_width = total_width / 95;
2609 font->average_width = font->space_width; /* XXX */
2611 if (!(macfont_info->screen_font
2612 && mac_screen_font_get_metrics (macfont_info->screen_font,
2613 &ascent, &descent, &leading)))
2615 CFStringRef family_name;
2617 ascent = CTFontGetAscent (macfont);
2618 descent = CTFontGetDescent (macfont);
2619 leading = CTFontGetLeading (macfont);
2620 /* AppKit and WebKit do some adjustment to the heights of
2621 Courier, Helvetica, and Times. */
2622 family_name = CTFontCopyFamilyName (macfont);
2625 if (CFEqual (family_name, CFSTR ("Courier"))
2626 || CFEqual (family_name, CFSTR ("Helvetica"))
2627 || CFEqual (family_name, CFSTR ("Times")))
2628 ascent += (ascent + descent) * .15f;
2629 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2634 CFRelease (family_name);
2637 font->ascent = ascent + 0.5f;
2638 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2639 if (CONSP (val) && !NILP (XCDR (val)))
2640 font->descent = descent + 0.5f;
2642 font->descent = descent + leading + 0.5f;
2643 font->height = font->ascent + font->descent;
2645 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2646 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2650 /* Unfortunately Xft doesn't provide a way to get minimum char
2651 width. So, we use space_width instead. */
2652 font->min_width = font->max_width = font->space_width; /* XXX */
2654 font->baseline_offset = 0;
2655 font->relative_compose = 0;
2656 font->default_ascent = 0;
2657 font->vertical_centering = 0;
2663 macfont_close (struct font *font)
2665 struct macfont_info *macfont_info = (struct macfont_info *) font;
2667 if (macfont_info->cache)
2672 CFRelease (macfont_info->macfont);
2673 CGFontRelease (macfont_info->cgfont);
2674 if (macfont_info->screen_font)
2675 CFRelease (macfont_info->screen_font);
2676 macfont_release_cache (macfont_info->cache);
2677 for (i = 0; i < macfont_info->metrics_nrows; i++)
2678 if (macfont_info->metrics[i])
2679 xfree (macfont_info->metrics[i]);
2680 if (macfont_info->metrics)
2681 xfree (macfont_info->metrics);
2682 macfont_info->cache = NULL;
2688 macfont_has_char (Lisp_Object font, int c)
2691 CFCharacterSetRef charset;
2694 if (FONT_ENTITY_P (font))
2699 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2701 name = XSAVE_POINTER (val, 0);
2702 charset = macfont_get_cf_charset_for_name (name);
2705 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2707 result = CFCharacterSetIsLongCharacterMember (charset, c);
2714 macfont_encode_char (struct font *font, int c)
2716 struct macfont_info *macfont_info = (struct macfont_info *) font;
2720 glyph = macfont_get_glyph_for_character (font, c);
2723 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2727 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2728 struct font_metrics *metrics)
2733 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2734 for (i = 1; i < nglyphs; i++)
2736 struct font_metrics m;
2737 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2742 if (width + m.lbearing < metrics->lbearing)
2743 metrics->lbearing = width + m.lbearing;
2744 if (width + m.rbearing > metrics->rbearing)
2745 metrics->rbearing = width + m.rbearing;
2746 if (m.ascent > metrics->ascent)
2747 metrics->ascent = m.ascent;
2748 if (m.descent > metrics->descent)
2749 metrics->descent = m.descent;
2756 metrics->width = width;
2760 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2761 bool with_background)
2763 struct frame * f = s->f;
2764 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2765 CGRect background_rect;
2766 CGPoint text_position;
2769 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2770 bool no_antialias_p =
2771 (NILP (ns_antialias_text)
2772 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2773 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2774 && font_size <= macfont_antialias_threshold));
2775 int len = to - from;
2776 struct face *face = s->face;
2777 CGContextRef context;
2781 if (with_background)
2782 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2783 s->width, FONT_HEIGHT (s->font));
2785 background_rect = CGRectNull;
2787 text_position = CGPointMake (x, -y);
2788 glyphs = xmalloc (sizeof (CGGlyph) * len);
2790 CGFloat advance_delta = 0;
2792 CGFloat total_width = 0;
2794 positions = xmalloc (sizeof (CGPoint) * len);
2795 for (i = 0; i < len; i++)
2799 glyphs[i] = s->char2b[from + i];
2800 width = (s->padding_p ? 1
2801 : macfont_glyph_extents (s->font, glyphs[i],
2802 NULL, &advance_delta,
2804 positions[i].x = total_width + advance_delta;
2806 total_width += width;
2810 context = [[NSGraphicsContext currentContext] graphicsPort];
2811 CGContextSaveGState (context);
2813 if (!CGRectIsNull (background_rect))
2815 if (s->hl == DRAW_MOUSE_FACE)
2817 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2819 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2821 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2822 CGContextFillRects (context, &background_rect, 1);
2825 if (macfont_info->cgfont)
2827 CGAffineTransform atfm;
2829 CGContextScaleCTM (context, 1, -1);
2830 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2831 if (macfont_info->synthetic_italic_p)
2832 atfm = synthetic_italic_atfm;
2834 atfm = CGAffineTransformIdentity;
2835 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2837 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2838 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2839 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2842 CGContextSetShouldAntialias (context, false);
2844 CGContextSetTextMatrix (context, atfm);
2845 CGContextSetTextPosition (context, text_position.x, text_position.y);
2847 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2848 if (macfont_info->color_bitmap_p
2849 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2850 && CTFontDrawGlyphs != NULL
2856 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2861 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2863 CGContextSetFont (context, macfont_info->cgfont);
2864 CGContextSetFontSize (context, font_size);
2865 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2872 CGContextRestoreGState (context);
2880 macfont_shape (Lisp_Object lgstring)
2882 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2883 struct macfont_info *macfont_info = (struct macfont_info *) font;
2884 CTFontRef macfont = macfont_info->macfont;
2885 ptrdiff_t glyph_len, len, i, j;
2888 CFIndex *nonbmp_indices;
2891 struct mac_glyph_layout *glyph_layouts;
2893 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2895 for (i = 0; i < glyph_len; i++)
2897 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2901 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2907 if (INT_MAX / 2 < len)
2908 memory_full (SIZE_MAX);
2910 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2911 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2912 for (i = j = 0; i < len; i++)
2914 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2916 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2918 nonbmp_indices[j] = i + j;
2922 nonbmp_indices[j] = len + j; /* sentinel */
2926 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2930 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2931 if (macfont_info->screen_font)
2932 used = mac_screen_font_shape (macfont_info->screen_font, string,
2933 glyph_layouts, glyph_len);
2935 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2946 for (i = 0; i < used; i++)
2948 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2949 struct mac_glyph_layout *gl = glyph_layouts + i;
2951 struct font_metrics metrics;
2952 int xoff, yoff, wadjust;
2956 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2957 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2960 from = gl->comp_range.location;
2961 /* Convert UTF-16 index to UTF-32. */
2963 while (nonbmp_indices[j] < from)
2966 LGLYPH_SET_FROM (lglyph, from);
2968 to = gl->comp_range.location + gl->comp_range.length;
2969 /* Convert UTF-16 index to UTF-32. */
2970 while (nonbmp_indices[j] < to)
2973 LGLYPH_SET_TO (lglyph, to - 1);
2975 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2976 the composition is trivial. */
2980 if (unichars[gl->string_index] >= 0xD800
2981 && unichars[gl->string_index] < 0xDC00)
2982 c = (((unichars[gl->string_index] - 0xD800) << 10)
2983 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2985 c = unichars[gl->string_index];
2986 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2988 LGLYPH_SET_CHAR (lglyph, c);
2992 unsigned long cc = gl->glyph_id;
2993 LGLYPH_SET_CODE (lglyph, cc);
2996 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2997 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2998 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2999 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3000 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3001 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3003 xoff = lround (gl->advance_delta);
3004 yoff = lround (- gl->baseline_delta);
3005 wadjust = lround (gl->advance);
3006 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3010 vec = Fmake_vector (make_number (3), Qnil);
3011 ASET (vec, 0, make_number (xoff));
3012 ASET (vec, 1, make_number (yoff));
3013 ASET (vec, 2, make_number (wadjust));
3014 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3020 return make_number (used);
3023 /* Structures for the UVS subtable (format 14) in the cmap table. */
3024 typedef UInt8 UINT24[3];
3026 #pragma pack(push, 1)
3027 struct variation_selector_record
3029 UINT24 var_selector;
3030 UInt32 default_uvs_offset, non_default_uvs_offset;
3035 UInt32 length, num_var_selector_records;
3036 struct variation_selector_record variation_selector_records[1];
3038 #define SIZEOF_UVS_TABLE_HEADER \
3039 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3041 struct unicode_value_range
3043 UINT24 start_unicode_value;
3044 UInt8 additional_count;
3046 struct default_uvs_table {
3047 UInt32 num_unicode_value_ranges;
3048 struct unicode_value_range unicode_value_ranges[1];
3050 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3051 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3055 UINT24 unicode_value;
3058 struct non_default_uvs_table
3060 UInt32 num_uvs_mappings;
3061 struct uvs_mapping uvs_mappings[1];
3063 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3064 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3067 /* Read big endian values. The argument LVAL must be an lvalue. */
3068 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3069 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3070 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3071 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3072 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3073 /* Succeeding one byte should also be accessible. */
3074 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3075 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3077 /* Return UVS subtable for the specified FONT. If the subtable is not
3078 found or ill-formatted, then return NULL. */
3081 mac_font_copy_uvs_table (CTFontRef font)
3083 CFDataRef cmap_table, uvs_table = NULL;
3085 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3086 kCTFontTableOptionNoOptions);
3089 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3090 struct uvs_table *uvs;
3091 struct variation_selector_record *records;
3092 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3095 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3099 cmap_len = CFDataGetLength (cmap_table);
3100 if (sizeof_sfntCMapHeader > cmap_len)
3103 ntables = BUINT16_VALUE (cmap->numTables);
3104 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3105 / sizeof_sfntCMapEncoding))
3108 for (i = 0; i < ntables; i++)
3109 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3110 == kFontUnicodePlatform)
3111 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3112 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3114 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3118 || uvs_offset > cmap_len
3119 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3122 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3123 uvs_len = BUINT32_VALUE (uvs->length);
3124 if (uvs_len > cmap_len - uvs_offset
3125 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3128 if (BUINT16_VALUE (uvs->format) != 14)
3131 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3132 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3133 / sizeof (struct variation_selector_record)))
3136 records = uvs->variation_selector_records;
3137 for (i = 0; i < nrecords; i++)
3139 UInt32 default_uvs_offset, non_default_uvs_offset;
3141 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3142 if (default_uvs_offset)
3144 struct default_uvs_table *default_uvs;
3147 if (default_uvs_offset > uvs_len
3148 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3149 > uvs_len - default_uvs_offset))
3152 default_uvs = ((struct default_uvs_table *)
3153 ((UInt8 *) uvs + default_uvs_offset));
3154 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3155 if (nranges > ((uvs_len - default_uvs_offset
3156 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3157 / sizeof (struct unicode_value_range)))
3159 /* Now 2 * nranges can't overflow, so we can safely use
3160 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3161 mac_font_get_glyphs_for_variants. */
3164 non_default_uvs_offset =
3165 BUINT32_VALUE (records[i].non_default_uvs_offset);
3166 if (non_default_uvs_offset)
3168 struct non_default_uvs_table *non_default_uvs;
3171 if (non_default_uvs_offset > uvs_len
3172 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3173 > uvs_len - non_default_uvs_offset))
3176 non_default_uvs = ((struct non_default_uvs_table *)
3177 ((UInt8 *) uvs + non_default_uvs_offset));
3178 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3179 if (nmappings > ((uvs_len - non_default_uvs_offset
3180 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3181 / sizeof (struct uvs_mapping)))
3183 /* Now 2 * nmappings can't overflow, so we can safely
3184 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3185 in mac_font_get_glyphs_for_variants. */
3189 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3192 CFRelease (cmap_table);
3198 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3199 sequence consisting of the given base character C and each
3200 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3201 result (explained below) into the corresponding GLYPHS[i]. If the
3202 entry is found in the Default UVS Table, then the result is 0. If
3203 the entry is found in the Non-Default UVS Table, then the result is
3204 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3205 elements in SELECTORS must be sorted in strictly increasing
3209 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3210 const UTF32Char selectors[], CGGlyph glyphs[],
3213 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3214 struct variation_selector_record *records = uvs->variation_selector_records;
3216 UInt32 ir, nrecords;
3217 dispatch_queue_t queue =
3218 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3219 dispatch_group_t group = dispatch_group_create ();
3221 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3224 while (i < count && ir < nrecords)
3226 UInt32 default_uvs_offset, non_default_uvs_offset;
3228 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3230 glyphs[i++] = kCGFontIndexInvalid;
3233 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3239 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3240 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3241 non_default_uvs_offset =
3242 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3243 dispatch_group_async (group, queue, ^{
3244 glyphs[i] = kCGFontIndexInvalid;
3246 if (default_uvs_offset)
3248 struct default_uvs_table *default_uvs =
3249 (struct default_uvs_table *) ((UInt8 *) uvs
3250 + default_uvs_offset);
3251 struct unicode_value_range *ranges =
3252 default_uvs->unicode_value_ranges;
3256 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3259 UInt32 mid = (lo + hi) / 2;
3261 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3267 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3268 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3272 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3274 struct non_default_uvs_table *non_default_uvs =
3275 (struct non_default_uvs_table *) ((UInt8 *) uvs
3276 + non_default_uvs_offset);
3277 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3281 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3284 UInt32 mid = (lo + hi) / 2;
3286 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3292 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3293 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3300 glyphs[i++] = kCGFontIndexInvalid;
3301 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3302 dispatch_release (group);
3306 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3308 CFDataRef uvs_table;
3309 CTCharacterCollection uvs_collection;
3313 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3317 UTF32Char selectors[256];
3318 CGGlyph glyphs[256];
3320 for (i = 0; i < 16; i++)
3321 selectors[i] = 0xFE00 + i;
3322 for (; i < 256; i++)
3323 selectors[i] = 0xE0100 + (i - 16);
3324 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3325 for (i = 0; i < 256; i++)
3327 CGGlyph glyph = glyphs[i];
3329 if (uvs_collection != kCTCharacterCollectionIdentityMapping
3330 && glyph != kCGFontIndexInvalid)
3331 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3332 if (glyph == kCGFontIndexInvalid)
3336 variations[i] = (glyph ? glyph
3337 : macfont_get_glyph_for_character (font, c));
3347 static const char *const macfont_booleans[] = {
3353 static const char *const macfont_non_booleans[] = {
3361 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3363 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3367 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3368 CFArrayRef languages)
3370 Boolean result = true;
3371 CFArrayRef desc_languages =
3372 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3374 if (desc_languages == NULL)
3378 CFIndex desc_languages_count, i, languages_count;
3380 desc_languages_count = CFArrayGetCount (desc_languages);
3381 languages_count = CFArrayGetCount (languages);
3382 for (i = 0; i < languages_count; i++)
3383 if (!CFArrayContainsValue (desc_languages,
3384 CFRangeMake (0, desc_languages_count),
3385 CFArrayGetValueAtIndex (languages, i)))
3390 CFRelease (desc_languages);
3397 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3399 CFStringRef result = NULL;
3400 CFStringRef charset_string =
3401 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3403 if (charset_string && CFStringGetLength (charset_string) > 0)
3405 CFStringRef keys[] = {
3406 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3407 kCTLanguageAttributeName
3409 CFSTR ("NSLanguage")
3412 CFTypeRef values[] = {NULL};
3413 CFIndex num_values = 0;
3414 CFArrayRef languages
3415 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3417 if (languages && CFArrayGetCount (languages) > 0)
3419 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3420 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3423 CFCharacterSetRef charset =
3424 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3426 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3431 CFAttributedStringRef attr_string = NULL;
3432 CTLineRef ctline = NULL;
3433 CFDictionaryRef attrs
3434 = CFDictionaryCreate (NULL, (const void **) keys,
3435 (const void **) values, num_values,
3436 &kCFTypeDictionaryKeyCallBacks,
3437 &kCFTypeDictionaryValueCallBacks);
3441 attr_string = CFAttributedStringCreate (NULL, charset_string,
3447 ctline = CTLineCreateWithAttributedString (attr_string);
3448 CFRelease (attr_string);
3452 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3453 CFIndex i, nruns = CFArrayGetCount (runs);
3456 for (i = 0; i < nruns; i++)
3458 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3459 CFDictionaryRef attributes = CTRunGetAttributes (run);
3460 CTFontRef font_in_run;
3462 if (attributes == NULL)
3465 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3466 if (font_in_run == NULL)
3470 else if (!mac_font_equal_in_postscript_name (font,
3474 if (nruns > 0 && i == nruns)
3475 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3484 static inline double
3485 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3487 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3491 static inline CGRect
3492 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3494 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3499 mac_font_create_available_families (void)
3501 CFMutableArrayRef families = NULL;
3502 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3506 CFIndex i, count = CFArrayGetCount (orig_families);
3508 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3510 for (i = 0; i < count; i++)
3512 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3514 if (!CFStringHasPrefix (family, CFSTR ("."))
3515 && (CTFontManagerCompareFontFamilyNames (family,
3516 CFSTR ("LastResort"),
3518 != kCFCompareEqualTo))
3519 CFArrayAppendValue (families, family);
3521 CFRelease (orig_families);
3528 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3531 CFStringRef name1, name2;
3537 name1 = CTFontCopyPostScriptName (font1);
3540 name2 = CTFontCopyPostScriptName (font2);
3543 result = CFEqual (name1, name2);
3553 mac_font_create_line_with_string_and_font (CFStringRef string,
3556 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3557 CFTypeRef values[] = {NULL, NULL};
3558 CFDictionaryRef attributes = NULL;
3559 CFAttributedStringRef attr_string = NULL;
3560 CTLineRef ctline = NULL;
3561 float float_zero = 0.0f;
3563 values[0] = macfont;
3564 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3567 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3568 (const void **) values,
3570 &kCFTypeDictionaryKeyCallBacks,
3571 &kCFTypeDictionaryValueCallBacks);
3572 CFRelease (values[1]);
3576 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3577 CFRelease (attributes);
3581 ctline = CTLineCreateWithAttributedString (attr_string);
3582 CFRelease (attr_string);
3586 /* Abandon if ctline contains some fonts other than the
3588 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3589 CFIndex i, nruns = CFArrayGetCount (runs);
3591 for (i = 0; i < nruns; i++)
3593 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3594 CFDictionaryRef attributes = CTRunGetAttributes (run);
3595 CTFontRef font_in_run;
3597 if (attributes == NULL)
3600 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3601 if (font_in_run == NULL)
3603 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3617 mac_font_shape (CTFontRef font, CFStringRef string,
3618 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3620 CFIndex used, result = 0;
3621 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3626 used = CTLineGetGlyphCount (ctline);
3627 if (used <= glyph_len)
3629 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3630 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3631 CGFloat total_advance = 0;
3632 CFIndex total_glyph_count = 0;
3634 for (k = 0; k < ctrun_count; k++)
3636 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3637 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3638 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3639 CFRange string_range, comp_range, range;
3640 CFIndex *permutation;
3642 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3643 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3647 #define RIGHT_TO_LEFT_P permutation
3649 /* Now the `comp_range' member of struct mac_glyph_layout is
3650 temporarily used as a work area such that:
3651 glbuf[i].comp_range.location =
3652 min {compRange[i + 1].location, ...,
3653 compRange[glyph_count - 1].location,
3654 maxRange (stringRangeForCTRun)}
3655 glbuf[i].comp_range.length = maxRange (compRange[i])
3656 where compRange[i] is the range of composed characters
3657 containing i-th glyph. */
3658 string_range = CTRunGetStringRange (ctrun);
3659 min_location = string_range.location + string_range.length;
3660 for (i = 0; i < glyph_count; i++)
3662 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3663 CFIndex glyph_index;
3666 if (!RIGHT_TO_LEFT_P)
3667 glyph_index = glyph_count - i - 1;
3670 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3673 CFStringGetRangeOfComposedCharactersAtIndex (string,
3675 gl->comp_range.location = min_location;
3676 gl->comp_range.length = rng.location + rng.length;
3677 if (rng.location < min_location)
3678 min_location = rng.location;
3681 /* Fill the `comp_range' member of struct mac_glyph_layout,
3682 and setup a permutation for right-to-left text. */
3683 comp_range = CFRangeMake (string_range.location, 0);
3684 range = CFRangeMake (0, 0);
3687 struct mac_glyph_layout *gl =
3688 glbuf + range.location + range.length;
3690 if (gl->comp_range.length
3691 > comp_range.location + comp_range.length)
3692 comp_range.length = gl->comp_range.length - comp_range.location;
3693 min_location = gl->comp_range.location;
3696 if (min_location >= comp_range.location + comp_range.length)
3698 comp_range.length = min_location - comp_range.location;
3699 for (i = 0; i < range.length; i++)
3701 glbuf[range.location + i].comp_range = comp_range;
3702 if (RIGHT_TO_LEFT_P)
3703 permutation[range.location + i] =
3704 range.location + range.length - i - 1;
3707 comp_range = CFRangeMake (min_location, 0);
3708 range.location += range.length;
3710 if (range.location == glyph_count)
3715 /* Then fill the remaining members. */
3716 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3719 struct mac_glyph_layout *gl;
3722 if (!RIGHT_TO_LEFT_P)
3723 gl = glbuf + range.location;
3728 src = glyph_count - 1 - range.location;
3729 dest = permutation[src];
3733 CFIndex tmp = gl->string_index;
3735 gl->string_index = glbuf[src].string_index;
3736 glbuf[src].string_index = tmp;
3739 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3741 CTRunGetPositions (ctrun, range, &position);
3742 gl->advance_delta = position.x - total_advance;
3743 gl->baseline_delta = position.y;
3744 gl->advance = (gl->advance_delta
3745 + CTRunGetTypographicBounds (ctrun, range,
3747 total_advance += gl->advance;
3750 if (RIGHT_TO_LEFT_P)
3751 xfree (permutation);
3753 #undef RIGHT_TO_LEFT_P
3755 total_glyph_count += glyph_count;
3765 /* The function below seems to cause a memory leak for the CFString
3766 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3767 10.6.3. For now, we use the NSGlyphInfo version instead. */
3768 #if USE_CT_GLYPH_INFO
3770 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3773 CGGlyph result = kCGFontIndexInvalid;
3774 UniChar characters[] = {0xfffd};
3776 CFAttributedStringRef attr_string = NULL;
3777 CTLineRef ctline = NULL;
3779 string = CFStringCreateWithCharacters (NULL, characters,
3780 ARRAYELTS (characters));
3784 CTGlyphInfoRef glyph_info =
3785 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3786 CFDictionaryRef attributes = NULL;
3790 CFStringRef keys[] = {kCTFontAttributeName,
3791 kCTGlyphInfoAttributeName};
3792 CFTypeRef values[] = {font, glyph_info};
3794 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3795 (const void **) values,
3797 &kCFTypeDictionaryKeyCallBacks,
3798 &kCFTypeDictionaryValueCallBacks);
3799 CFRelease (glyph_info);
3803 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3804 CFRelease (attributes);
3810 ctline = CTLineCreateWithAttributedString (attr_string);
3811 CFRelease (attr_string);
3815 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3817 if (CFArrayGetCount (runs) > 0)
3819 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3820 CFDictionaryRef attributes = CTRunGetAttributes (run);
3824 CTFontRef font_in_run =
3825 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3828 && mac_font_equal_in_postscript_name (font_in_run, font))
3830 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3831 if (result >= CTFontGetGlyphCount (font))
3832 result = kCGFontIndexInvalid;
3844 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3846 CFArrayRef result = NULL;
3848 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3849 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3850 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3853 CTFontRef user_font =
3854 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3858 CFArrayRef languages =
3859 CFArrayCreate (NULL, (const void **) &language, 1,
3860 &kCFTypeArrayCallBacks);
3864 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3866 CFRelease (languages);
3868 CFRelease (user_font);
3871 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3872 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3874 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3875 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3879 for (i = 0; macfont_language_default_font_names[i].language; i++)
3881 if (CFEqual (macfont_language_default_font_names[i].language,
3884 CFMutableArrayRef descriptors =
3885 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3892 macfont_language_default_font_names[i].font_names[j];
3895 CFDictionaryRef attributes =
3896 CFDictionaryCreate (NULL,
3898 &kCTFontNameAttribute),
3900 &macfont_language_default_font_names[i].font_names[j]),
3901 1, &kCFTypeDictionaryKeyCallBacks,
3902 &kCFTypeDictionaryValueCallBacks);
3906 CTFontDescriptorRef pat_desc =
3907 CTFontDescriptorCreateWithAttributes (attributes);
3911 CTFontDescriptorRef descriptor =
3912 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3916 CFArrayAppendValue (descriptors, descriptor);
3917 CFRelease (descriptor);
3919 CFRelease (pat_desc);
3921 CFRelease (attributes);
3924 result = descriptors;
3936 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3937 CFArrayRef languages)
3939 CFStringRef result = NULL;
3940 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3941 CFArrayRef descriptors =
3942 mac_font_copy_default_descriptors_for_language (language);
3946 CFIndex i, count = CFArrayGetCount (descriptors);
3948 for (i = 0; i < count; i++)
3950 CTFontDescriptorRef descriptor =
3951 CFArrayGetValueAtIndex (descriptors, i);
3953 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3956 CFStringRef family =
3957 CTFontDescriptorCopyAttribute (descriptor,
3958 kCTFontFamilyNameAttribute);
3961 if (!CFStringHasPrefix (family, CFSTR ("."))
3962 && !CFEqual (family, CFSTR ("LastResort")))
3972 CFRelease (descriptors);
3979 macfont_get_nsctfont (struct font *font)
3981 struct macfont_info *macfont_info = (struct macfont_info *) font;
3982 CTFontRef macfont = macfont_info->macfont;
3984 return (void *) macfont;
3988 mac_register_font_driver (struct frame *f)
3990 register_font_driver (&macfont_driver, f);
3995 syms_of_macfont (void)
3997 static struct font_driver mac_font_driver;
3999 /* Core Text, for Mac OS X. */
4000 DEFSYM (Qmac_ct, "mac-ct");
4001 macfont_driver.type = Qmac_ct;
4002 register_font_driver (&macfont_driver, NULL);
4004 /* The font property key specifying the font design destination. The
4005 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4006 text. (See the documentation of X Logical Font Description
4007 Conventions.) In the Mac font driver, 1 means the screen font is
4008 used for calculating some glyph metrics. You can see the
4009 difference with Monaco 8pt or 9pt, for example. */
4010 DEFSYM (QCdestination, ":destination");
4012 /* The boolean-valued font property key specifying the use of leading. */
4013 DEFSYM (QCminspace, ":minspace");
4015 macfont_family_cache = Qnil;
4016 staticpro (&macfont_family_cache);