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 Fcons (make_mint_ptr ((void *) name),
912 make_number (sym_traits)));
913 if (synth_sym_traits & kCTFontTraitItalic)
914 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
915 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
916 if (synth_sym_traits & kCTFontTraitBold)
917 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
918 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
919 if (synth_sym_traits & kCTFontTraitMonoSpace)
920 ASET (entity, FONT_SPACING_INDEX,
921 make_number (FONT_SPACING_SYNTHETIC_MONO));
926 /* Cache for font family name symbols vs CFStrings. A value of nil
927 means the cache has been invalidated. Otherwise the value is a Lisp
928 hash table whose keys are symbols and the value for a key is either
929 nil (no corresponding family name) or a Lisp save value wrapping the
930 corresponding family name in CFString. */
932 static Lisp_Object macfont_family_cache;
935 macfont_invalidate_family_cache (void)
937 if (HASH_TABLE_P (macfont_family_cache))
939 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
940 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
942 for (i = 0; i < size; ++i)
943 if (!NILP (HASH_HASH (h, i)))
945 Lisp_Object value = HASH_VALUE (h, i);
947 if (mint_ptrp (value))
948 CFRelease (xmint_pointer (value));
950 macfont_family_cache = Qnil;
955 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
957 if (HASH_TABLE_P (macfont_family_cache))
959 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
960 ptrdiff_t i = hash_lookup (h, symbol, NULL);
964 Lisp_Object value = HASH_VALUE (h, i);
966 *string = mint_ptrp (value) ? xmint_pointer (value) : NULL;
976 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
978 struct Lisp_Hash_Table *h;
983 if (!HASH_TABLE_P (macfont_family_cache))
984 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
986 h = XHASH_TABLE (macfont_family_cache);
987 i = hash_lookup (h, symbol, &hash);
988 value = string ? make_mint_ptr ((void *) CFRetain (string)) : Qnil;
991 Lisp_Object old_value = HASH_VALUE (h, i);
993 if (mint_ptrp (old_value))
994 CFRelease (xmint_pointer (old_value));
995 set_hash_value_slot (h, i, value);
998 hash_put (h, symbol, value, hash);
1001 /* Cache of all the available font family names except "LastResort"
1002 and those start with ".". NULL means the cache has been invalidated.
1003 Otherwise, the value is CFArray of CFStrings and the elements are
1004 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1005 Mac OS X 10.6 and later). */
1007 static CFArrayRef macfont_available_families_cache = NULL;
1010 macfont_invalidate_available_families_cache (void)
1012 if (macfont_available_families_cache)
1014 CFRelease (macfont_available_families_cache);
1015 macfont_available_families_cache = NULL;
1020 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1022 CFStringRef name, const void *object,
1023 CFDictionaryRef userInfo)
1025 macfont_invalidate_family_cache ();
1026 macfont_invalidate_available_families_cache ();
1030 macfont_init_font_change_handler (void)
1032 static bool initialized = false;
1038 CFNotificationCenterAddObserver
1039 (CFNotificationCenterGetLocalCenter (), NULL,
1040 macfont_handle_font_change_notification,
1041 kCTFontManagerRegisteredFontsChangedNotification,
1042 NULL, CFNotificationSuspensionBehaviorCoalesce);
1046 macfont_copy_available_families_cache (void)
1048 macfont_init_font_change_handler ();
1050 if (macfont_available_families_cache == NULL)
1051 macfont_available_families_cache = mac_font_create_available_families ();
1053 return (macfont_available_families_cache
1054 ? CFRetain (macfont_available_families_cache) : NULL);
1058 macfont_create_family_with_symbol (Lisp_Object symbol)
1060 CFStringRef result = NULL, family_name;
1061 CFDictionaryRef attributes = NULL;
1062 CTFontDescriptorRef pat_desc = NULL;
1064 if (macfont_get_family_cache_if_present (symbol, &result))
1065 return result ? CFRetain (result) : NULL;
1067 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1071 CFDictionaryCreate (NULL,
1072 (const void **) &kCTFontFamilyNameAttribute,
1073 (const void **) &family_name, 1,
1074 &kCFTypeDictionaryKeyCallBacks,
1075 &kCFTypeDictionaryValueCallBacks);
1076 CFRelease (family_name);
1080 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1081 CFRelease (attributes);
1085 CTFontDescriptorRef desc =
1086 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1091 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1094 macfont_set_family_cache (symbol, result);
1095 CFRelease (pat_desc);
1101 #define WIDTH_FRAC_BITS (4)
1102 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1104 struct macfont_metrics
1106 unsigned char lbearing_low, rbearing_low;
1107 signed lbearing_high : 4, rbearing_high : 4;
1108 unsigned char ascent_low, descent_low;
1109 signed ascent_high : 4, descent_high : 4;
1111 /* These two members are used for fixed-point representation of
1112 glyph width. The `width_int' member is an integer that is
1113 closest to the width. The `width_frac' member is the fractional
1114 adjustment representing a value in [-.5, .5], multiplied by
1115 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1116 the advance delta for centering instead of the glyph width. */
1117 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1120 #define METRICS_VALUE(metrics, member) \
1121 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1122 #define METRICS_SET_VALUE(metrics, member, value) \
1123 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1124 (metrics)->member##_high = tmp >> 8;} while (0)
1128 METRICS_INVALID = -1, /* metrics entry is invalid */
1129 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1132 #define METRICS_STATUS(metrics) \
1133 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1134 #define METRICS_SET_STATUS(metrics, status) \
1135 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1136 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1138 #define METRICS_NCOLS_PER_ROW (128)
1139 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1140 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1143 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1144 struct font_metrics *metrics, CGFloat *advance_delta,
1145 int force_integral_p)
1147 struct macfont_info *macfont_info = (struct macfont_info *) font;
1148 CTFontRef macfont = macfont_info->macfont;
1150 struct macfont_metrics *cache;
1153 row = glyph / METRICS_NCOLS_PER_ROW;
1154 col = glyph % METRICS_NCOLS_PER_ROW;
1155 if (row >= macfont_info->metrics_nrows)
1157 macfont_info->metrics =
1158 xrealloc (macfont_info->metrics,
1159 sizeof (struct macfont_metrics *) * (row + 1));
1160 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1161 (sizeof (struct macfont_metrics *)
1162 * (row + 1 - macfont_info->metrics_nrows)));
1163 macfont_info->metrics_nrows = row + 1;
1165 if (macfont_info->metrics[row] == NULL)
1167 struct macfont_metrics *new;
1170 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1171 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1172 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1173 macfont_info->metrics[row] = new;
1175 cache = macfont_info->metrics[row] + col;
1177 if (METRICS_STATUS (cache) == METRICS_INVALID)
1181 if (macfont_info->screen_font)
1182 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1184 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1186 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1187 advance delta value. */
1188 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1189 fwidth = (font->pixel_size - fwidth) / 2;
1190 cache->width_int = lround (fwidth);
1191 cache->width_frac = lround ((fwidth - cache->width_int)
1192 * WIDTH_FRAC_SCALE);
1193 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1195 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1196 width = font->pixel_size;
1198 width = cache->width_int;
1202 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1204 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1206 if (macfont_info->synthetic_italic_p)
1208 /* We assume the members a, b, c, and d in
1209 synthetic_italic_atfm are non-negative. */
1211 CGPointApplyAffineTransform (bounds.origin,
1212 synthetic_italic_atfm);
1214 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1216 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1218 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1220 bounds = CGRectInset (bounds, d, d);
1222 switch (macfont_info->spacing)
1224 case MACFONT_SPACING_PROPORTIONAL:
1225 bounds.origin.x += - (cache->width_frac
1226 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1228 case MACFONT_SPACING_MONO:
1230 case MACFONT_SPACING_SYNTHETIC_MONO:
1231 bounds.origin.x += (cache->width_int
1232 + (cache->width_frac
1233 / (CGFloat) WIDTH_FRAC_SCALE));
1236 if (bounds.size.width > 0)
1238 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1239 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1240 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1242 bounds = CGRectIntegral (bounds);
1243 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1244 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1245 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1246 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1248 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1249 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1250 metrics->width = width;
1251 metrics->ascent = METRICS_VALUE (cache, ascent);
1252 metrics->descent = METRICS_VALUE (cache, descent);
1257 switch (macfont_info->spacing)
1259 case MACFONT_SPACING_PROPORTIONAL:
1260 *advance_delta = (force_integral_p ? 0
1261 : - (cache->width_frac
1262 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1264 case MACFONT_SPACING_MONO:
1267 case MACFONT_SPACING_SYNTHETIC_MONO:
1268 *advance_delta = (force_integral_p ? cache->width_int
1270 + (cache->width_frac
1271 / (CGFloat) WIDTH_FRAC_SCALE)));
1279 static CFMutableDictionaryRef macfont_cache_dictionary;
1281 /* Threshold used in row_nkeys_or_perm. This must be less than or
1282 equal to the number of rows that are invalid as BMP (i.e., from
1283 U+D800 to U+DFFF). */
1284 #define ROW_PERM_OFFSET (8)
1286 /* The number of glyphs that can be stored in a value for a single
1287 entry of CFDictionary. */
1288 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1290 struct macfont_cache
1292 int reference_count;
1293 CFCharacterSetRef cf_charset;
1295 /* The cached glyph for a BMP character c is stored in
1296 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1297 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1298 unsigned char row_nkeys_or_perm[256];
1301 /* Number of rows for which the BMP cache is allocated so far.
1302 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1305 /* The cached glyph for a character c is stored as the (c %
1306 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1307 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1308 not stored here if row_nkeys_or_perm[c / 256] >=
1310 CFMutableDictionaryRef dictionary;
1314 /* UVS (Unicode Variation Sequence) subtable data, which is of
1315 type CFDataRef if available. NULL means it is not initialized
1316 yet. kCFNull means the subtable is not found and there is no
1317 suitable fallback table for this font. */
1320 /* Character collection specifying the destination of the mapping
1321 provided by `table' above. If `table' is obtained from the UVS
1322 subtable in the font cmap table, then the value of this member
1323 should be NSIdentityMappingCharacterCollection. */
1324 NSCharacterCollection collection;
1328 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1329 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1330 static void macfont_release_cache (struct macfont_cache *);
1331 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1332 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1333 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1334 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1335 NSCharacterCollection, CGFontIndex);
1336 static CFDataRef macfont_get_uvs_table (struct font *, NSCharacterCollection *);
1338 static struct macfont_cache *
1339 macfont_lookup_cache (CFStringRef key)
1341 struct macfont_cache *cache;
1343 if (macfont_cache_dictionary == NULL)
1345 macfont_cache_dictionary =
1346 CFDictionaryCreateMutable (NULL, 0,
1347 &kCFTypeDictionaryKeyCallBacks, NULL);
1351 cache = ((struct macfont_cache *)
1352 CFDictionaryGetValue (macfont_cache_dictionary, key));
1356 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1360 cache = xzalloc (sizeof (struct macfont_cache));
1361 /* Treat the LastResort font as if it contained glyphs for
1362 all characters. This may look too rough, but neither
1363 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1364 for this font is correct for non-BMP characters on Mac OS
1366 if (CFEqual (key, CFSTR ("LastResort")))
1368 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1371 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1373 if (cache->cf_charset == NULL)
1374 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1375 CFDictionaryAddValue (macfont_cache_dictionary, key,
1376 (const void *) cache);
1377 CFRelease (macfont);
1384 static struct macfont_cache *
1385 macfont_retain_cache (struct macfont_cache *cache)
1387 cache->reference_count++;
1393 macfont_release_cache (struct macfont_cache *cache)
1395 if (--cache->reference_count == 0)
1399 for (i = 0; i < cache->glyph.nrows; i++)
1400 xfree (cache->glyph.matrix[i]);
1401 xfree (cache->glyph.matrix);
1402 if (cache->glyph.dictionary)
1403 CFRelease (cache->glyph.dictionary);
1404 memset (&cache->glyph, 0, sizeof (cache->glyph));
1405 if (cache->uvs.table)
1406 CFRelease (cache->uvs.table);
1407 memset (&cache->uvs, 0, sizeof (cache->uvs));
1411 static CFCharacterSetRef
1412 macfont_get_cf_charset (struct font *font)
1414 struct macfont_info *macfont_info = (struct macfont_info *) font;
1416 return macfont_info->cache->cf_charset;
1419 static CFCharacterSetRef
1420 macfont_get_cf_charset_for_name (CFStringRef name)
1422 struct macfont_cache *cache = macfont_lookup_cache (name);
1424 return cache->cf_charset;
1428 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1430 struct macfont_info *macfont_info = (struct macfont_info *) font;
1431 CTFontRef macfont = macfont_info->macfont;
1432 struct macfont_cache *cache = macfont_info->cache;
1434 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1437 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1439 if (nkeys_or_perm < ROW_PERM_OFFSET)
1441 UniChar unichars[256], ch;
1449 CFMutableDictionaryRef dictionary;
1450 uintptr_t key, value;
1454 if (cache->glyph.dictionary == NULL)
1455 cache->glyph.dictionary =
1456 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1457 dictionary = cache->glyph.dictionary;
1458 key = c / NGLYPHS_IN_VALUE;
1459 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1460 value = ((uintptr_t)
1461 CFDictionaryGetValue (dictionary, (const void *) key));
1462 glyph = (value >> nshifts);
1466 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1469 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1471 glyph = kCGFontIndexInvalid;
1474 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1475 value |= ((uintptr_t) glyph << nshifts);
1476 CFDictionarySetValue (dictionary, (const void *) key,
1477 (const void *) value);
1482 nkeys = nkeys_or_perm;
1483 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1484 if (CFDictionaryContainsKey (dictionary,
1485 (const void *) key))
1487 CFDictionaryRemoveValue (dictionary,
1488 (const void *) key);
1495 for (i = 0; i < 256; i++)
1498 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1499 unichars[len++] = ch;
1502 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1505 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1508 int next = unichars[len - 1] % 256;
1511 glyphs[i] = kCGFontIndexInvalid;
1514 glyphs[i] = glyphs[len];
1521 glyphs[i] = kCGFontIndexInvalid;
1523 nrows = cache->glyph.nrows;
1524 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1525 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1527 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1528 sizeof (CGGlyph *) * nrows);
1529 cache->glyph.matrix[nrows - 1] = glyphs;
1530 cache->glyph.nrows = nrows;
1533 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1537 uintptr_t key, value;
1541 if (cache->glyph.dictionary == NULL)
1542 cache->glyph.dictionary =
1543 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1544 key = c / NGLYPHS_IN_VALUE;
1545 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1546 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1547 (const void *) key);
1548 glyph = (value >> nshifts);
1551 UniChar unichars[2];
1553 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1555 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1558 glyph = kCGFontIndexInvalid;
1560 value |= ((uintptr_t) glyph << nshifts);
1561 CFDictionarySetValue (cache->glyph.dictionary,
1562 (const void *) key, (const void *) value);
1570 macfont_get_glyph_for_cid (struct font *font, NSCharacterCollection collection,
1573 struct macfont_info *macfont_info = (struct macfont_info *) font;
1574 CTFontRef macfont = macfont_info->macfont;
1577 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1581 macfont_get_uvs_table (struct font *font, NSCharacterCollection *collection)
1583 struct macfont_info *macfont_info = (struct macfont_info *) font;
1584 CTFontRef macfont = macfont_info->macfont;
1585 struct macfont_cache *cache = macfont_info->cache;
1586 CFDataRef result = NULL;
1588 if (cache->uvs.table == NULL)
1590 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1591 NSCharacterCollection uvs_collection =
1592 NSIdentityMappingCharacterCollection;
1594 if (uvs_table == NULL
1595 && mac_font_get_glyph_for_cid (macfont,
1596 NSAdobeJapan1CharacterCollection,
1597 6480) != kCGFontIndexInvalid)
1599 /* If the glyph for U+4E55 is accessible via its CID 6480,
1600 then we use the Adobe-Japan1 UVS table, which maps a
1601 variation sequence to a CID, as a fallback. */
1602 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1604 if (mac_uvs_table_adobe_japan1 == NULL)
1605 mac_uvs_table_adobe_japan1 =
1606 CFDataCreateWithBytesNoCopy (NULL,
1607 mac_uvs_table_adobe_japan1_bytes,
1608 sizeof (mac_uvs_table_adobe_japan1_bytes),
1610 if (mac_uvs_table_adobe_japan1)
1612 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1613 uvs_collection = NSAdobeJapan1CharacterCollection;
1616 if (uvs_table == NULL)
1617 cache->uvs.table = kCFNull;
1619 cache->uvs.table = uvs_table;
1620 cache->uvs.collection = uvs_collection;
1623 if (cache->uvs.table != kCFNull)
1625 result = cache->uvs.table;
1626 *collection = cache->uvs.collection;
1632 static Lisp_Object macfont_get_cache (struct frame *);
1633 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1634 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1635 static Lisp_Object macfont_list_family (struct frame *);
1636 static void macfont_free_entity (Lisp_Object);
1637 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1638 static void macfont_close (struct font *);
1639 static int macfont_has_char (Lisp_Object, int);
1640 static unsigned macfont_encode_char (struct font *, int);
1641 static void macfont_text_extents (struct font *, unsigned int *, int,
1642 struct font_metrics *);
1643 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1644 static Lisp_Object macfont_shape (Lisp_Object);
1645 static int macfont_variation_glyphs (struct font *, int c,
1646 unsigned variations[256]);
1647 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1649 static struct font_driver const macfont_driver =
1651 .type = LISPSYM_INITIALLY (Qmac_ct),
1652 .get_cache = macfont_get_cache,
1653 .list = macfont_list,
1654 .match = macfont_match,
1655 .list_family = macfont_list_family,
1656 .free_entity = macfont_free_entity,
1657 .open = macfont_open,
1658 .close = macfont_close,
1659 .has_char = macfont_has_char,
1660 .encode_char = macfont_encode_char,
1661 .text_extents = macfont_text_extents,
1662 .draw = macfont_draw,
1663 .shape = macfont_shape,
1664 .get_variation_glyphs = macfont_variation_glyphs,
1665 .filter_properties = macfont_filter_properties,
1669 macfont_get_cache (struct frame * f)
1671 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1673 return (dpyinfo->name_list_element);
1677 macfont_get_charset (Lisp_Object registry)
1679 char *str = SSDATA (SYMBOL_NAME (registry));
1680 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1684 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1688 else if (str[i] == '*')
1695 regexp = make_unibyte_string (re, j);
1696 for (i = 0; cf_charset_table[i].name; i++)
1697 if (fast_c_string_match_ignore_case
1698 (regexp, cf_charset_table[i].name,
1699 strlen (cf_charset_table[i].name)) >= 0)
1701 if (! cf_charset_table[i].name)
1703 if (! cf_charset_table[i].cf_charset)
1705 int *uniquifier = cf_charset_table[i].uniquifier;
1706 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1709 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1713 for (j = 0; uniquifier[j]; j++)
1715 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1717 CFCharacterSetAddCharactersInRange (charset,
1718 CFRangeMake (uniquifier[j], 1));
1721 string = CFStringCreateWithCharacters (NULL, unichars, count);
1724 CFRelease (charset);
1727 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1729 CFRelease (charset);
1730 /* CFCharacterSetCreateWithCharactersInString does not handle
1731 surrogate pairs properly as of Mac OS X 10.5. */
1732 cf_charset_table[i].cf_charset_string = string;
1740 unsigned int script_tag, langsys_tag;
1742 unsigned int *features[2];
1745 #define OTF_SYM_TAG(SYM, TAG) \
1747 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1748 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1751 #define OTF_TAG_STR(TAG, P) \
1753 (P)[0] = (char) (TAG >> 24); \
1754 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1755 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1756 (P)[3] = (char) (TAG & 0xFF); \
1760 static struct OpenTypeSpec *
1761 macfont_get_open_type_spec (Lisp_Object otf_spec)
1763 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1770 spec->script = XCAR (otf_spec);
1771 if (! NILP (spec->script))
1773 OTF_SYM_TAG (spec->script, spec->script_tag);
1774 val = assq_no_quit (spec->script, Votf_script_alist);
1775 if (CONSP (val) && SYMBOLP (XCDR (val)))
1776 spec->script = XCDR (val);
1778 spec->script = Qnil;
1781 spec->script_tag = 0x44464C54; /* "DFLT" */
1782 otf_spec = XCDR (otf_spec);
1783 spec->langsys_tag = 0;
1784 if (! NILP (otf_spec))
1786 val = XCAR (otf_spec);
1788 OTF_SYM_TAG (val, spec->langsys_tag);
1789 otf_spec = XCDR (otf_spec);
1791 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1792 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1796 val = XCAR (otf_spec);
1799 len = Flength (val);
1801 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1803 : malloc (XINT (len) * sizeof *spec->features[i]));
1804 if (! spec->features[i])
1806 if (i > 0 && spec->features[0])
1807 free (spec->features[0]);
1811 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1813 if (NILP (XCAR (val)))
1819 OTF_SYM_TAG (XCAR (val), tag);
1820 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1823 spec->nfeatures[i] = j;
1828 static CFMutableDictionaryRef
1829 macfont_create_attributes_with_spec (Lisp_Object spec)
1831 Lisp_Object tmp, extra;
1832 CFMutableArrayRef langarray = NULL;
1833 CFCharacterSetRef charset = NULL;
1834 CFStringRef charset_string = NULL;
1835 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1836 Lisp_Object script = Qnil;
1837 Lisp_Object registry;
1838 int cf_charset_idx, i;
1839 struct OpenTypeSpec *otspec = NULL;
1841 enum font_property_index index;
1844 } numeric_traits[] =
1845 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1846 {{-0.4, 50}, /* light */
1847 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1848 {0, 100}, /* normal */
1849 {0.24, 140}, /* (semi-bold + normal) / 2 */
1850 {0.4, 200}, /* bold */
1851 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1852 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1853 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1854 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1855 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1857 registry = AREF (spec, FONT_REGISTRY_INDEX);
1859 || EQ (registry, Qascii_0)
1860 || EQ (registry, Qiso10646_1)
1861 || EQ (registry, Qunicode_bmp))
1862 cf_charset_idx = -1;
1867 cf_charset_idx = macfont_get_charset (registry);
1868 if (cf_charset_idx < 0)
1870 charset = cf_charset_table[cf_charset_idx].cf_charset;
1871 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1872 lang = cf_charset_table[cf_charset_idx].lang;
1875 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1878 CFArrayAppendValue (langarray, lang);
1882 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1883 CONSP (extra); extra = XCDR (extra))
1885 Lisp_Object key, val;
1888 key = XCAR (tmp), val = XCDR (tmp);
1889 if (EQ (key, QClang))
1892 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1897 for (; CONSP (val); val = XCDR (val))
1898 if (SYMBOLP (XCAR (val)))
1901 cfstring_create_with_string_noencode (SYMBOL_NAME
1906 CFArrayAppendValue (langarray, lang);
1910 else if (EQ (key, QCotf))
1912 otspec = macfont_get_open_type_spec (val);
1915 script = otspec->script;
1917 else if (EQ (key, QCscript))
1921 if (! NILP (script) && ! charset)
1923 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1925 if (CONSP (chars) && CONSP (CDR (chars)))
1927 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1928 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1930 if (! string || !cs)
1938 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1939 if (CHARACTERP (XCAR (chars)))
1941 UniChar unichars[2];
1943 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1945 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1947 CFStringAppendCharacters (string, unichars, count);
1948 CFCharacterSetAddCharactersInRange (cs, range);
1951 /* CFCharacterSetCreateWithCharactersInString does not
1952 handle surrogate pairs properly as of Mac OS X 10.5. */
1953 charset_string = string;
1957 attributes = CFDictionaryCreateMutable (NULL, 0,
1958 &kCFTypeDictionaryKeyCallBacks,
1959 &kCFTypeDictionaryValueCallBacks);
1963 tmp = AREF (spec, FONT_FAMILY_INDEX);
1964 if (SYMBOLP (tmp) && ! NILP (tmp))
1966 CFStringRef family = macfont_create_family_with_symbol (tmp);
1970 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1975 traits = CFDictionaryCreateMutable (NULL, 4,
1976 &kCFTypeDictionaryKeyCallBacks,
1977 &kCFTypeDictionaryValueCallBacks);
1981 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1983 tmp = AREF (spec, numeric_traits[i].index);
1986 CGPoint *point = numeric_traits[i].points;
1987 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1990 while (point->y < floatval)
1992 if (point == numeric_traits[i].points)
1994 else if (point->y == CGFLOAT_MAX)
1996 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1997 * ((point->x - (point - 1)->x)
1998 / (point->y - (point - 1)->y)));
2001 else if (floatval < -1.0)
2003 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2006 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2010 if (CFDictionaryGetCount (traits))
2011 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2014 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2017 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2020 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2027 CFRelease (attributes);
2032 if (langarray) CFRelease (langarray);
2033 if (charset && cf_charset_idx < 0) CFRelease (charset);
2034 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2035 if (traits) CFRelease (traits);
2038 if (otspec->nfeatures[0] > 0)
2039 free (otspec->features[0]);
2040 if (otspec->nfeatures[1] > 0)
2041 free (otspec->features[1]);
2049 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2050 CFCharacterSetRef charset,
2052 CFArrayRef languages)
2054 Boolean result = true;
2056 if (charset || VECTORP (chars))
2058 CFCharacterSetRef desc_charset =
2059 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2061 if (desc_charset == NULL)
2066 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2067 else /* VECTORP (chars) */
2071 for (j = 0; j < ASIZE (chars); j++)
2072 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2073 && CFCharacterSetIsLongCharacterMember (desc_charset,
2074 XFASTINT (AREF (chars, j))))
2076 if (j == ASIZE (chars))
2079 CFRelease (desc_charset);
2082 if (result && languages)
2083 result = mac_font_descriptor_supports_languages (desc, languages);
2089 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2090 CTFontSymbolicTraits sym_traits2)
2092 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2095 /* We prefer synthetic bold of italic to synthetic italic of bold
2096 when both bold and italic are available but bold-italic is not
2098 if (diff & kCTFontTraitBold)
2099 distance |= (1 << 0);
2100 if (diff & kCTFontTraitItalic)
2101 distance |= (1 << 1);
2102 if (diff & kCTFontTraitMonoSpace)
2103 distance |= (1 << 2);
2109 macfont_closest_traits_index_p (CFArrayRef traits_array,
2110 CTFontSymbolicTraits target,
2113 CFIndex i, count = CFArrayGetCount (traits_array);
2114 CTFontSymbolicTraits traits;
2117 traits = ((CTFontSymbolicTraits) (uintptr_t)
2118 CFArrayGetValueAtIndex (traits_array, index));
2119 my_distance = macfont_traits_distance (target, traits);
2121 for (i = 0; i < count; i++)
2124 traits = ((CTFontSymbolicTraits) (uintptr_t)
2125 CFArrayGetValueAtIndex (traits_array, i));
2126 if (macfont_traits_distance (target, traits) < my_distance)
2134 macfont_list (struct frame *f, Lisp_Object spec)
2136 Lisp_Object val = Qnil, family, extra;
2138 CFStringRef family_name = NULL;
2139 CFMutableDictionaryRef attributes = NULL, traits;
2140 Lisp_Object chars = Qnil;
2142 CTFontSymbolicTraits synth_sym_traits = 0;
2143 CFArrayRef families;
2144 CFIndex families_count;
2145 CFCharacterSetRef charset = NULL;
2146 CFArrayRef languages = NULL;
2150 family = AREF (spec, FONT_FAMILY_INDEX);
2151 if (! NILP (family))
2153 family_name = macfont_create_family_with_symbol (family);
2154 if (family_name == NULL)
2158 attributes = macfont_create_attributes_with_spec (spec);
2162 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2164 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2165 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2167 traits = ((CFMutableDictionaryRef)
2168 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2170 n = FONT_SLANT_NUMERIC (spec);
2171 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2173 synth_sym_traits |= kCTFontTraitItalic;
2175 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2178 n = FONT_WEIGHT_NUMERIC (spec);
2179 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2181 synth_sym_traits |= kCTFontTraitBold;
2183 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2187 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2189 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2191 if (CFStringHasPrefix (language, CFSTR ("ja"))
2192 || CFStringHasPrefix (language, CFSTR ("ko"))
2193 || CFStringHasPrefix (language, CFSTR ("zh")))
2194 synth_sym_traits |= kCTFontTraitMonoSpace;
2197 /* Create array of families. */
2199 families = CFArrayCreate (NULL, (const void **) &family_name,
2200 1, &kCFTypeArrayCallBacks);
2203 CFStringRef pref_family;
2204 CFIndex families_count, pref_family_index = -1;
2206 families = macfont_copy_available_families_cache ();
2207 if (families == NULL)
2210 families_count = CFArrayGetCount (families);
2212 /* Move preferred family to the front if exists. */
2214 mac_font_create_preferred_family_for_attributes (attributes);
2218 CFArrayGetFirstIndexOfValue (families,
2219 CFRangeMake (0, families_count),
2221 CFRelease (pref_family);
2223 if (pref_family_index > 0)
2225 CFMutableArrayRef mutable_families =
2226 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2228 if (mutable_families)
2230 CFArrayAppendValue (mutable_families,
2231 CFArrayGetValueAtIndex (families,
2232 pref_family_index));
2233 CFArrayAppendArray (mutable_families, families,
2234 CFRangeMake (0, pref_family_index));
2235 if (pref_family_index + 1 < families_count)
2236 CFArrayAppendArray (mutable_families, families,
2237 CFRangeMake (pref_family_index + 1,
2239 - (pref_family_index + 1)));
2240 CFRelease (families);
2241 families = mutable_families;
2246 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2250 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2254 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2257 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2258 if (CONSP (val) && VECTORP (XCDR (val)))
2266 CFRetain (languages);
2267 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2271 extra = AREF (spec, FONT_EXTRA_INDEX);
2272 families_count = CFArrayGetCount (families);
2273 for (i = 0; i < families_count; i++)
2275 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2276 CTFontDescriptorRef pat_desc;
2278 CFIndex descs_count;
2279 CFMutableArrayRef filtered_descs, traits_array;
2283 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2285 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2289 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2290 10.7 returns NULL if pat_desc represents the LastResort font.
2291 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2292 trailing "s") for such a font. */
2293 if (!CFEqual (family_name, CFSTR ("LastResort")))
2294 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2297 CTFontDescriptorRef lr_desc =
2298 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2301 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2302 &kCFTypeArrayCallBacks);
2303 CFRelease (lr_desc);
2308 CFRelease (pat_desc);
2312 descs_count = CFArrayGetCount (descs);
2313 if (descs_count == 0
2314 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2323 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2324 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2325 for (j = 0; j < descs_count; j++)
2327 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2328 CFDictionaryRef dict;
2330 CTFontSymbolicTraits sym_traits;
2332 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2336 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2339 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2343 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2344 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2345 != (spacing >= FONT_SPACING_MONO)))
2348 /* Don't use a color bitmap font until it is supported on
2350 if (sym_traits & kCTFontTraitColorGlyphs)
2354 && !macfont_supports_charset_and_languages_p (desc, charset,
2358 CFArrayAppendValue (filtered_descs, desc);
2359 CFArrayAppendValue (traits_array,
2360 (const void *) (uintptr_t) sym_traits);
2364 descs = filtered_descs;
2365 descs_count = CFArrayGetCount (descs);
2367 for (j = 0; j < descs_count; j++)
2369 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2370 CTFontSymbolicTraits sym_traits =
2371 ((CTFontSymbolicTraits) (uintptr_t)
2372 CFArrayGetValueAtIndex (traits_array, j));
2373 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2375 mask_min = ((synth_sym_traits ^ sym_traits)
2376 & (kCTFontTraitItalic | kCTFontTraitBold));
2377 if (FONT_SLANT_NUMERIC (spec) < 0)
2378 mask_min &= ~kCTFontTraitItalic;
2379 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2380 mask_min &= ~kCTFontTraitBold;
2382 mask_max = (synth_sym_traits & ~sym_traits);
2383 /* Synthetic bold does not work for bitmap-only fonts on Mac
2385 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2387 CFNumberRef format =
2388 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2392 uint32_t format_val;
2394 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2396 && format_val == kCTFontFormatBitmap)
2397 mask_max &= ~kCTFontTraitBold;
2401 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2403 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2404 mmask <= (mask_max & kCTFontTraitMonoSpace);
2405 mmask += kCTFontTraitMonoSpace)
2406 for (bmask = (mask_min & kCTFontTraitBold);
2407 bmask <= (mask_max & kCTFontTraitBold);
2408 bmask += kCTFontTraitBold)
2409 for (imask = (mask_min & kCTFontTraitItalic);
2410 imask <= (mask_max & kCTFontTraitItalic);
2411 imask += kCTFontTraitItalic)
2413 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2416 || macfont_closest_traits_index_p (traits_array,
2417 (sym_traits | synth),
2420 entity = macfont_descriptor_entity (desc, extra, synth);
2421 if (! NILP (entity))
2422 val = Fcons (entity, val);
2427 CFRelease (traits_array);
2431 CFRelease (families);
2432 val = Fnreverse (val);
2438 FONT_ADD_LOG ("macfont-list", spec, val);
2439 if (charset) CFRelease (charset);
2440 if (languages) CFRelease (languages);
2441 if (attributes) CFRelease (attributes);
2442 if (family_name) CFRelease (family_name);
2450 macfont_match (struct frame * frame, Lisp_Object spec)
2452 Lisp_Object entity = Qnil;
2453 CFMutableDictionaryRef attributes;
2454 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2458 attributes = macfont_create_attributes_with_spec (spec);
2461 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2462 CFRelease (attributes);
2466 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2467 CFRelease (pat_desc);
2471 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2477 FONT_ADD_LOG ("macfont-match", spec, entity);
2482 macfont_list_family (struct frame *frame)
2484 Lisp_Object list = Qnil;
2485 CFArrayRef families;
2489 families = macfont_copy_available_families_cache ();
2492 CFIndex i, count = CFArrayGetCount (families);
2494 for (i = 0; i < count; i++)
2495 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2496 CFRelease (families);
2505 macfont_free_entity (Lisp_Object entity)
2507 Lisp_Object val = assq_no_quit (QCfont_entity,
2508 AREF (entity, FONT_EXTRA_INDEX));
2509 CFStringRef name = xmint_pointer (XCAR (XCDR (val)));
2517 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2519 Lisp_Object val, font_object;
2520 CFStringRef font_name;
2521 struct macfont_info *macfont_info = NULL;
2525 CTFontSymbolicTraits sym_traits;
2528 CGFloat ascent, descent, leading;
2530 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2532 || ! CONSP (XCDR (val)))
2534 font_name = xmint_pointer (XCAR (XCDR (val)));
2535 sym_traits = XINT (XCDR (XCDR (val)));
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 = xmint_pointer (XCAR (val));
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);