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_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
44 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
45 static CFArrayRef mac_ctfont_create_available_families (void);
46 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
47 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
49 static CFComparisonResult mac_font_family_compare (const void *,
50 const void *, void *);
51 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
53 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
54 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
55 struct mac_glyph_layout *, CFIndex);
57 mac_font_copy_default_descriptors_for_language (CFStringRef language);
60 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
61 CFArrayRef languages);
64 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
65 CTCharacterCollection,
69 struct macfont_metrics;
71 /* The actual structure for Mac font that can be cast to struct font. */
78 ScreenFontRef screen_font;
79 struct macfont_cache *cache;
80 struct macfont_metrics **metrics;
82 bool_bf synthetic_italic_p : 1;
83 bool_bf synthetic_bold_p : 1;
85 unsigned antialias : 2;
86 bool_bf color_bitmap_p : 1;
89 /* Values for the `spacing' member in `struct macfont_info'. */
93 MACFONT_SPACING_PROPORTIONAL,
95 MACFONT_SPACING_SYNTHETIC_MONO,
98 /* Values for the `antialias' member in `struct macfont_info'. */
102 MACFONT_ANTIALIAS_DEFAULT,
103 MACFONT_ANTIALIAS_OFF,
104 MACFONT_ANTIALIAS_ON,
107 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
108 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
109 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
111 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
112 static const CGFloat synthetic_bold_factor = 0.024;
114 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
115 FontSymbolicTraits *);
116 static void macfont_store_descriptor_attributes (FontDescriptorRef,
118 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
121 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
122 static int macfont_glyph_extents (struct font *, CGGlyph,
123 struct font_metrics *, CGFloat *, int);
124 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
125 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
129 static Boolean macfont_closest_traits_index_p (CFArrayRef, FontSymbolicTraits,
131 static CFDataRef mac_font_copy_uvs_table (FontRef);
132 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
134 CGGlyph [], CFIndex);
136 /* From CFData to a lisp string. Always returns a unibyte string. */
139 cfdata_to_lisp (CFDataRef data)
141 CFIndex len = CFDataGetLength (data);
142 Lisp_Object result = make_uninit_string (len);
144 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
151 /* From CFString to a lisp string. Returns a unibyte string
152 containing a UTF-8 byte sequence. */
155 cfstring_to_lisp_nodecode (CFStringRef string)
157 Lisp_Object result = Qnil;
159 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
163 CFIndex i, length = CFStringGetLength (string);
165 for (i = 0; i < length; i++)
166 if (CFStringGetCharacterAtIndex (string, i) == 0)
170 return make_unibyte_string (s, strlen (s));
173 data = CFStringCreateExternalRepresentation (NULL, string,
174 kCFStringEncodingUTF8, '?');
177 result = cfdata_to_lisp (data);
184 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
185 cfstring_create_with_utf8_cstring, this function preserves NUL
189 cfstring_create_with_string_noencode (Lisp_Object s)
191 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
192 kCFStringEncodingUTF8, false);
195 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
196 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
197 kCFStringEncodingMacRoman, false);
203 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
205 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
207 return advancement.width;
211 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
214 #if USE_CT_GLYPH_INFO
215 return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
218 CGGlyph result = kCGFontIndexInvalid;
219 NSFont *nsFont = (NSFont *) font;
220 unichar characters[] = {0xfffd};
222 [NSString stringWithCharacters:characters
223 length:ARRAYELTS (characters)];
224 NSGlyphInfo *glyphInfo =
225 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
226 collection:collection
228 NSDictionary *attributes =
229 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
230 glyphInfo,NSGlyphInfoAttributeName,nil];
231 NSTextStorage *textStorage =
232 [[NSTextStorage alloc] initWithString:string
233 attributes:attributes];
234 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
235 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
236 NSFont *fontInTextStorage;
238 [layoutManager addTextContainer:textContainer];
239 [textContainer release];
240 [textStorage addLayoutManager:layoutManager];
241 [layoutManager release];
244 (void) [layoutManager glyphRangeForTextContainer:textContainer];
246 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
247 effectiveRange:NULL];
248 if (fontInTextStorage == nsFont
249 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
251 NSGlyph glyph = [layoutManager glyphAtIndex:0];
253 if (glyph < [nsFont numberOfGlyphs])
257 [textStorage release];
265 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
267 NSFont *result, *font;
269 font = [NSFont fontWithName:((NSString *) name) size:size];
270 result = [font screenFont];
272 return (ScreenFontRef)[result retain];
277 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
278 CGFloat *descent, CGFloat *leading)
280 NSFont *nsFont = [(NSFont *)font printerFont];
281 NSTextStorage *textStorage;
282 NSLayoutManager *layoutManager;
283 NSTextContainer *textContainer;
285 NSPoint spaceLocation;
288 textStorage = [[NSTextStorage alloc] initWithString:@" "];
289 layoutManager = [[NSLayoutManager alloc] init];
290 textContainer = [[NSTextContainer alloc] init];
292 [textStorage setFont:nsFont];
293 [textContainer setLineFragmentPadding:0];
294 [layoutManager setUsesScreenFonts:YES];
296 [layoutManager addTextContainer:textContainer];
297 [textContainer release];
298 [textStorage addLayoutManager:layoutManager];
299 [layoutManager release];
301 if (!(textStorage && layoutManager && textContainer))
303 [textStorage release];
308 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
309 effectiveRange:NULL];
310 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
311 [textStorage release];
313 *ascent = spaceLocation.y;
314 *descent = NSHeight (usedRect) - spaceLocation.y;
316 descender = [nsFont descender];
317 if (- descender < *descent)
319 *leading = *descent + descender;
320 *descent = - descender;
327 mac_font_shape_1 (NSFont *font, NSString *string,
328 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
333 NSTextStorage *textStorage;
334 NSLayoutManager *layoutManager;
335 NSTextContainer *textContainer;
336 NSUInteger stringLength;
337 NSPoint spaceLocation;
338 NSUInteger used, numberOfGlyphs;
340 textStorage = [[NSTextStorage alloc] initWithString:string];
341 layoutManager = [[NSLayoutManager alloc] init];
342 textContainer = [[NSTextContainer alloc] init];
344 /* Append a trailing space to measure baseline position. */
345 [textStorage appendAttributedString:([[[NSAttributedString alloc]
346 initWithString:@" "] autorelease])];
347 [textStorage setFont:font];
348 [textContainer setLineFragmentPadding:0];
349 [layoutManager setUsesScreenFonts:screen_font_p];
351 [layoutManager addTextContainer:textContainer];
352 [textContainer release];
353 [textStorage addLayoutManager:layoutManager];
354 [layoutManager release];
356 if (!(textStorage && layoutManager && textContainer))
358 [textStorage release];
363 stringLength = [string length];
366 (void) [layoutManager glyphRangeForTextContainer:textContainer];
368 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
370 /* Remove the appended trailing space because otherwise it may
371 generate a wrong result for a right-to-left text. */
372 [textStorage beginEditing];
373 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
374 [textStorage endEditing];
375 (void) [layoutManager glyphRangeForTextContainer:textContainer];
378 while (i < stringLength)
381 NSFont *fontInTextStorage =
382 [textStorage attribute:NSFontAttributeName atIndex:i
383 longestEffectiveRange:&range
384 inRange:(NSMakeRange (0, stringLength))];
386 if (!(fontInTextStorage == font
387 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
389 i = NSMaxRange (range);
391 if (i < stringLength)
392 /* Make the test `used <= glyph_len' below fail if textStorage
393 contained some fonts other than the specified one. */
394 used = glyph_len + 1;
397 NSRange range = NSMakeRange (0, stringLength);
399 range = [layoutManager glyphRangeForCharacterRange:range
400 actualCharacterRange:NULL];
401 numberOfGlyphs = NSMaxRange (range);
402 used = numberOfGlyphs;
403 for (i = 0; i < numberOfGlyphs; i++)
404 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
408 if (0 < used && used <= glyph_len)
410 NSUInteger glyphIndex, prevGlyphIndex;
411 unsigned char bidiLevel;
412 NSUInteger *permutation;
413 NSRange compRange, range;
414 CGFloat totalAdvance;
417 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
420 /* For now we assume the direction is not changed within the
422 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
423 glyphs:NULL characterIndexes:NULL
424 glyphInscriptions:NULL elasticBits:NULL
425 bidiLevels:&bidiLevel];
427 permutation = xmalloc (sizeof (NSUInteger) * used);
431 #define RIGHT_TO_LEFT_P permutation
433 /* Fill the `comp_range' member of struct mac_glyph_layout, and
434 setup a permutation for right-to-left text. */
435 compRange = NSMakeRange (0, 0);
436 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
439 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
440 NSUInteger characterIndex =
441 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
443 gl->string_index = characterIndex;
445 if (characterIndex >= NSMaxRange (compRange))
447 compRange.location = NSMaxRange (compRange);
450 NSRange characterRange =
452 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
455 NSMaxRange (characterRange) - compRange.location;
456 [layoutManager glyphRangeForCharacterRange:compRange
457 actualCharacterRange:&characterRange];
458 characterIndex = NSMaxRange (characterRange) - 1;
460 while (characterIndex >= NSMaxRange (compRange));
463 for (i = 0; i < range.length; i++)
464 permutation[range.location + i] = NSMaxRange (range) - i - 1;
466 range = NSMakeRange (NSMaxRange (range), 0);
469 gl->comp_range.location = compRange.location;
470 gl->comp_range.length = compRange.length;
472 while (++glyphIndex < numberOfGlyphs)
473 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
477 for (i = 0; i < range.length; i++)
478 permutation[range.location + i] = NSMaxRange (range) - i - 1;
480 /* Then fill the remaining members. */
481 glyphIndex = prevGlyphIndex = 0;
482 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
485 if (!RIGHT_TO_LEFT_P)
492 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
493 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
494 inTextContainer:textContainer rectCount:&nrects];
496 totalAdvance = NSMaxX (glyphRects[0]);
499 for (i = 0; i < used; i++)
501 struct mac_glyph_layout *gl;
503 NSUInteger nextGlyphIndex;
508 if (!RIGHT_TO_LEFT_P)
509 gl = glyph_layouts + i;
512 NSUInteger dest = permutation[i];
514 gl = glyph_layouts + dest;
517 CFIndex tmp = gl->string_index;
519 gl->string_index = glyph_layouts[i].string_index;
520 glyph_layouts[i].string_index = tmp;
523 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
525 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
526 gl->baseline_delta = spaceLocation.y - location.y;
528 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
531 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
534 if (!RIGHT_TO_LEFT_P)
538 if (prevGlyphIndex == 0)
539 glyphRange = NSMakeRange (0, nextGlyphIndex);
541 glyphRange = NSMakeRange (glyphIndex,
542 nextGlyphIndex - glyphIndex);
545 rectArrayForGlyphRange:glyphRange
546 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
547 inTextContainer:textContainer rectCount:&nrects];
548 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
549 gl->advance_delta = location.x - totalAdvance;
550 gl->advance = maxX - totalAdvance;
557 if (nextGlyphIndex == numberOfGlyphs)
558 glyphRange = NSMakeRange (prevGlyphIndex,
559 numberOfGlyphs - prevGlyphIndex);
561 glyphRange = NSMakeRange (prevGlyphIndex,
562 glyphIndex + 1 - prevGlyphIndex);
565 rectArrayForGlyphRange:glyphRange
566 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
567 inTextContainer:textContainer rectCount:&nrects];
568 minX = min (NSMinX (glyphRects[0]), totalAdvance);
569 gl->advance = totalAdvance - minX;
571 gl->advance_delta = location.x - totalAdvance;
574 prevGlyphIndex = glyphIndex + 1;
575 glyphIndex = nextGlyphIndex;
581 #undef RIGHT_TO_LEFT_P
585 [textStorage release];
591 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
592 struct mac_glyph_layout *glyph_layouts,
595 return mac_font_shape_1 ([(NSFont *)font printerFont],
597 glyph_layouts, glyph_len, YES);
601 get_cgcolor(unsigned long idx, struct frame *f)
603 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
605 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
606 NSInteger noc = [nsColor numberOfComponents];
607 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
610 [nsColor getComponents: components];
611 cgColor = CGColorCreate (colorSpace, components);
616 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
618 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
619 CGContextSetFillColorWithColor (context, refcol_) ; \
620 CGColorRelease (refcol_); \
622 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
624 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
625 CGContextSetFillColorWithColor (context, refcol_); \
626 CGColorRelease (refcol_); \
628 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
630 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
631 CGContextSetStrokeColorWithColor (context, refcol_); \
632 CGColorRelease (refcol_); \
637 /* Mac font driver. */
643 /* characters to distinguish the charset from the others */
645 /* additional constraint by language */
648 CFCharacterSetRef cf_charset;
649 CFStringRef cf_charset_string;
650 } cf_charset_table[] =
651 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
652 { "iso8859-2", { 0x00A0, 0x010E }},
653 { "iso8859-3", { 0x00A0, 0x0108 }},
654 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
655 { "iso8859-5", { 0x00A0, 0x0401 }},
656 { "iso8859-6", { 0x00A0, 0x060C }},
657 { "iso8859-7", { 0x00A0, 0x0384 }},
658 { "iso8859-8", { 0x00A0, 0x05D0 }},
659 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
660 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
661 { "iso8859-11", { 0x00A0, 0x0E01 }},
662 { "iso8859-13", { 0x00A0, 0x201C }},
663 { "iso8859-14", { 0x00A0, 0x0174 }},
664 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
665 { "iso8859-16", { 0x00A0, 0x0218}},
666 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
667 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
668 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
669 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
670 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
671 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
672 { "cns11643.1992-3", { 0x201A9 }},
673 { "cns11643.1992-4", { 0x20057 }},
674 { "cns11643.1992-5", { 0x20000 }},
675 { "cns11643.1992-6", { 0x20003 }},
676 { "cns11643.1992-7", { 0x20055 }},
677 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
678 { "jisx0212.1990-0", { 0x4E44 }},
679 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
680 { "jisx0213.2000-2", { 0xFA49 }},
681 { "jisx0213.2004-1", { 0x20B9F }},
682 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
683 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
684 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
685 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
686 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
687 { "unicode-sip", { 0x20000 }},
691 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
694 CFStringRef language;
695 CFStringRef font_names[3];
696 } macfont_language_default_font_names[] = {
697 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
698 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
700 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
701 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
703 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
704 CFSTR ("STXihei"), /* 10.4 - 10.5 */
706 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
707 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
713 static CGFloat macfont_antialias_threshold;
716 macfont_update_antialias_threshold (void)
722 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
723 kCFPreferencesCurrentApplication,
726 macfont_antialias_threshold = threshold;
729 static inline Lisp_Object
730 macfont_intern_prop_cfstring (CFStringRef cfstring)
732 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
734 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
737 static inline CFIndex
738 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
749 unichars[0] = (c >> 10) + 0xD800;
750 unichars[1] = (c & 0x3FF) + 0xDC00;
757 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
758 FontSymbolicTraits *sym_traits)
762 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
763 OS X 10.6 when the value is greater than or equal to 1 << 31. */
764 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
766 *sym_traits = (FontSymbolicTraits) sint64_value;
775 macfont_store_descriptor_attributes (FontDescriptorRef desc,
776 Lisp_Object spec_or_entity)
779 CFDictionaryRef dict;
783 str = mac_font_descriptor_copy_attribute (desc,
784 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
787 ASET (spec_or_entity, FONT_FAMILY_INDEX,
788 macfont_intern_prop_cfstring (str));
791 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
795 enum font_property_index index;
799 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
800 {{-0.4, 50}, /* light */
801 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
802 {0, 100}, /* normal */
803 {0.24, 140}, /* (semi-bold + normal) / 2 */
804 {0.4, 200}, /* bold */
805 {CGFLOAT_MAX, CGFLOAT_MAX}}},
806 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
807 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
808 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
809 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
812 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
814 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
815 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
817 CGPoint *point = numeric_traits[i].points;
819 while (point->x < floatval)
821 if (point == numeric_traits[i].points)
823 else if (point->x == CGFLOAT_MAX)
825 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
826 * ((point->y - (point - 1)->y)
827 / (point->x - (point - 1)->x)));
828 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
829 make_number (lround (floatval)));
833 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
836 FontSymbolicTraits sym_traits;
839 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
840 spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
841 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
842 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
847 num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
848 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
849 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
851 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
857 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
858 FontSymbolicTraits synth_sym_traits)
861 CFDictionaryRef dict;
862 FontSymbolicTraits sym_traits = 0;
865 entity = font_make_entity ();
867 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
868 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
870 macfont_store_descriptor_attributes (desc, entity);
872 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
875 CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
878 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
881 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
882 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
883 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
884 name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
885 font_put_extra (entity, QCfont_entity,
886 make_save_ptr_int ((void *) name, sym_traits));
887 if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
888 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
889 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
890 if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
891 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
892 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
893 if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
894 ASET (entity, FONT_SPACING_INDEX,
895 make_number (FONT_SPACING_SYNTHETIC_MONO));
900 /* Cache for font family name symbols vs CFStrings. A value of nil
901 means the cache has been invalidated. Otherwise the value is a Lisp
902 hash table whose keys are symbols and the value for a key is either
903 nil (no corresponding family name) or a Lisp save value wrapping the
904 corresponding family name in CFString. */
906 static Lisp_Object macfont_family_cache;
909 macfont_invalidate_family_cache (void)
911 if (HASH_TABLE_P (macfont_family_cache))
913 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
914 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
916 for (i = 0; i < size; ++i)
917 if (!NILP (HASH_HASH (h, i)))
919 Lisp_Object value = HASH_VALUE (h, i);
921 if (SAVE_VALUEP (value))
922 CFRelease (XSAVE_POINTER (value, 0));
924 macfont_family_cache = Qnil;
929 macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
931 if (HASH_TABLE_P (macfont_family_cache))
933 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
934 ptrdiff_t i = hash_lookup (h, symbol, NULL);
938 Lisp_Object value = HASH_VALUE (h, i);
940 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
950 macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
952 struct Lisp_Hash_Table *h;
957 if (!HASH_TABLE_P (macfont_family_cache))
963 macfont_family_cache = Fmake_hash_table (2, args);
966 h = XHASH_TABLE (macfont_family_cache);
967 i = hash_lookup (h, symbol, &hash);
968 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
971 Lisp_Object old_value = HASH_VALUE (h, i);
973 if (SAVE_VALUEP (old_value))
974 CFRelease (XSAVE_POINTER (old_value, 0));
975 set_hash_value_slot (h, i, value);
978 hash_put (h, symbol, value, hash);
981 /* Cache of all the available font family names except "LastResort"
982 and those start with ".". NULL means the cache has been invalidated.
983 Otherwise, the value is CFArray of CFStrings and the elements are
984 sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
985 OS X 10.6 and later). */
987 static CFArrayRef macfont_available_families_cache = NULL;
990 macfont_invalidate_available_families_cache (void)
992 if (macfont_available_families_cache)
994 CFRelease (macfont_available_families_cache);
995 macfont_available_families_cache = NULL;
1000 macfont_handle_font_change_notification (CFNotificationCenterRef center,
1002 CFStringRef name, const void *object,
1003 CFDictionaryRef userInfo)
1005 macfont_invalidate_family_cache ();
1006 macfont_invalidate_available_families_cache ();
1010 macfont_init_font_change_handler (void)
1012 static bool initialized = false;
1018 CFNotificationCenterAddObserver
1019 (CFNotificationCenterGetLocalCenter (), NULL,
1020 macfont_handle_font_change_notification,
1021 kCTFontManagerRegisteredFontsChangedNotification,
1022 NULL, CFNotificationSuspensionBehaviorCoalesce);
1026 macfont_copy_available_families_cache (void)
1028 macfont_init_font_change_handler ();
1030 if (macfont_available_families_cache == NULL)
1031 macfont_available_families_cache = mac_font_create_available_families ();
1033 return (macfont_available_families_cache
1034 ? CFRetain (macfont_available_families_cache) : NULL);
1038 macfont_create_family_with_symbol (Lisp_Object symbol)
1040 CFStringRef result = NULL, family_name;
1041 CFDictionaryRef attributes = NULL;
1042 FontDescriptorRef pat_desc = NULL;
1044 if (macfont_get_family_cache_if_present (symbol, &result))
1045 return result ? CFRetain (result) : NULL;
1047 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1051 CFDictionaryCreate (NULL,
1052 (const void **) &MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1053 (const void **) &family_name, 1,
1054 &kCFTypeDictionaryKeyCallBacks,
1055 &kCFTypeDictionaryValueCallBacks);
1056 CFRelease (family_name);
1060 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
1061 CFRelease (attributes);
1065 FontDescriptorRef desc =
1066 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
1071 mac_font_descriptor_copy_attribute (desc,
1072 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
1075 macfont_set_family_cache (symbol, result);
1076 CFRelease (pat_desc);
1082 #define WIDTH_FRAC_BITS (4)
1083 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1085 struct macfont_metrics
1087 unsigned char lbearing_low, rbearing_low;
1088 signed lbearing_high : 4, rbearing_high : 4;
1089 unsigned char ascent_low, descent_low;
1090 signed ascent_high : 4, descent_high : 4;
1092 /* These two members are used for fixed-point representation of
1093 glyph width. The `width_int' member is an integer that is
1094 closest to the width. The `width_frac' member is the fractional
1095 adjustment representing a value in [-.5, .5], multiplied by
1096 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1097 the advance delta for centering instead of the glyph width. */
1098 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1101 #define METRICS_VALUE(metrics, member) \
1102 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1103 #define METRICS_SET_VALUE(metrics, member, value) \
1104 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1105 (metrics)->member##_high = tmp >> 8;} while (0)
1109 METRICS_INVALID = -1, /* metrics entry is invalid */
1110 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1113 #define METRICS_STATUS(metrics) \
1114 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1115 #define METRICS_SET_STATUS(metrics, status) \
1116 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1117 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1119 #define METRICS_NCOLS_PER_ROW (128)
1120 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1121 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1124 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1125 struct font_metrics *metrics, CGFloat *advance_delta,
1126 int force_integral_p)
1128 struct macfont_info *macfont_info = (struct macfont_info *) font;
1129 FontRef macfont = macfont_info->macfont;
1131 struct macfont_metrics *cache;
1134 row = glyph / METRICS_NCOLS_PER_ROW;
1135 col = glyph % METRICS_NCOLS_PER_ROW;
1136 if (row >= macfont_info->metrics_nrows)
1138 macfont_info->metrics =
1139 xrealloc (macfont_info->metrics,
1140 sizeof (struct macfont_metrics *) * (row + 1));
1141 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1142 (sizeof (struct macfont_metrics *)
1143 * (row + 1 - macfont_info->metrics_nrows)));
1144 macfont_info->metrics_nrows = row + 1;
1146 if (macfont_info->metrics[row] == NULL)
1148 struct macfont_metrics *new;
1151 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1152 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1153 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1154 macfont_info->metrics[row] = new;
1156 cache = macfont_info->metrics[row] + col;
1158 if (METRICS_STATUS (cache) == METRICS_INVALID)
1162 if (macfont_info->screen_font)
1163 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1165 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1167 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1168 advance delta value. */
1169 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1170 fwidth = (font->pixel_size - fwidth) / 2;
1171 cache->width_int = lround (fwidth);
1172 cache->width_frac = lround ((fwidth - cache->width_int)
1173 * WIDTH_FRAC_SCALE);
1174 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1176 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1177 width = font->pixel_size;
1179 width = cache->width_int;
1183 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1185 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1187 if (macfont_info->synthetic_italic_p)
1189 /* We assume the members a, b, c, and d in
1190 synthetic_italic_atfm are non-negative. */
1192 CGPointApplyAffineTransform (bounds.origin,
1193 synthetic_italic_atfm);
1195 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1197 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1200 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1202 bounds = CGRectInset (bounds, d, d);
1204 switch (macfont_info->spacing)
1206 case MACFONT_SPACING_PROPORTIONAL:
1207 bounds.origin.x += - (cache->width_frac
1208 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1210 case MACFONT_SPACING_MONO:
1212 case MACFONT_SPACING_SYNTHETIC_MONO:
1213 bounds.origin.x += (cache->width_int
1214 + (cache->width_frac
1215 / (CGFloat) WIDTH_FRAC_SCALE));
1218 if (bounds.size.width > 0)
1220 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1221 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1222 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1224 bounds = CGRectIntegral (bounds);
1225 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1226 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1227 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1228 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1230 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1231 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1232 metrics->width = width;
1233 metrics->ascent = METRICS_VALUE (cache, ascent);
1234 metrics->descent = METRICS_VALUE (cache, descent);
1239 switch (macfont_info->spacing)
1241 case MACFONT_SPACING_PROPORTIONAL:
1242 *advance_delta = (force_integral_p ? 0
1243 : - (cache->width_frac
1244 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1246 case MACFONT_SPACING_MONO:
1249 case MACFONT_SPACING_SYNTHETIC_MONO:
1250 *advance_delta = (force_integral_p ? cache->width_int
1252 + (cache->width_frac
1253 / (CGFloat) WIDTH_FRAC_SCALE)));
1261 static CFMutableDictionaryRef macfont_cache_dictionary;
1263 /* Threshold used in row_nkeys_or_perm. This must be less than or
1264 equal to the number of rows that are invalid as BMP (i.e., from
1265 U+D800 to U+DFFF). */
1266 #define ROW_PERM_OFFSET (8)
1268 /* The number of glyphs that can be stored in a value for a single
1269 entry of CFDictionary. */
1270 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1272 struct macfont_cache
1274 int reference_count;
1275 CFCharacterSetRef cf_charset;
1277 /* The cached glyph for a BMP character c is stored in
1278 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1279 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1280 unsigned char row_nkeys_or_perm[256];
1283 /* Number of rows for which the BMP cache is allocated so far.
1284 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1287 /* The cached glyph for a character c is stored as the (c %
1288 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1289 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1290 not stored here if row_nkeys_or_perm[c / 256] >=
1292 CFMutableDictionaryRef dictionary;
1296 /* UVS (Unicode Variation Sequence) subtable data, which is of
1297 type CFDataRef if available. NULL means it is not initialized
1298 yet. kCFNull means the subtable is not found and there is no
1299 suitable fallback table for this font. */
1302 /* Character collection specifying the destination of the mapping
1303 provided by `table' above. If `table' is obtained from the UVS
1304 subtable in the font cmap table, then the value of this member
1305 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1306 CharacterCollection collection;
1310 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1311 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1312 static void macfont_release_cache (struct macfont_cache *);
1313 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1314 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1315 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1316 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1317 CharacterCollection, CGFontIndex);
1318 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1320 static struct macfont_cache *
1321 macfont_lookup_cache (CFStringRef key)
1323 struct macfont_cache *cache;
1325 if (macfont_cache_dictionary == NULL)
1327 macfont_cache_dictionary =
1328 CFDictionaryCreateMutable (NULL, 0,
1329 &kCFTypeDictionaryKeyCallBacks, NULL);
1333 cache = ((struct macfont_cache *)
1334 CFDictionaryGetValue (macfont_cache_dictionary, key));
1338 FontRef macfont = mac_font_create_with_name (key, 0);
1342 cache = xzalloc (sizeof (struct macfont_cache));
1343 /* Treat the LastResort font as if it contained glyphs for
1344 all characters. This may look too rough, but neither
1345 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1346 for this font is correct for non-BMP characters on Mac OS
1348 if (CFEqual (key, CFSTR ("LastResort")))
1350 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1353 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1355 if (cache->cf_charset == NULL)
1356 cache->cf_charset = mac_font_copy_character_set (macfont);
1357 CFDictionaryAddValue (macfont_cache_dictionary, key,
1358 (const void *) cache);
1359 CFRelease (macfont);
1366 static struct macfont_cache *
1367 macfont_retain_cache (struct macfont_cache *cache)
1369 cache->reference_count++;
1375 macfont_release_cache (struct macfont_cache *cache)
1377 if (--cache->reference_count == 0)
1381 for (i = 0; i < cache->glyph.nrows; i++)
1382 xfree (cache->glyph.matrix[i]);
1383 xfree (cache->glyph.matrix);
1384 if (cache->glyph.dictionary)
1385 CFRelease (cache->glyph.dictionary);
1386 memset (&cache->glyph, 0, sizeof (cache->glyph));
1387 if (cache->uvs.table)
1388 CFRelease (cache->uvs.table);
1389 memset (&cache->uvs, 0, sizeof (cache->uvs));
1393 static CFCharacterSetRef
1394 macfont_get_cf_charset (struct font *font)
1396 struct macfont_info *macfont_info = (struct macfont_info *) font;
1398 return macfont_info->cache->cf_charset;
1401 static CFCharacterSetRef
1402 macfont_get_cf_charset_for_name (CFStringRef name)
1404 struct macfont_cache *cache = macfont_lookup_cache (name);
1406 return cache->cf_charset;
1410 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1412 struct macfont_info *macfont_info = (struct macfont_info *) font;
1413 FontRef macfont = macfont_info->macfont;
1414 struct macfont_cache *cache = macfont_info->cache;
1416 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1419 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1421 if (nkeys_or_perm < ROW_PERM_OFFSET)
1423 UniChar unichars[256], ch;
1427 dispatch_queue_t queue;
1428 dispatch_group_t group = NULL;
1432 CFMutableDictionaryRef dictionary;
1433 uintptr_t key, value;
1437 if (cache->glyph.dictionary == NULL)
1438 cache->glyph.dictionary =
1439 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1440 dictionary = cache->glyph.dictionary;
1441 key = c / NGLYPHS_IN_VALUE;
1442 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1443 value = ((uintptr_t)
1444 CFDictionaryGetValue (dictionary, (const void *) key));
1445 glyph = (value >> nshifts);
1449 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1452 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1455 glyph = kCGFontIndexInvalid;
1458 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1459 value |= ((uintptr_t) glyph << nshifts);
1460 CFDictionarySetValue (dictionary, (const void *) key,
1461 (const void *) value);
1467 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1468 group = dispatch_group_create ();
1469 dispatch_group_async (group, queue, ^{
1472 nkeys = nkeys_or_perm;
1473 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1474 if (CFDictionaryContainsKey (dictionary,
1475 (const void *) key))
1477 CFDictionaryRemoveValue (dictionary,
1478 (const void *) key);
1486 for (i = 0; i < 256; i++)
1489 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1490 unichars[len++] = ch;
1493 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1496 mac_font_get_glyphs_for_characters (macfont, unichars,
1500 int next = unichars[len - 1] % 256;
1503 glyphs[i] = kCGFontIndexInvalid;
1506 glyphs[i] = glyphs[len];
1513 glyphs[i] = kCGFontIndexInvalid;
1515 nrows = cache->glyph.nrows;
1516 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1517 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1519 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1520 sizeof (CGGlyph *) * nrows);
1521 cache->glyph.matrix[nrows - 1] = glyphs;
1522 cache->glyph.nrows = nrows;
1526 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1527 dispatch_release (group);
1531 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1535 uintptr_t key, value;
1539 if (cache->glyph.dictionary == NULL)
1540 cache->glyph.dictionary =
1541 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1542 key = c / NGLYPHS_IN_VALUE;
1543 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1544 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1545 (const void *) key);
1546 glyph = (value >> nshifts);
1549 UniChar unichars[2];
1551 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1553 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1557 glyph = kCGFontIndexInvalid;
1559 value |= ((uintptr_t) glyph << nshifts);
1560 CFDictionarySetValue (cache->glyph.dictionary,
1561 (const void *) key, (const void *) value);
1569 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1572 struct macfont_info *macfont_info = (struct macfont_info *) font;
1573 FontRef macfont = macfont_info->macfont;
1576 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1580 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1582 struct macfont_info *macfont_info = (struct macfont_info *) font;
1583 FontRef macfont = macfont_info->macfont;
1584 struct macfont_cache *cache = macfont_info->cache;
1585 CFDataRef result = NULL;
1587 if (cache->uvs.table == NULL)
1589 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1590 CharacterCollection uvs_collection =
1591 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1593 if (uvs_table == NULL
1594 && mac_font_get_glyph_for_cid (macfont,
1595 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1596 6480) != kCGFontIndexInvalid)
1598 /* If the glyph for U+4E55 is accessible via its CID 6480,
1599 then we use the Adobe-Japan1 UVS table, which maps a
1600 variation sequence to a CID, as a fallback. */
1601 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1603 if (mac_uvs_table_adobe_japan1 == NULL)
1604 mac_uvs_table_adobe_japan1 =
1605 CFDataCreateWithBytesNoCopy (NULL,
1606 mac_uvs_table_adobe_japan1_bytes,
1607 sizeof (mac_uvs_table_adobe_japan1_bytes),
1609 if (mac_uvs_table_adobe_japan1)
1611 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1612 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1615 if (uvs_table == NULL)
1616 cache->uvs.table = kCFNull;
1618 cache->uvs.table = uvs_table;
1619 cache->uvs.collection = uvs_collection;
1622 if (cache->uvs.table != kCFNull)
1624 result = cache->uvs.table;
1625 *collection = cache->uvs.collection;
1631 static Lisp_Object macfont_get_cache (struct frame *);
1632 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1633 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1634 static Lisp_Object macfont_list_family (struct frame *);
1635 static void macfont_free_entity (Lisp_Object);
1636 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1637 static void macfont_close (struct font *);
1638 static int macfont_has_char (Lisp_Object, int);
1639 static unsigned macfont_encode_char (struct font *, int);
1640 static void macfont_text_extents (struct font *, unsigned int *, int,
1641 struct font_metrics *);
1642 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1643 static Lisp_Object macfont_shape (Lisp_Object);
1644 static int macfont_variation_glyphs (struct font *, int c,
1645 unsigned variations[256]);
1646 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1648 static struct font_driver macfont_driver =
1650 LISP_INITIALLY_ZERO, /* Qmac_ct */
1651 0, /* case insensitive */
1655 macfont_list_family,
1656 macfont_free_entity,
1659 NULL, /* prepare_face */
1660 NULL, /* done_face */
1662 macfont_encode_char,
1663 macfont_text_extents,
1665 NULL, /* get_bitmap */
1666 NULL, /* free_bitmap */
1667 NULL, /* anchor_point */
1668 NULL, /* otf_capability */
1669 NULL, /* otf_drive */
1670 NULL, /* start_for_frame */
1671 NULL, /* end_for_frame */
1674 macfont_variation_glyphs,
1675 macfont_filter_properties,
1679 macfont_get_cache (struct frame * f)
1681 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1683 return (dpyinfo->name_list_element);
1687 macfont_get_charset (Lisp_Object registry)
1689 char *str = SSDATA (SYMBOL_NAME (registry));
1690 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1694 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1698 else if (str[i] == '*')
1705 regexp = make_unibyte_string (re, j);
1706 for (i = 0; cf_charset_table[i].name; i++)
1707 if (fast_c_string_match_ignore_case
1708 (regexp, cf_charset_table[i].name,
1709 strlen (cf_charset_table[i].name)) >= 0)
1711 if (! cf_charset_table[i].name)
1713 if (! cf_charset_table[i].cf_charset)
1715 int *uniquifier = cf_charset_table[i].uniquifier;
1716 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1719 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1723 for (j = 0; uniquifier[j]; j++)
1725 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1727 CFCharacterSetAddCharactersInRange (charset,
1728 CFRangeMake (uniquifier[j], 1));
1731 string = CFStringCreateWithCharacters (NULL, unichars, count);
1734 CFRelease (charset);
1737 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1739 CFRelease (charset);
1740 /* CFCharacterSetCreateWithCharactersInString does not handle
1741 surrogate pairs properly as of Mac OS X 10.5. */
1742 cf_charset_table[i].cf_charset_string = string;
1750 unsigned int script_tag, langsys_tag;
1752 unsigned int *features[2];
1755 #define OTF_SYM_TAG(SYM, TAG) \
1757 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1758 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1761 #define OTF_TAG_STR(TAG, P) \
1763 (P)[0] = (char) (TAG >> 24); \
1764 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1765 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1766 (P)[3] = (char) (TAG & 0xFF); \
1770 static struct OpenTypeSpec *
1771 macfont_get_open_type_spec (Lisp_Object otf_spec)
1773 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1780 spec->script = XCAR (otf_spec);
1781 if (! NILP (spec->script))
1783 OTF_SYM_TAG (spec->script, spec->script_tag);
1784 val = assq_no_quit (spec->script, Votf_script_alist);
1785 if (CONSP (val) && SYMBOLP (XCDR (val)))
1786 spec->script = XCDR (val);
1788 spec->script = Qnil;
1791 spec->script_tag = 0x44464C54; /* "DFLT" */
1792 otf_spec = XCDR (otf_spec);
1793 spec->langsys_tag = 0;
1794 if (! NILP (otf_spec))
1796 val = XCAR (otf_spec);
1798 OTF_SYM_TAG (val, spec->langsys_tag);
1799 otf_spec = XCDR (otf_spec);
1801 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1802 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1806 val = XCAR (otf_spec);
1809 len = Flength (val);
1811 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1813 : malloc (XINT (len) * sizeof *spec->features[i]));
1814 if (! spec->features[i])
1816 if (i > 0 && spec->features[0])
1817 free (spec->features[0]);
1821 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1823 if (NILP (XCAR (val)))
1829 OTF_SYM_TAG (XCAR (val), tag);
1830 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1833 spec->nfeatures[i] = j;
1838 static CFMutableDictionaryRef
1839 macfont_create_attributes_with_spec (Lisp_Object spec)
1841 Lisp_Object tmp, extra;
1842 CFMutableArrayRef langarray = NULL;
1843 CFCharacterSetRef charset = NULL;
1844 CFStringRef charset_string = NULL;
1845 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1846 Lisp_Object script = Qnil;
1847 Lisp_Object registry;
1848 int cf_charset_idx, i;
1849 struct OpenTypeSpec *otspec = NULL;
1851 enum font_property_index index;
1854 } numeric_traits[] =
1855 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1856 {{-0.4, 50}, /* light */
1857 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1858 {0, 100}, /* normal */
1859 {0.24, 140}, /* (semi-bold + normal) / 2 */
1860 {0.4, 200}, /* bold */
1861 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1862 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1863 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1864 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1865 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1867 registry = AREF (spec, FONT_REGISTRY_INDEX);
1869 || EQ (registry, Qascii_0)
1870 || EQ (registry, Qiso10646_1)
1871 || EQ (registry, Qunicode_bmp))
1872 cf_charset_idx = -1;
1877 cf_charset_idx = macfont_get_charset (registry);
1878 if (cf_charset_idx < 0)
1880 charset = cf_charset_table[cf_charset_idx].cf_charset;
1881 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1882 lang = cf_charset_table[cf_charset_idx].lang;
1885 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1888 CFArrayAppendValue (langarray, lang);
1892 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1893 CONSP (extra); extra = XCDR (extra))
1895 Lisp_Object key, val;
1898 key = XCAR (tmp), val = XCDR (tmp);
1899 if (EQ (key, QClang))
1902 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1907 for (; CONSP (val); val = XCDR (val))
1908 if (SYMBOLP (XCAR (val)))
1911 cfstring_create_with_string_noencode (SYMBOL_NAME
1916 CFArrayAppendValue (langarray, lang);
1920 else if (EQ (key, QCotf))
1922 otspec = macfont_get_open_type_spec (val);
1925 script = otspec->script;
1927 else if (EQ (key, QCscript))
1931 if (! NILP (script) && ! charset)
1933 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1935 if (CONSP (chars) && CONSP (CDR (chars)))
1937 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1938 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1940 if (! string || !cs)
1948 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1949 if (CHARACTERP (XCAR (chars)))
1951 UniChar unichars[2];
1953 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1955 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1957 CFStringAppendCharacters (string, unichars, count);
1958 CFCharacterSetAddCharactersInRange (cs, range);
1961 /* CFCharacterSetCreateWithCharactersInString does not
1962 handle surrogate pairs properly as of Mac OS X 10.5. */
1963 charset_string = string;
1967 attributes = CFDictionaryCreateMutable (NULL, 0,
1968 &kCFTypeDictionaryKeyCallBacks,
1969 &kCFTypeDictionaryValueCallBacks);
1973 tmp = AREF (spec, FONT_FAMILY_INDEX);
1974 if (SYMBOLP (tmp) && ! NILP (tmp))
1976 CFStringRef family = macfont_create_family_with_symbol (tmp);
1980 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1985 traits = CFDictionaryCreateMutable (NULL, 4,
1986 &kCFTypeDictionaryKeyCallBacks,
1987 &kCFTypeDictionaryValueCallBacks);
1991 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1993 tmp = AREF (spec, numeric_traits[i].index);
1996 CGPoint *point = numeric_traits[i].points;
1997 CGFloat floatval = (XINT (tmp) >> 8); // XXX
2000 while (point->y < floatval)
2002 if (point == numeric_traits[i].points)
2004 else if (point->y == CGFLOAT_MAX)
2006 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
2007 * ((point->x - (point - 1)->x)
2008 / (point->y - (point - 1)->y)));
2011 else if (floatval < -1.0)
2013 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2016 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2020 if (CFDictionaryGetCount (traits))
2021 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
2024 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
2027 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2030 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
2037 CFRelease (attributes);
2042 if (langarray) CFRelease (langarray);
2043 if (charset && cf_charset_idx < 0) CFRelease (charset);
2044 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2045 if (traits) CFRelease (traits);
2048 if (otspec->nfeatures[0] > 0)
2049 free (otspec->features[0]);
2050 if (otspec->nfeatures[1] > 0)
2051 free (otspec->features[1]);
2059 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
2060 CFCharacterSetRef charset,
2062 CFArrayRef languages)
2064 Boolean result = true;
2066 if (charset || VECTORP (chars))
2068 CFCharacterSetRef desc_charset =
2069 mac_font_descriptor_copy_attribute (desc,
2070 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2072 if (desc_charset == NULL)
2077 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2078 else /* VECTORP (chars) */
2082 for (j = 0; j < ASIZE (chars); j++)
2083 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2084 && CFCharacterSetIsLongCharacterMember (desc_charset,
2085 XFASTINT (AREF (chars, j))))
2087 if (j == ASIZE (chars))
2090 CFRelease (desc_charset);
2093 if (result && languages)
2094 result = mac_font_descriptor_supports_languages (desc, languages);
2100 macfont_traits_distance (FontSymbolicTraits sym_traits1,
2101 FontSymbolicTraits sym_traits2)
2103 FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2106 /* We prefer synthetic bold of italic to synthetic italic of bold
2107 when both bold and italic are available but bold-italic is not
2109 if (diff & MAC_FONT_TRAIT_BOLD)
2110 distance |= (1 << 0);
2111 if (diff & MAC_FONT_TRAIT_ITALIC)
2112 distance |= (1 << 1);
2113 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2114 distance |= (1 << 2);
2120 macfont_closest_traits_index_p (CFArrayRef traits_array,
2121 FontSymbolicTraits target,
2124 CFIndex i, count = CFArrayGetCount (traits_array);
2125 FontSymbolicTraits traits;
2128 traits = ((FontSymbolicTraits) (uintptr_t)
2129 CFArrayGetValueAtIndex (traits_array, index));
2130 my_distance = macfont_traits_distance (target, traits);
2132 for (i = 0; i < count; i++)
2135 traits = ((FontSymbolicTraits) (uintptr_t)
2136 CFArrayGetValueAtIndex (traits_array, i));
2137 if (macfont_traits_distance (target, traits) < my_distance)
2145 macfont_list (struct frame *f, Lisp_Object spec)
2147 Lisp_Object val = Qnil, family, extra;
2149 CFStringRef family_name = NULL;
2150 CFMutableDictionaryRef attributes = NULL, traits;
2151 Lisp_Object chars = Qnil;
2153 FontSymbolicTraits synth_sym_traits = 0;
2154 CFArrayRef families;
2155 CFIndex families_count;
2156 CFCharacterSetRef charset = NULL;
2157 CFArrayRef languages = NULL;
2161 family = AREF (spec, FONT_FAMILY_INDEX);
2162 if (! NILP (family))
2164 family_name = macfont_create_family_with_symbol (family);
2165 if (family_name == NULL)
2169 attributes = macfont_create_attributes_with_spec (spec);
2173 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2175 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2176 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2178 traits = ((CFMutableDictionaryRef)
2179 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2181 n = FONT_SLANT_NUMERIC (spec);
2182 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2184 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2186 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2189 n = FONT_WEIGHT_NUMERIC (spec);
2190 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2192 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2194 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2198 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2200 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2202 if (CFStringHasPrefix (language, CFSTR ("ja"))
2203 || CFStringHasPrefix (language, CFSTR ("ko"))
2204 || CFStringHasPrefix (language, CFSTR ("zh")))
2205 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2208 /* Create array of families. */
2210 families = CFArrayCreate (NULL, (const void **) &family_name,
2211 1, &kCFTypeArrayCallBacks);
2214 CFStringRef pref_family;
2215 CFIndex families_count, pref_family_index = -1;
2217 families = macfont_copy_available_families_cache ();
2218 if (families == NULL)
2221 families_count = CFArrayGetCount (families);
2223 /* Move preferred family to the front if exists. */
2225 mac_font_create_preferred_family_for_attributes (attributes);
2229 CFArrayGetFirstIndexOfValue (families,
2230 CFRangeMake (0, families_count),
2232 CFRelease (pref_family);
2234 if (pref_family_index > 0)
2236 CFMutableArrayRef mutable_families =
2237 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2239 if (mutable_families)
2241 CFArrayAppendValue (mutable_families,
2242 CFArrayGetValueAtIndex (families,
2243 pref_family_index));
2244 CFArrayAppendArray (mutable_families, families,
2245 CFRangeMake (0, pref_family_index));
2246 if (pref_family_index + 1 < families_count)
2247 CFArrayAppendArray (mutable_families, families,
2248 CFRangeMake (pref_family_index + 1,
2250 - (pref_family_index + 1)));
2251 CFRelease (families);
2252 families = mutable_families;
2257 charset = CFDictionaryGetValue (attributes,
2258 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2262 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2266 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2269 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2270 if (CONSP (val) && VECTORP (XCDR (val)))
2278 CFRetain (languages);
2279 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2283 extra = AREF (spec, FONT_EXTRA_INDEX);
2284 families_count = CFArrayGetCount (families);
2285 for (i = 0; i < families_count; i++)
2287 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2288 FontDescriptorRef pat_desc;
2290 CFIndex descs_count;
2291 CFMutableArrayRef filtered_descs, traits_array;
2295 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2297 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2301 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2302 10.7 returns NULL if pat_desc represents the LastResort font.
2303 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2304 trailing "s") for such a font. */
2305 if (!CFEqual (family_name, CFSTR ("LastResort")))
2306 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2310 FontDescriptorRef lr_desc =
2311 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2315 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2316 &kCFTypeArrayCallBacks);
2317 CFRelease (lr_desc);
2322 CFRelease (pat_desc);
2326 descs_count = CFArrayGetCount (descs);
2327 if (descs_count == 0
2328 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2337 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2338 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2339 for (j = 0; j < descs_count; j++)
2341 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2342 CFDictionaryRef dict;
2344 FontSymbolicTraits sym_traits;
2346 dict = mac_font_descriptor_copy_attribute (desc,
2347 MAC_FONT_TRAITS_ATTRIBUTE);
2351 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2354 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2358 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2359 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2360 != (spacing >= FONT_SPACING_MONO)))
2363 /* Don't use a color bitmap font unless its family is
2364 explicitly specified. */
2365 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2369 && !macfont_supports_charset_and_languages_p (desc, charset,
2373 CFArrayAppendValue (filtered_descs, desc);
2374 CFArrayAppendValue (traits_array,
2375 (const void *) (uintptr_t) sym_traits);
2379 descs = filtered_descs;
2380 descs_count = CFArrayGetCount (descs);
2382 for (j = 0; j < descs_count; j++)
2384 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2385 FontSymbolicTraits sym_traits =
2386 ((FontSymbolicTraits) (uintptr_t)
2387 CFArrayGetValueAtIndex (traits_array, j));
2388 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2390 mask_min = ((synth_sym_traits ^ sym_traits)
2391 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2392 if (FONT_SLANT_NUMERIC (spec) < 0)
2393 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2394 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2395 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2397 mask_max = (synth_sym_traits & ~sym_traits);
2398 /* Synthetic bold does not work for bitmap-only fonts on Mac
2400 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2402 CFNumberRef format =
2403 mac_font_descriptor_copy_attribute (desc,
2404 MAC_FONT_FORMAT_ATTRIBUTE);
2408 uint32_t format_val;
2410 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2412 && format_val == MAC_FONT_FORMAT_BITMAP)
2413 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2417 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2419 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2420 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2421 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2422 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2423 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2424 bmask += MAC_FONT_TRAIT_BOLD)
2425 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2426 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2427 imask += MAC_FONT_TRAIT_ITALIC)
2429 FontSymbolicTraits synth = (imask | bmask | mmask);
2432 || macfont_closest_traits_index_p (traits_array,
2433 (sym_traits | synth),
2436 entity = macfont_descriptor_entity (desc, extra, synth);
2437 if (! NILP (entity))
2438 val = Fcons (entity, val);
2443 CFRelease (traits_array);
2447 CFRelease (families);
2448 val = Fnreverse (val);
2454 FONT_ADD_LOG ("macfont-list", spec, val);
2455 if (charset) CFRelease (charset);
2456 if (languages) CFRelease (languages);
2457 if (attributes) CFRelease (attributes);
2458 if (family_name) CFRelease (family_name);
2466 macfont_match (struct frame * frame, Lisp_Object spec)
2468 Lisp_Object entity = Qnil;
2469 CFMutableDictionaryRef attributes;
2470 FontDescriptorRef pat_desc = NULL, desc = NULL;
2474 attributes = macfont_create_attributes_with_spec (spec);
2477 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2478 CFRelease (attributes);
2482 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2484 CFRelease (pat_desc);
2488 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2494 FONT_ADD_LOG ("macfont-match", spec, entity);
2499 macfont_list_family (struct frame *frame)
2501 Lisp_Object list = Qnil;
2502 CFArrayRef families;
2506 families = macfont_copy_available_families_cache ();
2509 CFIndex i, count = CFArrayGetCount (families);
2511 for (i = 0; i < count; i++)
2512 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2513 CFRelease (families);
2522 macfont_free_entity (Lisp_Object entity)
2524 Lisp_Object val = assq_no_quit (QCfont_entity,
2525 AREF (entity, FONT_EXTRA_INDEX));
2526 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2534 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2536 Lisp_Object val, font_object;
2537 CFStringRef font_name;
2538 struct macfont_info *macfont_info = NULL;
2542 FontSymbolicTraits sym_traits;
2544 int len, i, total_width;
2546 CGFloat ascent, descent, leading;
2548 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2550 || XTYPE (XCDR (val)) != Lisp_Misc
2551 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2553 font_name = XSAVE_POINTER (XCDR (val), 0);
2554 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2556 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2561 macfont = mac_font_create_with_name (font_name, size);
2564 int fontsize = (int) [((NSFont *) macfont) pointSize];
2565 if (fontsize != size) size = fontsize;
2571 font_object = font_build_object (VECSIZE (struct macfont_info),
2572 Qmac_ct, entity, size);
2573 font = XFONT_OBJECT (font_object);
2574 font->pixel_size = size;
2575 font->driver = &macfont_driver;
2576 font->encoding_charset = font->repertory_charset = -1;
2580 macfont_info = (struct macfont_info *) font;
2581 macfont_info->macfont = macfont;
2582 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2584 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2585 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2586 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2589 macfont_info->screen_font = NULL;
2590 macfont_info->cache = macfont_lookup_cache (font_name);
2591 macfont_retain_cache (macfont_info->cache);
2592 macfont_info->metrics = NULL;
2593 macfont_info->metrics_nrows = 0;
2594 macfont_info->synthetic_italic_p = 0;
2595 macfont_info->synthetic_bold_p = 0;
2596 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2597 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2598 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2599 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2600 macfont_info->synthetic_italic_p = 1;
2601 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2602 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2603 macfont_info->synthetic_bold_p = 1;
2604 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2605 macfont_info->spacing = MACFONT_SPACING_MONO;
2606 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2607 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2608 == FONT_SPACING_SYNTHETIC_MONO))
2609 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2610 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2611 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2614 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2616 macfont_info->antialias =
2617 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2619 macfont_info->color_bitmap_p = 0;
2620 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2621 macfont_info->color_bitmap_p = 1;
2623 glyph = macfont_get_glyph_for_character (font, ' ');
2624 if (glyph != kCGFontIndexInvalid)
2625 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2627 /* dirty workaround */
2628 font->space_width = pixel_size;
2630 total_width = font->space_width;
2631 for (i = 1; i < 95; i++)
2633 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2634 if (glyph == kCGFontIndexInvalid)
2636 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2639 font->average_width = total_width / 95;
2641 font->average_width = font->space_width; /* XXX */
2643 if (!(macfont_info->screen_font
2644 && mac_screen_font_get_metrics (macfont_info->screen_font,
2645 &ascent, &descent, &leading)))
2647 CFStringRef family_name;
2649 ascent = mac_font_get_ascent (macfont);
2650 descent = mac_font_get_descent (macfont);
2651 leading = mac_font_get_leading (macfont);
2652 /* AppKit and WebKit do some adjustment to the heights of
2653 Courier, Helvetica, and Times. */
2654 family_name = mac_font_copy_family_name (macfont);
2657 if (CFEqual (family_name, CFSTR ("Courier"))
2658 || CFEqual (family_name, CFSTR ("Helvetica"))
2659 || CFEqual (family_name, CFSTR ("Times")))
2660 ascent += (ascent + descent) * .15f;
2661 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2666 CFRelease (family_name);
2669 font->ascent = ascent + 0.5f;
2670 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2671 if (CONSP (val) && !NILP (XCDR (val)))
2672 font->descent = descent + 0.5f;
2674 font->descent = descent + leading + 0.5f;
2675 font->height = font->ascent + font->descent;
2677 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2678 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2682 /* Unfortunately Xft doesn't provide a way to get minimum char
2683 width. So, we use space_width instead. */
2684 font->min_width = font->max_width = font->space_width; /* XXX */
2686 font->baseline_offset = 0;
2687 font->relative_compose = 0;
2688 font->default_ascent = 0;
2689 font->vertical_centering = 0;
2695 macfont_close (struct font *font)
2697 struct macfont_info *macfont_info = (struct macfont_info *) font;
2699 if (macfont_info->cache)
2704 CFRelease (macfont_info->macfont);
2705 CGFontRelease (macfont_info->cgfont);
2706 if (macfont_info->screen_font)
2707 CFRelease (macfont_info->screen_font);
2708 macfont_release_cache (macfont_info->cache);
2709 for (i = 0; i < macfont_info->metrics_nrows; i++)
2710 if (macfont_info->metrics[i])
2711 xfree (macfont_info->metrics[i]);
2712 if (macfont_info->metrics)
2713 xfree (macfont_info->metrics);
2714 macfont_info->cache = NULL;
2720 macfont_has_char (Lisp_Object font, int c)
2723 CFCharacterSetRef charset;
2726 if (FONT_ENTITY_P (font))
2731 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2733 name = XSAVE_POINTER (val, 0);
2734 charset = macfont_get_cf_charset_for_name (name);
2737 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2739 result = CFCharacterSetIsLongCharacterMember (charset, c);
2746 macfont_encode_char (struct font *font, int c)
2748 struct macfont_info *macfont_info = (struct macfont_info *) font;
2752 glyph = macfont_get_glyph_for_character (font, c);
2755 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2759 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2760 struct font_metrics *metrics)
2765 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2766 for (i = 1; i < nglyphs; i++)
2768 struct font_metrics m;
2769 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2774 if (width + m.lbearing < metrics->lbearing)
2775 metrics->lbearing = width + m.lbearing;
2776 if (width + m.rbearing > metrics->rbearing)
2777 metrics->rbearing = width + m.rbearing;
2778 if (m.ascent > metrics->ascent)
2779 metrics->ascent = m.ascent;
2780 if (m.descent > metrics->descent)
2781 metrics->descent = m.descent;
2788 metrics->width = width;
2792 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2793 bool with_background)
2795 struct frame * f = s->f;
2796 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2797 CGRect background_rect;
2798 CGPoint text_position;
2801 CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2802 bool no_antialias_p =
2803 (NILP (ns_antialias_text)
2804 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2805 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2806 && font_size <= macfont_antialias_threshold));
2807 int len = to - from;
2808 struct face *face = s->face;
2809 CGContextRef context;
2813 if (with_background)
2814 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2815 s->width, FONT_HEIGHT (s->font));
2817 background_rect = CGRectNull;
2819 text_position = CGPointMake (x, -y);
2820 glyphs = xmalloc (sizeof (CGGlyph) * len);
2822 CGFloat advance_delta = 0;
2824 CGFloat total_width = 0;
2826 positions = xmalloc (sizeof (CGPoint) * len);
2827 for (i = 0; i < len; i++)
2831 glyphs[i] = s->char2b[from + i];
2832 width = (s->padding_p ? 1
2833 : macfont_glyph_extents (s->font, glyphs[i],
2834 NULL, &advance_delta,
2836 positions[i].x = total_width + advance_delta;
2838 total_width += width;
2842 context = [[NSGraphicsContext currentContext] graphicsPort];
2843 CGContextSaveGState (context);
2845 if (!CGRectIsNull (background_rect))
2847 if (s->hl == DRAW_MOUSE_FACE)
2849 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2851 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2853 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2854 CGContextFillRects (context, &background_rect, 1);
2857 if (macfont_info->cgfont)
2859 CGAffineTransform atfm;
2861 CGContextScaleCTM (context, 1, -1);
2862 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2863 if (macfont_info->synthetic_italic_p)
2864 atfm = synthetic_italic_atfm;
2866 atfm = CGAffineTransformIdentity;
2867 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2869 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2870 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2871 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2874 CGContextSetShouldAntialias (context, false);
2876 CGContextSetTextMatrix (context, atfm);
2877 CGContextSetTextPosition (context, text_position.x, text_position.y);
2879 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2880 if (macfont_info->color_bitmap_p
2881 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2882 && CTFontDrawGlyphs != NULL
2888 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2893 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2895 CGContextSetFont (context, macfont_info->cgfont);
2896 CGContextSetFontSize (context, font_size);
2897 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2904 CGContextRestoreGState (context);
2912 macfont_shape (Lisp_Object lgstring)
2914 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2915 struct macfont_info *macfont_info = (struct macfont_info *) font;
2916 FontRef macfont = macfont_info->macfont;
2917 ptrdiff_t glyph_len, len, i, j;
2920 CFIndex *nonbmp_indices;
2923 struct mac_glyph_layout *glyph_layouts;
2925 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2927 for (i = 0; i < glyph_len; i++)
2929 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2933 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2939 if (INT_MAX / 2 < len)
2940 memory_full (SIZE_MAX);
2942 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2943 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2944 for (i = j = 0; i < len; i++)
2946 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2948 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2950 nonbmp_indices[j] = i + j;
2954 nonbmp_indices[j] = len + j; /* sentinel */
2958 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2962 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2963 if (macfont_info->screen_font)
2964 used = mac_screen_font_shape (macfont_info->screen_font, string,
2965 glyph_layouts, glyph_len);
2967 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2978 for (i = 0; i < used; i++)
2980 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2981 struct mac_glyph_layout *gl = glyph_layouts + i;
2983 struct font_metrics metrics;
2984 int xoff, yoff, wadjust;
2988 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2989 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2992 from = gl->comp_range.location;
2993 /* Convert UTF-16 index to UTF-32. */
2995 while (nonbmp_indices[j] < from)
2998 LGLYPH_SET_FROM (lglyph, from);
3000 to = gl->comp_range.location + gl->comp_range.length;
3001 /* Convert UTF-16 index to UTF-32. */
3002 while (nonbmp_indices[j] < to)
3005 LGLYPH_SET_TO (lglyph, to - 1);
3007 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3008 the composition is trivial. */
3012 if (unichars[gl->string_index] >= 0xD800
3013 && unichars[gl->string_index] < 0xDC00)
3014 c = (((unichars[gl->string_index] - 0xD800) << 10)
3015 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3017 c = unichars[gl->string_index];
3018 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3020 LGLYPH_SET_CHAR (lglyph, c);
3024 unsigned long cc = gl->glyph_id;
3025 LGLYPH_SET_CODE (lglyph, cc);
3028 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3029 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3030 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3031 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3032 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3033 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3035 xoff = lround (gl->advance_delta);
3036 yoff = lround (- gl->baseline_delta);
3037 wadjust = lround (gl->advance);
3038 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3042 vec = Fmake_vector (make_number (3), Qnil);
3043 ASET (vec, 0, make_number (xoff));
3044 ASET (vec, 1, make_number (yoff));
3045 ASET (vec, 2, make_number (wadjust));
3046 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3052 return make_number (used);
3055 /* Structures for the UVS subtable (format 14) in the cmap table. */
3056 typedef UInt8 UINT24[3];
3058 #pragma pack(push, 1)
3059 struct variation_selector_record
3061 UINT24 var_selector;
3062 UInt32 default_uvs_offset, non_default_uvs_offset;
3067 UInt32 length, num_var_selector_records;
3068 struct variation_selector_record variation_selector_records[1];
3070 #define SIZEOF_UVS_TABLE_HEADER \
3071 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3073 struct unicode_value_range
3075 UINT24 start_unicode_value;
3076 UInt8 additional_count;
3078 struct default_uvs_table {
3079 UInt32 num_unicode_value_ranges;
3080 struct unicode_value_range unicode_value_ranges[1];
3082 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3083 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3087 UINT24 unicode_value;
3090 struct non_default_uvs_table
3092 UInt32 num_uvs_mappings;
3093 struct uvs_mapping uvs_mappings[1];
3095 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3096 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3099 /* Read big endian values. The argument LVAL must be an lvalue. */
3100 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3101 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3102 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3103 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3104 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3105 /* Succeeding one byte should also be accessible. */
3106 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3107 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3109 /* Return UVS subtable for the specified FONT. If the subtable is not
3110 found or ill-formatted, then return NULL. */
3113 mac_font_copy_uvs_table (FontRef font)
3115 CFDataRef cmap_table, uvs_table = NULL;
3117 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3120 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3121 struct uvs_table *uvs;
3122 struct variation_selector_record *records;
3123 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3126 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3130 cmap_len = CFDataGetLength (cmap_table);
3131 if (sizeof_sfntCMapHeader > cmap_len)
3134 ntables = BUINT16_VALUE (cmap->numTables);
3135 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3136 / sizeof_sfntCMapEncoding))
3139 for (i = 0; i < ntables; i++)
3140 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3141 == kFontUnicodePlatform)
3142 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3143 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3145 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3149 || uvs_offset > cmap_len
3150 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3153 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3154 uvs_len = BUINT32_VALUE (uvs->length);
3155 if (uvs_len > cmap_len - uvs_offset
3156 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3159 if (BUINT16_VALUE (uvs->format) != 14)
3162 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3163 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3164 / sizeof (struct variation_selector_record)))
3167 records = uvs->variation_selector_records;
3168 for (i = 0; i < nrecords; i++)
3170 UInt32 default_uvs_offset, non_default_uvs_offset;
3172 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3173 if (default_uvs_offset)
3175 struct default_uvs_table *default_uvs;
3178 if (default_uvs_offset > uvs_len
3179 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3180 > uvs_len - default_uvs_offset))
3183 default_uvs = ((struct default_uvs_table *)
3184 ((UInt8 *) uvs + default_uvs_offset));
3185 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3186 if (nranges > ((uvs_len - default_uvs_offset
3187 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3188 / sizeof (struct unicode_value_range)))
3190 /* Now 2 * nranges can't overflow, so we can safely use
3191 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3192 mac_font_get_glyphs_for_variants. */
3195 non_default_uvs_offset =
3196 BUINT32_VALUE (records[i].non_default_uvs_offset);
3197 if (non_default_uvs_offset)
3199 struct non_default_uvs_table *non_default_uvs;
3202 if (non_default_uvs_offset > uvs_len
3203 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3204 > uvs_len - non_default_uvs_offset))
3207 non_default_uvs = ((struct non_default_uvs_table *)
3208 ((UInt8 *) uvs + non_default_uvs_offset));
3209 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3210 if (nmappings > ((uvs_len - non_default_uvs_offset
3211 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3212 / sizeof (struct uvs_mapping)))
3214 /* Now 2 * nmappings can't overflow, so we can safely
3215 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3216 in mac_font_get_glyphs_for_variants. */
3220 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3223 CFRelease (cmap_table);
3229 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3230 sequence consisting of the given base character C and each
3231 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3232 result (explained below) into the corresponding GLYPHS[i]. If the
3233 entry is found in the Default UVS Table, then the result is 0. If
3234 the entry is found in the Non-Default UVS Table, then the result is
3235 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3236 elements in SELECTORS must be sorted in strictly increasing
3240 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3241 const UTF32Char selectors[], CGGlyph glyphs[],
3244 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3245 struct variation_selector_record *records = uvs->variation_selector_records;
3247 UInt32 ir, nrecords;
3248 dispatch_queue_t queue =
3249 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3250 dispatch_group_t group = dispatch_group_create ();
3252 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3255 while (i < count && ir < nrecords)
3257 UInt32 default_uvs_offset, non_default_uvs_offset;
3259 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3261 glyphs[i++] = kCGFontIndexInvalid;
3264 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3270 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3271 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3272 non_default_uvs_offset =
3273 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3274 dispatch_group_async (group, queue, ^{
3275 glyphs[i] = kCGFontIndexInvalid;
3277 if (default_uvs_offset)
3279 struct default_uvs_table *default_uvs =
3280 (struct default_uvs_table *) ((UInt8 *) uvs
3281 + default_uvs_offset);
3282 struct unicode_value_range *ranges =
3283 default_uvs->unicode_value_ranges;
3287 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3290 UInt32 mid = (lo + hi) / 2;
3292 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3298 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3299 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3303 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3305 struct non_default_uvs_table *non_default_uvs =
3306 (struct non_default_uvs_table *) ((UInt8 *) uvs
3307 + non_default_uvs_offset);
3308 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3312 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3315 UInt32 mid = (lo + hi) / 2;
3317 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3323 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3324 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3331 glyphs[i++] = kCGFontIndexInvalid;
3332 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3333 dispatch_release (group);
3337 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3339 CFDataRef uvs_table;
3340 CharacterCollection uvs_collection;
3344 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3348 UTF32Char selectors[256];
3349 CGGlyph glyphs[256];
3351 for (i = 0; i < 16; i++)
3352 selectors[i] = 0xFE00 + i;
3353 for (; i < 256; i++)
3354 selectors[i] = 0xE0100 + (i - 16);
3355 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3356 for (i = 0; i < 256; i++)
3358 CGGlyph glyph = glyphs[i];
3360 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3361 && glyph != kCGFontIndexInvalid)
3362 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3363 if (glyph == kCGFontIndexInvalid)
3367 variations[i] = (glyph ? glyph
3368 : macfont_get_glyph_for_character (font, c));
3378 static const char *const macfont_booleans[] = {
3384 static const char *const macfont_non_booleans[] = {
3392 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3394 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3398 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3399 CFArrayRef languages)
3401 Boolean result = true;
3402 CFArrayRef desc_languages =
3403 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3405 if (desc_languages == NULL)
3409 CFIndex desc_languages_count, i, languages_count;
3411 desc_languages_count = CFArrayGetCount (desc_languages);
3412 languages_count = CFArrayGetCount (languages);
3413 for (i = 0; i < languages_count; i++)
3414 if (!CFArrayContainsValue (desc_languages,
3415 CFRangeMake (0, desc_languages_count),
3416 CFArrayGetValueAtIndex (languages, i)))
3421 CFRelease (desc_languages);
3428 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3430 CFStringRef result = NULL;
3431 CFStringRef charset_string =
3432 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3434 if (charset_string && CFStringGetLength (charset_string) > 0)
3436 CFStringRef keys[] = {
3437 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3438 kCTLanguageAttributeName
3440 CFSTR ("NSLanguage")
3443 CFTypeRef values[] = {NULL};
3444 CFIndex num_values = 0;
3445 CFArrayRef languages
3446 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3448 if (languages && CFArrayGetCount (languages) > 0)
3450 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3451 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3454 CFCharacterSetRef charset =
3455 CFDictionaryGetValue (attributes,
3456 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3458 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3463 CFAttributedStringRef attr_string = NULL;
3464 CTLineRef ctline = NULL;
3465 CFDictionaryRef attrs
3466 = CFDictionaryCreate (NULL, (const void **) keys,
3467 (const void **) values, num_values,
3468 &kCFTypeDictionaryKeyCallBacks,
3469 &kCFTypeDictionaryValueCallBacks);
3473 attr_string = CFAttributedStringCreate (NULL, charset_string,
3479 ctline = CTLineCreateWithAttributedString (attr_string);
3480 CFRelease (attr_string);
3484 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3485 CFIndex i, nruns = CFArrayGetCount (runs);
3488 for (i = 0; i < nruns; i++)
3490 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3491 CFDictionaryRef attributes = CTRunGetAttributes (run);
3492 CTFontRef font_in_run;
3494 if (attributes == NULL)
3497 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3498 if (font_in_run == NULL)
3502 else if (!mac_ctfont_equal_in_postscript_name (font,
3506 if (nruns > 0 && i == nruns)
3507 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3516 static inline double
3517 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3519 return CTFontGetAdvancesForGlyphs (font,
3520 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3521 kCTFontOrientationDefault,
3523 kCTFontDefaultOrientation,
3528 static inline CGRect
3529 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3531 return CTFontGetBoundingRectsForGlyphs (font,
3532 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3533 kCTFontOrientationDefault,
3535 kCTFontDefaultOrientation,
3541 mac_ctfont_create_available_families (void)
3543 CFMutableArrayRef families = NULL;
3546 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3550 CFIndex i, count = CFArrayGetCount (orig_families);
3552 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3554 for (i = 0; i < count; i++)
3556 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3558 if (!CFStringHasPrefix (family, CFSTR ("."))
3559 && (CTFontManagerCompareFontFamilyNames (family,
3560 CFSTR ("LastResort"),
3562 != kCFCompareEqualTo))
3563 CFArrayAppendValue (families, family);
3565 CFRelease (orig_families);
3573 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3576 CFStringRef name1, name2;
3582 name1 = CTFontCopyPostScriptName (font1);
3585 name2 = CTFontCopyPostScriptName (font2);
3588 result = CFEqual (name1, name2);
3598 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3601 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3602 CFTypeRef values[] = {NULL, NULL};
3603 CFDictionaryRef attributes = NULL;
3604 CFAttributedStringRef attr_string = NULL;
3605 CTLineRef ctline = NULL;
3606 float float_zero = 0.0f;
3608 values[0] = macfont;
3609 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3612 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3613 (const void **) values,
3615 &kCFTypeDictionaryKeyCallBacks,
3616 &kCFTypeDictionaryValueCallBacks);
3617 CFRelease (values[1]);
3621 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3622 CFRelease (attributes);
3626 ctline = CTLineCreateWithAttributedString (attr_string);
3627 CFRelease (attr_string);
3631 /* Abandon if ctline contains some fonts other than the
3633 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3634 CFIndex i, nruns = CFArrayGetCount (runs);
3636 for (i = 0; i < nruns; i++)
3638 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3639 CFDictionaryRef attributes = CTRunGetAttributes (run);
3640 CTFontRef font_in_run;
3642 if (attributes == NULL)
3645 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3646 if (font_in_run == NULL)
3648 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3662 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3663 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3665 CFIndex used, result = 0;
3666 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3671 used = CTLineGetGlyphCount (ctline);
3672 if (used <= glyph_len)
3674 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3675 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3676 CGFloat total_advance = 0;
3677 CFIndex total_glyph_count = 0;
3679 for (k = 0; k < ctrun_count; k++)
3681 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3682 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3683 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3684 CFRange string_range, comp_range, range;
3685 CFIndex *permutation;
3687 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3688 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3692 #define RIGHT_TO_LEFT_P permutation
3694 /* Now the `comp_range' member of struct mac_glyph_layout is
3695 temporarily used as a work area such that:
3696 glbuf[i].comp_range.location =
3697 min {compRange[i + 1].location, ...,
3698 compRange[glyph_count - 1].location,
3699 maxRange (stringRangeForCTRun)}
3700 glbuf[i].comp_range.length = maxRange (compRange[i])
3701 where compRange[i] is the range of composed characters
3702 containing i-th glyph. */
3703 string_range = CTRunGetStringRange (ctrun);
3704 min_location = string_range.location + string_range.length;
3705 for (i = 0; i < glyph_count; i++)
3707 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3708 CFIndex glyph_index;
3711 if (!RIGHT_TO_LEFT_P)
3712 glyph_index = glyph_count - i - 1;
3715 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3718 CFStringGetRangeOfComposedCharactersAtIndex (string,
3720 gl->comp_range.location = min_location;
3721 gl->comp_range.length = rng.location + rng.length;
3722 if (rng.location < min_location)
3723 min_location = rng.location;
3726 /* Fill the `comp_range' member of struct mac_glyph_layout,
3727 and setup a permutation for right-to-left text. */
3728 comp_range = CFRangeMake (string_range.location, 0);
3729 range = CFRangeMake (0, 0);
3732 struct mac_glyph_layout *gl =
3733 glbuf + range.location + range.length;
3735 if (gl->comp_range.length
3736 > comp_range.location + comp_range.length)
3737 comp_range.length = gl->comp_range.length - comp_range.location;
3738 min_location = gl->comp_range.location;
3741 if (min_location >= comp_range.location + comp_range.length)
3743 comp_range.length = min_location - comp_range.location;
3744 for (i = 0; i < range.length; i++)
3746 glbuf[range.location + i].comp_range = comp_range;
3747 if (RIGHT_TO_LEFT_P)
3748 permutation[range.location + i] =
3749 range.location + range.length - i - 1;
3752 comp_range = CFRangeMake (min_location, 0);
3753 range.location += range.length;
3755 if (range.location == glyph_count)
3760 /* Then fill the remaining members. */
3761 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3764 struct mac_glyph_layout *gl;
3767 if (!RIGHT_TO_LEFT_P)
3768 gl = glbuf + range.location;
3773 src = glyph_count - 1 - range.location;
3774 dest = permutation[src];
3778 CFIndex tmp = gl->string_index;
3780 gl->string_index = glbuf[src].string_index;
3781 glbuf[src].string_index = tmp;
3784 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3786 CTRunGetPositions (ctrun, range, &position);
3787 gl->advance_delta = position.x - total_advance;
3788 gl->baseline_delta = position.y;
3789 gl->advance = (gl->advance_delta
3790 + CTRunGetTypographicBounds (ctrun, range,
3792 total_advance += gl->advance;
3795 if (RIGHT_TO_LEFT_P)
3796 xfree (permutation);
3798 #undef RIGHT_TO_LEFT_P
3800 total_glyph_count += glyph_count;
3810 /* The function below seems to cause a memory leak for the CFString
3811 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3812 10.6.3. For now, we use the NSGlyphInfo version instead. */
3813 #if USE_CT_GLYPH_INFO
3815 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3818 CGGlyph result = kCGFontIndexInvalid;
3819 UniChar characters[] = {0xfffd};
3821 CFAttributedStringRef attr_string = NULL;
3822 CTLineRef ctline = NULL;
3824 string = CFStringCreateWithCharacters (NULL, characters,
3825 ARRAYELTS (characters));
3829 CTGlyphInfoRef glyph_info =
3830 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3831 CFDictionaryRef attributes = NULL;
3835 CFStringRef keys[] = {kCTFontAttributeName,
3836 kCTGlyphInfoAttributeName};
3837 CFTypeRef values[] = {font, glyph_info};
3839 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3840 (const void **) values,
3842 &kCFTypeDictionaryKeyCallBacks,
3843 &kCFTypeDictionaryValueCallBacks);
3844 CFRelease (glyph_info);
3848 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3849 CFRelease (attributes);
3855 ctline = CTLineCreateWithAttributedString (attr_string);
3856 CFRelease (attr_string);
3860 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3862 if (CFArrayGetCount (runs) > 0)
3864 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3865 CFDictionaryRef attributes = CTRunGetAttributes (run);
3869 CTFontRef font_in_run =
3870 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3873 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3875 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3876 if (result >= CTFontGetGlyphCount (font))
3877 result = kCGFontIndexInvalid;
3889 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3891 CFArrayRef result = NULL;
3893 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3894 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3895 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3898 CTFontRef user_font =
3899 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3903 CFArrayRef languages =
3904 CFArrayCreate (NULL, (const void **) &language, 1,
3905 &kCFTypeArrayCallBacks);
3909 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3911 CFRelease (languages);
3913 CFRelease (user_font);
3916 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3917 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3919 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3920 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3924 for (i = 0; macfont_language_default_font_names[i].language; i++)
3926 if (CFEqual (macfont_language_default_font_names[i].language,
3929 CFMutableArrayRef descriptors =
3930 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3937 macfont_language_default_font_names[i].font_names[j];
3940 CFDictionaryRef attributes =
3941 CFDictionaryCreate (NULL,
3943 &MAC_FONT_NAME_ATTRIBUTE),
3945 &macfont_language_default_font_names[i].font_names[j]),
3946 1, &kCFTypeDictionaryKeyCallBacks,
3947 &kCFTypeDictionaryValueCallBacks);
3951 FontDescriptorRef pat_desc =
3952 mac_font_descriptor_create_with_attributes (attributes);
3956 FontDescriptorRef descriptor =
3957 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3961 CFArrayAppendValue (descriptors, descriptor);
3962 CFRelease (descriptor);
3964 CFRelease (pat_desc);
3966 CFRelease (attributes);
3969 result = descriptors;
3981 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3982 CFArrayRef languages)
3984 CFStringRef result = NULL;
3985 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3986 CFArrayRef descriptors =
3987 mac_font_copy_default_descriptors_for_language (language);
3991 CFIndex i, count = CFArrayGetCount (descriptors);
3993 for (i = 0; i < count; i++)
3995 FontDescriptorRef descriptor =
3996 CFArrayGetValueAtIndex (descriptors, i);
3998 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4001 CFStringRef family =
4002 mac_font_descriptor_copy_attribute (descriptor,
4003 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
4006 if (!CFStringHasPrefix (family, CFSTR ("."))
4007 && !CFEqual (family, CFSTR ("LastResort")))
4017 CFRelease (descriptors);
4024 macfont_get_nsctfont (struct font *font)
4026 struct macfont_info *macfont_info = (struct macfont_info *) font;
4027 FontRef macfont = macfont_info->macfont;
4029 return (void *) macfont;
4033 mac_register_font_driver (struct frame *f)
4035 register_font_driver (&macfont_driver, f);
4040 syms_of_macfont (void)
4042 static struct font_driver mac_font_driver;
4044 /* Core Text, for Mac OS X. */
4045 DEFSYM (Qmac_ct, "mac-ct");
4046 macfont_driver.type = Qmac_ct;
4047 register_font_driver (&macfont_driver, NULL);
4049 /* The font property key specifying the font design destination. The
4050 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4051 text. (See the documentation of X Logical Font Description
4052 Conventions.) In the Mac font driver, 1 means the screen font is
4053 used for calculating some glyph metrics. You can see the
4054 difference with Monaco 8pt or 9pt, for example. */
4055 DEFSYM (QCdestination, ":destination");
4057 /* The boolean-valued font property key specifying the use of leading. */
4058 DEFSYM (QCminspace, ":minspace");
4060 macfont_family_cache = Qnil;
4061 staticpro (&macfont_family_cache);