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 <https://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #include <libkern/OSByteOrder.h>
41 static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
42 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
43 static CFArrayRef mac_font_create_available_families (void);
44 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
45 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
47 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
49 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
50 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
51 struct mac_glyph_layout *, CFIndex);
52 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
53 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
55 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
59 struct macfont_metrics;
61 /* The actual structure for Mac font that can be cast to struct font. */
68 ScreenFontRef screen_font;
69 struct macfont_cache *cache;
70 struct macfont_metrics **metrics;
72 bool_bf synthetic_italic_p : 1;
73 bool_bf synthetic_bold_p : 1;
75 unsigned antialias : 2;
76 bool_bf color_bitmap_p : 1;
79 /* Values for the `spacing' member in `struct macfont_info'. */
83 MACFONT_SPACING_PROPORTIONAL,
85 MACFONT_SPACING_SYNTHETIC_MONO,
88 /* Values for the `antialias' member in `struct macfont_info'. */
92 MACFONT_ANTIALIAS_DEFAULT,
93 MACFONT_ANTIALIAS_OFF,
97 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
98 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
99 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
101 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
102 static const CGFloat synthetic_bold_factor = 0.024;
104 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
105 CTFontSymbolicTraits *);
106 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
108 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
109 CTFontSymbolicTraits);
110 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
111 static int macfont_glyph_extents (struct font *, CGGlyph,
112 struct font_metrics *, CGFloat *, int);
113 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
114 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
118 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
120 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
121 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
123 CGGlyph [], CFIndex);
125 /* From CFData to a lisp string. Always returns a unibyte string. */
128 cfdata_to_lisp (CFDataRef data)
130 CFIndex len = CFDataGetLength (data);
131 Lisp_Object result = make_uninit_string (len);
133 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
140 /* From CFString to a lisp string. Returns a unibyte string
141 containing a UTF-8 byte sequence. */
144 cfstring_to_lisp_nodecode (CFStringRef string)
146 Lisp_Object result = Qnil;
148 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
152 CFIndex i, length = CFStringGetLength (string);
154 for (i = 0; i < length; i++)
155 if (CFStringGetCharacterAtIndex (string, i) == 0)
159 return make_unibyte_string (s, strlen (s));
162 data = CFStringCreateExternalRepresentation (NULL, string,
163 kCFStringEncodingUTF8, '?');
166 result = cfdata_to_lisp (data);
173 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
174 cfstring_create_with_utf8_cstring, this function preserves NUL
178 cfstring_create_with_string_noencode (Lisp_Object s)
180 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
181 kCFStringEncodingUTF8, false);
184 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
185 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
186 kCFStringEncodingMacRoman, false);
192 mac_font_get_weight (CTFontRef font)
194 NSFont *nsFont = (NSFont *) font;
196 return [[NSFontManager sharedFontManager] weightOfFont:nsFont];
200 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
202 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
204 return advancement.width;
207 #if !USE_CT_GLYPH_INFO
209 mac_font_get_glyph_for_cid (CTFontRef font, NSCharacterCollection collection,
212 CGGlyph result = kCGFontIndexInvalid;
213 NSFont *nsFont = (NSFont *) font;
214 unichar characters[] = {0xfffd};
216 [NSString stringWithCharacters:characters
217 length:ARRAYELTS (characters)];
218 NSGlyphInfo *glyphInfo =
219 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
220 collection:collection
222 NSDictionary *attributes =
223 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
224 glyphInfo,NSGlyphInfoAttributeName,nil];
225 NSTextStorage *textStorage =
226 [[NSTextStorage alloc] initWithString:string
227 attributes:attributes];
228 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
229 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
230 NSFont *fontInTextStorage;
232 [layoutManager addTextContainer:textContainer];
233 [textContainer release];
234 [textStorage addLayoutManager:layoutManager];
235 [layoutManager release];
238 (void) [layoutManager glyphRangeForTextContainer:textContainer];
240 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
241 effectiveRange:NULL];
242 if (fontInTextStorage == nsFont
243 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
245 NSGlyph glyph = [layoutManager glyphAtIndex:0];
247 if (glyph < [nsFont numberOfGlyphs])
251 [textStorage release];
258 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
260 NSFont *result, *font;
262 font = [NSFont fontWithName:((NSString *) name) size:size];
263 result = [font screenFont];
265 return (ScreenFontRef)[result retain];
270 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
271 CGFloat *descent, CGFloat *leading)
273 NSFont *nsFont = [(NSFont *)font printerFont];
274 NSTextStorage *textStorage;
275 NSLayoutManager *layoutManager;
276 NSTextContainer *textContainer;
278 NSPoint spaceLocation;
281 textStorage = [[NSTextStorage alloc] initWithString:@" "];
282 layoutManager = [[NSLayoutManager alloc] init];
283 textContainer = [[NSTextContainer alloc] init];
285 [textStorage setFont:nsFont];
286 [textContainer setLineFragmentPadding:0];
288 [layoutManager addTextContainer:textContainer];
289 [textContainer release];
290 [textStorage addLayoutManager:layoutManager];
291 [layoutManager release];
293 if (!(textStorage && layoutManager && textContainer))
295 [textStorage release];
300 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
301 effectiveRange:NULL];
302 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
303 [textStorage release];
305 *ascent = spaceLocation.y;
306 *descent = NSHeight (usedRect) - spaceLocation.y;
308 descender = [nsFont descender];
309 if (- descender < *descent)
311 *leading = *descent + descender;
312 *descent = - descender;
319 mac_font_shape_1 (NSFont *font, NSString *string,
320 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
324 NSTextStorage *textStorage;
325 NSLayoutManager *layoutManager;
326 NSTextContainer *textContainer;
327 NSUInteger stringLength;
328 NSPoint spaceLocation;
329 NSUInteger used, numberOfGlyphs;
331 textStorage = [[NSTextStorage alloc] initWithString:string];
332 layoutManager = [[NSLayoutManager alloc] init];
333 textContainer = [[NSTextContainer alloc] init];
335 /* Append a trailing space to measure baseline position. */
336 [textStorage appendAttributedString:([[[NSAttributedString alloc]
337 initWithString:@" "] autorelease])];
338 [textStorage setFont:font];
339 [textContainer setLineFragmentPadding:0];
341 [layoutManager addTextContainer:textContainer];
342 [textContainer release];
343 [textStorage addLayoutManager:layoutManager];
344 [layoutManager release];
346 if (!(textStorage && layoutManager && textContainer))
348 [textStorage release];
353 stringLength = [string length];
356 (void) [layoutManager glyphRangeForTextContainer:textContainer];
358 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
360 /* Remove the appended trailing space because otherwise it may
361 generate a wrong result for a right-to-left text. */
362 [textStorage beginEditing];
363 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
364 [textStorage endEditing];
365 (void) [layoutManager glyphRangeForTextContainer:textContainer];
368 while (i < stringLength)
371 NSFont *fontInTextStorage =
372 [textStorage attribute:NSFontAttributeName atIndex:i
373 longestEffectiveRange:&range
374 inRange:(NSMakeRange (0, stringLength))];
376 if (!(fontInTextStorage == font
377 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
379 i = NSMaxRange (range);
381 if (i < stringLength)
382 /* Make the test `used <= glyph_len' below fail if textStorage
383 contained some fonts other than the specified one. */
384 used = glyph_len + 1;
387 NSRange range = NSMakeRange (0, stringLength);
389 range = [layoutManager glyphRangeForCharacterRange:range
390 actualCharacterRange:NULL];
391 numberOfGlyphs = NSMaxRange (range);
392 used = numberOfGlyphs;
393 for (i = 0; i < numberOfGlyphs; i++)
394 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
398 if (0 < used && used <= glyph_len)
400 NSUInteger glyphIndex, prevGlyphIndex;
401 unsigned char bidiLevel;
402 NSUInteger *permutation;
403 NSRange compRange, range;
404 CGFloat totalAdvance;
407 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
410 /* For now we assume the direction is not changed within the
412 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
415 characterIndexes:NULL
416 bidiLevels:&bidiLevel];
418 permutation = xmalloc (sizeof (NSUInteger) * used);
422 #define RIGHT_TO_LEFT_P permutation
424 /* Fill the `comp_range' member of struct mac_glyph_layout, and
425 setup a permutation for right-to-left text. */
426 compRange = NSMakeRange (0, 0);
427 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
430 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
431 NSUInteger characterIndex =
432 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
434 gl->string_index = characterIndex;
436 if (characterIndex >= NSMaxRange (compRange))
438 compRange.location = NSMaxRange (compRange);
441 NSRange characterRange =
443 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
446 NSMaxRange (characterRange) - compRange.location;
447 [layoutManager glyphRangeForCharacterRange:compRange
448 actualCharacterRange:&characterRange];
449 characterIndex = NSMaxRange (characterRange) - 1;
451 while (characterIndex >= NSMaxRange (compRange));
454 for (i = 0; i < range.length; i++)
455 permutation[range.location + i] = NSMaxRange (range) - i - 1;
457 range = NSMakeRange (NSMaxRange (range), 0);
460 gl->comp_range.location = compRange.location;
461 gl->comp_range.length = compRange.length;
463 while (++glyphIndex < numberOfGlyphs)
464 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
468 for (i = 0; i < range.length; i++)
469 permutation[range.location + i] = NSMaxRange (range) - i - 1;
471 /* Then fill the remaining members. */
472 glyphIndex = prevGlyphIndex = 0;
473 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
476 if (!RIGHT_TO_LEFT_P)
483 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
484 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
485 inTextContainer:textContainer rectCount:&nrects];
487 totalAdvance = NSMaxX (glyphRects[0]);
490 for (i = 0; i < used; i++)
492 struct mac_glyph_layout *gl;
494 NSUInteger nextGlyphIndex;
499 if (!RIGHT_TO_LEFT_P)
500 gl = glyph_layouts + i;
503 NSUInteger dest = permutation[i];
505 gl = glyph_layouts + dest;
508 CFIndex tmp = gl->string_index;
510 gl->string_index = glyph_layouts[i].string_index;
511 glyph_layouts[i].string_index = tmp;
514 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
516 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
517 gl->baseline_delta = spaceLocation.y - location.y;
519 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
522 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
525 if (!RIGHT_TO_LEFT_P)
529 if (prevGlyphIndex == 0)
530 glyphRange = NSMakeRange (0, nextGlyphIndex);
532 glyphRange = NSMakeRange (glyphIndex,
533 nextGlyphIndex - glyphIndex);
536 rectArrayForGlyphRange:glyphRange
537 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
538 inTextContainer:textContainer rectCount:&nrects];
539 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
540 gl->advance_delta = location.x - totalAdvance;
541 gl->advance = maxX - totalAdvance;
548 if (nextGlyphIndex == numberOfGlyphs)
549 glyphRange = NSMakeRange (prevGlyphIndex,
550 numberOfGlyphs - prevGlyphIndex);
552 glyphRange = NSMakeRange (prevGlyphIndex,
553 glyphIndex + 1 - prevGlyphIndex);
556 rectArrayForGlyphRange:glyphRange
557 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
558 inTextContainer:textContainer rectCount:&nrects];
559 minX = min (NSMinX (glyphRects[0]), totalAdvance);
560 gl->advance = totalAdvance - minX;
562 gl->advance_delta = location.x - totalAdvance;
565 prevGlyphIndex = glyphIndex + 1;
566 glyphIndex = nextGlyphIndex;
572 #undef RIGHT_TO_LEFT_P
576 [textStorage release];
582 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
583 struct mac_glyph_layout *glyph_layouts,
586 return mac_font_shape_1 ([(NSFont *)font printerFont],
588 glyph_layouts, glyph_len);
592 get_cgcolor(unsigned long idx, struct frame *f)
594 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
596 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
597 NSInteger noc = [nsColor numberOfComponents];
598 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
601 [nsColor getComponents: components];
602 cgColor = CGColorCreate (colorSpace, components);
607 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
609 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
610 CGContextSetFillColorWithColor (context, refcol_) ; \
611 CGColorRelease (refcol_); \
613 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
615 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
616 CGContextSetFillColorWithColor (context, refcol_); \
617 CGColorRelease (refcol_); \
619 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
621 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
622 CGContextSetStrokeColorWithColor (context, refcol_); \
623 CGColorRelease (refcol_); \
628 /* Mac font driver. */
634 /* characters to distinguish the charset from the others */
636 /* additional constraint by language */
639 CFCharacterSetRef cf_charset;
640 CFStringRef cf_charset_string;
641 } cf_charset_table[] =
642 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
643 { "iso8859-2", { 0x00A0, 0x010E }},
644 { "iso8859-3", { 0x00A0, 0x0108 }},
645 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
646 { "iso8859-5", { 0x00A0, 0x0401 }},
647 { "iso8859-6", { 0x00A0, 0x060C }},
648 { "iso8859-7", { 0x00A0, 0x0384 }},
649 { "iso8859-8", { 0x00A0, 0x05D0 }},
650 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
651 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
652 { "iso8859-11", { 0x00A0, 0x0E01 }},
653 { "iso8859-13", { 0x00A0, 0x201C }},
654 { "iso8859-14", { 0x00A0, 0x0174 }},
655 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
656 { "iso8859-16", { 0x00A0, 0x0218}},
657 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
658 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
659 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
660 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
661 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
662 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
663 { "cns11643.1992-3", { 0x201A9 }},
664 { "cns11643.1992-4", { 0x20057 }},
665 { "cns11643.1992-5", { 0x20000 }},
666 { "cns11643.1992-6", { 0x20003 }},
667 { "cns11643.1992-7", { 0x20055 }},
668 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
669 { "jisx0212.1990-0", { 0x4E44 }},
670 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
671 { "jisx0213.2000-2", { 0xFA49 }},
672 { "jisx0213.2004-1", { 0x20B9F }},
673 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
674 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
675 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
676 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
677 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
678 { "unicode-sip", { 0x20000 }},
682 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
685 CFStringRef language;
686 CFStringRef font_names[3];
687 } macfont_language_default_font_names[] = {
688 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
689 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
691 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
692 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
694 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
695 CFSTR ("STXihei"), /* 10.4 - 10.5 */
697 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
698 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
704 static CGFloat macfont_antialias_threshold;
707 macfont_update_antialias_threshold (void)
713 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
714 kCFPreferencesCurrentApplication,
717 macfont_antialias_threshold = threshold;
720 static inline Lisp_Object
721 macfont_intern_prop_cfstring (CFStringRef cfstring)
723 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
725 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
728 static inline CFIndex
729 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
740 unichars[0] = (c >> 10) + 0xD800;
741 unichars[1] = (c & 0x3FF) + 0xDC00;
748 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
749 CTFontSymbolicTraits *sym_traits)
753 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
754 OS X 10.6 when the value is greater than or equal to 1 << 31. */
755 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
757 *sym_traits = (CTFontSymbolicTraits) sint64_value;
766 mac_font_descriptor_get_adjusted_weight (CTFontDescriptorRef desc, CGFloat val)
768 long percent_val = lround (val * 100);
770 if (percent_val == -40)
772 CTFontRef font = NULL;
774 CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
778 font = CTFontCreateWithName (name, 0, NULL);
783 CFIndex weight = mac_font_get_weight (font);
785 /* Workaround for crash when displaying Oriya characters
786 with Arial Unicode MS on OS X 10.11. */
797 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
798 Lisp_Object spec_or_entity)
801 CFDictionaryRef dict;
805 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
808 ASET (spec_or_entity, FONT_FAMILY_INDEX,
809 macfont_intern_prop_cfstring (str));
812 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
816 enum font_property_index index;
819 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
821 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
822 {{-0.4, 50}, /* light */
823 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
824 {0, 100}, /* normal */
825 {0.24, 140}, /* (semi-bold + normal) / 2 */
826 {0.4, 200}, /* bold */
827 {CGFLOAT_MAX, CGFLOAT_MAX}},
828 mac_font_descriptor_get_adjusted_weight},
829 {FONT_SLANT_INDEX, kCTFontSlantTrait,
830 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
831 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
832 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
835 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
837 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
838 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
840 CGPoint *point = numeric_traits[i].points;
842 if (numeric_traits[i].adjust_func)
843 floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
844 while (point->x < floatval)
846 if (point == numeric_traits[i].points)
848 else if (point->x == CGFLOAT_MAX)
850 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
851 * ((point->y - (point - 1)->y)
852 / (point->x - (point - 1)->x)));
853 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
854 make_number (lround (floatval)));
858 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
861 CTFontSymbolicTraits sym_traits;
864 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
865 spacing = (sym_traits & kCTFontTraitMonoSpace
866 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
867 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
872 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
873 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
874 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
876 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
882 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
883 CTFontSymbolicTraits synth_sym_traits)
886 CFDictionaryRef dict;
887 CTFontSymbolicTraits sym_traits = 0;
890 entity = font_make_entity ();
892 ASET (entity, FONT_TYPE_INDEX, Qmac_ct);
893 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
895 macfont_store_descriptor_attributes (desc, entity);
897 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
900 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
903 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
906 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
907 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
908 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
909 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
910 font_put_extra (entity, QCfont_entity,
911 make_save_ptr_int ((void *) name, sym_traits));
912 if (synth_sym_traits & kCTFontTraitItalic)
913 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
914 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
915 if (synth_sym_traits & kCTFontTraitBold)
916 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
917 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
918 if (synth_sym_traits & kCTFontTraitMonoSpace)
919 ASET (entity, FONT_SPACING_INDEX,
920 make_number (FONT_SPACING_SYNTHETIC_MONO));
925 /* Cache for font family name symbols vs CFStrings. A value of nil
926 means the cache has been invalidated. Otherwise the value is a Lisp
927 hash table whose keys are symbols and the value for a key is either
928 nil (no corresponding family name) or a Lisp save value wrapping the
929 corresponding family name in CFString. */
931 static Lisp_Object macfont_family_cache;
934 macfont_invalidate_family_cache (void)
936 if (HASH_TABLE_P (macfont_family_cache))
938 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
939 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
941 for (i = 0; i < size; ++i)
942 if (!NILP (HASH_HASH (h, i)))
944 Lisp_Object value = HASH_VALUE (h, i);
946 if (SAVE_VALUEP (value))
947 CFRelease (XSAVE_POINTER (value, 0));
949 macfont_family_cache = Qnil;
954 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
956 if (HASH_TABLE_P (macfont_family_cache))
958 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
959 ptrdiff_t i = hash_lookup (h, symbol, NULL);
963 Lisp_Object value = HASH_VALUE (h, i);
965 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
975 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
977 struct Lisp_Hash_Table *h;
982 if (!HASH_TABLE_P (macfont_family_cache))
983 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
985 h = XHASH_TABLE (macfont_family_cache);
986 i = hash_lookup (h, symbol, &hash);
987 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
990 Lisp_Object old_value = HASH_VALUE (h, i);
992 if (SAVE_VALUEP (old_value))
993 CFRelease (XSAVE_POINTER (old_value, 0));
994 set_hash_value_slot (h, i, value);
997 hash_put (h, symbol, value, hash);
1000 /* Cache of all the available font family names except "LastResort"
1001 and those start with ".". NULL means the cache has been invalidated.
1002 Otherwise, the value is CFArray of CFStrings and the elements are
1003 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1004 Mac OS X 10.6 and later). */
1006 static CFArrayRef macfont_available_families_cache = NULL;
1009 macfont_invalidate_available_families_cache (void)
1011 if (macfont_available_families_cache)
1013 CFRelease (macfont_available_families_cache);
1014 macfont_available_families_cache = NULL;
1019 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1021 CFStringRef name, const void *object,
1022 CFDictionaryRef userInfo)
1024 macfont_invalidate_family_cache ();
1025 macfont_invalidate_available_families_cache ();
1029 macfont_init_font_change_handler (void)
1031 static bool initialized = false;
1037 CFNotificationCenterAddObserver
1038 (CFNotificationCenterGetLocalCenter (), NULL,
1039 macfont_handle_font_change_notification,
1040 kCTFontManagerRegisteredFontsChangedNotification,
1041 NULL, CFNotificationSuspensionBehaviorCoalesce);
1045 macfont_copy_available_families_cache (void)
1047 macfont_init_font_change_handler ();
1049 if (macfont_available_families_cache == NULL)
1050 macfont_available_families_cache = mac_font_create_available_families ();
1052 return (macfont_available_families_cache
1053 ? CFRetain (macfont_available_families_cache) : NULL);
1057 macfont_create_family_with_symbol (Lisp_Object symbol)
1059 CFStringRef result = NULL, family_name;
1060 CFDictionaryRef attributes = NULL;
1061 CTFontDescriptorRef pat_desc = NULL;
1063 if (macfont_get_family_cache_if_present (symbol, &result))
1064 return result ? CFRetain (result) : NULL;
1066 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1070 CFDictionaryCreate (NULL,
1071 (const void **) &kCTFontFamilyNameAttribute,
1072 (const void **) &family_name, 1,
1073 &kCFTypeDictionaryKeyCallBacks,
1074 &kCFTypeDictionaryValueCallBacks);
1075 CFRelease (family_name);
1079 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1080 CFRelease (attributes);
1084 CTFontDescriptorRef desc =
1085 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1090 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1093 macfont_set_family_cache (symbol, result);
1094 CFRelease (pat_desc);
1100 #define WIDTH_FRAC_BITS (4)
1101 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1103 struct macfont_metrics
1105 unsigned char lbearing_low, rbearing_low;
1106 signed lbearing_high : 4, rbearing_high : 4;
1107 unsigned char ascent_low, descent_low;
1108 signed ascent_high : 4, descent_high : 4;
1110 /* These two members are used for fixed-point representation of
1111 glyph width. The `width_int' member is an integer that is
1112 closest to the width. The `width_frac' member is the fractional
1113 adjustment representing a value in [-.5, .5], multiplied by
1114 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1115 the advance delta for centering instead of the glyph width. */
1116 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1119 #define METRICS_VALUE(metrics, member) \
1120 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1121 #define METRICS_SET_VALUE(metrics, member, value) \
1122 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1123 (metrics)->member##_high = tmp >> 8;} while (0)
1127 METRICS_INVALID = -1, /* metrics entry is invalid */
1128 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1131 #define METRICS_STATUS(metrics) \
1132 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1133 #define METRICS_SET_STATUS(metrics, status) \
1134 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1135 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1137 #define METRICS_NCOLS_PER_ROW (128)
1138 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1139 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1142 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1143 struct font_metrics *metrics, CGFloat *advance_delta,
1144 int force_integral_p)
1146 struct macfont_info *macfont_info = (struct macfont_info *) font;
1147 CTFontRef macfont = macfont_info->macfont;
1149 struct macfont_metrics *cache;
1152 row = glyph / METRICS_NCOLS_PER_ROW;
1153 col = glyph % METRICS_NCOLS_PER_ROW;
1154 if (row >= macfont_info->metrics_nrows)
1156 macfont_info->metrics =
1157 xrealloc (macfont_info->metrics,
1158 sizeof (struct macfont_metrics *) * (row + 1));
1159 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1160 (sizeof (struct macfont_metrics *)
1161 * (row + 1 - macfont_info->metrics_nrows)));
1162 macfont_info->metrics_nrows = row + 1;
1164 if (macfont_info->metrics[row] == NULL)
1166 struct macfont_metrics *new;
1169 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1170 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1171 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1172 macfont_info->metrics[row] = new;
1174 cache = macfont_info->metrics[row] + col;
1176 if (METRICS_STATUS (cache) == METRICS_INVALID)
1180 if (macfont_info->screen_font)
1181 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1183 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1185 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1186 advance delta value. */
1187 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1188 fwidth = (font->pixel_size - fwidth) / 2;
1189 cache->width_int = lround (fwidth);
1190 cache->width_frac = lround ((fwidth - cache->width_int)
1191 * WIDTH_FRAC_SCALE);
1192 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1194 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1195 width = font->pixel_size;
1197 width = cache->width_int;
1201 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1203 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1205 if (macfont_info->synthetic_italic_p)
1207 /* We assume the members a, b, c, and d in
1208 synthetic_italic_atfm are non-negative. */
1210 CGPointApplyAffineTransform (bounds.origin,
1211 synthetic_italic_atfm);
1213 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1215 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1217 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1219 bounds = CGRectInset (bounds, d, d);
1221 switch (macfont_info->spacing)
1223 case MACFONT_SPACING_PROPORTIONAL:
1224 bounds.origin.x += - (cache->width_frac
1225 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1227 case MACFONT_SPACING_MONO:
1229 case MACFONT_SPACING_SYNTHETIC_MONO:
1230 bounds.origin.x += (cache->width_int
1231 + (cache->width_frac
1232 / (CGFloat) WIDTH_FRAC_SCALE));
1235 if (bounds.size.width > 0)
1237 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1238 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1239 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1241 bounds = CGRectIntegral (bounds);
1242 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1243 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1244 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1245 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1247 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1248 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1249 metrics->width = width;
1250 metrics->ascent = METRICS_VALUE (cache, ascent);
1251 metrics->descent = METRICS_VALUE (cache, descent);
1256 switch (macfont_info->spacing)
1258 case MACFONT_SPACING_PROPORTIONAL:
1259 *advance_delta = (force_integral_p ? 0
1260 : - (cache->width_frac
1261 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1263 case MACFONT_SPACING_MONO:
1266 case MACFONT_SPACING_SYNTHETIC_MONO:
1267 *advance_delta = (force_integral_p ? cache->width_int
1269 + (cache->width_frac
1270 / (CGFloat) WIDTH_FRAC_SCALE)));
1278 static CFMutableDictionaryRef macfont_cache_dictionary;
1280 /* Threshold used in row_nkeys_or_perm. This must be less than or
1281 equal to the number of rows that are invalid as BMP (i.e., from
1282 U+D800 to U+DFFF). */
1283 #define ROW_PERM_OFFSET (8)
1285 /* The number of glyphs that can be stored in a value for a single
1286 entry of CFDictionary. */
1287 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1289 struct macfont_cache
1291 int reference_count;
1292 CFCharacterSetRef cf_charset;
1294 /* The cached glyph for a BMP character c is stored in
1295 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1296 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1297 unsigned char row_nkeys_or_perm[256];
1300 /* Number of rows for which the BMP cache is allocated so far.
1301 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1304 /* The cached glyph for a character c is stored as the (c %
1305 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1306 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1307 not stored here if row_nkeys_or_perm[c / 256] >=
1309 CFMutableDictionaryRef dictionary;
1313 /* UVS (Unicode Variation Sequence) subtable data, which is of
1314 type CFDataRef if available. NULL means it is not initialized
1315 yet. kCFNull means the subtable is not found and there is no
1316 suitable fallback table for this font. */
1319 /* Character collection specifying the destination of the mapping
1320 provided by `table' above. If `table' is obtained from the UVS
1321 subtable in the font cmap table, then the value of this member
1322 should be NSIdentityMappingCharacterCollection. */
1323 NSCharacterCollection collection;
1327 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1328 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1329 static void macfont_release_cache (struct macfont_cache *);
1330 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1331 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1332 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1333 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1334 NSCharacterCollection, CGFontIndex);
1335 static CFDataRef macfont_get_uvs_table (struct font *, NSCharacterCollection *);
1337 static struct macfont_cache *
1338 macfont_lookup_cache (CFStringRef key)
1340 struct macfont_cache *cache;
1342 if (macfont_cache_dictionary == NULL)
1344 macfont_cache_dictionary =
1345 CFDictionaryCreateMutable (NULL, 0,
1346 &kCFTypeDictionaryKeyCallBacks, NULL);
1350 cache = ((struct macfont_cache *)
1351 CFDictionaryGetValue (macfont_cache_dictionary, key));
1355 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1359 cache = xzalloc (sizeof (struct macfont_cache));
1360 /* Treat the LastResort font as if it contained glyphs for
1361 all characters. This may look too rough, but neither
1362 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1363 for this font is correct for non-BMP characters on Mac OS
1365 if (CFEqual (key, CFSTR ("LastResort")))
1367 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1370 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1372 if (cache->cf_charset == NULL)
1373 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1374 CFDictionaryAddValue (macfont_cache_dictionary, key,
1375 (const void *) cache);
1376 CFRelease (macfont);
1383 static struct macfont_cache *
1384 macfont_retain_cache (struct macfont_cache *cache)
1386 cache->reference_count++;
1392 macfont_release_cache (struct macfont_cache *cache)
1394 if (--cache->reference_count == 0)
1398 for (i = 0; i < cache->glyph.nrows; i++)
1399 xfree (cache->glyph.matrix[i]);
1400 xfree (cache->glyph.matrix);
1401 if (cache->glyph.dictionary)
1402 CFRelease (cache->glyph.dictionary);
1403 memset (&cache->glyph, 0, sizeof (cache->glyph));
1404 if (cache->uvs.table)
1405 CFRelease (cache->uvs.table);
1406 memset (&cache->uvs, 0, sizeof (cache->uvs));
1410 static CFCharacterSetRef
1411 macfont_get_cf_charset (struct font *font)
1413 struct macfont_info *macfont_info = (struct macfont_info *) font;
1415 return macfont_info->cache->cf_charset;
1418 static CFCharacterSetRef
1419 macfont_get_cf_charset_for_name (CFStringRef name)
1421 struct macfont_cache *cache = macfont_lookup_cache (name);
1423 return cache->cf_charset;
1427 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1429 struct macfont_info *macfont_info = (struct macfont_info *) font;
1430 CTFontRef macfont = macfont_info->macfont;
1431 struct macfont_cache *cache = macfont_info->cache;
1433 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1436 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1438 if (nkeys_or_perm < ROW_PERM_OFFSET)
1440 UniChar unichars[256], ch;
1444 dispatch_queue_t queue;
1445 dispatch_group_t group = NULL;
1450 CFMutableDictionaryRef dictionary;
1451 uintptr_t key, value;
1455 if (cache->glyph.dictionary == NULL)
1456 cache->glyph.dictionary =
1457 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1458 dictionary = cache->glyph.dictionary;
1459 key = c / NGLYPHS_IN_VALUE;
1460 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1461 value = ((uintptr_t)
1462 CFDictionaryGetValue (dictionary, (const void *) key));
1463 glyph = (value >> nshifts);
1467 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1470 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1472 glyph = kCGFontIndexInvalid;
1475 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1476 value |= ((uintptr_t) glyph << nshifts);
1477 CFDictionarySetValue (dictionary, (const void *) key,
1478 (const void *) value);
1483 nkeys = nkeys_or_perm;
1484 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1485 if (CFDictionaryContainsKey (dictionary,
1486 (const void *) key))
1488 CFDictionaryRemoveValue (dictionary,
1489 (const void *) key);
1496 for (i = 0; i < 256; i++)
1499 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1500 unichars[len++] = ch;
1503 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1506 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1509 int next = unichars[len - 1] % 256;
1512 glyphs[i] = kCGFontIndexInvalid;
1515 glyphs[i] = glyphs[len];
1522 glyphs[i] = kCGFontIndexInvalid;
1524 nrows = cache->glyph.nrows;
1525 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1526 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1528 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1529 sizeof (CGGlyph *) * nrows);
1530 cache->glyph.matrix[nrows - 1] = glyphs;
1531 cache->glyph.nrows = nrows;
1534 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1538 uintptr_t key, value;
1542 if (cache->glyph.dictionary == NULL)
1543 cache->glyph.dictionary =
1544 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1545 key = c / NGLYPHS_IN_VALUE;
1546 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1547 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1548 (const void *) key);
1549 glyph = (value >> nshifts);
1552 UniChar unichars[2];
1554 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1556 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1559 glyph = kCGFontIndexInvalid;
1561 value |= ((uintptr_t) glyph << nshifts);
1562 CFDictionarySetValue (cache->glyph.dictionary,
1563 (const void *) key, (const void *) value);
1571 macfont_get_glyph_for_cid (struct font *font, NSCharacterCollection collection,
1574 struct macfont_info *macfont_info = (struct macfont_info *) font;
1575 CTFontRef macfont = macfont_info->macfont;
1578 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1582 macfont_get_uvs_table (struct font *font, NSCharacterCollection *collection)
1584 struct macfont_info *macfont_info = (struct macfont_info *) font;
1585 CTFontRef macfont = macfont_info->macfont;
1586 struct macfont_cache *cache = macfont_info->cache;
1587 CFDataRef result = NULL;
1589 if (cache->uvs.table == NULL)
1591 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1592 NSCharacterCollection uvs_collection =
1593 NSIdentityMappingCharacterCollection;
1595 if (uvs_table == NULL
1596 && mac_font_get_glyph_for_cid (macfont,
1597 NSAdobeJapan1CharacterCollection,
1598 6480) != kCGFontIndexInvalid)
1600 /* If the glyph for U+4E55 is accessible via its CID 6480,
1601 then we use the Adobe-Japan1 UVS table, which maps a
1602 variation sequence to a CID, as a fallback. */
1603 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1605 if (mac_uvs_table_adobe_japan1 == NULL)
1606 mac_uvs_table_adobe_japan1 =
1607 CFDataCreateWithBytesNoCopy (NULL,
1608 mac_uvs_table_adobe_japan1_bytes,
1609 sizeof (mac_uvs_table_adobe_japan1_bytes),
1611 if (mac_uvs_table_adobe_japan1)
1613 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1614 uvs_collection = NSAdobeJapan1CharacterCollection;
1617 if (uvs_table == NULL)
1618 cache->uvs.table = kCFNull;
1620 cache->uvs.table = uvs_table;
1621 cache->uvs.collection = uvs_collection;
1624 if (cache->uvs.table != kCFNull)
1626 result = cache->uvs.table;
1627 *collection = cache->uvs.collection;
1633 static Lisp_Object macfont_get_cache (struct frame *);
1634 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1635 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1636 static Lisp_Object macfont_list_family (struct frame *);
1637 static void macfont_free_entity (Lisp_Object);
1638 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1639 static void macfont_close (struct font *);
1640 static int macfont_has_char (Lisp_Object, int);
1641 static unsigned macfont_encode_char (struct font *, int);
1642 static void macfont_text_extents (struct font *, unsigned int *, int,
1643 struct font_metrics *);
1644 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1645 static Lisp_Object macfont_shape (Lisp_Object);
1646 static int macfont_variation_glyphs (struct font *, int c,
1647 unsigned variations[256]);
1648 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1650 static struct font_driver const macfont_driver =
1652 .type = LISPSYM_INITIALLY (Qmac_ct),
1653 .get_cache = macfont_get_cache,
1654 .list = macfont_list,
1655 .match = macfont_match,
1656 .list_family = macfont_list_family,
1657 .free_entity = macfont_free_entity,
1658 .open = macfont_open,
1659 .close = macfont_close,
1660 .has_char = macfont_has_char,
1661 .encode_char = macfont_encode_char,
1662 .text_extents = macfont_text_extents,
1663 .draw = macfont_draw,
1664 .shape = macfont_shape,
1665 .get_variation_glyphs = macfont_variation_glyphs,
1666 .filter_properties = macfont_filter_properties,
1670 macfont_get_cache (struct frame * f)
1672 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1674 return (dpyinfo->name_list_element);
1678 macfont_get_charset (Lisp_Object registry)
1680 char *str = SSDATA (SYMBOL_NAME (registry));
1681 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1685 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1689 else if (str[i] == '*')
1696 regexp = make_unibyte_string (re, j);
1697 for (i = 0; cf_charset_table[i].name; i++)
1698 if (fast_c_string_match_ignore_case
1699 (regexp, cf_charset_table[i].name,
1700 strlen (cf_charset_table[i].name)) >= 0)
1702 if (! cf_charset_table[i].name)
1704 if (! cf_charset_table[i].cf_charset)
1706 int *uniquifier = cf_charset_table[i].uniquifier;
1707 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1710 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1714 for (j = 0; uniquifier[j]; j++)
1716 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1718 CFCharacterSetAddCharactersInRange (charset,
1719 CFRangeMake (uniquifier[j], 1));
1722 string = CFStringCreateWithCharacters (NULL, unichars, count);
1725 CFRelease (charset);
1728 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1730 CFRelease (charset);
1731 /* CFCharacterSetCreateWithCharactersInString does not handle
1732 surrogate pairs properly as of Mac OS X 10.5. */
1733 cf_charset_table[i].cf_charset_string = string;
1741 unsigned int script_tag, langsys_tag;
1743 unsigned int *features[2];
1746 #define OTF_SYM_TAG(SYM, TAG) \
1748 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1749 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1752 #define OTF_TAG_STR(TAG, P) \
1754 (P)[0] = (char) (TAG >> 24); \
1755 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1756 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1757 (P)[3] = (char) (TAG & 0xFF); \
1761 static struct OpenTypeSpec *
1762 macfont_get_open_type_spec (Lisp_Object otf_spec)
1764 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1771 spec->script = XCAR (otf_spec);
1772 if (! NILP (spec->script))
1774 OTF_SYM_TAG (spec->script, spec->script_tag);
1775 val = assq_no_quit (spec->script, Votf_script_alist);
1776 if (CONSP (val) && SYMBOLP (XCDR (val)))
1777 spec->script = XCDR (val);
1779 spec->script = Qnil;
1782 spec->script_tag = 0x44464C54; /* "DFLT" */
1783 otf_spec = XCDR (otf_spec);
1784 spec->langsys_tag = 0;
1785 if (! NILP (otf_spec))
1787 val = XCAR (otf_spec);
1789 OTF_SYM_TAG (val, spec->langsys_tag);
1790 otf_spec = XCDR (otf_spec);
1792 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1793 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1797 val = XCAR (otf_spec);
1800 len = Flength (val);
1802 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1804 : malloc (XINT (len) * sizeof *spec->features[i]));
1805 if (! spec->features[i])
1807 if (i > 0 && spec->features[0])
1808 free (spec->features[0]);
1812 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1814 if (NILP (XCAR (val)))
1820 OTF_SYM_TAG (XCAR (val), tag);
1821 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1824 spec->nfeatures[i] = j;
1829 static CFMutableDictionaryRef
1830 macfont_create_attributes_with_spec (Lisp_Object spec)
1832 Lisp_Object tmp, extra;
1833 CFMutableArrayRef langarray = NULL;
1834 CFCharacterSetRef charset = NULL;
1835 CFStringRef charset_string = NULL;
1836 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1837 Lisp_Object script = Qnil;
1838 Lisp_Object registry;
1839 int cf_charset_idx, i;
1840 struct OpenTypeSpec *otspec = NULL;
1842 enum font_property_index index;
1845 } numeric_traits[] =
1846 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1847 {{-0.4, 50}, /* light */
1848 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1849 {0, 100}, /* normal */
1850 {0.24, 140}, /* (semi-bold + normal) / 2 */
1851 {0.4, 200}, /* bold */
1852 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1853 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1854 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1855 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1856 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1858 registry = AREF (spec, FONT_REGISTRY_INDEX);
1860 || EQ (registry, Qascii_0)
1861 || EQ (registry, Qiso10646_1)
1862 || EQ (registry, Qunicode_bmp))
1863 cf_charset_idx = -1;
1868 cf_charset_idx = macfont_get_charset (registry);
1869 if (cf_charset_idx < 0)
1871 charset = cf_charset_table[cf_charset_idx].cf_charset;
1872 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1873 lang = cf_charset_table[cf_charset_idx].lang;
1876 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1879 CFArrayAppendValue (langarray, lang);
1883 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1884 CONSP (extra); extra = XCDR (extra))
1886 Lisp_Object key, val;
1889 key = XCAR (tmp), val = XCDR (tmp);
1890 if (EQ (key, QClang))
1893 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1898 for (; CONSP (val); val = XCDR (val))
1899 if (SYMBOLP (XCAR (val)))
1902 cfstring_create_with_string_noencode (SYMBOL_NAME
1907 CFArrayAppendValue (langarray, lang);
1911 else if (EQ (key, QCotf))
1913 otspec = macfont_get_open_type_spec (val);
1916 script = otspec->script;
1918 else if (EQ (key, QCscript))
1922 if (! NILP (script) && ! charset)
1924 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1926 if (CONSP (chars) && CONSP (CDR (chars)))
1928 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1929 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1931 if (! string || !cs)
1939 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1940 if (CHARACTERP (XCAR (chars)))
1942 UniChar unichars[2];
1944 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1946 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1948 CFStringAppendCharacters (string, unichars, count);
1949 CFCharacterSetAddCharactersInRange (cs, range);
1952 /* CFCharacterSetCreateWithCharactersInString does not
1953 handle surrogate pairs properly as of Mac OS X 10.5. */
1954 charset_string = string;
1958 attributes = CFDictionaryCreateMutable (NULL, 0,
1959 &kCFTypeDictionaryKeyCallBacks,
1960 &kCFTypeDictionaryValueCallBacks);
1964 tmp = AREF (spec, FONT_FAMILY_INDEX);
1965 if (SYMBOLP (tmp) && ! NILP (tmp))
1967 CFStringRef family = macfont_create_family_with_symbol (tmp);
1971 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
1976 traits = CFDictionaryCreateMutable (NULL, 4,
1977 &kCFTypeDictionaryKeyCallBacks,
1978 &kCFTypeDictionaryValueCallBacks);
1982 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1984 tmp = AREF (spec, numeric_traits[i].index);
1987 CGPoint *point = numeric_traits[i].points;
1988 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1991 while (point->y < floatval)
1993 if (point == numeric_traits[i].points)
1995 else if (point->y == CGFLOAT_MAX)
1997 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1998 * ((point->x - (point - 1)->x)
1999 / (point->y - (point - 1)->y)));
2002 else if (floatval < -1.0)
2004 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2007 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2011 if (CFDictionaryGetCount (traits))
2012 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2015 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2018 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2021 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2028 CFRelease (attributes);
2033 if (langarray) CFRelease (langarray);
2034 if (charset && cf_charset_idx < 0) CFRelease (charset);
2035 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2036 if (traits) CFRelease (traits);
2039 if (otspec->nfeatures[0] > 0)
2040 free (otspec->features[0]);
2041 if (otspec->nfeatures[1] > 0)
2042 free (otspec->features[1]);
2050 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2051 CFCharacterSetRef charset,
2053 CFArrayRef languages)
2055 Boolean result = true;
2057 if (charset || VECTORP (chars))
2059 CFCharacterSetRef desc_charset =
2060 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2062 if (desc_charset == NULL)
2067 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2068 else /* VECTORP (chars) */
2072 for (j = 0; j < ASIZE (chars); j++)
2073 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2074 && CFCharacterSetIsLongCharacterMember (desc_charset,
2075 XFASTINT (AREF (chars, j))))
2077 if (j == ASIZE (chars))
2080 CFRelease (desc_charset);
2083 if (result && languages)
2084 result = mac_font_descriptor_supports_languages (desc, languages);
2090 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2091 CTFontSymbolicTraits sym_traits2)
2093 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2096 /* We prefer synthetic bold of italic to synthetic italic of bold
2097 when both bold and italic are available but bold-italic is not
2099 if (diff & kCTFontTraitBold)
2100 distance |= (1 << 0);
2101 if (diff & kCTFontTraitItalic)
2102 distance |= (1 << 1);
2103 if (diff & kCTFontTraitMonoSpace)
2104 distance |= (1 << 2);
2110 macfont_closest_traits_index_p (CFArrayRef traits_array,
2111 CTFontSymbolicTraits target,
2114 CFIndex i, count = CFArrayGetCount (traits_array);
2115 CTFontSymbolicTraits traits;
2118 traits = ((CTFontSymbolicTraits) (uintptr_t)
2119 CFArrayGetValueAtIndex (traits_array, index));
2120 my_distance = macfont_traits_distance (target, traits);
2122 for (i = 0; i < count; i++)
2125 traits = ((CTFontSymbolicTraits) (uintptr_t)
2126 CFArrayGetValueAtIndex (traits_array, i));
2127 if (macfont_traits_distance (target, traits) < my_distance)
2135 macfont_list (struct frame *f, Lisp_Object spec)
2137 Lisp_Object val = Qnil, family, extra;
2139 CFStringRef family_name = NULL;
2140 CFMutableDictionaryRef attributes = NULL, traits;
2141 Lisp_Object chars = Qnil;
2143 CTFontSymbolicTraits synth_sym_traits = 0;
2144 CFArrayRef families;
2145 CFIndex families_count;
2146 CFCharacterSetRef charset = NULL;
2147 CFArrayRef languages = NULL;
2151 family = AREF (spec, FONT_FAMILY_INDEX);
2152 if (! NILP (family))
2154 family_name = macfont_create_family_with_symbol (family);
2155 if (family_name == NULL)
2159 attributes = macfont_create_attributes_with_spec (spec);
2163 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2165 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2166 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2168 traits = ((CFMutableDictionaryRef)
2169 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2171 n = FONT_SLANT_NUMERIC (spec);
2172 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2174 synth_sym_traits |= kCTFontTraitItalic;
2176 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2179 n = FONT_WEIGHT_NUMERIC (spec);
2180 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2182 synth_sym_traits |= kCTFontTraitBold;
2184 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2188 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2190 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2192 if (CFStringHasPrefix (language, CFSTR ("ja"))
2193 || CFStringHasPrefix (language, CFSTR ("ko"))
2194 || CFStringHasPrefix (language, CFSTR ("zh")))
2195 synth_sym_traits |= kCTFontTraitMonoSpace;
2198 /* Create array of families. */
2200 families = CFArrayCreate (NULL, (const void **) &family_name,
2201 1, &kCFTypeArrayCallBacks);
2204 CFStringRef pref_family;
2205 CFIndex families_count, pref_family_index = -1;
2207 families = macfont_copy_available_families_cache ();
2208 if (families == NULL)
2211 families_count = CFArrayGetCount (families);
2213 /* Move preferred family to the front if exists. */
2215 mac_font_create_preferred_family_for_attributes (attributes);
2219 CFArrayGetFirstIndexOfValue (families,
2220 CFRangeMake (0, families_count),
2222 CFRelease (pref_family);
2224 if (pref_family_index > 0)
2226 CFMutableArrayRef mutable_families =
2227 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2229 if (mutable_families)
2231 CFArrayAppendValue (mutable_families,
2232 CFArrayGetValueAtIndex (families,
2233 pref_family_index));
2234 CFArrayAppendArray (mutable_families, families,
2235 CFRangeMake (0, pref_family_index));
2236 if (pref_family_index + 1 < families_count)
2237 CFArrayAppendArray (mutable_families, families,
2238 CFRangeMake (pref_family_index + 1,
2240 - (pref_family_index + 1)));
2241 CFRelease (families);
2242 families = mutable_families;
2247 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2251 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2255 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2258 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2259 if (CONSP (val) && VECTORP (XCDR (val)))
2267 CFRetain (languages);
2268 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2272 extra = AREF (spec, FONT_EXTRA_INDEX);
2273 families_count = CFArrayGetCount (families);
2274 for (i = 0; i < families_count; i++)
2276 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2277 CTFontDescriptorRef pat_desc;
2279 CFIndex descs_count;
2280 CFMutableArrayRef filtered_descs, traits_array;
2284 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2286 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2290 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2291 10.7 returns NULL if pat_desc represents the LastResort font.
2292 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2293 trailing "s") for such a font. */
2294 if (!CFEqual (family_name, CFSTR ("LastResort")))
2295 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2298 CTFontDescriptorRef lr_desc =
2299 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2302 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2303 &kCFTypeArrayCallBacks);
2304 CFRelease (lr_desc);
2309 CFRelease (pat_desc);
2313 descs_count = CFArrayGetCount (descs);
2314 if (descs_count == 0
2315 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2324 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2325 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2326 for (j = 0; j < descs_count; j++)
2328 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2329 CFDictionaryRef dict;
2331 CTFontSymbolicTraits sym_traits;
2333 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2337 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2340 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2344 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2345 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2346 != (spacing >= FONT_SPACING_MONO)))
2349 /* Don't use a color bitmap font until it is supported on
2351 if (sym_traits & kCTFontTraitColorGlyphs)
2355 && !macfont_supports_charset_and_languages_p (desc, charset,
2359 CFArrayAppendValue (filtered_descs, desc);
2360 CFArrayAppendValue (traits_array,
2361 (const void *) (uintptr_t) sym_traits);
2365 descs = filtered_descs;
2366 descs_count = CFArrayGetCount (descs);
2368 for (j = 0; j < descs_count; j++)
2370 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2371 CTFontSymbolicTraits sym_traits =
2372 ((CTFontSymbolicTraits) (uintptr_t)
2373 CFArrayGetValueAtIndex (traits_array, j));
2374 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2376 mask_min = ((synth_sym_traits ^ sym_traits)
2377 & (kCTFontTraitItalic | kCTFontTraitBold));
2378 if (FONT_SLANT_NUMERIC (spec) < 0)
2379 mask_min &= ~kCTFontTraitItalic;
2380 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2381 mask_min &= ~kCTFontTraitBold;
2383 mask_max = (synth_sym_traits & ~sym_traits);
2384 /* Synthetic bold does not work for bitmap-only fonts on Mac
2386 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2388 CFNumberRef format =
2389 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2393 uint32_t format_val;
2395 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2397 && format_val == kCTFontFormatBitmap)
2398 mask_max &= ~kCTFontTraitBold;
2402 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2404 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2405 mmask <= (mask_max & kCTFontTraitMonoSpace);
2406 mmask += kCTFontTraitMonoSpace)
2407 for (bmask = (mask_min & kCTFontTraitBold);
2408 bmask <= (mask_max & kCTFontTraitBold);
2409 bmask += kCTFontTraitBold)
2410 for (imask = (mask_min & kCTFontTraitItalic);
2411 imask <= (mask_max & kCTFontTraitItalic);
2412 imask += kCTFontTraitItalic)
2414 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2417 || macfont_closest_traits_index_p (traits_array,
2418 (sym_traits | synth),
2421 entity = macfont_descriptor_entity (desc, extra, synth);
2422 if (! NILP (entity))
2423 val = Fcons (entity, val);
2428 CFRelease (traits_array);
2432 CFRelease (families);
2433 val = Fnreverse (val);
2439 FONT_ADD_LOG ("macfont-list", spec, val);
2440 if (charset) CFRelease (charset);
2441 if (languages) CFRelease (languages);
2442 if (attributes) CFRelease (attributes);
2443 if (family_name) CFRelease (family_name);
2451 macfont_match (struct frame * frame, Lisp_Object spec)
2453 Lisp_Object entity = Qnil;
2454 CFMutableDictionaryRef attributes;
2455 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2459 attributes = macfont_create_attributes_with_spec (spec);
2462 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2463 CFRelease (attributes);
2467 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2468 CFRelease (pat_desc);
2472 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2478 FONT_ADD_LOG ("macfont-match", spec, entity);
2483 macfont_list_family (struct frame *frame)
2485 Lisp_Object list = Qnil;
2486 CFArrayRef families;
2490 families = macfont_copy_available_families_cache ();
2493 CFIndex i, count = CFArrayGetCount (families);
2495 for (i = 0; i < count; i++)
2496 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2497 CFRelease (families);
2506 macfont_free_entity (Lisp_Object entity)
2508 Lisp_Object val = assq_no_quit (QCfont_entity,
2509 AREF (entity, FONT_EXTRA_INDEX));
2510 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2518 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2520 Lisp_Object val, font_object;
2521 CFStringRef font_name;
2522 struct macfont_info *macfont_info = NULL;
2526 CTFontSymbolicTraits sym_traits;
2529 CGFloat ascent, descent, leading;
2531 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2533 || XTYPE (XCDR (val)) != Lisp_Misc
2534 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2536 font_name = XSAVE_POINTER (XCDR (val), 0);
2537 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2539 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2544 macfont = CTFontCreateWithName (font_name, size, NULL);
2547 int fontsize = (int) [((NSFont *) macfont) pointSize];
2548 if (fontsize != size) size = fontsize;
2554 font_object = font_build_object (VECSIZE (struct macfont_info),
2555 Qmac_ct, entity, size);
2556 font = XFONT_OBJECT (font_object);
2557 font->pixel_size = size;
2558 font->driver = &macfont_driver;
2559 font->encoding_charset = font->repertory_charset = -1;
2563 macfont_info = (struct macfont_info *) font;
2564 macfont_info->macfont = macfont;
2565 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2567 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2568 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2569 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2572 macfont_info->screen_font = NULL;
2573 macfont_info->cache = macfont_lookup_cache (font_name);
2574 macfont_retain_cache (macfont_info->cache);
2575 macfont_info->metrics = NULL;
2576 macfont_info->metrics_nrows = 0;
2577 macfont_info->synthetic_italic_p = 0;
2578 macfont_info->synthetic_bold_p = 0;
2579 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2580 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2581 if (!(sym_traits & kCTFontTraitItalic)
2582 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2583 macfont_info->synthetic_italic_p = 1;
2584 if (!(sym_traits & kCTFontTraitBold)
2585 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2586 macfont_info->synthetic_bold_p = 1;
2587 if (sym_traits & kCTFontTraitMonoSpace)
2588 macfont_info->spacing = MACFONT_SPACING_MONO;
2589 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2590 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2591 == FONT_SPACING_SYNTHETIC_MONO))
2592 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2593 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2594 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2597 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2599 macfont_info->antialias =
2600 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2602 macfont_info->color_bitmap_p = 0;
2603 if (sym_traits & kCTFontTraitColorGlyphs)
2604 macfont_info->color_bitmap_p = 1;
2606 glyph = macfont_get_glyph_for_character (font, ' ');
2607 if (glyph != kCGFontIndexInvalid)
2608 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2610 /* dirty workaround */
2611 font->space_width = pixel_size;
2613 total_width = font->space_width;
2614 for (i = 1; i < 95; i++)
2616 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2617 if (glyph == kCGFontIndexInvalid)
2619 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2622 font->average_width = total_width / 95;
2624 font->average_width = font->space_width; /* XXX */
2626 if (!(macfont_info->screen_font
2627 && mac_screen_font_get_metrics (macfont_info->screen_font,
2628 &ascent, &descent, &leading)))
2630 CFStringRef family_name;
2632 ascent = CTFontGetAscent (macfont);
2633 descent = CTFontGetDescent (macfont);
2634 leading = CTFontGetLeading (macfont);
2635 /* AppKit and WebKit do some adjustment to the heights of
2636 Courier, Helvetica, and Times. */
2637 family_name = CTFontCopyFamilyName (macfont);
2640 if (CFEqual (family_name, CFSTR ("Courier"))
2641 || CFEqual (family_name, CFSTR ("Helvetica"))
2642 || CFEqual (family_name, CFSTR ("Times")))
2643 ascent += (ascent + descent) * .15f;
2644 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2649 CFRelease (family_name);
2652 font->ascent = ascent + 0.5f;
2653 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2654 if (CONSP (val) && !NILP (XCDR (val)))
2655 font->descent = descent + 0.5f;
2657 font->descent = descent + leading + 0.5f;
2658 font->height = font->ascent + font->descent;
2660 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2661 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2665 /* Unfortunately Xft doesn't provide a way to get minimum char
2666 width. So, we use space_width instead. */
2667 font->min_width = font->max_width = font->space_width; /* XXX */
2669 font->baseline_offset = 0;
2670 font->relative_compose = 0;
2671 font->default_ascent = 0;
2672 font->vertical_centering = 0;
2678 macfont_close (struct font *font)
2680 struct macfont_info *macfont_info = (struct macfont_info *) font;
2682 if (macfont_info->cache)
2687 CFRelease (macfont_info->macfont);
2688 CGFontRelease (macfont_info->cgfont);
2689 if (macfont_info->screen_font)
2690 CFRelease (macfont_info->screen_font);
2691 macfont_release_cache (macfont_info->cache);
2692 for (i = 0; i < macfont_info->metrics_nrows; i++)
2693 if (macfont_info->metrics[i])
2694 xfree (macfont_info->metrics[i]);
2695 if (macfont_info->metrics)
2696 xfree (macfont_info->metrics);
2697 macfont_info->cache = NULL;
2703 macfont_has_char (Lisp_Object font, int c)
2706 CFCharacterSetRef charset;
2709 if (FONT_ENTITY_P (font))
2714 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2716 name = XSAVE_POINTER (val, 0);
2717 charset = macfont_get_cf_charset_for_name (name);
2720 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2722 result = CFCharacterSetIsLongCharacterMember (charset, c);
2729 macfont_encode_char (struct font *font, int c)
2734 glyph = macfont_get_glyph_for_character (font, c);
2737 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2741 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2742 struct font_metrics *metrics)
2747 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2748 for (i = 1; i < nglyphs; i++)
2750 struct font_metrics m;
2751 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2756 if (width + m.lbearing < metrics->lbearing)
2757 metrics->lbearing = width + m.lbearing;
2758 if (width + m.rbearing > metrics->rbearing)
2759 metrics->rbearing = width + m.rbearing;
2760 if (m.ascent > metrics->ascent)
2761 metrics->ascent = m.ascent;
2762 if (m.descent > metrics->descent)
2763 metrics->descent = m.descent;
2770 metrics->width = width;
2774 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2775 bool with_background)
2777 struct frame * f = s->f;
2778 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2779 CGRect background_rect;
2780 CGPoint text_position;
2783 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2784 bool no_antialias_p =
2785 (NILP (ns_antialias_text)
2786 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2787 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2788 && font_size <= macfont_antialias_threshold));
2789 int len = to - from;
2790 struct face *face = s->face;
2791 CGContextRef context;
2795 if (with_background)
2796 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2797 s->width, FONT_HEIGHT (s->font));
2799 background_rect = CGRectNull;
2801 text_position = CGPointMake (x, -y);
2802 glyphs = xmalloc (sizeof (CGGlyph) * len);
2804 CGFloat advance_delta = 0;
2806 CGFloat total_width = 0;
2808 positions = xmalloc (sizeof (CGPoint) * len);
2809 for (i = 0; i < len; i++)
2813 glyphs[i] = s->char2b[from + i];
2814 width = (s->padding_p ? 1
2815 : macfont_glyph_extents (s->font, glyphs[i],
2816 NULL, &advance_delta,
2818 positions[i].x = total_width + advance_delta;
2820 total_width += width;
2824 context = [[NSGraphicsContext currentContext] graphicsPort];
2825 CGContextSaveGState (context);
2827 if (!CGRectIsNull (background_rect))
2829 if (s->hl == DRAW_MOUSE_FACE)
2831 face = FACE_FROM_ID_OR_NULL (s->f,
2832 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2834 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2836 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2837 CGContextFillRects (context, &background_rect, 1);
2840 if (macfont_info->cgfont)
2842 CGAffineTransform atfm;
2844 CGContextScaleCTM (context, 1, -1);
2845 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2846 if (macfont_info->synthetic_italic_p)
2847 atfm = synthetic_italic_atfm;
2849 atfm = CGAffineTransformIdentity;
2850 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2852 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2854 /* Stroke line width for text drawing is not correctly
2855 scaled on Retina display/HiDPI mode when drawn to screen
2856 (whereas it is correctly scaled when drawn to bitmaps),
2857 and synthetic bold looks thinner on such environments.
2858 Apple says there are no plans to address this issue
2859 (rdar://11644870) currently. So we add a workaround. */
2860 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2861 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2862 if ([[FRAME_NS_VIEW(f) window] respondsToSelector:
2863 @selector(backingScaleFactor)])
2865 CGContextSetLineWidth (context, synthetic_bold_factor * font_size
2866 * [[FRAME_NS_VIEW(f) window] backingScaleFactor]);
2867 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2871 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2872 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2874 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2877 CGContextSetShouldAntialias (context, false);
2879 if (!NILP (ns_use_thin_smoothing))
2881 CGContextSetShouldSmoothFonts(context, YES);
2882 CGContextSetFontSmoothingStyle(context, 16);
2885 CGContextSetTextMatrix (context, atfm);
2886 CGContextSetTextPosition (context, text_position.x, text_position.y);
2888 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2889 if (macfont_info->color_bitmap_p
2890 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2891 && CTFontDrawGlyphs != NULL
2897 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2902 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2904 CGContextSetFont (context, macfont_info->cgfont);
2905 CGContextSetFontSize (context, font_size);
2906 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2913 CGContextRestoreGState (context);
2921 macfont_shape (Lisp_Object lgstring)
2923 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2924 struct macfont_info *macfont_info = (struct macfont_info *) font;
2925 CTFontRef macfont = macfont_info->macfont;
2926 ptrdiff_t glyph_len, len, i, j;
2929 CFIndex *nonbmp_indices;
2932 struct mac_glyph_layout *glyph_layouts;
2934 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2936 for (i = 0; i < glyph_len; i++)
2938 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2942 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2948 if (INT_MAX / 2 < len)
2949 memory_full (SIZE_MAX);
2951 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2952 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2953 for (i = j = 0; i < len; i++)
2955 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2957 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2959 nonbmp_indices[j] = i + j;
2963 nonbmp_indices[j] = len + j; /* sentinel */
2967 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2971 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2972 if (macfont_info->screen_font)
2973 used = mac_screen_font_shape (macfont_info->screen_font, string,
2974 glyph_layouts, glyph_len);
2976 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2987 for (i = 0; i < used; i++)
2989 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2990 struct mac_glyph_layout *gl = glyph_layouts + i;
2992 struct font_metrics metrics;
2993 int xoff, yoff, wadjust;
2997 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2998 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
3001 from = gl->comp_range.location;
3002 /* Convert UTF-16 index to UTF-32. */
3004 while (nonbmp_indices[j] < from)
3007 LGLYPH_SET_FROM (lglyph, from);
3009 to = gl->comp_range.location + gl->comp_range.length;
3010 /* Convert UTF-16 index to UTF-32. */
3011 while (nonbmp_indices[j] < to)
3014 LGLYPH_SET_TO (lglyph, to - 1);
3016 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3017 the composition is trivial. */
3021 if (unichars[gl->string_index] >= 0xD800
3022 && unichars[gl->string_index] < 0xDC00)
3023 c = (((unichars[gl->string_index] - 0xD800) << 10)
3024 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3026 c = unichars[gl->string_index];
3027 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3029 LGLYPH_SET_CHAR (lglyph, c);
3033 unsigned long cc = gl->glyph_id;
3034 LGLYPH_SET_CODE (lglyph, cc);
3037 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3038 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3039 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3040 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3041 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3042 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3044 xoff = lround (gl->advance_delta);
3045 yoff = lround (- gl->baseline_delta);
3046 wadjust = lround (gl->advance);
3047 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3051 vec = Fmake_vector (make_number (3), Qnil);
3052 ASET (vec, 0, make_number (xoff));
3053 ASET (vec, 1, make_number (yoff));
3054 ASET (vec, 2, make_number (wadjust));
3055 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3061 return make_number (used);
3064 /* Structures for the UVS subtable (format 14) in the cmap table. */
3065 typedef UInt8 UINT24[3];
3067 #pragma pack(push, 1)
3068 struct variation_selector_record
3070 UINT24 var_selector;
3071 UInt32 default_uvs_offset, non_default_uvs_offset;
3076 UInt32 length, num_var_selector_records;
3077 struct variation_selector_record variation_selector_records[1];
3079 #define SIZEOF_UVS_TABLE_HEADER \
3080 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3082 struct unicode_value_range
3084 UINT24 start_unicode_value;
3085 UInt8 additional_count;
3087 struct default_uvs_table {
3088 UInt32 num_unicode_value_ranges;
3089 struct unicode_value_range unicode_value_ranges[1];
3091 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3092 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3096 UINT24 unicode_value;
3099 struct non_default_uvs_table
3101 UInt32 num_uvs_mappings;
3102 struct uvs_mapping uvs_mappings[1];
3104 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3105 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3108 /* Read big endian values. The argument LVAL must be an lvalue. */
3109 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3110 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3111 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3112 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3113 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3114 /* Succeeding one byte should also be accessible. */
3115 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3116 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3118 /* Return UVS subtable for the specified FONT. If the subtable is not
3119 found or ill-formatted, then return NULL. */
3122 mac_font_copy_uvs_table (CTFontRef font)
3124 CFDataRef cmap_table, uvs_table = NULL;
3126 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3127 kCTFontTableOptionNoOptions);
3130 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3131 struct uvs_table *uvs;
3132 struct variation_selector_record *records;
3133 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3136 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3140 cmap_len = CFDataGetLength (cmap_table);
3141 if (sizeof_sfntCMapHeader > cmap_len)
3144 ntables = BUINT16_VALUE (cmap->numTables);
3145 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3146 / sizeof_sfntCMapEncoding))
3149 for (i = 0; i < ntables; i++)
3150 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3151 == kFontUnicodePlatform)
3152 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3153 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3155 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3159 || uvs_offset > cmap_len
3160 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3163 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3164 uvs_len = BUINT32_VALUE (uvs->length);
3165 if (uvs_len > cmap_len - uvs_offset
3166 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3169 if (BUINT16_VALUE (uvs->format) != 14)
3172 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3173 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3174 / sizeof (struct variation_selector_record)))
3177 records = uvs->variation_selector_records;
3178 for (i = 0; i < nrecords; i++)
3180 UInt32 default_uvs_offset, non_default_uvs_offset;
3182 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3183 if (default_uvs_offset)
3185 struct default_uvs_table *default_uvs;
3188 if (default_uvs_offset > uvs_len
3189 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3190 > uvs_len - default_uvs_offset))
3193 default_uvs = ((struct default_uvs_table *)
3194 ((UInt8 *) uvs + default_uvs_offset));
3195 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3196 if (nranges > ((uvs_len - default_uvs_offset
3197 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3198 / sizeof (struct unicode_value_range)))
3200 /* Now 2 * nranges can't overflow, so we can safely use
3201 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3202 mac_font_get_glyphs_for_variants. */
3205 non_default_uvs_offset =
3206 BUINT32_VALUE (records[i].non_default_uvs_offset);
3207 if (non_default_uvs_offset)
3209 struct non_default_uvs_table *non_default_uvs;
3212 if (non_default_uvs_offset > uvs_len
3213 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3214 > uvs_len - non_default_uvs_offset))
3217 non_default_uvs = ((struct non_default_uvs_table *)
3218 ((UInt8 *) uvs + non_default_uvs_offset));
3219 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3220 if (nmappings > ((uvs_len - non_default_uvs_offset
3221 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3222 / sizeof (struct uvs_mapping)))
3224 /* Now 2 * nmappings can't overflow, so we can safely
3225 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3226 in mac_font_get_glyphs_for_variants. */
3230 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3233 CFRelease (cmap_table);
3239 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3240 sequence consisting of the given base character C and each
3241 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3242 result (explained below) into the corresponding GLYPHS[i]. If the
3243 entry is found in the Default UVS Table, then the result is 0. If
3244 the entry is found in the Non-Default UVS Table, then the result is
3245 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3246 elements in SELECTORS must be sorted in strictly increasing
3250 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3251 const UTF32Char selectors[], CGGlyph glyphs[],
3254 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3255 struct variation_selector_record *records = uvs->variation_selector_records;
3257 UInt32 ir, nrecords;
3259 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3262 while (i < count && ir < nrecords)
3264 UInt32 default_uvs_offset, non_default_uvs_offset;
3266 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3268 glyphs[i++] = kCGFontIndexInvalid;
3271 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3277 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3278 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3279 non_default_uvs_offset =
3280 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3282 glyphs[i] = kCGFontIndexInvalid;
3284 if (default_uvs_offset)
3286 struct default_uvs_table *default_uvs =
3287 (struct default_uvs_table *) ((UInt8 *) uvs
3288 + default_uvs_offset);
3289 struct unicode_value_range *ranges =
3290 default_uvs->unicode_value_ranges;
3294 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3297 UInt32 mid = (lo + hi) / 2;
3299 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3305 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3306 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3310 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3312 struct non_default_uvs_table *non_default_uvs =
3313 (struct non_default_uvs_table *) ((UInt8 *) uvs
3314 + non_default_uvs_offset);
3315 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3319 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3322 UInt32 mid = (lo + hi) / 2;
3324 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3330 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3331 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3337 glyphs[i++] = kCGFontIndexInvalid;
3341 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3343 CFDataRef uvs_table;
3344 NSCharacterCollection uvs_collection;
3348 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3352 UTF32Char selectors[256];
3353 CGGlyph glyphs[256];
3355 for (i = 0; i < 16; i++)
3356 selectors[i] = 0xFE00 + i;
3357 for (; i < 256; i++)
3358 selectors[i] = 0xE0100 + (i - 16);
3359 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3360 for (i = 0; i < 256; i++)
3362 CGGlyph glyph = glyphs[i];
3364 if (uvs_collection != NSIdentityMappingCharacterCollection
3365 && glyph != kCGFontIndexInvalid)
3366 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3367 if (glyph == kCGFontIndexInvalid)
3371 variations[i] = (glyph ? glyph
3372 : macfont_get_glyph_for_character (font, c));
3382 static const char *const macfont_booleans[] = {
3388 static const char *const macfont_non_booleans[] = {
3396 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3398 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3402 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3403 CFArrayRef languages)
3405 Boolean result = true;
3406 CFArrayRef desc_languages =
3407 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3409 if (desc_languages == NULL)
3413 CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
3414 CFIndex i, languages_count = CFArrayGetCount (languages);
3416 for (i = 0; i < languages_count; i++)
3418 CFStringRef language = CFArrayGetValueAtIndex (languages, i);
3420 if (!CFArrayContainsValue (desc_languages, range, language)
3421 /* PingFang SC contains "zh" and "zh-Hant" as covered
3422 languages, but does not contain "zh-Hans". */
3423 && !(CFEqual (language, CFSTR ("zh-Hans"))
3424 && CFArrayContainsValue (desc_languages, range,
3431 CFRelease (desc_languages);
3438 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3440 CFStringRef result = NULL;
3441 CFStringRef charset_string =
3442 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3444 if (charset_string && CFStringGetLength (charset_string) > 0)
3446 CFStringRef keys[] = {
3447 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3448 kCTLanguageAttributeName
3450 CFSTR ("NSLanguage")
3453 CFTypeRef values[] = {NULL};
3454 CFIndex num_values = 0;
3455 CFArrayRef languages
3456 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3458 if (languages && CFArrayGetCount (languages) > 0)
3460 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3461 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3464 CFCharacterSetRef charset =
3465 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3467 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3472 CFAttributedStringRef attr_string = NULL;
3473 CTLineRef ctline = NULL;
3474 CFDictionaryRef attrs
3475 = CFDictionaryCreate (NULL, (const void **) keys,
3476 (const void **) values, num_values,
3477 &kCFTypeDictionaryKeyCallBacks,
3478 &kCFTypeDictionaryValueCallBacks);
3482 attr_string = CFAttributedStringCreate (NULL, charset_string,
3488 ctline = CTLineCreateWithAttributedString (attr_string);
3489 CFRelease (attr_string);
3493 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3494 CFIndex i, nruns = CFArrayGetCount (runs);
3497 for (i = 0; i < nruns; i++)
3499 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3500 CFDictionaryRef attributes = CTRunGetAttributes (run);
3501 CTFontRef font_in_run;
3503 if (attributes == NULL)
3506 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3507 if (font_in_run == NULL)
3511 else if (!mac_font_equal_in_postscript_name (font,
3515 if (nruns > 0 && i == nruns)
3516 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3525 static inline double
3526 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3528 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3532 static inline CGRect
3533 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3535 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3540 mac_font_create_available_families (void)
3542 CFMutableArrayRef families = NULL;
3543 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3547 CFIndex i, count = CFArrayGetCount (orig_families);
3549 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3551 for (i = 0; i < count; i++)
3553 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3555 if (!CFStringHasPrefix (family, CFSTR ("."))
3556 && (CTFontManagerCompareFontFamilyNames (family,
3557 CFSTR ("LastResort"),
3559 != kCFCompareEqualTo))
3560 CFArrayAppendValue (families, family);
3562 CFRelease (orig_families);
3569 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3572 CFStringRef name1, name2;
3578 name1 = CTFontCopyPostScriptName (font1);
3581 name2 = CTFontCopyPostScriptName (font2);
3584 result = CFEqual (name1, name2);
3594 mac_font_create_line_with_string_and_font (CFStringRef string,
3597 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3598 CFTypeRef values[] = {NULL, NULL};
3599 CFDictionaryRef attributes = NULL;
3600 CFAttributedStringRef attr_string = NULL;
3601 CTLineRef ctline = NULL;
3602 float float_zero = 0.0f;
3604 values[0] = macfont;
3605 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3608 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3609 (const void **) values,
3611 &kCFTypeDictionaryKeyCallBacks,
3612 &kCFTypeDictionaryValueCallBacks);
3613 CFRelease (values[1]);
3617 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3618 CFRelease (attributes);
3622 ctline = CTLineCreateWithAttributedString (attr_string);
3623 CFRelease (attr_string);
3627 /* Abandon if ctline contains some fonts other than the
3629 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3630 CFIndex i, nruns = CFArrayGetCount (runs);
3632 for (i = 0; i < nruns; i++)
3634 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3635 CFDictionaryRef attributes = CTRunGetAttributes (run);
3636 CTFontRef font_in_run;
3638 if (attributes == NULL)
3641 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3642 if (font_in_run == NULL)
3644 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3658 mac_font_shape (CTFontRef font, CFStringRef string,
3659 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3661 CFIndex used, result = 0;
3662 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3667 used = CTLineGetGlyphCount (ctline);
3668 if (used <= glyph_len)
3670 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3671 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3672 CGFloat total_advance = 0;
3673 CFIndex total_glyph_count = 0;
3675 for (k = 0; k < ctrun_count; k++)
3677 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3678 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3679 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3680 CFRange string_range, comp_range, range;
3681 CFIndex *permutation;
3683 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3684 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3688 #define RIGHT_TO_LEFT_P permutation
3690 /* Now the `comp_range' member of struct mac_glyph_layout is
3691 temporarily used as a work area such that:
3692 glbuf[i].comp_range.location =
3693 min {compRange[i + 1].location, ...,
3694 compRange[glyph_count - 1].location,
3695 maxRange (stringRangeForCTRun)}
3696 glbuf[i].comp_range.length = maxRange (compRange[i])
3697 where compRange[i] is the range of composed characters
3698 containing i-th glyph. */
3699 string_range = CTRunGetStringRange (ctrun);
3700 min_location = string_range.location + string_range.length;
3701 for (i = 0; i < glyph_count; i++)
3703 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3704 CFIndex glyph_index;
3707 if (!RIGHT_TO_LEFT_P)
3708 glyph_index = glyph_count - i - 1;
3711 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3714 CFStringGetRangeOfComposedCharactersAtIndex (string,
3716 gl->comp_range.location = min_location;
3717 gl->comp_range.length = rng.location + rng.length;
3718 if (rng.location < min_location)
3719 min_location = rng.location;
3722 /* Fill the `comp_range' member of struct mac_glyph_layout,
3723 and setup a permutation for right-to-left text. */
3724 comp_range = CFRangeMake (string_range.location, 0);
3725 range = CFRangeMake (0, 0);
3728 struct mac_glyph_layout *gl =
3729 glbuf + range.location + range.length;
3731 if (gl->comp_range.length
3732 > comp_range.location + comp_range.length)
3733 comp_range.length = gl->comp_range.length - comp_range.location;
3734 min_location = gl->comp_range.location;
3737 if (min_location >= comp_range.location + comp_range.length)
3739 comp_range.length = min_location - comp_range.location;
3740 for (i = 0; i < range.length; i++)
3742 glbuf[range.location + i].comp_range = comp_range;
3743 if (RIGHT_TO_LEFT_P)
3744 permutation[range.location + i] =
3745 range.location + range.length - i - 1;
3748 comp_range = CFRangeMake (min_location, 0);
3749 range.location += range.length;
3751 if (range.location == glyph_count)
3756 /* Then fill the remaining members. */
3757 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3760 struct mac_glyph_layout *gl;
3764 if (!RIGHT_TO_LEFT_P)
3765 gl = glbuf + range.location;
3770 src = glyph_count - 1 - range.location;
3771 dest = permutation[src];
3775 CFIndex tmp = gl->string_index;
3777 gl->string_index = glbuf[src].string_index;
3778 glbuf[src].string_index = tmp;
3781 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3783 CTRunGetPositions (ctrun, range, &position);
3784 max_x = position.x + CTRunGetTypographicBounds (ctrun, range,
3786 max_x = max (max_x, total_advance);
3787 gl->advance_delta = position.x - total_advance;
3788 gl->baseline_delta = position.y;
3789 gl->advance = max_x - total_advance;
3790 total_advance = max_x;
3793 if (RIGHT_TO_LEFT_P)
3794 xfree (permutation);
3796 #undef RIGHT_TO_LEFT_P
3798 total_glyph_count += glyph_count;
3808 /* The function below seems to cause a memory leak for the CFString
3809 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3810 10.6.3. For now, we use the NSGlyphInfo version instead. */
3811 #if USE_CT_GLYPH_INFO
3813 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3816 CGGlyph result = kCGFontIndexInvalid;
3817 UniChar characters[] = {0xfffd};
3819 CFAttributedStringRef attr_string = NULL;
3820 CTLineRef ctline = NULL;
3822 string = CFStringCreateWithCharacters (NULL, characters,
3823 ARRAYELTS (characters));
3827 CTGlyphInfoRef glyph_info =
3828 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3829 CFDictionaryRef attributes = NULL;
3833 CFStringRef keys[] = {kCTFontAttributeName,
3834 kCTGlyphInfoAttributeName};
3835 CFTypeRef values[] = {font, glyph_info};
3837 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3838 (const void **) values,
3840 &kCFTypeDictionaryKeyCallBacks,
3841 &kCFTypeDictionaryValueCallBacks);
3842 CFRelease (glyph_info);
3846 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3847 CFRelease (attributes);
3853 ctline = CTLineCreateWithAttributedString (attr_string);
3854 CFRelease (attr_string);
3858 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3860 if (CFArrayGetCount (runs) > 0)
3862 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3863 CFDictionaryRef attributes = CTRunGetAttributes (run);
3867 CTFontRef font_in_run =
3868 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3871 && mac_font_equal_in_postscript_name (font_in_run, font))
3873 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3874 if (result >= CTFontGetGlyphCount (font))
3875 result = kCGFontIndexInvalid;
3887 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3889 CFArrayRef result = NULL;
3891 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3892 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3893 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3896 CTFontRef user_font =
3897 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3901 CFArrayRef languages =
3902 CFArrayCreate (NULL, (const void **) &language, 1,
3903 &kCFTypeArrayCallBacks);
3907 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3909 CFRelease (languages);
3911 CFRelease (user_font);
3914 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3915 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3917 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3918 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3922 for (i = 0; macfont_language_default_font_names[i].language; i++)
3924 if (CFEqual (macfont_language_default_font_names[i].language,
3927 CFMutableArrayRef descriptors =
3928 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3935 macfont_language_default_font_names[i].font_names[j];
3938 CFDictionaryRef attributes =
3939 CFDictionaryCreate (NULL,
3941 &kCTFontNameAttribute),
3943 &macfont_language_default_font_names[i].font_names[j]),
3944 1, &kCFTypeDictionaryKeyCallBacks,
3945 &kCFTypeDictionaryValueCallBacks);
3949 CTFontDescriptorRef pat_desc =
3950 CTFontDescriptorCreateWithAttributes (attributes);
3954 CTFontDescriptorRef descriptor =
3955 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3959 CFArrayAppendValue (descriptors, descriptor);
3960 CFRelease (descriptor);
3962 CFRelease (pat_desc);
3964 CFRelease (attributes);
3967 result = descriptors;
3979 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3980 CFArrayRef languages)
3982 CFStringRef result = NULL;
3983 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3984 CFArrayRef descriptors =
3985 mac_font_copy_default_descriptors_for_language (language);
3989 CFIndex i, count = CFArrayGetCount (descriptors);
3991 for (i = 0; i < count; i++)
3993 CTFontDescriptorRef descriptor =
3994 CFArrayGetValueAtIndex (descriptors, i);
3996 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3999 CFStringRef family =
4000 CTFontDescriptorCopyAttribute (descriptor,
4001 kCTFontFamilyNameAttribute);
4004 if (!CFStringHasPrefix (family, CFSTR ("."))
4005 && !CFEqual (family, CFSTR ("LastResort")))
4015 CFRelease (descriptors);
4022 macfont_get_nsctfont (struct font *font)
4024 struct macfont_info *macfont_info = (struct macfont_info *) font;
4025 CTFontRef macfont = macfont_info->macfont;
4027 return (void *) macfont;
4031 mac_register_font_driver (struct frame *f)
4033 register_font_driver (&macfont_driver, f);
4038 syms_of_macfont (void)
4040 /* Core Text, for macOS. */
4041 DEFSYM (Qmac_ct, "mac-ct");
4042 register_font_driver (&macfont_driver, NULL);
4044 /* The font property key specifying the font design destination. The
4045 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4046 text. (See the documentation of X Logical Font Description
4047 Conventions.) In the Mac font driver, 1 means the screen font is
4048 used for calculating some glyph metrics. You can see the
4049 difference with Monaco 8pt or 9pt, for example. */
4050 DEFSYM (QCdestination, ":destination");
4052 /* The boolean-valued font property key specifying the use of leading. */
4053 DEFSYM (QCminspace, ":minspace");
4055 macfont_family_cache = Qnil;
4056 staticpro (&macfont_family_cache);