1 /* Font driver on Mac OSX Core text.
2 Copyright (C) 2009-2015 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #include <libkern/OSByteOrder.h>
41 static struct font_driver macfont_driver;
43 static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
44 static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
45 static CFArrayRef mac_font_create_available_families (void);
46 static Boolean mac_font_equal_in_postscript_name (CTFontRef, CTFontRef);
47 static CTLineRef mac_font_create_line_with_string_and_font (CFStringRef,
49 static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
51 static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
52 static CFIndex mac_font_shape (CTFontRef, CFStringRef,
53 struct mac_glyph_layout *, CFIndex);
54 static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
55 static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
57 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
61 struct macfont_metrics;
63 /* The actual structure for Mac font that can be cast to struct font. */
70 ScreenFontRef screen_font;
71 struct macfont_cache *cache;
72 struct macfont_metrics **metrics;
74 bool_bf synthetic_italic_p : 1;
75 bool_bf synthetic_bold_p : 1;
77 unsigned antialias : 2;
78 bool_bf color_bitmap_p : 1;
81 /* Values for the `spacing' member in `struct macfont_info'. */
85 MACFONT_SPACING_PROPORTIONAL,
87 MACFONT_SPACING_SYNTHETIC_MONO,
90 /* Values for the `antialias' member in `struct macfont_info'. */
94 MACFONT_ANTIALIAS_DEFAULT,
95 MACFONT_ANTIALIAS_OFF,
99 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
100 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
101 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
103 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
104 static const CGFloat synthetic_bold_factor = 0.024;
106 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
107 CTFontSymbolicTraits *);
108 static void macfont_store_descriptor_attributes (CTFontDescriptorRef,
110 static Lisp_Object macfont_descriptor_entity (CTFontDescriptorRef, Lisp_Object,
111 CTFontSymbolicTraits);
112 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
113 static int macfont_glyph_extents (struct font *, CGGlyph,
114 struct font_metrics *, CGFloat *, int);
115 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
116 static Boolean macfont_supports_charset_and_languages_p (CTFontDescriptorRef,
120 static Boolean macfont_closest_traits_index_p (CFArrayRef, CTFontSymbolicTraits,
122 static CFDataRef mac_font_copy_uvs_table (CTFontRef);
123 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
125 CGGlyph [], CFIndex);
127 /* From CFData to a lisp string. Always returns a unibyte string. */
130 cfdata_to_lisp (CFDataRef data)
132 CFIndex len = CFDataGetLength (data);
133 Lisp_Object result = make_uninit_string (len);
135 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
142 /* From CFString to a lisp string. Returns a unibyte string
143 containing a UTF-8 byte sequence. */
146 cfstring_to_lisp_nodecode (CFStringRef string)
148 Lisp_Object result = Qnil;
150 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
154 CFIndex i, length = CFStringGetLength (string);
156 for (i = 0; i < length; i++)
157 if (CFStringGetCharacterAtIndex (string, i) == 0)
161 return make_unibyte_string (s, strlen (s));
164 data = CFStringCreateExternalRepresentation (NULL, string,
165 kCFStringEncodingUTF8, '?');
168 result = cfdata_to_lisp (data);
175 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
176 cfstring_create_with_utf8_cstring, this function preserves NUL
180 cfstring_create_with_string_noencode (Lisp_Object s)
182 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
183 kCFStringEncodingUTF8, false);
186 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
187 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
188 kCFStringEncodingMacRoman, false);
194 mac_font_get_weight (CTFontRef font)
196 NSFont *nsFont = (NSFont *) font;
198 return [[NSFontManager sharedFontManager] weightOfFont:nsFont];
202 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
204 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
206 return advancement.width;
209 #if !USE_CT_GLYPH_INFO
211 mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
214 CGGlyph result = kCGFontIndexInvalid;
215 NSFont *nsFont = (NSFont *) font;
216 unichar characters[] = {0xfffd};
218 [NSString stringWithCharacters:characters
219 length:ARRAYELTS (characters)];
220 NSGlyphInfo *glyphInfo =
221 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
222 collection:collection
224 NSDictionary *attributes =
225 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
226 glyphInfo,NSGlyphInfoAttributeName,nil];
227 NSTextStorage *textStorage =
228 [[NSTextStorage alloc] initWithString:string
229 attributes:attributes];
230 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
231 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
232 NSFont *fontInTextStorage;
234 [layoutManager addTextContainer:textContainer];
235 [textContainer release];
236 [textStorage addLayoutManager:layoutManager];
237 [layoutManager release];
240 (void) [layoutManager glyphRangeForTextContainer:textContainer];
242 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
243 effectiveRange:NULL];
244 if (fontInTextStorage == nsFont
245 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
247 NSGlyph glyph = [layoutManager glyphAtIndex:0];
249 if (glyph < [nsFont numberOfGlyphs])
253 [textStorage release];
260 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
262 NSFont *result, *font;
264 font = [NSFont fontWithName:((NSString *) name) size:size];
265 result = [font screenFont];
267 return (ScreenFontRef)[result retain];
272 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
273 CGFloat *descent, CGFloat *leading)
275 NSFont *nsFont = [(NSFont *)font printerFont];
276 NSTextStorage *textStorage;
277 NSLayoutManager *layoutManager;
278 NSTextContainer *textContainer;
280 NSPoint spaceLocation;
283 textStorage = [[NSTextStorage alloc] initWithString:@" "];
284 layoutManager = [[NSLayoutManager alloc] init];
285 textContainer = [[NSTextContainer alloc] init];
287 [textStorage setFont:nsFont];
288 [textContainer setLineFragmentPadding:0];
289 [layoutManager setUsesScreenFonts:YES];
291 [layoutManager addTextContainer:textContainer];
292 [textContainer release];
293 [textStorage addLayoutManager:layoutManager];
294 [layoutManager release];
296 if (!(textStorage && layoutManager && textContainer))
298 [textStorage release];
303 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
304 effectiveRange:NULL];
305 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
306 [textStorage release];
308 *ascent = spaceLocation.y;
309 *descent = NSHeight (usedRect) - spaceLocation.y;
311 descender = [nsFont descender];
312 if (- descender < *descent)
314 *leading = *descent + descender;
315 *descent = - descender;
322 mac_font_shape_1 (NSFont *font, NSString *string,
323 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
328 NSTextStorage *textStorage;
329 NSLayoutManager *layoutManager;
330 NSTextContainer *textContainer;
331 NSUInteger stringLength;
332 NSPoint spaceLocation;
333 NSUInteger used, numberOfGlyphs;
335 textStorage = [[NSTextStorage alloc] initWithString:string];
336 layoutManager = [[NSLayoutManager alloc] init];
337 textContainer = [[NSTextContainer alloc] init];
339 /* Append a trailing space to measure baseline position. */
340 [textStorage appendAttributedString:([[[NSAttributedString alloc]
341 initWithString:@" "] autorelease])];
342 [textStorage setFont:font];
343 [textContainer setLineFragmentPadding:0];
344 [layoutManager setUsesScreenFonts:screen_font_p];
346 [layoutManager addTextContainer:textContainer];
347 [textContainer release];
348 [textStorage addLayoutManager:layoutManager];
349 [layoutManager release];
351 if (!(textStorage && layoutManager && textContainer))
353 [textStorage release];
358 stringLength = [string length];
361 (void) [layoutManager glyphRangeForTextContainer:textContainer];
363 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
365 /* Remove the appended trailing space because otherwise it may
366 generate a wrong result for a right-to-left text. */
367 [textStorage beginEditing];
368 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
369 [textStorage endEditing];
370 (void) [layoutManager glyphRangeForTextContainer:textContainer];
373 while (i < stringLength)
376 NSFont *fontInTextStorage =
377 [textStorage attribute:NSFontAttributeName atIndex:i
378 longestEffectiveRange:&range
379 inRange:(NSMakeRange (0, stringLength))];
381 if (!(fontInTextStorage == font
382 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
384 i = NSMaxRange (range);
386 if (i < stringLength)
387 /* Make the test `used <= glyph_len' below fail if textStorage
388 contained some fonts other than the specified one. */
389 used = glyph_len + 1;
392 NSRange range = NSMakeRange (0, stringLength);
394 range = [layoutManager glyphRangeForCharacterRange:range
395 actualCharacterRange:NULL];
396 numberOfGlyphs = NSMaxRange (range);
397 used = numberOfGlyphs;
398 for (i = 0; i < numberOfGlyphs; i++)
399 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
403 if (0 < used && used <= glyph_len)
405 NSUInteger glyphIndex, prevGlyphIndex;
406 unsigned char bidiLevel;
407 NSUInteger *permutation;
408 NSRange compRange, range;
409 CGFloat totalAdvance;
412 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
415 /* For now we assume the direction is not changed within the
417 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
418 glyphs:NULL characterIndexes:NULL
419 glyphInscriptions:NULL elasticBits:NULL
420 bidiLevels:&bidiLevel];
422 permutation = xmalloc (sizeof (NSUInteger) * used);
426 #define RIGHT_TO_LEFT_P permutation
428 /* Fill the `comp_range' member of struct mac_glyph_layout, and
429 setup a permutation for right-to-left text. */
430 compRange = NSMakeRange (0, 0);
431 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
434 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
435 NSUInteger characterIndex =
436 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
438 gl->string_index = characterIndex;
440 if (characterIndex >= NSMaxRange (compRange))
442 compRange.location = NSMaxRange (compRange);
445 NSRange characterRange =
447 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
450 NSMaxRange (characterRange) - compRange.location;
451 [layoutManager glyphRangeForCharacterRange:compRange
452 actualCharacterRange:&characterRange];
453 characterIndex = NSMaxRange (characterRange) - 1;
455 while (characterIndex >= NSMaxRange (compRange));
458 for (i = 0; i < range.length; i++)
459 permutation[range.location + i] = NSMaxRange (range) - i - 1;
461 range = NSMakeRange (NSMaxRange (range), 0);
464 gl->comp_range.location = compRange.location;
465 gl->comp_range.length = compRange.length;
467 while (++glyphIndex < numberOfGlyphs)
468 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
472 for (i = 0; i < range.length; i++)
473 permutation[range.location + i] = NSMaxRange (range) - i - 1;
475 /* Then fill the remaining members. */
476 glyphIndex = prevGlyphIndex = 0;
477 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
480 if (!RIGHT_TO_LEFT_P)
487 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
488 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
489 inTextContainer:textContainer rectCount:&nrects];
491 totalAdvance = NSMaxX (glyphRects[0]);
494 for (i = 0; i < used; i++)
496 struct mac_glyph_layout *gl;
498 NSUInteger nextGlyphIndex;
503 if (!RIGHT_TO_LEFT_P)
504 gl = glyph_layouts + i;
507 NSUInteger dest = permutation[i];
509 gl = glyph_layouts + dest;
512 CFIndex tmp = gl->string_index;
514 gl->string_index = glyph_layouts[i].string_index;
515 glyph_layouts[i].string_index = tmp;
518 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
520 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
521 gl->baseline_delta = spaceLocation.y - location.y;
523 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
526 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
529 if (!RIGHT_TO_LEFT_P)
533 if (prevGlyphIndex == 0)
534 glyphRange = NSMakeRange (0, nextGlyphIndex);
536 glyphRange = NSMakeRange (glyphIndex,
537 nextGlyphIndex - glyphIndex);
540 rectArrayForGlyphRange:glyphRange
541 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
542 inTextContainer:textContainer rectCount:&nrects];
543 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
544 gl->advance_delta = location.x - totalAdvance;
545 gl->advance = maxX - totalAdvance;
552 if (nextGlyphIndex == numberOfGlyphs)
553 glyphRange = NSMakeRange (prevGlyphIndex,
554 numberOfGlyphs - prevGlyphIndex);
556 glyphRange = NSMakeRange (prevGlyphIndex,
557 glyphIndex + 1 - prevGlyphIndex);
560 rectArrayForGlyphRange:glyphRange
561 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
562 inTextContainer:textContainer rectCount:&nrects];
563 minX = min (NSMinX (glyphRects[0]), totalAdvance);
564 gl->advance = totalAdvance - minX;
566 gl->advance_delta = location.x - totalAdvance;
569 prevGlyphIndex = glyphIndex + 1;
570 glyphIndex = nextGlyphIndex;
576 #undef RIGHT_TO_LEFT_P
580 [textStorage release];
586 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
587 struct mac_glyph_layout *glyph_layouts,
590 return mac_font_shape_1 ([(NSFont *)font printerFont],
592 glyph_layouts, glyph_len, YES);
596 get_cgcolor(unsigned long idx, struct frame *f)
598 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
600 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
601 NSInteger noc = [nsColor numberOfComponents];
602 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
605 [nsColor getComponents: components];
606 cgColor = CGColorCreate (colorSpace, components);
611 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
613 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
614 CGContextSetFillColorWithColor (context, refcol_) ; \
615 CGColorRelease (refcol_); \
617 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
619 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
620 CGContextSetFillColorWithColor (context, refcol_); \
621 CGColorRelease (refcol_); \
623 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
625 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
626 CGContextSetStrokeColorWithColor (context, refcol_); \
627 CGColorRelease (refcol_); \
632 /* Mac font driver. */
638 /* characters to distinguish the charset from the others */
640 /* additional constraint by language */
643 CFCharacterSetRef cf_charset;
644 CFStringRef cf_charset_string;
645 } cf_charset_table[] =
646 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
647 { "iso8859-2", { 0x00A0, 0x010E }},
648 { "iso8859-3", { 0x00A0, 0x0108 }},
649 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
650 { "iso8859-5", { 0x00A0, 0x0401 }},
651 { "iso8859-6", { 0x00A0, 0x060C }},
652 { "iso8859-7", { 0x00A0, 0x0384 }},
653 { "iso8859-8", { 0x00A0, 0x05D0 }},
654 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
655 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
656 { "iso8859-11", { 0x00A0, 0x0E01 }},
657 { "iso8859-13", { 0x00A0, 0x201C }},
658 { "iso8859-14", { 0x00A0, 0x0174 }},
659 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
660 { "iso8859-16", { 0x00A0, 0x0218}},
661 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
662 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
663 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
664 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
665 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
666 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
667 { "cns11643.1992-3", { 0x201A9 }},
668 { "cns11643.1992-4", { 0x20057 }},
669 { "cns11643.1992-5", { 0x20000 }},
670 { "cns11643.1992-6", { 0x20003 }},
671 { "cns11643.1992-7", { 0x20055 }},
672 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
673 { "jisx0212.1990-0", { 0x4E44 }},
674 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
675 { "jisx0213.2000-2", { 0xFA49 }},
676 { "jisx0213.2004-1", { 0x20B9F }},
677 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
678 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
679 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
680 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
681 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
682 { "unicode-sip", { 0x20000 }},
686 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
689 CFStringRef language;
690 CFStringRef font_names[3];
691 } macfont_language_default_font_names[] = {
692 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
693 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
695 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
696 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
698 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
699 CFSTR ("STXihei"), /* 10.4 - 10.5 */
701 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
702 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
708 static CGFloat macfont_antialias_threshold;
711 macfont_update_antialias_threshold (void)
717 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
718 kCFPreferencesCurrentApplication,
721 macfont_antialias_threshold = threshold;
724 static inline Lisp_Object
725 macfont_intern_prop_cfstring (CFStringRef cfstring)
727 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
729 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
732 static inline CFIndex
733 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
744 unichars[0] = (c >> 10) + 0xD800;
745 unichars[1] = (c & 0x3FF) + 0xDC00;
752 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
753 CTFontSymbolicTraits *sym_traits)
757 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
758 OS X 10.6 when the value is greater than or equal to 1 << 31. */
759 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
761 *sym_traits = (CTFontSymbolicTraits) sint64_value;
770 mac_font_descriptor_get_adjusted_weight (CTFontDescriptorRef desc, CGFloat val)
772 long percent_val = lround (val * 100);
774 if (percent_val == -40 || percent_val == 56)
776 CTFontRef font = NULL;
778 CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
782 font = CTFontCreateWithName (name, 0, NULL);
787 CFIndex weight = mac_font_get_weight (font);
789 if (percent_val == -40)
791 /* Workaround for crash when displaying Oriya characters
792 with Arial Unicode MS on OS X 10.11. */
796 else /* percent_val == 56 */
799 /* Adjustment for HiraginoSans-W7 on OS X 10.11. */
810 macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
811 Lisp_Object spec_or_entity)
814 CFDictionaryRef dict;
818 str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
821 ASET (spec_or_entity, FONT_FAMILY_INDEX,
822 macfont_intern_prop_cfstring (str));
825 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
829 enum font_property_index index;
832 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
834 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
835 {{-0.4, 50}, /* light */
836 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
837 {0, 100}, /* normal */
838 {0.24, 140}, /* (semi-bold + normal) / 2 */
839 {0.4, 200}, /* bold */
840 {CGFLOAT_MAX, CGFLOAT_MAX}},
841 mac_font_descriptor_get_adjusted_weight},
842 {FONT_SLANT_INDEX, kCTFontSlantTrait,
843 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
844 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
845 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
848 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
850 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
851 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
853 CGPoint *point = numeric_traits[i].points;
855 if (numeric_traits[i].adjust_func)
856 floatval = (*numeric_traits[i].adjust_func) (desc, floatval);
857 while (point->x < floatval)
859 if (point == numeric_traits[i].points)
861 else if (point->x == CGFLOAT_MAX)
863 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
864 * ((point->y - (point - 1)->y)
865 / (point->x - (point - 1)->x)));
866 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
867 make_number (lround (floatval)));
871 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
874 CTFontSymbolicTraits sym_traits;
877 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
878 spacing = (sym_traits & kCTFontTraitMonoSpace
879 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
880 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
885 num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
886 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
887 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
889 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
895 macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
896 CTFontSymbolicTraits synth_sym_traits)
899 CFDictionaryRef dict;
900 CTFontSymbolicTraits sym_traits = 0;
903 entity = font_make_entity ();
905 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
906 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
908 macfont_store_descriptor_attributes (desc, entity);
910 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
913 CFNumberRef num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
916 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
919 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
920 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
921 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
922 name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
923 font_put_extra (entity, QCfont_entity,
924 make_save_ptr_int ((void *) name, sym_traits));
925 if (synth_sym_traits & kCTFontTraitItalic)
926 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
927 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
928 if (synth_sym_traits & kCTFontTraitBold)
929 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
930 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
931 if (synth_sym_traits & kCTFontTraitMonoSpace)
932 ASET (entity, FONT_SPACING_INDEX,
933 make_number (FONT_SPACING_SYNTHETIC_MONO));
938 /* Cache for font family name symbols vs CFStrings. A value of nil
939 means the cache has been invalidated. Otherwise the value is a Lisp
940 hash table whose keys are symbols and the value for a key is either
941 nil (no corresponding family name) or a Lisp save value wrapping the
942 corresponding family name in CFString. */
944 static Lisp_Object macfont_family_cache;
947 macfont_invalidate_family_cache (void)
949 if (HASH_TABLE_P (macfont_family_cache))
951 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
952 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
954 for (i = 0; i < size; ++i)
955 if (!NILP (HASH_HASH (h, i)))
957 Lisp_Object value = HASH_VALUE (h, i);
959 if (SAVE_VALUEP (value))
960 CFRelease (XSAVE_POINTER (value, 0));
962 macfont_family_cache = Qnil;
967 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
969 if (HASH_TABLE_P (macfont_family_cache))
971 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
972 ptrdiff_t i = hash_lookup (h, symbol, NULL);
976 Lisp_Object value = HASH_VALUE (h, i);
978 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
988 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
990 struct Lisp_Hash_Table *h;
995 if (!HASH_TABLE_P (macfont_family_cache))
996 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
998 h = XHASH_TABLE (macfont_family_cache);
999 i = hash_lookup (h, symbol, &hash);
1000 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
1003 Lisp_Object old_value = HASH_VALUE (h, i);
1005 if (SAVE_VALUEP (old_value))
1006 CFRelease (XSAVE_POINTER (old_value, 0));
1007 set_hash_value_slot (h, i, value);
1010 hash_put (h, symbol, value, hash);
1013 /* Cache of all the available font family names except "LastResort"
1014 and those start with ".". NULL means the cache has been invalidated.
1015 Otherwise, the value is CFArray of CFStrings and the elements are
1016 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
1017 OS X 10.6 and later). */
1019 static CFArrayRef macfont_available_families_cache = NULL;
1022 macfont_invalidate_available_families_cache (void)
1024 if (macfont_available_families_cache)
1026 CFRelease (macfont_available_families_cache);
1027 macfont_available_families_cache = NULL;
1032 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1034 CFStringRef name, const void *object,
1035 CFDictionaryRef userInfo)
1037 macfont_invalidate_family_cache ();
1038 macfont_invalidate_available_families_cache ();
1042 macfont_init_font_change_handler (void)
1044 static bool initialized = false;
1050 CFNotificationCenterAddObserver
1051 (CFNotificationCenterGetLocalCenter (), NULL,
1052 macfont_handle_font_change_notification,
1053 kCTFontManagerRegisteredFontsChangedNotification,
1054 NULL, CFNotificationSuspensionBehaviorCoalesce);
1058 macfont_copy_available_families_cache (void)
1060 macfont_init_font_change_handler ();
1062 if (macfont_available_families_cache == NULL)
1063 macfont_available_families_cache = mac_font_create_available_families ();
1065 return (macfont_available_families_cache
1066 ? CFRetain (macfont_available_families_cache) : NULL);
1070 macfont_create_family_with_symbol (Lisp_Object symbol)
1072 CFStringRef result = NULL, family_name;
1073 CFDictionaryRef attributes = NULL;
1074 CTFontDescriptorRef pat_desc = NULL;
1076 if (macfont_get_family_cache_if_present (symbol, &result))
1077 return result ? CFRetain (result) : NULL;
1079 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1083 CFDictionaryCreate (NULL,
1084 (const void **) &kCTFontFamilyNameAttribute,
1085 (const void **) &family_name, 1,
1086 &kCFTypeDictionaryKeyCallBacks,
1087 &kCFTypeDictionaryValueCallBacks);
1088 CFRelease (family_name);
1092 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
1093 CFRelease (attributes);
1097 CTFontDescriptorRef desc =
1098 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
1103 CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute);
1106 macfont_set_family_cache (symbol, result);
1107 CFRelease (pat_desc);
1113 #define WIDTH_FRAC_BITS (4)
1114 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1116 struct macfont_metrics
1118 unsigned char lbearing_low, rbearing_low;
1119 signed lbearing_high : 4, rbearing_high : 4;
1120 unsigned char ascent_low, descent_low;
1121 signed ascent_high : 4, descent_high : 4;
1123 /* These two members are used for fixed-point representation of
1124 glyph width. The `width_int' member is an integer that is
1125 closest to the width. The `width_frac' member is the fractional
1126 adjustment representing a value in [-.5, .5], multiplied by
1127 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1128 the advance delta for centering instead of the glyph width. */
1129 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1132 #define METRICS_VALUE(metrics, member) \
1133 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1134 #define METRICS_SET_VALUE(metrics, member, value) \
1135 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1136 (metrics)->member##_high = tmp >> 8;} while (0)
1140 METRICS_INVALID = -1, /* metrics entry is invalid */
1141 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1144 #define METRICS_STATUS(metrics) \
1145 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1146 #define METRICS_SET_STATUS(metrics, status) \
1147 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1148 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1150 #define METRICS_NCOLS_PER_ROW (128)
1151 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1152 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1155 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1156 struct font_metrics *metrics, CGFloat *advance_delta,
1157 int force_integral_p)
1159 struct macfont_info *macfont_info = (struct macfont_info *) font;
1160 CTFontRef macfont = macfont_info->macfont;
1162 struct macfont_metrics *cache;
1165 row = glyph / METRICS_NCOLS_PER_ROW;
1166 col = glyph % METRICS_NCOLS_PER_ROW;
1167 if (row >= macfont_info->metrics_nrows)
1169 macfont_info->metrics =
1170 xrealloc (macfont_info->metrics,
1171 sizeof (struct macfont_metrics *) * (row + 1));
1172 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1173 (sizeof (struct macfont_metrics *)
1174 * (row + 1 - macfont_info->metrics_nrows)));
1175 macfont_info->metrics_nrows = row + 1;
1177 if (macfont_info->metrics[row] == NULL)
1179 struct macfont_metrics *new;
1182 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1183 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1184 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1185 macfont_info->metrics[row] = new;
1187 cache = macfont_info->metrics[row] + col;
1189 if (METRICS_STATUS (cache) == METRICS_INVALID)
1193 if (macfont_info->screen_font)
1194 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1196 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1198 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1199 advance delta value. */
1200 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1201 fwidth = (font->pixel_size - fwidth) / 2;
1202 cache->width_int = lround (fwidth);
1203 cache->width_frac = lround ((fwidth - cache->width_int)
1204 * WIDTH_FRAC_SCALE);
1205 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1207 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1208 width = font->pixel_size;
1210 width = cache->width_int;
1214 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1216 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1218 if (macfont_info->synthetic_italic_p)
1220 /* We assume the members a, b, c, and d in
1221 synthetic_italic_atfm are non-negative. */
1223 CGPointApplyAffineTransform (bounds.origin,
1224 synthetic_italic_atfm);
1226 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1228 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1230 CGFloat d = - synthetic_bold_factor * CTFontGetSize (macfont) / 2;
1232 bounds = CGRectInset (bounds, d, d);
1234 switch (macfont_info->spacing)
1236 case MACFONT_SPACING_PROPORTIONAL:
1237 bounds.origin.x += - (cache->width_frac
1238 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1240 case MACFONT_SPACING_MONO:
1242 case MACFONT_SPACING_SYNTHETIC_MONO:
1243 bounds.origin.x += (cache->width_int
1244 + (cache->width_frac
1245 / (CGFloat) WIDTH_FRAC_SCALE));
1248 if (bounds.size.width > 0)
1250 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1251 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1252 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1254 bounds = CGRectIntegral (bounds);
1255 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1256 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1257 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1258 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1260 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1261 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1262 metrics->width = width;
1263 metrics->ascent = METRICS_VALUE (cache, ascent);
1264 metrics->descent = METRICS_VALUE (cache, descent);
1269 switch (macfont_info->spacing)
1271 case MACFONT_SPACING_PROPORTIONAL:
1272 *advance_delta = (force_integral_p ? 0
1273 : - (cache->width_frac
1274 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1276 case MACFONT_SPACING_MONO:
1279 case MACFONT_SPACING_SYNTHETIC_MONO:
1280 *advance_delta = (force_integral_p ? cache->width_int
1282 + (cache->width_frac
1283 / (CGFloat) WIDTH_FRAC_SCALE)));
1291 static CFMutableDictionaryRef macfont_cache_dictionary;
1293 /* Threshold used in row_nkeys_or_perm. This must be less than or
1294 equal to the number of rows that are invalid as BMP (i.e., from
1295 U+D800 to U+DFFF). */
1296 #define ROW_PERM_OFFSET (8)
1298 /* The number of glyphs that can be stored in a value for a single
1299 entry of CFDictionary. */
1300 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1302 struct macfont_cache
1304 int reference_count;
1305 CFCharacterSetRef cf_charset;
1307 /* The cached glyph for a BMP character c is stored in
1308 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1309 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1310 unsigned char row_nkeys_or_perm[256];
1313 /* Number of rows for which the BMP cache is allocated so far.
1314 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1317 /* The cached glyph for a character c is stored as the (c %
1318 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1319 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1320 not stored here if row_nkeys_or_perm[c / 256] >=
1322 CFMutableDictionaryRef dictionary;
1326 /* UVS (Unicode Variation Sequence) subtable data, which is of
1327 type CFDataRef if available. NULL means it is not initialized
1328 yet. kCFNull means the subtable is not found and there is no
1329 suitable fallback table for this font. */
1332 /* Character collection specifying the destination of the mapping
1333 provided by `table' above. If `table' is obtained from the UVS
1334 subtable in the font cmap table, then the value of this member
1335 should be kCTCharacterCollectionIdentityMapping. */
1336 CTCharacterCollection collection;
1340 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1341 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1342 static void macfont_release_cache (struct macfont_cache *);
1343 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1344 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1345 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1346 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1347 CTCharacterCollection, CGFontIndex);
1348 static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *);
1350 static struct macfont_cache *
1351 macfont_lookup_cache (CFStringRef key)
1353 struct macfont_cache *cache;
1355 if (macfont_cache_dictionary == NULL)
1357 macfont_cache_dictionary =
1358 CFDictionaryCreateMutable (NULL, 0,
1359 &kCFTypeDictionaryKeyCallBacks, NULL);
1363 cache = ((struct macfont_cache *)
1364 CFDictionaryGetValue (macfont_cache_dictionary, key));
1368 CTFontRef macfont = CTFontCreateWithName (key, 0, NULL);
1372 cache = xzalloc (sizeof (struct macfont_cache));
1373 /* Treat the LastResort font as if it contained glyphs for
1374 all characters. This may look too rough, but neither
1375 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1376 for this font is correct for non-BMP characters on Mac OS
1378 if (CFEqual (key, CFSTR ("LastResort")))
1380 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1383 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1385 if (cache->cf_charset == NULL)
1386 cache->cf_charset = CTFontCopyCharacterSet (macfont);
1387 CFDictionaryAddValue (macfont_cache_dictionary, key,
1388 (const void *) cache);
1389 CFRelease (macfont);
1396 static struct macfont_cache *
1397 macfont_retain_cache (struct macfont_cache *cache)
1399 cache->reference_count++;
1405 macfont_release_cache (struct macfont_cache *cache)
1407 if (--cache->reference_count == 0)
1411 for (i = 0; i < cache->glyph.nrows; i++)
1412 xfree (cache->glyph.matrix[i]);
1413 xfree (cache->glyph.matrix);
1414 if (cache->glyph.dictionary)
1415 CFRelease (cache->glyph.dictionary);
1416 memset (&cache->glyph, 0, sizeof (cache->glyph));
1417 if (cache->uvs.table)
1418 CFRelease (cache->uvs.table);
1419 memset (&cache->uvs, 0, sizeof (cache->uvs));
1423 static CFCharacterSetRef
1424 macfont_get_cf_charset (struct font *font)
1426 struct macfont_info *macfont_info = (struct macfont_info *) font;
1428 return macfont_info->cache->cf_charset;
1431 static CFCharacterSetRef
1432 macfont_get_cf_charset_for_name (CFStringRef name)
1434 struct macfont_cache *cache = macfont_lookup_cache (name);
1436 return cache->cf_charset;
1440 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1442 struct macfont_info *macfont_info = (struct macfont_info *) font;
1443 CTFontRef macfont = macfont_info->macfont;
1444 struct macfont_cache *cache = macfont_info->cache;
1446 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1449 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1451 if (nkeys_or_perm < ROW_PERM_OFFSET)
1453 UniChar unichars[256], ch;
1457 dispatch_queue_t queue;
1458 dispatch_group_t group = NULL;
1462 CFMutableDictionaryRef dictionary;
1463 uintptr_t key, value;
1467 if (cache->glyph.dictionary == NULL)
1468 cache->glyph.dictionary =
1469 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1470 dictionary = cache->glyph.dictionary;
1471 key = c / NGLYPHS_IN_VALUE;
1472 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1473 value = ((uintptr_t)
1474 CFDictionaryGetValue (dictionary, (const void *) key));
1475 glyph = (value >> nshifts);
1479 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1482 if (!CTFontGetGlyphsForCharacters (macfont, &ch, &glyph, 1)
1484 glyph = kCGFontIndexInvalid;
1487 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1488 value |= ((uintptr_t) glyph << nshifts);
1489 CFDictionarySetValue (dictionary, (const void *) key,
1490 (const void *) value);
1496 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1497 group = dispatch_group_create ();
1498 dispatch_group_async (group, queue, ^{
1501 nkeys = nkeys_or_perm;
1502 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1503 if (CFDictionaryContainsKey (dictionary,
1504 (const void *) key))
1506 CFDictionaryRemoveValue (dictionary,
1507 (const void *) key);
1515 for (i = 0; i < 256; i++)
1518 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1519 unichars[len++] = ch;
1522 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1525 CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, len);
1528 int next = unichars[len - 1] % 256;
1531 glyphs[i] = kCGFontIndexInvalid;
1534 glyphs[i] = glyphs[len];
1541 glyphs[i] = kCGFontIndexInvalid;
1543 nrows = cache->glyph.nrows;
1544 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1545 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1547 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1548 sizeof (CGGlyph *) * nrows);
1549 cache->glyph.matrix[nrows - 1] = glyphs;
1550 cache->glyph.nrows = nrows;
1554 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1555 dispatch_release (group);
1559 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1563 uintptr_t key, value;
1567 if (cache->glyph.dictionary == NULL)
1568 cache->glyph.dictionary =
1569 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1570 key = c / NGLYPHS_IN_VALUE;
1571 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1572 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1573 (const void *) key);
1574 glyph = (value >> nshifts);
1577 UniChar unichars[2];
1579 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1581 if (CTFontGetGlyphsForCharacters (macfont, unichars, glyphs, count))
1584 glyph = kCGFontIndexInvalid;
1586 value |= ((uintptr_t) glyph << nshifts);
1587 CFDictionarySetValue (cache->glyph.dictionary,
1588 (const void *) key, (const void *) value);
1596 macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1599 struct macfont_info *macfont_info = (struct macfont_info *) font;
1600 CTFontRef macfont = macfont_info->macfont;
1603 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1607 macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1609 struct macfont_info *macfont_info = (struct macfont_info *) font;
1610 CTFontRef macfont = macfont_info->macfont;
1611 struct macfont_cache *cache = macfont_info->cache;
1612 CFDataRef result = NULL;
1614 if (cache->uvs.table == NULL)
1616 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1617 CTCharacterCollection uvs_collection =
1618 kCTCharacterCollectionIdentityMapping;
1620 if (uvs_table == NULL
1621 && mac_font_get_glyph_for_cid (macfont,
1622 kCTCharacterCollectionAdobeJapan1,
1623 6480) != kCGFontIndexInvalid)
1625 /* If the glyph for U+4E55 is accessible via its CID 6480,
1626 then we use the Adobe-Japan1 UVS table, which maps a
1627 variation sequence to a CID, as a fallback. */
1628 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1630 if (mac_uvs_table_adobe_japan1 == NULL)
1631 mac_uvs_table_adobe_japan1 =
1632 CFDataCreateWithBytesNoCopy (NULL,
1633 mac_uvs_table_adobe_japan1_bytes,
1634 sizeof (mac_uvs_table_adobe_japan1_bytes),
1636 if (mac_uvs_table_adobe_japan1)
1638 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1639 uvs_collection = kCTCharacterCollectionAdobeJapan1;
1642 if (uvs_table == NULL)
1643 cache->uvs.table = kCFNull;
1645 cache->uvs.table = uvs_table;
1646 cache->uvs.collection = uvs_collection;
1649 if (cache->uvs.table != kCFNull)
1651 result = cache->uvs.table;
1652 *collection = cache->uvs.collection;
1658 static Lisp_Object macfont_get_cache (struct frame *);
1659 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1660 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1661 static Lisp_Object macfont_list_family (struct frame *);
1662 static void macfont_free_entity (Lisp_Object);
1663 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1664 static void macfont_close (struct font *);
1665 static int macfont_has_char (Lisp_Object, int);
1666 static unsigned macfont_encode_char (struct font *, int);
1667 static void macfont_text_extents (struct font *, unsigned int *, int,
1668 struct font_metrics *);
1669 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1670 static Lisp_Object macfont_shape (Lisp_Object);
1671 static int macfont_variation_glyphs (struct font *, int c,
1672 unsigned variations[256]);
1673 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1675 static struct font_driver macfont_driver =
1677 LISP_INITIALLY_ZERO, /* Qmac_ct */
1678 0, /* case insensitive */
1682 macfont_list_family,
1683 macfont_free_entity,
1686 NULL, /* prepare_face */
1687 NULL, /* done_face */
1689 macfont_encode_char,
1690 macfont_text_extents,
1692 NULL, /* get_bitmap */
1693 NULL, /* free_bitmap */
1694 NULL, /* anchor_point */
1695 NULL, /* otf_capability */
1696 NULL, /* otf_drive */
1697 NULL, /* start_for_frame */
1698 NULL, /* end_for_frame */
1701 macfont_variation_glyphs,
1702 macfont_filter_properties,
1706 macfont_get_cache (struct frame * f)
1708 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1710 return (dpyinfo->name_list_element);
1714 macfont_get_charset (Lisp_Object registry)
1716 char *str = SSDATA (SYMBOL_NAME (registry));
1717 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1721 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1725 else if (str[i] == '*')
1732 regexp = make_unibyte_string (re, j);
1733 for (i = 0; cf_charset_table[i].name; i++)
1734 if (fast_c_string_match_ignore_case
1735 (regexp, cf_charset_table[i].name,
1736 strlen (cf_charset_table[i].name)) >= 0)
1738 if (! cf_charset_table[i].name)
1740 if (! cf_charset_table[i].cf_charset)
1742 int *uniquifier = cf_charset_table[i].uniquifier;
1743 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1746 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1750 for (j = 0; uniquifier[j]; j++)
1752 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1754 CFCharacterSetAddCharactersInRange (charset,
1755 CFRangeMake (uniquifier[j], 1));
1758 string = CFStringCreateWithCharacters (NULL, unichars, count);
1761 CFRelease (charset);
1764 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1766 CFRelease (charset);
1767 /* CFCharacterSetCreateWithCharactersInString does not handle
1768 surrogate pairs properly as of Mac OS X 10.5. */
1769 cf_charset_table[i].cf_charset_string = string;
1777 unsigned int script_tag, langsys_tag;
1779 unsigned int *features[2];
1782 #define OTF_SYM_TAG(SYM, TAG) \
1784 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1785 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1788 #define OTF_TAG_STR(TAG, P) \
1790 (P)[0] = (char) (TAG >> 24); \
1791 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1792 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1793 (P)[3] = (char) (TAG & 0xFF); \
1797 static struct OpenTypeSpec *
1798 macfont_get_open_type_spec (Lisp_Object otf_spec)
1800 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1807 spec->script = XCAR (otf_spec);
1808 if (! NILP (spec->script))
1810 OTF_SYM_TAG (spec->script, spec->script_tag);
1811 val = assq_no_quit (spec->script, Votf_script_alist);
1812 if (CONSP (val) && SYMBOLP (XCDR (val)))
1813 spec->script = XCDR (val);
1815 spec->script = Qnil;
1818 spec->script_tag = 0x44464C54; /* "DFLT" */
1819 otf_spec = XCDR (otf_spec);
1820 spec->langsys_tag = 0;
1821 if (! NILP (otf_spec))
1823 val = XCAR (otf_spec);
1825 OTF_SYM_TAG (val, spec->langsys_tag);
1826 otf_spec = XCDR (otf_spec);
1828 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1829 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1833 val = XCAR (otf_spec);
1836 len = Flength (val);
1838 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1840 : malloc (XINT (len) * sizeof *spec->features[i]));
1841 if (! spec->features[i])
1843 if (i > 0 && spec->features[0])
1844 free (spec->features[0]);
1848 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1850 if (NILP (XCAR (val)))
1856 OTF_SYM_TAG (XCAR (val), tag);
1857 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1860 spec->nfeatures[i] = j;
1865 static CFMutableDictionaryRef
1866 macfont_create_attributes_with_spec (Lisp_Object spec)
1868 Lisp_Object tmp, extra;
1869 CFMutableArrayRef langarray = NULL;
1870 CFCharacterSetRef charset = NULL;
1871 CFStringRef charset_string = NULL;
1872 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1873 Lisp_Object script = Qnil;
1874 Lisp_Object registry;
1875 int cf_charset_idx, i;
1876 struct OpenTypeSpec *otspec = NULL;
1878 enum font_property_index index;
1881 } numeric_traits[] =
1882 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
1883 {{-0.4, 50}, /* light */
1884 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1885 {0, 100}, /* normal */
1886 {0.24, 140}, /* (semi-bold + normal) / 2 */
1887 {0.4, 200}, /* bold */
1888 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1889 {FONT_SLANT_INDEX, kCTFontSlantTrait,
1890 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1891 {FONT_WIDTH_INDEX, kCTFontWidthTrait,
1892 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1894 registry = AREF (spec, FONT_REGISTRY_INDEX);
1896 || EQ (registry, Qascii_0)
1897 || EQ (registry, Qiso10646_1)
1898 || EQ (registry, Qunicode_bmp))
1899 cf_charset_idx = -1;
1904 cf_charset_idx = macfont_get_charset (registry);
1905 if (cf_charset_idx < 0)
1907 charset = cf_charset_table[cf_charset_idx].cf_charset;
1908 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1909 lang = cf_charset_table[cf_charset_idx].lang;
1912 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1915 CFArrayAppendValue (langarray, lang);
1919 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1920 CONSP (extra); extra = XCDR (extra))
1922 Lisp_Object key, val;
1925 key = XCAR (tmp), val = XCDR (tmp);
1926 if (EQ (key, QClang))
1929 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1934 for (; CONSP (val); val = XCDR (val))
1935 if (SYMBOLP (XCAR (val)))
1938 cfstring_create_with_string_noencode (SYMBOL_NAME
1943 CFArrayAppendValue (langarray, lang);
1947 else if (EQ (key, QCotf))
1949 otspec = macfont_get_open_type_spec (val);
1952 script = otspec->script;
1954 else if (EQ (key, QCscript))
1958 if (! NILP (script) && ! charset)
1960 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1962 if (CONSP (chars) && CONSP (CDR (chars)))
1964 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1965 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1967 if (! string || !cs)
1975 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1976 if (CHARACTERP (XCAR (chars)))
1978 UniChar unichars[2];
1980 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1982 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1984 CFStringAppendCharacters (string, unichars, count);
1985 CFCharacterSetAddCharactersInRange (cs, range);
1988 /* CFCharacterSetCreateWithCharactersInString does not
1989 handle surrogate pairs properly as of Mac OS X 10.5. */
1990 charset_string = string;
1994 attributes = CFDictionaryCreateMutable (NULL, 0,
1995 &kCFTypeDictionaryKeyCallBacks,
1996 &kCFTypeDictionaryValueCallBacks);
2000 tmp = AREF (spec, FONT_FAMILY_INDEX);
2001 if (SYMBOLP (tmp) && ! NILP (tmp))
2003 CFStringRef family = macfont_create_family_with_symbol (tmp);
2007 CFDictionaryAddValue (attributes, kCTFontFamilyNameAttribute,
2012 traits = CFDictionaryCreateMutable (NULL, 4,
2013 &kCFTypeDictionaryKeyCallBacks,
2014 &kCFTypeDictionaryValueCallBacks);
2018 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
2020 tmp = AREF (spec, numeric_traits[i].index);
2023 CGPoint *point = numeric_traits[i].points;
2024 CGFloat floatval = (XINT (tmp) >> 8); // XXX
2027 while (point->y < floatval)
2029 if (point == numeric_traits[i].points)
2031 else if (point->y == CGFLOAT_MAX)
2033 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
2034 * ((point->x - (point - 1)->x)
2035 / (point->y - (point - 1)->y)));
2038 else if (floatval < -1.0)
2040 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2043 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2047 if (CFDictionaryGetCount (traits))
2048 CFDictionaryAddValue (attributes, kCTFontTraitsAttribute, traits);
2051 CFDictionaryAddValue (attributes, kCTFontCharacterSetAttribute,
2054 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2057 CFDictionaryAddValue (attributes, kCTFontLanguagesAttribute, langarray);
2064 CFRelease (attributes);
2069 if (langarray) CFRelease (langarray);
2070 if (charset && cf_charset_idx < 0) CFRelease (charset);
2071 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2072 if (traits) CFRelease (traits);
2075 if (otspec->nfeatures[0] > 0)
2076 free (otspec->features[0]);
2077 if (otspec->nfeatures[1] > 0)
2078 free (otspec->features[1]);
2086 macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
2087 CFCharacterSetRef charset,
2089 CFArrayRef languages)
2091 Boolean result = true;
2093 if (charset || VECTORP (chars))
2095 CFCharacterSetRef desc_charset =
2096 CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
2098 if (desc_charset == NULL)
2103 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2104 else /* VECTORP (chars) */
2108 for (j = 0; j < ASIZE (chars); j++)
2109 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2110 && CFCharacterSetIsLongCharacterMember (desc_charset,
2111 XFASTINT (AREF (chars, j))))
2113 if (j == ASIZE (chars))
2116 CFRelease (desc_charset);
2119 if (result && languages)
2120 result = mac_font_descriptor_supports_languages (desc, languages);
2126 macfont_traits_distance (CTFontSymbolicTraits sym_traits1,
2127 CTFontSymbolicTraits sym_traits2)
2129 CTFontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2132 /* We prefer synthetic bold of italic to synthetic italic of bold
2133 when both bold and italic are available but bold-italic is not
2135 if (diff & kCTFontTraitBold)
2136 distance |= (1 << 0);
2137 if (diff & kCTFontTraitItalic)
2138 distance |= (1 << 1);
2139 if (diff & kCTFontTraitMonoSpace)
2140 distance |= (1 << 2);
2146 macfont_closest_traits_index_p (CFArrayRef traits_array,
2147 CTFontSymbolicTraits target,
2150 CFIndex i, count = CFArrayGetCount (traits_array);
2151 CTFontSymbolicTraits traits;
2154 traits = ((CTFontSymbolicTraits) (uintptr_t)
2155 CFArrayGetValueAtIndex (traits_array, index));
2156 my_distance = macfont_traits_distance (target, traits);
2158 for (i = 0; i < count; i++)
2161 traits = ((CTFontSymbolicTraits) (uintptr_t)
2162 CFArrayGetValueAtIndex (traits_array, i));
2163 if (macfont_traits_distance (target, traits) < my_distance)
2171 macfont_list (struct frame *f, Lisp_Object spec)
2173 Lisp_Object val = Qnil, family, extra;
2175 CFStringRef family_name = NULL;
2176 CFMutableDictionaryRef attributes = NULL, traits;
2177 Lisp_Object chars = Qnil;
2179 CTFontSymbolicTraits synth_sym_traits = 0;
2180 CFArrayRef families;
2181 CFIndex families_count;
2182 CFCharacterSetRef charset = NULL;
2183 CFArrayRef languages = NULL;
2187 family = AREF (spec, FONT_FAMILY_INDEX);
2188 if (! NILP (family))
2190 family_name = macfont_create_family_with_symbol (family);
2191 if (family_name == NULL)
2195 attributes = macfont_create_attributes_with_spec (spec);
2199 languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
2201 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2202 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2204 traits = ((CFMutableDictionaryRef)
2205 CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
2207 n = FONT_SLANT_NUMERIC (spec);
2208 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2210 synth_sym_traits |= kCTFontTraitItalic;
2212 CFDictionaryRemoveValue (traits, kCTFontSlantTrait);
2215 n = FONT_WEIGHT_NUMERIC (spec);
2216 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2218 synth_sym_traits |= kCTFontTraitBold;
2220 CFDictionaryRemoveValue (traits, kCTFontWeightTrait);
2224 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2226 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2228 if (CFStringHasPrefix (language, CFSTR ("ja"))
2229 || CFStringHasPrefix (language, CFSTR ("ko"))
2230 || CFStringHasPrefix (language, CFSTR ("zh")))
2231 synth_sym_traits |= kCTFontTraitMonoSpace;
2234 /* Create array of families. */
2236 families = CFArrayCreate (NULL, (const void **) &family_name,
2237 1, &kCFTypeArrayCallBacks);
2240 CFStringRef pref_family;
2241 CFIndex families_count, pref_family_index = -1;
2243 families = macfont_copy_available_families_cache ();
2244 if (families == NULL)
2247 families_count = CFArrayGetCount (families);
2249 /* Move preferred family to the front if exists. */
2251 mac_font_create_preferred_family_for_attributes (attributes);
2255 CFArrayGetFirstIndexOfValue (families,
2256 CFRangeMake (0, families_count),
2258 CFRelease (pref_family);
2260 if (pref_family_index > 0)
2262 CFMutableArrayRef mutable_families =
2263 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2265 if (mutable_families)
2267 CFArrayAppendValue (mutable_families,
2268 CFArrayGetValueAtIndex (families,
2269 pref_family_index));
2270 CFArrayAppendArray (mutable_families, families,
2271 CFRangeMake (0, pref_family_index));
2272 if (pref_family_index + 1 < families_count)
2273 CFArrayAppendArray (mutable_families, families,
2274 CFRangeMake (pref_family_index + 1,
2276 - (pref_family_index + 1)));
2277 CFRelease (families);
2278 families = mutable_families;
2283 charset = CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
2287 CFDictionaryRemoveValue (attributes, kCTFontCharacterSetAttribute);
2291 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2294 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2295 if (CONSP (val) && VECTORP (XCDR (val)))
2303 CFRetain (languages);
2304 CFDictionaryRemoveValue (attributes, kCTFontLanguagesAttribute);
2308 extra = AREF (spec, FONT_EXTRA_INDEX);
2309 families_count = CFArrayGetCount (families);
2310 for (i = 0; i < families_count; i++)
2312 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2313 CTFontDescriptorRef pat_desc;
2315 CFIndex descs_count;
2316 CFMutableArrayRef filtered_descs, traits_array;
2320 CFDictionarySetValue (attributes, kCTFontFamilyNameAttribute,
2322 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2326 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2327 10.7 returns NULL if pat_desc represents the LastResort font.
2328 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2329 trailing "s") for such a font. */
2330 if (!CFEqual (family_name, CFSTR ("LastResort")))
2331 descs = CTFontDescriptorCreateMatchingFontDescriptors (pat_desc, NULL);
2334 CTFontDescriptorRef lr_desc =
2335 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2338 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2339 &kCFTypeArrayCallBacks);
2340 CFRelease (lr_desc);
2345 CFRelease (pat_desc);
2349 descs_count = CFArrayGetCount (descs);
2350 if (descs_count == 0
2351 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2360 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2361 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2362 for (j = 0; j < descs_count; j++)
2364 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2365 CFDictionaryRef dict;
2367 CTFontSymbolicTraits sym_traits;
2369 dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute);
2373 num = CFDictionaryGetValue (dict, kCTFontSymbolicTrait);
2376 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2380 && !(synth_sym_traits & kCTFontTraitMonoSpace)
2381 && (((sym_traits & kCTFontTraitMonoSpace) != 0)
2382 != (spacing >= FONT_SPACING_MONO)))
2385 /* Don't use a color bitmap font unless its family is
2386 explicitly specified. */
2387 if ((sym_traits & kCTFontTraitColorGlyphs) && NILP (family))
2391 && !macfont_supports_charset_and_languages_p (desc, charset,
2395 CFArrayAppendValue (filtered_descs, desc);
2396 CFArrayAppendValue (traits_array,
2397 (const void *) (uintptr_t) sym_traits);
2401 descs = filtered_descs;
2402 descs_count = CFArrayGetCount (descs);
2404 for (j = 0; j < descs_count; j++)
2406 CTFontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2407 CTFontSymbolicTraits sym_traits =
2408 ((CTFontSymbolicTraits) (uintptr_t)
2409 CFArrayGetValueAtIndex (traits_array, j));
2410 CTFontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2412 mask_min = ((synth_sym_traits ^ sym_traits)
2413 & (kCTFontTraitItalic | kCTFontTraitBold));
2414 if (FONT_SLANT_NUMERIC (spec) < 0)
2415 mask_min &= ~kCTFontTraitItalic;
2416 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2417 mask_min &= ~kCTFontTraitBold;
2419 mask_max = (synth_sym_traits & ~sym_traits);
2420 /* Synthetic bold does not work for bitmap-only fonts on Mac
2422 if ((mask_min ^ mask_max) & kCTFontTraitBold)
2424 CFNumberRef format =
2425 CTFontDescriptorCopyAttribute (desc, kCTFontFormatAttribute);
2429 uint32_t format_val;
2431 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2433 && format_val == kCTFontFormatBitmap)
2434 mask_max &= ~kCTFontTraitBold;
2438 mask_min |= (mask_max & kCTFontTraitMonoSpace);
2440 for (mmask = (mask_min & kCTFontTraitMonoSpace);
2441 mmask <= (mask_max & kCTFontTraitMonoSpace);
2442 mmask += kCTFontTraitMonoSpace)
2443 for (bmask = (mask_min & kCTFontTraitBold);
2444 bmask <= (mask_max & kCTFontTraitBold);
2445 bmask += kCTFontTraitBold)
2446 for (imask = (mask_min & kCTFontTraitItalic);
2447 imask <= (mask_max & kCTFontTraitItalic);
2448 imask += kCTFontTraitItalic)
2450 CTFontSymbolicTraits synth = (imask | bmask | mmask);
2453 || macfont_closest_traits_index_p (traits_array,
2454 (sym_traits | synth),
2457 entity = macfont_descriptor_entity (desc, extra, synth);
2458 if (! NILP (entity))
2459 val = Fcons (entity, val);
2464 CFRelease (traits_array);
2468 CFRelease (families);
2469 val = Fnreverse (val);
2475 FONT_ADD_LOG ("macfont-list", spec, val);
2476 if (charset) CFRelease (charset);
2477 if (languages) CFRelease (languages);
2478 if (attributes) CFRelease (attributes);
2479 if (family_name) CFRelease (family_name);
2487 macfont_match (struct frame * frame, Lisp_Object spec)
2489 Lisp_Object entity = Qnil;
2490 CFMutableDictionaryRef attributes;
2491 CTFontDescriptorRef pat_desc = NULL, desc = NULL;
2495 attributes = macfont_create_attributes_with_spec (spec);
2498 pat_desc = CTFontDescriptorCreateWithAttributes (attributes);
2499 CFRelease (attributes);
2503 desc = CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
2504 CFRelease (pat_desc);
2508 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2514 FONT_ADD_LOG ("macfont-match", spec, entity);
2519 macfont_list_family (struct frame *frame)
2521 Lisp_Object list = Qnil;
2522 CFArrayRef families;
2526 families = macfont_copy_available_families_cache ();
2529 CFIndex i, count = CFArrayGetCount (families);
2531 for (i = 0; i < count; i++)
2532 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2533 CFRelease (families);
2542 macfont_free_entity (Lisp_Object entity)
2544 Lisp_Object val = assq_no_quit (QCfont_entity,
2545 AREF (entity, FONT_EXTRA_INDEX));
2546 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2554 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2556 Lisp_Object val, font_object;
2557 CFStringRef font_name;
2558 struct macfont_info *macfont_info = NULL;
2562 CTFontSymbolicTraits sym_traits;
2564 int len, i, total_width;
2566 CGFloat ascent, descent, leading;
2568 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2570 || XTYPE (XCDR (val)) != Lisp_Misc
2571 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2573 font_name = XSAVE_POINTER (XCDR (val), 0);
2574 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2576 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2581 macfont = CTFontCreateWithName (font_name, size, NULL);
2584 int fontsize = (int) [((NSFont *) macfont) pointSize];
2585 if (fontsize != size) size = fontsize;
2591 font_object = font_build_object (VECSIZE (struct macfont_info),
2592 Qmac_ct, entity, size);
2593 font = XFONT_OBJECT (font_object);
2594 font->pixel_size = size;
2595 font->driver = &macfont_driver;
2596 font->encoding_charset = font->repertory_charset = -1;
2600 macfont_info = (struct macfont_info *) font;
2601 macfont_info->macfont = macfont;
2602 macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
2604 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2605 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2606 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2609 macfont_info->screen_font = NULL;
2610 macfont_info->cache = macfont_lookup_cache (font_name);
2611 macfont_retain_cache (macfont_info->cache);
2612 macfont_info->metrics = NULL;
2613 macfont_info->metrics_nrows = 0;
2614 macfont_info->synthetic_italic_p = 0;
2615 macfont_info->synthetic_bold_p = 0;
2616 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2617 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2618 if (!(sym_traits & kCTFontTraitItalic)
2619 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2620 macfont_info->synthetic_italic_p = 1;
2621 if (!(sym_traits & kCTFontTraitBold)
2622 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2623 macfont_info->synthetic_bold_p = 1;
2624 if (sym_traits & kCTFontTraitMonoSpace)
2625 macfont_info->spacing = MACFONT_SPACING_MONO;
2626 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2627 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2628 == FONT_SPACING_SYNTHETIC_MONO))
2629 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2630 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2631 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2634 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2636 macfont_info->antialias =
2637 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2639 macfont_info->color_bitmap_p = 0;
2640 if (sym_traits & kCTFontTraitColorGlyphs)
2641 macfont_info->color_bitmap_p = 1;
2643 glyph = macfont_get_glyph_for_character (font, ' ');
2644 if (glyph != kCGFontIndexInvalid)
2645 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2647 /* dirty workaround */
2648 font->space_width = pixel_size;
2650 total_width = font->space_width;
2651 for (i = 1; i < 95; i++)
2653 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2654 if (glyph == kCGFontIndexInvalid)
2656 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2659 font->average_width = total_width / 95;
2661 font->average_width = font->space_width; /* XXX */
2663 if (!(macfont_info->screen_font
2664 && mac_screen_font_get_metrics (macfont_info->screen_font,
2665 &ascent, &descent, &leading)))
2667 CFStringRef family_name;
2669 ascent = CTFontGetAscent (macfont);
2670 descent = CTFontGetDescent (macfont);
2671 leading = CTFontGetLeading (macfont);
2672 /* AppKit and WebKit do some adjustment to the heights of
2673 Courier, Helvetica, and Times. */
2674 family_name = CTFontCopyFamilyName (macfont);
2677 if (CFEqual (family_name, CFSTR ("Courier"))
2678 || CFEqual (family_name, CFSTR ("Helvetica"))
2679 || CFEqual (family_name, CFSTR ("Times")))
2680 ascent += (ascent + descent) * .15f;
2681 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2686 CFRelease (family_name);
2689 font->ascent = ascent + 0.5f;
2690 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2691 if (CONSP (val) && !NILP (XCDR (val)))
2692 font->descent = descent + 0.5f;
2694 font->descent = descent + leading + 0.5f;
2695 font->height = font->ascent + font->descent;
2697 font->underline_position = - CTFontGetUnderlinePosition (macfont) + 0.5f;
2698 font->underline_thickness = CTFontGetUnderlineThickness (macfont) + 0.5f;
2702 /* Unfortunately Xft doesn't provide a way to get minimum char
2703 width. So, we use space_width instead. */
2704 font->min_width = font->max_width = font->space_width; /* XXX */
2706 font->baseline_offset = 0;
2707 font->relative_compose = 0;
2708 font->default_ascent = 0;
2709 font->vertical_centering = 0;
2715 macfont_close (struct font *font)
2717 struct macfont_info *macfont_info = (struct macfont_info *) font;
2719 if (macfont_info->cache)
2724 CFRelease (macfont_info->macfont);
2725 CGFontRelease (macfont_info->cgfont);
2726 if (macfont_info->screen_font)
2727 CFRelease (macfont_info->screen_font);
2728 macfont_release_cache (macfont_info->cache);
2729 for (i = 0; i < macfont_info->metrics_nrows; i++)
2730 if (macfont_info->metrics[i])
2731 xfree (macfont_info->metrics[i]);
2732 if (macfont_info->metrics)
2733 xfree (macfont_info->metrics);
2734 macfont_info->cache = NULL;
2740 macfont_has_char (Lisp_Object font, int c)
2743 CFCharacterSetRef charset;
2746 if (FONT_ENTITY_P (font))
2751 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2753 name = XSAVE_POINTER (val, 0);
2754 charset = macfont_get_cf_charset_for_name (name);
2757 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2759 result = CFCharacterSetIsLongCharacterMember (charset, c);
2766 macfont_encode_char (struct font *font, int c)
2771 glyph = macfont_get_glyph_for_character (font, c);
2774 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2778 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2779 struct font_metrics *metrics)
2784 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2785 for (i = 1; i < nglyphs; i++)
2787 struct font_metrics m;
2788 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2793 if (width + m.lbearing < metrics->lbearing)
2794 metrics->lbearing = width + m.lbearing;
2795 if (width + m.rbearing > metrics->rbearing)
2796 metrics->rbearing = width + m.rbearing;
2797 if (m.ascent > metrics->ascent)
2798 metrics->ascent = m.ascent;
2799 if (m.descent > metrics->descent)
2800 metrics->descent = m.descent;
2807 metrics->width = width;
2811 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2812 bool with_background)
2814 struct frame * f = s->f;
2815 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2816 CGRect background_rect;
2817 CGPoint text_position;
2820 CGFloat font_size = CTFontGetSize (macfont_info->macfont);
2821 bool no_antialias_p =
2822 (NILP (ns_antialias_text)
2823 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2824 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2825 && font_size <= macfont_antialias_threshold));
2826 int len = to - from;
2827 struct face *face = s->face;
2828 CGContextRef context;
2832 if (with_background)
2833 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2834 s->width, FONT_HEIGHT (s->font));
2836 background_rect = CGRectNull;
2838 text_position = CGPointMake (x, -y);
2839 glyphs = xmalloc (sizeof (CGGlyph) * len);
2841 CGFloat advance_delta = 0;
2843 CGFloat total_width = 0;
2845 positions = xmalloc (sizeof (CGPoint) * len);
2846 for (i = 0; i < len; i++)
2850 glyphs[i] = s->char2b[from + i];
2851 width = (s->padding_p ? 1
2852 : macfont_glyph_extents (s->font, glyphs[i],
2853 NULL, &advance_delta,
2855 positions[i].x = total_width + advance_delta;
2857 total_width += width;
2861 context = [[NSGraphicsContext currentContext] graphicsPort];
2862 CGContextSaveGState (context);
2864 if (!CGRectIsNull (background_rect))
2866 if (s->hl == DRAW_MOUSE_FACE)
2868 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2870 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2872 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2873 CGContextFillRects (context, &background_rect, 1);
2876 if (macfont_info->cgfont)
2878 CGAffineTransform atfm;
2880 CGContextScaleCTM (context, 1, -1);
2881 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2882 if (macfont_info->synthetic_italic_p)
2883 atfm = synthetic_italic_atfm;
2885 atfm = CGAffineTransformIdentity;
2886 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2888 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2889 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2890 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2893 CGContextSetShouldAntialias (context, false);
2895 CGContextSetTextMatrix (context, atfm);
2896 CGContextSetTextPosition (context, text_position.x, text_position.y);
2898 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2899 if (macfont_info->color_bitmap_p
2900 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2901 && CTFontDrawGlyphs != NULL
2907 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2912 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2914 CGContextSetFont (context, macfont_info->cgfont);
2915 CGContextSetFontSize (context, font_size);
2916 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2923 CGContextRestoreGState (context);
2931 macfont_shape (Lisp_Object lgstring)
2933 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2934 struct macfont_info *macfont_info = (struct macfont_info *) font;
2935 CTFontRef macfont = macfont_info->macfont;
2936 ptrdiff_t glyph_len, len, i, j;
2939 CFIndex *nonbmp_indices;
2942 struct mac_glyph_layout *glyph_layouts;
2944 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2946 for (i = 0; i < glyph_len; i++)
2948 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2952 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2958 if (INT_MAX / 2 < len)
2959 memory_full (SIZE_MAX);
2961 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2962 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2963 for (i = j = 0; i < len; i++)
2965 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2967 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2969 nonbmp_indices[j] = i + j;
2973 nonbmp_indices[j] = len + j; /* sentinel */
2977 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2981 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2982 if (macfont_info->screen_font)
2983 used = mac_screen_font_shape (macfont_info->screen_font, string,
2984 glyph_layouts, glyph_len);
2986 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2997 for (i = 0; i < used; i++)
2999 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
3000 struct mac_glyph_layout *gl = glyph_layouts + i;
3002 struct font_metrics metrics;
3003 int xoff, yoff, wadjust;
3007 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
3008 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
3011 from = gl->comp_range.location;
3012 /* Convert UTF-16 index to UTF-32. */
3014 while (nonbmp_indices[j] < from)
3017 LGLYPH_SET_FROM (lglyph, from);
3019 to = gl->comp_range.location + gl->comp_range.length;
3020 /* Convert UTF-16 index to UTF-32. */
3021 while (nonbmp_indices[j] < to)
3024 LGLYPH_SET_TO (lglyph, to - 1);
3026 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3027 the composition is trivial. */
3031 if (unichars[gl->string_index] >= 0xD800
3032 && unichars[gl->string_index] < 0xDC00)
3033 c = (((unichars[gl->string_index] - 0xD800) << 10)
3034 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3036 c = unichars[gl->string_index];
3037 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3039 LGLYPH_SET_CHAR (lglyph, c);
3043 unsigned long cc = gl->glyph_id;
3044 LGLYPH_SET_CODE (lglyph, cc);
3047 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3048 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3049 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3050 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3051 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3052 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3054 xoff = lround (gl->advance_delta);
3055 yoff = lround (- gl->baseline_delta);
3056 wadjust = lround (gl->advance);
3057 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3061 vec = Fmake_vector (make_number (3), Qnil);
3062 ASET (vec, 0, make_number (xoff));
3063 ASET (vec, 1, make_number (yoff));
3064 ASET (vec, 2, make_number (wadjust));
3065 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3071 return make_number (used);
3074 /* Structures for the UVS subtable (format 14) in the cmap table. */
3075 typedef UInt8 UINT24[3];
3077 #pragma pack(push, 1)
3078 struct variation_selector_record
3080 UINT24 var_selector;
3081 UInt32 default_uvs_offset, non_default_uvs_offset;
3086 UInt32 length, num_var_selector_records;
3087 struct variation_selector_record variation_selector_records[1];
3089 #define SIZEOF_UVS_TABLE_HEADER \
3090 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3092 struct unicode_value_range
3094 UINT24 start_unicode_value;
3095 UInt8 additional_count;
3097 struct default_uvs_table {
3098 UInt32 num_unicode_value_ranges;
3099 struct unicode_value_range unicode_value_ranges[1];
3101 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3102 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3106 UINT24 unicode_value;
3109 struct non_default_uvs_table
3111 UInt32 num_uvs_mappings;
3112 struct uvs_mapping uvs_mappings[1];
3114 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3115 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3118 /* Read big endian values. The argument LVAL must be an lvalue. */
3119 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3120 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3121 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3122 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3123 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3124 /* Succeeding one byte should also be accessible. */
3125 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3126 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3128 /* Return UVS subtable for the specified FONT. If the subtable is not
3129 found or ill-formatted, then return NULL. */
3132 mac_font_copy_uvs_table (CTFontRef font)
3134 CFDataRef cmap_table, uvs_table = NULL;
3136 cmap_table = CTFontCopyTable (font, cmapFontTableTag,
3137 kCTFontTableOptionNoOptions);
3140 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3141 struct uvs_table *uvs;
3142 struct variation_selector_record *records;
3143 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3146 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3150 cmap_len = CFDataGetLength (cmap_table);
3151 if (sizeof_sfntCMapHeader > cmap_len)
3154 ntables = BUINT16_VALUE (cmap->numTables);
3155 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3156 / sizeof_sfntCMapEncoding))
3159 for (i = 0; i < ntables; i++)
3160 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3161 == kFontUnicodePlatform)
3162 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3163 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3165 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3169 || uvs_offset > cmap_len
3170 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3173 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3174 uvs_len = BUINT32_VALUE (uvs->length);
3175 if (uvs_len > cmap_len - uvs_offset
3176 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3179 if (BUINT16_VALUE (uvs->format) != 14)
3182 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3183 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3184 / sizeof (struct variation_selector_record)))
3187 records = uvs->variation_selector_records;
3188 for (i = 0; i < nrecords; i++)
3190 UInt32 default_uvs_offset, non_default_uvs_offset;
3192 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3193 if (default_uvs_offset)
3195 struct default_uvs_table *default_uvs;
3198 if (default_uvs_offset > uvs_len
3199 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3200 > uvs_len - default_uvs_offset))
3203 default_uvs = ((struct default_uvs_table *)
3204 ((UInt8 *) uvs + default_uvs_offset));
3205 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3206 if (nranges > ((uvs_len - default_uvs_offset
3207 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3208 / sizeof (struct unicode_value_range)))
3210 /* Now 2 * nranges can't overflow, so we can safely use
3211 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3212 mac_font_get_glyphs_for_variants. */
3215 non_default_uvs_offset =
3216 BUINT32_VALUE (records[i].non_default_uvs_offset);
3217 if (non_default_uvs_offset)
3219 struct non_default_uvs_table *non_default_uvs;
3222 if (non_default_uvs_offset > uvs_len
3223 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3224 > uvs_len - non_default_uvs_offset))
3227 non_default_uvs = ((struct non_default_uvs_table *)
3228 ((UInt8 *) uvs + non_default_uvs_offset));
3229 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3230 if (nmappings > ((uvs_len - non_default_uvs_offset
3231 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3232 / sizeof (struct uvs_mapping)))
3234 /* Now 2 * nmappings can't overflow, so we can safely
3235 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3236 in mac_font_get_glyphs_for_variants. */
3240 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3243 CFRelease (cmap_table);
3249 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3250 sequence consisting of the given base character C and each
3251 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3252 result (explained below) into the corresponding GLYPHS[i]. If the
3253 entry is found in the Default UVS Table, then the result is 0. If
3254 the entry is found in the Non-Default UVS Table, then the result is
3255 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3256 elements in SELECTORS must be sorted in strictly increasing
3260 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3261 const UTF32Char selectors[], CGGlyph glyphs[],
3264 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3265 struct variation_selector_record *records = uvs->variation_selector_records;
3267 UInt32 ir, nrecords;
3268 dispatch_queue_t queue =
3269 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3270 dispatch_group_t group = dispatch_group_create ();
3272 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3275 while (i < count && ir < nrecords)
3277 UInt32 default_uvs_offset, non_default_uvs_offset;
3279 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3281 glyphs[i++] = kCGFontIndexInvalid;
3284 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3290 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3291 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3292 non_default_uvs_offset =
3293 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3294 dispatch_group_async (group, queue, ^{
3295 glyphs[i] = kCGFontIndexInvalid;
3297 if (default_uvs_offset)
3299 struct default_uvs_table *default_uvs =
3300 (struct default_uvs_table *) ((UInt8 *) uvs
3301 + default_uvs_offset);
3302 struct unicode_value_range *ranges =
3303 default_uvs->unicode_value_ranges;
3307 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3310 UInt32 mid = (lo + hi) / 2;
3312 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3318 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3319 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3323 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3325 struct non_default_uvs_table *non_default_uvs =
3326 (struct non_default_uvs_table *) ((UInt8 *) uvs
3327 + non_default_uvs_offset);
3328 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3332 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3335 UInt32 mid = (lo + hi) / 2;
3337 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3343 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3344 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3351 glyphs[i++] = kCGFontIndexInvalid;
3352 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3353 dispatch_release (group);
3357 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3359 CFDataRef uvs_table;
3360 CTCharacterCollection uvs_collection;
3364 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3368 UTF32Char selectors[256];
3369 CGGlyph glyphs[256];
3371 for (i = 0; i < 16; i++)
3372 selectors[i] = 0xFE00 + i;
3373 for (; i < 256; i++)
3374 selectors[i] = 0xE0100 + (i - 16);
3375 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3376 for (i = 0; i < 256; i++)
3378 CGGlyph glyph = glyphs[i];
3380 if (uvs_collection != kCTCharacterCollectionIdentityMapping
3381 && glyph != kCGFontIndexInvalid)
3382 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3383 if (glyph == kCGFontIndexInvalid)
3387 variations[i] = (glyph ? glyph
3388 : macfont_get_glyph_for_character (font, c));
3398 static const char *const macfont_booleans[] = {
3404 static const char *const macfont_non_booleans[] = {
3412 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3414 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3418 mac_font_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3419 CFArrayRef languages)
3421 Boolean result = true;
3422 CFArrayRef desc_languages =
3423 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3425 if (desc_languages == NULL)
3429 CFRange range = CFRangeMake (0, CFArrayGetCount (desc_languages));
3430 CFIndex i, languages_count = CFArrayGetCount (languages);
3432 for (i = 0; i < languages_count; i++)
3434 CFStringRef language = CFArrayGetValueAtIndex (languages, i);
3436 if (!CFArrayContainsValue (desc_languages, range, language)
3437 /* PingFang SC contains "zh" and "zh-Hant" as covered
3438 languages, but does not contain "zh-Hans". */
3439 && !(CFEqual (language, CFSTR ("zh-Hans"))
3440 && CFArrayContainsValue (desc_languages, range,
3447 CFRelease (desc_languages);
3454 mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3456 CFStringRef result = NULL;
3457 CFStringRef charset_string =
3458 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3460 if (charset_string && CFStringGetLength (charset_string) > 0)
3462 CFStringRef keys[] = {
3463 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3464 kCTLanguageAttributeName
3466 CFSTR ("NSLanguage")
3469 CFTypeRef values[] = {NULL};
3470 CFIndex num_values = 0;
3471 CFArrayRef languages
3472 = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
3474 if (languages && CFArrayGetCount (languages) > 0)
3476 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3477 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3480 CFCharacterSetRef charset =
3481 CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
3483 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3488 CFAttributedStringRef attr_string = NULL;
3489 CTLineRef ctline = NULL;
3490 CFDictionaryRef attrs
3491 = CFDictionaryCreate (NULL, (const void **) keys,
3492 (const void **) values, num_values,
3493 &kCFTypeDictionaryKeyCallBacks,
3494 &kCFTypeDictionaryValueCallBacks);
3498 attr_string = CFAttributedStringCreate (NULL, charset_string,
3504 ctline = CTLineCreateWithAttributedString (attr_string);
3505 CFRelease (attr_string);
3509 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3510 CFIndex i, nruns = CFArrayGetCount (runs);
3513 for (i = 0; i < nruns; i++)
3515 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3516 CFDictionaryRef attributes = CTRunGetAttributes (run);
3517 CTFontRef font_in_run;
3519 if (attributes == NULL)
3522 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3523 if (font_in_run == NULL)
3527 else if (!mac_font_equal_in_postscript_name (font,
3531 if (nruns > 0 && i == nruns)
3532 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3541 static inline double
3542 mac_font_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3544 return CTFontGetAdvancesForGlyphs (font, kCTFontOrientationDefault,
3548 static inline CGRect
3549 mac_font_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3551 return CTFontGetBoundingRectsForGlyphs (font, kCTFontOrientationDefault,
3556 mac_font_create_available_families (void)
3558 CFMutableArrayRef families = NULL;
3559 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3563 CFIndex i, count = CFArrayGetCount (orig_families);
3565 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3567 for (i = 0; i < count; i++)
3569 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3571 if (!CFStringHasPrefix (family, CFSTR ("."))
3572 && (CTFontManagerCompareFontFamilyNames (family,
3573 CFSTR ("LastResort"),
3575 != kCFCompareEqualTo))
3576 CFArrayAppendValue (families, family);
3578 CFRelease (orig_families);
3585 mac_font_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3588 CFStringRef name1, name2;
3594 name1 = CTFontCopyPostScriptName (font1);
3597 name2 = CTFontCopyPostScriptName (font2);
3600 result = CFEqual (name1, name2);
3610 mac_font_create_line_with_string_and_font (CFStringRef string,
3613 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3614 CFTypeRef values[] = {NULL, NULL};
3615 CFDictionaryRef attributes = NULL;
3616 CFAttributedStringRef attr_string = NULL;
3617 CTLineRef ctline = NULL;
3618 float float_zero = 0.0f;
3620 values[0] = macfont;
3621 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3624 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3625 (const void **) values,
3627 &kCFTypeDictionaryKeyCallBacks,
3628 &kCFTypeDictionaryValueCallBacks);
3629 CFRelease (values[1]);
3633 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3634 CFRelease (attributes);
3638 ctline = CTLineCreateWithAttributedString (attr_string);
3639 CFRelease (attr_string);
3643 /* Abandon if ctline contains some fonts other than the
3645 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3646 CFIndex i, nruns = CFArrayGetCount (runs);
3648 for (i = 0; i < nruns; i++)
3650 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3651 CFDictionaryRef attributes = CTRunGetAttributes (run);
3652 CTFontRef font_in_run;
3654 if (attributes == NULL)
3657 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3658 if (font_in_run == NULL)
3660 if (!mac_font_equal_in_postscript_name (macfont, font_in_run))
3674 mac_font_shape (CTFontRef font, CFStringRef string,
3675 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3677 CFIndex used, result = 0;
3678 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
3683 used = CTLineGetGlyphCount (ctline);
3684 if (used <= glyph_len)
3686 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3687 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3688 CGFloat total_advance = 0;
3689 CFIndex total_glyph_count = 0;
3691 for (k = 0; k < ctrun_count; k++)
3693 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3694 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3695 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3696 CFRange string_range, comp_range, range;
3697 CFIndex *permutation;
3699 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3700 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3704 #define RIGHT_TO_LEFT_P permutation
3706 /* Now the `comp_range' member of struct mac_glyph_layout is
3707 temporarily used as a work area such that:
3708 glbuf[i].comp_range.location =
3709 min {compRange[i + 1].location, ...,
3710 compRange[glyph_count - 1].location,
3711 maxRange (stringRangeForCTRun)}
3712 glbuf[i].comp_range.length = maxRange (compRange[i])
3713 where compRange[i] is the range of composed characters
3714 containing i-th glyph. */
3715 string_range = CTRunGetStringRange (ctrun);
3716 min_location = string_range.location + string_range.length;
3717 for (i = 0; i < glyph_count; i++)
3719 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3720 CFIndex glyph_index;
3723 if (!RIGHT_TO_LEFT_P)
3724 glyph_index = glyph_count - i - 1;
3727 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3730 CFStringGetRangeOfComposedCharactersAtIndex (string,
3732 gl->comp_range.location = min_location;
3733 gl->comp_range.length = rng.location + rng.length;
3734 if (rng.location < min_location)
3735 min_location = rng.location;
3738 /* Fill the `comp_range' member of struct mac_glyph_layout,
3739 and setup a permutation for right-to-left text. */
3740 comp_range = CFRangeMake (string_range.location, 0);
3741 range = CFRangeMake (0, 0);
3744 struct mac_glyph_layout *gl =
3745 glbuf + range.location + range.length;
3747 if (gl->comp_range.length
3748 > comp_range.location + comp_range.length)
3749 comp_range.length = gl->comp_range.length - comp_range.location;
3750 min_location = gl->comp_range.location;
3753 if (min_location >= comp_range.location + comp_range.length)
3755 comp_range.length = min_location - comp_range.location;
3756 for (i = 0; i < range.length; i++)
3758 glbuf[range.location + i].comp_range = comp_range;
3759 if (RIGHT_TO_LEFT_P)
3760 permutation[range.location + i] =
3761 range.location + range.length - i - 1;
3764 comp_range = CFRangeMake (min_location, 0);
3765 range.location += range.length;
3767 if (range.location == glyph_count)
3772 /* Then fill the remaining members. */
3773 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3776 struct mac_glyph_layout *gl;
3779 if (!RIGHT_TO_LEFT_P)
3780 gl = glbuf + range.location;
3785 src = glyph_count - 1 - range.location;
3786 dest = permutation[src];
3790 CFIndex tmp = gl->string_index;
3792 gl->string_index = glbuf[src].string_index;
3793 glbuf[src].string_index = tmp;
3796 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3798 CTRunGetPositions (ctrun, range, &position);
3799 gl->advance_delta = position.x - total_advance;
3800 gl->baseline_delta = position.y;
3801 gl->advance = (gl->advance_delta
3802 + CTRunGetTypographicBounds (ctrun, range,
3804 total_advance += gl->advance;
3807 if (RIGHT_TO_LEFT_P)
3808 xfree (permutation);
3810 #undef RIGHT_TO_LEFT_P
3812 total_glyph_count += glyph_count;
3822 /* The function below seems to cause a memory leak for the CFString
3823 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3824 10.6.3. For now, we use the NSGlyphInfo version instead. */
3825 #if USE_CT_GLYPH_INFO
3827 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3830 CGGlyph result = kCGFontIndexInvalid;
3831 UniChar characters[] = {0xfffd};
3833 CFAttributedStringRef attr_string = NULL;
3834 CTLineRef ctline = NULL;
3836 string = CFStringCreateWithCharacters (NULL, characters,
3837 ARRAYELTS (characters));
3841 CTGlyphInfoRef glyph_info =
3842 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3843 CFDictionaryRef attributes = NULL;
3847 CFStringRef keys[] = {kCTFontAttributeName,
3848 kCTGlyphInfoAttributeName};
3849 CFTypeRef values[] = {font, glyph_info};
3851 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3852 (const void **) values,
3854 &kCFTypeDictionaryKeyCallBacks,
3855 &kCFTypeDictionaryValueCallBacks);
3856 CFRelease (glyph_info);
3860 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3861 CFRelease (attributes);
3867 ctline = CTLineCreateWithAttributedString (attr_string);
3868 CFRelease (attr_string);
3872 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3874 if (CFArrayGetCount (runs) > 0)
3876 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3877 CFDictionaryRef attributes = CTRunGetAttributes (run);
3881 CTFontRef font_in_run =
3882 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3885 && mac_font_equal_in_postscript_name (font_in_run, font))
3887 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3888 if (result >= CTFontGetGlyphCount (font))
3889 result = kCGFontIndexInvalid;
3901 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3903 CFArrayRef result = NULL;
3905 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3906 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3907 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3910 CTFontRef user_font =
3911 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3915 CFArrayRef languages =
3916 CFArrayCreate (NULL, (const void **) &language, 1,
3917 &kCFTypeArrayCallBacks);
3921 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3923 CFRelease (languages);
3925 CFRelease (user_font);
3928 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3929 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3931 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3932 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3936 for (i = 0; macfont_language_default_font_names[i].language; i++)
3938 if (CFEqual (macfont_language_default_font_names[i].language,
3941 CFMutableArrayRef descriptors =
3942 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3949 macfont_language_default_font_names[i].font_names[j];
3952 CFDictionaryRef attributes =
3953 CFDictionaryCreate (NULL,
3955 &kCTFontNameAttribute),
3957 &macfont_language_default_font_names[i].font_names[j]),
3958 1, &kCFTypeDictionaryKeyCallBacks,
3959 &kCFTypeDictionaryValueCallBacks);
3963 CTFontDescriptorRef pat_desc =
3964 CTFontDescriptorCreateWithAttributes (attributes);
3968 CTFontDescriptorRef descriptor =
3969 CTFontDescriptorCreateMatchingFontDescriptor (pat_desc, NULL);
3973 CFArrayAppendValue (descriptors, descriptor);
3974 CFRelease (descriptor);
3976 CFRelease (pat_desc);
3978 CFRelease (attributes);
3981 result = descriptors;
3993 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3994 CFArrayRef languages)
3996 CFStringRef result = NULL;
3997 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3998 CFArrayRef descriptors =
3999 mac_font_copy_default_descriptors_for_language (language);
4003 CFIndex i, count = CFArrayGetCount (descriptors);
4005 for (i = 0; i < count; i++)
4007 CTFontDescriptorRef descriptor =
4008 CFArrayGetValueAtIndex (descriptors, i);
4010 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4013 CFStringRef family =
4014 CTFontDescriptorCopyAttribute (descriptor,
4015 kCTFontFamilyNameAttribute);
4018 if (!CFStringHasPrefix (family, CFSTR ("."))
4019 && !CFEqual (family, CFSTR ("LastResort")))
4029 CFRelease (descriptors);
4036 macfont_get_nsctfont (struct font *font)
4038 struct macfont_info *macfont_info = (struct macfont_info *) font;
4039 CTFontRef macfont = macfont_info->macfont;
4041 return (void *) macfont;
4045 mac_register_font_driver (struct frame *f)
4047 register_font_driver (&macfont_driver, f);
4052 syms_of_macfont (void)
4054 /* Core Text, for Mac OS X. */
4055 DEFSYM (Qmac_ct, "mac-ct");
4056 macfont_driver.type = Qmac_ct;
4057 register_font_driver (&macfont_driver, NULL);
4059 /* The font property key specifying the font design destination. The
4060 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4061 text. (See the documentation of X Logical Font Description
4062 Conventions.) In the Mac font driver, 1 means the screen font is
4063 used for calculating some glyph metrics. You can see the
4064 difference with Monaco 8pt or 9pt, for example. */
4065 DEFSYM (QCdestination, ":destination");
4067 /* The boolean-valued font property key specifying the use of leading. */
4068 DEFSYM (QCminspace, ":minspace");
4070 macfont_family_cache = Qnil;
4071 staticpro (&macfont_family_cache);