1 /* Font driver on Mac OSX 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 struct font_driver macfont_driver;
43 static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
44 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
45 static CFArrayRef mac_font_create_available_families (void);
46 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
47 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
49 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
51 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
52 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
53 struct mac_glyph_layout *, CFIndex);
54 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
55 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
57 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
61 struct macfont_metrics;
63 /* The actual structure for Mac font that can be cast to struct font. */
70 ScreenFontRef screen_font;
71 struct macfont_cache *cache;
72 struct macfont_metrics **metrics;
74 bool_bf synthetic_italic_p : 1;
75 bool_bf synthetic_bold_p : 1;
77 unsigned antialias : 2;
78 bool_bf color_bitmap_p : 1;
81 /* Values for the `spacing' member in `struct macfont_info'. */
85 MACFONT_SPACING_PROPORTIONAL,
87 MACFONT_SPACING_SYNTHETIC_MONO,
90 /* Values for the `antialias' member in `struct macfont_info'. */
94 MACFONT_ANTIALIAS_DEFAULT,
95 MACFONT_ANTIALIAS_OFF,
99 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
100 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
101 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
103 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
104 static const CGFloat synthetic_bold_factor = 0.024;
106 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
107 CTFontSymbolicTraits *);
108 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
110 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
111 CTFontSymbolicTraits);
112 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
113 static int macfont_glyph_extents (struct font *, CGGlyph,
114 struct font_metrics *, CGFloat *, int);
115 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
116 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
120 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
122 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
123 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
125 CGGlyph [], CFIndex);
127 /* From CFData to a lisp string. Always returns a unibyte string. */
130 cfdata_to_lisp (CFDataRef data)
132 CFIndex len = CFDataGetLength (data);
133 Lisp_Object result = make_uninit_string (len);
135 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
142 /* From CFString to a lisp string. Returns a unibyte string
143 containing a UTF-8 byte sequence. */
146 cfstring_to_lisp_nodecode (CFStringRef string)
148 Lisp_Object result = Qnil;
150 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
154 CFIndex i, length = CFStringGetLength (string);
156 for (i = 0; i < length; i++)
157 if (CFStringGetCharacterAtIndex (string, i) == 0)
161 return make_unibyte_string (s, strlen (s));
164 data = CFStringCreateExternalRepresentation (NULL, string,
165 kCFStringEncodingUTF8, '?');
168 result = cfdata_to_lisp (data);
175 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
176 cfstring_create_with_utf8_cstring, this function preserves NUL
180 cfstring_create_with_string_noencode (Lisp_Object s)
182 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
183 kCFStringEncodingUTF8, false);
186 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
187 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
188 kCFStringEncodingMacRoman, false);
194 mac_font_get_weight (CTFontRef font)
196 NSFont *nsFont = (NSFont *) font;
198 return [[NSFontManager sharedFontManager] weightOfFont:nsFont];
202 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
204 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
206 return advancement.width;
209 #if !USE_CT_GLYPH_INFO
211 mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
214 CGGlyph result = kCGFontIndexInvalid;
215 NSFont *nsFont = (NSFont *) font;
216 unichar characters[] = {0xfffd};
218 [NSString stringWithCharacters:characters
219 length:ARRAYELTS (characters)];
220 NSGlyphInfo *glyphInfo =
221 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
222 collection:collection
224 NSDictionary *attributes =
225 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
226 glyphInfo,NSGlyphInfoAttributeName,nil];
227 NSTextStorage *textStorage =
228 [[NSTextStorage alloc] initWithString:string
229 attributes:attributes];
230 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
231 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
232 NSFont *fontInTextStorage;
234 [layoutManager addTextContainer:textContainer];
235 [textContainer release];
236 [textStorage addLayoutManager:layoutManager];
237 [layoutManager release];
240 (void) [layoutManager glyphRangeForTextContainer:textContainer];
242 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
243 effectiveRange:NULL];
244 if (fontInTextStorage == nsFont
245 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
247 NSGlyph glyph = [layoutManager glyphAtIndex:0];
249 if (glyph < [nsFont numberOfGlyphs])
253 [textStorage release];
260 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
262 NSFont *result, *font;
264 font = [NSFont fontWithName:((NSString *) name) size:size];
265 result = [font screenFont];
267 return (ScreenFontRef)[result retain];
272 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
273 CGFloat *descent, CGFloat *leading)
275 NSFont *nsFont = [(NSFont *)font printerFont];
276 NSTextStorage *textStorage;
277 NSLayoutManager *layoutManager;
278 NSTextContainer *textContainer;
280 NSPoint spaceLocation;
283 textStorage = [[NSTextStorage alloc] initWithString:@" "];
284 layoutManager = [[NSLayoutManager alloc] init];
285 textContainer = [[NSTextContainer alloc] init];
287 [textStorage setFont:nsFont];
288 [textContainer setLineFragmentPadding:0];
289 [layoutManager setUsesScreenFonts:YES];
291 [layoutManager addTextContainer:textContainer];
292 [textContainer release];
293 [textStorage addLayoutManager:layoutManager];
294 [layoutManager release];
296 if (!(textStorage && layoutManager && textContainer))
298 [textStorage release];
303 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
304 effectiveRange:NULL];
305 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
306 [textStorage release];
308 *ascent = spaceLocation.y;
309 *descent = NSHeight (usedRect) - spaceLocation.y;
311 descender = [nsFont descender];
312 if (- descender < *descent)
314 *leading = *descent + descender;
315 *descent = - descender;
322 mac_font_shape_1 (NSFont *font, NSString *string,
323 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
328 NSTextStorage *textStorage;
329 NSLayoutManager *layoutManager;
330 NSTextContainer *textContainer;
331 NSUInteger stringLength;
332 NSPoint spaceLocation;
333 NSUInteger used, numberOfGlyphs;
335 textStorage = [[NSTextStorage alloc] initWithString:string];
336 layoutManager = [[NSLayoutManager alloc] init];
337 textContainer = [[NSTextContainer alloc] init];
339 /* Append a trailing space to measure baseline position. */
340 [textStorage appendAttributedString:([[[NSAttributedString alloc]
341 initWithString:@" "] autorelease])];
342 [textStorage setFont:font];
343 [textContainer setLineFragmentPadding:0];
344 [layoutManager setUsesScreenFonts:screen_font_p];
346 [layoutManager addTextContainer:textContainer];
347 [textContainer release];
348 [textStorage addLayoutManager:layoutManager];
349 [layoutManager release];
351 if (!(textStorage && layoutManager && textContainer))
353 [textStorage release];
358 stringLength = [string length];
361 (void) [layoutManager glyphRangeForTextContainer:textContainer];
363 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
365 /* Remove the appended trailing space because otherwise it may
366 generate a wrong result for a right-to-left text. */
367 [textStorage beginEditing];
368 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
369 [textStorage endEditing];
370 (void) [layoutManager glyphRangeForTextContainer:textContainer];
373 while (i < stringLength)
376 NSFont *fontInTextStorage =
377 [textStorage attribute:NSFontAttributeName atIndex:i
378 longestEffectiveRange:&range
379 inRange:(NSMakeRange (0, stringLength))];
381 if (!(fontInTextStorage == font
382 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
384 i = NSMaxRange (range);
386 if (i < stringLength)
387 /* Make the test `used <= glyph_len' below fail if textStorage
388 contained some fonts other than the specified one. */
389 used = glyph_len + 1;
392 NSRange range = NSMakeRange (0, stringLength);
394 range = [layoutManager glyphRangeForCharacterRange:range
395 actualCharacterRange:NULL];
396 numberOfGlyphs = NSMaxRange (range);
397 used = numberOfGlyphs;
398 for (i = 0; i < numberOfGlyphs; i++)
399 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
403 if (0 < used && used <= glyph_len)
405 NSUInteger glyphIndex, prevGlyphIndex;
406 unsigned char bidiLevel;
407 NSUInteger *permutation;
408 NSRange compRange, range;
409 CGFloat totalAdvance;
412 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
415 /* For now we assume the direction is not changed within the
417 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
418 glyphs:NULL characterIndexes:NULL
419 glyphInscriptions:NULL elasticBits:NULL
420 bidiLevels:&bidiLevel];
422 permutation = xmalloc (sizeof (NSUInteger) * used);
426 #define RIGHT_TO_LEFT_P permutation
428 /* Fill the `comp_range' member of struct mac_glyph_layout, and
429 setup a permutation for right-to-left text. */
430 compRange = NSMakeRange (0, 0);
431 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
434 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
435 NSUInteger characterIndex =
436 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
438 gl->string_index = characterIndex;
440 if (characterIndex >= NSMaxRange (compRange))
442 compRange.location = NSMaxRange (compRange);
445 NSRange characterRange =
447 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
450 NSMaxRange (characterRange) - compRange.location;
451 [layoutManager glyphRangeForCharacterRange:compRange
452 actualCharacterRange:&characterRange];
453 characterIndex = NSMaxRange (characterRange) - 1;
455 while (characterIndex >= NSMaxRange (compRange));
458 for (i = 0; i < range.length; i++)
459 permutation[range.location + i] = NSMaxRange (range) - i - 1;
461 range = NSMakeRange (NSMaxRange (range), 0);
464 gl->comp_range.location = compRange.location;
465 gl->comp_range.length = compRange.length;
467 while (++glyphIndex < numberOfGlyphs)
468 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
472 for (i = 0; i < range.length; i++)
473 permutation[range.location + i] = NSMaxRange (range) - i - 1;
475 /* Then fill the remaining members. */
476 glyphIndex = prevGlyphIndex = 0;
477 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
480 if (!RIGHT_TO_LEFT_P)
487 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
488 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
489 inTextContainer:textContainer rectCount:&nrects];
491 totalAdvance = NSMaxX (glyphRects[0]);
494 for (i = 0; i < used; i++)
496 struct mac_glyph_layout *gl;
498 NSUInteger nextGlyphIndex;
503 if (!RIGHT_TO_LEFT_P)
504 gl = glyph_layouts + i;
507 NSUInteger dest = permutation[i];
509 gl = glyph_layouts + dest;
512 CFIndex tmp = gl->string_index;
514 gl->string_index = glyph_layouts[i].string_index;
515 glyph_layouts[i].string_index = tmp;
518 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
520 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
521 gl->baseline_delta = spaceLocation.y - location.y;
523 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
526 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
529 if (!RIGHT_TO_LEFT_P)
533 if (prevGlyphIndex == 0)
534 glyphRange = NSMakeRange (0, nextGlyphIndex);
536 glyphRange = NSMakeRange (glyphIndex,
537 nextGlyphIndex - glyphIndex);
540 rectArrayForGlyphRange:glyphRange
541 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
542 inTextContainer:textContainer rectCount:&nrects];
543 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
544 gl->advance_delta = location.x - totalAdvance;
545 gl->advance = maxX - totalAdvance;
552 if (nextGlyphIndex == numberOfGlyphs)
553 glyphRange = NSMakeRange (prevGlyphIndex,
554 numberOfGlyphs - prevGlyphIndex);
556 glyphRange = NSMakeRange (prevGlyphIndex,
557 glyphIndex + 1 - prevGlyphIndex);
560 rectArrayForGlyphRange:glyphRange
561 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
562 inTextContainer:textContainer rectCount:&nrects];
563 minX = min (NSMinX (glyphRects[0]), totalAdvance);
564 gl->advance = totalAdvance - minX;
566 gl->advance_delta = location.x - totalAdvance;
569 prevGlyphIndex = glyphIndex + 1;
570 glyphIndex = nextGlyphIndex;
576 #undef RIGHT_TO_LEFT_P
580 [textStorage release];
586 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
587 struct mac_glyph_layout *glyph_layouts,
590 return mac_font_shape_1 ([(NSFont *)font printerFont],
592 glyph_layouts, glyph_len, YES);
596 get_cgcolor(unsigned long idx, struct frame *f)
598 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
600 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
601 NSInteger noc = [nsColor numberOfComponents];
602 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
605 [nsColor getComponents: components];
606 cgColor = CGColorCreate (colorSpace, components);
611 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
613 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
614 CGContextSetFillColorWithColor (context, refcol_) ; \
615 CGColorRelease (refcol_); \
617 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
619 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
620 CGContextSetFillColorWithColor (context, refcol_); \
621 CGColorRelease (refcol_); \
623 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
625 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
626 CGContextSetStrokeColorWithColor (context, refcol_); \
627 CGColorRelease (refcol_); \
632 /* Mac font driver. */
638 /* characters to distinguish the charset from the others */
640 /* additional constraint by language */
643 CFCharacterSetRef cf_charset;
644 CFStringRef cf_charset_string;
645 } cf_charset_table[] =
646 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
647 { "iso8859-2", { 0x00A0, 0x010E }},
648 { "iso8859-3", { 0x00A0, 0x0108 }},
649 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
650 { "iso8859-5", { 0x00A0, 0x0401 }},
651 { "iso8859-6", { 0x00A0, 0x060C }},
652 { "iso8859-7", { 0x00A0, 0x0384 }},
653 { "iso8859-8", { 0x00A0, 0x05D0 }},
654 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
655 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
656 { "iso8859-11", { 0x00A0, 0x0E01 }},
657 { "iso8859-13", { 0x00A0, 0x201C }},
658 { "iso8859-14", { 0x00A0, 0x0174 }},
659 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
660 { "iso8859-16", { 0x00A0, 0x0218}},
661 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
662 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
663 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
664 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
665 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
666 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
667 { "cns11643.1992-3", { 0x201A9 }},
668 { "cns11643.1992-4", { 0x20057 }},
669 { "cns11643.1992-5", { 0x20000 }},
670 { "cns11643.1992-6", { 0x20003 }},
671 { "cns11643.1992-7", { 0x20055 }},
672 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
673 { "jisx0212.1990-0", { 0x4E44 }},
674 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
675 { "jisx0213.2000-2", { 0xFA49 }},
676 { "jisx0213.2004-1", { 0x20B9F }},
677 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
678 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
679 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
680 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
681 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
682 { "unicode-sip", { 0x20000 }},
686 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
689 CFStringRef language;
690 CFStringRef font_names[3];
691 } macfont_language_default_font_names[] = {
692 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
693 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
695 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
696 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
698 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
699 CFSTR ("STXihei"), /* 10.4 - 10.5 */
701 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
702 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
708 static CGFloat macfont_antialias_threshold;
711 macfont_update_antialias_threshold (void)
717 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
718 kCFPreferencesCurrentApplication,
721 macfont_antialias_threshold = threshold;
724 static inline Lisp_Object
725 macfont_intern_prop_cfstring (CFStringRef cfstring)
727 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
729 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
732 static inline CFIndex
733 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
744 unichars[0] = (c >> 10) + 0xD800;
745 unichars[1] = (c & 0x3FF) + 0xDC00;
752 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
753 CTFontSymbolicTraits *sym_traits)
757 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
758 OS X 10.6 when the value is greater than or equal to 1 << 31. */
759 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
761 *sym_traits = (CTFontSymbolicTraits) sint64_value;
770 mac_font_descriptor_get_adjusted_weight (CTFontDescriptorRef desc, CGFloat val)
772 long percent_val = lround (val * 100);
774 if (percent_val == -40)
776 CTFontRef font = NULL;
778 CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
782 font = CTFontCreateWithName (name, 0, NULL);
787 CFIndex weight = mac_font_get_weight (font);
789 /* Workaround for crash when displaying Oriya characters
790 with Arial Unicode MS on OS X 10.11. */
801 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
802 Lisp_Object spec_or_entity)
805 CFDictionaryRef dict;
809 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
812 ASET (spec_or_entity, FONT_FAMILY_INDEX,
813 macfont_intern_prop_cfstring (str));
816 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
820 enum font_property_index index;
823 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
825 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
826 {{-0.4, 50}, /* light */
827 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
828 {0, 100}, /* normal */
829 {0.24, 140}, /* (semi-bold + normal) / 2 */
830 {0.4, 200}, /* bold */
831 {CGFLOAT_MAX, CGFLOAT_MAX}},
832 mac_font_descriptor_get_adjusted_weight},
833 {FONT_SLANT_INDEX, kCTFontSlantTrait,
834 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
835 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
836 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
839 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
841 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
842 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
844 CGPoint *point = numeric_traits[i].points;
846 if (numeric_traits[i].adjust_func)
847 floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
848 while (point->x < floatval)
850 if (point == numeric_traits[i].points)
852 else if (point->x == CGFLOAT_MAX)
854 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
855 * ((point->y - (point - 1)->y)
856 / (point->x - (point - 1)->x)));
857 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
858 make_number (lround (floatval)));
862 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
865 CTFontSymbolicTraits sym_traits;
868 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
869 spacing = (sym_traits & kCTFontTraitMonoSpace
870 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
871 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
876 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
877 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
878 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
880 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
886 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
887 CTFontSymbolicTraits synth_sym_traits)
890 CFDictionaryRef dict;
891 CTFontSymbolicTraits sym_traits = 0;
894 entity = font_make_entity ();
896 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
897 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
899 macfont_store_descriptor_attributes (desc, entity);
901 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
904 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
907 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
910 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
911 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
912 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
913 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
914 font_put_extra (entity, QCfont_entity,
915 make_save_ptr_int ((void *) name, sym_traits));
916 if (synth_sym_traits & kCTFontTraitItalic)
917 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
918 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
919 if (synth_sym_traits & kCTFontTraitBold)
920 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
921 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
922 if (synth_sym_traits & kCTFontTraitMonoSpace)
923 ASET (entity, FONT_SPACING_INDEX,
924 make_number (FONT_SPACING_SYNTHETIC_MONO));
929 /* Cache for font family name symbols vs CFStrings. A value of nil
930 means the cache has been invalidated. Otherwise the value is a Lisp
931 hash table whose keys are symbols and the value for a key is either
932 nil (no corresponding family name) or a Lisp save value wrapping the
933 corresponding family name in CFString. */
935 static Lisp_Object macfont_family_cache;
938 macfont_invalidate_family_cache (void)
940 if (HASH_TABLE_P (macfont_family_cache))
942 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
943 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
945 for (i = 0; i < size; ++i)
946 if (!NILP (HASH_HASH (h, i)))
948 Lisp_Object value = HASH_VALUE (h, i);
950 if (SAVE_VALUEP (value))
951 CFRelease (XSAVE_POINTER (value, 0));
953 macfont_family_cache = Qnil;
958 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
960 if (HASH_TABLE_P (macfont_family_cache))
962 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
963 ptrdiff_t i = hash_lookup (h, symbol, NULL);
967 Lisp_Object value = HASH_VALUE (h, i);
969 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
979 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
981 struct Lisp_Hash_Table *h;
986 if (!HASH_TABLE_P (macfont_family_cache))
987 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
989 h = XHASH_TABLE (macfont_family_cache);
990 i = hash_lookup (h, symbol, &hash);
991 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
994 Lisp_Object old_value = HASH_VALUE (h, i);
996 if (SAVE_VALUEP (old_value))
997 CFRelease (XSAVE_POINTER (old_value, 0));
998 set_hash_value_slot (h, i, value);
1001 hash_put (h, symbol, value, hash);
1004 /* Cache of all the available font family names except "LastResort"
1005 and those start with ".". NULL means the cache has been invalidated.
1006 Otherwise, the value is CFArray of CFStrings and the elements are
1007 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1008 OS X 10.6 and later). */
1010 static CFArrayRef macfont_available_families_cache = NULL;
1013 macfont_invalidate_available_families_cache (void)
1015 if (macfont_available_families_cache)
1017 CFRelease (macfont_available_families_cache);
1018 macfont_available_families_cache = NULL;
1023 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1025 CFStringRef name, const void *object,
1026 CFDictionaryRef userInfo)
1028 macfont_invalidate_family_cache ();
1029 macfont_invalidate_available_families_cache ();
1033 macfont_init_font_change_handler (void)
1035 static bool initialized = false;
1041 CFNotificationCenterAddObserver
1042 (CFNotificationCenterGetLocalCenter (), NULL,
1043 macfont_handle_font_change_notification,
1044 kCTFontManagerRegisteredFontsChangedNotification,
1045 NULL, CFNotificationSuspensionBehaviorCoalesce);
1049 macfont_copy_available_families_cache (void)
1051 macfont_init_font_change_handler ();
1053 if (macfont_available_families_cache == NULL)
1054 macfont_available_families_cache = mac_font_create_available_families ();
1056 return (macfont_available_families_cache
1057 ? CFRetain (macfont_available_families_cache) : NULL);
1061 macfont_create_family_with_symbol (Lisp_Object symbol)
1063 CFStringRef result = NULL, family_name;
1064 CFDictionaryRef attributes = NULL;
1065 CTFontDescriptorRef pat_desc = NULL;
1067 if (macfont_get_family_cache_if_present (symbol, &result))
1068 return result ? CFRetain (result) : NULL;
1070 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1074 CFDictionaryCreate (NULL,
1075 (const void **) &kCTFontFamilyNameAttribute,
1076 (const void **) &family_name, 1,
1077 &kCFTypeDictionaryKeyCallBacks,
1078 &kCFTypeDictionaryValueCallBacks);
1079 CFRelease (family_name);
1083 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1084 CFRelease (attributes);
1088 CTFontDescriptorRef desc =
1089 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1094 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1097 macfont_set_family_cache (symbol, result);
1098 CFRelease (pat_desc);
1104 #define WIDTH_FRAC_BITS (4)
1105 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1107 struct macfont_metrics
1109 unsigned char lbearing_low, rbearing_low;
1110 signed lbearing_high : 4, rbearing_high : 4;
1111 unsigned char ascent_low, descent_low;
1112 signed ascent_high : 4, descent_high : 4;
1114 /* These two members are used for fixed-point representation of
1115 glyph width. The `width_int' member is an integer that is
1116 closest to the width. The `width_frac' member is the fractional
1117 adjustment representing a value in [-.5, .5], multiplied by
1118 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1119 the advance delta for centering instead of the glyph width. */
1120 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1123 #define METRICS_VALUE(metrics, member) \
1124 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1125 #define METRICS_SET_VALUE(metrics, member, value) \
1126 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1127 (metrics)->member##_high = tmp >> 8;} while (0)
1131 METRICS_INVALID = -1, /* metrics entry is invalid */
1132 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1135 #define METRICS_STATUS(metrics) \
1136 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1137 #define METRICS_SET_STATUS(metrics, status) \
1138 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1139 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1141 #define METRICS_NCOLS_PER_ROW (128)
1142 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1143 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1146 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1147 struct font_metrics *metrics, CGFloat *advance_delta,
1148 int force_integral_p)
1150 struct macfont_info *macfont_info = (struct macfont_info *) font;
1151 CTFontRef macfont = macfont_info->macfont;
1153 struct macfont_metrics *cache;
1156 row = glyph / METRICS_NCOLS_PER_ROW;
1157 col = glyph % METRICS_NCOLS_PER_ROW;
1158 if (row >= macfont_info->metrics_nrows)
1160 macfont_info->metrics =
1161 xrealloc (macfont_info->metrics,
1162 sizeof (struct macfont_metrics *) * (row + 1));
1163 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1164 (sizeof (struct macfont_metrics *)
1165 * (row + 1 - macfont_info->metrics_nrows)));
1166 macfont_info->metrics_nrows = row + 1;
1168 if (macfont_info->metrics[row] == NULL)
1170 struct macfont_metrics *new;
1173 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1174 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1175 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1176 macfont_info->metrics[row] = new;
1178 cache = macfont_info->metrics[row] + col;
1180 if (METRICS_STATUS (cache) == METRICS_INVALID)
1184 if (macfont_info->screen_font)
1185 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1187 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1189 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1190 advance delta value. */
1191 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1192 fwidth = (font->pixel_size - fwidth) / 2;
1193 cache->width_int = lround (fwidth);
1194 cache->width_frac = lround ((fwidth - cache->width_int)
1195 * WIDTH_FRAC_SCALE);
1196 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1198 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1199 width = font->pixel_size;
1201 width = cache->width_int;
1205 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1207 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1209 if (macfont_info->synthetic_italic_p)
1211 /* We assume the members a, b, c, and d in
1212 synthetic_italic_atfm are non-negative. */
1214 CGPointApplyAffineTransform (bounds.origin,
1215 synthetic_italic_atfm);
1217 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1219 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1221 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1223 bounds = CGRectInset (bounds, d, d);
1225 switch (macfont_info->spacing)
1227 case MACFONT_SPACING_PROPORTIONAL:
1228 bounds.origin.x += - (cache->width_frac
1229 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1231 case MACFONT_SPACING_MONO:
1233 case MACFONT_SPACING_SYNTHETIC_MONO:
1234 bounds.origin.x += (cache->width_int
1235 + (cache->width_frac
1236 / (CGFloat) WIDTH_FRAC_SCALE));
1239 if (bounds.size.width > 0)
1241 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1242 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1243 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1245 bounds = CGRectIntegral (bounds);
1246 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1247 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1248 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1249 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1251 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1252 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1253 metrics->width = width;
1254 metrics->ascent = METRICS_VALUE (cache, ascent);
1255 metrics->descent = METRICS_VALUE (cache, descent);
1260 switch (macfont_info->spacing)
1262 case MACFONT_SPACING_PROPORTIONAL:
1263 *advance_delta = (force_integral_p ? 0
1264 : - (cache->width_frac
1265 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1267 case MACFONT_SPACING_MONO:
1270 case MACFONT_SPACING_SYNTHETIC_MONO:
1271 *advance_delta = (force_integral_p ? cache->width_int
1273 + (cache->width_frac
1274 / (CGFloat) WIDTH_FRAC_SCALE)));
1282 static CFMutableDictionaryRef macfont_cache_dictionary;
1284 /* Threshold used in row_nkeys_or_perm. This must be less than or
1285 equal to the number of rows that are invalid as BMP (i.e., from
1286 U+D800 to U+DFFF). */
1287 #define ROW_PERM_OFFSET (8)
1289 /* The number of glyphs that can be stored in a value for a single
1290 entry of CFDictionary. */
1291 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1293 struct macfont_cache
1295 int reference_count;
1296 CFCharacterSetRef cf_charset;
1298 /* The cached glyph for a BMP character c is stored in
1299 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1300 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1301 unsigned char row_nkeys_or_perm[256];
1304 /* Number of rows for which the BMP cache is allocated so far.
1305 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1308 /* The cached glyph for a character c is stored as the (c %
1309 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1310 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1311 not stored here if row_nkeys_or_perm[c / 256] >=
1313 CFMutableDictionaryRef dictionary;
1317 /* UVS (Unicode Variation Sequence) subtable data, which is of
1318 type CFDataRef if available. NULL means it is not initialized
1319 yet. kCFNull means the subtable is not found and there is no
1320 suitable fallback table for this font. */
1323 /* Character collection specifying the destination of the mapping
1324 provided by `table' above. If `table' is obtained from the UVS
1325 subtable in the font cmap table, then the value of this member
1326 should be kCTCharacterCollectionIdentityMapping. */
1327 CTCharacterCollection collection;
1331 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1332 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1333 static void macfont_release_cache (struct macfont_cache *);
1334 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1335 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1336 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1337 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1338 CTCharacterCollection, CGFontIndex);
1339 static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
1341 static struct macfont_cache *
1342 macfont_lookup_cache (CFStringRef key)
1344 struct macfont_cache *cache;
1346 if (macfont_cache_dictionary == NULL)
1348 macfont_cache_dictionary =
1349 CFDictionaryCreateMutable (NULL, 0,
1350 &kCFTypeDictionaryKeyCallBacks, NULL);
1354 cache = ((struct macfont_cache *)
1355 CFDictionaryGetValue (macfont_cache_dictionary, key));
1359 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1363 cache = xzalloc (sizeof (struct macfont_cache));
1364 /* Treat the LastResort font as if it contained glyphs for
1365 all characters. This may look too rough, but neither
1366 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1367 for this font is correct for non-BMP characters on Mac OS
1369 if (CFEqual (key, CFSTR ("LastResort")))
1371 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1374 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1376 if (cache->cf_charset == NULL)
1377 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1378 CFDictionaryAddValue (macfont_cache_dictionary, key,
1379 (const void *) cache);
1380 CFRelease (macfont);
1387 static struct macfont_cache *
1388 macfont_retain_cache (struct macfont_cache *cache)
1390 cache->reference_count++;
1396 macfont_release_cache (struct macfont_cache *cache)
1398 if (--cache->reference_count == 0)
1402 for (i = 0; i < cache->glyph.nrows; i++)
1403 xfree (cache->glyph.matrix[i]);
1404 xfree (cache->glyph.matrix);
1405 if (cache->glyph.dictionary)
1406 CFRelease (cache->glyph.dictionary);
1407 memset (&cache->glyph, 0, sizeof (cache->glyph));
1408 if (cache->uvs.table)
1409 CFRelease (cache->uvs.table);
1410 memset (&cache->uvs, 0, sizeof (cache->uvs));
1414 static CFCharacterSetRef
1415 macfont_get_cf_charset (struct font *font)
1417 struct macfont_info *macfont_info = (struct macfont_info *) font;
1419 return macfont_info->cache->cf_charset;
1422 static CFCharacterSetRef
1423 macfont_get_cf_charset_for_name (CFStringRef name)
1425 struct macfont_cache *cache = macfont_lookup_cache (name);
1427 return cache->cf_charset;
1431 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1433 struct macfont_info *macfont_info = (struct macfont_info *) font;
1434 CTFontRef macfont = macfont_info->macfont;
1435 struct macfont_cache *cache = macfont_info->cache;
1437 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1440 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1442 if (nkeys_or_perm < ROW_PERM_OFFSET)
1444 UniChar unichars[256], ch;
1448 dispatch_queue_t queue;
1449 dispatch_group_t group = NULL;
1453 CFMutableDictionaryRef dictionary;
1454 uintptr_t key, value;
1458 if (cache->glyph.dictionary == NULL)
1459 cache->glyph.dictionary =
1460 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1461 dictionary = cache->glyph.dictionary;
1462 key = c / NGLYPHS_IN_VALUE;
1463 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1464 value = ((uintptr_t)
1465 CFDictionaryGetValue (dictionary, (const void *) key));
1466 glyph = (value >> nshifts);
1470 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1473 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1475 glyph = kCGFontIndexInvalid;
1478 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1479 value |= ((uintptr_t) glyph << nshifts);
1480 CFDictionarySetValue (dictionary, (const void *) key,
1481 (const void *) value);
1487 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1488 group = dispatch_group_create ();
1489 dispatch_group_async (group, queue, ^{
1492 nkeys = nkeys_or_perm;
1493 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1494 if (CFDictionaryContainsKey (dictionary,
1495 (const void *) key))
1497 CFDictionaryRemoveValue (dictionary,
1498 (const void *) key);
1506 for (i = 0; i < 256; i++)
1509 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1510 unichars[len++] = ch;
1513 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1516 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1519 int next = unichars[len - 1] % 256;
1522 glyphs[i] = kCGFontIndexInvalid;
1525 glyphs[i] = glyphs[len];
1532 glyphs[i] = kCGFontIndexInvalid;
1534 nrows = cache->glyph.nrows;
1535 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1536 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1538 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1539 sizeof (CGGlyph *) * nrows);
1540 cache->glyph.matrix[nrows - 1] = glyphs;
1541 cache->glyph.nrows = nrows;
1545 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1546 dispatch_release (group);
1550 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1554 uintptr_t key, value;
1558 if (cache->glyph.dictionary == NULL)
1559 cache->glyph.dictionary =
1560 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1561 key = c / NGLYPHS_IN_VALUE;
1562 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1563 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1564 (const void *) key);
1565 glyph = (value >> nshifts);
1568 UniChar unichars[2];
1570 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1572 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1575 glyph = kCGFontIndexInvalid;
1577 value |= ((uintptr_t) glyph << nshifts);
1578 CFDictionarySetValue (cache->glyph.dictionary,
1579 (const void *) key, (const void *) value);
1587 macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1590 struct macfont_info *macfont_info = (struct macfont_info *) font;
1591 CTFontRef macfont = macfont_info->macfont;
1594 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1598 macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1600 struct macfont_info *macfont_info = (struct macfont_info *) font;
1601 CTFontRef macfont = macfont_info->macfont;
1602 struct macfont_cache *cache = macfont_info->cache;
1603 CFDataRef result = NULL;
1605 if (cache->uvs.table == NULL)
1607 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1608 CTCharacterCollection uvs_collection =
1609 kCTCharacterCollectionIdentityMapping;
1611 if (uvs_table == NULL
1612 && mac_font_get_glyph_for_cid (macfont,
1613 kCTCharacterCollectionAdobeJapan1,
1614 6480) != kCGFontIndexInvalid)
1616 /* If the glyph for U+4E55 is accessible via its CID 6480,
1617 then we use the Adobe-Japan1 UVS table, which maps a
1618 variation sequence to a CID, as a fallback. */
1619 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1621 if (mac_uvs_table_adobe_japan1 == NULL)
1622 mac_uvs_table_adobe_japan1 =
1623 CFDataCreateWithBytesNoCopy (NULL,
1624 mac_uvs_table_adobe_japan1_bytes,
1625 sizeof (mac_uvs_table_adobe_japan1_bytes),
1627 if (mac_uvs_table_adobe_japan1)
1629 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1630 uvs_collection = kCTCharacterCollectionAdobeJapan1;
1633 if (uvs_table == NULL)
1634 cache->uvs.table = kCFNull;
1636 cache->uvs.table = uvs_table;
1637 cache->uvs.collection = uvs_collection;
1640 if (cache->uvs.table != kCFNull)
1642 result = cache->uvs.table;
1643 *collection = cache->uvs.collection;
1649 static Lisp_Object macfont_get_cache (struct frame *);
1650 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1651 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1652 static Lisp_Object macfont_list_family (struct frame *);
1653 static void macfont_free_entity (Lisp_Object);
1654 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1655 static void macfont_close (struct font *);
1656 static int macfont_has_char (Lisp_Object, int);
1657 static unsigned macfont_encode_char (struct font *, int);
1658 static void macfont_text_extents (struct font *, unsigned int *, int,
1659 struct font_metrics *);
1660 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1661 static Lisp_Object macfont_shape (Lisp_Object);
1662 static int macfont_variation_glyphs (struct font *, int c,
1663 unsigned variations[256]);
1664 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1666 static struct font_driver macfont_driver =
1668 LISP_INITIALLY_ZERO, /* Qmac_ct */
1669 0, /* case insensitive */
1673 macfont_list_family,
1674 macfont_free_entity,
1677 NULL, /* prepare_face */
1678 NULL, /* done_face */
1680 macfont_encode_char,
1681 macfont_text_extents,
1683 NULL, /* get_bitmap */
1684 NULL, /* free_bitmap */
1685 NULL, /* anchor_point */
1686 NULL, /* otf_capability */
1687 NULL, /* otf_drive */
1688 NULL, /* start_for_frame */
1689 NULL, /* end_for_frame */
1692 macfont_variation_glyphs,
1693 macfont_filter_properties,
1697 macfont_get_cache (struct frame * f)
1699 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1701 return (dpyinfo->name_list_element);
1705 macfont_get_charset (Lisp_Object registry)
1707 char *str = SSDATA (SYMBOL_NAME (registry));
1708 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1712 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1716 else if (str[i] == '*')
1723 regexp = make_unibyte_string (re, j);
1724 for (i = 0; cf_charset_table[i].name; i++)
1725 if (fast_c_string_match_ignore_case
1726 (regexp, cf_charset_table[i].name,
1727 strlen (cf_charset_table[i].name)) >= 0)
1729 if (! cf_charset_table[i].name)
1731 if (! cf_charset_table[i].cf_charset)
1733 int *uniquifier = cf_charset_table[i].uniquifier;
1734 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1737 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1741 for (j = 0; uniquifier[j]; j++)
1743 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1745 CFCharacterSetAddCharactersInRange (charset,
1746 CFRangeMake (uniquifier[j], 1));
1749 string = CFStringCreateWithCharacters (NULL, unichars, count);
1752 CFRelease (charset);
1755 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1757 CFRelease (charset);
1758 /* CFCharacterSetCreateWithCharactersInString does not handle
1759 surrogate pairs properly as of Mac OS X 10.5. */
1760 cf_charset_table[i].cf_charset_string = string;
1768 unsigned int script_tag, langsys_tag;
1770 unsigned int *features[2];
1773 #define OTF_SYM_TAG(SYM, TAG) \
1775 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1776 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1779 #define OTF_TAG_STR(TAG, P) \
1781 (P)[0] = (char) (TAG >> 24); \
1782 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1783 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1784 (P)[3] = (char) (TAG & 0xFF); \
1788 static struct OpenTypeSpec *
1789 macfont_get_open_type_spec (Lisp_Object otf_spec)
1791 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1798 spec->script = XCAR (otf_spec);
1799 if (! NILP (spec->script))
1801 OTF_SYM_TAG (spec->script, spec->script_tag);
1802 val = assq_no_quit (spec->script, Votf_script_alist);
1803 if (CONSP (val) && SYMBOLP (XCDR (val)))
1804 spec->script = XCDR (val);
1806 spec->script = Qnil;
1809 spec->script_tag = 0x44464C54; /* "DFLT" */
1810 otf_spec = XCDR (otf_spec);
1811 spec->langsys_tag = 0;
1812 if (! NILP (otf_spec))
1814 val = XCAR (otf_spec);
1816 OTF_SYM_TAG (val, spec->langsys_tag);
1817 otf_spec = XCDR (otf_spec);
1819 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1820 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1824 val = XCAR (otf_spec);
1827 len = Flength (val);
1829 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1831 : malloc (XINT (len) * sizeof *spec->features[i]));
1832 if (! spec->features[i])
1834 if (i > 0 && spec->features[0])
1835 free (spec->features[0]);
1839 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1841 if (NILP (XCAR (val)))
1847 OTF_SYM_TAG (XCAR (val), tag);
1848 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1851 spec->nfeatures[i] = j;
1856 static CFMutableDictionaryRef
1857 macfont_create_attributes_with_spec (Lisp_Object spec)
1859 Lisp_Object tmp, extra;
1860 CFMutableArrayRef langarray = NULL;
1861 CFCharacterSetRef charset = NULL;
1862 CFStringRef charset_string = NULL;
1863 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1864 Lisp_Object script = Qnil;
1865 Lisp_Object registry;
1866 int cf_charset_idx, i;
1867 struct OpenTypeSpec *otspec = NULL;
1869 enum font_property_index index;
1872 } numeric_traits[] =
1873 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1874 {{-0.4, 50}, /* light */
1875 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1876 {0, 100}, /* normal */
1877 {0.24, 140}, /* (semi-bold + normal) / 2 */
1878 {0.4, 200}, /* bold */
1879 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1880 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1881 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1882 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1883 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1885 registry = AREF (spec, FONT_REGISTRY_INDEX);
1887 || EQ (registry, Qascii_0)
1888 || EQ (registry, Qiso10646_1)
1889 || EQ (registry, Qunicode_bmp))
1890 cf_charset_idx = -1;
1895 cf_charset_idx = macfont_get_charset (registry);
1896 if (cf_charset_idx < 0)
1898 charset = cf_charset_table[cf_charset_idx].cf_charset;
1899 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1900 lang = cf_charset_table[cf_charset_idx].lang;
1903 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1906 CFArrayAppendValue (langarray, lang);
1910 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1911 CONSP (extra); extra = XCDR (extra))
1913 Lisp_Object key, val;
1916 key = XCAR (tmp), val = XCDR (tmp);
1917 if (EQ (key, QClang))
1920 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1925 for (; CONSP (val); val = XCDR (val))
1926 if (SYMBOLP (XCAR (val)))
1929 cfstring_create_with_string_noencode (SYMBOL_NAME
1934 CFArrayAppendValue (langarray, lang);
1938 else if (EQ (key, QCotf))
1940 otspec = macfont_get_open_type_spec (val);
1943 script = otspec->script;
1945 else if (EQ (key, QCscript))
1949 if (! NILP (script) && ! charset)
1951 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1953 if (CONSP (chars) && CONSP (CDR (chars)))
1955 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1956 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1958 if (! string || !cs)
1966 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1967 if (CHARACTERP (XCAR (chars)))
1969 UniChar unichars[2];
1971 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1973 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1975 CFStringAppendCharacters (string, unichars, count);
1976 CFCharacterSetAddCharactersInRange (cs, range);
1979 /* CFCharacterSetCreateWithCharactersInString does not
1980 handle surrogate pairs properly as of Mac OS X 10.5. */
1981 charset_string = string;
1985 attributes = CFDictionaryCreateMutable (NULL, 0,
1986 &kCFTypeDictionaryKeyCallBacks,
1987 &kCFTypeDictionaryValueCallBacks);
1991 tmp = AREF (spec, FONT_FAMILY_INDEX);
1992 if (SYMBOLP (tmp) && ! NILP (tmp))
1994 CFStringRef family = macfont_create_family_with_symbol (tmp);
1998 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
2003 traits = CFDictionaryCreateMutable (NULL, 4,
2004 &kCFTypeDictionaryKeyCallBacks,
2005 &kCFTypeDictionaryValueCallBacks);
2009 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
2011 tmp = AREF (spec, numeric_traits[i].index);
2014 CGPoint *point = numeric_traits[i].points;
2015 CGFloat floatval = (XINT (tmp) >> 8); // XXX
2018 while (point->y < floatval)
2020 if (point == numeric_traits[i].points)
2022 else if (point->y == CGFLOAT_MAX)
2024 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
2025 * ((point->x - (point - 1)->x)
2026 / (point->y - (point - 1)->y)));
2029 else if (floatval < -1.0)
2031 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2034 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2038 if (CFDictionaryGetCount (traits))
2039 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2042 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2045 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2048 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2055 CFRelease (attributes);
2060 if (langarray) CFRelease (langarray);
2061 if (charset && cf_charset_idx < 0) CFRelease (charset);
2062 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2063 if (traits) CFRelease (traits);
2066 if (otspec->nfeatures[0] > 0)
2067 free (otspec->features[0]);
2068 if (otspec->nfeatures[1] > 0)
2069 free (otspec->features[1]);
2077 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2078 CFCharacterSetRef charset,
2080 CFArrayRef languages)
2082 Boolean result = true;
2084 if (charset || VECTORP (chars))
2086 CFCharacterSetRef desc_charset =
2087 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2089 if (desc_charset == NULL)
2094 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2095 else /* VECTORP (chars) */
2099 for (j = 0; j < ASIZE (chars); j++)
2100 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2101 && CFCharacterSetIsLongCharacterMember (desc_charset,
2102 XFASTINT (AREF (chars, j))))
2104 if (j == ASIZE (chars))
2107 CFRelease (desc_charset);
2110 if (result && languages)
2111 result = mac_font_descriptor_supports_languages (desc, languages);
2117 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2118 CTFontSymbolicTraits sym_traits2)
2120 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2123 /* We prefer synthetic bold of italic to synthetic italic of bold
2124 when both bold and italic are available but bold-italic is not
2126 if (diff & kCTFontTraitBold)
2127 distance |= (1 << 0);
2128 if (diff & kCTFontTraitItalic)
2129 distance |= (1 << 1);
2130 if (diff & kCTFontTraitMonoSpace)
2131 distance |= (1 << 2);
2137 macfont_closest_traits_index_p (CFArrayRef traits_array,
2138 CTFontSymbolicTraits target,
2141 CFIndex i, count = CFArrayGetCount (traits_array);
2142 CTFontSymbolicTraits traits;
2145 traits = ((CTFontSymbolicTraits) (uintptr_t)
2146 CFArrayGetValueAtIndex (traits_array, index));
2147 my_distance = macfont_traits_distance (target, traits);
2149 for (i = 0; i < count; i++)
2152 traits = ((CTFontSymbolicTraits) (uintptr_t)
2153 CFArrayGetValueAtIndex (traits_array, i));
2154 if (macfont_traits_distance (target, traits) < my_distance)
2162 macfont_list (struct frame *f, Lisp_Object spec)
2164 Lisp_Object val = Qnil, family, extra;
2166 CFStringRef family_name = NULL;
2167 CFMutableDictionaryRef attributes = NULL, traits;
2168 Lisp_Object chars = Qnil;
2170 CTFontSymbolicTraits synth_sym_traits = 0;
2171 CFArrayRef families;
2172 CFIndex families_count;
2173 CFCharacterSetRef charset = NULL;
2174 CFArrayRef languages = NULL;
2178 family = AREF (spec, FONT_FAMILY_INDEX);
2179 if (! NILP (family))
2181 family_name = macfont_create_family_with_symbol (family);
2182 if (family_name == NULL)
2186 attributes = macfont_create_attributes_with_spec (spec);
2190 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2192 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2193 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2195 traits = ((CFMutableDictionaryRef)
2196 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2198 n = FONT_SLANT_NUMERIC (spec);
2199 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2201 synth_sym_traits |= kCTFontTraitItalic;
2203 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2206 n = FONT_WEIGHT_NUMERIC (spec);
2207 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2209 synth_sym_traits |= kCTFontTraitBold;
2211 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2215 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2217 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2219 if (CFStringHasPrefix (language, CFSTR ("ja"))
2220 || CFStringHasPrefix (language, CFSTR ("ko"))
2221 || CFStringHasPrefix (language, CFSTR ("zh")))
2222 synth_sym_traits |= kCTFontTraitMonoSpace;
2225 /* Create array of families. */
2227 families = CFArrayCreate (NULL, (const void **) &family_name,
2228 1, &kCFTypeArrayCallBacks);
2231 CFStringRef pref_family;
2232 CFIndex families_count, pref_family_index = -1;
2234 families = macfont_copy_available_families_cache ();
2235 if (families == NULL)
2238 families_count = CFArrayGetCount (families);
2240 /* Move preferred family to the front if exists. */
2242 mac_font_create_preferred_family_for_attributes (attributes);
2246 CFArrayGetFirstIndexOfValue (families,
2247 CFRangeMake (0, families_count),
2249 CFRelease (pref_family);
2251 if (pref_family_index > 0)
2253 CFMutableArrayRef mutable_families =
2254 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2256 if (mutable_families)
2258 CFArrayAppendValue (mutable_families,
2259 CFArrayGetValueAtIndex (families,
2260 pref_family_index));
2261 CFArrayAppendArray (mutable_families, families,
2262 CFRangeMake (0, pref_family_index));
2263 if (pref_family_index + 1 < families_count)
2264 CFArrayAppendArray (mutable_families, families,
2265 CFRangeMake (pref_family_index + 1,
2267 - (pref_family_index + 1)));
2268 CFRelease (families);
2269 families = mutable_families;
2274 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2278 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2282 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2285 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2286 if (CONSP (val) && VECTORP (XCDR (val)))
2294 CFRetain (languages);
2295 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2299 extra = AREF (spec, FONT_EXTRA_INDEX);
2300 families_count = CFArrayGetCount (families);
2301 for (i = 0; i < families_count; i++)
2303 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2304 CTFontDescriptorRef pat_desc;
2306 CFIndex descs_count;
2307 CFMutableArrayRef filtered_descs, traits_array;
2311 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2313 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2317 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2318 10.7 returns NULL if pat_desc represents the LastResort font.
2319 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2320 trailing "s") for such a font. */
2321 if (!CFEqual (family_name, CFSTR ("LastResort")))
2322 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2325 CTFontDescriptorRef lr_desc =
2326 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2329 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2330 &kCFTypeArrayCallBacks);
2331 CFRelease (lr_desc);
2336 CFRelease (pat_desc);
2340 descs_count = CFArrayGetCount (descs);
2341 if (descs_count == 0
2342 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2351 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2352 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2353 for (j = 0; j < descs_count; j++)
2355 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2356 CFDictionaryRef dict;
2358 CTFontSymbolicTraits sym_traits;
2360 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2364 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2367 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2371 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2372 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2373 != (spacing >= FONT_SPACING_MONO)))
2376 /* Don't use a color bitmap font until it is supported on
2378 if (sym_traits & kCTFontTraitColorGlyphs)
2382 && !macfont_supports_charset_and_languages_p (desc, charset,
2386 CFArrayAppendValue (filtered_descs, desc);
2387 CFArrayAppendValue (traits_array,
2388 (const void *) (uintptr_t) sym_traits);
2392 descs = filtered_descs;
2393 descs_count = CFArrayGetCount (descs);
2395 for (j = 0; j < descs_count; j++)
2397 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2398 CTFontSymbolicTraits sym_traits =
2399 ((CTFontSymbolicTraits) (uintptr_t)
2400 CFArrayGetValueAtIndex (traits_array, j));
2401 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2403 mask_min = ((synth_sym_traits ^ sym_traits)
2404 & (kCTFontTraitItalic | kCTFontTraitBold));
2405 if (FONT_SLANT_NUMERIC (spec) < 0)
2406 mask_min &= ~kCTFontTraitItalic;
2407 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2408 mask_min &= ~kCTFontTraitBold;
2410 mask_max = (synth_sym_traits & ~sym_traits);
2411 /* Synthetic bold does not work for bitmap-only fonts on Mac
2413 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2415 CFNumberRef format =
2416 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2420 uint32_t format_val;
2422 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2424 && format_val == kCTFontFormatBitmap)
2425 mask_max &= ~kCTFontTraitBold;
2429 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2431 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2432 mmask <= (mask_max & kCTFontTraitMonoSpace);
2433 mmask += kCTFontTraitMonoSpace)
2434 for (bmask = (mask_min & kCTFontTraitBold);
2435 bmask <= (mask_max & kCTFontTraitBold);
2436 bmask += kCTFontTraitBold)
2437 for (imask = (mask_min & kCTFontTraitItalic);
2438 imask <= (mask_max & kCTFontTraitItalic);
2439 imask += kCTFontTraitItalic)
2441 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2444 || macfont_closest_traits_index_p (traits_array,
2445 (sym_traits | synth),
2448 entity = macfont_descriptor_entity (desc, extra, synth);
2449 if (! NILP (entity))
2450 val = Fcons (entity, val);
2455 CFRelease (traits_array);
2459 CFRelease (families);
2460 val = Fnreverse (val);
2466 FONT_ADD_LOG ("macfont-list", spec, val);
2467 if (charset) CFRelease (charset);
2468 if (languages) CFRelease (languages);
2469 if (attributes) CFRelease (attributes);
2470 if (family_name) CFRelease (family_name);
2478 macfont_match (struct frame * frame, Lisp_Object spec)
2480 Lisp_Object entity = Qnil;
2481 CFMutableDictionaryRef attributes;
2482 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2486 attributes = macfont_create_attributes_with_spec (spec);
2489 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2490 CFRelease (attributes);
2494 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2495 CFRelease (pat_desc);
2499 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2505 FONT_ADD_LOG ("macfont-match", spec, entity);
2510 macfont_list_family (struct frame *frame)
2512 Lisp_Object list = Qnil;
2513 CFArrayRef families;
2517 families = macfont_copy_available_families_cache ();
2520 CFIndex i, count = CFArrayGetCount (families);
2522 for (i = 0; i < count; i++)
2523 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2524 CFRelease (families);
2533 macfont_free_entity (Lisp_Object entity)
2535 Lisp_Object val = assq_no_quit (QCfont_entity,
2536 AREF (entity, FONT_EXTRA_INDEX));
2537 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2545 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2547 Lisp_Object val, font_object;
2548 CFStringRef font_name;
2549 struct macfont_info *macfont_info = NULL;
2553 CTFontSymbolicTraits sym_traits;
2555 int len, i, total_width;
2557 CGFloat ascent, descent, leading;
2559 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2561 || XTYPE (XCDR (val)) != Lisp_Misc
2562 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2564 font_name = XSAVE_POINTER (XCDR (val), 0);
2565 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2567 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2572 macfont = CTFontCreateWithName (font_name, size, NULL);
2575 int fontsize = (int) [((NSFont *) macfont) pointSize];
2576 if (fontsize != size) size = fontsize;
2582 font_object = font_build_object (VECSIZE (struct macfont_info),
2583 Qmac_ct, entity, size);
2584 font = XFONT_OBJECT (font_object);
2585 font->pixel_size = size;
2586 font->driver = &macfont_driver;
2587 font->encoding_charset = font->repertory_charset = -1;
2591 macfont_info = (struct macfont_info *) font;
2592 macfont_info->macfont = macfont;
2593 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2595 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2596 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2597 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2600 macfont_info->screen_font = NULL;
2601 macfont_info->cache = macfont_lookup_cache (font_name);
2602 macfont_retain_cache (macfont_info->cache);
2603 macfont_info->metrics = NULL;
2604 macfont_info->metrics_nrows = 0;
2605 macfont_info->synthetic_italic_p = 0;
2606 macfont_info->synthetic_bold_p = 0;
2607 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2608 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2609 if (!(sym_traits & kCTFontTraitItalic)
2610 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2611 macfont_info->synthetic_italic_p = 1;
2612 if (!(sym_traits & kCTFontTraitBold)
2613 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2614 macfont_info->synthetic_bold_p = 1;
2615 if (sym_traits & kCTFontTraitMonoSpace)
2616 macfont_info->spacing = MACFONT_SPACING_MONO;
2617 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2618 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2619 == FONT_SPACING_SYNTHETIC_MONO))
2620 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2621 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2622 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2625 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2627 macfont_info->antialias =
2628 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2630 macfont_info->color_bitmap_p = 0;
2631 if (sym_traits & kCTFontTraitColorGlyphs)
2632 macfont_info->color_bitmap_p = 1;
2634 glyph = macfont_get_glyph_for_character (font, ' ');
2635 if (glyph != kCGFontIndexInvalid)
2636 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2638 /* dirty workaround */
2639 font->space_width = pixel_size;
2641 total_width = font->space_width;
2642 for (i = 1; i < 95; i++)
2644 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2645 if (glyph == kCGFontIndexInvalid)
2647 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2650 font->average_width = total_width / 95;
2652 font->average_width = font->space_width; /* XXX */
2654 if (!(macfont_info->screen_font
2655 && mac_screen_font_get_metrics (macfont_info->screen_font,
2656 &ascent, &descent, &leading)))
2658 CFStringRef family_name;
2660 ascent = CTFontGetAscent (macfont);
2661 descent = CTFontGetDescent (macfont);
2662 leading = CTFontGetLeading (macfont);
2663 /* AppKit and WebKit do some adjustment to the heights of
2664 Courier, Helvetica, and Times. */
2665 family_name = CTFontCopyFamilyName (macfont);
2668 if (CFEqual (family_name, CFSTR ("Courier"))
2669 || CFEqual (family_name, CFSTR ("Helvetica"))
2670 || CFEqual (family_name, CFSTR ("Times")))
2671 ascent += (ascent + descent) * .15f;
2672 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2677 CFRelease (family_name);
2680 font->ascent = ascent + 0.5f;
2681 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2682 if (CONSP (val) && !NILP (XCDR (val)))
2683 font->descent = descent + 0.5f;
2685 font->descent = descent + leading + 0.5f;
2686 font->height = font->ascent + font->descent;
2688 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2689 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2693 /* Unfortunately Xft doesn't provide a way to get minimum char
2694 width. So, we use space_width instead. */
2695 font->min_width = font->max_width = font->space_width; /* XXX */
2697 font->baseline_offset = 0;
2698 font->relative_compose = 0;
2699 font->default_ascent = 0;
2700 font->vertical_centering = 0;
2706 macfont_close (struct font *font)
2708 struct macfont_info *macfont_info = (struct macfont_info *) font;
2710 if (macfont_info->cache)
2715 CFRelease (macfont_info->macfont);
2716 CGFontRelease (macfont_info->cgfont);
2717 if (macfont_info->screen_font)
2718 CFRelease (macfont_info->screen_font);
2719 macfont_release_cache (macfont_info->cache);
2720 for (i = 0; i < macfont_info->metrics_nrows; i++)
2721 if (macfont_info->metrics[i])
2722 xfree (macfont_info->metrics[i]);
2723 if (macfont_info->metrics)
2724 xfree (macfont_info->metrics);
2725 macfont_info->cache = NULL;
2731 macfont_has_char (Lisp_Object font, int c)
2734 CFCharacterSetRef charset;
2737 if (FONT_ENTITY_P (font))
2742 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2744 name = XSAVE_POINTER (val, 0);
2745 charset = macfont_get_cf_charset_for_name (name);
2748 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2750 result = CFCharacterSetIsLongCharacterMember (charset, c);
2757 macfont_encode_char (struct font *font, int c)
2762 glyph = macfont_get_glyph_for_character (font, c);
2765 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2769 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2770 struct font_metrics *metrics)
2775 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2776 for (i = 1; i < nglyphs; i++)
2778 struct font_metrics m;
2779 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2784 if (width + m.lbearing < metrics->lbearing)
2785 metrics->lbearing = width + m.lbearing;
2786 if (width + m.rbearing > metrics->rbearing)
2787 metrics->rbearing = width + m.rbearing;
2788 if (m.ascent > metrics->ascent)
2789 metrics->ascent = m.ascent;
2790 if (m.descent > metrics->descent)
2791 metrics->descent = m.descent;
2798 metrics->width = width;
2802 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2803 bool with_background)
2805 struct frame * f = s->f;
2806 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2807 CGRect background_rect;
2808 CGPoint text_position;
2811 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2812 bool no_antialias_p =
2813 (NILP (ns_antialias_text)
2814 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2815 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2816 && font_size <= macfont_antialias_threshold));
2817 int len = to - from;
2818 struct face *face = s->face;
2819 CGContextRef context;
2823 if (with_background)
2824 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2825 s->width, FONT_HEIGHT (s->font));
2827 background_rect = CGRectNull;
2829 text_position = CGPointMake (x, -y);
2830 glyphs = xmalloc (sizeof (CGGlyph) * len);
2832 CGFloat advance_delta = 0;
2834 CGFloat total_width = 0;
2836 positions = xmalloc (sizeof (CGPoint) * len);
2837 for (i = 0; i < len; i++)
2841 glyphs[i] = s->char2b[from + i];
2842 width = (s->padding_p ? 1
2843 : macfont_glyph_extents (s->font, glyphs[i],
2844 NULL, &advance_delta,
2846 positions[i].x = total_width + advance_delta;
2848 total_width += width;
2852 context = [[NSGraphicsContext currentContext] graphicsPort];
2853 CGContextSaveGState (context);
2855 if (!CGRectIsNull (background_rect))
2857 if (s->hl == DRAW_MOUSE_FACE)
2859 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2861 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2863 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2864 CGContextFillRects (context, &background_rect, 1);
2867 if (macfont_info->cgfont)
2869 CGAffineTransform atfm;
2871 CGContextScaleCTM (context, 1, -1);
2872 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2873 if (macfont_info->synthetic_italic_p)
2874 atfm = synthetic_italic_atfm;
2876 atfm = CGAffineTransformIdentity;
2877 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2879 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2880 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;
3770 if (!RIGHT_TO_LEFT_P)
3771 gl = glbuf + range.location;
3776 src = glyph_count - 1 - range.location;
3777 dest = permutation[src];
3781 CFIndex tmp = gl->string_index;
3783 gl->string_index = glbuf[src].string_index;
3784 glbuf[src].string_index = tmp;
3787 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3789 CTRunGetPositions (ctrun, range, &position);
3790 gl->advance_delta = position.x - total_advance;
3791 gl->baseline_delta = position.y;
3792 gl->advance = (gl->advance_delta
3793 + CTRunGetTypographicBounds (ctrun, range,
3795 total_advance += gl->advance;
3798 if (RIGHT_TO_LEFT_P)
3799 xfree (permutation);
3801 #undef RIGHT_TO_LEFT_P
3803 total_glyph_count += glyph_count;
3813 /* The function below seems to cause a memory leak for the CFString
3814 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3815 10.6.3. For now, we use the NSGlyphInfo version instead. */
3816 #if USE_CT_GLYPH_INFO
3818 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3821 CGGlyph result = kCGFontIndexInvalid;
3822 UniChar characters[] = {0xfffd};
3824 CFAttributedStringRef attr_string = NULL;
3825 CTLineRef ctline = NULL;
3827 string = CFStringCreateWithCharacters (NULL, characters,
3828 ARRAYELTS (characters));
3832 CTGlyphInfoRef glyph_info =
3833 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3834 CFDictionaryRef attributes = NULL;
3838 CFStringRef keys[] = {kCTFontAttributeName,
3839 kCTGlyphInfoAttributeName};
3840 CFTypeRef values[] = {font, glyph_info};
3842 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3843 (const void **) values,
3845 &kCFTypeDictionaryKeyCallBacks,
3846 &kCFTypeDictionaryValueCallBacks);
3847 CFRelease (glyph_info);
3851 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3852 CFRelease (attributes);
3858 ctline = CTLineCreateWithAttributedString (attr_string);
3859 CFRelease (attr_string);
3863 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3865 if (CFArrayGetCount (runs) > 0)
3867 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3868 CFDictionaryRef attributes = CTRunGetAttributes (run);
3872 CTFontRef font_in_run =
3873 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3876 && mac_font_equal_in_postscript_name (font_in_run, font))
3878 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3879 if (result >= CTFontGetGlyphCount (font))
3880 result = kCGFontIndexInvalid;
3892 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3894 CFArrayRef result = NULL;
3896 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3897 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3898 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3901 CTFontRef user_font =
3902 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3906 CFArrayRef languages =
3907 CFArrayCreate (NULL, (const void **) &language, 1,
3908 &kCFTypeArrayCallBacks);
3912 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3914 CFRelease (languages);
3916 CFRelease (user_font);
3919 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3920 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3922 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3923 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3927 for (i = 0; macfont_language_default_font_names[i].language; i++)
3929 if (CFEqual (macfont_language_default_font_names[i].language,
3932 CFMutableArrayRef descriptors =
3933 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3940 macfont_language_default_font_names[i].font_names[j];
3943 CFDictionaryRef attributes =
3944 CFDictionaryCreate (NULL,
3946 &kCTFontNameAttribute),
3948 &macfont_language_default_font_names[i].font_names[j]),
3949 1, &kCFTypeDictionaryKeyCallBacks,
3950 &kCFTypeDictionaryValueCallBacks);
3954 CTFontDescriptorRef pat_desc =
3955 CTFontDescriptorCreateWithAttributes (attributes);
3959 CTFontDescriptorRef descriptor =
3960 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3964 CFArrayAppendValue (descriptors, descriptor);
3965 CFRelease (descriptor);
3967 CFRelease (pat_desc);
3969 CFRelease (attributes);
3972 result = descriptors;
3984 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3985 CFArrayRef languages)
3987 CFStringRef result = NULL;
3988 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3989 CFArrayRef descriptors =
3990 mac_font_copy_default_descriptors_for_language (language);
3994 CFIndex i, count = CFArrayGetCount (descriptors);
3996 for (i = 0; i < count; i++)
3998 CTFontDescriptorRef descriptor =
3999 CFArrayGetValueAtIndex (descriptors, i);
4001 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4004 CFStringRef family =
4005 CTFontDescriptorCopyAttribute (descriptor,
4006 kCTFontFamilyNameAttribute);
4009 if (!CFStringHasPrefix (family, CFSTR ("."))
4010 && !CFEqual (family, CFSTR ("LastResort")))
4020 CFRelease (descriptors);
4027 macfont_get_nsctfont (struct font *font)
4029 struct macfont_info *macfont_info = (struct macfont_info *) font;
4030 CTFontRef macfont = macfont_info->macfont;
4032 return (void *) macfont;
4036 mac_register_font_driver (struct frame *f)
4038 register_font_driver (&macfont_driver, f);
4043 syms_of_macfont (void)
4045 /* Core Text, for Mac OS X. */
4046 DEFSYM (Qmac_ct, "mac-ct");
4047 macfont_driver.type = Qmac_ct;
4048 register_font_driver (&macfont_driver, NULL);
4050 /* The font property key specifying the font design destination. The
4051 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4052 text. (See the documentation of X Logical Font Description
4053 Conventions.) In the Mac font driver, 1 means the screen font is
4054 used for calculating some glyph metrics. You can see the
4055 difference with Monaco 8pt or 9pt, for example. */
4056 DEFSYM (QCdestination, ":destination");
4058 /* The boolean-valued font property key specifying the use of leading. */
4059 DEFSYM (QCminspace, ":minspace");
4061 macfont_family_cache = Qnil;
4062 staticpro (&macfont_family_cache);