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 CFComparatorFunction family_name_comparator;
1043 if (macfont_get_family_cache_if_present (symbol, &result))
1044 return result ? CFRetain (result) : NULL;
1046 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
1047 if (family_name == NULL)
1051 family_name_comparator = CTFontManagerCompareFontFamilyNames;
1054 if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
1055 == kCFCompareEqualTo)
1056 result = CFSTR ("LastResort");
1060 CFArrayRef families = macfont_copy_available_families_cache ();
1064 count = CFArrayGetCount (families);
1065 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
1066 (const void *) family_name,
1067 family_name_comparator, NULL);
1070 CFStringRef name = CFArrayGetValueAtIndex (families, i);
1072 if ((*family_name_comparator) (name, family_name, NULL)
1073 == kCFCompareEqualTo)
1074 result = CFRetain (name);
1076 CFRelease (families);
1080 CFRelease (family_name);
1082 macfont_set_family_cache (symbol, result);
1087 #define WIDTH_FRAC_BITS (4)
1088 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
1090 struct macfont_metrics
1092 unsigned char lbearing_low, rbearing_low;
1093 signed lbearing_high : 4, rbearing_high : 4;
1094 unsigned char ascent_low, descent_low;
1095 signed ascent_high : 4, descent_high : 4;
1097 /* These two members are used for fixed-point representation of
1098 glyph width. The `width_int' member is an integer that is
1099 closest to the width. The `width_frac' member is the fractional
1100 adjustment representing a value in [-.5, .5], multiplied by
1101 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1102 the advance delta for centering instead of the glyph width. */
1103 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1106 #define METRICS_VALUE(metrics, member) \
1107 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1108 #define METRICS_SET_VALUE(metrics, member, value) \
1109 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1110 (metrics)->member##_high = tmp >> 8;} while (0)
1114 METRICS_INVALID = -1, /* metrics entry is invalid */
1115 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1118 #define METRICS_STATUS(metrics) \
1119 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1120 #define METRICS_SET_STATUS(metrics, status) \
1121 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1122 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1124 #define METRICS_NCOLS_PER_ROW (128)
1125 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1126 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1129 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1130 struct font_metrics *metrics, CGFloat *advance_delta,
1131 int force_integral_p)
1133 struct macfont_info *macfont_info = (struct macfont_info *) font;
1134 FontRef macfont = macfont_info->macfont;
1136 struct macfont_metrics *cache;
1139 row = glyph / METRICS_NCOLS_PER_ROW;
1140 col = glyph % METRICS_NCOLS_PER_ROW;
1141 if (row >= macfont_info->metrics_nrows)
1143 macfont_info->metrics =
1144 xrealloc (macfont_info->metrics,
1145 sizeof (struct macfont_metrics *) * (row + 1));
1146 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1147 (sizeof (struct macfont_metrics *)
1148 * (row + 1 - macfont_info->metrics_nrows)));
1149 macfont_info->metrics_nrows = row + 1;
1151 if (macfont_info->metrics[row] == NULL)
1153 struct macfont_metrics *new;
1156 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1157 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1158 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1159 macfont_info->metrics[row] = new;
1161 cache = macfont_info->metrics[row] + col;
1163 if (METRICS_STATUS (cache) == METRICS_INVALID)
1167 if (macfont_info->screen_font)
1168 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1170 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1172 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1173 advance delta value. */
1174 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1175 fwidth = (font->pixel_size - fwidth) / 2;
1176 cache->width_int = lround (fwidth);
1177 cache->width_frac = lround ((fwidth - cache->width_int)
1178 * WIDTH_FRAC_SCALE);
1179 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1181 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1182 width = font->pixel_size;
1184 width = cache->width_int;
1188 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1190 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1192 if (macfont_info->synthetic_italic_p)
1194 /* We assume the members a, b, c, and d in
1195 synthetic_italic_atfm are non-negative. */
1197 CGPointApplyAffineTransform (bounds.origin,
1198 synthetic_italic_atfm);
1200 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1202 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1205 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1207 bounds = CGRectInset (bounds, d, d);
1209 switch (macfont_info->spacing)
1211 case MACFONT_SPACING_PROPORTIONAL:
1212 bounds.origin.x += - (cache->width_frac
1213 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1215 case MACFONT_SPACING_MONO:
1217 case MACFONT_SPACING_SYNTHETIC_MONO:
1218 bounds.origin.x += (cache->width_int
1219 + (cache->width_frac
1220 / (CGFloat) WIDTH_FRAC_SCALE));
1223 if (bounds.size.width > 0)
1225 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1226 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1227 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1229 bounds = CGRectIntegral (bounds);
1230 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1231 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1232 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1233 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1235 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1236 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1237 metrics->width = width;
1238 metrics->ascent = METRICS_VALUE (cache, ascent);
1239 metrics->descent = METRICS_VALUE (cache, descent);
1244 switch (macfont_info->spacing)
1246 case MACFONT_SPACING_PROPORTIONAL:
1247 *advance_delta = (force_integral_p ? 0
1248 : - (cache->width_frac
1249 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1251 case MACFONT_SPACING_MONO:
1254 case MACFONT_SPACING_SYNTHETIC_MONO:
1255 *advance_delta = (force_integral_p ? cache->width_int
1257 + (cache->width_frac
1258 / (CGFloat) WIDTH_FRAC_SCALE)));
1266 static CFMutableDictionaryRef macfont_cache_dictionary;
1268 /* Threshold used in row_nkeys_or_perm. This must be less than or
1269 equal to the number of rows that are invalid as BMP (i.e., from
1270 U+D800 to U+DFFF). */
1271 #define ROW_PERM_OFFSET (8)
1273 /* The number of glyphs that can be stored in a value for a single
1274 entry of CFDictionary. */
1275 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1277 struct macfont_cache
1279 int reference_count;
1280 CFCharacterSetRef cf_charset;
1282 /* The cached glyph for a BMP character c is stored in
1283 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1284 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1285 unsigned char row_nkeys_or_perm[256];
1288 /* Number of rows for which the BMP cache is allocated so far.
1289 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1292 /* The cached glyph for a character c is stored as the (c %
1293 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1294 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1295 not stored here if row_nkeys_or_perm[c / 256] >=
1297 CFMutableDictionaryRef dictionary;
1301 /* UVS (Unicode Variation Sequence) subtable data, which is of
1302 type CFDataRef if available. NULL means it is not initialized
1303 yet. kCFNull means the subtable is not found and there is no
1304 suitable fallback table for this font. */
1307 /* Character collection specifying the destination of the mapping
1308 provided by `table' above. If `table' is obtained from the UVS
1309 subtable in the font cmap table, then the value of this member
1310 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1311 CharacterCollection collection;
1315 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1316 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1317 static void macfont_release_cache (struct macfont_cache *);
1318 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1319 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1320 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1321 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1322 CharacterCollection, CGFontIndex);
1323 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1325 static struct macfont_cache *
1326 macfont_lookup_cache (CFStringRef key)
1328 struct macfont_cache *cache;
1330 if (macfont_cache_dictionary == NULL)
1332 macfont_cache_dictionary =
1333 CFDictionaryCreateMutable (NULL, 0,
1334 &kCFTypeDictionaryKeyCallBacks, NULL);
1338 cache = ((struct macfont_cache *)
1339 CFDictionaryGetValue (macfont_cache_dictionary, key));
1343 FontRef macfont = mac_font_create_with_name (key, 0);
1347 cache = xzalloc (sizeof (struct macfont_cache));
1348 /* Treat the LastResort font as if it contained glyphs for
1349 all characters. This may look too rough, but neither
1350 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1351 for this font is correct for non-BMP characters on Mac OS
1353 if (CFEqual (key, CFSTR ("LastResort")))
1355 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1358 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1360 if (cache->cf_charset == NULL)
1361 cache->cf_charset = mac_font_copy_character_set (macfont);
1362 CFDictionaryAddValue (macfont_cache_dictionary, key,
1363 (const void *) cache);
1364 CFRelease (macfont);
1371 static struct macfont_cache *
1372 macfont_retain_cache (struct macfont_cache *cache)
1374 cache->reference_count++;
1380 macfont_release_cache (struct macfont_cache *cache)
1382 if (--cache->reference_count == 0)
1386 for (i = 0; i < cache->glyph.nrows; i++)
1387 xfree (cache->glyph.matrix[i]);
1388 xfree (cache->glyph.matrix);
1389 if (cache->glyph.dictionary)
1390 CFRelease (cache->glyph.dictionary);
1391 memset (&cache->glyph, 0, sizeof (cache->glyph));
1392 if (cache->uvs.table)
1393 CFRelease (cache->uvs.table);
1394 memset (&cache->uvs, 0, sizeof (cache->uvs));
1398 static CFCharacterSetRef
1399 macfont_get_cf_charset (struct font *font)
1401 struct macfont_info *macfont_info = (struct macfont_info *) font;
1403 return macfont_info->cache->cf_charset;
1406 static CFCharacterSetRef
1407 macfont_get_cf_charset_for_name (CFStringRef name)
1409 struct macfont_cache *cache = macfont_lookup_cache (name);
1411 return cache->cf_charset;
1415 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1417 struct macfont_info *macfont_info = (struct macfont_info *) font;
1418 FontRef macfont = macfont_info->macfont;
1419 struct macfont_cache *cache = macfont_info->cache;
1421 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1424 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1426 if (nkeys_or_perm < ROW_PERM_OFFSET)
1428 UniChar unichars[256], ch;
1432 dispatch_queue_t queue;
1433 dispatch_group_t group = NULL;
1437 CFMutableDictionaryRef dictionary;
1438 uintptr_t key, value;
1442 if (cache->glyph.dictionary == NULL)
1443 cache->glyph.dictionary =
1444 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1445 dictionary = cache->glyph.dictionary;
1446 key = c / NGLYPHS_IN_VALUE;
1447 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1448 value = ((uintptr_t)
1449 CFDictionaryGetValue (dictionary, (const void *) key));
1450 glyph = (value >> nshifts);
1454 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1457 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1460 glyph = kCGFontIndexInvalid;
1463 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1464 value |= ((uintptr_t) glyph << nshifts);
1465 CFDictionarySetValue (dictionary, (const void *) key,
1466 (const void *) value);
1472 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1473 group = dispatch_group_create ();
1474 dispatch_group_async (group, queue, ^{
1477 nkeys = nkeys_or_perm;
1478 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1479 if (CFDictionaryContainsKey (dictionary,
1480 (const void *) key))
1482 CFDictionaryRemoveValue (dictionary,
1483 (const void *) key);
1491 for (i = 0; i < 256; i++)
1494 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1495 unichars[len++] = ch;
1498 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1501 mac_font_get_glyphs_for_characters (macfont, unichars,
1505 int next = unichars[len - 1] % 256;
1508 glyphs[i] = kCGFontIndexInvalid;
1511 glyphs[i] = glyphs[len];
1518 glyphs[i] = kCGFontIndexInvalid;
1520 nrows = cache->glyph.nrows;
1521 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1522 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1524 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1525 sizeof (CGGlyph *) * nrows);
1526 cache->glyph.matrix[nrows - 1] = glyphs;
1527 cache->glyph.nrows = nrows;
1531 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1532 dispatch_release (group);
1536 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1540 uintptr_t key, value;
1544 if (cache->glyph.dictionary == NULL)
1545 cache->glyph.dictionary =
1546 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1547 key = c / NGLYPHS_IN_VALUE;
1548 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1549 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1550 (const void *) key);
1551 glyph = (value >> nshifts);
1554 UniChar unichars[2];
1556 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1558 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1562 glyph = kCGFontIndexInvalid;
1564 value |= ((uintptr_t) glyph << nshifts);
1565 CFDictionarySetValue (cache->glyph.dictionary,
1566 (const void *) key, (const void *) value);
1574 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1577 struct macfont_info *macfont_info = (struct macfont_info *) font;
1578 FontRef macfont = macfont_info->macfont;
1581 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1585 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1587 struct macfont_info *macfont_info = (struct macfont_info *) font;
1588 FontRef macfont = macfont_info->macfont;
1589 struct macfont_cache *cache = macfont_info->cache;
1590 CFDataRef result = NULL;
1592 if (cache->uvs.table == NULL)
1594 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1595 CharacterCollection uvs_collection =
1596 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1598 if (uvs_table == NULL
1599 && mac_font_get_glyph_for_cid (macfont,
1600 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1601 6480) != kCGFontIndexInvalid)
1603 /* If the glyph for U+4E55 is accessible via its CID 6480,
1604 then we use the Adobe-Japan1 UVS table, which maps a
1605 variation sequence to a CID, as a fallback. */
1606 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1608 if (mac_uvs_table_adobe_japan1 == NULL)
1609 mac_uvs_table_adobe_japan1 =
1610 CFDataCreateWithBytesNoCopy (NULL,
1611 mac_uvs_table_adobe_japan1_bytes,
1612 sizeof (mac_uvs_table_adobe_japan1_bytes),
1614 if (mac_uvs_table_adobe_japan1)
1616 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1617 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1620 if (uvs_table == NULL)
1621 cache->uvs.table = kCFNull;
1623 cache->uvs.table = uvs_table;
1624 cache->uvs.collection = uvs_collection;
1627 if (cache->uvs.table != kCFNull)
1629 result = cache->uvs.table;
1630 *collection = cache->uvs.collection;
1636 static Lisp_Object macfont_get_cache (struct frame *);
1637 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1638 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1639 static Lisp_Object macfont_list_family (struct frame *);
1640 static void macfont_free_entity (Lisp_Object);
1641 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1642 static void macfont_close (struct font *);
1643 static int macfont_has_char (Lisp_Object, int);
1644 static unsigned macfont_encode_char (struct font *, int);
1645 static void macfont_text_extents (struct font *, unsigned int *, int,
1646 struct font_metrics *);
1647 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1648 static Lisp_Object macfont_shape (Lisp_Object);
1649 static int macfont_variation_glyphs (struct font *, int c,
1650 unsigned variations[256]);
1651 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1653 static struct font_driver macfont_driver =
1655 LISP_INITIALLY_ZERO, /* Qmac_ct */
1656 0, /* case insensitive */
1660 macfont_list_family,
1661 macfont_free_entity,
1664 NULL, /* prepare_face */
1665 NULL, /* done_face */
1667 macfont_encode_char,
1668 macfont_text_extents,
1670 NULL, /* get_bitmap */
1671 NULL, /* free_bitmap */
1672 NULL, /* anchor_point */
1673 NULL, /* otf_capability */
1674 NULL, /* otf_drive */
1675 NULL, /* start_for_frame */
1676 NULL, /* end_for_frame */
1679 macfont_variation_glyphs,
1680 macfont_filter_properties,
1684 macfont_get_cache (struct frame * f)
1686 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1688 return (dpyinfo->name_list_element);
1692 macfont_get_charset (Lisp_Object registry)
1694 char *str = SSDATA (SYMBOL_NAME (registry));
1695 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1699 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1703 else if (str[i] == '*')
1710 regexp = make_unibyte_string (re, j);
1711 for (i = 0; cf_charset_table[i].name; i++)
1712 if (fast_c_string_match_ignore_case
1713 (regexp, cf_charset_table[i].name,
1714 strlen (cf_charset_table[i].name)) >= 0)
1716 if (! cf_charset_table[i].name)
1718 if (! cf_charset_table[i].cf_charset)
1720 int *uniquifier = cf_charset_table[i].uniquifier;
1721 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1724 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1728 for (j = 0; uniquifier[j]; j++)
1730 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1732 CFCharacterSetAddCharactersInRange (charset,
1733 CFRangeMake (uniquifier[j], 1));
1736 string = CFStringCreateWithCharacters (NULL, unichars, count);
1739 CFRelease (charset);
1742 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1744 CFRelease (charset);
1745 /* CFCharacterSetCreateWithCharactersInString does not handle
1746 surrogate pairs properly as of Mac OS X 10.5. */
1747 cf_charset_table[i].cf_charset_string = string;
1755 unsigned int script_tag, langsys_tag;
1757 unsigned int *features[2];
1760 #define OTF_SYM_TAG(SYM, TAG) \
1762 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1763 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1766 #define OTF_TAG_STR(TAG, P) \
1768 (P)[0] = (char) (TAG >> 24); \
1769 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1770 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1771 (P)[3] = (char) (TAG & 0xFF); \
1775 static struct OpenTypeSpec *
1776 macfont_get_open_type_spec (Lisp_Object otf_spec)
1778 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1785 spec->script = XCAR (otf_spec);
1786 if (! NILP (spec->script))
1788 OTF_SYM_TAG (spec->script, spec->script_tag);
1789 val = assq_no_quit (spec->script, Votf_script_alist);
1790 if (CONSP (val) && SYMBOLP (XCDR (val)))
1791 spec->script = XCDR (val);
1793 spec->script = Qnil;
1796 spec->script_tag = 0x44464C54; /* "DFLT" */
1797 otf_spec = XCDR (otf_spec);
1798 spec->langsys_tag = 0;
1799 if (! NILP (otf_spec))
1801 val = XCAR (otf_spec);
1803 OTF_SYM_TAG (val, spec->langsys_tag);
1804 otf_spec = XCDR (otf_spec);
1806 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1807 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1811 val = XCAR (otf_spec);
1814 len = Flength (val);
1816 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1818 : malloc (XINT (len) * sizeof *spec->features[i]));
1819 if (! spec->features[i])
1821 if (i > 0 && spec->features[0])
1822 free (spec->features[0]);
1826 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1828 if (NILP (XCAR (val)))
1834 OTF_SYM_TAG (XCAR (val), tag);
1835 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1838 spec->nfeatures[i] = j;
1843 static CFMutableDictionaryRef
1844 macfont_create_attributes_with_spec (Lisp_Object spec)
1846 Lisp_Object tmp, extra;
1847 CFMutableArrayRef langarray = NULL;
1848 CFCharacterSetRef charset = NULL;
1849 CFStringRef charset_string = NULL;
1850 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1851 Lisp_Object script = Qnil;
1852 Lisp_Object registry;
1853 int cf_charset_idx, i;
1854 struct OpenTypeSpec *otspec = NULL;
1856 enum font_property_index index;
1859 } numeric_traits[] =
1860 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1861 {{-0.4, 50}, /* light */
1862 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1863 {0, 100}, /* normal */
1864 {0.24, 140}, /* (semi-bold + normal) / 2 */
1865 {0.4, 200}, /* bold */
1866 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1867 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1868 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1869 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1870 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1872 registry = AREF (spec, FONT_REGISTRY_INDEX);
1874 || EQ (registry, Qascii_0)
1875 || EQ (registry, Qiso10646_1)
1876 || EQ (registry, Qunicode_bmp))
1877 cf_charset_idx = -1;
1882 cf_charset_idx = macfont_get_charset (registry);
1883 if (cf_charset_idx < 0)
1885 charset = cf_charset_table[cf_charset_idx].cf_charset;
1886 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1887 lang = cf_charset_table[cf_charset_idx].lang;
1890 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1893 CFArrayAppendValue (langarray, lang);
1897 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1898 CONSP (extra); extra = XCDR (extra))
1900 Lisp_Object key, val;
1903 key = XCAR (tmp), val = XCDR (tmp);
1904 if (EQ (key, QClang))
1907 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1912 for (; CONSP (val); val = XCDR (val))
1913 if (SYMBOLP (XCAR (val)))
1916 cfstring_create_with_string_noencode (SYMBOL_NAME
1921 CFArrayAppendValue (langarray, lang);
1925 else if (EQ (key, QCotf))
1927 otspec = macfont_get_open_type_spec (val);
1930 script = otspec->script;
1932 else if (EQ (key, QCscript))
1936 if (! NILP (script) && ! charset)
1938 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1940 if (CONSP (chars) && CONSP (CDR (chars)))
1942 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1943 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1945 if (! string || !cs)
1953 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1954 if (CHARACTERP (XCAR (chars)))
1956 UniChar unichars[2];
1958 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1960 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1962 CFStringAppendCharacters (string, unichars, count);
1963 CFCharacterSetAddCharactersInRange (cs, range);
1966 /* CFCharacterSetCreateWithCharactersInString does not
1967 handle surrogate pairs properly as of Mac OS X 10.5. */
1968 charset_string = string;
1972 attributes = CFDictionaryCreateMutable (NULL, 0,
1973 &kCFTypeDictionaryKeyCallBacks,
1974 &kCFTypeDictionaryValueCallBacks);
1978 tmp = AREF (spec, FONT_FAMILY_INDEX);
1979 if (SYMBOLP (tmp) && ! NILP (tmp))
1981 CFStringRef family = macfont_create_family_with_symbol (tmp);
1985 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1990 traits = CFDictionaryCreateMutable (NULL, 4,
1991 &kCFTypeDictionaryKeyCallBacks,
1992 &kCFTypeDictionaryValueCallBacks);
1996 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1998 tmp = AREF (spec, numeric_traits[i].index);
2001 CGPoint *point = numeric_traits[i].points;
2002 CGFloat floatval = (XINT (tmp) >> 8); // XXX
2005 while (point->y < floatval)
2007 if (point == numeric_traits[i].points)
2009 else if (point->y == CGFLOAT_MAX)
2011 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
2012 * ((point->x - (point - 1)->x)
2013 / (point->y - (point - 1)->y)));
2016 else if (floatval < -1.0)
2018 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
2021 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
2025 if (CFDictionaryGetCount (traits))
2026 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
2029 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
2032 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
2035 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
2042 CFRelease (attributes);
2047 if (langarray) CFRelease (langarray);
2048 if (charset && cf_charset_idx < 0) CFRelease (charset);
2049 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
2050 if (traits) CFRelease (traits);
2053 if (otspec->nfeatures[0] > 0)
2054 free (otspec->features[0]);
2055 if (otspec->nfeatures[1] > 0)
2056 free (otspec->features[1]);
2064 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
2065 CFCharacterSetRef charset,
2067 CFArrayRef languages)
2069 Boolean result = true;
2071 if (charset || VECTORP (chars))
2073 CFCharacterSetRef desc_charset =
2074 mac_font_descriptor_copy_attribute (desc,
2075 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2077 if (desc_charset == NULL)
2082 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
2083 else /* VECTORP (chars) */
2087 for (j = 0; j < ASIZE (chars); j++)
2088 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2089 && CFCharacterSetIsLongCharacterMember (desc_charset,
2090 XFASTINT (AREF (chars, j))))
2092 if (j == ASIZE (chars))
2095 CFRelease (desc_charset);
2098 if (result && languages)
2099 result = mac_font_descriptor_supports_languages (desc, languages);
2105 macfont_traits_distance (FontSymbolicTraits sym_traits1,
2106 FontSymbolicTraits sym_traits2)
2108 FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2111 /* We prefer synthetic bold of italic to synthetic italic of bold
2112 when both bold and italic are available but bold-italic is not
2114 if (diff & MAC_FONT_TRAIT_BOLD)
2115 distance |= (1 << 0);
2116 if (diff & MAC_FONT_TRAIT_ITALIC)
2117 distance |= (1 << 1);
2118 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2119 distance |= (1 << 2);
2125 macfont_closest_traits_index_p (CFArrayRef traits_array,
2126 FontSymbolicTraits target,
2129 CFIndex i, count = CFArrayGetCount (traits_array);
2130 FontSymbolicTraits traits;
2133 traits = ((FontSymbolicTraits) (uintptr_t)
2134 CFArrayGetValueAtIndex (traits_array, index));
2135 my_distance = macfont_traits_distance (target, traits);
2137 for (i = 0; i < count; i++)
2140 traits = ((FontSymbolicTraits) (uintptr_t)
2141 CFArrayGetValueAtIndex (traits_array, i));
2142 if (macfont_traits_distance (target, traits) < my_distance)
2150 macfont_list (struct frame *f, Lisp_Object spec)
2152 Lisp_Object val = Qnil, family, extra;
2154 CFStringRef family_name = NULL;
2155 CFMutableDictionaryRef attributes = NULL, traits;
2156 Lisp_Object chars = Qnil;
2158 FontSymbolicTraits synth_sym_traits = 0;
2159 CFArrayRef families;
2160 CFIndex families_count;
2161 CFCharacterSetRef charset = NULL;
2162 CFArrayRef languages = NULL;
2166 family = AREF (spec, FONT_FAMILY_INDEX);
2167 if (! NILP (family))
2169 family_name = macfont_create_family_with_symbol (family);
2170 if (family_name == NULL)
2174 attributes = macfont_create_attributes_with_spec (spec);
2178 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2180 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2181 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2183 traits = ((CFMutableDictionaryRef)
2184 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2186 n = FONT_SLANT_NUMERIC (spec);
2187 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2189 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2191 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2194 n = FONT_WEIGHT_NUMERIC (spec);
2195 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2197 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2199 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2203 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2205 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2207 if (CFStringHasPrefix (language, CFSTR ("ja"))
2208 || CFStringHasPrefix (language, CFSTR ("ko"))
2209 || CFStringHasPrefix (language, CFSTR ("zh")))
2210 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2213 /* Create array of families. */
2215 families = CFArrayCreate (NULL, (const void **) &family_name,
2216 1, &kCFTypeArrayCallBacks);
2219 CFStringRef pref_family;
2220 CFIndex families_count, pref_family_index = -1;
2222 families = macfont_copy_available_families_cache ();
2223 if (families == NULL)
2226 families_count = CFArrayGetCount (families);
2228 /* Move preferred family to the front if exists. */
2230 mac_font_create_preferred_family_for_attributes (attributes);
2234 CFArrayGetFirstIndexOfValue (families,
2235 CFRangeMake (0, families_count),
2237 CFRelease (pref_family);
2239 if (pref_family_index > 0)
2241 CFMutableArrayRef mutable_families =
2242 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2244 if (mutable_families)
2246 CFArrayAppendValue (mutable_families,
2247 CFArrayGetValueAtIndex (families,
2248 pref_family_index));
2249 CFArrayAppendArray (mutable_families, families,
2250 CFRangeMake (0, pref_family_index));
2251 if (pref_family_index + 1 < families_count)
2252 CFArrayAppendArray (mutable_families, families,
2253 CFRangeMake (pref_family_index + 1,
2255 - (pref_family_index + 1)));
2256 CFRelease (families);
2257 families = mutable_families;
2262 charset = CFDictionaryGetValue (attributes,
2263 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2267 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2271 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2274 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2275 if (CONSP (val) && VECTORP (XCDR (val)))
2283 CFRetain (languages);
2284 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2288 extra = AREF (spec, FONT_EXTRA_INDEX);
2289 families_count = CFArrayGetCount (families);
2290 for (i = 0; i < families_count; i++)
2292 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2293 FontDescriptorRef pat_desc;
2295 CFIndex descs_count;
2296 CFMutableArrayRef filtered_descs, traits_array;
2300 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2302 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2306 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2307 10.7 returns NULL if pat_desc represents the LastResort font.
2308 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2309 trailing "s") for such a font. */
2310 if (!CFEqual (family_name, CFSTR ("LastResort")))
2311 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2315 FontDescriptorRef lr_desc =
2316 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2320 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2321 &kCFTypeArrayCallBacks);
2322 CFRelease (lr_desc);
2327 CFRelease (pat_desc);
2331 descs_count = CFArrayGetCount (descs);
2332 if (descs_count == 0
2333 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2342 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2343 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2344 for (j = 0; j < descs_count; j++)
2346 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2347 CFDictionaryRef dict;
2349 FontSymbolicTraits sym_traits;
2351 dict = mac_font_descriptor_copy_attribute (desc,
2352 MAC_FONT_TRAITS_ATTRIBUTE);
2356 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2359 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2363 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2364 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2365 != (spacing >= FONT_SPACING_MONO)))
2368 /* Don't use a color bitmap font unless its family is
2369 explicitly specified. */
2370 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2374 && !macfont_supports_charset_and_languages_p (desc, charset,
2378 CFArrayAppendValue (filtered_descs, desc);
2379 CFArrayAppendValue (traits_array,
2380 (const void *) (uintptr_t) sym_traits);
2384 descs = filtered_descs;
2385 descs_count = CFArrayGetCount (descs);
2387 for (j = 0; j < descs_count; j++)
2389 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2390 FontSymbolicTraits sym_traits =
2391 ((FontSymbolicTraits) (uintptr_t)
2392 CFArrayGetValueAtIndex (traits_array, j));
2393 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2395 mask_min = ((synth_sym_traits ^ sym_traits)
2396 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2397 if (FONT_SLANT_NUMERIC (spec) < 0)
2398 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2399 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2400 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2402 mask_max = (synth_sym_traits & ~sym_traits);
2403 /* Synthetic bold does not work for bitmap-only fonts on Mac
2405 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2407 CFNumberRef format =
2408 mac_font_descriptor_copy_attribute (desc,
2409 MAC_FONT_FORMAT_ATTRIBUTE);
2413 uint32_t format_val;
2415 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2417 && format_val == MAC_FONT_FORMAT_BITMAP)
2418 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2422 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2424 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2425 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2426 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2427 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2428 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2429 bmask += MAC_FONT_TRAIT_BOLD)
2430 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2431 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2432 imask += MAC_FONT_TRAIT_ITALIC)
2434 FontSymbolicTraits synth = (imask | bmask | mmask);
2437 || macfont_closest_traits_index_p (traits_array,
2438 (sym_traits | synth),
2441 entity = macfont_descriptor_entity (desc, extra, synth);
2442 if (! NILP (entity))
2443 val = Fcons (entity, val);
2448 CFRelease (traits_array);
2452 CFRelease (families);
2453 val = Fnreverse (val);
2459 FONT_ADD_LOG ("macfont-list", spec, val);
2460 if (charset) CFRelease (charset);
2461 if (languages) CFRelease (languages);
2462 if (attributes) CFRelease (attributes);
2463 if (family_name) CFRelease (family_name);
2471 macfont_match (struct frame * frame, Lisp_Object spec)
2473 Lisp_Object entity = Qnil;
2474 CFMutableDictionaryRef attributes;
2475 FontDescriptorRef pat_desc = NULL, desc = NULL;
2479 attributes = macfont_create_attributes_with_spec (spec);
2482 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2483 CFRelease (attributes);
2487 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2489 CFRelease (pat_desc);
2493 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2499 FONT_ADD_LOG ("macfont-match", spec, entity);
2504 macfont_list_family (struct frame *frame)
2506 Lisp_Object list = Qnil;
2507 CFArrayRef families;
2511 families = macfont_copy_available_families_cache ();
2514 CFIndex i, count = CFArrayGetCount (families);
2516 for (i = 0; i < count; i++)
2517 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2518 CFRelease (families);
2527 macfont_free_entity (Lisp_Object entity)
2529 Lisp_Object val = assq_no_quit (QCfont_entity,
2530 AREF (entity, FONT_EXTRA_INDEX));
2531 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2539 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2541 Lisp_Object val, font_object;
2542 CFStringRef font_name;
2543 struct macfont_info *macfont_info = NULL;
2547 FontSymbolicTraits sym_traits;
2549 int len, i, total_width;
2551 CGFloat ascent, descent, leading;
2553 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2555 || XTYPE (XCDR (val)) != Lisp_Misc
2556 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2558 font_name = XSAVE_POINTER (XCDR (val), 0);
2559 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2561 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2566 macfont = mac_font_create_with_name (font_name, size);
2569 int fontsize = (int) [((NSFont *) macfont) pointSize];
2570 if (fontsize != size) size = fontsize;
2576 font_object = font_build_object (VECSIZE (struct macfont_info),
2577 Qmac_ct, entity, size);
2578 font = XFONT_OBJECT (font_object);
2579 font->pixel_size = size;
2580 font->driver = &macfont_driver;
2581 font->encoding_charset = font->repertory_charset = -1;
2585 macfont_info = (struct macfont_info *) font;
2586 macfont_info->macfont = macfont;
2587 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2589 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2590 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2591 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2594 macfont_info->screen_font = NULL;
2595 macfont_info->cache = macfont_lookup_cache (font_name);
2596 macfont_retain_cache (macfont_info->cache);
2597 macfont_info->metrics = NULL;
2598 macfont_info->metrics_nrows = 0;
2599 macfont_info->synthetic_italic_p = 0;
2600 macfont_info->synthetic_bold_p = 0;
2601 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2602 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2603 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2604 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2605 macfont_info->synthetic_italic_p = 1;
2606 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2607 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2608 macfont_info->synthetic_bold_p = 1;
2609 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2610 macfont_info->spacing = MACFONT_SPACING_MONO;
2611 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2612 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2613 == FONT_SPACING_SYNTHETIC_MONO))
2614 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2615 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2616 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2619 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2621 macfont_info->antialias =
2622 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2624 macfont_info->color_bitmap_p = 0;
2625 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2626 macfont_info->color_bitmap_p = 1;
2628 glyph = macfont_get_glyph_for_character (font, ' ');
2629 if (glyph != kCGFontIndexInvalid)
2630 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2632 /* dirty workaround */
2633 font->space_width = pixel_size;
2635 total_width = font->space_width;
2636 for (i = 1; i < 95; i++)
2638 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2639 if (glyph == kCGFontIndexInvalid)
2641 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2644 font->average_width = total_width / 95;
2646 font->average_width = font->space_width; /* XXX */
2648 if (!(macfont_info->screen_font
2649 && mac_screen_font_get_metrics (macfont_info->screen_font,
2650 &ascent, &descent, &leading)))
2652 CFStringRef family_name;
2654 ascent = mac_font_get_ascent (macfont);
2655 descent = mac_font_get_descent (macfont);
2656 leading = mac_font_get_leading (macfont);
2657 /* AppKit and WebKit do some adjustment to the heights of
2658 Courier, Helvetica, and Times. */
2659 family_name = mac_font_copy_family_name (macfont);
2662 if (CFEqual (family_name, CFSTR ("Courier"))
2663 || CFEqual (family_name, CFSTR ("Helvetica"))
2664 || CFEqual (family_name, CFSTR ("Times")))
2665 ascent += (ascent + descent) * .15f;
2666 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2671 CFRelease (family_name);
2674 font->ascent = ascent + 0.5f;
2675 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2676 if (CONSP (val) && !NILP (XCDR (val)))
2677 font->descent = descent + 0.5f;
2679 font->descent = descent + leading + 0.5f;
2680 font->height = font->ascent + font->descent;
2682 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2683 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2687 /* Unfortunately Xft doesn't provide a way to get minimum char
2688 width. So, we use space_width instead. */
2689 font->min_width = font->max_width = font->space_width; /* XXX */
2691 font->baseline_offset = 0;
2692 font->relative_compose = 0;
2693 font->default_ascent = 0;
2694 font->vertical_centering = 0;
2700 macfont_close (struct font *font)
2702 struct macfont_info *macfont_info = (struct macfont_info *) font;
2704 if (macfont_info->cache)
2709 CFRelease (macfont_info->macfont);
2710 CGFontRelease (macfont_info->cgfont);
2711 if (macfont_info->screen_font)
2712 CFRelease (macfont_info->screen_font);
2713 macfont_release_cache (macfont_info->cache);
2714 for (i = 0; i < macfont_info->metrics_nrows; i++)
2715 if (macfont_info->metrics[i])
2716 xfree (macfont_info->metrics[i]);
2717 if (macfont_info->metrics)
2718 xfree (macfont_info->metrics);
2719 macfont_info->cache = NULL;
2725 macfont_has_char (Lisp_Object font, int c)
2728 CFCharacterSetRef charset;
2731 if (FONT_ENTITY_P (font))
2736 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2738 name = XSAVE_POINTER (val, 0);
2739 charset = macfont_get_cf_charset_for_name (name);
2742 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2744 result = CFCharacterSetIsLongCharacterMember (charset, c);
2751 macfont_encode_char (struct font *font, int c)
2753 struct macfont_info *macfont_info = (struct macfont_info *) font;
2757 glyph = macfont_get_glyph_for_character (font, c);
2760 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2764 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2765 struct font_metrics *metrics)
2770 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2771 for (i = 1; i < nglyphs; i++)
2773 struct font_metrics m;
2774 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2779 if (width + m.lbearing < metrics->lbearing)
2780 metrics->lbearing = width + m.lbearing;
2781 if (width + m.rbearing > metrics->rbearing)
2782 metrics->rbearing = width + m.rbearing;
2783 if (m.ascent > metrics->ascent)
2784 metrics->ascent = m.ascent;
2785 if (m.descent > metrics->descent)
2786 metrics->descent = m.descent;
2793 metrics->width = width;
2797 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2798 bool with_background)
2800 struct frame * f = s->f;
2801 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2802 CGRect background_rect;
2803 CGPoint text_position;
2806 CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2807 bool no_antialias_p =
2808 (NILP (ns_antialias_text)
2809 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2810 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2811 && font_size <= macfont_antialias_threshold));
2812 int len = to - from;
2813 struct face *face = s->face;
2814 CGContextRef context;
2818 if (with_background)
2819 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2820 s->width, FONT_HEIGHT (s->font));
2822 background_rect = CGRectNull;
2824 text_position = CGPointMake (x, -y);
2825 glyphs = xmalloc (sizeof (CGGlyph) * len);
2827 CGFloat advance_delta = 0;
2829 CGFloat total_width = 0;
2831 positions = xmalloc (sizeof (CGPoint) * len);
2832 for (i = 0; i < len; i++)
2836 glyphs[i] = s->char2b[from + i];
2837 width = (s->padding_p ? 1
2838 : macfont_glyph_extents (s->font, glyphs[i],
2839 NULL, &advance_delta,
2841 positions[i].x = total_width + advance_delta;
2843 total_width += width;
2847 context = [[NSGraphicsContext currentContext] graphicsPort];
2848 CGContextSaveGState (context);
2850 if (!CGRectIsNull (background_rect))
2852 if (s->hl == DRAW_MOUSE_FACE)
2854 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2856 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2858 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2859 CGContextFillRects (context, &background_rect, 1);
2862 if (macfont_info->cgfont)
2864 CGAffineTransform atfm;
2866 CGContextScaleCTM (context, 1, -1);
2867 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2868 if (macfont_info->synthetic_italic_p)
2869 atfm = synthetic_italic_atfm;
2871 atfm = CGAffineTransformIdentity;
2872 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2874 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2875 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2876 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2879 CGContextSetShouldAntialias (context, false);
2881 CGContextSetTextMatrix (context, atfm);
2882 CGContextSetTextPosition (context, text_position.x, text_position.y);
2884 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2885 if (macfont_info->color_bitmap_p
2886 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2887 && CTFontDrawGlyphs != NULL
2893 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2898 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2900 CGContextSetFont (context, macfont_info->cgfont);
2901 CGContextSetFontSize (context, font_size);
2902 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2909 CGContextRestoreGState (context);
2917 macfont_shape (Lisp_Object lgstring)
2919 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2920 struct macfont_info *macfont_info = (struct macfont_info *) font;
2921 FontRef macfont = macfont_info->macfont;
2922 ptrdiff_t glyph_len, len, i, j;
2925 CFIndex *nonbmp_indices;
2928 struct mac_glyph_layout *glyph_layouts;
2930 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2932 for (i = 0; i < glyph_len; i++)
2934 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2938 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2944 if (INT_MAX / 2 < len)
2945 memory_full (SIZE_MAX);
2947 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2948 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2949 for (i = j = 0; i < len; i++)
2951 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2953 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2955 nonbmp_indices[j] = i + j;
2959 nonbmp_indices[j] = len + j; /* sentinel */
2963 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2967 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2968 if (macfont_info->screen_font)
2969 used = mac_screen_font_shape (macfont_info->screen_font, string,
2970 glyph_layouts, glyph_len);
2972 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2983 for (i = 0; i < used; i++)
2985 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2986 struct mac_glyph_layout *gl = glyph_layouts + i;
2988 struct font_metrics metrics;
2989 int xoff, yoff, wadjust;
2993 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2994 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2997 from = gl->comp_range.location;
2998 /* Convert UTF-16 index to UTF-32. */
3000 while (nonbmp_indices[j] < from)
3003 LGLYPH_SET_FROM (lglyph, from);
3005 to = gl->comp_range.location + gl->comp_range.length;
3006 /* Convert UTF-16 index to UTF-32. */
3007 while (nonbmp_indices[j] < to)
3010 LGLYPH_SET_TO (lglyph, to - 1);
3012 /* LGLYPH_CHAR is used in `describe-char' for checking whether
3013 the composition is trivial. */
3017 if (unichars[gl->string_index] >= 0xD800
3018 && unichars[gl->string_index] < 0xDC00)
3019 c = (((unichars[gl->string_index] - 0xD800) << 10)
3020 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
3022 c = unichars[gl->string_index];
3023 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
3025 LGLYPH_SET_CHAR (lglyph, c);
3029 unsigned long cc = gl->glyph_id;
3030 LGLYPH_SET_CODE (lglyph, cc);
3033 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
3034 LGLYPH_SET_WIDTH (lglyph, metrics.width);
3035 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
3036 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
3037 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
3038 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
3040 xoff = lround (gl->advance_delta);
3041 yoff = lround (- gl->baseline_delta);
3042 wadjust = lround (gl->advance);
3043 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
3047 vec = Fmake_vector (make_number (3), Qnil);
3048 ASET (vec, 0, make_number (xoff));
3049 ASET (vec, 1, make_number (yoff));
3050 ASET (vec, 2, make_number (wadjust));
3051 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
3057 return make_number (used);
3060 /* Structures for the UVS subtable (format 14) in the cmap table. */
3061 typedef UInt8 UINT24[3];
3063 #pragma pack(push, 1)
3064 struct variation_selector_record
3066 UINT24 var_selector;
3067 UInt32 default_uvs_offset, non_default_uvs_offset;
3072 UInt32 length, num_var_selector_records;
3073 struct variation_selector_record variation_selector_records[1];
3075 #define SIZEOF_UVS_TABLE_HEADER \
3076 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3078 struct unicode_value_range
3080 UINT24 start_unicode_value;
3081 UInt8 additional_count;
3083 struct default_uvs_table {
3084 UInt32 num_unicode_value_ranges;
3085 struct unicode_value_range unicode_value_ranges[1];
3087 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3088 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3092 UINT24 unicode_value;
3095 struct non_default_uvs_table
3097 UInt32 num_uvs_mappings;
3098 struct uvs_mapping uvs_mappings[1];
3100 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3101 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3104 /* Read big endian values. The argument LVAL must be an lvalue. */
3105 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3106 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3107 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3108 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3109 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3110 /* Succeeding one byte should also be accessible. */
3111 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3112 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3114 /* Return UVS subtable for the specified FONT. If the subtable is not
3115 found or ill-formatted, then return NULL. */
3118 mac_font_copy_uvs_table (FontRef font)
3120 CFDataRef cmap_table, uvs_table = NULL;
3122 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3125 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3126 struct uvs_table *uvs;
3127 struct variation_selector_record *records;
3128 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3131 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3135 cmap_len = CFDataGetLength (cmap_table);
3136 if (sizeof_sfntCMapHeader > cmap_len)
3139 ntables = BUINT16_VALUE (cmap->numTables);
3140 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3141 / sizeof_sfntCMapEncoding))
3144 for (i = 0; i < ntables; i++)
3145 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3146 == kFontUnicodePlatform)
3147 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3148 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3150 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3154 || uvs_offset > cmap_len
3155 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3158 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3159 uvs_len = BUINT32_VALUE (uvs->length);
3160 if (uvs_len > cmap_len - uvs_offset
3161 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3164 if (BUINT16_VALUE (uvs->format) != 14)
3167 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3168 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3169 / sizeof (struct variation_selector_record)))
3172 records = uvs->variation_selector_records;
3173 for (i = 0; i < nrecords; i++)
3175 UInt32 default_uvs_offset, non_default_uvs_offset;
3177 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3178 if (default_uvs_offset)
3180 struct default_uvs_table *default_uvs;
3183 if (default_uvs_offset > uvs_len
3184 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3185 > uvs_len - default_uvs_offset))
3188 default_uvs = ((struct default_uvs_table *)
3189 ((UInt8 *) uvs + default_uvs_offset));
3190 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3191 if (nranges > ((uvs_len - default_uvs_offset
3192 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3193 / sizeof (struct unicode_value_range)))
3195 /* Now 2 * nranges can't overflow, so we can safely use
3196 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3197 mac_font_get_glyphs_for_variants. */
3200 non_default_uvs_offset =
3201 BUINT32_VALUE (records[i].non_default_uvs_offset);
3202 if (non_default_uvs_offset)
3204 struct non_default_uvs_table *non_default_uvs;
3207 if (non_default_uvs_offset > uvs_len
3208 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3209 > uvs_len - non_default_uvs_offset))
3212 non_default_uvs = ((struct non_default_uvs_table *)
3213 ((UInt8 *) uvs + non_default_uvs_offset));
3214 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3215 if (nmappings > ((uvs_len - non_default_uvs_offset
3216 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3217 / sizeof (struct uvs_mapping)))
3219 /* Now 2 * nmappings can't overflow, so we can safely
3220 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3221 in mac_font_get_glyphs_for_variants. */
3225 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3228 CFRelease (cmap_table);
3234 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3235 sequence consisting of the given base character C and each
3236 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3237 result (explained below) into the corresponding GLYPHS[i]. If the
3238 entry is found in the Default UVS Table, then the result is 0. If
3239 the entry is found in the Non-Default UVS Table, then the result is
3240 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3241 elements in SELECTORS must be sorted in strictly increasing
3245 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3246 const UTF32Char selectors[], CGGlyph glyphs[],
3249 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3250 struct variation_selector_record *records = uvs->variation_selector_records;
3252 UInt32 ir, nrecords;
3253 dispatch_queue_t queue =
3254 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3255 dispatch_group_t group = dispatch_group_create ();
3257 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3260 while (i < count && ir < nrecords)
3262 UInt32 default_uvs_offset, non_default_uvs_offset;
3264 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3266 glyphs[i++] = kCGFontIndexInvalid;
3269 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3275 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3276 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3277 non_default_uvs_offset =
3278 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3279 dispatch_group_async (group, queue, ^{
3280 glyphs[i] = kCGFontIndexInvalid;
3282 if (default_uvs_offset)
3284 struct default_uvs_table *default_uvs =
3285 (struct default_uvs_table *) ((UInt8 *) uvs
3286 + default_uvs_offset);
3287 struct unicode_value_range *ranges =
3288 default_uvs->unicode_value_ranges;
3292 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3295 UInt32 mid = (lo + hi) / 2;
3297 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3303 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3304 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3308 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3310 struct non_default_uvs_table *non_default_uvs =
3311 (struct non_default_uvs_table *) ((UInt8 *) uvs
3312 + non_default_uvs_offset);
3313 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3317 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3320 UInt32 mid = (lo + hi) / 2;
3322 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3328 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3329 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3336 glyphs[i++] = kCGFontIndexInvalid;
3337 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3338 dispatch_release (group);
3342 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3344 CFDataRef uvs_table;
3345 CharacterCollection uvs_collection;
3349 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3353 UTF32Char selectors[256];
3354 CGGlyph glyphs[256];
3356 for (i = 0; i < 16; i++)
3357 selectors[i] = 0xFE00 + i;
3358 for (; i < 256; i++)
3359 selectors[i] = 0xE0100 + (i - 16);
3360 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3361 for (i = 0; i < 256; i++)
3363 CGGlyph glyph = glyphs[i];
3365 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3366 && glyph != kCGFontIndexInvalid)
3367 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3368 if (glyph == kCGFontIndexInvalid)
3372 variations[i] = (glyph ? glyph
3373 : macfont_get_glyph_for_character (font, c));
3383 static const char *const macfont_booleans[] = {
3389 static const char *const macfont_non_booleans[] = {
3397 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3399 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3403 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3404 CFArrayRef languages)
3406 Boolean result = true;
3407 CFArrayRef desc_languages =
3408 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3410 if (desc_languages == NULL)
3414 CFIndex desc_languages_count, i, languages_count;
3416 desc_languages_count = CFArrayGetCount (desc_languages);
3417 languages_count = CFArrayGetCount (languages);
3418 for (i = 0; i < languages_count; i++)
3419 if (!CFArrayContainsValue (desc_languages,
3420 CFRangeMake (0, desc_languages_count),
3421 CFArrayGetValueAtIndex (languages, i)))
3426 CFRelease (desc_languages);
3433 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3435 CFStringRef result = NULL;
3436 CFStringRef charset_string =
3437 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3439 if (charset_string && CFStringGetLength (charset_string) > 0)
3441 CFStringRef keys[] = {
3442 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3443 kCTLanguageAttributeName
3445 CFSTR ("NSLanguage")
3448 CFTypeRef values[] = {NULL};
3449 CFIndex num_values = 0;
3450 CFArrayRef languages
3451 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3453 if (languages && CFArrayGetCount (languages) > 0)
3455 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3456 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3459 CFCharacterSetRef charset =
3460 CFDictionaryGetValue (attributes,
3461 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3463 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3468 CFAttributedStringRef attr_string = NULL;
3469 CTLineRef ctline = NULL;
3470 CFDictionaryRef attrs
3471 = CFDictionaryCreate (NULL, (const void **) keys,
3472 (const void **) values, num_values,
3473 &kCFTypeDictionaryKeyCallBacks,
3474 &kCFTypeDictionaryValueCallBacks);
3478 attr_string = CFAttributedStringCreate (NULL, charset_string,
3484 ctline = CTLineCreateWithAttributedString (attr_string);
3485 CFRelease (attr_string);
3489 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3490 CFIndex i, nruns = CFArrayGetCount (runs);
3493 for (i = 0; i < nruns; i++)
3495 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3496 CFDictionaryRef attributes = CTRunGetAttributes (run);
3497 CTFontRef font_in_run;
3499 if (attributes == NULL)
3502 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3503 if (font_in_run == NULL)
3507 else if (!mac_ctfont_equal_in_postscript_name (font,
3511 if (nruns > 0 && i == nruns)
3512 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3521 static inline double
3522 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3524 return CTFontGetAdvancesForGlyphs (font,
3525 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3526 kCTFontOrientationDefault,
3528 kCTFontDefaultOrientation,
3533 static inline CGRect
3534 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3536 return CTFontGetBoundingRectsForGlyphs (font,
3537 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3538 kCTFontOrientationDefault,
3540 kCTFontDefaultOrientation,
3546 mac_ctfont_create_available_families (void)
3548 CFMutableArrayRef families = NULL;
3551 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3555 CFIndex i, count = CFArrayGetCount (orig_families);
3557 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3559 for (i = 0; i < count; i++)
3561 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3563 if (!CFStringHasPrefix (family, CFSTR ("."))
3564 && (CTFontManagerCompareFontFamilyNames (family,
3565 CFSTR ("LastResort"),
3567 != kCFCompareEqualTo))
3568 CFArrayAppendValue (families, family);
3570 CFRelease (orig_families);
3578 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3581 CFStringRef name1, name2;
3587 name1 = CTFontCopyPostScriptName (font1);
3590 name2 = CTFontCopyPostScriptName (font2);
3593 result = CFEqual (name1, name2);
3603 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3606 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3607 CFTypeRef values[] = {NULL, NULL};
3608 CFDictionaryRef attributes = NULL;
3609 CFAttributedStringRef attr_string = NULL;
3610 CTLineRef ctline = NULL;
3611 float float_zero = 0.0f;
3613 values[0] = macfont;
3614 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3617 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3618 (const void **) values,
3620 &kCFTypeDictionaryKeyCallBacks,
3621 &kCFTypeDictionaryValueCallBacks);
3622 CFRelease (values[1]);
3626 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3627 CFRelease (attributes);
3631 ctline = CTLineCreateWithAttributedString (attr_string);
3632 CFRelease (attr_string);
3636 /* Abandon if ctline contains some fonts other than the
3638 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3639 CFIndex i, nruns = CFArrayGetCount (runs);
3641 for (i = 0; i < nruns; i++)
3643 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3644 CFDictionaryRef attributes = CTRunGetAttributes (run);
3645 CTFontRef font_in_run;
3647 if (attributes == NULL)
3650 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3651 if (font_in_run == NULL)
3653 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3667 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3668 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3670 CFIndex used, result = 0;
3671 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3676 used = CTLineGetGlyphCount (ctline);
3677 if (used <= glyph_len)
3679 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3680 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3681 CGFloat total_advance = 0;
3682 CFIndex total_glyph_count = 0;
3684 for (k = 0; k < ctrun_count; k++)
3686 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3687 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3688 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3689 CFRange string_range, comp_range, range;
3690 CFIndex *permutation;
3692 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3693 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3697 #define RIGHT_TO_LEFT_P permutation
3699 /* Now the `comp_range' member of struct mac_glyph_layout is
3700 temporarily used as a work area such that:
3701 glbuf[i].comp_range.location =
3702 min {compRange[i + 1].location, ...,
3703 compRange[glyph_count - 1].location,
3704 maxRange (stringRangeForCTRun)}
3705 glbuf[i].comp_range.length = maxRange (compRange[i])
3706 where compRange[i] is the range of composed characters
3707 containing i-th glyph. */
3708 string_range = CTRunGetStringRange (ctrun);
3709 min_location = string_range.location + string_range.length;
3710 for (i = 0; i < glyph_count; i++)
3712 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3713 CFIndex glyph_index;
3716 if (!RIGHT_TO_LEFT_P)
3717 glyph_index = glyph_count - i - 1;
3720 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3723 CFStringGetRangeOfComposedCharactersAtIndex (string,
3725 gl->comp_range.location = min_location;
3726 gl->comp_range.length = rng.location + rng.length;
3727 if (rng.location < min_location)
3728 min_location = rng.location;
3731 /* Fill the `comp_range' member of struct mac_glyph_layout,
3732 and setup a permutation for right-to-left text. */
3733 comp_range = CFRangeMake (string_range.location, 0);
3734 range = CFRangeMake (0, 0);
3737 struct mac_glyph_layout *gl =
3738 glbuf + range.location + range.length;
3740 if (gl->comp_range.length
3741 > comp_range.location + comp_range.length)
3742 comp_range.length = gl->comp_range.length - comp_range.location;
3743 min_location = gl->comp_range.location;
3746 if (min_location >= comp_range.location + comp_range.length)
3748 comp_range.length = min_location - comp_range.location;
3749 for (i = 0; i < range.length; i++)
3751 glbuf[range.location + i].comp_range = comp_range;
3752 if (RIGHT_TO_LEFT_P)
3753 permutation[range.location + i] =
3754 range.location + range.length - i - 1;
3757 comp_range = CFRangeMake (min_location, 0);
3758 range.location += range.length;
3760 if (range.location == glyph_count)
3765 /* Then fill the remaining members. */
3766 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3769 struct mac_glyph_layout *gl;
3772 if (!RIGHT_TO_LEFT_P)
3773 gl = glbuf + range.location;
3778 src = glyph_count - 1 - range.location;
3779 dest = permutation[src];
3783 CFIndex tmp = gl->string_index;
3785 gl->string_index = glbuf[src].string_index;
3786 glbuf[src].string_index = tmp;
3789 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3791 CTRunGetPositions (ctrun, range, &position);
3792 gl->advance_delta = position.x - total_advance;
3793 gl->baseline_delta = position.y;
3794 gl->advance = (gl->advance_delta
3795 + CTRunGetTypographicBounds (ctrun, range,
3797 total_advance += gl->advance;
3800 if (RIGHT_TO_LEFT_P)
3801 xfree (permutation);
3803 #undef RIGHT_TO_LEFT_P
3805 total_glyph_count += glyph_count;
3815 /* The function below seems to cause a memory leak for the CFString
3816 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3817 10.6.3. For now, we use the NSGlyphInfo version instead. */
3818 #if USE_CT_GLYPH_INFO
3820 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3823 CGGlyph result = kCGFontIndexInvalid;
3824 UniChar characters[] = {0xfffd};
3826 CFAttributedStringRef attr_string = NULL;
3827 CTLineRef ctline = NULL;
3829 string = CFStringCreateWithCharacters (NULL, characters,
3830 ARRAYELTS (characters));
3834 CTGlyphInfoRef glyph_info =
3835 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3836 CFDictionaryRef attributes = NULL;
3840 CFStringRef keys[] = {kCTFontAttributeName,
3841 kCTGlyphInfoAttributeName};
3842 CFTypeRef values[] = {font, glyph_info};
3844 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3845 (const void **) values,
3847 &kCFTypeDictionaryKeyCallBacks,
3848 &kCFTypeDictionaryValueCallBacks);
3849 CFRelease (glyph_info);
3853 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3854 CFRelease (attributes);
3860 ctline = CTLineCreateWithAttributedString (attr_string);
3861 CFRelease (attr_string);
3865 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3867 if (CFArrayGetCount (runs) > 0)
3869 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3870 CFDictionaryRef attributes = CTRunGetAttributes (run);
3874 CTFontRef font_in_run =
3875 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3878 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3880 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3881 if (result >= CTFontGetGlyphCount (font))
3882 result = kCGFontIndexInvalid;
3894 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3896 CFArrayRef result = NULL;
3898 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3899 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3900 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3903 CTFontRef user_font =
3904 CTFontCreateUIFontForLanguage (kCTFontUIFontUser, 0, language);
3908 CFArrayRef languages =
3909 CFArrayCreate (NULL, (const void **) &language, 1,
3910 &kCFTypeArrayCallBacks);
3914 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3916 CFRelease (languages);
3918 CFRelease (user_font);
3921 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3922 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3924 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3925 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3929 for (i = 0; macfont_language_default_font_names[i].language; i++)
3931 if (CFEqual (macfont_language_default_font_names[i].language,
3934 CFMutableArrayRef descriptors =
3935 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3942 macfont_language_default_font_names[i].font_names[j];
3945 CFDictionaryRef attributes =
3946 CFDictionaryCreate (NULL,
3948 &MAC_FONT_NAME_ATTRIBUTE),
3950 &macfont_language_default_font_names[i].font_names[j]),
3951 1, &kCFTypeDictionaryKeyCallBacks,
3952 &kCFTypeDictionaryValueCallBacks);
3956 FontDescriptorRef pat_desc =
3957 mac_font_descriptor_create_with_attributes (attributes);
3961 FontDescriptorRef descriptor =
3962 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3966 CFArrayAppendValue (descriptors, descriptor);
3967 CFRelease (descriptor);
3969 CFRelease (pat_desc);
3971 CFRelease (attributes);
3974 result = descriptors;
3986 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3987 CFArrayRef languages)
3989 CFStringRef result = NULL;
3990 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3991 CFArrayRef descriptors =
3992 mac_font_copy_default_descriptors_for_language (language);
3996 CFIndex i, count = CFArrayGetCount (descriptors);
3998 for (i = 0; i < count; i++)
4000 FontDescriptorRef descriptor =
4001 CFArrayGetValueAtIndex (descriptors, i);
4003 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4006 CFStringRef family =
4007 mac_font_descriptor_copy_attribute (descriptor,
4008 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
4011 if (!CFStringHasPrefix (family, CFSTR ("."))
4012 && !CFEqual (family, CFSTR ("LastResort")))
4022 CFRelease (descriptors);
4029 macfont_get_nsctfont (struct font *font)
4031 struct macfont_info *macfont_info = (struct macfont_info *) font;
4032 FontRef macfont = macfont_info->macfont;
4034 return (void *) macfont;
4038 mac_register_font_driver (struct frame *f)
4040 register_font_driver (&macfont_driver, f);
4045 syms_of_macfont (void)
4047 static struct font_driver mac_font_driver;
4049 /* Core Text, for Mac OS X. */
4050 DEFSYM (Qmac_ct, "mac-ct");
4051 macfont_driver.type = Qmac_ct;
4052 register_font_driver (&macfont_driver, NULL);
4054 /* The font property key specifying the font design destination. The
4055 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
4056 text. (See the documentation of X Logical Font Description
4057 Conventions.) In the Mac font driver, 1 means the screen font is
4058 used for calculating some glyph metrics. You can see the
4059 difference with Monaco 8pt or 9pt, for example. */
4060 DEFSYM (QCdestination, ":destination");
4062 /* The boolean-valued font property key specifying the use of leading. */
4063 DEFSYM (QCminspace, ":minspace");
4065 macfont_family_cache = Qnil;
4066 staticpro (&macfont_family_cache);