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_OPT_FROM_ID (s->f,
2860 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2862 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2864 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2865 CGContextFillRects (context, &background_rect, 1);
2868 if (macfont_info->cgfont)
2870 CGAffineTransform atfm;
2872 CGContextScaleCTM (context, 1, -1);
2873 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2874 if (macfont_info->synthetic_italic_p)
2875 atfm = synthetic_italic_atfm;
2877 atfm = CGAffineTransformIdentity;
2878 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2880 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2881 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2882 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2885 CGContextSetShouldAntialias (context, false);
2887 CGContextSetTextMatrix (context, atfm);
2888 CGContextSetTextPosition (context, text_position.x, text_position.y);
2890 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2891 if (macfont_info->color_bitmap_p
2892 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2893 && CTFontDrawGlyphs != NULL
2899 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2904 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2906 CGContextSetFont (context, macfont_info->cgfont);
2907 CGContextSetFontSize (context, font_size);
2908 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2915 CGContextRestoreGState (context);
2923 macfont_shape (Lisp_Object lgstring)
2925 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2926 struct macfont_info *macfont_info = (struct macfont_info *) font;
2927 CTFontRef macfont = macfont_info->macfont;
2928 ptrdiff_t glyph_len, len, i, j;
2931 CFIndex *nonbmp_indices;
2934 struct mac_glyph_layout *glyph_layouts;
2936 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2938 for (i = 0; i < glyph_len; i++)
2940 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2944 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2950 if (INT_MAX / 2 < len)
2951 memory_full (SIZE_MAX);
2953 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2954 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2955 for (i = j = 0; i < len; i++)
2957 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2959 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2961 nonbmp_indices[j] = i + j;
2965 nonbmp_indices[j] = len + j; /* sentinel */
2969 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2973 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2974 if (macfont_info->screen_font)
2975 used = mac_screen_font_shape (macfont_info->screen_font, string,
2976 glyph_layouts, glyph_len);
2978 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2989 for (i = 0; i < used; i++)
2991 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2992 struct mac_glyph_layout *gl = glyph_layouts + i;
2994 struct font_metrics metrics;
2995 int xoff, yoff, wadjust;
2999 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
3000 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
3003 from = gl->comp_range.location;
3004 /* Convert UTF-16 index to UTF-32. */
3006 while (nonbmp_indices[j] < from)
3009 LGLYPH_SET_FROM (lglyph, from);
3011 to = gl->comp_range.location + gl->comp_range.length;
3012 /* Convert UTF-16 index to UTF-32. */
3013 while (nonbmp_indices[j] < to)
3016 LGLYPH_SET_TO (lglyph, to - 1);
3018 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3019 the composition is trivial. */
3023 if (unichars[gl->string_index] >= 0xD800
3024 && unichars[gl->string_index] < 0xDC00)
3025 c = (((unichars[gl->string_index] - 0xD800) << 10)
3026 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3028 c = unichars[gl->string_index];
3029 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3031 LGLYPH_SET_CHAR (lglyph, c);
3035 unsigned long cc = gl->glyph_id;
3036 LGLYPH_SET_CODE (lglyph, cc);
3039 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3040 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3041 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3042 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3043 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3044 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3046 xoff = lround (gl->advance_delta);
3047 yoff = lround (- gl->baseline_delta);
3048 wadjust = lround (gl->advance);
3049 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3053 vec = Fmake_vector (make_number (3), Qnil);
3054 ASET (vec, 0, make_number (xoff));
3055 ASET (vec, 1, make_number (yoff));
3056 ASET (vec, 2, make_number (wadjust));
3057 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3063 return make_number (used);
3066 /* Structures for the UVS subtable (format 14) in the cmap table. */
3067 typedef UInt8 UINT24[3];
3069 #pragma pack(push, 1)
3070 struct variation_selector_record
3072 UINT24 var_selector;
3073 UInt32 default_uvs_offset, non_default_uvs_offset;
3078 UInt32 length, num_var_selector_records;
3079 struct variation_selector_record variation_selector_records[1];
3081 #define SIZEOF_UVS_TABLE_HEADER \
3082 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3084 struct unicode_value_range
3086 UINT24 start_unicode_value;
3087 UInt8 additional_count;
3089 struct default_uvs_table {
3090 UInt32 num_unicode_value_ranges;
3091 struct unicode_value_range unicode_value_ranges[1];
3093 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3094 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3098 UINT24 unicode_value;
3101 struct non_default_uvs_table
3103 UInt32 num_uvs_mappings;
3104 struct uvs_mapping uvs_mappings[1];
3106 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3107 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3110 /* Read big endian values. The argument LVAL must be an lvalue. */
3111 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3112 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3113 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3114 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3115 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3116 /* Succeeding one byte should also be accessible. */
3117 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3118 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3120 /* Return UVS subtable for the specified FONT. If the subtable is not
3121 found or ill-formatted, then return NULL. */
3124 mac_font_copy_uvs_table (CTFontRef font)
3126 CFDataRef cmap_table, uvs_table = NULL;
3128 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3129 kCTFontTableOptionNoOptions);
3132 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3133 struct uvs_table *uvs;
3134 struct variation_selector_record *records;
3135 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3138 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3142 cmap_len = CFDataGetLength (cmap_table);
3143 if (sizeof_sfntCMapHeader > cmap_len)
3146 ntables = BUINT16_VALUE (cmap->numTables);
3147 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3148 / sizeof_sfntCMapEncoding))
3151 for (i = 0; i < ntables; i++)
3152 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3153 == kFontUnicodePlatform)
3154 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3155 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3157 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3161 || uvs_offset > cmap_len
3162 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3165 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3166 uvs_len = BUINT32_VALUE (uvs->length);
3167 if (uvs_len > cmap_len - uvs_offset
3168 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3171 if (BUINT16_VALUE (uvs->format) != 14)
3174 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3175 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3176 / sizeof (struct variation_selector_record)))
3179 records = uvs->variation_selector_records;
3180 for (i = 0; i < nrecords; i++)
3182 UInt32 default_uvs_offset, non_default_uvs_offset;
3184 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3185 if (default_uvs_offset)
3187 struct default_uvs_table *default_uvs;
3190 if (default_uvs_offset > uvs_len
3191 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3192 > uvs_len - default_uvs_offset))
3195 default_uvs = ((struct default_uvs_table *)
3196 ((UInt8 *) uvs + default_uvs_offset));
3197 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3198 if (nranges > ((uvs_len - default_uvs_offset
3199 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3200 / sizeof (struct unicode_value_range)))
3202 /* Now 2 * nranges can't overflow, so we can safely use
3203 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3204 mac_font_get_glyphs_for_variants. */
3207 non_default_uvs_offset =
3208 BUINT32_VALUE (records[i].non_default_uvs_offset);
3209 if (non_default_uvs_offset)
3211 struct non_default_uvs_table *non_default_uvs;
3214 if (non_default_uvs_offset > uvs_len
3215 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3216 > uvs_len - non_default_uvs_offset))
3219 non_default_uvs = ((struct non_default_uvs_table *)
3220 ((UInt8 *) uvs + non_default_uvs_offset));
3221 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3222 if (nmappings > ((uvs_len - non_default_uvs_offset
3223 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3224 / sizeof (struct uvs_mapping)))
3226 /* Now 2 * nmappings can't overflow, so we can safely
3227 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3228 in mac_font_get_glyphs_for_variants. */
3232 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3235 CFRelease (cmap_table);
3241 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3242 sequence consisting of the given base character C and each
3243 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3244 result (explained below) into the corresponding GLYPHS[i]. If the
3245 entry is found in the Default UVS Table, then the result is 0. If
3246 the entry is found in the Non-Default UVS Table, then the result is
3247 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3248 elements in SELECTORS must be sorted in strictly increasing
3252 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3253 const UTF32Char selectors[], CGGlyph glyphs[],
3256 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3257 struct variation_selector_record *records = uvs->variation_selector_records;
3259 UInt32 ir, nrecords;
3260 dispatch_queue_t queue =
3261 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3262 dispatch_group_t group = dispatch_group_create ();
3264 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3267 while (i < count && ir < nrecords)
3269 UInt32 default_uvs_offset, non_default_uvs_offset;
3271 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3273 glyphs[i++] = kCGFontIndexInvalid;
3276 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3282 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3283 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3284 non_default_uvs_offset =
3285 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3286 dispatch_group_async (group, queue, ^{
3287 glyphs[i] = kCGFontIndexInvalid;
3289 if (default_uvs_offset)
3291 struct default_uvs_table *default_uvs =
3292 (struct default_uvs_table *) ((UInt8 *) uvs
3293 + default_uvs_offset);
3294 struct unicode_value_range *ranges =
3295 default_uvs->unicode_value_ranges;
3299 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3302 UInt32 mid = (lo + hi) / 2;
3304 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3310 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3311 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3315 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3317 struct non_default_uvs_table *non_default_uvs =
3318 (struct non_default_uvs_table *) ((UInt8 *) uvs
3319 + non_default_uvs_offset);
3320 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3324 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3327 UInt32 mid = (lo + hi) / 2;
3329 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3335 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3336 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3343 glyphs[i++] = kCGFontIndexInvalid;
3344 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3345 dispatch_release (group);
3349 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3351 CFDataRef uvs_table;
3352 CTCharacterCollection uvs_collection;
3356 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3360 UTF32Char selectors[256];
3361 CGGlyph glyphs[256];
3363 for (i = 0; i < 16; i++)
3364 selectors[i] = 0xFE00 + i;
3365 for (; i < 256; i++)
3366 selectors[i] = 0xE0100 + (i - 16);
3367 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3368 for (i = 0; i < 256; i++)
3370 CGGlyph glyph = glyphs[i];
3372 if (uvs_collection != kCTCharacterCollectionIdentityMapping
3373 && glyph != kCGFontIndexInvalid)
3374 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3375 if (glyph == kCGFontIndexInvalid)
3379 variations[i] = (glyph ? glyph
3380 : macfont_get_glyph_for_character (font, c));
3390 static const char *const macfont_booleans[] = {
3396 static const char *const macfont_non_booleans[] = {
3404 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3406 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3410 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3411 CFArrayRef languages)
3413 Boolean result = true;
3414 CFArrayRef desc_languages =
3415 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3417 if (desc_languages == NULL)
3421 CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
3422 CFIndex i, languages_count = CFArrayGetCount (languages);
3424 for (i = 0; i < languages_count; i++)
3426 CFStringRef language = CFArrayGetValueAtIndex (languages, i);
3428 if (!CFArrayContainsValue (desc_languages, range, language)
3429 /* PingFang SC contains "zh" and "zh-Hant" as covered
3430 languages, but does not contain "zh-Hans". */
3431 && !(CFEqual (language, CFSTR ("zh-Hans"))
3432 && CFArrayContainsValue (desc_languages, range,
3439 CFRelease (desc_languages);
3446 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3448 CFStringRef result = NULL;
3449 CFStringRef charset_string =
3450 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3452 if (charset_string && CFStringGetLength (charset_string) > 0)
3454 CFStringRef keys[] = {
3455 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3456 kCTLanguageAttributeName
3458 CFSTR ("NSLanguage")
3461 CFTypeRef values[] = {NULL};
3462 CFIndex num_values = 0;
3463 CFArrayRef languages
3464 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3466 if (languages && CFArrayGetCount (languages) > 0)
3468 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3469 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3472 CFCharacterSetRef charset =
3473 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3475 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3480 CFAttributedStringRef attr_string = NULL;
3481 CTLineRef ctline = NULL;
3482 CFDictionaryRef attrs
3483 = CFDictionaryCreate (NULL, (const void **) keys,
3484 (const void **) values, num_values,
3485 &kCFTypeDictionaryKeyCallBacks,
3486 &kCFTypeDictionaryValueCallBacks);
3490 attr_string = CFAttributedStringCreate (NULL, charset_string,
3496 ctline = CTLineCreateWithAttributedString (attr_string);
3497 CFRelease (attr_string);
3501 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3502 CFIndex i, nruns = CFArrayGetCount (runs);
3505 for (i = 0; i < nruns; i++)
3507 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3508 CFDictionaryRef attributes = CTRunGetAttributes (run);
3509 CTFontRef font_in_run;
3511 if (attributes == NULL)
3514 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3515 if (font_in_run == NULL)
3519 else if (!mac_font_equal_in_postscript_name (font,
3523 if (nruns > 0 && i == nruns)
3524 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3533 static inline double
3534 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3536 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3540 static inline CGRect
3541 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3543 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3548 mac_font_create_available_families (void)
3550 CFMutableArrayRef families = NULL;
3551 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3555 CFIndex i, count = CFArrayGetCount (orig_families);
3557 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3559 for (i = 0; i < count; i++)
3561 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3563 if (!CFStringHasPrefix (family, CFSTR ("."))
3564 && (CTFontManagerCompareFontFamilyNames (family,
3565 CFSTR ("LastResort"),
3567 != kCFCompareEqualTo))
3568 CFArrayAppendValue (families, family);
3570 CFRelease (orig_families);
3577 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3580 CFStringRef name1, name2;
3586 name1 = CTFontCopyPostScriptName (font1);
3589 name2 = CTFontCopyPostScriptName (font2);
3592 result = CFEqual (name1, name2);
3602 mac_font_create_line_with_string_and_font (CFStringRef string,
3605 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3606 CFTypeRef values[] = {NULL, NULL};
3607 CFDictionaryRef attributes = NULL;
3608 CFAttributedStringRef attr_string = NULL;
3609 CTLineRef ctline = NULL;
3610 float float_zero = 0.0f;
3612 values[0] = macfont;
3613 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3616 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3617 (const void **) values,
3619 &kCFTypeDictionaryKeyCallBacks,
3620 &kCFTypeDictionaryValueCallBacks);
3621 CFRelease (values[1]);
3625 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3626 CFRelease (attributes);
3630 ctline = CTLineCreateWithAttributedString (attr_string);
3631 CFRelease (attr_string);
3635 /* Abandon if ctline contains some fonts other than the
3637 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3638 CFIndex i, nruns = CFArrayGetCount (runs);
3640 for (i = 0; i < nruns; i++)
3642 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3643 CFDictionaryRef attributes = CTRunGetAttributes (run);
3644 CTFontRef font_in_run;
3646 if (attributes == NULL)
3649 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3650 if (font_in_run == NULL)
3652 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3666 mac_font_shape (CTFontRef font, CFStringRef string,
3667 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3669 CFIndex used, result = 0;
3670 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3675 used = CTLineGetGlyphCount (ctline);
3676 if (used <= glyph_len)
3678 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3679 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3680 CGFloat total_advance = 0;
3681 CFIndex total_glyph_count = 0;
3683 for (k = 0; k < ctrun_count; k++)
3685 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3686 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3687 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3688 CFRange string_range, comp_range, range;
3689 CFIndex *permutation;
3691 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3692 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3696 #define RIGHT_TO_LEFT_P permutation
3698 /* Now the `comp_range' member of struct mac_glyph_layout is
3699 temporarily used as a work area such that:
3700 glbuf[i].comp_range.location =
3701 min {compRange[i + 1].location, ...,
3702 compRange[glyph_count - 1].location,
3703 maxRange (stringRangeForCTRun)}
3704 glbuf[i].comp_range.length = maxRange (compRange[i])
3705 where compRange[i] is the range of composed characters
3706 containing i-th glyph. */
3707 string_range = CTRunGetStringRange (ctrun);
3708 min_location = string_range.location + string_range.length;
3709 for (i = 0; i < glyph_count; i++)
3711 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3712 CFIndex glyph_index;
3715 if (!RIGHT_TO_LEFT_P)
3716 glyph_index = glyph_count - i - 1;
3719 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3722 CFStringGetRangeOfComposedCharactersAtIndex (string,
3724 gl->comp_range.location = min_location;
3725 gl->comp_range.length = rng.location + rng.length;
3726 if (rng.location < min_location)
3727 min_location = rng.location;
3730 /* Fill the `comp_range' member of struct mac_glyph_layout,
3731 and setup a permutation for right-to-left text. */
3732 comp_range = CFRangeMake (string_range.location, 0);
3733 range = CFRangeMake (0, 0);
3736 struct mac_glyph_layout *gl =
3737 glbuf + range.location + range.length;
3739 if (gl->comp_range.length
3740 > comp_range.location + comp_range.length)
3741 comp_range.length = gl->comp_range.length - comp_range.location;
3742 min_location = gl->comp_range.location;
3745 if (min_location >= comp_range.location + comp_range.length)
3747 comp_range.length = min_location - comp_range.location;
3748 for (i = 0; i < range.length; i++)
3750 glbuf[range.location + i].comp_range = comp_range;
3751 if (RIGHT_TO_LEFT_P)
3752 permutation[range.location + i] =
3753 range.location + range.length - i - 1;
3756 comp_range = CFRangeMake (min_location, 0);
3757 range.location += range.length;
3759 if (range.location == glyph_count)
3764 /* Then fill the remaining members. */
3765 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3768 struct mac_glyph_layout *gl;
3771 if (!RIGHT_TO_LEFT_P)
3772 gl = glbuf + range.location;
3777 src = glyph_count - 1 - range.location;
3778 dest = permutation[src];
3782 CFIndex tmp = gl->string_index;
3784 gl->string_index = glbuf[src].string_index;
3785 glbuf[src].string_index = tmp;
3788 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3790 CTRunGetPositions (ctrun, range, &position);
3791 gl->advance_delta = position.x - total_advance;
3792 gl->baseline_delta = position.y;
3793 gl->advance = (gl->advance_delta
3794 + CTRunGetTypographicBounds (ctrun, range,
3796 total_advance += gl->advance;
3799 if (RIGHT_TO_LEFT_P)
3800 xfree (permutation);
3802 #undef RIGHT_TO_LEFT_P
3804 total_glyph_count += glyph_count;
3814 /* The function below seems to cause a memory leak for the CFString
3815 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3816 10.6.3. For now, we use the NSGlyphInfo version instead. */
3817 #if USE_CT_GLYPH_INFO
3819 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3822 CGGlyph result = kCGFontIndexInvalid;
3823 UniChar characters[] = {0xfffd};
3825 CFAttributedStringRef attr_string = NULL;
3826 CTLineRef ctline = NULL;
3828 string = CFStringCreateWithCharacters (NULL, characters,
3829 ARRAYELTS (characters));
3833 CTGlyphInfoRef glyph_info =
3834 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3835 CFDictionaryRef attributes = NULL;
3839 CFStringRef keys[] = {kCTFontAttributeName,
3840 kCTGlyphInfoAttributeName};
3841 CFTypeRef values[] = {font, glyph_info};
3843 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3844 (const void **) values,
3846 &kCFTypeDictionaryKeyCallBacks,
3847 &kCFTypeDictionaryValueCallBacks);
3848 CFRelease (glyph_info);
3852 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3853 CFRelease (attributes);
3859 ctline = CTLineCreateWithAttributedString (attr_string);
3860 CFRelease (attr_string);
3864 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3866 if (CFArrayGetCount (runs) > 0)
3868 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3869 CFDictionaryRef attributes = CTRunGetAttributes (run);
3873 CTFontRef font_in_run =
3874 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3877 && mac_font_equal_in_postscript_name (font_in_run, font))
3879 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3880 if (result >= CTFontGetGlyphCount (font))
3881 result = kCGFontIndexInvalid;
3893 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3895 CFArrayRef result = NULL;
3897 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3898 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3899 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3902 CTFontRef user_font =
3903 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3907 CFArrayRef languages =
3908 CFArrayCreate (NULL, (const void **) &language, 1,
3909 &kCFTypeArrayCallBacks);
3913 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3915 CFRelease (languages);
3917 CFRelease (user_font);
3920 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3921 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3923 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3924 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3928 for (i = 0; macfont_language_default_font_names[i].language; i++)
3930 if (CFEqual (macfont_language_default_font_names[i].language,
3933 CFMutableArrayRef descriptors =
3934 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3941 macfont_language_default_font_names[i].font_names[j];
3944 CFDictionaryRef attributes =
3945 CFDictionaryCreate (NULL,
3947 &kCTFontNameAttribute),
3949 &macfont_language_default_font_names[i].font_names[j]),
3950 1, &kCFTypeDictionaryKeyCallBacks,
3951 &kCFTypeDictionaryValueCallBacks);
3955 CTFontDescriptorRef pat_desc =
3956 CTFontDescriptorCreateWithAttributes (attributes);
3960 CTFontDescriptorRef descriptor =
3961 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3965 CFArrayAppendValue (descriptors, descriptor);
3966 CFRelease (descriptor);
3968 CFRelease (pat_desc);
3970 CFRelease (attributes);
3973 result = descriptors;
3985 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3986 CFArrayRef languages)
3988 CFStringRef result = NULL;
3989 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3990 CFArrayRef descriptors =
3991 mac_font_copy_default_descriptors_for_language (language);
3995 CFIndex i, count = CFArrayGetCount (descriptors);
3997 for (i = 0; i < count; i++)
3999 CTFontDescriptorRef descriptor =
4000 CFArrayGetValueAtIndex (descriptors, i);
4002 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4005 CFStringRef family =
4006 CTFontDescriptorCopyAttribute (descriptor,
4007 kCTFontFamilyNameAttribute);
4010 if (!CFStringHasPrefix (family, CFSTR ("."))
4011 && !CFEqual (family, CFSTR ("LastResort")))
4021 CFRelease (descriptors);
4028 macfont_get_nsctfont (struct font *font)
4030 struct macfont_info *macfont_info = (struct macfont_info *) font;
4031 CTFontRef macfont = macfont_info->macfont;
4033 return (void *) macfont;
4037 mac_register_font_driver (struct frame *f)
4039 register_font_driver (&macfont_driver, f);
4044 syms_of_macfont (void)
4046 /* Core Text, for Mac OS X. */
4047 DEFSYM (Qmac_ct, "mac-ct");
4048 macfont_driver.type = Qmac_ct;
4049 register_font_driver (&macfont_driver, NULL);
4051 /* The font property key specifying the font design destination. The
4052 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4053 text. (See the documentation of X Logical Font Description
4054 Conventions.) In the Mac font driver, 1 means the screen font is
4055 used for calculating some glyph metrics. You can see the
4056 difference with Monaco 8pt or 9pt, for example. */
4057 DEFSYM (QCdestination, ":destination");
4059 /* The boolean-valued font property key specifying the use of leading. */
4060 DEFSYM (QCminspace, ":minspace");
4062 macfont_family_cache = Qnil;
4063 staticpro (&macfont_family_cache);