1 /* Font driver on macOS Core text.
2 Copyright (C) 2009-2017 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or (at
9 your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #include <libkern/OSByteOrder.h>
41 static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
42 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
43 static CFArrayRef mac_font_create_available_families (void);
44 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
45 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
47 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
49 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
50 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
51 struct mac_glyph_layout *, CFIndex);
52 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
53 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
55 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
59 struct macfont_metrics;
61 /* The actual structure for Mac font that can be cast to struct font. */
68 ScreenFontRef screen_font;
69 struct macfont_cache *cache;
70 struct macfont_metrics **metrics;
72 bool_bf synthetic_italic_p : 1;
73 bool_bf synthetic_bold_p : 1;
75 unsigned antialias : 2;
76 bool_bf color_bitmap_p : 1;
79 /* Values for the `spacing' member in `struct macfont_info'. */
83 MACFONT_SPACING_PROPORTIONAL,
85 MACFONT_SPACING_SYNTHETIC_MONO,
88 /* Values for the `antialias' member in `struct macfont_info'. */
92 MACFONT_ANTIALIAS_DEFAULT,
93 MACFONT_ANTIALIAS_OFF,
97 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
98 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
99 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
101 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
102 static const CGFloat synthetic_bold_factor = 0.024;
104 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
105 CTFontSymbolicTraits *);
106 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
108 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
109 CTFontSymbolicTraits);
110 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
111 static int macfont_glyph_extents (struct font *, CGGlyph,
112 struct font_metrics *, CGFloat *, int);
113 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
114 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
118 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
120 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
121 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
123 CGGlyph [], CFIndex);
125 /* From CFData to a lisp string. Always returns a unibyte string. */
128 cfdata_to_lisp (CFDataRef data)
130 CFIndex len = CFDataGetLength (data);
131 Lisp_Object result = make_uninit_string (len);
133 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
140 /* From CFString to a lisp string. Returns a unibyte string
141 containing a UTF-8 byte sequence. */
144 cfstring_to_lisp_nodecode (CFStringRef string)
146 Lisp_Object result = Qnil;
148 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
152 CFIndex i, length = CFStringGetLength (string);
154 for (i = 0; i < length; i++)
155 if (CFStringGetCharacterAtIndex (string, i) == 0)
159 return make_unibyte_string (s, strlen (s));
162 data = CFStringCreateExternalRepresentation (NULL, string,
163 kCFStringEncodingUTF8, '?');
166 result = cfdata_to_lisp (data);
173 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
174 cfstring_create_with_utf8_cstring, this function preserves NUL
178 cfstring_create_with_string_noencode (Lisp_Object s)
180 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
181 kCFStringEncodingUTF8, false);
184 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
185 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
186 kCFStringEncodingMacRoman, false);
192 mac_font_get_weight (CTFontRef font)
194 NSFont *nsFont = (NSFont *) font;
196 return [[NSFontManager sharedFontManager] weightOfFont:nsFont];
200 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
202 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
204 return advancement.width;
207 #if !USE_CT_GLYPH_INFO
209 mac_font_get_glyph_for_cid (CTFontRef font, NSCharacterCollection collection,
212 CGGlyph result = kCGFontIndexInvalid;
213 NSFont *nsFont = (NSFont *) font;
214 unichar characters[] = {0xfffd};
216 [NSString stringWithCharacters:characters
217 length:ARRAYELTS (characters)];
218 NSGlyphInfo *glyphInfo =
219 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
220 collection:collection
222 NSDictionary *attributes =
223 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
224 glyphInfo,NSGlyphInfoAttributeName,nil];
225 NSTextStorage *textStorage =
226 [[NSTextStorage alloc] initWithString:string
227 attributes:attributes];
228 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
229 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
230 NSFont *fontInTextStorage;
232 [layoutManager addTextContainer:textContainer];
233 [textContainer release];
234 [textStorage addLayoutManager:layoutManager];
235 [layoutManager release];
238 (void) [layoutManager glyphRangeForTextContainer:textContainer];
240 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
241 effectiveRange:NULL];
242 if (fontInTextStorage == nsFont
243 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
245 NSGlyph glyph = [layoutManager glyphAtIndex:0];
247 if (glyph < [nsFont numberOfGlyphs])
251 [textStorage release];
258 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
260 NSFont *result, *font;
262 font = [NSFont fontWithName:((NSString *) name) size:size];
263 result = [font screenFont];
265 return (ScreenFontRef)[result retain];
270 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
271 CGFloat *descent, CGFloat *leading)
273 NSFont *nsFont = [(NSFont *)font printerFont];
274 NSTextStorage *textStorage;
275 NSLayoutManager *layoutManager;
276 NSTextContainer *textContainer;
278 NSPoint spaceLocation;
281 textStorage = [[NSTextStorage alloc] initWithString:@" "];
282 layoutManager = [[NSLayoutManager alloc] init];
283 textContainer = [[NSTextContainer alloc] init];
285 [textStorage setFont:nsFont];
286 [textContainer setLineFragmentPadding:0];
288 [layoutManager addTextContainer:textContainer];
289 [textContainer release];
290 [textStorage addLayoutManager:layoutManager];
291 [layoutManager release];
293 if (!(textStorage && layoutManager && textContainer))
295 [textStorage release];
300 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
301 effectiveRange:NULL];
302 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
303 [textStorage release];
305 *ascent = spaceLocation.y;
306 *descent = NSHeight (usedRect) - spaceLocation.y;
308 descender = [nsFont descender];
309 if (- descender < *descent)
311 *leading = *descent + descender;
312 *descent = - descender;
319 mac_font_shape_1 (NSFont *font, NSString *string,
320 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
324 NSTextStorage *textStorage;
325 NSLayoutManager *layoutManager;
326 NSTextContainer *textContainer;
327 NSUInteger stringLength;
328 NSPoint spaceLocation;
329 NSUInteger used, numberOfGlyphs;
331 textStorage = [[NSTextStorage alloc] initWithString:string];
332 layoutManager = [[NSLayoutManager alloc] init];
333 textContainer = [[NSTextContainer alloc] init];
335 /* Append a trailing space to measure baseline position. */
336 [textStorage appendAttributedString:([[[NSAttributedString alloc]
337 initWithString:@" "] autorelease])];
338 [textStorage setFont:font];
339 [textContainer setLineFragmentPadding:0];
341 [layoutManager addTextContainer:textContainer];
342 [textContainer release];
343 [textStorage addLayoutManager:layoutManager];
344 [layoutManager release];
346 if (!(textStorage && layoutManager && textContainer))
348 [textStorage release];
353 stringLength = [string length];
356 (void) [layoutManager glyphRangeForTextContainer:textContainer];
358 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
360 /* Remove the appended trailing space because otherwise it may
361 generate a wrong result for a right-to-left text. */
362 [textStorage beginEditing];
363 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
364 [textStorage endEditing];
365 (void) [layoutManager glyphRangeForTextContainer:textContainer];
368 while (i < stringLength)
371 NSFont *fontInTextStorage =
372 [textStorage attribute:NSFontAttributeName atIndex:i
373 longestEffectiveRange:&range
374 inRange:(NSMakeRange (0, stringLength))];
376 if (!(fontInTextStorage == font
377 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
379 i = NSMaxRange (range);
381 if (i < stringLength)
382 /* Make the test `used <= glyph_len' below fail if textStorage
383 contained some fonts other than the specified one. */
384 used = glyph_len + 1;
387 NSRange range = NSMakeRange (0, stringLength);
389 range = [layoutManager glyphRangeForCharacterRange:range
390 actualCharacterRange:NULL];
391 numberOfGlyphs = NSMaxRange (range);
392 used = numberOfGlyphs;
393 for (i = 0; i < numberOfGlyphs; i++)
394 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
398 if (0 < used && used <= glyph_len)
400 NSUInteger glyphIndex, prevGlyphIndex;
401 unsigned char bidiLevel;
402 NSUInteger *permutation;
403 NSRange compRange, range;
404 CGFloat totalAdvance;
407 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
410 /* For now we assume the direction is not changed within the
412 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
415 characterIndexes:NULL
416 bidiLevels:&bidiLevel];
418 permutation = xmalloc (sizeof (NSUInteger) * used);
422 #define RIGHT_TO_LEFT_P permutation
424 /* Fill the `comp_range' member of struct mac_glyph_layout, and
425 setup a permutation for right-to-left text. */
426 compRange = NSMakeRange (0, 0);
427 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
430 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
431 NSUInteger characterIndex =
432 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
434 gl->string_index = characterIndex;
436 if (characterIndex >= NSMaxRange (compRange))
438 compRange.location = NSMaxRange (compRange);
441 NSRange characterRange =
443 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
446 NSMaxRange (characterRange) - compRange.location;
447 [layoutManager glyphRangeForCharacterRange:compRange
448 actualCharacterRange:&characterRange];
449 characterIndex = NSMaxRange (characterRange) - 1;
451 while (characterIndex >= NSMaxRange (compRange));
454 for (i = 0; i < range.length; i++)
455 permutation[range.location + i] = NSMaxRange (range) - i - 1;
457 range = NSMakeRange (NSMaxRange (range), 0);
460 gl->comp_range.location = compRange.location;
461 gl->comp_range.length = compRange.length;
463 while (++glyphIndex < numberOfGlyphs)
464 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
468 for (i = 0; i < range.length; i++)
469 permutation[range.location + i] = NSMaxRange (range) - i - 1;
471 /* Then fill the remaining members. */
472 glyphIndex = prevGlyphIndex = 0;
473 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
476 if (!RIGHT_TO_LEFT_P)
483 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
484 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
485 inTextContainer:textContainer rectCount:&nrects];
487 totalAdvance = NSMaxX (glyphRects[0]);
490 for (i = 0; i < used; i++)
492 struct mac_glyph_layout *gl;
494 NSUInteger nextGlyphIndex;
499 if (!RIGHT_TO_LEFT_P)
500 gl = glyph_layouts + i;
503 NSUInteger dest = permutation[i];
505 gl = glyph_layouts + dest;
508 CFIndex tmp = gl->string_index;
510 gl->string_index = glyph_layouts[i].string_index;
511 glyph_layouts[i].string_index = tmp;
514 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
516 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
517 gl->baseline_delta = spaceLocation.y - location.y;
519 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
522 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
525 if (!RIGHT_TO_LEFT_P)
529 if (prevGlyphIndex == 0)
530 glyphRange = NSMakeRange (0, nextGlyphIndex);
532 glyphRange = NSMakeRange (glyphIndex,
533 nextGlyphIndex - glyphIndex);
536 rectArrayForGlyphRange:glyphRange
537 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
538 inTextContainer:textContainer rectCount:&nrects];
539 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
540 gl->advance_delta = location.x - totalAdvance;
541 gl->advance = maxX - totalAdvance;
548 if (nextGlyphIndex == numberOfGlyphs)
549 glyphRange = NSMakeRange (prevGlyphIndex,
550 numberOfGlyphs - prevGlyphIndex);
552 glyphRange = NSMakeRange (prevGlyphIndex,
553 glyphIndex + 1 - prevGlyphIndex);
556 rectArrayForGlyphRange:glyphRange
557 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
558 inTextContainer:textContainer rectCount:&nrects];
559 minX = min (NSMinX (glyphRects[0]), totalAdvance);
560 gl->advance = totalAdvance - minX;
562 gl->advance_delta = location.x - totalAdvance;
565 prevGlyphIndex = glyphIndex + 1;
566 glyphIndex = nextGlyphIndex;
572 #undef RIGHT_TO_LEFT_P
576 [textStorage release];
582 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
583 struct mac_glyph_layout *glyph_layouts,
586 return mac_font_shape_1 ([(NSFont *)font printerFont],
588 glyph_layouts, glyph_len);
592 get_cgcolor(unsigned long idx, struct frame *f)
594 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
596 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
597 NSInteger noc = [nsColor numberOfComponents];
598 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
601 [nsColor getComponents: components];
602 cgColor = CGColorCreate (colorSpace, components);
607 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
609 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
610 CGContextSetFillColorWithColor (context, refcol_) ; \
611 CGColorRelease (refcol_); \
613 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
615 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
616 CGContextSetFillColorWithColor (context, refcol_); \
617 CGColorRelease (refcol_); \
619 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
621 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
622 CGContextSetStrokeColorWithColor (context, refcol_); \
623 CGColorRelease (refcol_); \
628 /* Mac font driver. */
634 /* characters to distinguish the charset from the others */
636 /* additional constraint by language */
639 CFCharacterSetRef cf_charset;
640 CFStringRef cf_charset_string;
641 } cf_charset_table[] =
642 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
643 { "iso8859-2", { 0x00A0, 0x010E }},
644 { "iso8859-3", { 0x00A0, 0x0108 }},
645 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
646 { "iso8859-5", { 0x00A0, 0x0401 }},
647 { "iso8859-6", { 0x00A0, 0x060C }},
648 { "iso8859-7", { 0x00A0, 0x0384 }},
649 { "iso8859-8", { 0x00A0, 0x05D0 }},
650 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
651 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
652 { "iso8859-11", { 0x00A0, 0x0E01 }},
653 { "iso8859-13", { 0x00A0, 0x201C }},
654 { "iso8859-14", { 0x00A0, 0x0174 }},
655 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
656 { "iso8859-16", { 0x00A0, 0x0218}},
657 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
658 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
659 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
660 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
661 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
662 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
663 { "cns11643.1992-3", { 0x201A9 }},
664 { "cns11643.1992-4", { 0x20057 }},
665 { "cns11643.1992-5", { 0x20000 }},
666 { "cns11643.1992-6", { 0x20003 }},
667 { "cns11643.1992-7", { 0x20055 }},
668 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
669 { "jisx0212.1990-0", { 0x4E44 }},
670 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
671 { "jisx0213.2000-2", { 0xFA49 }},
672 { "jisx0213.2004-1", { 0x20B9F }},
673 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
674 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
675 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
676 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
677 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
678 { "unicode-sip", { 0x20000 }},
682 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
685 CFStringRef language;
686 CFStringRef font_names[3];
687 } macfont_language_default_font_names[] = {
688 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
689 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
691 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
692 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
694 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
695 CFSTR ("STXihei"), /* 10.4 - 10.5 */
697 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
698 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
704 static CGFloat macfont_antialias_threshold;
707 macfont_update_antialias_threshold (void)
713 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
714 kCFPreferencesCurrentApplication,
717 macfont_antialias_threshold = threshold;
720 static inline Lisp_Object
721 macfont_intern_prop_cfstring (CFStringRef cfstring)
723 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
725 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
728 static inline CFIndex
729 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
740 unichars[0] = (c >> 10) + 0xD800;
741 unichars[1] = (c & 0x3FF) + 0xDC00;
748 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
749 CTFontSymbolicTraits *sym_traits)
753 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
754 OS X 10.6 when the value is greater than or equal to 1 << 31. */
755 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
757 *sym_traits = (CTFontSymbolicTraits) sint64_value;
766 mac_font_descriptor_get_adjusted_weight (CTFontDescriptorRef desc, CGFloat val)
768 long percent_val = lround (val * 100);
770 if (percent_val == -40)
772 CTFontRef font = NULL;
774 CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
778 font = CTFontCreateWithName (name, 0, NULL);
783 CFIndex weight = mac_font_get_weight (font);
785 /* Workaround for crash when displaying Oriya characters
786 with Arial Unicode MS on OS X 10.11. */
797 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
798 Lisp_Object spec_or_entity)
801 CFDictionaryRef dict;
805 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
808 ASET (spec_or_entity, FONT_FAMILY_INDEX,
809 macfont_intern_prop_cfstring (str));
812 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
816 enum font_property_index index;
819 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
821 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
822 {{-0.4, 50}, /* light */
823 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
824 {0, 100}, /* normal */
825 {0.24, 140}, /* (semi-bold + normal) / 2 */
826 {0.4, 200}, /* bold */
827 {CGFLOAT_MAX, CGFLOAT_MAX}},
828 mac_font_descriptor_get_adjusted_weight},
829 {FONT_SLANT_INDEX, kCTFontSlantTrait,
830 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
831 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
832 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
835 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
837 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
838 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
840 CGPoint *point = numeric_traits[i].points;
842 if (numeric_traits[i].adjust_func)
843 floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
844 while (point->x < floatval)
846 if (point == numeric_traits[i].points)
848 else if (point->x == CGFLOAT_MAX)
850 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
851 * ((point->y - (point - 1)->y)
852 / (point->x - (point - 1)->x)));
853 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
854 make_number (lround (floatval)));
858 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
861 CTFontSymbolicTraits sym_traits;
864 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
865 spacing = (sym_traits & kCTFontTraitMonoSpace
866 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
867 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
872 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
873 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
874 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
876 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
882 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
883 CTFontSymbolicTraits synth_sym_traits)
886 CFDictionaryRef dict;
887 CTFontSymbolicTraits sym_traits = 0;
890 entity = font_make_entity ();
892 ASET (entity, FONT_TYPE_INDEX, Qmac_ct);
893 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
895 macfont_store_descriptor_attributes (desc, entity);
897 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
900 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
903 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
906 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
907 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
908 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
909 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
910 font_put_extra (entity, QCfont_entity,
911 make_save_ptr_int ((void *) name, sym_traits));
912 if (synth_sym_traits & kCTFontTraitItalic)
913 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
914 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
915 if (synth_sym_traits & kCTFontTraitBold)
916 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
917 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
918 if (synth_sym_traits & kCTFontTraitMonoSpace)
919 ASET (entity, FONT_SPACING_INDEX,
920 make_number (FONT_SPACING_SYNTHETIC_MONO));
925 /* Cache for font family name symbols vs CFStrings. A value of nil
926 means the cache has been invalidated. Otherwise the value is a Lisp
927 hash table whose keys are symbols and the value for a key is either
928 nil (no corresponding family name) or a Lisp save value wrapping the
929 corresponding family name in CFString. */
931 static Lisp_Object macfont_family_cache;
934 macfont_invalidate_family_cache (void)
936 if (HASH_TABLE_P (macfont_family_cache))
938 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
939 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
941 for (i = 0; i < size; ++i)
942 if (!NILP (HASH_HASH (h, i)))
944 Lisp_Object value = HASH_VALUE (h, i);
946 if (SAVE_VALUEP (value))
947 CFRelease (XSAVE_POINTER (value, 0));
949 macfont_family_cache = Qnil;
954 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
956 if (HASH_TABLE_P (macfont_family_cache))
958 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
959 ptrdiff_t i = hash_lookup (h, symbol, NULL);
963 Lisp_Object value = HASH_VALUE (h, i);
965 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
975 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
977 struct Lisp_Hash_Table *h;
982 if (!HASH_TABLE_P (macfont_family_cache))
983 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
985 h = XHASH_TABLE (macfont_family_cache);
986 i = hash_lookup (h, symbol, &hash);
987 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
990 Lisp_Object old_value = HASH_VALUE (h, i);
992 if (SAVE_VALUEP (old_value))
993 CFRelease (XSAVE_POINTER (old_value, 0));
994 set_hash_value_slot (h, i, value);
997 hash_put (h, symbol, value, hash);
1000 /* Cache of all the available font family names except "LastResort"
1001 and those start with ".". NULL means the cache has been invalidated.
1002 Otherwise, the value is CFArray of CFStrings and the elements are
1003 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1004 Mac OS X 10.6 and later). */
1006 static CFArrayRef macfont_available_families_cache = NULL;
1009 macfont_invalidate_available_families_cache (void)
1011 if (macfont_available_families_cache)
1013 CFRelease (macfont_available_families_cache);
1014 macfont_available_families_cache = NULL;
1019 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1021 CFStringRef name, const void *object,
1022 CFDictionaryRef userInfo)
1024 macfont_invalidate_family_cache ();
1025 macfont_invalidate_available_families_cache ();
1029 macfont_init_font_change_handler (void)
1031 static bool initialized = false;
1037 CFNotificationCenterAddObserver
1038 (CFNotificationCenterGetLocalCenter (), NULL,
1039 macfont_handle_font_change_notification,
1040 kCTFontManagerRegisteredFontsChangedNotification,
1041 NULL, CFNotificationSuspensionBehaviorCoalesce);
1045 macfont_copy_available_families_cache (void)
1047 macfont_init_font_change_handler ();
1049 if (macfont_available_families_cache == NULL)
1050 macfont_available_families_cache = mac_font_create_available_families ();
1052 return (macfont_available_families_cache
1053 ? CFRetain (macfont_available_families_cache) : NULL);
1057 macfont_create_family_with_symbol (Lisp_Object symbol)
1059 CFStringRef result = NULL, family_name;
1060 CFDictionaryRef attributes = NULL;
1061 CTFontDescriptorRef pat_desc = NULL;
1063 if (macfont_get_family_cache_if_present (symbol, &result))
1064 return result ? CFRetain (result) : NULL;
1066 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1070 CFDictionaryCreate (NULL,
1071 (const void **) &kCTFontFamilyNameAttribute,
1072 (const void **) &family_name, 1,
1073 &kCFTypeDictionaryKeyCallBacks,
1074 &kCFTypeDictionaryValueCallBacks);
1075 CFRelease (family_name);
1079 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1080 CFRelease (attributes);
1084 CTFontDescriptorRef desc =
1085 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1090 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1093 macfont_set_family_cache (symbol, result);
1094 CFRelease (pat_desc);
1100 #define WIDTH_FRAC_BITS (4)
1101 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1103 struct macfont_metrics
1105 unsigned char lbearing_low, rbearing_low;
1106 signed lbearing_high : 4, rbearing_high : 4;
1107 unsigned char ascent_low, descent_low;
1108 signed ascent_high : 4, descent_high : 4;
1110 /* These two members are used for fixed-point representation of
1111 glyph width. The `width_int' member is an integer that is
1112 closest to the width. The `width_frac' member is the fractional
1113 adjustment representing a value in [-.5, .5], multiplied by
1114 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1115 the advance delta for centering instead of the glyph width. */
1116 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1119 #define METRICS_VALUE(metrics, member) \
1120 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1121 #define METRICS_SET_VALUE(metrics, member, value) \
1122 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1123 (metrics)->member##_high = tmp >> 8;} while (0)
1127 METRICS_INVALID = -1, /* metrics entry is invalid */
1128 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1131 #define METRICS_STATUS(metrics) \
1132 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1133 #define METRICS_SET_STATUS(metrics, status) \
1134 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1135 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1137 #define METRICS_NCOLS_PER_ROW (128)
1138 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1139 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1142 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1143 struct font_metrics *metrics, CGFloat *advance_delta,
1144 int force_integral_p)
1146 struct macfont_info *macfont_info = (struct macfont_info *) font;
1147 CTFontRef macfont = macfont_info->macfont;
1149 struct macfont_metrics *cache;
1152 row = glyph / METRICS_NCOLS_PER_ROW;
1153 col = glyph % METRICS_NCOLS_PER_ROW;
1154 if (row >= macfont_info->metrics_nrows)
1156 macfont_info->metrics =
1157 xrealloc (macfont_info->metrics,
1158 sizeof (struct macfont_metrics *) * (row + 1));
1159 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1160 (sizeof (struct macfont_metrics *)
1161 * (row + 1 - macfont_info->metrics_nrows)));
1162 macfont_info->metrics_nrows = row + 1;
1164 if (macfont_info->metrics[row] == NULL)
1166 struct macfont_metrics *new;
1169 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1170 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1171 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1172 macfont_info->metrics[row] = new;
1174 cache = macfont_info->metrics[row] + col;
1176 if (METRICS_STATUS (cache) == METRICS_INVALID)
1180 if (macfont_info->screen_font)
1181 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1183 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1185 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1186 advance delta value. */
1187 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1188 fwidth = (font->pixel_size - fwidth) / 2;
1189 cache->width_int = lround (fwidth);
1190 cache->width_frac = lround ((fwidth - cache->width_int)
1191 * WIDTH_FRAC_SCALE);
1192 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1194 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1195 width = font->pixel_size;
1197 width = cache->width_int;
1201 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1203 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1205 if (macfont_info->synthetic_italic_p)
1207 /* We assume the members a, b, c, and d in
1208 synthetic_italic_atfm are non-negative. */
1210 CGPointApplyAffineTransform (bounds.origin,
1211 synthetic_italic_atfm);
1213 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1215 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1217 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1219 bounds = CGRectInset (bounds, d, d);
1221 switch (macfont_info->spacing)
1223 case MACFONT_SPACING_PROPORTIONAL:
1224 bounds.origin.x += - (cache->width_frac
1225 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1227 case MACFONT_SPACING_MONO:
1229 case MACFONT_SPACING_SYNTHETIC_MONO:
1230 bounds.origin.x += (cache->width_int
1231 + (cache->width_frac
1232 / (CGFloat) WIDTH_FRAC_SCALE));
1235 if (bounds.size.width > 0)
1237 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1238 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1239 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1241 bounds = CGRectIntegral (bounds);
1242 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1243 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1244 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1245 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1247 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1248 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1249 metrics->width = width;
1250 metrics->ascent = METRICS_VALUE (cache, ascent);
1251 metrics->descent = METRICS_VALUE (cache, descent);
1256 switch (macfont_info->spacing)
1258 case MACFONT_SPACING_PROPORTIONAL:
1259 *advance_delta = (force_integral_p ? 0
1260 : - (cache->width_frac
1261 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1263 case MACFONT_SPACING_MONO:
1266 case MACFONT_SPACING_SYNTHETIC_MONO:
1267 *advance_delta = (force_integral_p ? cache->width_int
1269 + (cache->width_frac
1270 / (CGFloat) WIDTH_FRAC_SCALE)));
1278 static CFMutableDictionaryRef macfont_cache_dictionary;
1280 /* Threshold used in row_nkeys_or_perm. This must be less than or
1281 equal to the number of rows that are invalid as BMP (i.e., from
1282 U+D800 to U+DFFF). */
1283 #define ROW_PERM_OFFSET (8)
1285 /* The number of glyphs that can be stored in a value for a single
1286 entry of CFDictionary. */
1287 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1289 struct macfont_cache
1291 int reference_count;
1292 CFCharacterSetRef cf_charset;
1294 /* The cached glyph for a BMP character c is stored in
1295 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1296 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1297 unsigned char row_nkeys_or_perm[256];
1300 /* Number of rows for which the BMP cache is allocated so far.
1301 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1304 /* The cached glyph for a character c is stored as the (c %
1305 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1306 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1307 not stored here if row_nkeys_or_perm[c / 256] >=
1309 CFMutableDictionaryRef dictionary;
1313 /* UVS (Unicode Variation Sequence) subtable data, which is of
1314 type CFDataRef if available. NULL means it is not initialized
1315 yet. kCFNull means the subtable is not found and there is no
1316 suitable fallback table for this font. */
1319 /* Character collection specifying the destination of the mapping
1320 provided by `table' above. If `table' is obtained from the UVS
1321 subtable in the font cmap table, then the value of this member
1322 should be NSIdentityMappingCharacterCollection. */
1323 NSCharacterCollection collection;
1327 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1328 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1329 static void macfont_release_cache (struct macfont_cache *);
1330 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1331 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1332 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1333 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1334 NSCharacterCollection, CGFontIndex);
1335 static CFDataRef macfont_get_uvs_table (struct font *, NSCharacterCollection *);
1337 static struct macfont_cache *
1338 macfont_lookup_cache (CFStringRef key)
1340 struct macfont_cache *cache;
1342 if (macfont_cache_dictionary == NULL)
1344 macfont_cache_dictionary =
1345 CFDictionaryCreateMutable (NULL, 0,
1346 &kCFTypeDictionaryKeyCallBacks, NULL);
1350 cache = ((struct macfont_cache *)
1351 CFDictionaryGetValue (macfont_cache_dictionary, key));
1355 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1359 cache = xzalloc (sizeof (struct macfont_cache));
1360 /* Treat the LastResort font as if it contained glyphs for
1361 all characters. This may look too rough, but neither
1362 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1363 for this font is correct for non-BMP characters on Mac OS
1365 if (CFEqual (key, CFSTR ("LastResort")))
1367 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1370 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1372 if (cache->cf_charset == NULL)
1373 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1374 CFDictionaryAddValue (macfont_cache_dictionary, key,
1375 (const void *) cache);
1376 CFRelease (macfont);
1383 static struct macfont_cache *
1384 macfont_retain_cache (struct macfont_cache *cache)
1386 cache->reference_count++;
1392 macfont_release_cache (struct macfont_cache *cache)
1394 if (--cache->reference_count == 0)
1398 for (i = 0; i < cache->glyph.nrows; i++)
1399 xfree (cache->glyph.matrix[i]);
1400 xfree (cache->glyph.matrix);
1401 if (cache->glyph.dictionary)
1402 CFRelease (cache->glyph.dictionary);
1403 memset (&cache->glyph, 0, sizeof (cache->glyph));
1404 if (cache->uvs.table)
1405 CFRelease (cache->uvs.table);
1406 memset (&cache->uvs, 0, sizeof (cache->uvs));
1410 static CFCharacterSetRef
1411 macfont_get_cf_charset (struct font *font)
1413 struct macfont_info *macfont_info = (struct macfont_info *) font;
1415 return macfont_info->cache->cf_charset;
1418 static CFCharacterSetRef
1419 macfont_get_cf_charset_for_name (CFStringRef name)
1421 struct macfont_cache *cache = macfont_lookup_cache (name);
1423 return cache->cf_charset;
1427 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1429 struct macfont_info *macfont_info = (struct macfont_info *) font;
1430 CTFontRef macfont = macfont_info->macfont;
1431 struct macfont_cache *cache = macfont_info->cache;
1433 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1436 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1438 if (nkeys_or_perm < ROW_PERM_OFFSET)
1440 UniChar unichars[256], ch;
1444 dispatch_queue_t queue;
1445 dispatch_group_t group = NULL;
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);
1483 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1484 group = dispatch_group_create ();
1485 dispatch_group_async (group, queue, ^{
1488 nkeys = nkeys_or_perm;
1489 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1490 if (CFDictionaryContainsKey (dictionary,
1491 (const void *) key))
1493 CFDictionaryRemoveValue (dictionary,
1494 (const void *) key);
1502 for (i = 0; i < 256; i++)
1505 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1506 unichars[len++] = ch;
1509 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1512 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1515 int next = unichars[len - 1] % 256;
1518 glyphs[i] = kCGFontIndexInvalid;
1521 glyphs[i] = glyphs[len];
1528 glyphs[i] = kCGFontIndexInvalid;
1530 nrows = cache->glyph.nrows;
1531 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1532 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1534 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1535 sizeof (CGGlyph *) * nrows);
1536 cache->glyph.matrix[nrows - 1] = glyphs;
1537 cache->glyph.nrows = nrows;
1541 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1542 dispatch_release (group);
1546 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1550 uintptr_t key, value;
1554 if (cache->glyph.dictionary == NULL)
1555 cache->glyph.dictionary =
1556 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1557 key = c / NGLYPHS_IN_VALUE;
1558 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1559 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1560 (const void *) key);
1561 glyph = (value >> nshifts);
1564 UniChar unichars[2];
1566 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1568 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1571 glyph = kCGFontIndexInvalid;
1573 value |= ((uintptr_t) glyph << nshifts);
1574 CFDictionarySetValue (cache->glyph.dictionary,
1575 (const void *) key, (const void *) value);
1583 macfont_get_glyph_for_cid (struct font *font, NSCharacterCollection collection,
1586 struct macfont_info *macfont_info = (struct macfont_info *) font;
1587 CTFontRef macfont = macfont_info->macfont;
1590 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1594 macfont_get_uvs_table (struct font *font, NSCharacterCollection *collection)
1596 struct macfont_info *macfont_info = (struct macfont_info *) font;
1597 CTFontRef macfont = macfont_info->macfont;
1598 struct macfont_cache *cache = macfont_info->cache;
1599 CFDataRef result = NULL;
1601 if (cache->uvs.table == NULL)
1603 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1604 NSCharacterCollection uvs_collection =
1605 NSIdentityMappingCharacterCollection;
1607 if (uvs_table == NULL
1608 && mac_font_get_glyph_for_cid (macfont,
1609 NSAdobeJapan1CharacterCollection,
1610 6480) != kCGFontIndexInvalid)
1612 /* If the glyph for U+4E55 is accessible via its CID 6480,
1613 then we use the Adobe-Japan1 UVS table, which maps a
1614 variation sequence to a CID, as a fallback. */
1615 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1617 if (mac_uvs_table_adobe_japan1 == NULL)
1618 mac_uvs_table_adobe_japan1 =
1619 CFDataCreateWithBytesNoCopy (NULL,
1620 mac_uvs_table_adobe_japan1_bytes,
1621 sizeof (mac_uvs_table_adobe_japan1_bytes),
1623 if (mac_uvs_table_adobe_japan1)
1625 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1626 uvs_collection = NSAdobeJapan1CharacterCollection;
1629 if (uvs_table == NULL)
1630 cache->uvs.table = kCFNull;
1632 cache->uvs.table = uvs_table;
1633 cache->uvs.collection = uvs_collection;
1636 if (cache->uvs.table != kCFNull)
1638 result = cache->uvs.table;
1639 *collection = cache->uvs.collection;
1645 static Lisp_Object macfont_get_cache (struct frame *);
1646 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1647 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1648 static Lisp_Object macfont_list_family (struct frame *);
1649 static void macfont_free_entity (Lisp_Object);
1650 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1651 static void macfont_close (struct font *);
1652 static int macfont_has_char (Lisp_Object, int);
1653 static unsigned macfont_encode_char (struct font *, int);
1654 static void macfont_text_extents (struct font *, unsigned int *, int,
1655 struct font_metrics *);
1656 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1657 static Lisp_Object macfont_shape (Lisp_Object);
1658 static int macfont_variation_glyphs (struct font *, int c,
1659 unsigned variations[256]);
1660 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1662 static struct font_driver const macfont_driver =
1664 .type = LISPSYM_INITIALLY (Qmac_ct),
1665 .get_cache = macfont_get_cache,
1666 .list = macfont_list,
1667 .match = macfont_match,
1668 .list_family = macfont_list_family,
1669 .free_entity = macfont_free_entity,
1670 .open = macfont_open,
1671 .close = macfont_close,
1672 .has_char = macfont_has_char,
1673 .encode_char = macfont_encode_char,
1674 .text_extents = macfont_text_extents,
1675 .draw = macfont_draw,
1676 .shape = macfont_shape,
1677 .get_variation_glyphs = macfont_variation_glyphs,
1678 .filter_properties = macfont_filter_properties,
1682 macfont_get_cache (struct frame * f)
1684 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1686 return (dpyinfo->name_list_element);
1690 macfont_get_charset (Lisp_Object registry)
1692 char *str = SSDATA (SYMBOL_NAME (registry));
1693 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1697 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1701 else if (str[i] == '*')
1708 regexp = make_unibyte_string (re, j);
1709 for (i = 0; cf_charset_table[i].name; i++)
1710 if (fast_c_string_match_ignore_case
1711 (regexp, cf_charset_table[i].name,
1712 strlen (cf_charset_table[i].name)) >= 0)
1714 if (! cf_charset_table[i].name)
1716 if (! cf_charset_table[i].cf_charset)
1718 int *uniquifier = cf_charset_table[i].uniquifier;
1719 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1722 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1726 for (j = 0; uniquifier[j]; j++)
1728 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1730 CFCharacterSetAddCharactersInRange (charset,
1731 CFRangeMake (uniquifier[j], 1));
1734 string = CFStringCreateWithCharacters (NULL, unichars, count);
1737 CFRelease (charset);
1740 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1742 CFRelease (charset);
1743 /* CFCharacterSetCreateWithCharactersInString does not handle
1744 surrogate pairs properly as of Mac OS X 10.5. */
1745 cf_charset_table[i].cf_charset_string = string;
1753 unsigned int script_tag, langsys_tag;
1755 unsigned int *features[2];
1758 #define OTF_SYM_TAG(SYM, TAG) \
1760 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1761 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1764 #define OTF_TAG_STR(TAG, P) \
1766 (P)[0] = (char) (TAG >> 24); \
1767 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1768 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1769 (P)[3] = (char) (TAG & 0xFF); \
1773 static struct OpenTypeSpec *
1774 macfont_get_open_type_spec (Lisp_Object otf_spec)
1776 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1783 spec->script = XCAR (otf_spec);
1784 if (! NILP (spec->script))
1786 OTF_SYM_TAG (spec->script, spec->script_tag);
1787 val = assq_no_quit (spec->script, Votf_script_alist);
1788 if (CONSP (val) && SYMBOLP (XCDR (val)))
1789 spec->script = XCDR (val);
1791 spec->script = Qnil;
1794 spec->script_tag = 0x44464C54; /* "DFLT" */
1795 otf_spec = XCDR (otf_spec);
1796 spec->langsys_tag = 0;
1797 if (! NILP (otf_spec))
1799 val = XCAR (otf_spec);
1801 OTF_SYM_TAG (val, spec->langsys_tag);
1802 otf_spec = XCDR (otf_spec);
1804 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1805 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1809 val = XCAR (otf_spec);
1812 len = Flength (val);
1814 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1816 : malloc (XINT (len) * sizeof *spec->features[i]));
1817 if (! spec->features[i])
1819 if (i > 0 && spec->features[0])
1820 free (spec->features[0]);
1824 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1826 if (NILP (XCAR (val)))
1832 OTF_SYM_TAG (XCAR (val), tag);
1833 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1836 spec->nfeatures[i] = j;
1841 static CFMutableDictionaryRef
1842 macfont_create_attributes_with_spec (Lisp_Object spec)
1844 Lisp_Object tmp, extra;
1845 CFMutableArrayRef langarray = NULL;
1846 CFCharacterSetRef charset = NULL;
1847 CFStringRef charset_string = NULL;
1848 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1849 Lisp_Object script = Qnil;
1850 Lisp_Object registry;
1851 int cf_charset_idx, i;
1852 struct OpenTypeSpec *otspec = NULL;
1854 enum font_property_index index;
1857 } numeric_traits[] =
1858 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1859 {{-0.4, 50}, /* light */
1860 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1861 {0, 100}, /* normal */
1862 {0.24, 140}, /* (semi-bold + normal) / 2 */
1863 {0.4, 200}, /* bold */
1864 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1865 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1866 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1867 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1868 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1870 registry = AREF (spec, FONT_REGISTRY_INDEX);
1872 || EQ (registry, Qascii_0)
1873 || EQ (registry, Qiso10646_1)
1874 || EQ (registry, Qunicode_bmp))
1875 cf_charset_idx = -1;
1880 cf_charset_idx = macfont_get_charset (registry);
1881 if (cf_charset_idx < 0)
1883 charset = cf_charset_table[cf_charset_idx].cf_charset;
1884 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1885 lang = cf_charset_table[cf_charset_idx].lang;
1888 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1891 CFArrayAppendValue (langarray, lang);
1895 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1896 CONSP (extra); extra = XCDR (extra))
1898 Lisp_Object key, val;
1901 key = XCAR (tmp), val = XCDR (tmp);
1902 if (EQ (key, QClang))
1905 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1910 for (; CONSP (val); val = XCDR (val))
1911 if (SYMBOLP (XCAR (val)))
1914 cfstring_create_with_string_noencode (SYMBOL_NAME
1919 CFArrayAppendValue (langarray, lang);
1923 else if (EQ (key, QCotf))
1925 otspec = macfont_get_open_type_spec (val);
1928 script = otspec->script;
1930 else if (EQ (key, QCscript))
1934 if (! NILP (script) && ! charset)
1936 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1938 if (CONSP (chars) && CONSP (CDR (chars)))
1940 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1941 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1943 if (! string || !cs)
1951 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1952 if (CHARACTERP (XCAR (chars)))
1954 UniChar unichars[2];
1956 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1958 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1960 CFStringAppendCharacters (string, unichars, count);
1961 CFCharacterSetAddCharactersInRange (cs, range);
1964 /* CFCharacterSetCreateWithCharactersInString does not
1965 handle surrogate pairs properly as of Mac OS X 10.5. */
1966 charset_string = string;
1970 attributes = CFDictionaryCreateMutable (NULL, 0,
1971 &kCFTypeDictionaryKeyCallBacks,
1972 &kCFTypeDictionaryValueCallBacks);
1976 tmp = AREF (spec, FONT_FAMILY_INDEX);
1977 if (SYMBOLP (tmp) && ! NILP (tmp))
1979 CFStringRef family = macfont_create_family_with_symbol (tmp);
1983 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1988 traits = CFDictionaryCreateMutable (NULL, 4,
1989 &kCFTypeDictionaryKeyCallBacks,
1990 &kCFTypeDictionaryValueCallBacks);
1994 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1996 tmp = AREF (spec, numeric_traits[i].index);
1999 CGPoint *point = numeric_traits[i].points;
2000 CGFloat floatval = (XINT (tmp) >> 8); // XXX
2003 while (point->y < floatval)
2005 if (point == numeric_traits[i].points)
2007 else if (point->y == CGFLOAT_MAX)
2009 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
2010 * ((point->x - (point - 1)->x)
2011 / (point->y - (point - 1)->y)));
2014 else if (floatval < -1.0)
2016 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2019 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2023 if (CFDictionaryGetCount (traits))
2024 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2027 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2030 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2033 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2040 CFRelease (attributes);
2045 if (langarray) CFRelease (langarray);
2046 if (charset && cf_charset_idx < 0) CFRelease (charset);
2047 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2048 if (traits) CFRelease (traits);
2051 if (otspec->nfeatures[0] > 0)
2052 free (otspec->features[0]);
2053 if (otspec->nfeatures[1] > 0)
2054 free (otspec->features[1]);
2062 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2063 CFCharacterSetRef charset,
2065 CFArrayRef languages)
2067 Boolean result = true;
2069 if (charset || VECTORP (chars))
2071 CFCharacterSetRef desc_charset =
2072 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2074 if (desc_charset == NULL)
2079 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2080 else /* VECTORP (chars) */
2084 for (j = 0; j < ASIZE (chars); j++)
2085 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2086 && CFCharacterSetIsLongCharacterMember (desc_charset,
2087 XFASTINT (AREF (chars, j))))
2089 if (j == ASIZE (chars))
2092 CFRelease (desc_charset);
2095 if (result && languages)
2096 result = mac_font_descriptor_supports_languages (desc, languages);
2102 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2103 CTFontSymbolicTraits sym_traits2)
2105 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2108 /* We prefer synthetic bold of italic to synthetic italic of bold
2109 when both bold and italic are available but bold-italic is not
2111 if (diff & kCTFontTraitBold)
2112 distance |= (1 << 0);
2113 if (diff & kCTFontTraitItalic)
2114 distance |= (1 << 1);
2115 if (diff & kCTFontTraitMonoSpace)
2116 distance |= (1 << 2);
2122 macfont_closest_traits_index_p (CFArrayRef traits_array,
2123 CTFontSymbolicTraits target,
2126 CFIndex i, count = CFArrayGetCount (traits_array);
2127 CTFontSymbolicTraits traits;
2130 traits = ((CTFontSymbolicTraits) (uintptr_t)
2131 CFArrayGetValueAtIndex (traits_array, index));
2132 my_distance = macfont_traits_distance (target, traits);
2134 for (i = 0; i < count; i++)
2137 traits = ((CTFontSymbolicTraits) (uintptr_t)
2138 CFArrayGetValueAtIndex (traits_array, i));
2139 if (macfont_traits_distance (target, traits) < my_distance)
2147 macfont_list (struct frame *f, Lisp_Object spec)
2149 Lisp_Object val = Qnil, family, extra;
2151 CFStringRef family_name = NULL;
2152 CFMutableDictionaryRef attributes = NULL, traits;
2153 Lisp_Object chars = Qnil;
2155 CTFontSymbolicTraits synth_sym_traits = 0;
2156 CFArrayRef families;
2157 CFIndex families_count;
2158 CFCharacterSetRef charset = NULL;
2159 CFArrayRef languages = NULL;
2163 family = AREF (spec, FONT_FAMILY_INDEX);
2164 if (! NILP (family))
2166 family_name = macfont_create_family_with_symbol (family);
2167 if (family_name == NULL)
2171 attributes = macfont_create_attributes_with_spec (spec);
2175 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2177 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2178 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2180 traits = ((CFMutableDictionaryRef)
2181 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2183 n = FONT_SLANT_NUMERIC (spec);
2184 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2186 synth_sym_traits |= kCTFontTraitItalic;
2188 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2191 n = FONT_WEIGHT_NUMERIC (spec);
2192 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2194 synth_sym_traits |= kCTFontTraitBold;
2196 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2200 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2202 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2204 if (CFStringHasPrefix (language, CFSTR ("ja"))
2205 || CFStringHasPrefix (language, CFSTR ("ko"))
2206 || CFStringHasPrefix (language, CFSTR ("zh")))
2207 synth_sym_traits |= kCTFontTraitMonoSpace;
2210 /* Create array of families. */
2212 families = CFArrayCreate (NULL, (const void **) &family_name,
2213 1, &kCFTypeArrayCallBacks);
2216 CFStringRef pref_family;
2217 CFIndex families_count, pref_family_index = -1;
2219 families = macfont_copy_available_families_cache ();
2220 if (families == NULL)
2223 families_count = CFArrayGetCount (families);
2225 /* Move preferred family to the front if exists. */
2227 mac_font_create_preferred_family_for_attributes (attributes);
2231 CFArrayGetFirstIndexOfValue (families,
2232 CFRangeMake (0, families_count),
2234 CFRelease (pref_family);
2236 if (pref_family_index > 0)
2238 CFMutableArrayRef mutable_families =
2239 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2241 if (mutable_families)
2243 CFArrayAppendValue (mutable_families,
2244 CFArrayGetValueAtIndex (families,
2245 pref_family_index));
2246 CFArrayAppendArray (mutable_families, families,
2247 CFRangeMake (0, pref_family_index));
2248 if (pref_family_index + 1 < families_count)
2249 CFArrayAppendArray (mutable_families, families,
2250 CFRangeMake (pref_family_index + 1,
2252 - (pref_family_index + 1)));
2253 CFRelease (families);
2254 families = mutable_families;
2259 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2263 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2267 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2270 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2271 if (CONSP (val) && VECTORP (XCDR (val)))
2279 CFRetain (languages);
2280 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2284 extra = AREF (spec, FONT_EXTRA_INDEX);
2285 families_count = CFArrayGetCount (families);
2286 for (i = 0; i < families_count; i++)
2288 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2289 CTFontDescriptorRef pat_desc;
2291 CFIndex descs_count;
2292 CFMutableArrayRef filtered_descs, traits_array;
2296 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2298 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2302 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2303 10.7 returns NULL if pat_desc represents the LastResort font.
2304 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2305 trailing "s") for such a font. */
2306 if (!CFEqual (family_name, CFSTR ("LastResort")))
2307 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2310 CTFontDescriptorRef lr_desc =
2311 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2314 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2315 &kCFTypeArrayCallBacks);
2316 CFRelease (lr_desc);
2321 CFRelease (pat_desc);
2325 descs_count = CFArrayGetCount (descs);
2326 if (descs_count == 0
2327 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2336 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2337 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2338 for (j = 0; j < descs_count; j++)
2340 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2341 CFDictionaryRef dict;
2343 CTFontSymbolicTraits sym_traits;
2345 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2349 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2352 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2356 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2357 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2358 != (spacing >= FONT_SPACING_MONO)))
2361 /* Don't use a color bitmap font until it is supported on
2363 if (sym_traits & kCTFontTraitColorGlyphs)
2367 && !macfont_supports_charset_and_languages_p (desc, charset,
2371 CFArrayAppendValue (filtered_descs, desc);
2372 CFArrayAppendValue (traits_array,
2373 (const void *) (uintptr_t) sym_traits);
2377 descs = filtered_descs;
2378 descs_count = CFArrayGetCount (descs);
2380 for (j = 0; j < descs_count; j++)
2382 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2383 CTFontSymbolicTraits sym_traits =
2384 ((CTFontSymbolicTraits) (uintptr_t)
2385 CFArrayGetValueAtIndex (traits_array, j));
2386 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2388 mask_min = ((synth_sym_traits ^ sym_traits)
2389 & (kCTFontTraitItalic | kCTFontTraitBold));
2390 if (FONT_SLANT_NUMERIC (spec) < 0)
2391 mask_min &= ~kCTFontTraitItalic;
2392 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2393 mask_min &= ~kCTFontTraitBold;
2395 mask_max = (synth_sym_traits & ~sym_traits);
2396 /* Synthetic bold does not work for bitmap-only fonts on Mac
2398 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2400 CFNumberRef format =
2401 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2405 uint32_t format_val;
2407 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2409 && format_val == kCTFontFormatBitmap)
2410 mask_max &= ~kCTFontTraitBold;
2414 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2416 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2417 mmask <= (mask_max & kCTFontTraitMonoSpace);
2418 mmask += kCTFontTraitMonoSpace)
2419 for (bmask = (mask_min & kCTFontTraitBold);
2420 bmask <= (mask_max & kCTFontTraitBold);
2421 bmask += kCTFontTraitBold)
2422 for (imask = (mask_min & kCTFontTraitItalic);
2423 imask <= (mask_max & kCTFontTraitItalic);
2424 imask += kCTFontTraitItalic)
2426 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2429 || macfont_closest_traits_index_p (traits_array,
2430 (sym_traits | synth),
2433 entity = macfont_descriptor_entity (desc, extra, synth);
2434 if (! NILP (entity))
2435 val = Fcons (entity, val);
2440 CFRelease (traits_array);
2444 CFRelease (families);
2445 val = Fnreverse (val);
2451 FONT_ADD_LOG ("macfont-list", spec, val);
2452 if (charset) CFRelease (charset);
2453 if (languages) CFRelease (languages);
2454 if (attributes) CFRelease (attributes);
2455 if (family_name) CFRelease (family_name);
2463 macfont_match (struct frame * frame, Lisp_Object spec)
2465 Lisp_Object entity = Qnil;
2466 CFMutableDictionaryRef attributes;
2467 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2471 attributes = macfont_create_attributes_with_spec (spec);
2474 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2475 CFRelease (attributes);
2479 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2480 CFRelease (pat_desc);
2484 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2490 FONT_ADD_LOG ("macfont-match", spec, entity);
2495 macfont_list_family (struct frame *frame)
2497 Lisp_Object list = Qnil;
2498 CFArrayRef families;
2502 families = macfont_copy_available_families_cache ();
2505 CFIndex i, count = CFArrayGetCount (families);
2507 for (i = 0; i < count; i++)
2508 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2509 CFRelease (families);
2518 macfont_free_entity (Lisp_Object entity)
2520 Lisp_Object val = assq_no_quit (QCfont_entity,
2521 AREF (entity, FONT_EXTRA_INDEX));
2522 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2530 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2532 Lisp_Object val, font_object;
2533 CFStringRef font_name;
2534 struct macfont_info *macfont_info = NULL;
2538 CTFontSymbolicTraits sym_traits;
2541 CGFloat ascent, descent, leading;
2543 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2545 || XTYPE (XCDR (val)) != Lisp_Misc
2546 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2548 font_name = XSAVE_POINTER (XCDR (val), 0);
2549 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2551 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2556 macfont = CTFontCreateWithName (font_name, size, NULL);
2559 int fontsize = (int) [((NSFont *) macfont) pointSize];
2560 if (fontsize != size) size = fontsize;
2566 font_object = font_build_object (VECSIZE (struct macfont_info),
2567 Qmac_ct, entity, size);
2568 font = XFONT_OBJECT (font_object);
2569 font->pixel_size = size;
2570 font->driver = &macfont_driver;
2571 font->encoding_charset = font->repertory_charset = -1;
2575 macfont_info = (struct macfont_info *) font;
2576 macfont_info->macfont = macfont;
2577 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2579 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2580 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2581 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2584 macfont_info->screen_font = NULL;
2585 macfont_info->cache = macfont_lookup_cache (font_name);
2586 macfont_retain_cache (macfont_info->cache);
2587 macfont_info->metrics = NULL;
2588 macfont_info->metrics_nrows = 0;
2589 macfont_info->synthetic_italic_p = 0;
2590 macfont_info->synthetic_bold_p = 0;
2591 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2592 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2593 if (!(sym_traits & kCTFontTraitItalic)
2594 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2595 macfont_info->synthetic_italic_p = 1;
2596 if (!(sym_traits & kCTFontTraitBold)
2597 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2598 macfont_info->synthetic_bold_p = 1;
2599 if (sym_traits & kCTFontTraitMonoSpace)
2600 macfont_info->spacing = MACFONT_SPACING_MONO;
2601 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2602 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2603 == FONT_SPACING_SYNTHETIC_MONO))
2604 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2605 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2606 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2609 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2611 macfont_info->antialias =
2612 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2614 macfont_info->color_bitmap_p = 0;
2615 if (sym_traits & kCTFontTraitColorGlyphs)
2616 macfont_info->color_bitmap_p = 1;
2618 glyph = macfont_get_glyph_for_character (font, ' ');
2619 if (glyph != kCGFontIndexInvalid)
2620 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2622 /* dirty workaround */
2623 font->space_width = pixel_size;
2625 total_width = font->space_width;
2626 for (i = 1; i < 95; i++)
2628 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2629 if (glyph == kCGFontIndexInvalid)
2631 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2634 font->average_width = total_width / 95;
2636 font->average_width = font->space_width; /* XXX */
2638 if (!(macfont_info->screen_font
2639 && mac_screen_font_get_metrics (macfont_info->screen_font,
2640 &ascent, &descent, &leading)))
2642 CFStringRef family_name;
2644 ascent = CTFontGetAscent (macfont);
2645 descent = CTFontGetDescent (macfont);
2646 leading = CTFontGetLeading (macfont);
2647 /* AppKit and WebKit do some adjustment to the heights of
2648 Courier, Helvetica, and Times. */
2649 family_name = CTFontCopyFamilyName (macfont);
2652 if (CFEqual (family_name, CFSTR ("Courier"))
2653 || CFEqual (family_name, CFSTR ("Helvetica"))
2654 || CFEqual (family_name, CFSTR ("Times")))
2655 ascent += (ascent + descent) * .15f;
2656 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2661 CFRelease (family_name);
2664 font->ascent = ascent + 0.5f;
2665 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2666 if (CONSP (val) && !NILP (XCDR (val)))
2667 font->descent = descent + 0.5f;
2669 font->descent = descent + leading + 0.5f;
2670 font->height = font->ascent + font->descent;
2672 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2673 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2677 /* Unfortunately Xft doesn't provide a way to get minimum char
2678 width. So, we use space_width instead. */
2679 font->min_width = font->max_width = font->space_width; /* XXX */
2681 font->baseline_offset = 0;
2682 font->relative_compose = 0;
2683 font->default_ascent = 0;
2684 font->vertical_centering = 0;
2690 macfont_close (struct font *font)
2692 struct macfont_info *macfont_info = (struct macfont_info *) font;
2694 if (macfont_info->cache)
2699 CFRelease (macfont_info->macfont);
2700 CGFontRelease (macfont_info->cgfont);
2701 if (macfont_info->screen_font)
2702 CFRelease (macfont_info->screen_font);
2703 macfont_release_cache (macfont_info->cache);
2704 for (i = 0; i < macfont_info->metrics_nrows; i++)
2705 if (macfont_info->metrics[i])
2706 xfree (macfont_info->metrics[i]);
2707 if (macfont_info->metrics)
2708 xfree (macfont_info->metrics);
2709 macfont_info->cache = NULL;
2715 macfont_has_char (Lisp_Object font, int c)
2718 CFCharacterSetRef charset;
2721 if (FONT_ENTITY_P (font))
2726 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2728 name = XSAVE_POINTER (val, 0);
2729 charset = macfont_get_cf_charset_for_name (name);
2732 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2734 result = CFCharacterSetIsLongCharacterMember (charset, c);
2741 macfont_encode_char (struct font *font, int c)
2746 glyph = macfont_get_glyph_for_character (font, c);
2749 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2753 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2754 struct font_metrics *metrics)
2759 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2760 for (i = 1; i < nglyphs; i++)
2762 struct font_metrics m;
2763 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2768 if (width + m.lbearing < metrics->lbearing)
2769 metrics->lbearing = width + m.lbearing;
2770 if (width + m.rbearing > metrics->rbearing)
2771 metrics->rbearing = width + m.rbearing;
2772 if (m.ascent > metrics->ascent)
2773 metrics->ascent = m.ascent;
2774 if (m.descent > metrics->descent)
2775 metrics->descent = m.descent;
2782 metrics->width = width;
2786 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2787 bool with_background)
2789 struct frame * f = s->f;
2790 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2791 CGRect background_rect;
2792 CGPoint text_position;
2795 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2796 bool no_antialias_p =
2797 (NILP (ns_antialias_text)
2798 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2799 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2800 && font_size <= macfont_antialias_threshold));
2801 int len = to - from;
2802 struct face *face = s->face;
2803 CGContextRef context;
2807 if (with_background)
2808 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2809 s->width, FONT_HEIGHT (s->font));
2811 background_rect = CGRectNull;
2813 text_position = CGPointMake (x, -y);
2814 glyphs = xmalloc (sizeof (CGGlyph) * len);
2816 CGFloat advance_delta = 0;
2818 CGFloat total_width = 0;
2820 positions = xmalloc (sizeof (CGPoint) * len);
2821 for (i = 0; i < len; i++)
2825 glyphs[i] = s->char2b[from + i];
2826 width = (s->padding_p ? 1
2827 : macfont_glyph_extents (s->font, glyphs[i],
2828 NULL, &advance_delta,
2830 positions[i].x = total_width + advance_delta;
2832 total_width += width;
2836 context = [[NSGraphicsContext currentContext] graphicsPort];
2837 CGContextSaveGState (context);
2839 if (!CGRectIsNull (background_rect))
2841 if (s->hl == DRAW_MOUSE_FACE)
2843 face = FACE_FROM_ID_OR_NULL (s->f,
2844 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2846 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2848 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2849 CGContextFillRects (context, &background_rect, 1);
2852 if (macfont_info->cgfont)
2854 CGAffineTransform atfm;
2856 CGContextScaleCTM (context, 1, -1);
2857 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2858 if (macfont_info->synthetic_italic_p)
2859 atfm = synthetic_italic_atfm;
2861 atfm = CGAffineTransformIdentity;
2862 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2864 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2866 /* Stroke line width for text drawing is not correctly
2867 scaled on Retina display/HiDPI mode when drawn to screen
2868 (whereas it is correctly scaled when drawn to bitmaps),
2869 and synthetic bold looks thinner on such environments.
2870 Apple says there are no plans to address this issue
2871 (rdar://11644870) currently. So we add a workaround. */
2872 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2873 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2874 if ([[FRAME_NS_VIEW(f) window] respondsToSelector:
2875 @selector(backingScaleFactor)])
2877 CGContextSetLineWidth (context, synthetic_bold_factor * font_size
2878 * [[FRAME_NS_VIEW(f) window] backingScaleFactor]);
2879 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2883 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2884 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2886 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2889 CGContextSetShouldAntialias (context, false);
2891 if (!NILP (ns_use_thin_smoothing))
2893 CGContextSetShouldSmoothFonts(context, YES);
2894 CGContextSetFontSmoothingStyle(context, 16);
2897 CGContextSetTextMatrix (context, atfm);
2898 CGContextSetTextPosition (context, text_position.x, text_position.y);
2900 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2901 if (macfont_info->color_bitmap_p
2902 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2903 && CTFontDrawGlyphs != NULL
2909 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2914 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2916 CGContextSetFont (context, macfont_info->cgfont);
2917 CGContextSetFontSize (context, font_size);
2918 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2925 CGContextRestoreGState (context);
2933 macfont_shape (Lisp_Object lgstring)
2935 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2936 struct macfont_info *macfont_info = (struct macfont_info *) font;
2937 CTFontRef macfont = macfont_info->macfont;
2938 ptrdiff_t glyph_len, len, i, j;
2941 CFIndex *nonbmp_indices;
2944 struct mac_glyph_layout *glyph_layouts;
2946 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2948 for (i = 0; i < glyph_len; i++)
2950 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2954 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2960 if (INT_MAX / 2 < len)
2961 memory_full (SIZE_MAX);
2963 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2964 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2965 for (i = j = 0; i < len; i++)
2967 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2969 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2971 nonbmp_indices[j] = i + j;
2975 nonbmp_indices[j] = len + j; /* sentinel */
2979 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2983 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2984 if (macfont_info->screen_font)
2985 used = mac_screen_font_shape (macfont_info->screen_font, string,
2986 glyph_layouts, glyph_len);
2988 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2999 for (i = 0; i < used; i++)
3001 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
3002 struct mac_glyph_layout *gl = glyph_layouts + i;
3004 struct font_metrics metrics;
3005 int xoff, yoff, wadjust;
3009 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
3010 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
3013 from = gl->comp_range.location;
3014 /* Convert UTF-16 index to UTF-32. */
3016 while (nonbmp_indices[j] < from)
3019 LGLYPH_SET_FROM (lglyph, from);
3021 to = gl->comp_range.location + gl->comp_range.length;
3022 /* Convert UTF-16 index to UTF-32. */
3023 while (nonbmp_indices[j] < to)
3026 LGLYPH_SET_TO (lglyph, to - 1);
3028 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3029 the composition is trivial. */
3033 if (unichars[gl->string_index] >= 0xD800
3034 && unichars[gl->string_index] < 0xDC00)
3035 c = (((unichars[gl->string_index] - 0xD800) << 10)
3036 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3038 c = unichars[gl->string_index];
3039 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3041 LGLYPH_SET_CHAR (lglyph, c);
3045 unsigned long cc = gl->glyph_id;
3046 LGLYPH_SET_CODE (lglyph, cc);
3049 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3050 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3051 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3052 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3053 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3054 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3056 xoff = lround (gl->advance_delta);
3057 yoff = lround (- gl->baseline_delta);
3058 wadjust = lround (gl->advance);
3059 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3063 vec = Fmake_vector (make_number (3), Qnil);
3064 ASET (vec, 0, make_number (xoff));
3065 ASET (vec, 1, make_number (yoff));
3066 ASET (vec, 2, make_number (wadjust));
3067 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3073 return make_number (used);
3076 /* Structures for the UVS subtable (format 14) in the cmap table. */
3077 typedef UInt8 UINT24[3];
3079 #pragma pack(push, 1)
3080 struct variation_selector_record
3082 UINT24 var_selector;
3083 UInt32 default_uvs_offset, non_default_uvs_offset;
3088 UInt32 length, num_var_selector_records;
3089 struct variation_selector_record variation_selector_records[1];
3091 #define SIZEOF_UVS_TABLE_HEADER \
3092 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3094 struct unicode_value_range
3096 UINT24 start_unicode_value;
3097 UInt8 additional_count;
3099 struct default_uvs_table {
3100 UInt32 num_unicode_value_ranges;
3101 struct unicode_value_range unicode_value_ranges[1];
3103 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3104 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3108 UINT24 unicode_value;
3111 struct non_default_uvs_table
3113 UInt32 num_uvs_mappings;
3114 struct uvs_mapping uvs_mappings[1];
3116 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3117 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3120 /* Read big endian values. The argument LVAL must be an lvalue. */
3121 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3122 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3123 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3124 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3125 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3126 /* Succeeding one byte should also be accessible. */
3127 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3128 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3130 /* Return UVS subtable for the specified FONT. If the subtable is not
3131 found or ill-formatted, then return NULL. */
3134 mac_font_copy_uvs_table (CTFontRef font)
3136 CFDataRef cmap_table, uvs_table = NULL;
3138 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3139 kCTFontTableOptionNoOptions);
3142 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3143 struct uvs_table *uvs;
3144 struct variation_selector_record *records;
3145 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3148 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3152 cmap_len = CFDataGetLength (cmap_table);
3153 if (sizeof_sfntCMapHeader > cmap_len)
3156 ntables = BUINT16_VALUE (cmap->numTables);
3157 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3158 / sizeof_sfntCMapEncoding))
3161 for (i = 0; i < ntables; i++)
3162 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3163 == kFontUnicodePlatform)
3164 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3165 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3167 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3171 || uvs_offset > cmap_len
3172 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3175 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3176 uvs_len = BUINT32_VALUE (uvs->length);
3177 if (uvs_len > cmap_len - uvs_offset
3178 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3181 if (BUINT16_VALUE (uvs->format) != 14)
3184 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3185 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3186 / sizeof (struct variation_selector_record)))
3189 records = uvs->variation_selector_records;
3190 for (i = 0; i < nrecords; i++)
3192 UInt32 default_uvs_offset, non_default_uvs_offset;
3194 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3195 if (default_uvs_offset)
3197 struct default_uvs_table *default_uvs;
3200 if (default_uvs_offset > uvs_len
3201 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3202 > uvs_len - default_uvs_offset))
3205 default_uvs = ((struct default_uvs_table *)
3206 ((UInt8 *) uvs + default_uvs_offset));
3207 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3208 if (nranges > ((uvs_len - default_uvs_offset
3209 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3210 / sizeof (struct unicode_value_range)))
3212 /* Now 2 * nranges can't overflow, so we can safely use
3213 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3214 mac_font_get_glyphs_for_variants. */
3217 non_default_uvs_offset =
3218 BUINT32_VALUE (records[i].non_default_uvs_offset);
3219 if (non_default_uvs_offset)
3221 struct non_default_uvs_table *non_default_uvs;
3224 if (non_default_uvs_offset > uvs_len
3225 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3226 > uvs_len - non_default_uvs_offset))
3229 non_default_uvs = ((struct non_default_uvs_table *)
3230 ((UInt8 *) uvs + non_default_uvs_offset));
3231 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3232 if (nmappings > ((uvs_len - non_default_uvs_offset
3233 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3234 / sizeof (struct uvs_mapping)))
3236 /* Now 2 * nmappings can't overflow, so we can safely
3237 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3238 in mac_font_get_glyphs_for_variants. */
3242 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3245 CFRelease (cmap_table);
3251 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3252 sequence consisting of the given base character C and each
3253 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3254 result (explained below) into the corresponding GLYPHS[i]. If the
3255 entry is found in the Default UVS Table, then the result is 0. If
3256 the entry is found in the Non-Default UVS Table, then the result is
3257 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3258 elements in SELECTORS must be sorted in strictly increasing
3262 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3263 const UTF32Char selectors[], CGGlyph glyphs[],
3266 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3267 struct variation_selector_record *records = uvs->variation_selector_records;
3269 UInt32 ir, nrecords;
3270 dispatch_queue_t queue =
3271 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3272 dispatch_group_t group = dispatch_group_create ();
3274 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3277 while (i < count && ir < nrecords)
3279 UInt32 default_uvs_offset, non_default_uvs_offset;
3281 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3283 glyphs[i++] = kCGFontIndexInvalid;
3286 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3292 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3293 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3294 non_default_uvs_offset =
3295 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3296 dispatch_group_async (group, queue, ^{
3297 glyphs[i] = kCGFontIndexInvalid;
3299 if (default_uvs_offset)
3301 struct default_uvs_table *default_uvs =
3302 (struct default_uvs_table *) ((UInt8 *) uvs
3303 + default_uvs_offset);
3304 struct unicode_value_range *ranges =
3305 default_uvs->unicode_value_ranges;
3309 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3312 UInt32 mid = (lo + hi) / 2;
3314 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3320 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3321 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3325 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3327 struct non_default_uvs_table *non_default_uvs =
3328 (struct non_default_uvs_table *) ((UInt8 *) uvs
3329 + non_default_uvs_offset);
3330 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3334 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3337 UInt32 mid = (lo + hi) / 2;
3339 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3345 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3346 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3353 glyphs[i++] = kCGFontIndexInvalid;
3354 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3355 dispatch_release (group);
3359 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3361 CFDataRef uvs_table;
3362 NSCharacterCollection uvs_collection;
3366 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3370 UTF32Char selectors[256];
3371 CGGlyph glyphs[256];
3373 for (i = 0; i < 16; i++)
3374 selectors[i] = 0xFE00 + i;
3375 for (; i < 256; i++)
3376 selectors[i] = 0xE0100 + (i - 16);
3377 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3378 for (i = 0; i < 256; i++)
3380 CGGlyph glyph = glyphs[i];
3382 if (uvs_collection != NSIdentityMappingCharacterCollection
3383 && glyph != kCGFontIndexInvalid)
3384 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3385 if (glyph == kCGFontIndexInvalid)
3389 variations[i] = (glyph ? glyph
3390 : macfont_get_glyph_for_character (font, c));
3400 static const char *const macfont_booleans[] = {
3406 static const char *const macfont_non_booleans[] = {
3414 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3416 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3420 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3421 CFArrayRef languages)
3423 Boolean result = true;
3424 CFArrayRef desc_languages =
3425 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3427 if (desc_languages == NULL)
3431 CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
3432 CFIndex i, languages_count = CFArrayGetCount (languages);
3434 for (i = 0; i < languages_count; i++)
3436 CFStringRef language = CFArrayGetValueAtIndex (languages, i);
3438 if (!CFArrayContainsValue (desc_languages, range, language)
3439 /* PingFang SC contains "zh" and "zh-Hant" as covered
3440 languages, but does not contain "zh-Hans". */
3441 && !(CFEqual (language, CFSTR ("zh-Hans"))
3442 && CFArrayContainsValue (desc_languages, range,
3449 CFRelease (desc_languages);
3456 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3458 CFStringRef result = NULL;
3459 CFStringRef charset_string =
3460 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3462 if (charset_string && CFStringGetLength (charset_string) > 0)
3464 CFStringRef keys[] = {
3465 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3466 kCTLanguageAttributeName
3468 CFSTR ("NSLanguage")
3471 CFTypeRef values[] = {NULL};
3472 CFIndex num_values = 0;
3473 CFArrayRef languages
3474 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3476 if (languages && CFArrayGetCount (languages) > 0)
3478 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3479 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3482 CFCharacterSetRef charset =
3483 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3485 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3490 CFAttributedStringRef attr_string = NULL;
3491 CTLineRef ctline = NULL;
3492 CFDictionaryRef attrs
3493 = CFDictionaryCreate (NULL, (const void **) keys,
3494 (const void **) values, num_values,
3495 &kCFTypeDictionaryKeyCallBacks,
3496 &kCFTypeDictionaryValueCallBacks);
3500 attr_string = CFAttributedStringCreate (NULL, charset_string,
3506 ctline = CTLineCreateWithAttributedString (attr_string);
3507 CFRelease (attr_string);
3511 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3512 CFIndex i, nruns = CFArrayGetCount (runs);
3515 for (i = 0; i < nruns; i++)
3517 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3518 CFDictionaryRef attributes = CTRunGetAttributes (run);
3519 CTFontRef font_in_run;
3521 if (attributes == NULL)
3524 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3525 if (font_in_run == NULL)
3529 else if (!mac_font_equal_in_postscript_name (font,
3533 if (nruns > 0 && i == nruns)
3534 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3543 static inline double
3544 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3546 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3550 static inline CGRect
3551 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3553 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3558 mac_font_create_available_families (void)
3560 CFMutableArrayRef families = NULL;
3561 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3565 CFIndex i, count = CFArrayGetCount (orig_families);
3567 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3569 for (i = 0; i < count; i++)
3571 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3573 if (!CFStringHasPrefix (family, CFSTR ("."))
3574 && (CTFontManagerCompareFontFamilyNames (family,
3575 CFSTR ("LastResort"),
3577 != kCFCompareEqualTo))
3578 CFArrayAppendValue (families, family);
3580 CFRelease (orig_families);
3587 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3590 CFStringRef name1, name2;
3596 name1 = CTFontCopyPostScriptName (font1);
3599 name2 = CTFontCopyPostScriptName (font2);
3602 result = CFEqual (name1, name2);
3612 mac_font_create_line_with_string_and_font (CFStringRef string,
3615 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3616 CFTypeRef values[] = {NULL, NULL};
3617 CFDictionaryRef attributes = NULL;
3618 CFAttributedStringRef attr_string = NULL;
3619 CTLineRef ctline = NULL;
3620 float float_zero = 0.0f;
3622 values[0] = macfont;
3623 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3626 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3627 (const void **) values,
3629 &kCFTypeDictionaryKeyCallBacks,
3630 &kCFTypeDictionaryValueCallBacks);
3631 CFRelease (values[1]);
3635 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3636 CFRelease (attributes);
3640 ctline = CTLineCreateWithAttributedString (attr_string);
3641 CFRelease (attr_string);
3645 /* Abandon if ctline contains some fonts other than the
3647 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3648 CFIndex i, nruns = CFArrayGetCount (runs);
3650 for (i = 0; i < nruns; i++)
3652 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3653 CFDictionaryRef attributes = CTRunGetAttributes (run);
3654 CTFontRef font_in_run;
3656 if (attributes == NULL)
3659 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3660 if (font_in_run == NULL)
3662 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3676 mac_font_shape (CTFontRef font, CFStringRef string,
3677 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3679 CFIndex used, result = 0;
3680 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3685 used = CTLineGetGlyphCount (ctline);
3686 if (used <= glyph_len)
3688 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3689 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3690 CGFloat total_advance = 0;
3691 CFIndex total_glyph_count = 0;
3693 for (k = 0; k < ctrun_count; k++)
3695 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3696 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3697 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3698 CFRange string_range, comp_range, range;
3699 CFIndex *permutation;
3701 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3702 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3706 #define RIGHT_TO_LEFT_P permutation
3708 /* Now the `comp_range' member of struct mac_glyph_layout is
3709 temporarily used as a work area such that:
3710 glbuf[i].comp_range.location =
3711 min {compRange[i + 1].location, ...,
3712 compRange[glyph_count - 1].location,
3713 maxRange (stringRangeForCTRun)}
3714 glbuf[i].comp_range.length = maxRange (compRange[i])
3715 where compRange[i] is the range of composed characters
3716 containing i-th glyph. */
3717 string_range = CTRunGetStringRange (ctrun);
3718 min_location = string_range.location + string_range.length;
3719 for (i = 0; i < glyph_count; i++)
3721 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3722 CFIndex glyph_index;
3725 if (!RIGHT_TO_LEFT_P)
3726 glyph_index = glyph_count - i - 1;
3729 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3732 CFStringGetRangeOfComposedCharactersAtIndex (string,
3734 gl->comp_range.location = min_location;
3735 gl->comp_range.length = rng.location + rng.length;
3736 if (rng.location < min_location)
3737 min_location = rng.location;
3740 /* Fill the `comp_range' member of struct mac_glyph_layout,
3741 and setup a permutation for right-to-left text. */
3742 comp_range = CFRangeMake (string_range.location, 0);
3743 range = CFRangeMake (0, 0);
3746 struct mac_glyph_layout *gl =
3747 glbuf + range.location + range.length;
3749 if (gl->comp_range.length
3750 > comp_range.location + comp_range.length)
3751 comp_range.length = gl->comp_range.length - comp_range.location;
3752 min_location = gl->comp_range.location;
3755 if (min_location >= comp_range.location + comp_range.length)
3757 comp_range.length = min_location - comp_range.location;
3758 for (i = 0; i < range.length; i++)
3760 glbuf[range.location + i].comp_range = comp_range;
3761 if (RIGHT_TO_LEFT_P)
3762 permutation[range.location + i] =
3763 range.location + range.length - i - 1;
3766 comp_range = CFRangeMake (min_location, 0);
3767 range.location += range.length;
3769 if (range.location == glyph_count)
3774 /* Then fill the remaining members. */
3775 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3778 struct mac_glyph_layout *gl;
3782 if (!RIGHT_TO_LEFT_P)
3783 gl = glbuf + range.location;
3788 src = glyph_count - 1 - range.location;
3789 dest = permutation[src];
3793 CFIndex tmp = gl->string_index;
3795 gl->string_index = glbuf[src].string_index;
3796 glbuf[src].string_index = tmp;
3799 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3801 CTRunGetPositions (ctrun, range, &position);
3802 max_x = position.x + CTRunGetTypographicBounds (ctrun, range,
3804 max_x = max (max_x, total_advance);
3805 gl->advance_delta = position.x - total_advance;
3806 gl->baseline_delta = position.y;
3807 gl->advance = max_x - total_advance;
3808 total_advance = max_x;
3811 if (RIGHT_TO_LEFT_P)
3812 xfree (permutation);
3814 #undef RIGHT_TO_LEFT_P
3816 total_glyph_count += glyph_count;
3826 /* The function below seems to cause a memory leak for the CFString
3827 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3828 10.6.3. For now, we use the NSGlyphInfo version instead. */
3829 #if USE_CT_GLYPH_INFO
3831 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3834 CGGlyph result = kCGFontIndexInvalid;
3835 UniChar characters[] = {0xfffd};
3837 CFAttributedStringRef attr_string = NULL;
3838 CTLineRef ctline = NULL;
3840 string = CFStringCreateWithCharacters (NULL, characters,
3841 ARRAYELTS (characters));
3845 CTGlyphInfoRef glyph_info =
3846 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3847 CFDictionaryRef attributes = NULL;
3851 CFStringRef keys[] = {kCTFontAttributeName,
3852 kCTGlyphInfoAttributeName};
3853 CFTypeRef values[] = {font, glyph_info};
3855 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3856 (const void **) values,
3858 &kCFTypeDictionaryKeyCallBacks,
3859 &kCFTypeDictionaryValueCallBacks);
3860 CFRelease (glyph_info);
3864 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3865 CFRelease (attributes);
3871 ctline = CTLineCreateWithAttributedString (attr_string);
3872 CFRelease (attr_string);
3876 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3878 if (CFArrayGetCount (runs) > 0)
3880 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3881 CFDictionaryRef attributes = CTRunGetAttributes (run);
3885 CTFontRef font_in_run =
3886 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3889 && mac_font_equal_in_postscript_name (font_in_run, font))
3891 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3892 if (result >= CTFontGetGlyphCount (font))
3893 result = kCGFontIndexInvalid;
3905 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3907 CFArrayRef result = NULL;
3909 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3910 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3911 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3914 CTFontRef user_font =
3915 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3919 CFArrayRef languages =
3920 CFArrayCreate (NULL, (const void **) &language, 1,
3921 &kCFTypeArrayCallBacks);
3925 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3927 CFRelease (languages);
3929 CFRelease (user_font);
3932 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3933 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3935 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3936 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3940 for (i = 0; macfont_language_default_font_names[i].language; i++)
3942 if (CFEqual (macfont_language_default_font_names[i].language,
3945 CFMutableArrayRef descriptors =
3946 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3953 macfont_language_default_font_names[i].font_names[j];
3956 CFDictionaryRef attributes =
3957 CFDictionaryCreate (NULL,
3959 &kCTFontNameAttribute),
3961 &macfont_language_default_font_names[i].font_names[j]),
3962 1, &kCFTypeDictionaryKeyCallBacks,
3963 &kCFTypeDictionaryValueCallBacks);
3967 CTFontDescriptorRef pat_desc =
3968 CTFontDescriptorCreateWithAttributes (attributes);
3972 CTFontDescriptorRef descriptor =
3973 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3977 CFArrayAppendValue (descriptors, descriptor);
3978 CFRelease (descriptor);
3980 CFRelease (pat_desc);
3982 CFRelease (attributes);
3985 result = descriptors;
3997 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3998 CFArrayRef languages)
4000 CFStringRef result = NULL;
4001 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
4002 CFArrayRef descriptors =
4003 mac_font_copy_default_descriptors_for_language (language);
4007 CFIndex i, count = CFArrayGetCount (descriptors);
4009 for (i = 0; i < count; i++)
4011 CTFontDescriptorRef descriptor =
4012 CFArrayGetValueAtIndex (descriptors, i);
4014 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4017 CFStringRef family =
4018 CTFontDescriptorCopyAttribute (descriptor,
4019 kCTFontFamilyNameAttribute);
4022 if (!CFStringHasPrefix (family, CFSTR ("."))
4023 && !CFEqual (family, CFSTR ("LastResort")))
4033 CFRelease (descriptors);
4040 macfont_get_nsctfont (struct font *font)
4042 struct macfont_info *macfont_info = (struct macfont_info *) font;
4043 CTFontRef macfont = macfont_info->macfont;
4045 return (void *) macfont;
4049 mac_register_font_driver (struct frame *f)
4051 register_font_driver (&macfont_driver, f);
4056 syms_of_macfont (void)
4058 /* Core Text, for macOS. */
4059 DEFSYM (Qmac_ct, "mac-ct");
4060 register_font_driver (&macfont_driver, NULL);
4062 /* The font property key specifying the font design destination. The
4063 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4064 text. (See the documentation of X Logical Font Description
4065 Conventions.) In the Mac font driver, 1 means the screen font is
4066 used for calculating some glyph metrics. You can see the
4067 difference with Monaco 8pt or 9pt, for example. */
4068 DEFSYM (QCdestination, ":destination");
4070 /* The boolean-valued font property key specifying the use of leading. */
4071 DEFSYM (QCminspace, ":minspace");
4073 macfont_family_cache = Qnil;
4074 staticpro (&macfont_family_cache);