1 /* Font driver on macOS Core text.
2 Copyright (C) 2009-2016 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 (at
9 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 double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
42 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
43 static CFArrayRef mac_font_create_available_families (void);
44 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
45 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
47 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
49 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
50 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
51 struct mac_glyph_layout *, CFIndex);
52 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
53 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
55 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
59 struct macfont_metrics;
61 /* The actual structure for Mac font that can be cast to struct font. */
68 ScreenFontRef screen_font;
69 struct macfont_cache *cache;
70 struct macfont_metrics **metrics;
72 bool_bf synthetic_italic_p : 1;
73 bool_bf synthetic_bold_p : 1;
75 unsigned antialias : 2;
76 bool_bf color_bitmap_p : 1;
79 /* Values for the `spacing' member in `struct macfont_info'. */
83 MACFONT_SPACING_PROPORTIONAL,
85 MACFONT_SPACING_SYNTHETIC_MONO,
88 /* Values for the `antialias' member in `struct macfont_info'. */
92 MACFONT_ANTIALIAS_DEFAULT,
93 MACFONT_ANTIALIAS_OFF,
97 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
98 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
99 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
101 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
102 static const CGFloat synthetic_bold_factor = 0.024;
104 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
105 CTFontSymbolicTraits *);
106 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
108 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
109 CTFontSymbolicTraits);
110 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
111 static int macfont_glyph_extents (struct font *, CGGlyph,
112 struct font_metrics *, CGFloat *, int);
113 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
114 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
118 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
120 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
121 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
123 CGGlyph [], CFIndex);
125 /* From CFData to a lisp string. Always returns a unibyte string. */
128 cfdata_to_lisp (CFDataRef data)
130 CFIndex len = CFDataGetLength (data);
131 Lisp_Object result = make_uninit_string (len);
133 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
140 /* From CFString to a lisp string. Returns a unibyte string
141 containing a UTF-8 byte sequence. */
144 cfstring_to_lisp_nodecode (CFStringRef string)
146 Lisp_Object result = Qnil;
148 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
152 CFIndex i, length = CFStringGetLength (string);
154 for (i = 0; i < length; i++)
155 if (CFStringGetCharacterAtIndex (string, i) == 0)
159 return make_unibyte_string (s, strlen (s));
162 data = CFStringCreateExternalRepresentation (NULL, string,
163 kCFStringEncodingUTF8, '?');
166 result = cfdata_to_lisp (data);
173 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
174 cfstring_create_with_utf8_cstring, this function preserves NUL
178 cfstring_create_with_string_noencode (Lisp_Object s)
180 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
181 kCFStringEncodingUTF8, false);
184 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
185 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
186 kCFStringEncodingMacRoman, false);
192 mac_font_get_weight (CTFontRef font)
194 NSFont *nsFont = (NSFont *) font;
196 return [[NSFontManager sharedFontManager] weightOfFont:nsFont];
200 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
202 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
204 return advancement.width;
207 #if !USE_CT_GLYPH_INFO
209 mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
212 CGGlyph result = kCGFontIndexInvalid;
213 NSFont *nsFont = (NSFont *) font;
214 unichar characters[] = {0xfffd};
216 [NSString stringWithCharacters:characters
217 length:ARRAYELTS (characters)];
218 NSGlyphInfo *glyphInfo =
219 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
220 collection:collection
222 NSDictionary *attributes =
223 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
224 glyphInfo,NSGlyphInfoAttributeName,nil];
225 NSTextStorage *textStorage =
226 [[NSTextStorage alloc] initWithString:string
227 attributes:attributes];
228 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
229 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
230 NSFont *fontInTextStorage;
232 [layoutManager addTextContainer:textContainer];
233 [textContainer release];
234 [textStorage addLayoutManager:layoutManager];
235 [layoutManager release];
238 (void) [layoutManager glyphRangeForTextContainer:textContainer];
240 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
241 effectiveRange:NULL];
242 if (fontInTextStorage == nsFont
243 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
245 NSGlyph glyph = [layoutManager glyphAtIndex:0];
247 if (glyph < [nsFont numberOfGlyphs])
251 [textStorage release];
258 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
260 NSFont *result, *font;
262 font = [NSFont fontWithName:((NSString *) name) size:size];
263 result = [font screenFont];
265 return (ScreenFontRef)[result retain];
270 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
271 CGFloat *descent, CGFloat *leading)
273 NSFont *nsFont = [(NSFont *)font printerFont];
274 NSTextStorage *textStorage;
275 NSLayoutManager *layoutManager;
276 NSTextContainer *textContainer;
278 NSPoint spaceLocation;
281 textStorage = [[NSTextStorage alloc] initWithString:@" "];
282 layoutManager = [[NSLayoutManager alloc] init];
283 textContainer = [[NSTextContainer alloc] init];
285 [textStorage setFont:nsFont];
286 [textContainer setLineFragmentPadding:0];
287 [layoutManager setUsesScreenFonts:YES];
289 [layoutManager addTextContainer:textContainer];
290 [textContainer release];
291 [textStorage addLayoutManager:layoutManager];
292 [layoutManager release];
294 if (!(textStorage && layoutManager && textContainer))
296 [textStorage release];
301 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
302 effectiveRange:NULL];
303 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
304 [textStorage release];
306 *ascent = spaceLocation.y;
307 *descent = NSHeight (usedRect) - spaceLocation.y;
309 descender = [nsFont descender];
310 if (- descender < *descent)
312 *leading = *descent + descender;
313 *descent = - descender;
320 mac_font_shape_1 (NSFont *font, NSString *string,
321 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
326 NSTextStorage *textStorage;
327 NSLayoutManager *layoutManager;
328 NSTextContainer *textContainer;
329 NSUInteger stringLength;
330 NSPoint spaceLocation;
331 NSUInteger used, numberOfGlyphs;
333 textStorage = [[NSTextStorage alloc] initWithString:string];
334 layoutManager = [[NSLayoutManager alloc] init];
335 textContainer = [[NSTextContainer alloc] init];
337 /* Append a trailing space to measure baseline position. */
338 [textStorage appendAttributedString:([[[NSAttributedString alloc]
339 initWithString:@" "] autorelease])];
340 [textStorage setFont:font];
341 [textContainer setLineFragmentPadding:0];
342 [layoutManager setUsesScreenFonts:screen_font_p];
344 [layoutManager addTextContainer:textContainer];
345 [textContainer release];
346 [textStorage addLayoutManager:layoutManager];
347 [layoutManager release];
349 if (!(textStorage && layoutManager && textContainer))
351 [textStorage release];
356 stringLength = [string length];
359 (void) [layoutManager glyphRangeForTextContainer:textContainer];
361 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
363 /* Remove the appended trailing space because otherwise it may
364 generate a wrong result for a right-to-left text. */
365 [textStorage beginEditing];
366 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
367 [textStorage endEditing];
368 (void) [layoutManager glyphRangeForTextContainer:textContainer];
371 while (i < stringLength)
374 NSFont *fontInTextStorage =
375 [textStorage attribute:NSFontAttributeName atIndex:i
376 longestEffectiveRange:&range
377 inRange:(NSMakeRange (0, stringLength))];
379 if (!(fontInTextStorage == font
380 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
382 i = NSMaxRange (range);
384 if (i < stringLength)
385 /* Make the test `used <= glyph_len' below fail if textStorage
386 contained some fonts other than the specified one. */
387 used = glyph_len + 1;
390 NSRange range = NSMakeRange (0, stringLength);
392 range = [layoutManager glyphRangeForCharacterRange:range
393 actualCharacterRange:NULL];
394 numberOfGlyphs = NSMaxRange (range);
395 used = numberOfGlyphs;
396 for (i = 0; i < numberOfGlyphs; i++)
397 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
401 if (0 < used && used <= glyph_len)
403 NSUInteger glyphIndex, prevGlyphIndex;
404 unsigned char bidiLevel;
405 NSUInteger *permutation;
406 NSRange compRange, range;
407 CGFloat totalAdvance;
410 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
413 /* For now we assume the direction is not changed within the
415 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
416 glyphs:NULL characterIndexes:NULL
417 glyphInscriptions:NULL elasticBits:NULL
418 bidiLevels:&bidiLevel];
420 permutation = xmalloc (sizeof (NSUInteger) * used);
424 #define RIGHT_TO_LEFT_P permutation
426 /* Fill the `comp_range' member of struct mac_glyph_layout, and
427 setup a permutation for right-to-left text. */
428 compRange = NSMakeRange (0, 0);
429 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
432 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
433 NSUInteger characterIndex =
434 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
436 gl->string_index = characterIndex;
438 if (characterIndex >= NSMaxRange (compRange))
440 compRange.location = NSMaxRange (compRange);
443 NSRange characterRange =
445 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
448 NSMaxRange (characterRange) - compRange.location;
449 [layoutManager glyphRangeForCharacterRange:compRange
450 actualCharacterRange:&characterRange];
451 characterIndex = NSMaxRange (characterRange) - 1;
453 while (characterIndex >= NSMaxRange (compRange));
456 for (i = 0; i < range.length; i++)
457 permutation[range.location + i] = NSMaxRange (range) - i - 1;
459 range = NSMakeRange (NSMaxRange (range), 0);
462 gl->comp_range.location = compRange.location;
463 gl->comp_range.length = compRange.length;
465 while (++glyphIndex < numberOfGlyphs)
466 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
470 for (i = 0; i < range.length; i++)
471 permutation[range.location + i] = NSMaxRange (range) - i - 1;
473 /* Then fill the remaining members. */
474 glyphIndex = prevGlyphIndex = 0;
475 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
478 if (!RIGHT_TO_LEFT_P)
485 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
486 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
487 inTextContainer:textContainer rectCount:&nrects];
489 totalAdvance = NSMaxX (glyphRects[0]);
492 for (i = 0; i < used; i++)
494 struct mac_glyph_layout *gl;
496 NSUInteger nextGlyphIndex;
501 if (!RIGHT_TO_LEFT_P)
502 gl = glyph_layouts + i;
505 NSUInteger dest = permutation[i];
507 gl = glyph_layouts + dest;
510 CFIndex tmp = gl->string_index;
512 gl->string_index = glyph_layouts[i].string_index;
513 glyph_layouts[i].string_index = tmp;
516 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
518 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
519 gl->baseline_delta = spaceLocation.y - location.y;
521 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
524 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
527 if (!RIGHT_TO_LEFT_P)
531 if (prevGlyphIndex == 0)
532 glyphRange = NSMakeRange (0, nextGlyphIndex);
534 glyphRange = NSMakeRange (glyphIndex,
535 nextGlyphIndex - glyphIndex);
538 rectArrayForGlyphRange:glyphRange
539 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
540 inTextContainer:textContainer rectCount:&nrects];
541 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
542 gl->advance_delta = location.x - totalAdvance;
543 gl->advance = maxX - totalAdvance;
550 if (nextGlyphIndex == numberOfGlyphs)
551 glyphRange = NSMakeRange (prevGlyphIndex,
552 numberOfGlyphs - prevGlyphIndex);
554 glyphRange = NSMakeRange (prevGlyphIndex,
555 glyphIndex + 1 - prevGlyphIndex);
558 rectArrayForGlyphRange:glyphRange
559 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
560 inTextContainer:textContainer rectCount:&nrects];
561 minX = min (NSMinX (glyphRects[0]), totalAdvance);
562 gl->advance = totalAdvance - minX;
564 gl->advance_delta = location.x - totalAdvance;
567 prevGlyphIndex = glyphIndex + 1;
568 glyphIndex = nextGlyphIndex;
574 #undef RIGHT_TO_LEFT_P
578 [textStorage release];
584 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
585 struct mac_glyph_layout *glyph_layouts,
588 return mac_font_shape_1 ([(NSFont *)font printerFont],
590 glyph_layouts, glyph_len, YES);
594 get_cgcolor(unsigned long idx, struct frame *f)
596 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
598 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
599 NSInteger noc = [nsColor numberOfComponents];
600 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
603 [nsColor getComponents: components];
604 cgColor = CGColorCreate (colorSpace, components);
609 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
611 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
612 CGContextSetFillColorWithColor (context, refcol_) ; \
613 CGColorRelease (refcol_); \
615 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
617 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
618 CGContextSetFillColorWithColor (context, refcol_); \
619 CGColorRelease (refcol_); \
621 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
623 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
624 CGContextSetStrokeColorWithColor (context, refcol_); \
625 CGColorRelease (refcol_); \
630 /* Mac font driver. */
636 /* characters to distinguish the charset from the others */
638 /* additional constraint by language */
641 CFCharacterSetRef cf_charset;
642 CFStringRef cf_charset_string;
643 } cf_charset_table[] =
644 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
645 { "iso8859-2", { 0x00A0, 0x010E }},
646 { "iso8859-3", { 0x00A0, 0x0108 }},
647 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
648 { "iso8859-5", { 0x00A0, 0x0401 }},
649 { "iso8859-6", { 0x00A0, 0x060C }},
650 { "iso8859-7", { 0x00A0, 0x0384 }},
651 { "iso8859-8", { 0x00A0, 0x05D0 }},
652 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
653 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
654 { "iso8859-11", { 0x00A0, 0x0E01 }},
655 { "iso8859-13", { 0x00A0, 0x201C }},
656 { "iso8859-14", { 0x00A0, 0x0174 }},
657 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
658 { "iso8859-16", { 0x00A0, 0x0218}},
659 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
660 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
661 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
662 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
663 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
664 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
665 { "cns11643.1992-3", { 0x201A9 }},
666 { "cns11643.1992-4", { 0x20057 }},
667 { "cns11643.1992-5", { 0x20000 }},
668 { "cns11643.1992-6", { 0x20003 }},
669 { "cns11643.1992-7", { 0x20055 }},
670 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
671 { "jisx0212.1990-0", { 0x4E44 }},
672 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
673 { "jisx0213.2000-2", { 0xFA49 }},
674 { "jisx0213.2004-1", { 0x20B9F }},
675 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
676 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
677 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
678 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
679 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
680 { "unicode-sip", { 0x20000 }},
684 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
687 CFStringRef language;
688 CFStringRef font_names[3];
689 } macfont_language_default_font_names[] = {
690 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
691 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
693 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
694 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
696 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
697 CFSTR ("STXihei"), /* 10.4 - 10.5 */
699 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
700 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
706 static CGFloat macfont_antialias_threshold;
709 macfont_update_antialias_threshold (void)
715 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
716 kCFPreferencesCurrentApplication,
719 macfont_antialias_threshold = threshold;
722 static inline Lisp_Object
723 macfont_intern_prop_cfstring (CFStringRef cfstring)
725 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
727 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
730 static inline CFIndex
731 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
742 unichars[0] = (c >> 10) + 0xD800;
743 unichars[1] = (c & 0x3FF) + 0xDC00;
750 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
751 CTFontSymbolicTraits *sym_traits)
755 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
756 OS X 10.6 when the value is greater than or equal to 1 << 31. */
757 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
759 *sym_traits = (CTFontSymbolicTraits) sint64_value;
768 mac_font_descriptor_get_adjusted_weight (CTFontDescriptorRef desc, CGFloat val)
770 long percent_val = lround (val * 100);
772 if (percent_val == -40)
774 CTFontRef font = NULL;
776 CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
780 font = CTFontCreateWithName (name, 0, NULL);
785 CFIndex weight = mac_font_get_weight (font);
787 /* Workaround for crash when displaying Oriya characters
788 with Arial Unicode MS on OS X 10.11. */
799 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
800 Lisp_Object spec_or_entity)
803 CFDictionaryRef dict;
807 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
810 ASET (spec_or_entity, FONT_FAMILY_INDEX,
811 macfont_intern_prop_cfstring (str));
814 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
818 enum font_property_index index;
821 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
823 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
824 {{-0.4, 50}, /* light */
825 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
826 {0, 100}, /* normal */
827 {0.24, 140}, /* (semi-bold + normal) / 2 */
828 {0.4, 200}, /* bold */
829 {CGFLOAT_MAX, CGFLOAT_MAX}},
830 mac_font_descriptor_get_adjusted_weight},
831 {FONT_SLANT_INDEX, kCTFontSlantTrait,
832 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
833 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
834 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
837 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
839 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
840 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
842 CGPoint *point = numeric_traits[i].points;
844 if (numeric_traits[i].adjust_func)
845 floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
846 while (point->x < floatval)
848 if (point == numeric_traits[i].points)
850 else if (point->x == CGFLOAT_MAX)
852 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
853 * ((point->y - (point - 1)->y)
854 / (point->x - (point - 1)->x)));
855 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
856 make_number (lround (floatval)));
860 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
863 CTFontSymbolicTraits sym_traits;
866 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
867 spacing = (sym_traits & kCTFontTraitMonoSpace
868 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
869 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
874 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
875 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
876 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
878 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
884 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
885 CTFontSymbolicTraits synth_sym_traits)
888 CFDictionaryRef dict;
889 CTFontSymbolicTraits sym_traits = 0;
892 entity = font_make_entity ();
894 ASET (entity, FONT_TYPE_INDEX, Qmac_ct);
895 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
897 macfont_store_descriptor_attributes (desc, entity);
899 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
902 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
905 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
908 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
909 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
910 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
911 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
912 font_put_extra (entity, QCfont_entity,
913 make_save_ptr_int ((void *) name, sym_traits));
914 if (synth_sym_traits & kCTFontTraitItalic)
915 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
916 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
917 if (synth_sym_traits & kCTFontTraitBold)
918 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
919 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
920 if (synth_sym_traits & kCTFontTraitMonoSpace)
921 ASET (entity, FONT_SPACING_INDEX,
922 make_number (FONT_SPACING_SYNTHETIC_MONO));
927 /* Cache for font family name symbols vs CFStrings. A value of nil
928 means the cache has been invalidated. Otherwise the value is a Lisp
929 hash table whose keys are symbols and the value for a key is either
930 nil (no corresponding family name) or a Lisp save value wrapping the
931 corresponding family name in CFString. */
933 static Lisp_Object macfont_family_cache;
936 macfont_invalidate_family_cache (void)
938 if (HASH_TABLE_P (macfont_family_cache))
940 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
941 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
943 for (i = 0; i < size; ++i)
944 if (!NILP (HASH_HASH (h, i)))
946 Lisp_Object value = HASH_VALUE (h, i);
948 if (SAVE_VALUEP (value))
949 CFRelease (XSAVE_POINTER (value, 0));
951 macfont_family_cache = Qnil;
956 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
958 if (HASH_TABLE_P (macfont_family_cache))
960 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
961 ptrdiff_t i = hash_lookup (h, symbol, NULL);
965 Lisp_Object value = HASH_VALUE (h, i);
967 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
977 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
979 struct Lisp_Hash_Table *h;
984 if (!HASH_TABLE_P (macfont_family_cache))
985 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
987 h = XHASH_TABLE (macfont_family_cache);
988 i = hash_lookup (h, symbol, &hash);
989 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
992 Lisp_Object old_value = HASH_VALUE (h, i);
994 if (SAVE_VALUEP (old_value))
995 CFRelease (XSAVE_POINTER (old_value, 0));
996 set_hash_value_slot (h, i, value);
999 hash_put (h, symbol, value, hash);
1002 /* Cache of all the available font family names except "LastResort"
1003 and those start with ".". NULL means the cache has been invalidated.
1004 Otherwise, the value is CFArray of CFStrings and the elements are
1005 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1006 Mac OS X 10.6 and later). */
1008 static CFArrayRef macfont_available_families_cache = NULL;
1011 macfont_invalidate_available_families_cache (void)
1013 if (macfont_available_families_cache)
1015 CFRelease (macfont_available_families_cache);
1016 macfont_available_families_cache = NULL;
1021 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1023 CFStringRef name, const void *object,
1024 CFDictionaryRef userInfo)
1026 macfont_invalidate_family_cache ();
1027 macfont_invalidate_available_families_cache ();
1031 macfont_init_font_change_handler (void)
1033 static bool initialized = false;
1039 CFNotificationCenterAddObserver
1040 (CFNotificationCenterGetLocalCenter (), NULL,
1041 macfont_handle_font_change_notification,
1042 kCTFontManagerRegisteredFontsChangedNotification,
1043 NULL, CFNotificationSuspensionBehaviorCoalesce);
1047 macfont_copy_available_families_cache (void)
1049 macfont_init_font_change_handler ();
1051 if (macfont_available_families_cache == NULL)
1052 macfont_available_families_cache = mac_font_create_available_families ();
1054 return (macfont_available_families_cache
1055 ? CFRetain (macfont_available_families_cache) : NULL);
1059 macfont_create_family_with_symbol (Lisp_Object symbol)
1061 CFStringRef result = NULL, family_name;
1062 CFDictionaryRef attributes = NULL;
1063 CTFontDescriptorRef pat_desc = NULL;
1065 if (macfont_get_family_cache_if_present (symbol, &result))
1066 return result ? CFRetain (result) : NULL;
1068 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1072 CFDictionaryCreate (NULL,
1073 (const void **) &kCTFontFamilyNameAttribute,
1074 (const void **) &family_name, 1,
1075 &kCFTypeDictionaryKeyCallBacks,
1076 &kCFTypeDictionaryValueCallBacks);
1077 CFRelease (family_name);
1081 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1082 CFRelease (attributes);
1086 CTFontDescriptorRef desc =
1087 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1092 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1095 macfont_set_family_cache (symbol, result);
1096 CFRelease (pat_desc);
1102 #define WIDTH_FRAC_BITS (4)
1103 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1105 struct macfont_metrics
1107 unsigned char lbearing_low, rbearing_low;
1108 signed lbearing_high : 4, rbearing_high : 4;
1109 unsigned char ascent_low, descent_low;
1110 signed ascent_high : 4, descent_high : 4;
1112 /* These two members are used for fixed-point representation of
1113 glyph width. The `width_int' member is an integer that is
1114 closest to the width. The `width_frac' member is the fractional
1115 adjustment representing a value in [-.5, .5], multiplied by
1116 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1117 the advance delta for centering instead of the glyph width. */
1118 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1121 #define METRICS_VALUE(metrics, member) \
1122 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1123 #define METRICS_SET_VALUE(metrics, member, value) \
1124 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1125 (metrics)->member##_high = tmp >> 8;} while (0)
1129 METRICS_INVALID = -1, /* metrics entry is invalid */
1130 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1133 #define METRICS_STATUS(metrics) \
1134 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1135 #define METRICS_SET_STATUS(metrics, status) \
1136 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1137 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1139 #define METRICS_NCOLS_PER_ROW (128)
1140 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1141 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1144 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1145 struct font_metrics *metrics, CGFloat *advance_delta,
1146 int force_integral_p)
1148 struct macfont_info *macfont_info = (struct macfont_info *) font;
1149 CTFontRef macfont = macfont_info->macfont;
1151 struct macfont_metrics *cache;
1154 row = glyph / METRICS_NCOLS_PER_ROW;
1155 col = glyph % METRICS_NCOLS_PER_ROW;
1156 if (row >= macfont_info->metrics_nrows)
1158 macfont_info->metrics =
1159 xrealloc (macfont_info->metrics,
1160 sizeof (struct macfont_metrics *) * (row + 1));
1161 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1162 (sizeof (struct macfont_metrics *)
1163 * (row + 1 - macfont_info->metrics_nrows)));
1164 macfont_info->metrics_nrows = row + 1;
1166 if (macfont_info->metrics[row] == NULL)
1168 struct macfont_metrics *new;
1171 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1172 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1173 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1174 macfont_info->metrics[row] = new;
1176 cache = macfont_info->metrics[row] + col;
1178 if (METRICS_STATUS (cache) == METRICS_INVALID)
1182 if (macfont_info->screen_font)
1183 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1185 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1187 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1188 advance delta value. */
1189 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1190 fwidth = (font->pixel_size - fwidth) / 2;
1191 cache->width_int = lround (fwidth);
1192 cache->width_frac = lround ((fwidth - cache->width_int)
1193 * WIDTH_FRAC_SCALE);
1194 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1196 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1197 width = font->pixel_size;
1199 width = cache->width_int;
1203 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1205 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1207 if (macfont_info->synthetic_italic_p)
1209 /* We assume the members a, b, c, and d in
1210 synthetic_italic_atfm are non-negative. */
1212 CGPointApplyAffineTransform (bounds.origin,
1213 synthetic_italic_atfm);
1215 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1217 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1219 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1221 bounds = CGRectInset (bounds, d, d);
1223 switch (macfont_info->spacing)
1225 case MACFONT_SPACING_PROPORTIONAL:
1226 bounds.origin.x += - (cache->width_frac
1227 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1229 case MACFONT_SPACING_MONO:
1231 case MACFONT_SPACING_SYNTHETIC_MONO:
1232 bounds.origin.x += (cache->width_int
1233 + (cache->width_frac
1234 / (CGFloat) WIDTH_FRAC_SCALE));
1237 if (bounds.size.width > 0)
1239 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1240 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1241 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1243 bounds = CGRectIntegral (bounds);
1244 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1245 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1246 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1247 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1249 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1250 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1251 metrics->width = width;
1252 metrics->ascent = METRICS_VALUE (cache, ascent);
1253 metrics->descent = METRICS_VALUE (cache, descent);
1258 switch (macfont_info->spacing)
1260 case MACFONT_SPACING_PROPORTIONAL:
1261 *advance_delta = (force_integral_p ? 0
1262 : - (cache->width_frac
1263 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1265 case MACFONT_SPACING_MONO:
1268 case MACFONT_SPACING_SYNTHETIC_MONO:
1269 *advance_delta = (force_integral_p ? cache->width_int
1271 + (cache->width_frac
1272 / (CGFloat) WIDTH_FRAC_SCALE)));
1280 static CFMutableDictionaryRef macfont_cache_dictionary;
1282 /* Threshold used in row_nkeys_or_perm. This must be less than or
1283 equal to the number of rows that are invalid as BMP (i.e., from
1284 U+D800 to U+DFFF). */
1285 #define ROW_PERM_OFFSET (8)
1287 /* The number of glyphs that can be stored in a value for a single
1288 entry of CFDictionary. */
1289 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1291 struct macfont_cache
1293 int reference_count;
1294 CFCharacterSetRef cf_charset;
1296 /* The cached glyph for a BMP character c is stored in
1297 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1298 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1299 unsigned char row_nkeys_or_perm[256];
1302 /* Number of rows for which the BMP cache is allocated so far.
1303 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1306 /* The cached glyph for a character c is stored as the (c %
1307 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1308 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1309 not stored here if row_nkeys_or_perm[c / 256] >=
1311 CFMutableDictionaryRef dictionary;
1315 /* UVS (Unicode Variation Sequence) subtable data, which is of
1316 type CFDataRef if available. NULL means it is not initialized
1317 yet. kCFNull means the subtable is not found and there is no
1318 suitable fallback table for this font. */
1321 /* Character collection specifying the destination of the mapping
1322 provided by `table' above. If `table' is obtained from the UVS
1323 subtable in the font cmap table, then the value of this member
1324 should be kCTCharacterCollectionIdentityMapping. */
1325 CTCharacterCollection collection;
1329 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1330 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1331 static void macfont_release_cache (struct macfont_cache *);
1332 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1333 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1334 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1335 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1336 CTCharacterCollection, CGFontIndex);
1337 static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
1339 static struct macfont_cache *
1340 macfont_lookup_cache (CFStringRef key)
1342 struct macfont_cache *cache;
1344 if (macfont_cache_dictionary == NULL)
1346 macfont_cache_dictionary =
1347 CFDictionaryCreateMutable (NULL, 0,
1348 &kCFTypeDictionaryKeyCallBacks, NULL);
1352 cache = ((struct macfont_cache *)
1353 CFDictionaryGetValue (macfont_cache_dictionary, key));
1357 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1361 cache = xzalloc (sizeof (struct macfont_cache));
1362 /* Treat the LastResort font as if it contained glyphs for
1363 all characters. This may look too rough, but neither
1364 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1365 for this font is correct for non-BMP characters on Mac OS
1367 if (CFEqual (key, CFSTR ("LastResort")))
1369 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1372 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1374 if (cache->cf_charset == NULL)
1375 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1376 CFDictionaryAddValue (macfont_cache_dictionary, key,
1377 (const void *) cache);
1378 CFRelease (macfont);
1385 static struct macfont_cache *
1386 macfont_retain_cache (struct macfont_cache *cache)
1388 cache->reference_count++;
1394 macfont_release_cache (struct macfont_cache *cache)
1396 if (--cache->reference_count == 0)
1400 for (i = 0; i < cache->glyph.nrows; i++)
1401 xfree (cache->glyph.matrix[i]);
1402 xfree (cache->glyph.matrix);
1403 if (cache->glyph.dictionary)
1404 CFRelease (cache->glyph.dictionary);
1405 memset (&cache->glyph, 0, sizeof (cache->glyph));
1406 if (cache->uvs.table)
1407 CFRelease (cache->uvs.table);
1408 memset (&cache->uvs, 0, sizeof (cache->uvs));
1412 static CFCharacterSetRef
1413 macfont_get_cf_charset (struct font *font)
1415 struct macfont_info *macfont_info = (struct macfont_info *) font;
1417 return macfont_info->cache->cf_charset;
1420 static CFCharacterSetRef
1421 macfont_get_cf_charset_for_name (CFStringRef name)
1423 struct macfont_cache *cache = macfont_lookup_cache (name);
1425 return cache->cf_charset;
1429 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1431 struct macfont_info *macfont_info = (struct macfont_info *) font;
1432 CTFontRef macfont = macfont_info->macfont;
1433 struct macfont_cache *cache = macfont_info->cache;
1435 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1438 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1440 if (nkeys_or_perm < ROW_PERM_OFFSET)
1442 UniChar unichars[256], ch;
1446 dispatch_queue_t queue;
1447 dispatch_group_t group = NULL;
1451 CFMutableDictionaryRef dictionary;
1452 uintptr_t key, value;
1456 if (cache->glyph.dictionary == NULL)
1457 cache->glyph.dictionary =
1458 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1459 dictionary = cache->glyph.dictionary;
1460 key = c / NGLYPHS_IN_VALUE;
1461 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1462 value = ((uintptr_t)
1463 CFDictionaryGetValue (dictionary, (const void *) key));
1464 glyph = (value >> nshifts);
1468 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1471 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1473 glyph = kCGFontIndexInvalid;
1476 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1477 value |= ((uintptr_t) glyph << nshifts);
1478 CFDictionarySetValue (dictionary, (const void *) key,
1479 (const void *) value);
1485 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1486 group = dispatch_group_create ();
1487 dispatch_group_async (group, queue, ^{
1490 nkeys = nkeys_or_perm;
1491 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1492 if (CFDictionaryContainsKey (dictionary,
1493 (const void *) key))
1495 CFDictionaryRemoveValue (dictionary,
1496 (const void *) key);
1504 for (i = 0; i < 256; i++)
1507 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1508 unichars[len++] = ch;
1511 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1514 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1517 int next = unichars[len - 1] % 256;
1520 glyphs[i] = kCGFontIndexInvalid;
1523 glyphs[i] = glyphs[len];
1530 glyphs[i] = kCGFontIndexInvalid;
1532 nrows = cache->glyph.nrows;
1533 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1534 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1536 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1537 sizeof (CGGlyph *) * nrows);
1538 cache->glyph.matrix[nrows - 1] = glyphs;
1539 cache->glyph.nrows = nrows;
1543 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1544 dispatch_release (group);
1548 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1552 uintptr_t key, value;
1556 if (cache->glyph.dictionary == NULL)
1557 cache->glyph.dictionary =
1558 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1559 key = c / NGLYPHS_IN_VALUE;
1560 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1561 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1562 (const void *) key);
1563 glyph = (value >> nshifts);
1566 UniChar unichars[2];
1568 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1570 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1573 glyph = kCGFontIndexInvalid;
1575 value |= ((uintptr_t) glyph << nshifts);
1576 CFDictionarySetValue (cache->glyph.dictionary,
1577 (const void *) key, (const void *) value);
1585 macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1588 struct macfont_info *macfont_info = (struct macfont_info *) font;
1589 CTFontRef macfont = macfont_info->macfont;
1592 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1596 macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1598 struct macfont_info *macfont_info = (struct macfont_info *) font;
1599 CTFontRef macfont = macfont_info->macfont;
1600 struct macfont_cache *cache = macfont_info->cache;
1601 CFDataRef result = NULL;
1603 if (cache->uvs.table == NULL)
1605 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1606 CTCharacterCollection uvs_collection =
1607 kCTCharacterCollectionIdentityMapping;
1609 if (uvs_table == NULL
1610 && mac_font_get_glyph_for_cid (macfont,
1611 kCTCharacterCollectionAdobeJapan1,
1612 6480) != kCGFontIndexInvalid)
1614 /* If the glyph for U+4E55 is accessible via its CID 6480,
1615 then we use the Adobe-Japan1 UVS table, which maps a
1616 variation sequence to a CID, as a fallback. */
1617 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1619 if (mac_uvs_table_adobe_japan1 == NULL)
1620 mac_uvs_table_adobe_japan1 =
1621 CFDataCreateWithBytesNoCopy (NULL,
1622 mac_uvs_table_adobe_japan1_bytes,
1623 sizeof (mac_uvs_table_adobe_japan1_bytes),
1625 if (mac_uvs_table_adobe_japan1)
1627 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1628 uvs_collection = kCTCharacterCollectionAdobeJapan1;
1631 if (uvs_table == NULL)
1632 cache->uvs.table = kCFNull;
1634 cache->uvs.table = uvs_table;
1635 cache->uvs.collection = uvs_collection;
1638 if (cache->uvs.table != kCFNull)
1640 result = cache->uvs.table;
1641 *collection = cache->uvs.collection;
1647 static Lisp_Object macfont_get_cache (struct frame *);
1648 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1649 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1650 static Lisp_Object macfont_list_family (struct frame *);
1651 static void macfont_free_entity (Lisp_Object);
1652 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1653 static void macfont_close (struct font *);
1654 static int macfont_has_char (Lisp_Object, int);
1655 static unsigned macfont_encode_char (struct font *, int);
1656 static void macfont_text_extents (struct font *, unsigned int *, int,
1657 struct font_metrics *);
1658 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1659 static Lisp_Object macfont_shape (Lisp_Object);
1660 static int macfont_variation_glyphs (struct font *, int c,
1661 unsigned variations[256]);
1662 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1664 static struct font_driver const macfont_driver =
1666 .type = LISPSYM_INITIALLY (Qmac_ct),
1667 .get_cache = macfont_get_cache,
1668 .list = macfont_list,
1669 .match = macfont_match,
1670 .list_family = macfont_list_family,
1671 .free_entity = macfont_free_entity,
1672 .open = macfont_open,
1673 .close = macfont_close,
1674 .has_char = macfont_has_char,
1675 .encode_char = macfont_encode_char,
1676 .text_extents = macfont_text_extents,
1677 .draw = macfont_draw,
1678 .shape = macfont_shape,
1679 .get_variation_glyphs = macfont_variation_glyphs,
1680 .filter_properties = macfont_filter_properties,
1684 macfont_get_cache (struct frame * f)
1686 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1688 return (dpyinfo->name_list_element);
1692 macfont_get_charset (Lisp_Object registry)
1694 char *str = SSDATA (SYMBOL_NAME (registry));
1695 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1699 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1703 else if (str[i] == '*')
1710 regexp = make_unibyte_string (re, j);
1711 for (i = 0; cf_charset_table[i].name; i++)
1712 if (fast_c_string_match_ignore_case
1713 (regexp, cf_charset_table[i].name,
1714 strlen (cf_charset_table[i].name)) >= 0)
1716 if (! cf_charset_table[i].name)
1718 if (! cf_charset_table[i].cf_charset)
1720 int *uniquifier = cf_charset_table[i].uniquifier;
1721 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1724 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1728 for (j = 0; uniquifier[j]; j++)
1730 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1732 CFCharacterSetAddCharactersInRange (charset,
1733 CFRangeMake (uniquifier[j], 1));
1736 string = CFStringCreateWithCharacters (NULL, unichars, count);
1739 CFRelease (charset);
1742 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1744 CFRelease (charset);
1745 /* CFCharacterSetCreateWithCharactersInString does not handle
1746 surrogate pairs properly as of Mac OS X 10.5. */
1747 cf_charset_table[i].cf_charset_string = string;
1755 unsigned int script_tag, langsys_tag;
1757 unsigned int *features[2];
1760 #define OTF_SYM_TAG(SYM, TAG) \
1762 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1763 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1766 #define OTF_TAG_STR(TAG, P) \
1768 (P)[0] = (char) (TAG >> 24); \
1769 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1770 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1771 (P)[3] = (char) (TAG & 0xFF); \
1775 static struct OpenTypeSpec *
1776 macfont_get_open_type_spec (Lisp_Object otf_spec)
1778 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1785 spec->script = XCAR (otf_spec);
1786 if (! NILP (spec->script))
1788 OTF_SYM_TAG (spec->script, spec->script_tag);
1789 val = assq_no_quit (spec->script, Votf_script_alist);
1790 if (CONSP (val) && SYMBOLP (XCDR (val)))
1791 spec->script = XCDR (val);
1793 spec->script = Qnil;
1796 spec->script_tag = 0x44464C54; /* "DFLT" */
1797 otf_spec = XCDR (otf_spec);
1798 spec->langsys_tag = 0;
1799 if (! NILP (otf_spec))
1801 val = XCAR (otf_spec);
1803 OTF_SYM_TAG (val, spec->langsys_tag);
1804 otf_spec = XCDR (otf_spec);
1806 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1807 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1811 val = XCAR (otf_spec);
1814 len = Flength (val);
1816 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1818 : malloc (XINT (len) * sizeof *spec->features[i]));
1819 if (! spec->features[i])
1821 if (i > 0 && spec->features[0])
1822 free (spec->features[0]);
1826 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1828 if (NILP (XCAR (val)))
1834 OTF_SYM_TAG (XCAR (val), tag);
1835 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1838 spec->nfeatures[i] = j;
1843 static CFMutableDictionaryRef
1844 macfont_create_attributes_with_spec (Lisp_Object spec)
1846 Lisp_Object tmp, extra;
1847 CFMutableArrayRef langarray = NULL;
1848 CFCharacterSetRef charset = NULL;
1849 CFStringRef charset_string = NULL;
1850 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1851 Lisp_Object script = Qnil;
1852 Lisp_Object registry;
1853 int cf_charset_idx, i;
1854 struct OpenTypeSpec *otspec = NULL;
1856 enum font_property_index index;
1859 } numeric_traits[] =
1860 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1861 {{-0.4, 50}, /* light */
1862 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1863 {0, 100}, /* normal */
1864 {0.24, 140}, /* (semi-bold + normal) / 2 */
1865 {0.4, 200}, /* bold */
1866 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1867 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1868 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1869 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1870 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1872 registry = AREF (spec, FONT_REGISTRY_INDEX);
1874 || EQ (registry, Qascii_0)
1875 || EQ (registry, Qiso10646_1)
1876 || EQ (registry, Qunicode_bmp))
1877 cf_charset_idx = -1;
1882 cf_charset_idx = macfont_get_charset (registry);
1883 if (cf_charset_idx < 0)
1885 charset = cf_charset_table[cf_charset_idx].cf_charset;
1886 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1887 lang = cf_charset_table[cf_charset_idx].lang;
1890 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1893 CFArrayAppendValue (langarray, lang);
1897 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1898 CONSP (extra); extra = XCDR (extra))
1900 Lisp_Object key, val;
1903 key = XCAR (tmp), val = XCDR (tmp);
1904 if (EQ (key, QClang))
1907 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1912 for (; CONSP (val); val = XCDR (val))
1913 if (SYMBOLP (XCAR (val)))
1916 cfstring_create_with_string_noencode (SYMBOL_NAME
1921 CFArrayAppendValue (langarray, lang);
1925 else if (EQ (key, QCotf))
1927 otspec = macfont_get_open_type_spec (val);
1930 script = otspec->script;
1932 else if (EQ (key, QCscript))
1936 if (! NILP (script) && ! charset)
1938 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1940 if (CONSP (chars) && CONSP (CDR (chars)))
1942 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1943 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1945 if (! string || !cs)
1953 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1954 if (CHARACTERP (XCAR (chars)))
1956 UniChar unichars[2];
1958 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1960 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1962 CFStringAppendCharacters (string, unichars, count);
1963 CFCharacterSetAddCharactersInRange (cs, range);
1966 /* CFCharacterSetCreateWithCharactersInString does not
1967 handle surrogate pairs properly as of Mac OS X 10.5. */
1968 charset_string = string;
1972 attributes = CFDictionaryCreateMutable (NULL, 0,
1973 &kCFTypeDictionaryKeyCallBacks,
1974 &kCFTypeDictionaryValueCallBacks);
1978 tmp = AREF (spec, FONT_FAMILY_INDEX);
1979 if (SYMBOLP (tmp) && ! NILP (tmp))
1981 CFStringRef family = macfont_create_family_with_symbol (tmp);
1985 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1990 traits = CFDictionaryCreateMutable (NULL, 4,
1991 &kCFTypeDictionaryKeyCallBacks,
1992 &kCFTypeDictionaryValueCallBacks);
1996 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1998 tmp = AREF (spec, numeric_traits[i].index);
2001 CGPoint *point = numeric_traits[i].points;
2002 CGFloat floatval = (XINT (tmp) >> 8); // XXX
2005 while (point->y < floatval)
2007 if (point == numeric_traits[i].points)
2009 else if (point->y == CGFLOAT_MAX)
2011 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
2012 * ((point->x - (point - 1)->x)
2013 / (point->y - (point - 1)->y)));
2016 else if (floatval < -1.0)
2018 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2021 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2025 if (CFDictionaryGetCount (traits))
2026 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2029 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2032 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2035 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2042 CFRelease (attributes);
2047 if (langarray) CFRelease (langarray);
2048 if (charset && cf_charset_idx < 0) CFRelease (charset);
2049 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2050 if (traits) CFRelease (traits);
2053 if (otspec->nfeatures[0] > 0)
2054 free (otspec->features[0]);
2055 if (otspec->nfeatures[1] > 0)
2056 free (otspec->features[1]);
2064 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2065 CFCharacterSetRef charset,
2067 CFArrayRef languages)
2069 Boolean result = true;
2071 if (charset || VECTORP (chars))
2073 CFCharacterSetRef desc_charset =
2074 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2076 if (desc_charset == NULL)
2081 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2082 else /* VECTORP (chars) */
2086 for (j = 0; j < ASIZE (chars); j++)
2087 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2088 && CFCharacterSetIsLongCharacterMember (desc_charset,
2089 XFASTINT (AREF (chars, j))))
2091 if (j == ASIZE (chars))
2094 CFRelease (desc_charset);
2097 if (result && languages)
2098 result = mac_font_descriptor_supports_languages (desc, languages);
2104 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2105 CTFontSymbolicTraits sym_traits2)
2107 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2110 /* We prefer synthetic bold of italic to synthetic italic of bold
2111 when both bold and italic are available but bold-italic is not
2113 if (diff & kCTFontTraitBold)
2114 distance |= (1 << 0);
2115 if (diff & kCTFontTraitItalic)
2116 distance |= (1 << 1);
2117 if (diff & kCTFontTraitMonoSpace)
2118 distance |= (1 << 2);
2124 macfont_closest_traits_index_p (CFArrayRef traits_array,
2125 CTFontSymbolicTraits target,
2128 CFIndex i, count = CFArrayGetCount (traits_array);
2129 CTFontSymbolicTraits traits;
2132 traits = ((CTFontSymbolicTraits) (uintptr_t)
2133 CFArrayGetValueAtIndex (traits_array, index));
2134 my_distance = macfont_traits_distance (target, traits);
2136 for (i = 0; i < count; i++)
2139 traits = ((CTFontSymbolicTraits) (uintptr_t)
2140 CFArrayGetValueAtIndex (traits_array, i));
2141 if (macfont_traits_distance (target, traits) < my_distance)
2149 macfont_list (struct frame *f, Lisp_Object spec)
2151 Lisp_Object val = Qnil, family, extra;
2153 CFStringRef family_name = NULL;
2154 CFMutableDictionaryRef attributes = NULL, traits;
2155 Lisp_Object chars = Qnil;
2157 CTFontSymbolicTraits synth_sym_traits = 0;
2158 CFArrayRef families;
2159 CFIndex families_count;
2160 CFCharacterSetRef charset = NULL;
2161 CFArrayRef languages = NULL;
2165 family = AREF (spec, FONT_FAMILY_INDEX);
2166 if (! NILP (family))
2168 family_name = macfont_create_family_with_symbol (family);
2169 if (family_name == NULL)
2173 attributes = macfont_create_attributes_with_spec (spec);
2177 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2179 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2180 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2182 traits = ((CFMutableDictionaryRef)
2183 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2185 n = FONT_SLANT_NUMERIC (spec);
2186 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2188 synth_sym_traits |= kCTFontTraitItalic;
2190 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2193 n = FONT_WEIGHT_NUMERIC (spec);
2194 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2196 synth_sym_traits |= kCTFontTraitBold;
2198 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2202 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2204 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2206 if (CFStringHasPrefix (language, CFSTR ("ja"))
2207 || CFStringHasPrefix (language, CFSTR ("ko"))
2208 || CFStringHasPrefix (language, CFSTR ("zh")))
2209 synth_sym_traits |= kCTFontTraitMonoSpace;
2212 /* Create array of families. */
2214 families = CFArrayCreate (NULL, (const void **) &family_name,
2215 1, &kCFTypeArrayCallBacks);
2218 CFStringRef pref_family;
2219 CFIndex families_count, pref_family_index = -1;
2221 families = macfont_copy_available_families_cache ();
2222 if (families == NULL)
2225 families_count = CFArrayGetCount (families);
2227 /* Move preferred family to the front if exists. */
2229 mac_font_create_preferred_family_for_attributes (attributes);
2233 CFArrayGetFirstIndexOfValue (families,
2234 CFRangeMake (0, families_count),
2236 CFRelease (pref_family);
2238 if (pref_family_index > 0)
2240 CFMutableArrayRef mutable_families =
2241 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2243 if (mutable_families)
2245 CFArrayAppendValue (mutable_families,
2246 CFArrayGetValueAtIndex (families,
2247 pref_family_index));
2248 CFArrayAppendArray (mutable_families, families,
2249 CFRangeMake (0, pref_family_index));
2250 if (pref_family_index + 1 < families_count)
2251 CFArrayAppendArray (mutable_families, families,
2252 CFRangeMake (pref_family_index + 1,
2254 - (pref_family_index + 1)));
2255 CFRelease (families);
2256 families = mutable_families;
2261 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2265 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2269 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2272 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2273 if (CONSP (val) && VECTORP (XCDR (val)))
2281 CFRetain (languages);
2282 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2286 extra = AREF (spec, FONT_EXTRA_INDEX);
2287 families_count = CFArrayGetCount (families);
2288 for (i = 0; i < families_count; i++)
2290 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2291 CTFontDescriptorRef pat_desc;
2293 CFIndex descs_count;
2294 CFMutableArrayRef filtered_descs, traits_array;
2298 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2300 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2304 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2305 10.7 returns NULL if pat_desc represents the LastResort font.
2306 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2307 trailing "s") for such a font. */
2308 if (!CFEqual (family_name, CFSTR ("LastResort")))
2309 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2312 CTFontDescriptorRef lr_desc =
2313 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2316 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2317 &kCFTypeArrayCallBacks);
2318 CFRelease (lr_desc);
2323 CFRelease (pat_desc);
2327 descs_count = CFArrayGetCount (descs);
2328 if (descs_count == 0
2329 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2338 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2339 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2340 for (j = 0; j < descs_count; j++)
2342 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2343 CFDictionaryRef dict;
2345 CTFontSymbolicTraits sym_traits;
2347 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2351 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2354 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2358 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2359 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2360 != (spacing >= FONT_SPACING_MONO)))
2363 /* Don't use a color bitmap font until it is supported on
2365 if (sym_traits & kCTFontTraitColorGlyphs)
2369 && !macfont_supports_charset_and_languages_p (desc, charset,
2373 CFArrayAppendValue (filtered_descs, desc);
2374 CFArrayAppendValue (traits_array,
2375 (const void *) (uintptr_t) sym_traits);
2379 descs = filtered_descs;
2380 descs_count = CFArrayGetCount (descs);
2382 for (j = 0; j < descs_count; j++)
2384 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2385 CTFontSymbolicTraits sym_traits =
2386 ((CTFontSymbolicTraits) (uintptr_t)
2387 CFArrayGetValueAtIndex (traits_array, j));
2388 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2390 mask_min = ((synth_sym_traits ^ sym_traits)
2391 & (kCTFontTraitItalic | kCTFontTraitBold));
2392 if (FONT_SLANT_NUMERIC (spec) < 0)
2393 mask_min &= ~kCTFontTraitItalic;
2394 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2395 mask_min &= ~kCTFontTraitBold;
2397 mask_max = (synth_sym_traits & ~sym_traits);
2398 /* Synthetic bold does not work for bitmap-only fonts on Mac
2400 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2402 CFNumberRef format =
2403 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2407 uint32_t format_val;
2409 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2411 && format_val == kCTFontFormatBitmap)
2412 mask_max &= ~kCTFontTraitBold;
2416 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2418 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2419 mmask <= (mask_max & kCTFontTraitMonoSpace);
2420 mmask += kCTFontTraitMonoSpace)
2421 for (bmask = (mask_min & kCTFontTraitBold);
2422 bmask <= (mask_max & kCTFontTraitBold);
2423 bmask += kCTFontTraitBold)
2424 for (imask = (mask_min & kCTFontTraitItalic);
2425 imask <= (mask_max & kCTFontTraitItalic);
2426 imask += kCTFontTraitItalic)
2428 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2431 || macfont_closest_traits_index_p (traits_array,
2432 (sym_traits | synth),
2435 entity = macfont_descriptor_entity (desc, extra, synth);
2436 if (! NILP (entity))
2437 val = Fcons (entity, val);
2442 CFRelease (traits_array);
2446 CFRelease (families);
2447 val = Fnreverse (val);
2453 FONT_ADD_LOG ("macfont-list", spec, val);
2454 if (charset) CFRelease (charset);
2455 if (languages) CFRelease (languages);
2456 if (attributes) CFRelease (attributes);
2457 if (family_name) CFRelease (family_name);
2465 macfont_match (struct frame * frame, Lisp_Object spec)
2467 Lisp_Object entity = Qnil;
2468 CFMutableDictionaryRef attributes;
2469 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2473 attributes = macfont_create_attributes_with_spec (spec);
2476 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2477 CFRelease (attributes);
2481 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2482 CFRelease (pat_desc);
2486 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2492 FONT_ADD_LOG ("macfont-match", spec, entity);
2497 macfont_list_family (struct frame *frame)
2499 Lisp_Object list = Qnil;
2500 CFArrayRef families;
2504 families = macfont_copy_available_families_cache ();
2507 CFIndex i, count = CFArrayGetCount (families);
2509 for (i = 0; i < count; i++)
2510 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2511 CFRelease (families);
2520 macfont_free_entity (Lisp_Object entity)
2522 Lisp_Object val = assq_no_quit (QCfont_entity,
2523 AREF (entity, FONT_EXTRA_INDEX));
2524 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2532 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2534 Lisp_Object val, font_object;
2535 CFStringRef font_name;
2536 struct macfont_info *macfont_info = NULL;
2540 CTFontSymbolicTraits sym_traits;
2542 int len, i, total_width;
2544 CGFloat ascent, descent, leading;
2546 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2548 || XTYPE (XCDR (val)) != Lisp_Misc
2549 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2551 font_name = XSAVE_POINTER (XCDR (val), 0);
2552 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2554 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2559 macfont = CTFontCreateWithName (font_name, size, NULL);
2562 int fontsize = (int) [((NSFont *) macfont) pointSize];
2563 if (fontsize != size) size = fontsize;
2569 font_object = font_build_object (VECSIZE (struct macfont_info),
2570 Qmac_ct, entity, size);
2571 font = XFONT_OBJECT (font_object);
2572 font->pixel_size = size;
2573 font->driver = &macfont_driver;
2574 font->encoding_charset = font->repertory_charset = -1;
2578 macfont_info = (struct macfont_info *) font;
2579 macfont_info->macfont = macfont;
2580 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2582 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2583 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2584 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2587 macfont_info->screen_font = NULL;
2588 macfont_info->cache = macfont_lookup_cache (font_name);
2589 macfont_retain_cache (macfont_info->cache);
2590 macfont_info->metrics = NULL;
2591 macfont_info->metrics_nrows = 0;
2592 macfont_info->synthetic_italic_p = 0;
2593 macfont_info->synthetic_bold_p = 0;
2594 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2595 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2596 if (!(sym_traits & kCTFontTraitItalic)
2597 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2598 macfont_info->synthetic_italic_p = 1;
2599 if (!(sym_traits & kCTFontTraitBold)
2600 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2601 macfont_info->synthetic_bold_p = 1;
2602 if (sym_traits & kCTFontTraitMonoSpace)
2603 macfont_info->spacing = MACFONT_SPACING_MONO;
2604 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2605 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2606 == FONT_SPACING_SYNTHETIC_MONO))
2607 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2608 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2609 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2612 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2614 macfont_info->antialias =
2615 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2617 macfont_info->color_bitmap_p = 0;
2618 if (sym_traits & kCTFontTraitColorGlyphs)
2619 macfont_info->color_bitmap_p = 1;
2621 glyph = macfont_get_glyph_for_character (font, ' ');
2622 if (glyph != kCGFontIndexInvalid)
2623 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2625 /* dirty workaround */
2626 font->space_width = pixel_size;
2628 total_width = font->space_width;
2629 for (i = 1; i < 95; i++)
2631 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2632 if (glyph == kCGFontIndexInvalid)
2634 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2637 font->average_width = total_width / 95;
2639 font->average_width = font->space_width; /* XXX */
2641 if (!(macfont_info->screen_font
2642 && mac_screen_font_get_metrics (macfont_info->screen_font,
2643 &ascent, &descent, &leading)))
2645 CFStringRef family_name;
2647 ascent = CTFontGetAscent (macfont);
2648 descent = CTFontGetDescent (macfont);
2649 leading = CTFontGetLeading (macfont);
2650 /* AppKit and WebKit do some adjustment to the heights of
2651 Courier, Helvetica, and Times. */
2652 family_name = CTFontCopyFamilyName (macfont);
2655 if (CFEqual (family_name, CFSTR ("Courier"))
2656 || CFEqual (family_name, CFSTR ("Helvetica"))
2657 || CFEqual (family_name, CFSTR ("Times")))
2658 ascent += (ascent + descent) * .15f;
2659 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2664 CFRelease (family_name);
2667 font->ascent = ascent + 0.5f;
2668 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2669 if (CONSP (val) && !NILP (XCDR (val)))
2670 font->descent = descent + 0.5f;
2672 font->descent = descent + leading + 0.5f;
2673 font->height = font->ascent + font->descent;
2675 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2676 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2680 /* Unfortunately Xft doesn't provide a way to get minimum char
2681 width. So, we use space_width instead. */
2682 font->min_width = font->max_width = font->space_width; /* XXX */
2684 font->baseline_offset = 0;
2685 font->relative_compose = 0;
2686 font->default_ascent = 0;
2687 font->vertical_centering = 0;
2693 macfont_close (struct font *font)
2695 struct macfont_info *macfont_info = (struct macfont_info *) font;
2697 if (macfont_info->cache)
2702 CFRelease (macfont_info->macfont);
2703 CGFontRelease (macfont_info->cgfont);
2704 if (macfont_info->screen_font)
2705 CFRelease (macfont_info->screen_font);
2706 macfont_release_cache (macfont_info->cache);
2707 for (i = 0; i < macfont_info->metrics_nrows; i++)
2708 if (macfont_info->metrics[i])
2709 xfree (macfont_info->metrics[i]);
2710 if (macfont_info->metrics)
2711 xfree (macfont_info->metrics);
2712 macfont_info->cache = NULL;
2718 macfont_has_char (Lisp_Object font, int c)
2721 CFCharacterSetRef charset;
2724 if (FONT_ENTITY_P (font))
2729 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2731 name = XSAVE_POINTER (val, 0);
2732 charset = macfont_get_cf_charset_for_name (name);
2735 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2737 result = CFCharacterSetIsLongCharacterMember (charset, c);
2744 macfont_encode_char (struct font *font, int c)
2749 glyph = macfont_get_glyph_for_character (font, c);
2752 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2756 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2757 struct font_metrics *metrics)
2762 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2763 for (i = 1; i < nglyphs; i++)
2765 struct font_metrics m;
2766 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2771 if (width + m.lbearing < metrics->lbearing)
2772 metrics->lbearing = width + m.lbearing;
2773 if (width + m.rbearing > metrics->rbearing)
2774 metrics->rbearing = width + m.rbearing;
2775 if (m.ascent > metrics->ascent)
2776 metrics->ascent = m.ascent;
2777 if (m.descent > metrics->descent)
2778 metrics->descent = m.descent;
2785 metrics->width = width;
2789 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2790 bool with_background)
2792 struct frame * f = s->f;
2793 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2794 CGRect background_rect;
2795 CGPoint text_position;
2798 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2799 bool no_antialias_p =
2800 (NILP (ns_antialias_text)
2801 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2802 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2803 && font_size <= macfont_antialias_threshold));
2804 int len = to - from;
2805 struct face *face = s->face;
2806 CGContextRef context;
2810 if (with_background)
2811 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2812 s->width, FONT_HEIGHT (s->font));
2814 background_rect = CGRectNull;
2816 text_position = CGPointMake (x, -y);
2817 glyphs = xmalloc (sizeof (CGGlyph) * len);
2819 CGFloat advance_delta = 0;
2821 CGFloat total_width = 0;
2823 positions = xmalloc (sizeof (CGPoint) * len);
2824 for (i = 0; i < len; i++)
2828 glyphs[i] = s->char2b[from + i];
2829 width = (s->padding_p ? 1
2830 : macfont_glyph_extents (s->font, glyphs[i],
2831 NULL, &advance_delta,
2833 positions[i].x = total_width + advance_delta;
2835 total_width += width;
2839 context = [[NSGraphicsContext currentContext] graphicsPort];
2840 CGContextSaveGState (context);
2842 if (!CGRectIsNull (background_rect))
2844 if (s->hl == DRAW_MOUSE_FACE)
2846 face = FACE_FROM_ID_OR_NULL (s->f,
2847 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2849 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2851 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2852 CGContextFillRects (context, &background_rect, 1);
2855 if (macfont_info->cgfont)
2857 CGAffineTransform atfm;
2859 CGContextScaleCTM (context, 1, -1);
2860 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2861 if (macfont_info->synthetic_italic_p)
2862 atfm = synthetic_italic_atfm;
2864 atfm = CGAffineTransformIdentity;
2865 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2867 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2869 /* Stroke line width for text drawing is not correctly
2870 scaled on Retina display/HiDPI mode when drawn to screen
2871 (whereas it is correctly scaled when drawn to bitmaps),
2872 and synthetic bold looks thinner on such environments.
2873 Apple says there are no plans to address this issue
2874 (rdar://11644870) currently. So we add a workaround. */
2875 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
2876 CGContextSetLineWidth (context, synthetic_bold_factor * font_size
2877 * [[FRAME_NS_VIEW(f) window] backingScaleFactor]);
2879 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2881 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2884 CGContextSetShouldAntialias (context, false);
2886 CGContextSetTextMatrix (context, atfm);
2887 CGContextSetTextPosition (context, text_position.x, text_position.y);
2889 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2890 if (macfont_info->color_bitmap_p
2891 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2892 && CTFontDrawGlyphs != NULL
2898 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2903 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2905 CGContextSetFont (context, macfont_info->cgfont);
2906 CGContextSetFontSize (context, font_size);
2907 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2914 CGContextRestoreGState (context);
2922 macfont_shape (Lisp_Object lgstring)
2924 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2925 struct macfont_info *macfont_info = (struct macfont_info *) font;
2926 CTFontRef macfont = macfont_info->macfont;
2927 ptrdiff_t glyph_len, len, i, j;
2930 CFIndex *nonbmp_indices;
2933 struct mac_glyph_layout *glyph_layouts;
2935 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2937 for (i = 0; i < glyph_len; i++)
2939 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2943 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2949 if (INT_MAX / 2 < len)
2950 memory_full (SIZE_MAX);
2952 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2953 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2954 for (i = j = 0; i < len; i++)
2956 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2958 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2960 nonbmp_indices[j] = i + j;
2964 nonbmp_indices[j] = len + j; /* sentinel */
2968 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2972 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2973 if (macfont_info->screen_font)
2974 used = mac_screen_font_shape (macfont_info->screen_font, string,
2975 glyph_layouts, glyph_len);
2977 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2988 for (i = 0; i < used; i++)
2990 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2991 struct mac_glyph_layout *gl = glyph_layouts + i;
2993 struct font_metrics metrics;
2994 int xoff, yoff, wadjust;
2998 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2999 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
3002 from = gl->comp_range.location;
3003 /* Convert UTF-16 index to UTF-32. */
3005 while (nonbmp_indices[j] < from)
3008 LGLYPH_SET_FROM (lglyph, from);
3010 to = gl->comp_range.location + gl->comp_range.length;
3011 /* Convert UTF-16 index to UTF-32. */
3012 while (nonbmp_indices[j] < to)
3015 LGLYPH_SET_TO (lglyph, to - 1);
3017 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3018 the composition is trivial. */
3022 if (unichars[gl->string_index] >= 0xD800
3023 && unichars[gl->string_index] < 0xDC00)
3024 c = (((unichars[gl->string_index] - 0xD800) << 10)
3025 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3027 c = unichars[gl->string_index];
3028 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3030 LGLYPH_SET_CHAR (lglyph, c);
3034 unsigned long cc = gl->glyph_id;
3035 LGLYPH_SET_CODE (lglyph, cc);
3038 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3039 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3040 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3041 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3042 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3043 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3045 xoff = lround (gl->advance_delta);
3046 yoff = lround (- gl->baseline_delta);
3047 wadjust = lround (gl->advance);
3048 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3052 vec = Fmake_vector (make_number (3), Qnil);
3053 ASET (vec, 0, make_number (xoff));
3054 ASET (vec, 1, make_number (yoff));
3055 ASET (vec, 2, make_number (wadjust));
3056 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3062 return make_number (used);
3065 /* Structures for the UVS subtable (format 14) in the cmap table. */
3066 typedef UInt8 UINT24[3];
3068 #pragma pack(push, 1)
3069 struct variation_selector_record
3071 UINT24 var_selector;
3072 UInt32 default_uvs_offset, non_default_uvs_offset;
3077 UInt32 length, num_var_selector_records;
3078 struct variation_selector_record variation_selector_records[1];
3080 #define SIZEOF_UVS_TABLE_HEADER \
3081 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3083 struct unicode_value_range
3085 UINT24 start_unicode_value;
3086 UInt8 additional_count;
3088 struct default_uvs_table {
3089 UInt32 num_unicode_value_ranges;
3090 struct unicode_value_range unicode_value_ranges[1];
3092 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3093 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3097 UINT24 unicode_value;
3100 struct non_default_uvs_table
3102 UInt32 num_uvs_mappings;
3103 struct uvs_mapping uvs_mappings[1];
3105 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3106 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3109 /* Read big endian values. The argument LVAL must be an lvalue. */
3110 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3111 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3112 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3113 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3114 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3115 /* Succeeding one byte should also be accessible. */
3116 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3117 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3119 /* Return UVS subtable for the specified FONT. If the subtable is not
3120 found or ill-formatted, then return NULL. */
3123 mac_font_copy_uvs_table (CTFontRef font)
3125 CFDataRef cmap_table, uvs_table = NULL;
3127 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3128 kCTFontTableOptionNoOptions);
3131 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3132 struct uvs_table *uvs;
3133 struct variation_selector_record *records;
3134 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3137 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3141 cmap_len = CFDataGetLength (cmap_table);
3142 if (sizeof_sfntCMapHeader > cmap_len)
3145 ntables = BUINT16_VALUE (cmap->numTables);
3146 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3147 / sizeof_sfntCMapEncoding))
3150 for (i = 0; i < ntables; i++)
3151 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3152 == kFontUnicodePlatform)
3153 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3154 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3156 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3160 || uvs_offset > cmap_len
3161 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3164 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3165 uvs_len = BUINT32_VALUE (uvs->length);
3166 if (uvs_len > cmap_len - uvs_offset
3167 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3170 if (BUINT16_VALUE (uvs->format) != 14)
3173 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3174 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3175 / sizeof (struct variation_selector_record)))
3178 records = uvs->variation_selector_records;
3179 for (i = 0; i < nrecords; i++)
3181 UInt32 default_uvs_offset, non_default_uvs_offset;
3183 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3184 if (default_uvs_offset)
3186 struct default_uvs_table *default_uvs;
3189 if (default_uvs_offset > uvs_len
3190 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3191 > uvs_len - default_uvs_offset))
3194 default_uvs = ((struct default_uvs_table *)
3195 ((UInt8 *) uvs + default_uvs_offset));
3196 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3197 if (nranges > ((uvs_len - default_uvs_offset
3198 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3199 / sizeof (struct unicode_value_range)))
3201 /* Now 2 * nranges can't overflow, so we can safely use
3202 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3203 mac_font_get_glyphs_for_variants. */
3206 non_default_uvs_offset =
3207 BUINT32_VALUE (records[i].non_default_uvs_offset);
3208 if (non_default_uvs_offset)
3210 struct non_default_uvs_table *non_default_uvs;
3213 if (non_default_uvs_offset > uvs_len
3214 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3215 > uvs_len - non_default_uvs_offset))
3218 non_default_uvs = ((struct non_default_uvs_table *)
3219 ((UInt8 *) uvs + non_default_uvs_offset));
3220 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3221 if (nmappings > ((uvs_len - non_default_uvs_offset
3222 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3223 / sizeof (struct uvs_mapping)))
3225 /* Now 2 * nmappings can't overflow, so we can safely
3226 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3227 in mac_font_get_glyphs_for_variants. */
3231 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3234 CFRelease (cmap_table);
3240 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3241 sequence consisting of the given base character C and each
3242 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3243 result (explained below) into the corresponding GLYPHS[i]. If the
3244 entry is found in the Default UVS Table, then the result is 0. If
3245 the entry is found in the Non-Default UVS Table, then the result is
3246 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3247 elements in SELECTORS must be sorted in strictly increasing
3251 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3252 const UTF32Char selectors[], CGGlyph glyphs[],
3255 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3256 struct variation_selector_record *records = uvs->variation_selector_records;
3258 UInt32 ir, nrecords;
3259 dispatch_queue_t queue =
3260 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3261 dispatch_group_t group = dispatch_group_create ();
3263 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3266 while (i < count && ir < nrecords)
3268 UInt32 default_uvs_offset, non_default_uvs_offset;
3270 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3272 glyphs[i++] = kCGFontIndexInvalid;
3275 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3281 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3282 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3283 non_default_uvs_offset =
3284 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3285 dispatch_group_async (group, queue, ^{
3286 glyphs[i] = kCGFontIndexInvalid;
3288 if (default_uvs_offset)
3290 struct default_uvs_table *default_uvs =
3291 (struct default_uvs_table *) ((UInt8 *) uvs
3292 + default_uvs_offset);
3293 struct unicode_value_range *ranges =
3294 default_uvs->unicode_value_ranges;
3298 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3301 UInt32 mid = (lo + hi) / 2;
3303 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3309 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3310 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3314 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3316 struct non_default_uvs_table *non_default_uvs =
3317 (struct non_default_uvs_table *) ((UInt8 *) uvs
3318 + non_default_uvs_offset);
3319 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3323 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3326 UInt32 mid = (lo + hi) / 2;
3328 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3334 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3335 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3342 glyphs[i++] = kCGFontIndexInvalid;
3343 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3344 dispatch_release (group);
3348 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3350 CFDataRef uvs_table;
3351 CTCharacterCollection uvs_collection;
3355 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3359 UTF32Char selectors[256];
3360 CGGlyph glyphs[256];
3362 for (i = 0; i < 16; i++)
3363 selectors[i] = 0xFE00 + i;
3364 for (; i < 256; i++)
3365 selectors[i] = 0xE0100 + (i - 16);
3366 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3367 for (i = 0; i < 256; i++)
3369 CGGlyph glyph = glyphs[i];
3371 if (uvs_collection != kCTCharacterCollectionIdentityMapping
3372 && glyph != kCGFontIndexInvalid)
3373 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3374 if (glyph == kCGFontIndexInvalid)
3378 variations[i] = (glyph ? glyph
3379 : macfont_get_glyph_for_character (font, c));
3389 static const char *const macfont_booleans[] = {
3395 static const char *const macfont_non_booleans[] = {
3403 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3405 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3409 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3410 CFArrayRef languages)
3412 Boolean result = true;
3413 CFArrayRef desc_languages =
3414 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3416 if (desc_languages == NULL)
3420 CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
3421 CFIndex i, languages_count = CFArrayGetCount (languages);
3423 for (i = 0; i < languages_count; i++)
3425 CFStringRef language = CFArrayGetValueAtIndex (languages, i);
3427 if (!CFArrayContainsValue (desc_languages, range, language)
3428 /* PingFang SC contains "zh" and "zh-Hant" as covered
3429 languages, but does not contain "zh-Hans". */
3430 && !(CFEqual (language, CFSTR ("zh-Hans"))
3431 && CFArrayContainsValue (desc_languages, range,
3438 CFRelease (desc_languages);
3445 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3447 CFStringRef result = NULL;
3448 CFStringRef charset_string =
3449 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3451 if (charset_string && CFStringGetLength (charset_string) > 0)
3453 CFStringRef keys[] = {
3454 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3455 kCTLanguageAttributeName
3457 CFSTR ("NSLanguage")
3460 CFTypeRef values[] = {NULL};
3461 CFIndex num_values = 0;
3462 CFArrayRef languages
3463 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3465 if (languages && CFArrayGetCount (languages) > 0)
3467 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3468 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3471 CFCharacterSetRef charset =
3472 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3474 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3479 CFAttributedStringRef attr_string = NULL;
3480 CTLineRef ctline = NULL;
3481 CFDictionaryRef attrs
3482 = CFDictionaryCreate (NULL, (const void **) keys,
3483 (const void **) values, num_values,
3484 &kCFTypeDictionaryKeyCallBacks,
3485 &kCFTypeDictionaryValueCallBacks);
3489 attr_string = CFAttributedStringCreate (NULL, charset_string,
3495 ctline = CTLineCreateWithAttributedString (attr_string);
3496 CFRelease (attr_string);
3500 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3501 CFIndex i, nruns = CFArrayGetCount (runs);
3504 for (i = 0; i < nruns; i++)
3506 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3507 CFDictionaryRef attributes = CTRunGetAttributes (run);
3508 CTFontRef font_in_run;
3510 if (attributes == NULL)
3513 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3514 if (font_in_run == NULL)
3518 else if (!mac_font_equal_in_postscript_name (font,
3522 if (nruns > 0 && i == nruns)
3523 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3532 static inline double
3533 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3535 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3539 static inline CGRect
3540 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3542 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3547 mac_font_create_available_families (void)
3549 CFMutableArrayRef families = NULL;
3550 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3554 CFIndex i, count = CFArrayGetCount (orig_families);
3556 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3558 for (i = 0; i < count; i++)
3560 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3562 if (!CFStringHasPrefix (family, CFSTR ("."))
3563 && (CTFontManagerCompareFontFamilyNames (family,
3564 CFSTR ("LastResort"),
3566 != kCFCompareEqualTo))
3567 CFArrayAppendValue (families, family);
3569 CFRelease (orig_families);
3576 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3579 CFStringRef name1, name2;
3585 name1 = CTFontCopyPostScriptName (font1);
3588 name2 = CTFontCopyPostScriptName (font2);
3591 result = CFEqual (name1, name2);
3601 mac_font_create_line_with_string_and_font (CFStringRef string,
3604 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3605 CFTypeRef values[] = {NULL, NULL};
3606 CFDictionaryRef attributes = NULL;
3607 CFAttributedStringRef attr_string = NULL;
3608 CTLineRef ctline = NULL;
3609 float float_zero = 0.0f;
3611 values[0] = macfont;
3612 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3615 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3616 (const void **) values,
3618 &kCFTypeDictionaryKeyCallBacks,
3619 &kCFTypeDictionaryValueCallBacks);
3620 CFRelease (values[1]);
3624 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3625 CFRelease (attributes);
3629 ctline = CTLineCreateWithAttributedString (attr_string);
3630 CFRelease (attr_string);
3634 /* Abandon if ctline contains some fonts other than the
3636 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3637 CFIndex i, nruns = CFArrayGetCount (runs);
3639 for (i = 0; i < nruns; i++)
3641 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3642 CFDictionaryRef attributes = CTRunGetAttributes (run);
3643 CTFontRef font_in_run;
3645 if (attributes == NULL)
3648 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3649 if (font_in_run == NULL)
3651 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3665 mac_font_shape (CTFontRef font, CFStringRef string,
3666 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3668 CFIndex used, result = 0;
3669 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3674 used = CTLineGetGlyphCount (ctline);
3675 if (used <= glyph_len)
3677 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3678 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3679 CGFloat total_advance = 0;
3680 CFIndex total_glyph_count = 0;
3682 for (k = 0; k < ctrun_count; k++)
3684 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3685 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3686 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3687 CFRange string_range, comp_range, range;
3688 CFIndex *permutation;
3690 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3691 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3695 #define RIGHT_TO_LEFT_P permutation
3697 /* Now the `comp_range' member of struct mac_glyph_layout is
3698 temporarily used as a work area such that:
3699 glbuf[i].comp_range.location =
3700 min {compRange[i + 1].location, ...,
3701 compRange[glyph_count - 1].location,
3702 maxRange (stringRangeForCTRun)}
3703 glbuf[i].comp_range.length = maxRange (compRange[i])
3704 where compRange[i] is the range of composed characters
3705 containing i-th glyph. */
3706 string_range = CTRunGetStringRange (ctrun);
3707 min_location = string_range.location + string_range.length;
3708 for (i = 0; i < glyph_count; i++)
3710 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3711 CFIndex glyph_index;
3714 if (!RIGHT_TO_LEFT_P)
3715 glyph_index = glyph_count - i - 1;
3718 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3721 CFStringGetRangeOfComposedCharactersAtIndex (string,
3723 gl->comp_range.location = min_location;
3724 gl->comp_range.length = rng.location + rng.length;
3725 if (rng.location < min_location)
3726 min_location = rng.location;
3729 /* Fill the `comp_range' member of struct mac_glyph_layout,
3730 and setup a permutation for right-to-left text. */
3731 comp_range = CFRangeMake (string_range.location, 0);
3732 range = CFRangeMake (0, 0);
3735 struct mac_glyph_layout *gl =
3736 glbuf + range.location + range.length;
3738 if (gl->comp_range.length
3739 > comp_range.location + comp_range.length)
3740 comp_range.length = gl->comp_range.length - comp_range.location;
3741 min_location = gl->comp_range.location;
3744 if (min_location >= comp_range.location + comp_range.length)
3746 comp_range.length = min_location - comp_range.location;
3747 for (i = 0; i < range.length; i++)
3749 glbuf[range.location + i].comp_range = comp_range;
3750 if (RIGHT_TO_LEFT_P)
3751 permutation[range.location + i] =
3752 range.location + range.length - i - 1;
3755 comp_range = CFRangeMake (min_location, 0);
3756 range.location += range.length;
3758 if (range.location == glyph_count)
3763 /* Then fill the remaining members. */
3764 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3767 struct mac_glyph_layout *gl;
3771 if (!RIGHT_TO_LEFT_P)
3772 gl = glbuf + range.location;
3777 src = glyph_count - 1 - range.location;
3778 dest = permutation[src];
3782 CFIndex tmp = gl->string_index;
3784 gl->string_index = glbuf[src].string_index;
3785 glbuf[src].string_index = tmp;
3788 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3790 CTRunGetPositions (ctrun, range, &position);
3791 max_x = position.x + CTRunGetTypographicBounds (ctrun, range,
3793 max_x = max (max_x, total_advance);
3794 gl->advance_delta = position.x - total_advance;
3795 gl->baseline_delta = position.y;
3796 gl->advance = max_x - total_advance;
3797 total_advance = max_x;
3800 if (RIGHT_TO_LEFT_P)
3801 xfree (permutation);
3803 #undef RIGHT_TO_LEFT_P
3805 total_glyph_count += glyph_count;
3815 /* The function below seems to cause a memory leak for the CFString
3816 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3817 10.6.3. For now, we use the NSGlyphInfo version instead. */
3818 #if USE_CT_GLYPH_INFO
3820 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3823 CGGlyph result = kCGFontIndexInvalid;
3824 UniChar characters[] = {0xfffd};
3826 CFAttributedStringRef attr_string = NULL;
3827 CTLineRef ctline = NULL;
3829 string = CFStringCreateWithCharacters (NULL, characters,
3830 ARRAYELTS (characters));
3834 CTGlyphInfoRef glyph_info =
3835 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3836 CFDictionaryRef attributes = NULL;
3840 CFStringRef keys[] = {kCTFontAttributeName,
3841 kCTGlyphInfoAttributeName};
3842 CFTypeRef values[] = {font, glyph_info};
3844 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3845 (const void **) values,
3847 &kCFTypeDictionaryKeyCallBacks,
3848 &kCFTypeDictionaryValueCallBacks);
3849 CFRelease (glyph_info);
3853 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3854 CFRelease (attributes);
3860 ctline = CTLineCreateWithAttributedString (attr_string);
3861 CFRelease (attr_string);
3865 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3867 if (CFArrayGetCount (runs) > 0)
3869 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3870 CFDictionaryRef attributes = CTRunGetAttributes (run);
3874 CTFontRef font_in_run =
3875 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3878 && mac_font_equal_in_postscript_name (font_in_run, font))
3880 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3881 if (result >= CTFontGetGlyphCount (font))
3882 result = kCGFontIndexInvalid;
3894 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3896 CFArrayRef result = NULL;
3898 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3899 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3900 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3903 CTFontRef user_font =
3904 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3908 CFArrayRef languages =
3909 CFArrayCreate (NULL, (const void **) &language, 1,
3910 &kCFTypeArrayCallBacks);
3914 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3916 CFRelease (languages);
3918 CFRelease (user_font);
3921 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3922 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3924 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3925 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3929 for (i = 0; macfont_language_default_font_names[i].language; i++)
3931 if (CFEqual (macfont_language_default_font_names[i].language,
3934 CFMutableArrayRef descriptors =
3935 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3942 macfont_language_default_font_names[i].font_names[j];
3945 CFDictionaryRef attributes =
3946 CFDictionaryCreate (NULL,
3948 &kCTFontNameAttribute),
3950 &macfont_language_default_font_names[i].font_names[j]),
3951 1, &kCFTypeDictionaryKeyCallBacks,
3952 &kCFTypeDictionaryValueCallBacks);
3956 CTFontDescriptorRef pat_desc =
3957 CTFontDescriptorCreateWithAttributes (attributes);
3961 CTFontDescriptorRef descriptor =
3962 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3966 CFArrayAppendValue (descriptors, descriptor);
3967 CFRelease (descriptor);
3969 CFRelease (pat_desc);
3971 CFRelease (attributes);
3974 result = descriptors;
3986 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3987 CFArrayRef languages)
3989 CFStringRef result = NULL;
3990 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3991 CFArrayRef descriptors =
3992 mac_font_copy_default_descriptors_for_language (language);
3996 CFIndex i, count = CFArrayGetCount (descriptors);
3998 for (i = 0; i < count; i++)
4000 CTFontDescriptorRef descriptor =
4001 CFArrayGetValueAtIndex (descriptors, i);
4003 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4006 CFStringRef family =
4007 CTFontDescriptorCopyAttribute (descriptor,
4008 kCTFontFamilyNameAttribute);
4011 if (!CFStringHasPrefix (family, CFSTR ("."))
4012 && !CFEqual (family, CFSTR ("LastResort")))
4022 CFRelease (descriptors);
4029 macfont_get_nsctfont (struct font *font)
4031 struct macfont_info *macfont_info = (struct macfont_info *) font;
4032 CTFontRef macfont = macfont_info->macfont;
4034 return (void *) macfont;
4038 mac_register_font_driver (struct frame *f)
4040 register_font_driver (&macfont_driver, f);
4045 syms_of_macfont (void)
4047 /* Core Text, for macOS. */
4048 DEFSYM (Qmac_ct, "mac-ct");
4049 register_font_driver (&macfont_driver, NULL);
4051 /* The font property key specifying the font design destination. The
4052 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4053 text. (See the documentation of X Logical Font Description
4054 Conventions.) In the Mac font driver, 1 means the screen font is
4055 used for calculating some glyph metrics. You can see the
4056 difference with Monaco 8pt or 9pt, for example. */
4057 DEFSYM (QCdestination, ":destination");
4059 /* The boolean-valued font property key specifying the use of leading. */
4060 DEFSYM (QCminspace, ":minspace");
4062 macfont_family_cache = Qnil;
4063 staticpro (&macfont_family_cache);