1 /* Font driver on Mac OSX Core text.
2 Copyright (C) 2009-2015 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #include <libkern/OSByteOrder.h>
41 static struct font_driver macfont_driver;
43 static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
44 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
45 static CFArrayRef mac_font_create_available_families (void);
46 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
47 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
49 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
51 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
52 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
53 struct mac_glyph_layout *, CFIndex);
54 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
55 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
57 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
61 struct macfont_metrics;
63 /* The actual structure for Mac font that can be cast to struct font. */
70 ScreenFontRef screen_font;
71 struct macfont_cache *cache;
72 struct macfont_metrics **metrics;
74 bool_bf synthetic_italic_p : 1;
75 bool_bf synthetic_bold_p : 1;
77 unsigned antialias : 2;
78 bool_bf color_bitmap_p : 1;
81 /* Values for the `spacing' member in `struct macfont_info'. */
85 MACFONT_SPACING_PROPORTIONAL,
87 MACFONT_SPACING_SYNTHETIC_MONO,
90 /* Values for the `antialias' member in `struct macfont_info'. */
94 MACFONT_ANTIALIAS_DEFAULT,
95 MACFONT_ANTIALIAS_OFF,
99 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
100 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
101 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
103 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
104 static const CGFloat synthetic_bold_factor = 0.024;
106 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
107 CTFontSymbolicTraits *);
108 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
110 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
111 CTFontSymbolicTraits);
112 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
113 static int macfont_glyph_extents (struct font *, CGGlyph,
114 struct font_metrics *, CGFloat *, int);
115 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
116 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
120 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
122 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
123 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
125 CGGlyph [], CFIndex);
127 /* From CFData to a lisp string. Always returns a unibyte string. */
130 cfdata_to_lisp (CFDataRef data)
132 CFIndex len = CFDataGetLength (data);
133 Lisp_Object result = make_uninit_string (len);
135 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
142 /* From CFString to a lisp string. Returns a unibyte string
143 containing a UTF-8 byte sequence. */
146 cfstring_to_lisp_nodecode (CFStringRef string)
148 Lisp_Object result = Qnil;
150 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
154 CFIndex i, length = CFStringGetLength (string);
156 for (i = 0; i < length; i++)
157 if (CFStringGetCharacterAtIndex (string, i) == 0)
161 return make_unibyte_string (s, strlen (s));
164 data = CFStringCreateExternalRepresentation (NULL, string,
165 kCFStringEncodingUTF8, '?');
168 result = cfdata_to_lisp (data);
175 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
176 cfstring_create_with_utf8_cstring, this function preserves NUL
180 cfstring_create_with_string_noencode (Lisp_Object s)
182 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
183 kCFStringEncodingUTF8, false);
186 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
187 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
188 kCFStringEncodingMacRoman, false);
194 mac_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 || percent_val == 56)
776 CTFontRef font = NULL;
778 CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
782 font = CTFontCreateWithName (name, 0, NULL);
787 CFIndex weight = mac_font_get_weight (font);
789 if (percent_val == -40)
791 /* Workaround for crash when displaying Oriya characters
792 with Arial Unicode MS on OS X 10.11. */
796 else /* percent_val == 56 */
799 /* Adjustment for HiraginoSans-W7 on OS X 10.11. */
810 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
811 Lisp_Object spec_or_entity)
814 CFDictionaryRef dict;
818 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
821 ASET (spec_or_entity, FONT_FAMILY_INDEX,
822 macfont_intern_prop_cfstring (str));
825 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
829 enum font_property_index index;
832 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
834 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
835 {{-0.4, 50}, /* light */
836 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
837 {0, 100}, /* normal */
838 {0.24, 140}, /* (semi-bold + normal) / 2 */
839 {0.4, 200}, /* bold */
840 {CGFLOAT_MAX, CGFLOAT_MAX}},
841 mac_font_descriptor_get_adjusted_weight},
842 {FONT_SLANT_INDEX, kCTFontSlantTrait,
843 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
844 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
845 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
848 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
850 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
851 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
853 CGPoint *point = numeric_traits[i].points;
855 if (numeric_traits[i].adjust_func)
856 floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
857 while (point->x < floatval)
859 if (point == numeric_traits[i].points)
861 else if (point->x == CGFLOAT_MAX)
863 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
864 * ((point->y - (point - 1)->y)
865 / (point->x - (point - 1)->x)));
866 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
867 make_number (lround (floatval)));
871 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
874 CTFontSymbolicTraits sym_traits;
877 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
878 spacing = (sym_traits & kCTFontTraitMonoSpace
879 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
880 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
885 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
886 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
887 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
889 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
895 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
896 CTFontSymbolicTraits synth_sym_traits)
899 CFDictionaryRef dict;
900 CTFontSymbolicTraits sym_traits = 0;
903 entity = font_make_entity ();
905 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
906 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
908 macfont_store_descriptor_attributes (desc, entity);
910 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
913 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
916 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
919 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
920 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
921 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
922 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
923 font_put_extra (entity, QCfont_entity,
924 make_save_ptr_int ((void *) name, sym_traits));
925 if (synth_sym_traits & kCTFontTraitItalic)
926 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
927 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
928 if (synth_sym_traits & kCTFontTraitBold)
929 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
930 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
931 if (synth_sym_traits & kCTFontTraitMonoSpace)
932 ASET (entity, FONT_SPACING_INDEX,
933 make_number (FONT_SPACING_SYNTHETIC_MONO));
938 /* Cache for font family name symbols vs CFStrings. A value of nil
939 means the cache has been invalidated. Otherwise the value is a Lisp
940 hash table whose keys are symbols and the value for a key is either
941 nil (no corresponding family name) or a Lisp save value wrapping the
942 corresponding family name in CFString. */
944 static Lisp_Object macfont_family_cache;
947 macfont_invalidate_family_cache (void)
949 if (HASH_TABLE_P (macfont_family_cache))
951 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
952 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
954 for (i = 0; i < size; ++i)
955 if (!NILP (HASH_HASH (h, i)))
957 Lisp_Object value = HASH_VALUE (h, i);
959 if (SAVE_VALUEP (value))
960 CFRelease (XSAVE_POINTER (value, 0));
962 macfont_family_cache = Qnil;
967 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
969 if (HASH_TABLE_P (macfont_family_cache))
971 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
972 ptrdiff_t i = hash_lookup (h, symbol, NULL);
976 Lisp_Object value = HASH_VALUE (h, i);
978 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
988 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
990 struct Lisp_Hash_Table *h;
995 if (!HASH_TABLE_P (macfont_family_cache))
996 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
998 h = XHASH_TABLE (macfont_family_cache);
999 i = hash_lookup (h, symbol, &hash);
1000 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
1003 Lisp_Object old_value = HASH_VALUE (h, i);
1005 if (SAVE_VALUEP (old_value))
1006 CFRelease (XSAVE_POINTER (old_value, 0));
1007 set_hash_value_slot (h, i, value);
1010 hash_put (h, symbol, value, hash);
1013 /* Cache of all the available font family names except "LastResort"
1014 and those start with ".". NULL means the cache has been invalidated.
1015 Otherwise, the value is CFArray of CFStrings and the elements are
1016 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1017 OS X 10.6 and later). */
1019 static CFArrayRef macfont_available_families_cache = NULL;
1022 macfont_invalidate_available_families_cache (void)
1024 if (macfont_available_families_cache)
1026 CFRelease (macfont_available_families_cache);
1027 macfont_available_families_cache = NULL;
1032 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1034 CFStringRef name, const void *object,
1035 CFDictionaryRef userInfo)
1037 macfont_invalidate_family_cache ();
1038 macfont_invalidate_available_families_cache ();
1042 macfont_init_font_change_handler (void)
1044 static bool initialized = false;
1050 CFNotificationCenterAddObserver
1051 (CFNotificationCenterGetLocalCenter (), NULL,
1052 macfont_handle_font_change_notification,
1053 kCTFontManagerRegisteredFontsChangedNotification,
1054 NULL, CFNotificationSuspensionBehaviorCoalesce);
1058 macfont_copy_available_families_cache (void)
1060 macfont_init_font_change_handler ();
1062 if (macfont_available_families_cache == NULL)
1063 macfont_available_families_cache = mac_font_create_available_families ();
1065 return (macfont_available_families_cache
1066 ? CFRetain (macfont_available_families_cache) : NULL);
1070 macfont_create_family_with_symbol (Lisp_Object symbol)
1072 CFStringRef result = NULL, family_name;
1073 CFDictionaryRef attributes = NULL;
1074 CTFontDescriptorRef pat_desc = NULL;
1076 if (macfont_get_family_cache_if_present (symbol, &result))
1077 return result ? CFRetain (result) : NULL;
1079 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1083 CFDictionaryCreate (NULL,
1084 (const void **) &kCTFontFamilyNameAttribute,
1085 (const void **) &family_name, 1,
1086 &kCFTypeDictionaryKeyCallBacks,
1087 &kCFTypeDictionaryValueCallBacks);
1088 CFRelease (family_name);
1092 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1093 CFRelease (attributes);
1097 CTFontDescriptorRef desc =
1098 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1103 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1106 macfont_set_family_cache (symbol, result);
1107 CFRelease (pat_desc);
1113 #define WIDTH_FRAC_BITS (4)
1114 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1116 struct macfont_metrics
1118 unsigned char lbearing_low, rbearing_low;
1119 signed lbearing_high : 4, rbearing_high : 4;
1120 unsigned char ascent_low, descent_low;
1121 signed ascent_high : 4, descent_high : 4;
1123 /* These two members are used for fixed-point representation of
1124 glyph width. The `width_int' member is an integer that is
1125 closest to the width. The `width_frac' member is the fractional
1126 adjustment representing a value in [-.5, .5], multiplied by
1127 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1128 the advance delta for centering instead of the glyph width. */
1129 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1132 #define METRICS_VALUE(metrics, member) \
1133 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1134 #define METRICS_SET_VALUE(metrics, member, value) \
1135 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1136 (metrics)->member##_high = tmp >> 8;} while (0)
1140 METRICS_INVALID = -1, /* metrics entry is invalid */
1141 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1144 #define METRICS_STATUS(metrics) \
1145 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1146 #define METRICS_SET_STATUS(metrics, status) \
1147 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1148 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1150 #define METRICS_NCOLS_PER_ROW (128)
1151 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1152 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1155 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1156 struct font_metrics *metrics, CGFloat *advance_delta,
1157 int force_integral_p)
1159 struct macfont_info *macfont_info = (struct macfont_info *) font;
1160 CTFontRef macfont = macfont_info->macfont;
1162 struct macfont_metrics *cache;
1165 row = glyph / METRICS_NCOLS_PER_ROW;
1166 col = glyph % METRICS_NCOLS_PER_ROW;
1167 if (row >= macfont_info->metrics_nrows)
1169 macfont_info->metrics =
1170 xrealloc (macfont_info->metrics,
1171 sizeof (struct macfont_metrics *) * (row + 1));
1172 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1173 (sizeof (struct macfont_metrics *)
1174 * (row + 1 - macfont_info->metrics_nrows)));
1175 macfont_info->metrics_nrows = row + 1;
1177 if (macfont_info->metrics[row] == NULL)
1179 struct macfont_metrics *new;
1182 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1183 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1184 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1185 macfont_info->metrics[row] = new;
1187 cache = macfont_info->metrics[row] + col;
1189 if (METRICS_STATUS (cache) == METRICS_INVALID)
1193 if (macfont_info->screen_font)
1194 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1196 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1198 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1199 advance delta value. */
1200 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1201 fwidth = (font->pixel_size - fwidth) / 2;
1202 cache->width_int = lround (fwidth);
1203 cache->width_frac = lround ((fwidth - cache->width_int)
1204 * WIDTH_FRAC_SCALE);
1205 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1207 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1208 width = font->pixel_size;
1210 width = cache->width_int;
1214 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1216 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1218 if (macfont_info->synthetic_italic_p)
1220 /* We assume the members a, b, c, and d in
1221 synthetic_italic_atfm are non-negative. */
1223 CGPointApplyAffineTransform (bounds.origin,
1224 synthetic_italic_atfm);
1226 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1228 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1230 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1232 bounds = CGRectInset (bounds, d, d);
1234 switch (macfont_info->spacing)
1236 case MACFONT_SPACING_PROPORTIONAL:
1237 bounds.origin.x += - (cache->width_frac
1238 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1240 case MACFONT_SPACING_MONO:
1242 case MACFONT_SPACING_SYNTHETIC_MONO:
1243 bounds.origin.x += (cache->width_int
1244 + (cache->width_frac
1245 / (CGFloat) WIDTH_FRAC_SCALE));
1248 if (bounds.size.width > 0)
1250 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1251 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1252 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1254 bounds = CGRectIntegral (bounds);
1255 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1256 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1257 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1258 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1260 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1261 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1262 metrics->width = width;
1263 metrics->ascent = METRICS_VALUE (cache, ascent);
1264 metrics->descent = METRICS_VALUE (cache, descent);
1269 switch (macfont_info->spacing)
1271 case MACFONT_SPACING_PROPORTIONAL:
1272 *advance_delta = (force_integral_p ? 0
1273 : - (cache->width_frac
1274 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1276 case MACFONT_SPACING_MONO:
1279 case MACFONT_SPACING_SYNTHETIC_MONO:
1280 *advance_delta = (force_integral_p ? cache->width_int
1282 + (cache->width_frac
1283 / (CGFloat) WIDTH_FRAC_SCALE)));
1291 static CFMutableDictionaryRef macfont_cache_dictionary;
1293 /* Threshold used in row_nkeys_or_perm. This must be less than or
1294 equal to the number of rows that are invalid as BMP (i.e., from
1295 U+D800 to U+DFFF). */
1296 #define ROW_PERM_OFFSET (8)
1298 /* The number of glyphs that can be stored in a value for a single
1299 entry of CFDictionary. */
1300 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1302 struct macfont_cache
1304 int reference_count;
1305 CFCharacterSetRef cf_charset;
1307 /* The cached glyph for a BMP character c is stored in
1308 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1309 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1310 unsigned char row_nkeys_or_perm[256];
1313 /* Number of rows for which the BMP cache is allocated so far.
1314 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1317 /* The cached glyph for a character c is stored as the (c %
1318 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1319 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1320 not stored here if row_nkeys_or_perm[c / 256] >=
1322 CFMutableDictionaryRef dictionary;
1326 /* UVS (Unicode Variation Sequence) subtable data, which is of
1327 type CFDataRef if available. NULL means it is not initialized
1328 yet. kCFNull means the subtable is not found and there is no
1329 suitable fallback table for this font. */
1332 /* Character collection specifying the destination of the mapping
1333 provided by `table' above. If `table' is obtained from the UVS
1334 subtable in the font cmap table, then the value of this member
1335 should be kCTCharacterCollectionIdentityMapping. */
1336 CTCharacterCollection collection;
1340 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1341 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1342 static void macfont_release_cache (struct macfont_cache *);
1343 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1344 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1345 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1346 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1347 CTCharacterCollection, CGFontIndex);
1348 static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
1350 static struct macfont_cache *
1351 macfont_lookup_cache (CFStringRef key)
1353 struct macfont_cache *cache;
1355 if (macfont_cache_dictionary == NULL)
1357 macfont_cache_dictionary =
1358 CFDictionaryCreateMutable (NULL, 0,
1359 &kCFTypeDictionaryKeyCallBacks, NULL);
1363 cache = ((struct macfont_cache *)
1364 CFDictionaryGetValue (macfont_cache_dictionary, key));
1368 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1372 cache = xzalloc (sizeof (struct macfont_cache));
1373 /* Treat the LastResort font as if it contained glyphs for
1374 all characters. This may look too rough, but neither
1375 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1376 for this font is correct for non-BMP characters on Mac OS
1378 if (CFEqual (key, CFSTR ("LastResort")))
1380 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1383 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1385 if (cache->cf_charset == NULL)
1386 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1387 CFDictionaryAddValue (macfont_cache_dictionary, key,
1388 (const void *) cache);
1389 CFRelease (macfont);
1396 static struct macfont_cache *
1397 macfont_retain_cache (struct macfont_cache *cache)
1399 cache->reference_count++;
1405 macfont_release_cache (struct macfont_cache *cache)
1407 if (--cache->reference_count == 0)
1411 for (i = 0; i < cache->glyph.nrows; i++)
1412 xfree (cache->glyph.matrix[i]);
1413 xfree (cache->glyph.matrix);
1414 if (cache->glyph.dictionary)
1415 CFRelease (cache->glyph.dictionary);
1416 memset (&cache->glyph, 0, sizeof (cache->glyph));
1417 if (cache->uvs.table)
1418 CFRelease (cache->uvs.table);
1419 memset (&cache->uvs, 0, sizeof (cache->uvs));
1423 static CFCharacterSetRef
1424 macfont_get_cf_charset (struct font *font)
1426 struct macfont_info *macfont_info = (struct macfont_info *) font;
1428 return macfont_info->cache->cf_charset;
1431 static CFCharacterSetRef
1432 macfont_get_cf_charset_for_name (CFStringRef name)
1434 struct macfont_cache *cache = macfont_lookup_cache (name);
1436 return cache->cf_charset;
1440 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1442 struct macfont_info *macfont_info = (struct macfont_info *) font;
1443 CTFontRef macfont = macfont_info->macfont;
1444 struct macfont_cache *cache = macfont_info->cache;
1446 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1449 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1451 if (nkeys_or_perm < ROW_PERM_OFFSET)
1453 UniChar unichars[256], ch;
1457 dispatch_queue_t queue;
1458 dispatch_group_t group = NULL;
1462 CFMutableDictionaryRef dictionary;
1463 uintptr_t key, value;
1467 if (cache->glyph.dictionary == NULL)
1468 cache->glyph.dictionary =
1469 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1470 dictionary = cache->glyph.dictionary;
1471 key = c / NGLYPHS_IN_VALUE;
1472 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1473 value = ((uintptr_t)
1474 CFDictionaryGetValue (dictionary, (const void *) key));
1475 glyph = (value >> nshifts);
1479 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1482 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1484 glyph = kCGFontIndexInvalid;
1487 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1488 value |= ((uintptr_t) glyph << nshifts);
1489 CFDictionarySetValue (dictionary, (const void *) key,
1490 (const void *) value);
1496 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1497 group = dispatch_group_create ();
1498 dispatch_group_async (group, queue, ^{
1501 nkeys = nkeys_or_perm;
1502 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1503 if (CFDictionaryContainsKey (dictionary,
1504 (const void *) key))
1506 CFDictionaryRemoveValue (dictionary,
1507 (const void *) key);
1515 for (i = 0; i < 256; i++)
1518 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1519 unichars[len++] = ch;
1522 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1525 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1528 int next = unichars[len - 1] % 256;
1531 glyphs[i] = kCGFontIndexInvalid;
1534 glyphs[i] = glyphs[len];
1541 glyphs[i] = kCGFontIndexInvalid;
1543 nrows = cache->glyph.nrows;
1544 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1545 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1547 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1548 sizeof (CGGlyph *) * nrows);
1549 cache->glyph.matrix[nrows - 1] = glyphs;
1550 cache->glyph.nrows = nrows;
1554 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1555 dispatch_release (group);
1559 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1563 uintptr_t key, value;
1567 if (cache->glyph.dictionary == NULL)
1568 cache->glyph.dictionary =
1569 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1570 key = c / NGLYPHS_IN_VALUE;
1571 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1572 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1573 (const void *) key);
1574 glyph = (value >> nshifts);
1577 UniChar unichars[2];
1579 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1581 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1584 glyph = kCGFontIndexInvalid;
1586 value |= ((uintptr_t) glyph << nshifts);
1587 CFDictionarySetValue (cache->glyph.dictionary,
1588 (const void *) key, (const void *) value);
1596 macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1599 struct macfont_info *macfont_info = (struct macfont_info *) font;
1600 CTFontRef macfont = macfont_info->macfont;
1603 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1607 macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1609 struct macfont_info *macfont_info = (struct macfont_info *) font;
1610 CTFontRef macfont = macfont_info->macfont;
1611 struct macfont_cache *cache = macfont_info->cache;
1612 CFDataRef result = NULL;
1614 if (cache->uvs.table == NULL)
1616 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1617 CTCharacterCollection uvs_collection =
1618 kCTCharacterCollectionIdentityMapping;
1620 if (uvs_table == NULL
1621 && mac_font_get_glyph_for_cid (macfont,
1622 kCTCharacterCollectionAdobeJapan1,
1623 6480) != kCGFontIndexInvalid)
1625 /* If the glyph for U+4E55 is accessible via its CID 6480,
1626 then we use the Adobe-Japan1 UVS table, which maps a
1627 variation sequence to a CID, as a fallback. */
1628 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1630 if (mac_uvs_table_adobe_japan1 == NULL)
1631 mac_uvs_table_adobe_japan1 =
1632 CFDataCreateWithBytesNoCopy (NULL,
1633 mac_uvs_table_adobe_japan1_bytes,
1634 sizeof (mac_uvs_table_adobe_japan1_bytes),
1636 if (mac_uvs_table_adobe_japan1)
1638 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1639 uvs_collection = kCTCharacterCollectionAdobeJapan1;
1642 if (uvs_table == NULL)
1643 cache->uvs.table = kCFNull;
1645 cache->uvs.table = uvs_table;
1646 cache->uvs.collection = uvs_collection;
1649 if (cache->uvs.table != kCFNull)
1651 result = cache->uvs.table;
1652 *collection = cache->uvs.collection;
1658 static Lisp_Object macfont_get_cache (struct frame *);
1659 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1660 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1661 static Lisp_Object macfont_list_family (struct frame *);
1662 static void macfont_free_entity (Lisp_Object);
1663 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1664 static void macfont_close (struct font *);
1665 static int macfont_has_char (Lisp_Object, int);
1666 static unsigned macfont_encode_char (struct font *, int);
1667 static void macfont_text_extents (struct font *, unsigned int *, int,
1668 struct font_metrics *);
1669 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1670 static Lisp_Object macfont_shape (Lisp_Object);
1671 static int macfont_variation_glyphs (struct font *, int c,
1672 unsigned variations[256]);
1673 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1675 static struct font_driver macfont_driver =
1677 LISP_INITIALLY_ZERO, /* Qmac_ct */
1678 0, /* case insensitive */
1682 macfont_list_family,
1683 macfont_free_entity,
1686 NULL, /* prepare_face */
1687 NULL, /* done_face */
1689 macfont_encode_char,
1690 macfont_text_extents,
1692 NULL, /* get_bitmap */
1693 NULL, /* free_bitmap */
1694 NULL, /* anchor_point */
1695 NULL, /* otf_capability */
1696 NULL, /* otf_drive */
1697 NULL, /* start_for_frame */
1698 NULL, /* end_for_frame */
1701 macfont_variation_glyphs,
1702 macfont_filter_properties,
1706 macfont_get_cache (struct frame * f)
1708 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1710 return (dpyinfo->name_list_element);
1714 macfont_get_charset (Lisp_Object registry)
1716 char *str = SSDATA (SYMBOL_NAME (registry));
1717 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1721 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1725 else if (str[i] == '*')
1732 regexp = make_unibyte_string (re, j);
1733 for (i = 0; cf_charset_table[i].name; i++)
1734 if (fast_c_string_match_ignore_case
1735 (regexp, cf_charset_table[i].name,
1736 strlen (cf_charset_table[i].name)) >= 0)
1738 if (! cf_charset_table[i].name)
1740 if (! cf_charset_table[i].cf_charset)
1742 int *uniquifier = cf_charset_table[i].uniquifier;
1743 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1746 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1750 for (j = 0; uniquifier[j]; j++)
1752 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1754 CFCharacterSetAddCharactersInRange (charset,
1755 CFRangeMake (uniquifier[j], 1));
1758 string = CFStringCreateWithCharacters (NULL, unichars, count);
1761 CFRelease (charset);
1764 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1766 CFRelease (charset);
1767 /* CFCharacterSetCreateWithCharactersInString does not handle
1768 surrogate pairs properly as of Mac OS X 10.5. */
1769 cf_charset_table[i].cf_charset_string = string;
1777 unsigned int script_tag, langsys_tag;
1779 unsigned int *features[2];
1782 #define OTF_SYM_TAG(SYM, TAG) \
1784 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1785 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1788 #define OTF_TAG_STR(TAG, P) \
1790 (P)[0] = (char) (TAG >> 24); \
1791 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1792 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1793 (P)[3] = (char) (TAG & 0xFF); \
1797 static struct OpenTypeSpec *
1798 macfont_get_open_type_spec (Lisp_Object otf_spec)
1800 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1807 spec->script = XCAR (otf_spec);
1808 if (! NILP (spec->script))
1810 OTF_SYM_TAG (spec->script, spec->script_tag);
1811 val = assq_no_quit (spec->script, Votf_script_alist);
1812 if (CONSP (val) && SYMBOLP (XCDR (val)))
1813 spec->script = XCDR (val);
1815 spec->script = Qnil;
1818 spec->script_tag = 0x44464C54; /* "DFLT" */
1819 otf_spec = XCDR (otf_spec);
1820 spec->langsys_tag = 0;
1821 if (! NILP (otf_spec))
1823 val = XCAR (otf_spec);
1825 OTF_SYM_TAG (val, spec->langsys_tag);
1826 otf_spec = XCDR (otf_spec);
1828 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1829 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1833 val = XCAR (otf_spec);
1836 len = Flength (val);
1838 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1840 : malloc (XINT (len) * sizeof *spec->features[i]));
1841 if (! spec->features[i])
1843 if (i > 0 && spec->features[0])
1844 free (spec->features[0]);
1848 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1850 if (NILP (XCAR (val)))
1856 OTF_SYM_TAG (XCAR (val), tag);
1857 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1860 spec->nfeatures[i] = j;
1865 static CFMutableDictionaryRef
1866 macfont_create_attributes_with_spec (Lisp_Object spec)
1868 Lisp_Object tmp, extra;
1869 CFMutableArrayRef langarray = NULL;
1870 CFCharacterSetRef charset = NULL;
1871 CFStringRef charset_string = NULL;
1872 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1873 Lisp_Object script = Qnil;
1874 Lisp_Object registry;
1875 int cf_charset_idx, i;
1876 struct OpenTypeSpec *otspec = NULL;
1878 enum font_property_index index;
1881 } numeric_traits[] =
1882 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1883 {{-0.4, 50}, /* light */
1884 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1885 {0, 100}, /* normal */
1886 {0.24, 140}, /* (semi-bold + normal) / 2 */
1887 {0.4, 200}, /* bold */
1888 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1889 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1890 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1891 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1892 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1894 registry = AREF (spec, FONT_REGISTRY_INDEX);
1896 || EQ (registry, Qascii_0)
1897 || EQ (registry, Qiso10646_1)
1898 || EQ (registry, Qunicode_bmp))
1899 cf_charset_idx = -1;
1904 cf_charset_idx = macfont_get_charset (registry);
1905 if (cf_charset_idx < 0)
1907 charset = cf_charset_table[cf_charset_idx].cf_charset;
1908 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1909 lang = cf_charset_table[cf_charset_idx].lang;
1912 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1915 CFArrayAppendValue (langarray, lang);
1919 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1920 CONSP (extra); extra = XCDR (extra))
1922 Lisp_Object key, val;
1925 key = XCAR (tmp), val = XCDR (tmp);
1926 if (EQ (key, QClang))
1929 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1934 for (; CONSP (val); val = XCDR (val))
1935 if (SYMBOLP (XCAR (val)))
1938 cfstring_create_with_string_noencode (SYMBOL_NAME
1943 CFArrayAppendValue (langarray, lang);
1947 else if (EQ (key, QCotf))
1949 otspec = macfont_get_open_type_spec (val);
1952 script = otspec->script;
1954 else if (EQ (key, QCscript))
1958 if (! NILP (script) && ! charset)
1960 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1962 if (CONSP (chars) && CONSP (CDR (chars)))
1964 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1965 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1967 if (! string || !cs)
1975 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1976 if (CHARACTERP (XCAR (chars)))
1978 UniChar unichars[2];
1980 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1982 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1984 CFStringAppendCharacters (string, unichars, count);
1985 CFCharacterSetAddCharactersInRange (cs, range);
1988 /* CFCharacterSetCreateWithCharactersInString does not
1989 handle surrogate pairs properly as of Mac OS X 10.5. */
1990 charset_string = string;
1994 attributes = CFDictionaryCreateMutable (NULL, 0,
1995 &kCFTypeDictionaryKeyCallBacks,
1996 &kCFTypeDictionaryValueCallBacks);
2000 tmp = AREF (spec, FONT_FAMILY_INDEX);
2001 if (SYMBOLP (tmp) && ! NILP (tmp))
2003 CFStringRef family = macfont_create_family_with_symbol (tmp);
2007 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
2012 traits = CFDictionaryCreateMutable (NULL, 4,
2013 &kCFTypeDictionaryKeyCallBacks,
2014 &kCFTypeDictionaryValueCallBacks);
2018 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
2020 tmp = AREF (spec, numeric_traits[i].index);
2023 CGPoint *point = numeric_traits[i].points;
2024 CGFloat floatval = (XINT (tmp) >> 8); // XXX
2027 while (point->y < floatval)
2029 if (point == numeric_traits[i].points)
2031 else if (point->y == CGFLOAT_MAX)
2033 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
2034 * ((point->x - (point - 1)->x)
2035 / (point->y - (point - 1)->y)));
2038 else if (floatval < -1.0)
2040 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2043 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2047 if (CFDictionaryGetCount (traits))
2048 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2051 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2054 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2057 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2064 CFRelease (attributes);
2069 if (langarray) CFRelease (langarray);
2070 if (charset && cf_charset_idx < 0) CFRelease (charset);
2071 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2072 if (traits) CFRelease (traits);
2075 if (otspec->nfeatures[0] > 0)
2076 free (otspec->features[0]);
2077 if (otspec->nfeatures[1] > 0)
2078 free (otspec->features[1]);
2086 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2087 CFCharacterSetRef charset,
2089 CFArrayRef languages)
2091 Boolean result = true;
2093 if (charset || VECTORP (chars))
2095 CFCharacterSetRef desc_charset =
2096 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2098 if (desc_charset == NULL)
2103 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2104 else /* VECTORP (chars) */
2108 for (j = 0; j < ASIZE (chars); j++)
2109 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2110 && CFCharacterSetIsLongCharacterMember (desc_charset,
2111 XFASTINT (AREF (chars, j))))
2113 if (j == ASIZE (chars))
2116 CFRelease (desc_charset);
2119 if (result && languages)
2120 result = mac_font_descriptor_supports_languages (desc, languages);
2126 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2127 CTFontSymbolicTraits sym_traits2)
2129 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2132 /* We prefer synthetic bold of italic to synthetic italic of bold
2133 when both bold and italic are available but bold-italic is not
2135 if (diff & kCTFontTraitBold)
2136 distance |= (1 << 0);
2137 if (diff & kCTFontTraitItalic)
2138 distance |= (1 << 1);
2139 if (diff & kCTFontTraitMonoSpace)
2140 distance |= (1 << 2);
2146 macfont_closest_traits_index_p (CFArrayRef traits_array,
2147 CTFontSymbolicTraits target,
2150 CFIndex i, count = CFArrayGetCount (traits_array);
2151 CTFontSymbolicTraits traits;
2154 traits = ((CTFontSymbolicTraits) (uintptr_t)
2155 CFArrayGetValueAtIndex (traits_array, index));
2156 my_distance = macfont_traits_distance (target, traits);
2158 for (i = 0; i < count; i++)
2161 traits = ((CTFontSymbolicTraits) (uintptr_t)
2162 CFArrayGetValueAtIndex (traits_array, i));
2163 if (macfont_traits_distance (target, traits) < my_distance)
2171 macfont_list (struct frame *f, Lisp_Object spec)
2173 Lisp_Object val = Qnil, family, extra;
2175 CFStringRef family_name = NULL;
2176 CFMutableDictionaryRef attributes = NULL, traits;
2177 Lisp_Object chars = Qnil;
2179 CTFontSymbolicTraits synth_sym_traits = 0;
2180 CFArrayRef families;
2181 CFIndex families_count;
2182 CFCharacterSetRef charset = NULL;
2183 CFArrayRef languages = NULL;
2187 family = AREF (spec, FONT_FAMILY_INDEX);
2188 if (! NILP (family))
2190 family_name = macfont_create_family_with_symbol (family);
2191 if (family_name == NULL)
2195 attributes = macfont_create_attributes_with_spec (spec);
2199 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2201 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2202 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2204 traits = ((CFMutableDictionaryRef)
2205 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2207 n = FONT_SLANT_NUMERIC (spec);
2208 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2210 synth_sym_traits |= kCTFontTraitItalic;
2212 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2215 n = FONT_WEIGHT_NUMERIC (spec);
2216 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2218 synth_sym_traits |= kCTFontTraitBold;
2220 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2224 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2226 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2228 if (CFStringHasPrefix (language, CFSTR ("ja"))
2229 || CFStringHasPrefix (language, CFSTR ("ko"))
2230 || CFStringHasPrefix (language, CFSTR ("zh")))
2231 synth_sym_traits |= kCTFontTraitMonoSpace;
2234 /* Create array of families. */
2236 families = CFArrayCreate (NULL, (const void **) &family_name,
2237 1, &kCFTypeArrayCallBacks);
2240 CFStringRef pref_family;
2241 CFIndex families_count, pref_family_index = -1;
2243 families = macfont_copy_available_families_cache ();
2244 if (families == NULL)
2247 families_count = CFArrayGetCount (families);
2249 /* Move preferred family to the front if exists. */
2251 mac_font_create_preferred_family_for_attributes (attributes);
2255 CFArrayGetFirstIndexOfValue (families,
2256 CFRangeMake (0, families_count),
2258 CFRelease (pref_family);
2260 if (pref_family_index > 0)
2262 CFMutableArrayRef mutable_families =
2263 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2265 if (mutable_families)
2267 CFArrayAppendValue (mutable_families,
2268 CFArrayGetValueAtIndex (families,
2269 pref_family_index));
2270 CFArrayAppendArray (mutable_families, families,
2271 CFRangeMake (0, pref_family_index));
2272 if (pref_family_index + 1 < families_count)
2273 CFArrayAppendArray (mutable_families, families,
2274 CFRangeMake (pref_family_index + 1,
2276 - (pref_family_index + 1)));
2277 CFRelease (families);
2278 families = mutable_families;
2283 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2287 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2291 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2294 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2295 if (CONSP (val) && VECTORP (XCDR (val)))
2303 CFRetain (languages);
2304 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2308 extra = AREF (spec, FONT_EXTRA_INDEX);
2309 families_count = CFArrayGetCount (families);
2310 for (i = 0; i < families_count; i++)
2312 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2313 CTFontDescriptorRef pat_desc;
2315 CFIndex descs_count;
2316 CFMutableArrayRef filtered_descs, traits_array;
2320 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2322 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2326 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2327 10.7 returns NULL if pat_desc represents the LastResort font.
2328 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2329 trailing "s") for such a font. */
2330 if (!CFEqual (family_name, CFSTR ("LastResort")))
2331 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2334 CTFontDescriptorRef lr_desc =
2335 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2338 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2339 &kCFTypeArrayCallBacks);
2340 CFRelease (lr_desc);
2345 CFRelease (pat_desc);
2349 descs_count = CFArrayGetCount (descs);
2350 if (descs_count == 0
2351 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2360 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2361 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2362 for (j = 0; j < descs_count; j++)
2364 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2365 CFDictionaryRef dict;
2367 CTFontSymbolicTraits sym_traits;
2369 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2373 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2376 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2380 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2381 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2382 != (spacing >= FONT_SPACING_MONO)))
2385 /* Don't use a color bitmap font unless its family is
2386 explicitly specified. */
2387 if ((sym_traits & kCTFontTraitColorGlyphs) && NILP (family))
2391 && !macfont_supports_charset_and_languages_p (desc, charset,
2395 CFArrayAppendValue (filtered_descs, desc);
2396 CFArrayAppendValue (traits_array,
2397 (const void *) (uintptr_t) sym_traits);
2401 descs = filtered_descs;
2402 descs_count = CFArrayGetCount (descs);
2404 for (j = 0; j < descs_count; j++)
2406 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2407 CTFontSymbolicTraits sym_traits =
2408 ((CTFontSymbolicTraits) (uintptr_t)
2409 CFArrayGetValueAtIndex (traits_array, j));
2410 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2412 mask_min = ((synth_sym_traits ^ sym_traits)
2413 & (kCTFontTraitItalic | kCTFontTraitBold));
2414 if (FONT_SLANT_NUMERIC (spec) < 0)
2415 mask_min &= ~kCTFontTraitItalic;
2416 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2417 mask_min &= ~kCTFontTraitBold;
2419 mask_max = (synth_sym_traits & ~sym_traits);
2420 /* Synthetic bold does not work for bitmap-only fonts on Mac
2422 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2424 CFNumberRef format =
2425 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2429 uint32_t format_val;
2431 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2433 && format_val == kCTFontFormatBitmap)
2434 mask_max &= ~kCTFontTraitBold;
2438 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2440 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2441 mmask <= (mask_max & kCTFontTraitMonoSpace);
2442 mmask += kCTFontTraitMonoSpace)
2443 for (bmask = (mask_min & kCTFontTraitBold);
2444 bmask <= (mask_max & kCTFontTraitBold);
2445 bmask += kCTFontTraitBold)
2446 for (imask = (mask_min & kCTFontTraitItalic);
2447 imask <= (mask_max & kCTFontTraitItalic);
2448 imask += kCTFontTraitItalic)
2450 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2453 || macfont_closest_traits_index_p (traits_array,
2454 (sym_traits | synth),
2457 entity = macfont_descriptor_entity (desc, extra, synth);
2458 if (! NILP (entity))
2459 val = Fcons (entity, val);
2464 CFRelease (traits_array);
2468 CFRelease (families);
2469 val = Fnreverse (val);
2475 FONT_ADD_LOG ("macfont-list", spec, val);
2476 if (charset) CFRelease (charset);
2477 if (languages) CFRelease (languages);
2478 if (attributes) CFRelease (attributes);
2479 if (family_name) CFRelease (family_name);
2487 macfont_match (struct frame * frame, Lisp_Object spec)
2489 Lisp_Object entity = Qnil;
2490 CFMutableDictionaryRef attributes;
2491 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2495 attributes = macfont_create_attributes_with_spec (spec);
2498 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2499 CFRelease (attributes);
2503 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2504 CFRelease (pat_desc);
2508 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2514 FONT_ADD_LOG ("macfont-match", spec, entity);
2519 macfont_list_family (struct frame *frame)
2521 Lisp_Object list = Qnil;
2522 CFArrayRef families;
2526 families = macfont_copy_available_families_cache ();
2529 CFIndex i, count = CFArrayGetCount (families);
2531 for (i = 0; i < count; i++)
2532 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2533 CFRelease (families);
2542 macfont_free_entity (Lisp_Object entity)
2544 Lisp_Object val = assq_no_quit (QCfont_entity,
2545 AREF (entity, FONT_EXTRA_INDEX));
2546 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2554 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2556 Lisp_Object val, font_object;
2557 CFStringRef font_name;
2558 struct macfont_info *macfont_info = NULL;
2562 CTFontSymbolicTraits sym_traits;
2564 int len, i, total_width;
2566 CGFloat ascent, descent, leading;
2568 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2570 || XTYPE (XCDR (val)) != Lisp_Misc
2571 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2573 font_name = XSAVE_POINTER (XCDR (val), 0);
2574 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2576 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2581 macfont = CTFontCreateWithName (font_name, size, NULL);
2584 int fontsize = (int) [((NSFont *) macfont) pointSize];
2585 if (fontsize != size) size = fontsize;
2591 font_object = font_build_object (VECSIZE (struct macfont_info),
2592 Qmac_ct, entity, size);
2593 font = XFONT_OBJECT (font_object);
2594 font->pixel_size = size;
2595 font->driver = &macfont_driver;
2596 font->encoding_charset = font->repertory_charset = -1;
2600 macfont_info = (struct macfont_info *) font;
2601 macfont_info->macfont = macfont;
2602 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2604 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2605 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2606 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2609 macfont_info->screen_font = NULL;
2610 macfont_info->cache = macfont_lookup_cache (font_name);
2611 macfont_retain_cache (macfont_info->cache);
2612 macfont_info->metrics = NULL;
2613 macfont_info->metrics_nrows = 0;
2614 macfont_info->synthetic_italic_p = 0;
2615 macfont_info->synthetic_bold_p = 0;
2616 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2617 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2618 if (!(sym_traits & kCTFontTraitItalic)
2619 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2620 macfont_info->synthetic_italic_p = 1;
2621 if (!(sym_traits & kCTFontTraitBold)
2622 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2623 macfont_info->synthetic_bold_p = 1;
2624 if (sym_traits & kCTFontTraitMonoSpace)
2625 macfont_info->spacing = MACFONT_SPACING_MONO;
2626 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2627 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2628 == FONT_SPACING_SYNTHETIC_MONO))
2629 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2630 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2631 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2634 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2636 macfont_info->antialias =
2637 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2639 macfont_info->color_bitmap_p = 0;
2640 if (sym_traits & kCTFontTraitColorGlyphs)
2641 macfont_info->color_bitmap_p = 1;
2643 glyph = macfont_get_glyph_for_character (font, ' ');
2644 if (glyph != kCGFontIndexInvalid)
2645 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2647 /* dirty workaround */
2648 font->space_width = pixel_size;
2650 total_width = font->space_width;
2651 for (i = 1; i < 95; i++)
2653 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2654 if (glyph == kCGFontIndexInvalid)
2656 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2659 font->average_width = total_width / 95;
2661 font->average_width = font->space_width; /* XXX */
2663 if (!(macfont_info->screen_font
2664 && mac_screen_font_get_metrics (macfont_info->screen_font,
2665 &ascent, &descent, &leading)))
2667 CFStringRef family_name;
2669 ascent = CTFontGetAscent (macfont);
2670 descent = CTFontGetDescent (macfont);
2671 leading = CTFontGetLeading (macfont);
2672 /* AppKit and WebKit do some adjustment to the heights of
2673 Courier, Helvetica, and Times. */
2674 family_name = CTFontCopyFamilyName (macfont);
2677 if (CFEqual (family_name, CFSTR ("Courier"))
2678 || CFEqual (family_name, CFSTR ("Helvetica"))
2679 || CFEqual (family_name, CFSTR ("Times")))
2680 ascent += (ascent + descent) * .15f;
2681 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2686 CFRelease (family_name);
2689 font->ascent = ascent + 0.5f;
2690 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2691 if (CONSP (val) && !NILP (XCDR (val)))
2692 font->descent = descent + 0.5f;
2694 font->descent = descent + leading + 0.5f;
2695 font->height = font->ascent + font->descent;
2697 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2698 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2702 /* Unfortunately Xft doesn't provide a way to get minimum char
2703 width. So, we use space_width instead. */
2704 font->min_width = font->max_width = font->space_width; /* XXX */
2706 font->baseline_offset = 0;
2707 font->relative_compose = 0;
2708 font->default_ascent = 0;
2709 font->vertical_centering = 0;
2715 macfont_close (struct font *font)
2717 struct macfont_info *macfont_info = (struct macfont_info *) font;
2719 if (macfont_info->cache)
2724 CFRelease (macfont_info->macfont);
2725 CGFontRelease (macfont_info->cgfont);
2726 if (macfont_info->screen_font)
2727 CFRelease (macfont_info->screen_font);
2728 macfont_release_cache (macfont_info->cache);
2729 for (i = 0; i < macfont_info->metrics_nrows; i++)
2730 if (macfont_info->metrics[i])
2731 xfree (macfont_info->metrics[i]);
2732 if (macfont_info->metrics)
2733 xfree (macfont_info->metrics);
2734 macfont_info->cache = NULL;
2740 macfont_has_char (Lisp_Object font, int c)
2743 CFCharacterSetRef charset;
2746 if (FONT_ENTITY_P (font))
2751 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2753 name = XSAVE_POINTER (val, 0);
2754 charset = macfont_get_cf_charset_for_name (name);
2757 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2759 result = CFCharacterSetIsLongCharacterMember (charset, c);
2766 macfont_encode_char (struct font *font, int c)
2768 struct macfont_info *macfont_info = (struct macfont_info *) font;
2772 glyph = macfont_get_glyph_for_character (font, c);
2775 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2779 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2780 struct font_metrics *metrics)
2785 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2786 for (i = 1; i < nglyphs; i++)
2788 struct font_metrics m;
2789 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2794 if (width + m.lbearing < metrics->lbearing)
2795 metrics->lbearing = width + m.lbearing;
2796 if (width + m.rbearing > metrics->rbearing)
2797 metrics->rbearing = width + m.rbearing;
2798 if (m.ascent > metrics->ascent)
2799 metrics->ascent = m.ascent;
2800 if (m.descent > metrics->descent)
2801 metrics->descent = m.descent;
2808 metrics->width = width;
2812 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2813 bool with_background)
2815 struct frame * f = s->f;
2816 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2817 CGRect background_rect;
2818 CGPoint text_position;
2821 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2822 bool no_antialias_p =
2823 (NILP (ns_antialias_text)
2824 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2825 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2826 && font_size <= macfont_antialias_threshold));
2827 int len = to - from;
2828 struct face *face = s->face;
2829 CGContextRef context;
2833 if (with_background)
2834 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2835 s->width, FONT_HEIGHT (s->font));
2837 background_rect = CGRectNull;
2839 text_position = CGPointMake (x, -y);
2840 glyphs = xmalloc (sizeof (CGGlyph) * len);
2842 CGFloat advance_delta = 0;
2844 CGFloat total_width = 0;
2846 positions = xmalloc (sizeof (CGPoint) * len);
2847 for (i = 0; i < len; i++)
2851 glyphs[i] = s->char2b[from + i];
2852 width = (s->padding_p ? 1
2853 : macfont_glyph_extents (s->font, glyphs[i],
2854 NULL, &advance_delta,
2856 positions[i].x = total_width + advance_delta;
2858 total_width += width;
2862 context = [[NSGraphicsContext currentContext] graphicsPort];
2863 CGContextSaveGState (context);
2865 if (!CGRectIsNull (background_rect))
2867 if (s->hl == DRAW_MOUSE_FACE)
2869 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2871 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2873 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2874 CGContextFillRects (context, &background_rect, 1);
2877 if (macfont_info->cgfont)
2879 CGAffineTransform atfm;
2881 CGContextScaleCTM (context, 1, -1);
2882 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2883 if (macfont_info->synthetic_italic_p)
2884 atfm = synthetic_italic_atfm;
2886 atfm = CGAffineTransformIdentity;
2887 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2889 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2890 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2891 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2894 CGContextSetShouldAntialias (context, false);
2896 CGContextSetTextMatrix (context, atfm);
2897 CGContextSetTextPosition (context, text_position.x, text_position.y);
2899 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2900 if (macfont_info->color_bitmap_p
2901 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2902 && CTFontDrawGlyphs != NULL
2908 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2913 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2915 CGContextSetFont (context, macfont_info->cgfont);
2916 CGContextSetFontSize (context, font_size);
2917 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2924 CGContextRestoreGState (context);
2932 macfont_shape (Lisp_Object lgstring)
2934 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2935 struct macfont_info *macfont_info = (struct macfont_info *) font;
2936 CTFontRef macfont = macfont_info->macfont;
2937 ptrdiff_t glyph_len, len, i, j;
2940 CFIndex *nonbmp_indices;
2943 struct mac_glyph_layout *glyph_layouts;
2945 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2947 for (i = 0; i < glyph_len; i++)
2949 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2953 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2959 if (INT_MAX / 2 < len)
2960 memory_full (SIZE_MAX);
2962 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2963 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2964 for (i = j = 0; i < len; i++)
2966 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2968 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2970 nonbmp_indices[j] = i + j;
2974 nonbmp_indices[j] = len + j; /* sentinel */
2978 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2982 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2983 if (macfont_info->screen_font)
2984 used = mac_screen_font_shape (macfont_info->screen_font, string,
2985 glyph_layouts, glyph_len);
2987 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2998 for (i = 0; i < used; i++)
3000 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
3001 struct mac_glyph_layout *gl = glyph_layouts + i;
3003 struct font_metrics metrics;
3004 int xoff, yoff, wadjust;
3008 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
3009 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
3012 from = gl->comp_range.location;
3013 /* Convert UTF-16 index to UTF-32. */
3015 while (nonbmp_indices[j] < from)
3018 LGLYPH_SET_FROM (lglyph, from);
3020 to = gl->comp_range.location + gl->comp_range.length;
3021 /* Convert UTF-16 index to UTF-32. */
3022 while (nonbmp_indices[j] < to)
3025 LGLYPH_SET_TO (lglyph, to - 1);
3027 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3028 the composition is trivial. */
3032 if (unichars[gl->string_index] >= 0xD800
3033 && unichars[gl->string_index] < 0xDC00)
3034 c = (((unichars[gl->string_index] - 0xD800) << 10)
3035 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3037 c = unichars[gl->string_index];
3038 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3040 LGLYPH_SET_CHAR (lglyph, c);
3044 unsigned long cc = gl->glyph_id;
3045 LGLYPH_SET_CODE (lglyph, cc);
3048 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3049 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3050 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3051 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3052 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3053 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3055 xoff = lround (gl->advance_delta);
3056 yoff = lround (- gl->baseline_delta);
3057 wadjust = lround (gl->advance);
3058 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3062 vec = Fmake_vector (make_number (3), Qnil);
3063 ASET (vec, 0, make_number (xoff));
3064 ASET (vec, 1, make_number (yoff));
3065 ASET (vec, 2, make_number (wadjust));
3066 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3072 return make_number (used);
3075 /* Structures for the UVS subtable (format 14) in the cmap table. */
3076 typedef UInt8 UINT24[3];
3078 #pragma pack(push, 1)
3079 struct variation_selector_record
3081 UINT24 var_selector;
3082 UInt32 default_uvs_offset, non_default_uvs_offset;
3087 UInt32 length, num_var_selector_records;
3088 struct variation_selector_record variation_selector_records[1];
3090 #define SIZEOF_UVS_TABLE_HEADER \
3091 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3093 struct unicode_value_range
3095 UINT24 start_unicode_value;
3096 UInt8 additional_count;
3098 struct default_uvs_table {
3099 UInt32 num_unicode_value_ranges;
3100 struct unicode_value_range unicode_value_ranges[1];
3102 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3103 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3107 UINT24 unicode_value;
3110 struct non_default_uvs_table
3112 UInt32 num_uvs_mappings;
3113 struct uvs_mapping uvs_mappings[1];
3115 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3116 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3119 /* Read big endian values. The argument LVAL must be an lvalue. */
3120 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3121 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3122 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3123 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3124 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3125 /* Succeeding one byte should also be accessible. */
3126 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3127 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3129 /* Return UVS subtable for the specified FONT. If the subtable is not
3130 found or ill-formatted, then return NULL. */
3133 mac_font_copy_uvs_table (CTFontRef font)
3135 CFDataRef cmap_table, uvs_table = NULL;
3137 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3138 kCTFontTableOptionNoOptions);
3141 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3142 struct uvs_table *uvs;
3143 struct variation_selector_record *records;
3144 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3147 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3151 cmap_len = CFDataGetLength (cmap_table);
3152 if (sizeof_sfntCMapHeader > cmap_len)
3155 ntables = BUINT16_VALUE (cmap->numTables);
3156 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3157 / sizeof_sfntCMapEncoding))
3160 for (i = 0; i < ntables; i++)
3161 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3162 == kFontUnicodePlatform)
3163 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3164 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3166 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3170 || uvs_offset > cmap_len
3171 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3174 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3175 uvs_len = BUINT32_VALUE (uvs->length);
3176 if (uvs_len > cmap_len - uvs_offset
3177 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3180 if (BUINT16_VALUE (uvs->format) != 14)
3183 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3184 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3185 / sizeof (struct variation_selector_record)))
3188 records = uvs->variation_selector_records;
3189 for (i = 0; i < nrecords; i++)
3191 UInt32 default_uvs_offset, non_default_uvs_offset;
3193 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3194 if (default_uvs_offset)
3196 struct default_uvs_table *default_uvs;
3199 if (default_uvs_offset > uvs_len
3200 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3201 > uvs_len - default_uvs_offset))
3204 default_uvs = ((struct default_uvs_table *)
3205 ((UInt8 *) uvs + default_uvs_offset));
3206 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3207 if (nranges > ((uvs_len - default_uvs_offset
3208 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3209 / sizeof (struct unicode_value_range)))
3211 /* Now 2 * nranges can't overflow, so we can safely use
3212 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3213 mac_font_get_glyphs_for_variants. */
3216 non_default_uvs_offset =
3217 BUINT32_VALUE (records[i].non_default_uvs_offset);
3218 if (non_default_uvs_offset)
3220 struct non_default_uvs_table *non_default_uvs;
3223 if (non_default_uvs_offset > uvs_len
3224 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3225 > uvs_len - non_default_uvs_offset))
3228 non_default_uvs = ((struct non_default_uvs_table *)
3229 ((UInt8 *) uvs + non_default_uvs_offset));
3230 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3231 if (nmappings > ((uvs_len - non_default_uvs_offset
3232 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3233 / sizeof (struct uvs_mapping)))
3235 /* Now 2 * nmappings can't overflow, so we can safely
3236 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3237 in mac_font_get_glyphs_for_variants. */
3241 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3244 CFRelease (cmap_table);
3250 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3251 sequence consisting of the given base character C and each
3252 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3253 result (explained below) into the corresponding GLYPHS[i]. If the
3254 entry is found in the Default UVS Table, then the result is 0. If
3255 the entry is found in the Non-Default UVS Table, then the result is
3256 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3257 elements in SELECTORS must be sorted in strictly increasing
3261 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3262 const UTF32Char selectors[], CGGlyph glyphs[],
3265 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3266 struct variation_selector_record *records = uvs->variation_selector_records;
3268 UInt32 ir, nrecords;
3269 dispatch_queue_t queue =
3270 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3271 dispatch_group_t group = dispatch_group_create ();
3273 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3276 while (i < count && ir < nrecords)
3278 UInt32 default_uvs_offset, non_default_uvs_offset;
3280 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3282 glyphs[i++] = kCGFontIndexInvalid;
3285 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3291 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3292 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3293 non_default_uvs_offset =
3294 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3295 dispatch_group_async (group, queue, ^{
3296 glyphs[i] = kCGFontIndexInvalid;
3298 if (default_uvs_offset)
3300 struct default_uvs_table *default_uvs =
3301 (struct default_uvs_table *) ((UInt8 *) uvs
3302 + default_uvs_offset);
3303 struct unicode_value_range *ranges =
3304 default_uvs->unicode_value_ranges;
3308 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3311 UInt32 mid = (lo + hi) / 2;
3313 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3319 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3320 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3324 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3326 struct non_default_uvs_table *non_default_uvs =
3327 (struct non_default_uvs_table *) ((UInt8 *) uvs
3328 + non_default_uvs_offset);
3329 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3333 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3336 UInt32 mid = (lo + hi) / 2;
3338 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3344 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3345 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3352 glyphs[i++] = kCGFontIndexInvalid;
3353 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3354 dispatch_release (group);
3358 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3360 CFDataRef uvs_table;
3361 CTCharacterCollection uvs_collection;
3365 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3369 UTF32Char selectors[256];
3370 CGGlyph glyphs[256];
3372 for (i = 0; i < 16; i++)
3373 selectors[i] = 0xFE00 + i;
3374 for (; i < 256; i++)
3375 selectors[i] = 0xE0100 + (i - 16);
3376 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3377 for (i = 0; i < 256; i++)
3379 CGGlyph glyph = glyphs[i];
3381 if (uvs_collection != kCTCharacterCollectionIdentityMapping
3382 && glyph != kCGFontIndexInvalid)
3383 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3384 if (glyph == kCGFontIndexInvalid)
3388 variations[i] = (glyph ? glyph
3389 : macfont_get_glyph_for_character (font, c));
3399 static const char *const macfont_booleans[] = {
3405 static const char *const macfont_non_booleans[] = {
3413 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3415 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3419 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3420 CFArrayRef languages)
3422 Boolean result = true;
3423 CFArrayRef desc_languages =
3424 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3426 if (desc_languages == NULL)
3430 CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
3431 CFIndex i, languages_count = CFArrayGetCount (languages);
3433 for (i = 0; i < languages_count; i++)
3435 CFStringRef language = CFArrayGetValueAtIndex (languages, i);
3437 if (!CFArrayContainsValue (desc_languages, range, language)
3438 /* PingFang SC contains "zh" and "zh-Hant" as covered
3439 languages, but does not contain "zh-Hans". */
3440 && !(CFEqual (language, CFSTR ("zh-Hans"))
3441 && CFArrayContainsValue (desc_languages, range,
3448 CFRelease (desc_languages);
3455 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3457 CFStringRef result = NULL;
3458 CFStringRef charset_string =
3459 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3461 if (charset_string && CFStringGetLength (charset_string) > 0)
3463 CFStringRef keys[] = {
3464 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3465 kCTLanguageAttributeName
3467 CFSTR ("NSLanguage")
3470 CFTypeRef values[] = {NULL};
3471 CFIndex num_values = 0;
3472 CFArrayRef languages
3473 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3475 if (languages && CFArrayGetCount (languages) > 0)
3477 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3478 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3481 CFCharacterSetRef charset =
3482 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3484 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3489 CFAttributedStringRef attr_string = NULL;
3490 CTLineRef ctline = NULL;
3491 CFDictionaryRef attrs
3492 = CFDictionaryCreate (NULL, (const void **) keys,
3493 (const void **) values, num_values,
3494 &kCFTypeDictionaryKeyCallBacks,
3495 &kCFTypeDictionaryValueCallBacks);
3499 attr_string = CFAttributedStringCreate (NULL, charset_string,
3505 ctline = CTLineCreateWithAttributedString (attr_string);
3506 CFRelease (attr_string);
3510 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3511 CFIndex i, nruns = CFArrayGetCount (runs);
3514 for (i = 0; i < nruns; i++)
3516 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3517 CFDictionaryRef attributes = CTRunGetAttributes (run);
3518 CTFontRef font_in_run;
3520 if (attributes == NULL)
3523 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3524 if (font_in_run == NULL)
3528 else if (!mac_font_equal_in_postscript_name (font,
3532 if (nruns > 0 && i == nruns)
3533 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3542 static inline double
3543 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3545 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3549 static inline CGRect
3550 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3552 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3557 mac_font_create_available_families (void)
3559 CFMutableArrayRef families = NULL;
3560 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3564 CFIndex i, count = CFArrayGetCount (orig_families);
3566 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3568 for (i = 0; i < count; i++)
3570 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3572 if (!CFStringHasPrefix (family, CFSTR ("."))
3573 && (CTFontManagerCompareFontFamilyNames (family,
3574 CFSTR ("LastResort"),
3576 != kCFCompareEqualTo))
3577 CFArrayAppendValue (families, family);
3579 CFRelease (orig_families);
3586 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3589 CFStringRef name1, name2;
3595 name1 = CTFontCopyPostScriptName (font1);
3598 name2 = CTFontCopyPostScriptName (font2);
3601 result = CFEqual (name1, name2);
3611 mac_font_create_line_with_string_and_font (CFStringRef string,
3614 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3615 CFTypeRef values[] = {NULL, NULL};
3616 CFDictionaryRef attributes = NULL;
3617 CFAttributedStringRef attr_string = NULL;
3618 CTLineRef ctline = NULL;
3619 float float_zero = 0.0f;
3621 values[0] = macfont;
3622 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3625 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3626 (const void **) values,
3628 &kCFTypeDictionaryKeyCallBacks,
3629 &kCFTypeDictionaryValueCallBacks);
3630 CFRelease (values[1]);
3634 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3635 CFRelease (attributes);
3639 ctline = CTLineCreateWithAttributedString (attr_string);
3640 CFRelease (attr_string);
3644 /* Abandon if ctline contains some fonts other than the
3646 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3647 CFIndex i, nruns = CFArrayGetCount (runs);
3649 for (i = 0; i < nruns; i++)
3651 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3652 CFDictionaryRef attributes = CTRunGetAttributes (run);
3653 CTFontRef font_in_run;
3655 if (attributes == NULL)
3658 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3659 if (font_in_run == NULL)
3661 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3675 mac_font_shape (CTFontRef font, CFStringRef string,
3676 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3678 CFIndex used, result = 0;
3679 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3684 used = CTLineGetGlyphCount (ctline);
3685 if (used <= glyph_len)
3687 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3688 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3689 CGFloat total_advance = 0;
3690 CFIndex total_glyph_count = 0;
3692 for (k = 0; k < ctrun_count; k++)
3694 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3695 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3696 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3697 CFRange string_range, comp_range, range;
3698 CFIndex *permutation;
3700 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3701 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3705 #define RIGHT_TO_LEFT_P permutation
3707 /* Now the `comp_range' member of struct mac_glyph_layout is
3708 temporarily used as a work area such that:
3709 glbuf[i].comp_range.location =
3710 min {compRange[i + 1].location, ...,
3711 compRange[glyph_count - 1].location,
3712 maxRange (stringRangeForCTRun)}
3713 glbuf[i].comp_range.length = maxRange (compRange[i])
3714 where compRange[i] is the range of composed characters
3715 containing i-th glyph. */
3716 string_range = CTRunGetStringRange (ctrun);
3717 min_location = string_range.location + string_range.length;
3718 for (i = 0; i < glyph_count; i++)
3720 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3721 CFIndex glyph_index;
3724 if (!RIGHT_TO_LEFT_P)
3725 glyph_index = glyph_count - i - 1;
3728 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3731 CFStringGetRangeOfComposedCharactersAtIndex (string,
3733 gl->comp_range.location = min_location;
3734 gl->comp_range.length = rng.location + rng.length;
3735 if (rng.location < min_location)
3736 min_location = rng.location;
3739 /* Fill the `comp_range' member of struct mac_glyph_layout,
3740 and setup a permutation for right-to-left text. */
3741 comp_range = CFRangeMake (string_range.location, 0);
3742 range = CFRangeMake (0, 0);
3745 struct mac_glyph_layout *gl =
3746 glbuf + range.location + range.length;
3748 if (gl->comp_range.length
3749 > comp_range.location + comp_range.length)
3750 comp_range.length = gl->comp_range.length - comp_range.location;
3751 min_location = gl->comp_range.location;
3754 if (min_location >= comp_range.location + comp_range.length)
3756 comp_range.length = min_location - comp_range.location;
3757 for (i = 0; i < range.length; i++)
3759 glbuf[range.location + i].comp_range = comp_range;
3760 if (RIGHT_TO_LEFT_P)
3761 permutation[range.location + i] =
3762 range.location + range.length - i - 1;
3765 comp_range = CFRangeMake (min_location, 0);
3766 range.location += range.length;
3768 if (range.location == glyph_count)
3773 /* Then fill the remaining members. */
3774 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3777 struct mac_glyph_layout *gl;
3780 if (!RIGHT_TO_LEFT_P)
3781 gl = glbuf + range.location;
3786 src = glyph_count - 1 - range.location;
3787 dest = permutation[src];
3791 CFIndex tmp = gl->string_index;
3793 gl->string_index = glbuf[src].string_index;
3794 glbuf[src].string_index = tmp;
3797 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3799 CTRunGetPositions (ctrun, range, &position);
3800 gl->advance_delta = position.x - total_advance;
3801 gl->baseline_delta = position.y;
3802 gl->advance = (gl->advance_delta
3803 + CTRunGetTypographicBounds (ctrun, range,
3805 total_advance += gl->advance;
3808 if (RIGHT_TO_LEFT_P)
3809 xfree (permutation);
3811 #undef RIGHT_TO_LEFT_P
3813 total_glyph_count += glyph_count;
3823 /* The function below seems to cause a memory leak for the CFString
3824 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3825 10.6.3. For now, we use the NSGlyphInfo version instead. */
3826 #if USE_CT_GLYPH_INFO
3828 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3831 CGGlyph result = kCGFontIndexInvalid;
3832 UniChar characters[] = {0xfffd};
3834 CFAttributedStringRef attr_string = NULL;
3835 CTLineRef ctline = NULL;
3837 string = CFStringCreateWithCharacters (NULL, characters,
3838 ARRAYELTS (characters));
3842 CTGlyphInfoRef glyph_info =
3843 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3844 CFDictionaryRef attributes = NULL;
3848 CFStringRef keys[] = {kCTFontAttributeName,
3849 kCTGlyphInfoAttributeName};
3850 CFTypeRef values[] = {font, glyph_info};
3852 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3853 (const void **) values,
3855 &kCFTypeDictionaryKeyCallBacks,
3856 &kCFTypeDictionaryValueCallBacks);
3857 CFRelease (glyph_info);
3861 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3862 CFRelease (attributes);
3868 ctline = CTLineCreateWithAttributedString (attr_string);
3869 CFRelease (attr_string);
3873 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3875 if (CFArrayGetCount (runs) > 0)
3877 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3878 CFDictionaryRef attributes = CTRunGetAttributes (run);
3882 CTFontRef font_in_run =
3883 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3886 && mac_font_equal_in_postscript_name (font_in_run, font))
3888 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3889 if (result >= CTFontGetGlyphCount (font))
3890 result = kCGFontIndexInvalid;
3902 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3904 CFArrayRef result = NULL;
3906 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3907 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3908 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3911 CTFontRef user_font =
3912 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3916 CFArrayRef languages =
3917 CFArrayCreate (NULL, (const void **) &language, 1,
3918 &kCFTypeArrayCallBacks);
3922 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3924 CFRelease (languages);
3926 CFRelease (user_font);
3929 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3930 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3932 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3933 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3937 for (i = 0; macfont_language_default_font_names[i].language; i++)
3939 if (CFEqual (macfont_language_default_font_names[i].language,
3942 CFMutableArrayRef descriptors =
3943 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3950 macfont_language_default_font_names[i].font_names[j];
3953 CFDictionaryRef attributes =
3954 CFDictionaryCreate (NULL,
3956 &kCTFontNameAttribute),
3958 &macfont_language_default_font_names[i].font_names[j]),
3959 1, &kCFTypeDictionaryKeyCallBacks,
3960 &kCFTypeDictionaryValueCallBacks);
3964 CTFontDescriptorRef pat_desc =
3965 CTFontDescriptorCreateWithAttributes (attributes);
3969 CTFontDescriptorRef descriptor =
3970 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3974 CFArrayAppendValue (descriptors, descriptor);
3975 CFRelease (descriptor);
3977 CFRelease (pat_desc);
3979 CFRelease (attributes);
3982 result = descriptors;
3994 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3995 CFArrayRef languages)
3997 CFStringRef result = NULL;
3998 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3999 CFArrayRef descriptors =
4000 mac_font_copy_default_descriptors_for_language (language);
4004 CFIndex i, count = CFArrayGetCount (descriptors);
4006 for (i = 0; i < count; i++)
4008 CTFontDescriptorRef descriptor =
4009 CFArrayGetValueAtIndex (descriptors, i);
4011 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4014 CFStringRef family =
4015 CTFontDescriptorCopyAttribute (descriptor,
4016 kCTFontFamilyNameAttribute);
4019 if (!CFStringHasPrefix (family, CFSTR ("."))
4020 && !CFEqual (family, CFSTR ("LastResort")))
4030 CFRelease (descriptors);
4037 macfont_get_nsctfont (struct font *font)
4039 struct macfont_info *macfont_info = (struct macfont_info *) font;
4040 CTFontRef macfont = macfont_info->macfont;
4042 return (void *) macfont;
4046 mac_register_font_driver (struct frame *f)
4048 register_font_driver (&macfont_driver, f);
4053 syms_of_macfont (void)
4055 static struct font_driver mac_font_driver;
4057 /* Core Text, for Mac OS X. */
4058 DEFSYM (Qmac_ct, "mac-ct");
4059 macfont_driver.type = Qmac_ct;
4060 register_font_driver (&macfont_driver, NULL);
4062 /* The font property key specifying the font design destination. The
4063 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4064 text. (See the documentation of X Logical Font Description
4065 Conventions.) In the Mac font driver, 1 means the screen font is
4066 used for calculating some glyph metrics. You can see the
4067 difference with Monaco 8pt or 9pt, for example. */
4068 DEFSYM (QCdestination, ":destination");
4070 /* The boolean-valued font property key specifying the use of leading. */
4071 DEFSYM (QCminspace, ":minspace");
4073 macfont_family_cache = Qnil;
4074 staticpro (&macfont_family_cache);