1 /* Font driver on macOS Core text.
2 Copyright (C) 2009-2018 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or (at
9 your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #include <libkern/OSByteOrder.h>
41 static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
42 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
43 static CFArrayRef mac_font_create_available_families (void);
44 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
45 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
47 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
49 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
50 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
51 struct mac_glyph_layout *, CFIndex);
52 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
53 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
55 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
59 struct macfont_metrics;
61 /* The actual structure for Mac font that can be cast to struct font. */
68 ScreenFontRef screen_font;
69 struct macfont_cache *cache;
70 struct macfont_metrics **metrics;
72 bool_bf synthetic_italic_p : 1;
73 bool_bf synthetic_bold_p : 1;
75 unsigned antialias : 2;
76 bool_bf color_bitmap_p : 1;
79 /* Values for the `spacing' member in `struct macfont_info'. */
83 MACFONT_SPACING_PROPORTIONAL,
85 MACFONT_SPACING_SYNTHETIC_MONO,
88 /* Values for the `antialias' member in `struct macfont_info'. */
92 MACFONT_ANTIALIAS_DEFAULT,
93 MACFONT_ANTIALIAS_OFF,
97 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
98 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
99 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
101 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
102 static const CGFloat synthetic_bold_factor = 0.024;
104 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
105 CTFontSymbolicTraits *);
106 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
108 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
109 CTFontSymbolicTraits);
110 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
111 static int macfont_glyph_extents (struct font *, CGGlyph,
112 struct font_metrics *, CGFloat *, int);
113 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
114 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
118 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
120 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
121 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
123 CGGlyph [], CFIndex);
125 /* From CFData to a lisp string. Always returns a unibyte string. */
128 cfdata_to_lisp (CFDataRef data)
130 CFIndex len = CFDataGetLength (data);
131 Lisp_Object result = make_uninit_string (len);
133 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
140 /* From CFString to a lisp string. Returns a unibyte string
141 containing a UTF-8 byte sequence. */
144 cfstring_to_lisp_nodecode (CFStringRef string)
146 Lisp_Object result = Qnil;
148 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
152 CFIndex i, length = CFStringGetLength (string);
154 for (i = 0; i < length; i++)
155 if (CFStringGetCharacterAtIndex (string, i) == 0)
159 return make_unibyte_string (s, strlen (s));
162 data = CFStringCreateExternalRepresentation (NULL, string,
163 kCFStringEncodingUTF8, '?');
166 result = cfdata_to_lisp (data);
173 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
174 cfstring_create_with_utf8_cstring, this function preserves NUL
178 cfstring_create_with_string_noencode (Lisp_Object s)
180 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
181 kCFStringEncodingUTF8, false);
184 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
185 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
186 kCFStringEncodingMacRoman, false);
192 mac_font_get_weight (CTFontRef font)
194 NSFont *nsFont = (NSFont *) font;
196 return [[NSFontManager sharedFontManager] weightOfFont:nsFont];
200 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
202 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
204 return advancement.width;
207 #if !USE_CT_GLYPH_INFO
209 mac_font_get_glyph_for_cid (CTFontRef font, NSCharacterCollection collection,
212 CGGlyph result = kCGFontIndexInvalid;
213 NSFont *nsFont = (NSFont *) font;
214 unichar characters[] = {0xfffd};
216 [NSString stringWithCharacters:characters
217 length:ARRAYELTS (characters)];
218 NSGlyphInfo *glyphInfo =
219 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
220 collection:collection
222 NSDictionary *attributes =
223 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
224 glyphInfo,NSGlyphInfoAttributeName,nil];
225 NSTextStorage *textStorage =
226 [[NSTextStorage alloc] initWithString:string
227 attributes:attributes];
228 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
229 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
230 NSFont *fontInTextStorage;
232 [layoutManager addTextContainer:textContainer];
233 [textContainer release];
234 [textStorage addLayoutManager:layoutManager];
235 [layoutManager release];
238 (void) [layoutManager glyphRangeForTextContainer:textContainer];
240 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
241 effectiveRange:NULL];
242 if (fontInTextStorage == nsFont
243 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
245 NSGlyph glyph = [layoutManager glyphAtIndex:0];
247 if (glyph < [nsFont numberOfGlyphs])
251 [textStorage release];
258 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
260 NSFont *result, *font;
262 font = [NSFont fontWithName:((NSString *) name) size:size];
263 result = [font screenFont];
265 return (ScreenFontRef)[result retain];
270 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
271 CGFloat *descent, CGFloat *leading)
273 NSFont *nsFont = [(NSFont *)font printerFont];
274 NSTextStorage *textStorage;
275 NSLayoutManager *layoutManager;
276 NSTextContainer *textContainer;
278 NSPoint spaceLocation;
281 textStorage = [[NSTextStorage alloc] initWithString:@" "];
282 layoutManager = [[NSLayoutManager alloc] init];
283 textContainer = [[NSTextContainer alloc] init];
285 [textStorage setFont:nsFont];
286 [textContainer setLineFragmentPadding:0];
288 [layoutManager addTextContainer:textContainer];
289 [textContainer release];
290 [textStorage addLayoutManager:layoutManager];
291 [layoutManager release];
293 if (!(textStorage && layoutManager && textContainer))
295 [textStorage release];
300 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
301 effectiveRange:NULL];
302 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
303 [textStorage release];
305 *ascent = spaceLocation.y;
306 *descent = NSHeight (usedRect) - spaceLocation.y;
308 descender = [nsFont descender];
309 if (- descender < *descent)
311 *leading = *descent + descender;
312 *descent = - descender;
319 mac_font_shape_1 (NSFont *font, NSString *string,
320 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
324 NSTextStorage *textStorage;
325 NSLayoutManager *layoutManager;
326 NSTextContainer *textContainer;
327 NSUInteger stringLength;
328 NSPoint spaceLocation;
329 NSUInteger used, numberOfGlyphs;
331 textStorage = [[NSTextStorage alloc] initWithString:string];
332 layoutManager = [[NSLayoutManager alloc] init];
333 textContainer = [[NSTextContainer alloc] init];
335 /* Append a trailing space to measure baseline position. */
336 [textStorage appendAttributedString:([[[NSAttributedString alloc]
337 initWithString:@" "] autorelease])];
338 [textStorage setFont:font];
339 [textContainer setLineFragmentPadding:0];
341 [layoutManager addTextContainer:textContainer];
342 [textContainer release];
343 [textStorage addLayoutManager:layoutManager];
344 [layoutManager release];
346 if (!(textStorage && layoutManager && textContainer))
348 [textStorage release];
353 stringLength = [string length];
356 (void) [layoutManager glyphRangeForTextContainer:textContainer];
358 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
360 /* Remove the appended trailing space because otherwise it may
361 generate a wrong result for a right-to-left text. */
362 [textStorage beginEditing];
363 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
364 [textStorage endEditing];
365 (void) [layoutManager glyphRangeForTextContainer:textContainer];
368 while (i < stringLength)
371 NSFont *fontInTextStorage =
372 [textStorage attribute:NSFontAttributeName atIndex:i
373 longestEffectiveRange:&range
374 inRange:(NSMakeRange (0, stringLength))];
376 if (!(fontInTextStorage == font
377 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
379 i = NSMaxRange (range);
381 if (i < stringLength)
382 /* Make the test `used <= glyph_len' below fail if textStorage
383 contained some fonts other than the specified one. */
384 used = glyph_len + 1;
387 NSRange range = NSMakeRange (0, stringLength);
389 range = [layoutManager glyphRangeForCharacterRange:range
390 actualCharacterRange:NULL];
391 numberOfGlyphs = NSMaxRange (range);
392 used = numberOfGlyphs;
393 for (i = 0; i < numberOfGlyphs; i++)
394 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
398 if (0 < used && used <= glyph_len)
400 NSUInteger glyphIndex, prevGlyphIndex;
401 unsigned char bidiLevel;
402 NSUInteger *permutation;
403 NSRange compRange, range;
404 CGFloat totalAdvance;
407 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
410 /* For now we assume the direction is not changed within the
412 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
415 characterIndexes:NULL
416 bidiLevels:&bidiLevel];
418 permutation = xmalloc (sizeof (NSUInteger) * used);
422 #define RIGHT_TO_LEFT_P permutation
424 /* Fill the `comp_range' member of struct mac_glyph_layout, and
425 setup a permutation for right-to-left text. */
426 compRange = NSMakeRange (0, 0);
427 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
430 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
431 NSUInteger characterIndex =
432 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
434 gl->string_index = characterIndex;
436 if (characterIndex >= NSMaxRange (compRange))
438 compRange.location = NSMaxRange (compRange);
441 NSRange characterRange =
443 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
446 NSMaxRange (characterRange) - compRange.location;
447 [layoutManager glyphRangeForCharacterRange:compRange
448 actualCharacterRange:&characterRange];
449 characterIndex = NSMaxRange (characterRange) - 1;
451 while (characterIndex >= NSMaxRange (compRange));
454 for (i = 0; i < range.length; i++)
455 permutation[range.location + i] = NSMaxRange (range) - i - 1;
457 range = NSMakeRange (NSMaxRange (range), 0);
460 gl->comp_range.location = compRange.location;
461 gl->comp_range.length = compRange.length;
463 while (++glyphIndex < numberOfGlyphs)
464 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
468 for (i = 0; i < range.length; i++)
469 permutation[range.location + i] = NSMaxRange (range) - i - 1;
471 /* Then fill the remaining members. */
472 glyphIndex = prevGlyphIndex = 0;
473 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
476 if (!RIGHT_TO_LEFT_P)
483 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
484 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
485 inTextContainer:textContainer rectCount:&nrects];
487 totalAdvance = NSMaxX (glyphRects[0]);
490 for (i = 0; i < used; i++)
492 struct mac_glyph_layout *gl;
494 NSUInteger nextGlyphIndex;
499 if (!RIGHT_TO_LEFT_P)
500 gl = glyph_layouts + i;
503 NSUInteger dest = permutation[i];
505 gl = glyph_layouts + dest;
508 CFIndex tmp = gl->string_index;
510 gl->string_index = glyph_layouts[i].string_index;
511 glyph_layouts[i].string_index = tmp;
514 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
516 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
517 gl->baseline_delta = spaceLocation.y - location.y;
519 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
522 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
525 if (!RIGHT_TO_LEFT_P)
529 if (prevGlyphIndex == 0)
530 glyphRange = NSMakeRange (0, nextGlyphIndex);
532 glyphRange = NSMakeRange (glyphIndex,
533 nextGlyphIndex - glyphIndex);
536 rectArrayForGlyphRange:glyphRange
537 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
538 inTextContainer:textContainer rectCount:&nrects];
539 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
540 gl->advance_delta = location.x - totalAdvance;
541 gl->advance = maxX - totalAdvance;
548 if (nextGlyphIndex == numberOfGlyphs)
549 glyphRange = NSMakeRange (prevGlyphIndex,
550 numberOfGlyphs - prevGlyphIndex);
552 glyphRange = NSMakeRange (prevGlyphIndex,
553 glyphIndex + 1 - prevGlyphIndex);
556 rectArrayForGlyphRange:glyphRange
557 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
558 inTextContainer:textContainer rectCount:&nrects];
559 minX = min (NSMinX (glyphRects[0]), totalAdvance);
560 gl->advance = totalAdvance - minX;
562 gl->advance_delta = location.x - totalAdvance;
565 prevGlyphIndex = glyphIndex + 1;
566 glyphIndex = nextGlyphIndex;
572 #undef RIGHT_TO_LEFT_P
576 [textStorage release];
582 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
583 struct mac_glyph_layout *glyph_layouts,
586 return mac_font_shape_1 ([(NSFont *)font printerFont],
588 glyph_layouts, glyph_len);
592 get_cgcolor(unsigned long idx, struct frame *f)
594 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
596 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
597 NSInteger noc = [nsColor numberOfComponents];
598 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
601 [nsColor getComponents: components];
602 cgColor = CGColorCreate (colorSpace, components);
607 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
609 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
610 CGContextSetFillColorWithColor (context, refcol_) ; \
611 CGColorRelease (refcol_); \
613 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
615 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
616 CGContextSetFillColorWithColor (context, refcol_); \
617 CGColorRelease (refcol_); \
619 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
621 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
622 CGContextSetStrokeColorWithColor (context, refcol_); \
623 CGColorRelease (refcol_); \
628 /* Mac font driver. */
634 /* characters to distinguish the charset from the others */
636 /* additional constraint by language */
639 CFCharacterSetRef cf_charset;
640 CFStringRef cf_charset_string;
641 } cf_charset_table[] =
642 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
643 { "iso8859-2", { 0x00A0, 0x010E }},
644 { "iso8859-3", { 0x00A0, 0x0108 }},
645 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
646 { "iso8859-5", { 0x00A0, 0x0401 }},
647 { "iso8859-6", { 0x00A0, 0x060C }},
648 { "iso8859-7", { 0x00A0, 0x0384 }},
649 { "iso8859-8", { 0x00A0, 0x05D0 }},
650 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
651 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
652 { "iso8859-11", { 0x00A0, 0x0E01 }},
653 { "iso8859-13", { 0x00A0, 0x201C }},
654 { "iso8859-14", { 0x00A0, 0x0174 }},
655 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
656 { "iso8859-16", { 0x00A0, 0x0218}},
657 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
658 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
659 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
660 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
661 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
662 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
663 { "cns11643.1992-3", { 0x201A9 }},
664 { "cns11643.1992-4", { 0x20057 }},
665 { "cns11643.1992-5", { 0x20000 }},
666 { "cns11643.1992-6", { 0x20003 }},
667 { "cns11643.1992-7", { 0x20055 }},
668 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
669 { "jisx0212.1990-0", { 0x4E44 }},
670 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
671 { "jisx0213.2000-2", { 0xFA49 }},
672 { "jisx0213.2004-1", { 0x20B9F }},
673 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
674 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
675 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
676 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
677 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
678 { "unicode-sip", { 0x20000 }},
682 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
685 CFStringRef language;
686 CFStringRef font_names[3];
687 } macfont_language_default_font_names[] = {
688 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
689 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
691 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
692 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
694 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
695 CFSTR ("STXihei"), /* 10.4 - 10.5 */
697 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
698 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
704 static CGFloat macfont_antialias_threshold;
707 macfont_update_antialias_threshold (void)
713 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
714 kCFPreferencesCurrentApplication,
717 macfont_antialias_threshold = threshold;
720 static inline Lisp_Object
721 macfont_intern_prop_cfstring (CFStringRef cfstring)
723 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
725 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
728 static inline CFIndex
729 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
740 unichars[0] = (c >> 10) + 0xD800;
741 unichars[1] = (c & 0x3FF) + 0xDC00;
748 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
749 CTFontSymbolicTraits *sym_traits)
753 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
754 OS X 10.6 when the value is greater than or equal to 1 << 31. */
755 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
757 *sym_traits = (CTFontSymbolicTraits) sint64_value;
766 mac_font_descriptor_get_adjusted_weight (CTFontDescriptorRef desc, CGFloat val)
768 long percent_val = lround (val * 100);
770 if (percent_val == -40)
772 CTFontRef font = NULL;
774 CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
778 font = CTFontCreateWithName (name, 0, NULL);
783 CFIndex weight = mac_font_get_weight (font);
785 /* Workaround for crash when displaying Oriya characters
786 with Arial Unicode MS on OS X 10.11. */
797 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
798 Lisp_Object spec_or_entity)
801 CFDictionaryRef dict;
805 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
808 ASET (spec_or_entity, FONT_FAMILY_INDEX,
809 macfont_intern_prop_cfstring (str));
812 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
816 enum font_property_index index;
819 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
821 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
822 {{-0.4, 50}, /* light */
823 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
824 {0, 100}, /* normal */
825 {0.24, 140}, /* (semi-bold + normal) / 2 */
826 {0.4, 200}, /* bold */
827 {CGFLOAT_MAX, CGFLOAT_MAX}},
828 mac_font_descriptor_get_adjusted_weight},
829 {FONT_SLANT_INDEX, kCTFontSlantTrait,
830 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
831 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
832 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
835 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
837 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
838 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
840 CGPoint *point = numeric_traits[i].points;
842 if (numeric_traits[i].adjust_func)
843 floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
844 while (point->x < floatval)
846 if (point == numeric_traits[i].points)
848 else if (point->x == CGFLOAT_MAX)
850 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
851 * ((point->y - (point - 1)->y)
852 / (point->x - (point - 1)->x)));
853 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
854 make_number (lround (floatval)));
858 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
861 CTFontSymbolicTraits sym_traits;
864 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
865 spacing = (sym_traits & kCTFontTraitMonoSpace
866 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
867 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
872 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
873 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
874 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
876 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
882 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
883 CTFontSymbolicTraits synth_sym_traits)
886 CFDictionaryRef dict;
887 CTFontSymbolicTraits sym_traits = 0;
890 entity = font_make_entity ();
892 ASET (entity, FONT_TYPE_INDEX, Qmac_ct);
893 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
895 macfont_store_descriptor_attributes (desc, entity);
897 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
900 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
903 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
906 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
907 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
908 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
909 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
910 font_put_extra (entity, QCfont_entity,
911 make_save_ptr_int ((void *) name, sym_traits));
912 if (synth_sym_traits & kCTFontTraitItalic)
913 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
914 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
915 if (synth_sym_traits & kCTFontTraitBold)
916 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
917 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
918 if (synth_sym_traits & kCTFontTraitMonoSpace)
919 ASET (entity, FONT_SPACING_INDEX,
920 make_number (FONT_SPACING_SYNTHETIC_MONO));
925 /* Cache for font family name symbols vs CFStrings. A value of nil
926 means the cache has been invalidated. Otherwise the value is a Lisp
927 hash table whose keys are symbols and the value for a key is either
928 nil (no corresponding family name) or a Lisp save value wrapping the
929 corresponding family name in CFString. */
931 static Lisp_Object macfont_family_cache;
934 macfont_invalidate_family_cache (void)
936 if (HASH_TABLE_P (macfont_family_cache))
938 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
939 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
941 for (i = 0; i < size; ++i)
942 if (!NILP (HASH_HASH (h, i)))
944 Lisp_Object value = HASH_VALUE (h, i);
946 if (SAVE_VALUEP (value))
947 CFRelease (XSAVE_POINTER (value, 0));
949 macfont_family_cache = Qnil;
954 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
956 if (HASH_TABLE_P (macfont_family_cache))
958 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
959 ptrdiff_t i = hash_lookup (h, symbol, NULL);
963 Lisp_Object value = HASH_VALUE (h, i);
965 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
975 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
977 struct Lisp_Hash_Table *h;
982 if (!HASH_TABLE_P (macfont_family_cache))
983 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
985 h = XHASH_TABLE (macfont_family_cache);
986 i = hash_lookup (h, symbol, &hash);
987 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
990 Lisp_Object old_value = HASH_VALUE (h, i);
992 if (SAVE_VALUEP (old_value))
993 CFRelease (XSAVE_POINTER (old_value, 0));
994 set_hash_value_slot (h, i, value);
997 hash_put (h, symbol, value, hash);
1000 /* Cache of all the available font family names except "LastResort"
1001 and those start with ".". NULL means the cache has been invalidated.
1002 Otherwise, the value is CFArray of CFStrings and the elements are
1003 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1004 Mac OS X 10.6 and later). */
1006 static CFArrayRef macfont_available_families_cache = NULL;
1009 macfont_invalidate_available_families_cache (void)
1011 if (macfont_available_families_cache)
1013 CFRelease (macfont_available_families_cache);
1014 macfont_available_families_cache = NULL;
1019 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1021 CFStringRef name, const void *object,
1022 CFDictionaryRef userInfo)
1024 macfont_invalidate_family_cache ();
1025 macfont_invalidate_available_families_cache ();
1029 macfont_init_font_change_handler (void)
1031 static bool initialized = false;
1037 CFNotificationCenterAddObserver
1038 (CFNotificationCenterGetLocalCenter (), NULL,
1039 macfont_handle_font_change_notification,
1040 kCTFontManagerRegisteredFontsChangedNotification,
1041 NULL, CFNotificationSuspensionBehaviorCoalesce);
1045 macfont_copy_available_families_cache (void)
1047 macfont_init_font_change_handler ();
1049 if (macfont_available_families_cache == NULL)
1050 macfont_available_families_cache = mac_font_create_available_families ();
1052 return (macfont_available_families_cache
1053 ? CFRetain (macfont_available_families_cache) : NULL);
1057 macfont_create_family_with_symbol (Lisp_Object symbol)
1059 CFStringRef result = NULL, family_name;
1060 CFDictionaryRef attributes = NULL;
1061 CTFontDescriptorRef pat_desc = NULL;
1063 if (macfont_get_family_cache_if_present (symbol, &result))
1064 return result ? CFRetain (result) : NULL;
1066 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1070 CFDictionaryCreate (NULL,
1071 (const void **) &kCTFontFamilyNameAttribute,
1072 (const void **) &family_name, 1,
1073 &kCFTypeDictionaryKeyCallBacks,
1074 &kCFTypeDictionaryValueCallBacks);
1075 CFRelease (family_name);
1079 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1080 CFRelease (attributes);
1084 CTFontDescriptorRef desc =
1085 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1090 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1093 macfont_set_family_cache (symbol, result);
1094 CFRelease (pat_desc);
1100 #define WIDTH_FRAC_BITS (4)
1101 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1103 struct macfont_metrics
1105 unsigned char lbearing_low, rbearing_low;
1106 signed lbearing_high : 4, rbearing_high : 4;
1107 unsigned char ascent_low, descent_low;
1108 signed ascent_high : 4, descent_high : 4;
1110 /* These two members are used for fixed-point representation of
1111 glyph width. The `width_int' member is an integer that is
1112 closest to the width. The `width_frac' member is the fractional
1113 adjustment representing a value in [-.5, .5], multiplied by
1114 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1115 the advance delta for centering instead of the glyph width. */
1116 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1119 #define METRICS_VALUE(metrics, member) \
1120 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1121 #define METRICS_SET_VALUE(metrics, member, value) \
1122 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1123 (metrics)->member##_high = tmp >> 8;} while (0)
1127 METRICS_INVALID = -1, /* metrics entry is invalid */
1128 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1131 #define METRICS_STATUS(metrics) \
1132 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1133 #define METRICS_SET_STATUS(metrics, status) \
1134 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1135 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1137 #define METRICS_NCOLS_PER_ROW (128)
1138 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1139 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1142 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1143 struct font_metrics *metrics, CGFloat *advance_delta,
1144 int force_integral_p)
1146 struct macfont_info *macfont_info = (struct macfont_info *) font;
1147 CTFontRef macfont = macfont_info->macfont;
1149 struct macfont_metrics *cache;
1152 row = glyph / METRICS_NCOLS_PER_ROW;
1153 col = glyph % METRICS_NCOLS_PER_ROW;
1154 if (row >= macfont_info->metrics_nrows)
1156 macfont_info->metrics =
1157 xrealloc (macfont_info->metrics,
1158 sizeof (struct macfont_metrics *) * (row + 1));
1159 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1160 (sizeof (struct macfont_metrics *)
1161 * (row + 1 - macfont_info->metrics_nrows)));
1162 macfont_info->metrics_nrows = row + 1;
1164 if (macfont_info->metrics[row] == NULL)
1166 struct macfont_metrics *new;
1169 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1170 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1171 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1172 macfont_info->metrics[row] = new;
1174 cache = macfont_info->metrics[row] + col;
1176 if (METRICS_STATUS (cache) == METRICS_INVALID)
1180 if (macfont_info->screen_font)
1181 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1183 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1185 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1186 advance delta value. */
1187 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1188 fwidth = (font->pixel_size - fwidth) / 2;
1189 cache->width_int = lround (fwidth);
1190 cache->width_frac = lround ((fwidth - cache->width_int)
1191 * WIDTH_FRAC_SCALE);
1192 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1194 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1195 width = font->pixel_size;
1197 width = cache->width_int;
1201 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1203 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1205 if (macfont_info->synthetic_italic_p)
1207 /* We assume the members a, b, c, and d in
1208 synthetic_italic_atfm are non-negative. */
1210 CGPointApplyAffineTransform (bounds.origin,
1211 synthetic_italic_atfm);
1213 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1215 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1217 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1219 bounds = CGRectInset (bounds, d, d);
1221 switch (macfont_info->spacing)
1223 case MACFONT_SPACING_PROPORTIONAL:
1224 bounds.origin.x += - (cache->width_frac
1225 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1227 case MACFONT_SPACING_MONO:
1229 case MACFONT_SPACING_SYNTHETIC_MONO:
1230 bounds.origin.x += (cache->width_int
1231 + (cache->width_frac
1232 / (CGFloat) WIDTH_FRAC_SCALE));
1235 if (bounds.size.width > 0)
1237 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1238 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1239 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1241 bounds = CGRectIntegral (bounds);
1242 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1243 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1244 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1245 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1247 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1248 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1249 metrics->width = width;
1250 metrics->ascent = METRICS_VALUE (cache, ascent);
1251 metrics->descent = METRICS_VALUE (cache, descent);
1256 switch (macfont_info->spacing)
1258 case MACFONT_SPACING_PROPORTIONAL:
1259 *advance_delta = (force_integral_p ? 0
1260 : - (cache->width_frac
1261 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1263 case MACFONT_SPACING_MONO:
1266 case MACFONT_SPACING_SYNTHETIC_MONO:
1267 *advance_delta = (force_integral_p ? cache->width_int
1269 + (cache->width_frac
1270 / (CGFloat) WIDTH_FRAC_SCALE)));
1278 static CFMutableDictionaryRef macfont_cache_dictionary;
1280 /* Threshold used in row_nkeys_or_perm. This must be less than or
1281 equal to the number of rows that are invalid as BMP (i.e., from
1282 U+D800 to U+DFFF). */
1283 #define ROW_PERM_OFFSET (8)
1285 /* The number of glyphs that can be stored in a value for a single
1286 entry of CFDictionary. */
1287 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1289 struct macfont_cache
1291 int reference_count;
1292 CFCharacterSetRef cf_charset;
1294 /* The cached glyph for a BMP character c is stored in
1295 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1296 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1297 unsigned char row_nkeys_or_perm[256];
1300 /* Number of rows for which the BMP cache is allocated so far.
1301 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1304 /* The cached glyph for a character c is stored as the (c %
1305 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1306 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1307 not stored here if row_nkeys_or_perm[c / 256] >=
1309 CFMutableDictionaryRef dictionary;
1313 /* UVS (Unicode Variation Sequence) subtable data, which is of
1314 type CFDataRef if available. NULL means it is not initialized
1315 yet. kCFNull means the subtable is not found and there is no
1316 suitable fallback table for this font. */
1319 /* Character collection specifying the destination of the mapping
1320 provided by `table' above. If `table' is obtained from the UVS
1321 subtable in the font cmap table, then the value of this member
1322 should be NSIdentityMappingCharacterCollection. */
1323 NSCharacterCollection collection;
1327 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1328 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1329 static void macfont_release_cache (struct macfont_cache *);
1330 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1331 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1332 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1333 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1334 NSCharacterCollection, CGFontIndex);
1335 static CFDataRef macfont_get_uvs_table (struct font *, NSCharacterCollection *);
1337 static struct macfont_cache *
1338 macfont_lookup_cache (CFStringRef key)
1340 struct macfont_cache *cache;
1342 if (macfont_cache_dictionary == NULL)
1344 macfont_cache_dictionary =
1345 CFDictionaryCreateMutable (NULL, 0,
1346 &kCFTypeDictionaryKeyCallBacks, NULL);
1350 cache = ((struct macfont_cache *)
1351 CFDictionaryGetValue (macfont_cache_dictionary, key));
1355 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1359 cache = xzalloc (sizeof (struct macfont_cache));
1360 /* Treat the LastResort font as if it contained glyphs for
1361 all characters. This may look too rough, but neither
1362 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1363 for this font is correct for non-BMP characters on Mac OS
1365 if (CFEqual (key, CFSTR ("LastResort")))
1367 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1370 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1372 if (cache->cf_charset == NULL)
1373 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1374 CFDictionaryAddValue (macfont_cache_dictionary, key,
1375 (const void *) cache);
1376 CFRelease (macfont);
1383 static struct macfont_cache *
1384 macfont_retain_cache (struct macfont_cache *cache)
1386 cache->reference_count++;
1392 macfont_release_cache (struct macfont_cache *cache)
1394 if (--cache->reference_count == 0)
1398 for (i = 0; i < cache->glyph.nrows; i++)
1399 xfree (cache->glyph.matrix[i]);
1400 xfree (cache->glyph.matrix);
1401 if (cache->glyph.dictionary)
1402 CFRelease (cache->glyph.dictionary);
1403 memset (&cache->glyph, 0, sizeof (cache->glyph));
1404 if (cache->uvs.table)
1405 CFRelease (cache->uvs.table);
1406 memset (&cache->uvs, 0, sizeof (cache->uvs));
1410 static CFCharacterSetRef
1411 macfont_get_cf_charset (struct font *font)
1413 struct macfont_info *macfont_info = (struct macfont_info *) font;
1415 return macfont_info->cache->cf_charset;
1418 static CFCharacterSetRef
1419 macfont_get_cf_charset_for_name (CFStringRef name)
1421 struct macfont_cache *cache = macfont_lookup_cache (name);
1423 return cache->cf_charset;
1427 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1429 struct macfont_info *macfont_info = (struct macfont_info *) font;
1430 CTFontRef macfont = macfont_info->macfont;
1431 struct macfont_cache *cache = macfont_info->cache;
1433 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1436 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1438 if (nkeys_or_perm < ROW_PERM_OFFSET)
1440 UniChar unichars[256], ch;
1448 CFMutableDictionaryRef dictionary;
1449 uintptr_t key, value;
1453 if (cache->glyph.dictionary == NULL)
1454 cache->glyph.dictionary =
1455 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1456 dictionary = cache->glyph.dictionary;
1457 key = c / NGLYPHS_IN_VALUE;
1458 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1459 value = ((uintptr_t)
1460 CFDictionaryGetValue (dictionary, (const void *) key));
1461 glyph = (value >> nshifts);
1465 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1468 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1470 glyph = kCGFontIndexInvalid;
1473 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1474 value |= ((uintptr_t) glyph << nshifts);
1475 CFDictionarySetValue (dictionary, (const void *) key,
1476 (const void *) value);
1481 nkeys = nkeys_or_perm;
1482 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1483 if (CFDictionaryContainsKey (dictionary,
1484 (const void *) key))
1486 CFDictionaryRemoveValue (dictionary,
1487 (const void *) key);
1494 for (i = 0; i < 256; i++)
1497 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1498 unichars[len++] = ch;
1501 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1504 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1507 int next = unichars[len - 1] % 256;
1510 glyphs[i] = kCGFontIndexInvalid;
1513 glyphs[i] = glyphs[len];
1520 glyphs[i] = kCGFontIndexInvalid;
1522 nrows = cache->glyph.nrows;
1523 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1524 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1526 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1527 sizeof (CGGlyph *) * nrows);
1528 cache->glyph.matrix[nrows - 1] = glyphs;
1529 cache->glyph.nrows = nrows;
1532 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1536 uintptr_t key, value;
1540 if (cache->glyph.dictionary == NULL)
1541 cache->glyph.dictionary =
1542 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1543 key = c / NGLYPHS_IN_VALUE;
1544 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1545 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1546 (const void *) key);
1547 glyph = (value >> nshifts);
1550 UniChar unichars[2];
1552 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1554 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1557 glyph = kCGFontIndexInvalid;
1559 value |= ((uintptr_t) glyph << nshifts);
1560 CFDictionarySetValue (cache->glyph.dictionary,
1561 (const void *) key, (const void *) value);
1569 macfont_get_glyph_for_cid (struct font *font, NSCharacterCollection collection,
1572 struct macfont_info *macfont_info = (struct macfont_info *) font;
1573 CTFontRef macfont = macfont_info->macfont;
1576 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1580 macfont_get_uvs_table (struct font *font, NSCharacterCollection *collection)
1582 struct macfont_info *macfont_info = (struct macfont_info *) font;
1583 CTFontRef macfont = macfont_info->macfont;
1584 struct macfont_cache *cache = macfont_info->cache;
1585 CFDataRef result = NULL;
1587 if (cache->uvs.table == NULL)
1589 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1590 NSCharacterCollection uvs_collection =
1591 NSIdentityMappingCharacterCollection;
1593 if (uvs_table == NULL
1594 && mac_font_get_glyph_for_cid (macfont,
1595 NSAdobeJapan1CharacterCollection,
1596 6480) != kCGFontIndexInvalid)
1598 /* If the glyph for U+4E55 is accessible via its CID 6480,
1599 then we use the Adobe-Japan1 UVS table, which maps a
1600 variation sequence to a CID, as a fallback. */
1601 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1603 if (mac_uvs_table_adobe_japan1 == NULL)
1604 mac_uvs_table_adobe_japan1 =
1605 CFDataCreateWithBytesNoCopy (NULL,
1606 mac_uvs_table_adobe_japan1_bytes,
1607 sizeof (mac_uvs_table_adobe_japan1_bytes),
1609 if (mac_uvs_table_adobe_japan1)
1611 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1612 uvs_collection = NSAdobeJapan1CharacterCollection;
1615 if (uvs_table == NULL)
1616 cache->uvs.table = kCFNull;
1618 cache->uvs.table = uvs_table;
1619 cache->uvs.collection = uvs_collection;
1622 if (cache->uvs.table != kCFNull)
1624 result = cache->uvs.table;
1625 *collection = cache->uvs.collection;
1631 static Lisp_Object macfont_get_cache (struct frame *);
1632 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1633 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1634 static Lisp_Object macfont_list_family (struct frame *);
1635 static void macfont_free_entity (Lisp_Object);
1636 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1637 static void macfont_close (struct font *);
1638 static int macfont_has_char (Lisp_Object, int);
1639 static unsigned macfont_encode_char (struct font *, int);
1640 static void macfont_text_extents (struct font *, unsigned int *, int,
1641 struct font_metrics *);
1642 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1643 static Lisp_Object macfont_shape (Lisp_Object);
1644 static int macfont_variation_glyphs (struct font *, int c,
1645 unsigned variations[256]);
1646 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1648 static struct font_driver const macfont_driver =
1650 .type = LISPSYM_INITIALLY (Qmac_ct),
1651 .get_cache = macfont_get_cache,
1652 .list = macfont_list,
1653 .match = macfont_match,
1654 .list_family = macfont_list_family,
1655 .free_entity = macfont_free_entity,
1656 .open = macfont_open,
1657 .close = macfont_close,
1658 .has_char = macfont_has_char,
1659 .encode_char = macfont_encode_char,
1660 .text_extents = macfont_text_extents,
1661 .draw = macfont_draw,
1662 .shape = macfont_shape,
1663 .get_variation_glyphs = macfont_variation_glyphs,
1664 .filter_properties = macfont_filter_properties,
1668 macfont_get_cache (struct frame * f)
1670 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1672 return (dpyinfo->name_list_element);
1676 macfont_get_charset (Lisp_Object registry)
1678 char *str = SSDATA (SYMBOL_NAME (registry));
1679 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1683 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1687 else if (str[i] == '*')
1694 regexp = make_unibyte_string (re, j);
1695 for (i = 0; cf_charset_table[i].name; i++)
1696 if (fast_c_string_match_ignore_case
1697 (regexp, cf_charset_table[i].name,
1698 strlen (cf_charset_table[i].name)) >= 0)
1700 if (! cf_charset_table[i].name)
1702 if (! cf_charset_table[i].cf_charset)
1704 int *uniquifier = cf_charset_table[i].uniquifier;
1705 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1708 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1712 for (j = 0; uniquifier[j]; j++)
1714 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1716 CFCharacterSetAddCharactersInRange (charset,
1717 CFRangeMake (uniquifier[j], 1));
1720 string = CFStringCreateWithCharacters (NULL, unichars, count);
1723 CFRelease (charset);
1726 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1728 CFRelease (charset);
1729 /* CFCharacterSetCreateWithCharactersInString does not handle
1730 surrogate pairs properly as of Mac OS X 10.5. */
1731 cf_charset_table[i].cf_charset_string = string;
1739 unsigned int script_tag, langsys_tag;
1741 unsigned int *features[2];
1744 #define OTF_SYM_TAG(SYM, TAG) \
1746 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1747 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1750 #define OTF_TAG_STR(TAG, P) \
1752 (P)[0] = (char) (TAG >> 24); \
1753 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1754 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1755 (P)[3] = (char) (TAG & 0xFF); \
1759 static struct OpenTypeSpec *
1760 macfont_get_open_type_spec (Lisp_Object otf_spec)
1762 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1769 spec->script = XCAR (otf_spec);
1770 if (! NILP (spec->script))
1772 OTF_SYM_TAG (spec->script, spec->script_tag);
1773 val = assq_no_quit (spec->script, Votf_script_alist);
1774 if (CONSP (val) && SYMBOLP (XCDR (val)))
1775 spec->script = XCDR (val);
1777 spec->script = Qnil;
1780 spec->script_tag = 0x44464C54; /* "DFLT" */
1781 otf_spec = XCDR (otf_spec);
1782 spec->langsys_tag = 0;
1783 if (! NILP (otf_spec))
1785 val = XCAR (otf_spec);
1787 OTF_SYM_TAG (val, spec->langsys_tag);
1788 otf_spec = XCDR (otf_spec);
1790 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1791 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1795 val = XCAR (otf_spec);
1798 len = Flength (val);
1800 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1802 : malloc (XINT (len) * sizeof *spec->features[i]));
1803 if (! spec->features[i])
1805 if (i > 0 && spec->features[0])
1806 free (spec->features[0]);
1810 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1812 if (NILP (XCAR (val)))
1818 OTF_SYM_TAG (XCAR (val), tag);
1819 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1822 spec->nfeatures[i] = j;
1827 static CFMutableDictionaryRef
1828 macfont_create_attributes_with_spec (Lisp_Object spec)
1830 Lisp_Object tmp, extra;
1831 CFMutableArrayRef langarray = NULL;
1832 CFCharacterSetRef charset = NULL;
1833 CFStringRef charset_string = NULL;
1834 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1835 Lisp_Object script = Qnil;
1836 Lisp_Object registry;
1837 int cf_charset_idx, i;
1838 struct OpenTypeSpec *otspec = NULL;
1840 enum font_property_index index;
1843 } numeric_traits[] =
1844 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1845 {{-0.4, 50}, /* light */
1846 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1847 {0, 100}, /* normal */
1848 {0.24, 140}, /* (semi-bold + normal) / 2 */
1849 {0.4, 200}, /* bold */
1850 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1851 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1852 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1853 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1854 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1856 registry = AREF (spec, FONT_REGISTRY_INDEX);
1858 || EQ (registry, Qascii_0)
1859 || EQ (registry, Qiso10646_1)
1860 || EQ (registry, Qunicode_bmp))
1861 cf_charset_idx = -1;
1866 cf_charset_idx = macfont_get_charset (registry);
1867 if (cf_charset_idx < 0)
1869 charset = cf_charset_table[cf_charset_idx].cf_charset;
1870 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1871 lang = cf_charset_table[cf_charset_idx].lang;
1874 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1877 CFArrayAppendValue (langarray, lang);
1881 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1882 CONSP (extra); extra = XCDR (extra))
1884 Lisp_Object key, val;
1887 key = XCAR (tmp), val = XCDR (tmp);
1888 if (EQ (key, QClang))
1891 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1896 for (; CONSP (val); val = XCDR (val))
1897 if (SYMBOLP (XCAR (val)))
1900 cfstring_create_with_string_noencode (SYMBOL_NAME
1905 CFArrayAppendValue (langarray, lang);
1909 else if (EQ (key, QCotf))
1911 otspec = macfont_get_open_type_spec (val);
1914 script = otspec->script;
1916 else if (EQ (key, QCscript))
1920 if (! NILP (script) && ! charset)
1922 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1924 if (CONSP (chars) && CONSP (CDR (chars)))
1926 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1927 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1929 if (! string || !cs)
1937 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1938 if (CHARACTERP (XCAR (chars)))
1940 UniChar unichars[2];
1942 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1944 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1946 CFStringAppendCharacters (string, unichars, count);
1947 CFCharacterSetAddCharactersInRange (cs, range);
1950 /* CFCharacterSetCreateWithCharactersInString does not
1951 handle surrogate pairs properly as of Mac OS X 10.5. */
1952 charset_string = string;
1956 attributes = CFDictionaryCreateMutable (NULL, 0,
1957 &kCFTypeDictionaryKeyCallBacks,
1958 &kCFTypeDictionaryValueCallBacks);
1962 tmp = AREF (spec, FONT_FAMILY_INDEX);
1963 if (SYMBOLP (tmp) && ! NILP (tmp))
1965 CFStringRef family = macfont_create_family_with_symbol (tmp);
1969 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1974 traits = CFDictionaryCreateMutable (NULL, 4,
1975 &kCFTypeDictionaryKeyCallBacks,
1976 &kCFTypeDictionaryValueCallBacks);
1980 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1982 tmp = AREF (spec, numeric_traits[i].index);
1985 CGPoint *point = numeric_traits[i].points;
1986 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1989 while (point->y < floatval)
1991 if (point == numeric_traits[i].points)
1993 else if (point->y == CGFLOAT_MAX)
1995 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1996 * ((point->x - (point - 1)->x)
1997 / (point->y - (point - 1)->y)));
2000 else if (floatval < -1.0)
2002 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2005 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2009 if (CFDictionaryGetCount (traits))
2010 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2013 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2016 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2019 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2026 CFRelease (attributes);
2031 if (langarray) CFRelease (langarray);
2032 if (charset && cf_charset_idx < 0) CFRelease (charset);
2033 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2034 if (traits) CFRelease (traits);
2037 if (otspec->nfeatures[0] > 0)
2038 free (otspec->features[0]);
2039 if (otspec->nfeatures[1] > 0)
2040 free (otspec->features[1]);
2048 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2049 CFCharacterSetRef charset,
2051 CFArrayRef languages)
2053 Boolean result = true;
2055 if (charset || VECTORP (chars))
2057 CFCharacterSetRef desc_charset =
2058 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2060 if (desc_charset == NULL)
2065 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2066 else /* VECTORP (chars) */
2070 for (j = 0; j < ASIZE (chars); j++)
2071 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2072 && CFCharacterSetIsLongCharacterMember (desc_charset,
2073 XFASTINT (AREF (chars, j))))
2075 if (j == ASIZE (chars))
2078 CFRelease (desc_charset);
2081 if (result && languages)
2082 result = mac_font_descriptor_supports_languages (desc, languages);
2088 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2089 CTFontSymbolicTraits sym_traits2)
2091 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2094 /* We prefer synthetic bold of italic to synthetic italic of bold
2095 when both bold and italic are available but bold-italic is not
2097 if (diff & kCTFontTraitBold)
2098 distance |= (1 << 0);
2099 if (diff & kCTFontTraitItalic)
2100 distance |= (1 << 1);
2101 if (diff & kCTFontTraitMonoSpace)
2102 distance |= (1 << 2);
2108 macfont_closest_traits_index_p (CFArrayRef traits_array,
2109 CTFontSymbolicTraits target,
2112 CFIndex i, count = CFArrayGetCount (traits_array);
2113 CTFontSymbolicTraits traits;
2116 traits = ((CTFontSymbolicTraits) (uintptr_t)
2117 CFArrayGetValueAtIndex (traits_array, index));
2118 my_distance = macfont_traits_distance (target, traits);
2120 for (i = 0; i < count; i++)
2123 traits = ((CTFontSymbolicTraits) (uintptr_t)
2124 CFArrayGetValueAtIndex (traits_array, i));
2125 if (macfont_traits_distance (target, traits) < my_distance)
2133 macfont_list (struct frame *f, Lisp_Object spec)
2135 Lisp_Object val = Qnil, family, extra;
2137 CFStringRef family_name = NULL;
2138 CFMutableDictionaryRef attributes = NULL, traits;
2139 Lisp_Object chars = Qnil;
2141 CTFontSymbolicTraits synth_sym_traits = 0;
2142 CFArrayRef families;
2143 CFIndex families_count;
2144 CFCharacterSetRef charset = NULL;
2145 CFArrayRef languages = NULL;
2149 family = AREF (spec, FONT_FAMILY_INDEX);
2150 if (! NILP (family))
2152 family_name = macfont_create_family_with_symbol (family);
2153 if (family_name == NULL)
2157 attributes = macfont_create_attributes_with_spec (spec);
2161 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2163 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2164 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2166 traits = ((CFMutableDictionaryRef)
2167 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2169 n = FONT_SLANT_NUMERIC (spec);
2170 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2172 synth_sym_traits |= kCTFontTraitItalic;
2174 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2177 n = FONT_WEIGHT_NUMERIC (spec);
2178 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2180 synth_sym_traits |= kCTFontTraitBold;
2182 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2186 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2188 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2190 if (CFStringHasPrefix (language, CFSTR ("ja"))
2191 || CFStringHasPrefix (language, CFSTR ("ko"))
2192 || CFStringHasPrefix (language, CFSTR ("zh")))
2193 synth_sym_traits |= kCTFontTraitMonoSpace;
2196 /* Create array of families. */
2198 families = CFArrayCreate (NULL, (const void **) &family_name,
2199 1, &kCFTypeArrayCallBacks);
2202 CFStringRef pref_family;
2203 CFIndex families_count, pref_family_index = -1;
2205 families = macfont_copy_available_families_cache ();
2206 if (families == NULL)
2209 families_count = CFArrayGetCount (families);
2211 /* Move preferred family to the front if exists. */
2213 mac_font_create_preferred_family_for_attributes (attributes);
2217 CFArrayGetFirstIndexOfValue (families,
2218 CFRangeMake (0, families_count),
2220 CFRelease (pref_family);
2222 if (pref_family_index > 0)
2224 CFMutableArrayRef mutable_families =
2225 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2227 if (mutable_families)
2229 CFArrayAppendValue (mutable_families,
2230 CFArrayGetValueAtIndex (families,
2231 pref_family_index));
2232 CFArrayAppendArray (mutable_families, families,
2233 CFRangeMake (0, pref_family_index));
2234 if (pref_family_index + 1 < families_count)
2235 CFArrayAppendArray (mutable_families, families,
2236 CFRangeMake (pref_family_index + 1,
2238 - (pref_family_index + 1)));
2239 CFRelease (families);
2240 families = mutable_families;
2245 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2249 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2253 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2256 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2257 if (CONSP (val) && VECTORP (XCDR (val)))
2265 CFRetain (languages);
2266 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2270 extra = AREF (spec, FONT_EXTRA_INDEX);
2271 families_count = CFArrayGetCount (families);
2272 for (i = 0; i < families_count; i++)
2274 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2275 CTFontDescriptorRef pat_desc;
2277 CFIndex descs_count;
2278 CFMutableArrayRef filtered_descs, traits_array;
2282 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2284 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2288 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2289 10.7 returns NULL if pat_desc represents the LastResort font.
2290 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2291 trailing "s") for such a font. */
2292 if (!CFEqual (family_name, CFSTR ("LastResort")))
2293 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2296 CTFontDescriptorRef lr_desc =
2297 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2300 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2301 &kCFTypeArrayCallBacks);
2302 CFRelease (lr_desc);
2307 CFRelease (pat_desc);
2311 descs_count = CFArrayGetCount (descs);
2312 if (descs_count == 0
2313 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2322 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2323 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2324 for (j = 0; j < descs_count; j++)
2326 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2327 CFDictionaryRef dict;
2329 CTFontSymbolicTraits sym_traits;
2331 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2335 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2338 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2342 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2343 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2344 != (spacing >= FONT_SPACING_MONO)))
2347 /* Don't use a color bitmap font until it is supported on
2349 if (sym_traits & kCTFontTraitColorGlyphs)
2353 && !macfont_supports_charset_and_languages_p (desc, charset,
2357 CFArrayAppendValue (filtered_descs, desc);
2358 CFArrayAppendValue (traits_array,
2359 (const void *) (uintptr_t) sym_traits);
2363 descs = filtered_descs;
2364 descs_count = CFArrayGetCount (descs);
2366 for (j = 0; j < descs_count; j++)
2368 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2369 CTFontSymbolicTraits sym_traits =
2370 ((CTFontSymbolicTraits) (uintptr_t)
2371 CFArrayGetValueAtIndex (traits_array, j));
2372 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2374 mask_min = ((synth_sym_traits ^ sym_traits)
2375 & (kCTFontTraitItalic | kCTFontTraitBold));
2376 if (FONT_SLANT_NUMERIC (spec) < 0)
2377 mask_min &= ~kCTFontTraitItalic;
2378 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2379 mask_min &= ~kCTFontTraitBold;
2381 mask_max = (synth_sym_traits & ~sym_traits);
2382 /* Synthetic bold does not work for bitmap-only fonts on Mac
2384 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2386 CFNumberRef format =
2387 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2391 uint32_t format_val;
2393 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2395 && format_val == kCTFontFormatBitmap)
2396 mask_max &= ~kCTFontTraitBold;
2400 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2402 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2403 mmask <= (mask_max & kCTFontTraitMonoSpace);
2404 mmask += kCTFontTraitMonoSpace)
2405 for (bmask = (mask_min & kCTFontTraitBold);
2406 bmask <= (mask_max & kCTFontTraitBold);
2407 bmask += kCTFontTraitBold)
2408 for (imask = (mask_min & kCTFontTraitItalic);
2409 imask <= (mask_max & kCTFontTraitItalic);
2410 imask += kCTFontTraitItalic)
2412 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2415 || macfont_closest_traits_index_p (traits_array,
2416 (sym_traits | synth),
2419 entity = macfont_descriptor_entity (desc, extra, synth);
2420 if (! NILP (entity))
2421 val = Fcons (entity, val);
2426 CFRelease (traits_array);
2430 CFRelease (families);
2431 val = Fnreverse (val);
2437 FONT_ADD_LOG ("macfont-list", spec, val);
2438 if (charset) CFRelease (charset);
2439 if (languages) CFRelease (languages);
2440 if (attributes) CFRelease (attributes);
2441 if (family_name) CFRelease (family_name);
2449 macfont_match (struct frame * frame, Lisp_Object spec)
2451 Lisp_Object entity = Qnil;
2452 CFMutableDictionaryRef attributes;
2453 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2457 attributes = macfont_create_attributes_with_spec (spec);
2460 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2461 CFRelease (attributes);
2465 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2466 CFRelease (pat_desc);
2470 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2476 FONT_ADD_LOG ("macfont-match", spec, entity);
2481 macfont_list_family (struct frame *frame)
2483 Lisp_Object list = Qnil;
2484 CFArrayRef families;
2488 families = macfont_copy_available_families_cache ();
2491 CFIndex i, count = CFArrayGetCount (families);
2493 for (i = 0; i < count; i++)
2494 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2495 CFRelease (families);
2504 macfont_free_entity (Lisp_Object entity)
2506 Lisp_Object val = assq_no_quit (QCfont_entity,
2507 AREF (entity, FONT_EXTRA_INDEX));
2508 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2516 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2518 Lisp_Object val, font_object;
2519 CFStringRef font_name;
2520 struct macfont_info *macfont_info = NULL;
2524 CTFontSymbolicTraits sym_traits;
2527 CGFloat ascent, descent, leading;
2529 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2531 || XTYPE (XCDR (val)) != Lisp_Misc
2532 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2534 font_name = XSAVE_POINTER (XCDR (val), 0);
2535 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2537 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2542 macfont = CTFontCreateWithName (font_name, size, NULL);
2545 int fontsize = (int) [((NSFont *) macfont) pointSize];
2546 if (fontsize != size) size = fontsize;
2552 font_object = font_build_object (VECSIZE (struct macfont_info),
2553 Qmac_ct, entity, size);
2554 font = XFONT_OBJECT (font_object);
2555 font->pixel_size = size;
2556 font->driver = &macfont_driver;
2557 font->encoding_charset = font->repertory_charset = -1;
2561 macfont_info = (struct macfont_info *) font;
2562 macfont_info->macfont = macfont;
2563 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2565 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2566 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2567 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2570 macfont_info->screen_font = NULL;
2571 macfont_info->cache = macfont_lookup_cache (font_name);
2572 macfont_retain_cache (macfont_info->cache);
2573 macfont_info->metrics = NULL;
2574 macfont_info->metrics_nrows = 0;
2575 macfont_info->synthetic_italic_p = 0;
2576 macfont_info->synthetic_bold_p = 0;
2577 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2578 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2579 if (!(sym_traits & kCTFontTraitItalic)
2580 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2581 macfont_info->synthetic_italic_p = 1;
2582 if (!(sym_traits & kCTFontTraitBold)
2583 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2584 macfont_info->synthetic_bold_p = 1;
2585 if (sym_traits & kCTFontTraitMonoSpace)
2586 macfont_info->spacing = MACFONT_SPACING_MONO;
2587 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2588 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2589 == FONT_SPACING_SYNTHETIC_MONO))
2590 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2591 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2592 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2595 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2597 macfont_info->antialias =
2598 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2600 macfont_info->color_bitmap_p = 0;
2601 if (sym_traits & kCTFontTraitColorGlyphs)
2602 macfont_info->color_bitmap_p = 1;
2604 glyph = macfont_get_glyph_for_character (font, ' ');
2605 if (glyph != kCGFontIndexInvalid)
2606 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2608 /* dirty workaround */
2609 font->space_width = pixel_size;
2611 total_width = font->space_width;
2612 for (i = 1; i < 95; i++)
2614 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2615 if (glyph == kCGFontIndexInvalid)
2617 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2620 font->average_width = total_width / 95;
2622 font->average_width = font->space_width; /* XXX */
2624 if (!(macfont_info->screen_font
2625 && mac_screen_font_get_metrics (macfont_info->screen_font,
2626 &ascent, &descent, &leading)))
2628 CFStringRef family_name;
2630 ascent = CTFontGetAscent (macfont);
2631 descent = CTFontGetDescent (macfont);
2632 leading = CTFontGetLeading (macfont);
2633 /* AppKit and WebKit do some adjustment to the heights of
2634 Courier, Helvetica, and Times. */
2635 family_name = CTFontCopyFamilyName (macfont);
2638 if (CFEqual (family_name, CFSTR ("Courier"))
2639 || CFEqual (family_name, CFSTR ("Helvetica"))
2640 || CFEqual (family_name, CFSTR ("Times")))
2641 ascent += (ascent + descent) * .15f;
2642 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2647 CFRelease (family_name);
2650 font->ascent = ascent + 0.5f;
2651 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2652 if (CONSP (val) && !NILP (XCDR (val)))
2653 font->descent = descent + 0.5f;
2655 font->descent = descent + leading + 0.5f;
2656 font->height = font->ascent + font->descent;
2658 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2659 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2663 /* Unfortunately Xft doesn't provide a way to get minimum char
2664 width. So, we use space_width instead. */
2665 font->min_width = font->max_width = font->space_width; /* XXX */
2667 font->baseline_offset = 0;
2668 font->relative_compose = 0;
2669 font->default_ascent = 0;
2670 font->vertical_centering = 0;
2676 macfont_close (struct font *font)
2678 struct macfont_info *macfont_info = (struct macfont_info *) font;
2680 if (macfont_info->cache)
2685 CFRelease (macfont_info->macfont);
2686 CGFontRelease (macfont_info->cgfont);
2687 if (macfont_info->screen_font)
2688 CFRelease (macfont_info->screen_font);
2689 macfont_release_cache (macfont_info->cache);
2690 for (i = 0; i < macfont_info->metrics_nrows; i++)
2691 if (macfont_info->metrics[i])
2692 xfree (macfont_info->metrics[i]);
2693 if (macfont_info->metrics)
2694 xfree (macfont_info->metrics);
2695 macfont_info->cache = NULL;
2701 macfont_has_char (Lisp_Object font, int c)
2704 CFCharacterSetRef charset;
2707 if (FONT_ENTITY_P (font))
2712 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2714 name = XSAVE_POINTER (val, 0);
2715 charset = macfont_get_cf_charset_for_name (name);
2718 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2720 result = CFCharacterSetIsLongCharacterMember (charset, c);
2727 macfont_encode_char (struct font *font, int c)
2732 glyph = macfont_get_glyph_for_character (font, c);
2735 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2739 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2740 struct font_metrics *metrics)
2745 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2746 for (i = 1; i < nglyphs; i++)
2748 struct font_metrics m;
2749 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2754 if (width + m.lbearing < metrics->lbearing)
2755 metrics->lbearing = width + m.lbearing;
2756 if (width + m.rbearing > metrics->rbearing)
2757 metrics->rbearing = width + m.rbearing;
2758 if (m.ascent > metrics->ascent)
2759 metrics->ascent = m.ascent;
2760 if (m.descent > metrics->descent)
2761 metrics->descent = m.descent;
2768 metrics->width = width;
2772 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2773 bool with_background)
2775 struct frame * f = s->f;
2776 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2777 CGRect background_rect;
2778 CGPoint text_position;
2781 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2782 bool no_antialias_p =
2783 (NILP (ns_antialias_text)
2784 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2785 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2786 && font_size <= macfont_antialias_threshold));
2787 int len = to - from;
2788 struct face *face = s->face;
2789 CGContextRef context;
2793 if (with_background)
2794 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2795 s->width, FONT_HEIGHT (s->font));
2797 background_rect = CGRectNull;
2799 text_position = CGPointMake (x, -y);
2800 glyphs = xmalloc (sizeof (CGGlyph) * len);
2802 CGFloat advance_delta = 0;
2804 CGFloat total_width = 0;
2806 positions = xmalloc (sizeof (CGPoint) * len);
2807 for (i = 0; i < len; i++)
2811 glyphs[i] = s->char2b[from + i];
2812 width = (s->padding_p ? 1
2813 : macfont_glyph_extents (s->font, glyphs[i],
2814 NULL, &advance_delta,
2816 positions[i].x = total_width + advance_delta;
2818 total_width += width;
2822 context = [[NSGraphicsContext currentContext] graphicsPort];
2823 CGContextSaveGState (context);
2825 if (!CGRectIsNull (background_rect))
2827 if (s->hl == DRAW_MOUSE_FACE)
2829 face = FACE_FROM_ID_OR_NULL (s->f,
2830 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2832 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2834 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2835 CGContextFillRects (context, &background_rect, 1);
2838 if (macfont_info->cgfont)
2840 CGAffineTransform atfm;
2842 CGContextScaleCTM (context, 1, -1);
2843 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2844 if (macfont_info->synthetic_italic_p)
2845 atfm = synthetic_italic_atfm;
2847 atfm = CGAffineTransformIdentity;
2848 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2850 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2852 /* Stroke line width for text drawing is not correctly
2853 scaled on Retina display/HiDPI mode when drawn to screen
2854 (whereas it is correctly scaled when drawn to bitmaps),
2855 and synthetic bold looks thinner on such environments.
2856 Apple says there are no plans to address this issue
2857 (rdar://11644870) currently. So we add a workaround. */
2858 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2859 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2860 if ([[FRAME_NS_VIEW(f) window] respondsToSelector:
2861 @selector(backingScaleFactor)])
2863 CGContextSetLineWidth (context, synthetic_bold_factor * font_size
2864 * [[FRAME_NS_VIEW(f) window] backingScaleFactor]);
2865 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2869 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2870 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2872 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2875 CGContextSetShouldAntialias (context, false);
2877 if (!NILP (ns_use_thin_smoothing))
2879 CGContextSetShouldSmoothFonts(context, YES);
2880 CGContextSetFontSmoothingStyle(context, 16);
2883 CGContextSetTextMatrix (context, atfm);
2884 CGContextSetTextPosition (context, text_position.x, text_position.y);
2886 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2887 if (macfont_info->color_bitmap_p
2888 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2889 && CTFontDrawGlyphs != NULL
2895 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2900 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2902 CGContextSetFont (context, macfont_info->cgfont);
2903 CGContextSetFontSize (context, font_size);
2904 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2911 CGContextRestoreGState (context);
2919 macfont_shape (Lisp_Object lgstring)
2921 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2922 struct macfont_info *macfont_info = (struct macfont_info *) font;
2923 CTFontRef macfont = macfont_info->macfont;
2924 ptrdiff_t glyph_len, len, i, j;
2927 CFIndex *nonbmp_indices;
2930 struct mac_glyph_layout *glyph_layouts;
2932 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2934 for (i = 0; i < glyph_len; i++)
2936 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2940 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2946 if (INT_MAX / 2 < len)
2947 memory_full (SIZE_MAX);
2949 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2950 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2951 for (i = j = 0; i < len; i++)
2953 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2955 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2957 nonbmp_indices[j] = i + j;
2961 nonbmp_indices[j] = len + j; /* sentinel */
2965 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2969 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2970 if (macfont_info->screen_font)
2971 used = mac_screen_font_shape (macfont_info->screen_font, string,
2972 glyph_layouts, glyph_len);
2974 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2985 for (i = 0; i < used; i++)
2987 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2988 struct mac_glyph_layout *gl = glyph_layouts + i;
2990 struct font_metrics metrics;
2991 int xoff, yoff, wadjust;
2995 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2996 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2999 from = gl->comp_range.location;
3000 /* Convert UTF-16 index to UTF-32. */
3002 while (nonbmp_indices[j] < from)
3005 LGLYPH_SET_FROM (lglyph, from);
3007 to = gl->comp_range.location + gl->comp_range.length;
3008 /* Convert UTF-16 index to UTF-32. */
3009 while (nonbmp_indices[j] < to)
3012 LGLYPH_SET_TO (lglyph, to - 1);
3014 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3015 the composition is trivial. */
3019 if (unichars[gl->string_index] >= 0xD800
3020 && unichars[gl->string_index] < 0xDC00)
3021 c = (((unichars[gl->string_index] - 0xD800) << 10)
3022 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3024 c = unichars[gl->string_index];
3025 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3027 LGLYPH_SET_CHAR (lglyph, c);
3031 unsigned long cc = gl->glyph_id;
3032 LGLYPH_SET_CODE (lglyph, cc);
3035 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3036 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3037 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3038 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3039 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3040 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3042 xoff = lround (gl->advance_delta);
3043 yoff = lround (- gl->baseline_delta);
3044 wadjust = lround (gl->advance);
3045 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3049 vec = Fmake_vector (make_number (3), Qnil);
3050 ASET (vec, 0, make_number (xoff));
3051 ASET (vec, 1, make_number (yoff));
3052 ASET (vec, 2, make_number (wadjust));
3053 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3059 return make_number (used);
3062 /* Structures for the UVS subtable (format 14) in the cmap table. */
3063 typedef UInt8 UINT24[3];
3065 #pragma pack(push, 1)
3066 struct variation_selector_record
3068 UINT24 var_selector;
3069 UInt32 default_uvs_offset, non_default_uvs_offset;
3074 UInt32 length, num_var_selector_records;
3075 struct variation_selector_record variation_selector_records[1];
3077 #define SIZEOF_UVS_TABLE_HEADER \
3078 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3080 struct unicode_value_range
3082 UINT24 start_unicode_value;
3083 UInt8 additional_count;
3085 struct default_uvs_table {
3086 UInt32 num_unicode_value_ranges;
3087 struct unicode_value_range unicode_value_ranges[1];
3089 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3090 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3094 UINT24 unicode_value;
3097 struct non_default_uvs_table
3099 UInt32 num_uvs_mappings;
3100 struct uvs_mapping uvs_mappings[1];
3102 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3103 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3106 /* Read big endian values. The argument LVAL must be an lvalue. */
3107 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3108 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3109 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3110 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3111 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3112 /* Succeeding one byte should also be accessible. */
3113 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3114 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3116 /* Return UVS subtable for the specified FONT. If the subtable is not
3117 found or ill-formatted, then return NULL. */
3120 mac_font_copy_uvs_table (CTFontRef font)
3122 CFDataRef cmap_table, uvs_table = NULL;
3124 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3125 kCTFontTableOptionNoOptions);
3128 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3129 struct uvs_table *uvs;
3130 struct variation_selector_record *records;
3131 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3134 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3138 cmap_len = CFDataGetLength (cmap_table);
3139 if (sizeof_sfntCMapHeader > cmap_len)
3142 ntables = BUINT16_VALUE (cmap->numTables);
3143 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3144 / sizeof_sfntCMapEncoding))
3147 for (i = 0; i < ntables; i++)
3148 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3149 == kFontUnicodePlatform)
3150 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3151 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3153 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3157 || uvs_offset > cmap_len
3158 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3161 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3162 uvs_len = BUINT32_VALUE (uvs->length);
3163 if (uvs_len > cmap_len - uvs_offset
3164 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3167 if (BUINT16_VALUE (uvs->format) != 14)
3170 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3171 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3172 / sizeof (struct variation_selector_record)))
3175 records = uvs->variation_selector_records;
3176 for (i = 0; i < nrecords; i++)
3178 UInt32 default_uvs_offset, non_default_uvs_offset;
3180 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3181 if (default_uvs_offset)
3183 struct default_uvs_table *default_uvs;
3186 if (default_uvs_offset > uvs_len
3187 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3188 > uvs_len - default_uvs_offset))
3191 default_uvs = ((struct default_uvs_table *)
3192 ((UInt8 *) uvs + default_uvs_offset));
3193 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3194 if (nranges > ((uvs_len - default_uvs_offset
3195 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3196 / sizeof (struct unicode_value_range)))
3198 /* Now 2 * nranges can't overflow, so we can safely use
3199 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3200 mac_font_get_glyphs_for_variants. */
3203 non_default_uvs_offset =
3204 BUINT32_VALUE (records[i].non_default_uvs_offset);
3205 if (non_default_uvs_offset)
3207 struct non_default_uvs_table *non_default_uvs;
3210 if (non_default_uvs_offset > uvs_len
3211 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3212 > uvs_len - non_default_uvs_offset))
3215 non_default_uvs = ((struct non_default_uvs_table *)
3216 ((UInt8 *) uvs + non_default_uvs_offset));
3217 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3218 if (nmappings > ((uvs_len - non_default_uvs_offset
3219 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3220 / sizeof (struct uvs_mapping)))
3222 /* Now 2 * nmappings can't overflow, so we can safely
3223 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3224 in mac_font_get_glyphs_for_variants. */
3228 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3231 CFRelease (cmap_table);
3237 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3238 sequence consisting of the given base character C and each
3239 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3240 result (explained below) into the corresponding GLYPHS[i]. If the
3241 entry is found in the Default UVS Table, then the result is 0. If
3242 the entry is found in the Non-Default UVS Table, then the result is
3243 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3244 elements in SELECTORS must be sorted in strictly increasing
3248 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3249 const UTF32Char selectors[], CGGlyph glyphs[],
3252 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3253 struct variation_selector_record *records = uvs->variation_selector_records;
3255 UInt32 ir, nrecords;
3257 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3260 while (i < count && ir < nrecords)
3262 UInt32 default_uvs_offset, non_default_uvs_offset;
3264 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3266 glyphs[i++] = kCGFontIndexInvalid;
3269 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3275 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3276 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3277 non_default_uvs_offset =
3278 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3280 glyphs[i] = kCGFontIndexInvalid;
3282 if (default_uvs_offset)
3284 struct default_uvs_table *default_uvs =
3285 (struct default_uvs_table *) ((UInt8 *) uvs
3286 + default_uvs_offset);
3287 struct unicode_value_range *ranges =
3288 default_uvs->unicode_value_ranges;
3292 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3295 UInt32 mid = (lo + hi) / 2;
3297 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3303 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3304 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3308 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3310 struct non_default_uvs_table *non_default_uvs =
3311 (struct non_default_uvs_table *) ((UInt8 *) uvs
3312 + non_default_uvs_offset);
3313 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3317 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3320 UInt32 mid = (lo + hi) / 2;
3322 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3328 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3329 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3335 glyphs[i++] = kCGFontIndexInvalid;
3339 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3341 CFDataRef uvs_table;
3342 NSCharacterCollection uvs_collection;
3346 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3350 UTF32Char selectors[256];
3351 CGGlyph glyphs[256];
3353 for (i = 0; i < 16; i++)
3354 selectors[i] = 0xFE00 + i;
3355 for (; i < 256; i++)
3356 selectors[i] = 0xE0100 + (i - 16);
3357 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3358 for (i = 0; i < 256; i++)
3360 CGGlyph glyph = glyphs[i];
3362 if (uvs_collection != NSIdentityMappingCharacterCollection
3363 && glyph != kCGFontIndexInvalid)
3364 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3365 if (glyph == kCGFontIndexInvalid)
3369 variations[i] = (glyph ? glyph
3370 : macfont_get_glyph_for_character (font, c));
3380 static const char *const macfont_booleans[] = {
3386 static const char *const macfont_non_booleans[] = {
3394 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3396 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3400 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3401 CFArrayRef languages)
3403 Boolean result = true;
3404 CFArrayRef desc_languages =
3405 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3407 if (desc_languages == NULL)
3411 CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
3412 CFIndex i, languages_count = CFArrayGetCount (languages);
3414 for (i = 0; i < languages_count; i++)
3416 CFStringRef language = CFArrayGetValueAtIndex (languages, i);
3418 if (!CFArrayContainsValue (desc_languages, range, language)
3419 /* PingFang SC contains "zh" and "zh-Hant" as covered
3420 languages, but does not contain "zh-Hans". */
3421 && !(CFEqual (language, CFSTR ("zh-Hans"))
3422 && CFArrayContainsValue (desc_languages, range,
3429 CFRelease (desc_languages);
3436 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3438 CFStringRef result = NULL;
3439 CFStringRef charset_string =
3440 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3442 if (charset_string && CFStringGetLength (charset_string) > 0)
3444 CFStringRef keys[] = {
3445 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3446 kCTLanguageAttributeName
3448 CFSTR ("NSLanguage")
3451 CFTypeRef values[] = {NULL};
3452 CFIndex num_values = 0;
3453 CFArrayRef languages
3454 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3456 if (languages && CFArrayGetCount (languages) > 0)
3458 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3459 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3462 CFCharacterSetRef charset =
3463 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3465 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3470 CFAttributedStringRef attr_string = NULL;
3471 CTLineRef ctline = NULL;
3472 CFDictionaryRef attrs
3473 = CFDictionaryCreate (NULL, (const void **) keys,
3474 (const void **) values, num_values,
3475 &kCFTypeDictionaryKeyCallBacks,
3476 &kCFTypeDictionaryValueCallBacks);
3480 attr_string = CFAttributedStringCreate (NULL, charset_string,
3486 ctline = CTLineCreateWithAttributedString (attr_string);
3487 CFRelease (attr_string);
3491 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3492 CFIndex i, nruns = CFArrayGetCount (runs);
3495 for (i = 0; i < nruns; i++)
3497 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3498 CFDictionaryRef attributes = CTRunGetAttributes (run);
3499 CTFontRef font_in_run;
3501 if (attributes == NULL)
3504 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3505 if (font_in_run == NULL)
3509 else if (!mac_font_equal_in_postscript_name (font,
3513 if (nruns > 0 && i == nruns)
3514 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3523 static inline double
3524 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3526 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3530 static inline CGRect
3531 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3533 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3538 mac_font_create_available_families (void)
3540 CFMutableArrayRef families = NULL;
3541 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3545 CFIndex i, count = CFArrayGetCount (orig_families);
3547 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3549 for (i = 0; i < count; i++)
3551 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3553 if (!CFStringHasPrefix (family, CFSTR ("."))
3554 && (CTFontManagerCompareFontFamilyNames (family,
3555 CFSTR ("LastResort"),
3557 != kCFCompareEqualTo))
3558 CFArrayAppendValue (families, family);
3560 CFRelease (orig_families);
3567 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3570 CFStringRef name1, name2;
3576 name1 = CTFontCopyPostScriptName (font1);
3579 name2 = CTFontCopyPostScriptName (font2);
3582 result = CFEqual (name1, name2);
3592 mac_font_create_line_with_string_and_font (CFStringRef string,
3595 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3596 CFTypeRef values[] = {NULL, NULL};
3597 CFDictionaryRef attributes = NULL;
3598 CFAttributedStringRef attr_string = NULL;
3599 CTLineRef ctline = NULL;
3600 float float_zero = 0.0f;
3602 values[0] = macfont;
3603 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3606 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3607 (const void **) values,
3609 &kCFTypeDictionaryKeyCallBacks,
3610 &kCFTypeDictionaryValueCallBacks);
3611 CFRelease (values[1]);
3615 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3616 CFRelease (attributes);
3620 ctline = CTLineCreateWithAttributedString (attr_string);
3621 CFRelease (attr_string);
3625 /* Abandon if ctline contains some fonts other than the
3627 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3628 CFIndex i, nruns = CFArrayGetCount (runs);
3630 for (i = 0; i < nruns; i++)
3632 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3633 CFDictionaryRef attributes = CTRunGetAttributes (run);
3634 CTFontRef font_in_run;
3636 if (attributes == NULL)
3639 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3640 if (font_in_run == NULL)
3642 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3656 mac_font_shape (CTFontRef font, CFStringRef string,
3657 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3659 CFIndex used, result = 0;
3660 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3665 used = CTLineGetGlyphCount (ctline);
3666 if (used <= glyph_len)
3668 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3669 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3670 CGFloat total_advance = 0;
3671 CFIndex total_glyph_count = 0;
3673 for (k = 0; k < ctrun_count; k++)
3675 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3676 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3677 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3678 CFRange string_range, comp_range, range;
3679 CFIndex *permutation;
3681 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3682 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3686 #define RIGHT_TO_LEFT_P permutation
3688 /* Now the `comp_range' member of struct mac_glyph_layout is
3689 temporarily used as a work area such that:
3690 glbuf[i].comp_range.location =
3691 min {compRange[i + 1].location, ...,
3692 compRange[glyph_count - 1].location,
3693 maxRange (stringRangeForCTRun)}
3694 glbuf[i].comp_range.length = maxRange (compRange[i])
3695 where compRange[i] is the range of composed characters
3696 containing i-th glyph. */
3697 string_range = CTRunGetStringRange (ctrun);
3698 min_location = string_range.location + string_range.length;
3699 for (i = 0; i < glyph_count; i++)
3701 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3702 CFIndex glyph_index;
3705 if (!RIGHT_TO_LEFT_P)
3706 glyph_index = glyph_count - i - 1;
3709 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3712 CFStringGetRangeOfComposedCharactersAtIndex (string,
3714 gl->comp_range.location = min_location;
3715 gl->comp_range.length = rng.location + rng.length;
3716 if (rng.location < min_location)
3717 min_location = rng.location;
3720 /* Fill the `comp_range' member of struct mac_glyph_layout,
3721 and setup a permutation for right-to-left text. */
3722 comp_range = CFRangeMake (string_range.location, 0);
3723 range = CFRangeMake (0, 0);
3726 struct mac_glyph_layout *gl =
3727 glbuf + range.location + range.length;
3729 if (gl->comp_range.length
3730 > comp_range.location + comp_range.length)
3731 comp_range.length = gl->comp_range.length - comp_range.location;
3732 min_location = gl->comp_range.location;
3735 if (min_location >= comp_range.location + comp_range.length)
3737 comp_range.length = min_location - comp_range.location;
3738 for (i = 0; i < range.length; i++)
3740 glbuf[range.location + i].comp_range = comp_range;
3741 if (RIGHT_TO_LEFT_P)
3742 permutation[range.location + i] =
3743 range.location + range.length - i - 1;
3746 comp_range = CFRangeMake (min_location, 0);
3747 range.location += range.length;
3749 if (range.location == glyph_count)
3754 /* Then fill the remaining members. */
3755 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3758 struct mac_glyph_layout *gl;
3762 if (!RIGHT_TO_LEFT_P)
3763 gl = glbuf + range.location;
3768 src = glyph_count - 1 - range.location;
3769 dest = permutation[src];
3773 CFIndex tmp = gl->string_index;
3775 gl->string_index = glbuf[src].string_index;
3776 glbuf[src].string_index = tmp;
3779 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3781 CTRunGetPositions (ctrun, range, &position);
3782 max_x = position.x + CTRunGetTypographicBounds (ctrun, range,
3784 max_x = max (max_x, total_advance);
3785 gl->advance_delta = position.x - total_advance;
3786 gl->baseline_delta = position.y;
3787 gl->advance = max_x - total_advance;
3788 total_advance = max_x;
3791 if (RIGHT_TO_LEFT_P)
3792 xfree (permutation);
3794 #undef RIGHT_TO_LEFT_P
3796 total_glyph_count += glyph_count;
3806 /* The function below seems to cause a memory leak for the CFString
3807 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3808 10.6.3. For now, we use the NSGlyphInfo version instead. */
3809 #if USE_CT_GLYPH_INFO
3811 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3814 CGGlyph result = kCGFontIndexInvalid;
3815 UniChar characters[] = {0xfffd};
3817 CFAttributedStringRef attr_string = NULL;
3818 CTLineRef ctline = NULL;
3820 string = CFStringCreateWithCharacters (NULL, characters,
3821 ARRAYELTS (characters));
3825 CTGlyphInfoRef glyph_info =
3826 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3827 CFDictionaryRef attributes = NULL;
3831 CFStringRef keys[] = {kCTFontAttributeName,
3832 kCTGlyphInfoAttributeName};
3833 CFTypeRef values[] = {font, glyph_info};
3835 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3836 (const void **) values,
3838 &kCFTypeDictionaryKeyCallBacks,
3839 &kCFTypeDictionaryValueCallBacks);
3840 CFRelease (glyph_info);
3844 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3845 CFRelease (attributes);
3851 ctline = CTLineCreateWithAttributedString (attr_string);
3852 CFRelease (attr_string);
3856 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3858 if (CFArrayGetCount (runs) > 0)
3860 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3861 CFDictionaryRef attributes = CTRunGetAttributes (run);
3865 CTFontRef font_in_run =
3866 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3869 && mac_font_equal_in_postscript_name (font_in_run, font))
3871 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3872 if (result >= CTFontGetGlyphCount (font))
3873 result = kCGFontIndexInvalid;
3885 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3887 CFArrayRef result = NULL;
3889 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3890 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3891 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3894 CTFontRef user_font =
3895 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3899 CFArrayRef languages =
3900 CFArrayCreate (NULL, (const void **) &language, 1,
3901 &kCFTypeArrayCallBacks);
3905 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3907 CFRelease (languages);
3909 CFRelease (user_font);
3912 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3913 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3915 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3916 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3920 for (i = 0; macfont_language_default_font_names[i].language; i++)
3922 if (CFEqual (macfont_language_default_font_names[i].language,
3925 CFMutableArrayRef descriptors =
3926 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3933 macfont_language_default_font_names[i].font_names[j];
3936 CFDictionaryRef attributes =
3937 CFDictionaryCreate (NULL,
3939 &kCTFontNameAttribute),
3941 &macfont_language_default_font_names[i].font_names[j]),
3942 1, &kCFTypeDictionaryKeyCallBacks,
3943 &kCFTypeDictionaryValueCallBacks);
3947 CTFontDescriptorRef pat_desc =
3948 CTFontDescriptorCreateWithAttributes (attributes);
3952 CTFontDescriptorRef descriptor =
3953 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3957 CFArrayAppendValue (descriptors, descriptor);
3958 CFRelease (descriptor);
3960 CFRelease (pat_desc);
3962 CFRelease (attributes);
3965 result = descriptors;
3977 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3978 CFArrayRef languages)
3980 CFStringRef result = NULL;
3981 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3982 CFArrayRef descriptors =
3983 mac_font_copy_default_descriptors_for_language (language);
3987 CFIndex i, count = CFArrayGetCount (descriptors);
3989 for (i = 0; i < count; i++)
3991 CTFontDescriptorRef descriptor =
3992 CFArrayGetValueAtIndex (descriptors, i);
3994 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3997 CFStringRef family =
3998 CTFontDescriptorCopyAttribute (descriptor,
3999 kCTFontFamilyNameAttribute);
4002 if (!CFStringHasPrefix (family, CFSTR ("."))
4003 && !CFEqual (family, CFSTR ("LastResort")))
4013 CFRelease (descriptors);
4020 macfont_get_nsctfont (struct font *font)
4022 struct macfont_info *macfont_info = (struct macfont_info *) font;
4023 CTFontRef macfont = macfont_info->macfont;
4025 return (void *) macfont;
4029 mac_register_font_driver (struct frame *f)
4031 register_font_driver (&macfont_driver, f);
4036 syms_of_macfont (void)
4038 /* Core Text, for macOS. */
4039 DEFSYM (Qmac_ct, "mac-ct");
4040 register_font_driver (&macfont_driver, NULL);
4042 /* The font property key specifying the font design destination. The
4043 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4044 text. (See the documentation of X Logical Font Description
4045 Conventions.) In the Mac font driver, 1 means the screen font is
4046 used for calculating some glyph metrics. You can see the
4047 difference with Monaco 8pt or 9pt, for example. */
4048 DEFSYM (QCdestination, ":destination");
4050 /* The boolean-valued font property key specifying the use of leading. */
4051 DEFSYM (QCminspace, ":minspace");
4053 macfont_family_cache = Qnil;
4054 staticpro (&macfont_family_cache);