1 /* Font driver on Mac OSX Core text.
2 Copyright (C) 2009-2014 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 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
41 #include <libkern/OSByteOrder.h>
43 static struct font_driver macfont_driver;
45 /* Core Text, for Mac OS X 10.5 and later. */
46 static Lisp_Object Qmac_ct;
48 static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
49 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
50 static CFArrayRef mac_ctfont_create_available_families (void);
51 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
52 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
54 static CFComparisonResult mac_font_family_compare (const void *,
55 const void *, void *);
56 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
58 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
59 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
60 struct mac_glyph_layout *, CFIndex);
62 mac_font_copy_default_descriptors_for_language (CFStringRef language);
65 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
66 CFArrayRef languages);
69 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
70 CTCharacterCollection,
74 /* The font property key specifying the font design destination. The
75 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
76 text. (See the documentation of X Logical Font Description
77 Conventions.) In the Mac font driver, 1 means the screen font is
78 used for calculating some glyph metrics. You can see the
79 difference with Monaco 8pt or 9pt, for example. */
80 static Lisp_Object QCdestination;
82 /* The boolean-valued font property key specifying the use of
84 static Lisp_Object QCminspace;
86 struct macfont_metrics;
88 /* The actual structure for Mac font that can be cast to struct font. */
95 ScreenFontRef screen_font;
96 struct macfont_cache *cache;
97 struct macfont_metrics **metrics;
99 bool_bf synthetic_italic_p : 1;
100 bool_bf synthetic_bold_p : 1;
101 unsigned spacing : 2;
102 unsigned antialias : 2;
103 bool_bf color_bitmap_p : 1;
106 /* Values for the `spacing' member in `struct macfont_info'. */
110 MACFONT_SPACING_PROPORTIONAL,
111 MACFONT_SPACING_MONO,
112 MACFONT_SPACING_SYNTHETIC_MONO,
115 /* Values for the `antialias' member in `struct macfont_info'. */
119 MACFONT_ANTIALIAS_DEFAULT,
120 MACFONT_ANTIALIAS_OFF,
121 MACFONT_ANTIALIAS_ON,
124 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
125 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
126 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
128 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
129 static const CGFloat synthetic_bold_factor = 0.024;
131 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
132 FontSymbolicTraits *);
133 static void macfont_store_descriptor_attributes (FontDescriptorRef,
135 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
138 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
139 static int macfont_glyph_extents (struct font *, CGGlyph,
140 struct font_metrics *, CGFloat *, int);
141 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
142 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
146 static CFIndex macfont_closest_traits_index (CFArrayRef,
148 static CFDataRef mac_font_copy_uvs_table (FontRef);
149 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
151 CGGlyph [], CFIndex);
153 /* From CFData to a lisp string. Always returns a unibyte string. */
156 cfdata_to_lisp (CFDataRef data)
158 CFIndex len = CFDataGetLength (data);
159 Lisp_Object result = make_uninit_string (len);
161 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
168 /* From CFString to a lisp string. Returns a unibyte string
169 containing a UTF-8 byte sequence. */
172 cfstring_to_lisp_nodecode (CFStringRef string)
174 Lisp_Object result = Qnil;
176 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
180 CFIndex i, length = CFStringGetLength (string);
182 for (i = 0; i < length; i++)
183 if (CFStringGetCharacterAtIndex (string, i) == 0)
187 return make_unibyte_string (s, strlen (s));
190 data = CFStringCreateExternalRepresentation (NULL, string,
191 kCFStringEncodingUTF8, '?');
194 result = cfdata_to_lisp (data);
201 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
202 cfstring_create_with_utf8_cstring, this function preserves NUL
206 cfstring_create_with_string_noencode (Lisp_Object s)
208 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
209 kCFStringEncodingUTF8, false);
212 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
213 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
214 kCFStringEncodingMacRoman, false);
220 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
222 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
224 return advancement.width;
228 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
231 #if USE_CT_GLYPH_INFO
232 return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
235 CGGlyph result = kCGFontIndexInvalid;
236 NSFont *nsFont = (NSFont *) font;
237 unichar characters[] = {0xfffd};
239 [NSString stringWithCharacters:characters
240 length:(sizeof (characters)
241 / sizeof (characters[0]))];
242 NSGlyphInfo *glyphInfo =
243 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
244 collection:collection
246 NSDictionary *attributes =
247 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
248 glyphInfo,NSGlyphInfoAttributeName,nil];
249 NSTextStorage *textStorage =
250 [[NSTextStorage alloc] initWithString:string
251 attributes:attributes];
252 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
253 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
254 NSFont *fontInTextStorage;
256 [layoutManager addTextContainer:textContainer];
257 [textContainer release];
258 [textStorage addLayoutManager:layoutManager];
259 [layoutManager release];
262 (void) [layoutManager glyphRangeForTextContainer:textContainer];
264 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
265 effectiveRange:NULL];
266 if (fontInTextStorage == nsFont
267 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
269 NSGlyph glyph = [layoutManager glyphAtIndex:0];
271 if (glyph < [nsFont numberOfGlyphs])
275 [textStorage release];
283 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
285 NSFont *result, *font;
287 font = [NSFont fontWithName:((NSString *) name) size:size];
288 result = [font screenFont];
290 return (ScreenFontRef)[result retain];
295 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
296 CGFloat *descent, CGFloat *leading)
298 NSFont *nsFont = [(NSFont *)font printerFont];
299 NSTextStorage *textStorage;
300 NSLayoutManager *layoutManager;
301 NSTextContainer *textContainer;
303 NSPoint spaceLocation;
306 textStorage = [[NSTextStorage alloc] initWithString:@" "];
307 layoutManager = [[NSLayoutManager alloc] init];
308 textContainer = [[NSTextContainer alloc] init];
310 [textStorage setFont:nsFont];
311 [textContainer setLineFragmentPadding:0];
312 [layoutManager setUsesScreenFonts:YES];
314 [layoutManager addTextContainer:textContainer];
315 [textContainer release];
316 [textStorage addLayoutManager:layoutManager];
317 [layoutManager release];
319 if (!(textStorage && layoutManager && textContainer))
321 [textStorage release];
326 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
327 effectiveRange:NULL];
328 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
329 [textStorage release];
331 *ascent = spaceLocation.y;
332 *descent = NSHeight (usedRect) - spaceLocation.y;
334 descender = [nsFont descender];
335 if (- descender < *descent)
337 *leading = *descent + descender;
338 *descent = - descender;
345 mac_font_shape_1 (NSFont *font, NSString *string,
346 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
351 NSTextStorage *textStorage;
352 NSLayoutManager *layoutManager;
353 NSTextContainer *textContainer;
354 NSUInteger stringLength;
355 NSPoint spaceLocation;
356 NSUInteger used, numberOfGlyphs;
358 textStorage = [[NSTextStorage alloc] initWithString:string];
359 layoutManager = [[NSLayoutManager alloc] init];
360 textContainer = [[NSTextContainer alloc] init];
362 /* Append a trailing space to measure baseline position. */
363 [textStorage appendAttributedString:([[[NSAttributedString alloc]
364 initWithString:@" "] autorelease])];
365 [textStorage setFont:font];
366 [textContainer setLineFragmentPadding:0];
367 [layoutManager setUsesScreenFonts:screen_font_p];
369 [layoutManager addTextContainer:textContainer];
370 [textContainer release];
371 [textStorage addLayoutManager:layoutManager];
372 [layoutManager release];
374 if (!(textStorage && layoutManager && textContainer))
376 [textStorage release];
381 stringLength = [string length];
384 (void) [layoutManager glyphRangeForTextContainer:textContainer];
386 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
388 /* Remove the appended trailing space because otherwise it may
389 generate a wrong result for a right-to-left text. */
390 [textStorage beginEditing];
391 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
392 [textStorage endEditing];
393 (void) [layoutManager glyphRangeForTextContainer:textContainer];
396 while (i < stringLength)
399 NSFont *fontInTextStorage =
400 [textStorage attribute:NSFontAttributeName atIndex:i
401 longestEffectiveRange:&range
402 inRange:(NSMakeRange (0, stringLength))];
404 if (!(fontInTextStorage == font
405 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
407 i = NSMaxRange (range);
409 if (i < stringLength)
410 /* Make the test `used <= glyph_len' below fail if textStorage
411 contained some fonts other than the specified one. */
412 used = glyph_len + 1;
415 NSRange range = NSMakeRange (0, stringLength);
417 range = [layoutManager glyphRangeForCharacterRange:range
418 actualCharacterRange:NULL];
419 numberOfGlyphs = NSMaxRange (range);
420 used = numberOfGlyphs;
421 for (i = 0; i < numberOfGlyphs; i++)
422 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
426 if (0 < used && used <= glyph_len)
428 NSUInteger glyphIndex, prevGlyphIndex;
429 unsigned char bidiLevel;
430 NSUInteger *permutation;
431 NSRange compRange, range;
432 CGFloat totalAdvance;
435 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
438 /* For now we assume the direction is not changed within the
440 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
441 glyphs:NULL characterIndexes:NULL
442 glyphInscriptions:NULL elasticBits:NULL
443 bidiLevels:&bidiLevel];
445 permutation = xmalloc (sizeof (NSUInteger) * used);
449 #define RIGHT_TO_LEFT_P permutation
451 /* Fill the `comp_range' member of struct mac_glyph_layout, and
452 setup a permutation for right-to-left text. */
453 compRange = NSMakeRange (0, 0);
454 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
457 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
458 NSUInteger characterIndex =
459 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
461 gl->string_index = characterIndex;
463 if (characterIndex >= NSMaxRange (compRange))
465 compRange.location = NSMaxRange (compRange);
468 NSRange characterRange =
470 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
473 NSMaxRange (characterRange) - compRange.location;
474 [layoutManager glyphRangeForCharacterRange:compRange
475 actualCharacterRange:&characterRange];
476 characterIndex = NSMaxRange (characterRange) - 1;
478 while (characterIndex >= NSMaxRange (compRange));
481 for (i = 0; i < range.length; i++)
482 permutation[range.location + i] = NSMaxRange (range) - i - 1;
484 range = NSMakeRange (NSMaxRange (range), 0);
487 gl->comp_range.location = compRange.location;
488 gl->comp_range.length = compRange.length;
490 while (++glyphIndex < numberOfGlyphs)
491 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
495 for (i = 0; i < range.length; i++)
496 permutation[range.location + i] = NSMaxRange (range) - i - 1;
498 /* Then fill the remaining members. */
499 glyphIndex = prevGlyphIndex = 0;
500 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
503 if (!RIGHT_TO_LEFT_P)
510 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
511 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
512 inTextContainer:textContainer rectCount:&nrects];
514 totalAdvance = NSMaxX (glyphRects[0]);
517 for (i = 0; i < used; i++)
519 struct mac_glyph_layout *gl;
521 NSUInteger nextGlyphIndex;
526 if (!RIGHT_TO_LEFT_P)
527 gl = glyph_layouts + i;
530 NSUInteger dest = permutation[i];
532 gl = glyph_layouts + dest;
535 CFIndex tmp = gl->string_index;
537 gl->string_index = glyph_layouts[i].string_index;
538 glyph_layouts[i].string_index = tmp;
541 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
543 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
544 gl->baseline_delta = spaceLocation.y - location.y;
546 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
549 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
552 if (!RIGHT_TO_LEFT_P)
556 if (prevGlyphIndex == 0)
557 glyphRange = NSMakeRange (0, nextGlyphIndex);
559 glyphRange = NSMakeRange (glyphIndex,
560 nextGlyphIndex - glyphIndex);
563 rectArrayForGlyphRange:glyphRange
564 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
565 inTextContainer:textContainer rectCount:&nrects];
566 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
567 gl->advance_delta = location.x - totalAdvance;
568 gl->advance = maxX - totalAdvance;
575 if (nextGlyphIndex == numberOfGlyphs)
576 glyphRange = NSMakeRange (prevGlyphIndex,
577 numberOfGlyphs - prevGlyphIndex);
579 glyphRange = NSMakeRange (prevGlyphIndex,
580 glyphIndex + 1 - prevGlyphIndex);
583 rectArrayForGlyphRange:glyphRange
584 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
585 inTextContainer:textContainer rectCount:&nrects];
586 minX = min (NSMinX (glyphRects[0]), totalAdvance);
587 gl->advance = totalAdvance - minX;
589 gl->advance_delta = location.x - totalAdvance;
592 prevGlyphIndex = glyphIndex + 1;
593 glyphIndex = nextGlyphIndex;
599 #undef RIGHT_TO_LEFT_P
603 [textStorage release];
609 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
610 struct mac_glyph_layout *glyph_layouts,
613 return mac_font_shape_1 ([(NSFont *)font printerFont],
615 glyph_layouts, glyph_len, YES);
619 get_cgcolor(unsigned long idx, struct frame *f)
621 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
623 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
624 NSInteger noc = [nsColor numberOfComponents];
625 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
628 [nsColor getComponents: components];
629 cgColor = CGColorCreate (colorSpace, components);
634 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
636 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
637 CGContextSetFillColorWithColor (context, refcol_) ; \
638 CGColorRelease (refcol_); \
640 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
642 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
643 CGContextSetFillColorWithColor (context, refcol_); \
644 CGColorRelease (refcol_); \
646 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
648 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
649 CGContextSetStrokeColorWithColor (context, refcol_); \
650 CGColorRelease (refcol_); \
654 /* Mac font driver. */
660 /* characters to distinguish the charset from the others */
662 /* additional constraint by language */
665 CFCharacterSetRef cf_charset;
666 CFStringRef cf_charset_string;
667 } cf_charset_table[] =
668 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
669 { "iso8859-2", { 0x00A0, 0x010E }},
670 { "iso8859-3", { 0x00A0, 0x0108 }},
671 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
672 { "iso8859-5", { 0x00A0, 0x0401 }},
673 { "iso8859-6", { 0x00A0, 0x060C }},
674 { "iso8859-7", { 0x00A0, 0x0384 }},
675 { "iso8859-8", { 0x00A0, 0x05D0 }},
676 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
677 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
678 { "iso8859-11", { 0x00A0, 0x0E01 }},
679 { "iso8859-13", { 0x00A0, 0x201C }},
680 { "iso8859-14", { 0x00A0, 0x0174 }},
681 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
682 { "iso8859-16", { 0x00A0, 0x0218}},
683 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
684 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
685 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
686 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
687 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
688 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
689 { "cns11643.1992-3", { 0x201A9 }},
690 { "cns11643.1992-4", { 0x20057 }},
691 { "cns11643.1992-5", { 0x20000 }},
692 { "cns11643.1992-6", { 0x20003 }},
693 { "cns11643.1992-7", { 0x20055 }},
694 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
695 { "jisx0212.1990-0", { 0x4E44 }},
696 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
697 { "jisx0213.2000-2", { 0xFA49 }},
698 { "jisx0213.2004-1", { 0x20B9F }},
699 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
700 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
701 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
702 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
703 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
704 { "unicode-sip", { 0x20000 }},
708 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
711 CFStringRef language;
712 CFStringRef font_names[3];
713 } macfont_language_default_font_names[] = {
714 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
715 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
717 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
718 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
720 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
721 CFSTR ("STXihei"), /* 10.4 - 10.5 */
723 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
724 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
730 static CGFloat macfont_antialias_threshold;
733 macfont_update_antialias_threshold (void)
739 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
740 kCFPreferencesCurrentApplication,
743 macfont_antialias_threshold = threshold;
746 static inline Lisp_Object
747 macfont_intern_prop_cfstring (CFStringRef cfstring)
749 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
751 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
754 static inline CFIndex
755 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
766 unichars[0] = (c >> 10) + 0xD800;
767 unichars[1] = (c & 0x3FF) + 0xDC00;
774 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
775 FontSymbolicTraits *sym_traits)
779 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
780 OS 10.6 when the value is greater than or equal to 1 << 31. */
781 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
783 *sym_traits = (FontSymbolicTraits) sint64_value;
792 macfont_store_descriptor_attributes (FontDescriptorRef desc,
793 Lisp_Object spec_or_entity)
796 CFDictionaryRef dict;
800 str = mac_font_descriptor_copy_attribute (desc,
801 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
804 ASET (spec_or_entity, FONT_FAMILY_INDEX,
805 macfont_intern_prop_cfstring (str));
808 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
812 enum font_property_index index;
816 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
817 {{-0.4, 50}, /* light */
818 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
819 {0, 100}, /* normal */
820 {0.24, 140}, /* (semi-bold + normal) / 2 */
821 {0.4, 200}, /* bold */
822 {CGFLOAT_MAX, CGFLOAT_MAX}}},
823 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
824 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
825 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
826 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
829 for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
831 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
832 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
834 CGPoint *point = numeric_traits[i].points;
836 while (point->x < floatval)
838 if (point == numeric_traits[i].points)
840 else if (point->x == CGFLOAT_MAX)
842 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
843 * ((point->y - (point - 1)->y)
844 / (point->x - (point - 1)->x)));
845 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
846 make_number (lround (floatval)));
850 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
853 FontSymbolicTraits sym_traits;
856 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
857 spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
858 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
859 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
864 num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
865 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
866 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
868 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
874 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
875 FontSymbolicTraits synth_sym_traits)
878 CFDictionaryRef dict;
879 FontSymbolicTraits sym_traits = 0;
882 entity = font_make_entity ();
884 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
885 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
887 macfont_store_descriptor_attributes (desc, entity);
889 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
892 CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
895 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
898 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
899 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
900 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
901 name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
902 font_put_extra (entity, QCfont_entity,
903 make_save_ptr_int ((void *) name, sym_traits));
904 if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
905 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
906 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
907 if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
908 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
909 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
910 if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
911 ASET (entity, FONT_SPACING_INDEX,
912 make_number (FONT_SPACING_SYNTHETIC_MONO));
918 macfont_create_family_with_symbol (Lisp_Object symbol)
920 static CFArrayRef families = NULL;
921 CFStringRef result = NULL, family_name;
922 int using_cache_p = 1;
923 CFComparatorFunction family_name_comparator;
925 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
926 if (family_name == NULL)
929 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
930 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
931 if (CTFontManagerCompareFontFamilyNames != NULL)
934 family_name_comparator = CTFontManagerCompareFontFamilyNames;
936 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
937 else /* CTFontManagerCompareFontFamilyNames == NULL */
939 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
940 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
942 family_name_comparator = mac_font_family_compare;
946 if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
947 == kCFCompareEqualTo)
948 result = CFSTR ("LastResort");
954 if (families == NULL)
956 families = mac_font_create_available_families ();
958 if (families == NULL)
962 count = CFArrayGetCount (families);
963 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
964 (const void *) family_name,
965 family_name_comparator, NULL);
968 CFStringRef name = CFArrayGetValueAtIndex (families, i);
970 if ((*family_name_comparator) (name, family_name, NULL)
971 == kCFCompareEqualTo)
972 result = CFRetain (name);
975 if (result || !using_cache_p)
979 CFRelease (families);
984 CFRelease (family_name);
989 #define WIDTH_FRAC_BITS (4)
990 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
992 struct macfont_metrics
994 unsigned char lbearing_low, rbearing_low;
995 signed lbearing_high : 4, rbearing_high : 4;
996 unsigned char ascent_low, descent_low;
997 signed ascent_high : 4, descent_high : 4;
999 /* These two members are used for fixed-point representation of
1000 glyph width. The `width_int' member is an integer that is
1001 closest to the width. The `width_frac' member is the fractional
1002 adjustment representing a value in [-.5, .5], multiplied by
1003 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1004 the advance delta for centering instead of the glyph width. */
1005 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1008 #define METRICS_VALUE(metrics, member) \
1009 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1010 #define METRICS_SET_VALUE(metrics, member, value) \
1011 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1012 (metrics)->member##_high = tmp >> 8;} while (0)
1016 METRICS_INVALID = -1, /* metrics entry is invalid */
1017 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1020 #define METRICS_STATUS(metrics) \
1021 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1022 #define METRICS_SET_STATUS(metrics, status) \
1023 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1024 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1026 #define METRICS_NCOLS_PER_ROW (128)
1027 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1028 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1031 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1032 struct font_metrics *metrics, CGFloat *advance_delta,
1033 int force_integral_p)
1035 struct macfont_info *macfont_info = (struct macfont_info *) font;
1036 FontRef macfont = macfont_info->macfont;
1038 struct macfont_metrics *cache;
1041 row = glyph / METRICS_NCOLS_PER_ROW;
1042 col = glyph % METRICS_NCOLS_PER_ROW;
1043 if (row >= macfont_info->metrics_nrows)
1045 macfont_info->metrics =
1046 xrealloc (macfont_info->metrics,
1047 sizeof (struct macfont_metrics *) * (row + 1));
1048 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1049 (sizeof (struct macfont_metrics *)
1050 * (row + 1 - macfont_info->metrics_nrows)));
1051 macfont_info->metrics_nrows = row + 1;
1053 if (macfont_info->metrics[row] == NULL)
1055 struct macfont_metrics *new;
1058 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1059 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1060 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1061 macfont_info->metrics[row] = new;
1063 cache = macfont_info->metrics[row] + col;
1065 if (METRICS_STATUS (cache) == METRICS_INVALID)
1069 if (macfont_info->screen_font)
1070 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1072 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1074 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1075 advance delta value. */
1076 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1077 fwidth = (font->pixel_size - fwidth) / 2;
1078 cache->width_int = lround (fwidth);
1079 cache->width_frac = lround ((fwidth - cache->width_int)
1080 * WIDTH_FRAC_SCALE);
1081 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1083 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1084 width = font->pixel_size;
1086 width = cache->width_int;
1090 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1092 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1094 if (macfont_info->synthetic_italic_p)
1096 /* We assume the members a, b, c, and d in
1097 synthetic_italic_atfm are non-negative. */
1099 CGPointApplyAffineTransform (bounds.origin,
1100 synthetic_italic_atfm);
1102 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1104 if (macfont_info->synthetic_bold_p)
1107 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1109 bounds = CGRectInset (bounds, d, d);
1111 switch (macfont_info->spacing)
1113 case MACFONT_SPACING_PROPORTIONAL:
1114 bounds.origin.x += - (cache->width_frac
1115 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1117 case MACFONT_SPACING_MONO:
1119 case MACFONT_SPACING_SYNTHETIC_MONO:
1120 bounds.origin.x += (cache->width_int
1121 + (cache->width_frac
1122 / (CGFloat) WIDTH_FRAC_SCALE));
1125 if (bounds.size.width > 0)
1127 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1128 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1129 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1131 bounds = CGRectIntegral (bounds);
1132 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1133 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1134 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1135 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1137 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1138 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1139 metrics->width = width;
1140 metrics->ascent = METRICS_VALUE (cache, ascent);
1141 metrics->descent = METRICS_VALUE (cache, descent);
1146 switch (macfont_info->spacing)
1148 case MACFONT_SPACING_PROPORTIONAL:
1149 *advance_delta = (force_integral_p ? 0
1150 : - (cache->width_frac
1151 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1153 case MACFONT_SPACING_MONO:
1156 case MACFONT_SPACING_SYNTHETIC_MONO:
1157 *advance_delta = (force_integral_p ? cache->width_int
1159 + (cache->width_frac
1160 / (CGFloat) WIDTH_FRAC_SCALE)));
1168 static CFMutableDictionaryRef macfont_cache_dictionary;
1170 /* Threshold used in row_nkeys_or_perm. This must be less than or
1171 equal to the number of rows that are invalid as BMP (i.e., from
1172 U+D800 to U+DFFF). */
1173 #define ROW_PERM_OFFSET (8)
1175 /* The number of glyphs that can be stored in a value for a single
1176 entry of CFDictionary. */
1177 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1179 struct macfont_cache
1181 int reference_count;
1182 CFCharacterSetRef cf_charset;
1184 /* The cached glyph for a BMP character c is stored in
1185 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1186 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1187 unsigned char row_nkeys_or_perm[256];
1190 /* Number of rows for which the BMP cache is allocated so far.
1191 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1194 /* The cached glyph for a character c is stored as the (c %
1195 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1196 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1197 not stored here if row_nkeys_or_perm[c / 256] >=
1199 CFMutableDictionaryRef dictionary;
1203 /* UVS (Unicode Variation Sequence) subtable data, which is of
1204 type CFDataRef if available. NULL means it is not initialized
1205 yet. kCFNull means the subtable is not found and there is no
1206 suitable fallback table for this font. */
1209 /* Character collection specifying the destination of the mapping
1210 provided by `table' above. If `table' is obtained from the UVS
1211 subtable in the font cmap table, then the value of this member
1212 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1213 CharacterCollection collection;
1217 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1218 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1219 static void macfont_release_cache (struct macfont_cache *);
1220 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1221 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1222 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1223 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1224 CharacterCollection, CGFontIndex);
1225 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1227 static struct macfont_cache *
1228 macfont_lookup_cache (CFStringRef key)
1230 struct macfont_cache *cache;
1232 if (macfont_cache_dictionary == NULL)
1234 macfont_cache_dictionary =
1235 CFDictionaryCreateMutable (NULL, 0,
1236 &kCFTypeDictionaryKeyCallBacks, NULL);
1240 cache = ((struct macfont_cache *)
1241 CFDictionaryGetValue (macfont_cache_dictionary, key));
1245 FontRef macfont = mac_font_create_with_name (key, 0);
1249 cache = xzalloc (sizeof (struct macfont_cache));
1250 /* Treat the LastResort font as if it contained glyphs for
1251 all characters. This may look too rough, but neither
1252 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1253 for this font is correct for non-BMP characters on Mac OS
1255 if (CFStringCompare (key, CFSTR ("LastResort"), 0)
1256 == kCFCompareEqualTo)
1258 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1261 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1263 if (cache->cf_charset == NULL)
1264 cache->cf_charset = mac_font_copy_character_set (macfont);
1265 CFDictionaryAddValue (macfont_cache_dictionary, key,
1266 (const void *) cache);
1267 CFRelease (macfont);
1274 static struct macfont_cache *
1275 macfont_retain_cache (struct macfont_cache *cache)
1277 cache->reference_count++;
1283 macfont_release_cache (struct macfont_cache *cache)
1285 if (--cache->reference_count == 0)
1289 for (i = 0; i < cache->glyph.nrows; i++)
1290 xfree (cache->glyph.matrix[i]);
1291 xfree (cache->glyph.matrix);
1292 if (cache->glyph.dictionary)
1293 CFRelease (cache->glyph.dictionary);
1294 memset (&cache->glyph, 0, sizeof (cache->glyph));
1295 if (cache->uvs.table)
1296 CFRelease (cache->uvs.table);
1297 memset (&cache->uvs, 0, sizeof (cache->uvs));
1301 static CFCharacterSetRef
1302 macfont_get_cf_charset (struct font *font)
1304 struct macfont_info *macfont_info = (struct macfont_info *) font;
1306 return macfont_info->cache->cf_charset;
1309 static CFCharacterSetRef
1310 macfont_get_cf_charset_for_name (CFStringRef name)
1312 struct macfont_cache *cache = macfont_lookup_cache (name);
1314 return cache->cf_charset;
1318 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1320 struct macfont_info *macfont_info = (struct macfont_info *) font;
1321 FontRef macfont = macfont_info->macfont;
1322 struct macfont_cache *cache = macfont_info->cache;
1324 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1327 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1329 if (nkeys_or_perm < ROW_PERM_OFFSET)
1331 UniChar unichars[256], ch;
1335 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1336 dispatch_queue_t queue;
1337 dispatch_group_t group = NULL;
1344 CFMutableDictionaryRef dictionary;
1345 uintptr_t key, value;
1349 if (cache->glyph.dictionary == NULL)
1350 cache->glyph.dictionary =
1351 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1352 dictionary = cache->glyph.dictionary;
1353 key = c / NGLYPHS_IN_VALUE;
1354 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1355 value = ((uintptr_t)
1356 CFDictionaryGetValue (dictionary, (const void *) key));
1357 glyph = (value >> nshifts);
1361 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1364 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1367 glyph = kCGFontIndexInvalid;
1370 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1371 value |= ((uintptr_t) glyph << nshifts);
1372 CFDictionarySetValue (dictionary, (const void *) key,
1373 (const void *) value);
1378 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1380 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1381 group = dispatch_group_create ();
1382 dispatch_group_async (group, queue, ^{
1386 nkeys = nkeys_or_perm;
1387 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1388 if (CFDictionaryContainsKey (dictionary,
1389 (const void *) key))
1391 CFDictionaryRemoveValue (dictionary,
1392 (const void *) key);
1396 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1402 for (i = 0; i < 256; i++)
1405 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1406 unichars[len++] = ch;
1409 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1412 mac_font_get_glyphs_for_characters (macfont, unichars,
1416 int next = unichars[len - 1] % 256;
1419 glyphs[i] = kCGFontIndexInvalid;
1422 glyphs[i] = glyphs[len];
1429 glyphs[i] = kCGFontIndexInvalid;
1431 nrows = cache->glyph.nrows;
1432 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1433 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1435 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1436 sizeof (CGGlyph *) * nrows);
1437 cache->glyph.matrix[nrows - 1] = glyphs;
1438 cache->glyph.nrows = nrows;
1440 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1443 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1444 dispatch_release (group);
1449 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1453 uintptr_t key, value;
1457 if (cache->glyph.dictionary == NULL)
1458 cache->glyph.dictionary =
1459 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1460 key = c / NGLYPHS_IN_VALUE;
1461 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1462 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1463 (const void *) key);
1464 glyph = (value >> nshifts);
1467 UniChar unichars[2];
1469 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1471 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1475 glyph = kCGFontIndexInvalid;
1477 value |= ((uintptr_t) glyph << nshifts);
1478 CFDictionarySetValue (cache->glyph.dictionary,
1479 (const void *) key, (const void *) value);
1487 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1490 struct macfont_info *macfont_info = (struct macfont_info *) font;
1491 FontRef macfont = macfont_info->macfont;
1494 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1498 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1500 struct macfont_info *macfont_info = (struct macfont_info *) font;
1501 FontRef macfont = macfont_info->macfont;
1502 struct macfont_cache *cache = macfont_info->cache;
1503 CFDataRef result = NULL;
1505 if (cache->uvs.table == NULL)
1507 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1508 CharacterCollection uvs_collection =
1509 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1511 if (uvs_table == NULL
1512 && mac_font_get_glyph_for_cid (macfont,
1513 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1514 6480) != kCGFontIndexInvalid)
1516 /* If the glyph for U+4E55 is accessible via its CID 6480,
1517 then we use the Adobe-Japan1 UVS table, which maps a
1518 variation sequence to a CID, as a fallback. */
1519 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1521 if (mac_uvs_table_adobe_japan1 == NULL)
1522 mac_uvs_table_adobe_japan1 =
1523 CFDataCreateWithBytesNoCopy (NULL,
1524 mac_uvs_table_adobe_japan1_bytes,
1525 sizeof (mac_uvs_table_adobe_japan1_bytes),
1527 if (mac_uvs_table_adobe_japan1)
1529 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1530 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1533 if (uvs_table == NULL)
1534 cache->uvs.table = kCFNull;
1536 cache->uvs.table = uvs_table;
1537 cache->uvs.collection = uvs_collection;
1540 if (cache->uvs.table != kCFNull)
1542 result = cache->uvs.table;
1543 *collection = cache->uvs.collection;
1549 static Lisp_Object macfont_get_cache (struct frame *);
1550 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1551 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1552 static Lisp_Object macfont_list_family (struct frame *);
1553 static void macfont_free_entity (Lisp_Object);
1554 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1555 static void macfont_close (struct font *);
1556 static int macfont_has_char (Lisp_Object, int);
1557 static unsigned macfont_encode_char (struct font *, int);
1558 static int macfont_text_extents (struct font *, unsigned int *, int,
1559 struct font_metrics *);
1560 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1561 static Lisp_Object macfont_shape (Lisp_Object);
1562 static int macfont_variation_glyphs (struct font *, int c,
1563 unsigned variations[256]);
1564 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1566 static struct font_driver macfont_driver =
1568 LISP_INITIALLY_ZERO, /* Qmac_ct */
1569 0, /* case insensitive */
1573 macfont_list_family,
1574 macfont_free_entity,
1577 NULL, /* prepare_face */
1578 NULL, /* done_face */
1580 macfont_encode_char,
1581 macfont_text_extents,
1583 NULL, /* get_bitmap */
1584 NULL, /* free_bitmap */
1585 NULL, /* get_outline */
1586 NULL, /* free_outline */
1587 NULL, /* anchor_point */
1588 NULL, /* otf_capability */
1589 NULL, /* otf_drive */
1590 NULL, /* start_for_frame */
1591 NULL, /* end_for_frame */
1594 macfont_variation_glyphs,
1595 macfont_filter_properties,
1599 macfont_get_cache (struct frame * f)
1601 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1603 return (dpyinfo->name_list_element);
1607 macfont_get_charset (Lisp_Object registry)
1609 char *str = SSDATA (SYMBOL_NAME (registry));
1610 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1614 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1618 else if (str[i] == '*')
1625 regexp = make_unibyte_string (re, j);
1626 for (i = 0; cf_charset_table[i].name; i++)
1627 if (fast_c_string_match_ignore_case
1628 (regexp, cf_charset_table[i].name,
1629 strlen (cf_charset_table[i].name)) >= 0)
1631 if (! cf_charset_table[i].name)
1633 if (! cf_charset_table[i].cf_charset)
1635 int *uniquifier = cf_charset_table[i].uniquifier;
1636 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1639 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1643 for (j = 0; uniquifier[j]; j++)
1645 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1647 CFCharacterSetAddCharactersInRange (charset,
1648 CFRangeMake (uniquifier[j], 1));
1651 string = CFStringCreateWithCharacters (NULL, unichars, count);
1654 CFRelease (charset);
1657 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1659 CFRelease (charset);
1660 /* CFCharacterSetCreateWithCharactersInString does not handle
1661 surrogate pairs properly as of Mac OS X 10.5. */
1662 cf_charset_table[i].cf_charset_string = string;
1670 unsigned int script_tag, langsys_tag;
1672 unsigned int *features[2];
1675 #define OTF_SYM_TAG(SYM, TAG) \
1677 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1678 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1681 #define OTF_TAG_STR(TAG, P) \
1683 (P)[0] = (char) (TAG >> 24); \
1684 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1685 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1686 (P)[3] = (char) (TAG & 0xFF); \
1690 static struct OpenTypeSpec *
1691 macfont_get_open_type_spec (Lisp_Object otf_spec)
1693 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1700 spec->script = XCAR (otf_spec);
1701 if (! NILP (spec->script))
1703 OTF_SYM_TAG (spec->script, spec->script_tag);
1704 val = assq_no_quit (spec->script, Votf_script_alist);
1705 if (CONSP (val) && SYMBOLP (XCDR (val)))
1706 spec->script = XCDR (val);
1708 spec->script = Qnil;
1711 spec->script_tag = 0x44464C54; /* "DFLT" */
1712 otf_spec = XCDR (otf_spec);
1713 spec->langsys_tag = 0;
1714 if (! NILP (otf_spec))
1716 val = XCAR (otf_spec);
1718 OTF_SYM_TAG (val, spec->langsys_tag);
1719 otf_spec = XCDR (otf_spec);
1721 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1722 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1726 val = XCAR (otf_spec);
1729 len = Flength (val);
1731 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1733 : malloc (XINT (len) * sizeof *spec->features[i]));
1734 if (! spec->features[i])
1736 if (i > 0 && spec->features[0])
1737 free (spec->features[0]);
1741 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1743 if (NILP (XCAR (val)))
1749 OTF_SYM_TAG (XCAR (val), tag);
1750 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1753 spec->nfeatures[i] = j;
1758 static CFMutableDictionaryRef
1759 macfont_create_attributes_with_spec (Lisp_Object spec)
1761 Lisp_Object tmp, extra;
1762 CFMutableArrayRef langarray = NULL;
1763 CFCharacterSetRef charset = NULL;
1764 CFStringRef charset_string = NULL;
1765 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1766 Lisp_Object script = Qnil;
1767 Lisp_Object registry;
1768 int cf_charset_idx, i;
1769 struct OpenTypeSpec *otspec = NULL;
1771 enum font_property_index index;
1774 } numeric_traits[] =
1775 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1776 {{-0.4, 50}, /* light */
1777 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1778 {0, 100}, /* normal */
1779 {0.24, 140}, /* (semi-bold + normal) / 2 */
1780 {0.4, 200}, /* bold */
1781 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1782 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1783 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1784 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1785 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1787 registry = AREF (spec, FONT_REGISTRY_INDEX);
1789 || EQ (registry, Qascii_0)
1790 || EQ (registry, Qiso10646_1)
1791 || EQ (registry, Qunicode_bmp))
1792 cf_charset_idx = -1;
1797 cf_charset_idx = macfont_get_charset (registry);
1798 if (cf_charset_idx < 0)
1800 charset = cf_charset_table[cf_charset_idx].cf_charset;
1801 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1802 lang = cf_charset_table[cf_charset_idx].lang;
1805 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1808 CFArrayAppendValue (langarray, lang);
1812 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1813 CONSP (extra); extra = XCDR (extra))
1815 Lisp_Object key, val;
1818 key = XCAR (tmp), val = XCDR (tmp);
1819 if (EQ (key, QClang))
1822 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1827 for (; CONSP (val); val = XCDR (val))
1828 if (SYMBOLP (XCAR (val)))
1831 cfstring_create_with_string_noencode (SYMBOL_NAME
1836 CFArrayAppendValue (langarray, lang);
1840 else if (EQ (key, QCotf))
1842 otspec = macfont_get_open_type_spec (val);
1845 script = otspec->script;
1847 else if (EQ (key, QCscript))
1851 if (! NILP (script) && ! charset)
1853 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1855 if (CONSP (chars) && CONSP (CDR (chars)))
1857 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1858 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1860 if (! string || !cs)
1868 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1869 if (CHARACTERP (XCAR (chars)))
1871 UniChar unichars[2];
1873 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1875 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1877 CFStringAppendCharacters (string, unichars, count);
1878 CFCharacterSetAddCharactersInRange (cs, range);
1881 /* CFCharacterSetCreateWithCharactersInString does not
1882 handle surrogate pairs properly as of Mac OS X 10.5. */
1883 charset_string = string;
1887 attributes = CFDictionaryCreateMutable (NULL, 0,
1888 &kCFTypeDictionaryKeyCallBacks,
1889 &kCFTypeDictionaryValueCallBacks);
1893 tmp = AREF (spec, FONT_FAMILY_INDEX);
1894 if (SYMBOLP (tmp) && ! NILP (tmp))
1896 CFStringRef family = macfont_create_family_with_symbol (tmp);
1900 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1905 traits = CFDictionaryCreateMutable (NULL, 4,
1906 &kCFTypeDictionaryKeyCallBacks,
1907 &kCFTypeDictionaryValueCallBacks);
1911 for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
1913 tmp = AREF (spec, numeric_traits[i].index);
1916 CGPoint *point = numeric_traits[i].points;
1917 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1920 while (point->y < floatval)
1922 if (point == numeric_traits[i].points)
1924 else if (point->y == CGFLOAT_MAX)
1926 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1927 * ((point->x - (point - 1)->x)
1928 / (point->y - (point - 1)->y)));
1931 else if (floatval < -1.0)
1933 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1936 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1940 if (CFDictionaryGetCount (traits))
1941 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1944 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1947 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1950 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1957 CFRelease (attributes);
1962 if (langarray) CFRelease (langarray);
1963 if (charset && cf_charset_idx < 0) CFRelease (charset);
1964 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1965 if (traits) CFRelease (traits);
1968 if (otspec->nfeatures[0] > 0)
1969 free (otspec->features[0]);
1970 if (otspec->nfeatures[1] > 0)
1971 free (otspec->features[1]);
1979 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1980 CFCharacterSetRef charset,
1982 CFArrayRef languages)
1984 Boolean result = true;
1986 if (charset || VECTORP (chars))
1988 CFCharacterSetRef desc_charset =
1989 mac_font_descriptor_copy_attribute (desc,
1990 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1992 if (desc_charset == NULL)
1997 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1998 else /* VECTORP (chars) */
2002 for (j = 0; j < ASIZE (chars); j++)
2003 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2004 && CFCharacterSetIsLongCharacterMember (desc_charset,
2005 XFASTINT (AREF (chars, j))))
2007 if (j == ASIZE (chars))
2010 CFRelease (desc_charset);
2013 if (result && languages)
2014 result = mac_font_descriptor_supports_languages (desc, languages);
2020 macfont_closest_traits_index (CFArrayRef traits_array,
2021 FontSymbolicTraits target)
2023 CFIndex i, result = -1, count = CFArrayGetCount (traits_array);
2024 int min_distance = (1 << 3);
2026 for (i = 0; i < count; i++)
2028 FontSymbolicTraits traits, diff;
2031 traits = ((FontSymbolicTraits) (uintptr_t)
2032 CFArrayGetValueAtIndex (traits_array, i));
2033 diff = (target ^ traits);
2034 /* We prefer synthetic bold of italic to synthetic italic of
2035 bold when both bold and italic are available but bold-italic
2036 is not available. */
2037 if (diff & MAC_FONT_TRAIT_BOLD)
2038 distance |= (1 << 0);
2039 if (diff & MAC_FONT_TRAIT_ITALIC)
2040 distance |= (1 << 1);
2041 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2042 distance |= (1 << 2);
2043 if (distance < min_distance)
2045 min_distance = distance;
2054 macfont_list (struct frame *f, Lisp_Object spec)
2056 Lisp_Object val = Qnil, family, extra;
2058 CFStringRef family_name = NULL;
2059 CFMutableDictionaryRef attributes = NULL, traits;
2060 Lisp_Object chars = Qnil;
2062 FontSymbolicTraits synth_sym_traits = 0;
2063 CFArrayRef families;
2064 CFIndex families_count;
2065 CFCharacterSetRef charset = NULL;
2066 CFArrayRef languages = NULL;
2070 family = AREF (spec, FONT_FAMILY_INDEX);
2071 if (! NILP (family))
2073 family_name = macfont_create_family_with_symbol (family);
2074 if (family_name == NULL)
2078 attributes = macfont_create_attributes_with_spec (spec);
2082 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2084 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2085 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2087 traits = ((CFMutableDictionaryRef)
2088 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2090 n = FONT_SLANT_NUMERIC (spec);
2091 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2093 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2095 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2098 n = FONT_WEIGHT_NUMERIC (spec);
2099 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2101 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2103 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2107 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2109 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2111 if (CFStringHasPrefix (language, CFSTR ("ja"))
2112 || CFStringHasPrefix (language, CFSTR ("ko"))
2113 || CFStringHasPrefix (language, CFSTR ("zh")))
2114 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2117 /* Create array of families. */
2119 families = CFArrayCreate (NULL, (const void **) &family_name,
2120 1, &kCFTypeArrayCallBacks);
2123 CFStringRef pref_family;
2124 CFIndex families_count, pref_family_index = -1;
2126 families = mac_font_create_available_families ();
2127 if (families == NULL)
2130 families_count = CFArrayGetCount (families);
2132 /* Move preferred family to the front if exists. */
2134 mac_font_create_preferred_family_for_attributes (attributes);
2138 CFArrayGetFirstIndexOfValue (families,
2139 CFRangeMake (0, families_count),
2141 CFRelease (pref_family);
2143 if (pref_family_index > 0)
2145 CFMutableArrayRef mutable_families =
2146 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2148 if (mutable_families)
2150 CFArrayAppendValue (mutable_families,
2151 CFArrayGetValueAtIndex (families,
2152 pref_family_index));
2153 CFArrayAppendArray (mutable_families, families,
2154 CFRangeMake (0, pref_family_index));
2155 if (pref_family_index + 1 < families_count)
2156 CFArrayAppendArray (mutable_families, families,
2157 CFRangeMake (pref_family_index + 1,
2159 - (pref_family_index + 1)));
2160 CFRelease (families);
2161 families = mutable_families;
2166 charset = CFDictionaryGetValue (attributes,
2167 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2171 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2175 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2178 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2179 if (CONSP (val) && VECTORP (XCDR (val)))
2187 CFRetain (languages);
2188 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2192 extra = AREF (spec, FONT_EXTRA_INDEX);
2193 families_count = CFArrayGetCount (families);
2194 for (i = 0; i < families_count; i++)
2196 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2197 FontDescriptorRef pat_desc;
2199 CFIndex descs_count;
2200 CFMutableArrayRef filtered_descs, traits_array;
2204 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2206 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2210 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2211 10.7 returns NULL if pat_desc represents the LastResort font.
2212 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2213 trailing "s") for such a font. */
2214 if (CFStringCompare (family_name, CFSTR ("LastResort"), 0)
2215 != kCFCompareEqualTo)
2216 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2220 FontDescriptorRef lr_desc =
2221 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2225 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2226 &kCFTypeArrayCallBacks);
2227 CFRelease (lr_desc);
2232 CFRelease (pat_desc);
2236 descs_count = CFArrayGetCount (descs);
2237 if (descs_count == 0
2238 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2247 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2248 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2249 for (j = 0; j < descs_count; j++)
2251 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2252 CFDictionaryRef dict;
2254 FontSymbolicTraits sym_traits;
2256 dict = mac_font_descriptor_copy_attribute (desc,
2257 MAC_FONT_TRAITS_ATTRIBUTE);
2261 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2264 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2268 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2269 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2270 != (spacing >= FONT_SPACING_MONO)))
2273 /* Don't use a color bitmap font unless its family is
2274 explicitly specified. */
2275 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2279 && !macfont_supports_charset_and_languages_p (desc, charset,
2283 CFArrayAppendValue (filtered_descs, desc);
2284 CFArrayAppendValue (traits_array,
2285 (const void *) (uintptr_t) sym_traits);
2289 descs = filtered_descs;
2290 descs_count = CFArrayGetCount (descs);
2292 for (j = 0; j < descs_count; j++)
2294 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2295 FontSymbolicTraits sym_traits =
2296 ((FontSymbolicTraits) (uintptr_t)
2297 CFArrayGetValueAtIndex (traits_array, j));
2298 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2300 mask_min = ((synth_sym_traits ^ sym_traits)
2301 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2302 if (FONT_SLANT_NUMERIC (spec) < 0)
2303 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2304 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2305 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2307 mask_max = (synth_sym_traits & ~sym_traits);
2308 /* Synthetic bold does not work for bitmap-only fonts on Mac
2310 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2312 CFNumberRef format =
2313 mac_font_descriptor_copy_attribute (desc,
2314 MAC_FONT_FORMAT_ATTRIBUTE);
2318 uint32_t format_val;
2320 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2322 && format_val == MAC_FONT_FORMAT_BITMAP)
2323 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2327 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2329 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2330 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2331 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2332 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2333 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2334 bmask += MAC_FONT_TRAIT_BOLD)
2335 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2336 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2337 imask += MAC_FONT_TRAIT_ITALIC)
2339 FontSymbolicTraits synth = (imask | bmask | mmask);
2342 || j == macfont_closest_traits_index (traits_array,
2343 (sym_traits | synth)))
2345 entity = macfont_descriptor_entity (desc, extra, synth);
2346 if (! NILP (entity))
2347 val = Fcons (entity, val);
2352 CFRelease (traits_array);
2356 CFRelease (families);
2357 val = Fnreverse (val);
2363 FONT_ADD_LOG ("macfont-list", spec, val);
2364 if (charset) CFRelease (charset);
2365 if (languages) CFRelease (languages);
2366 if (attributes) CFRelease (attributes);
2367 if (family_name) CFRelease (family_name);
2375 macfont_match (struct frame * frame, Lisp_Object spec)
2377 Lisp_Object entity = Qnil;
2378 CFMutableDictionaryRef attributes;
2379 FontDescriptorRef pat_desc = NULL, desc = NULL;
2383 attributes = macfont_create_attributes_with_spec (spec);
2386 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2387 CFRelease (attributes);
2391 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2393 CFRelease (pat_desc);
2397 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2403 FONT_ADD_LOG ("macfont-match", spec, entity);
2408 macfont_list_family (struct frame *frame)
2410 Lisp_Object list = Qnil;
2411 CFArrayRef families;
2415 families = mac_font_create_available_families ();
2418 CFIndex i, count = CFArrayGetCount (families);
2420 for (i = 0; i < count; i++)
2421 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2422 CFRelease (families);
2431 macfont_free_entity (Lisp_Object entity)
2433 Lisp_Object val = assq_no_quit (QCfont_entity,
2434 AREF (entity, FONT_EXTRA_INDEX));
2435 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2443 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2445 Lisp_Object val, font_object;
2446 CFStringRef font_name;
2447 struct macfont_info *macfont_info = NULL;
2451 FontSymbolicTraits sym_traits;
2453 int len, i, total_width;
2455 CGFloat ascent, descent, leading;
2457 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2459 || XTYPE (XCDR (val)) != Lisp_Misc
2460 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2462 font_name = XSAVE_POINTER (XCDR (val), 0);
2463 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2465 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2470 macfont = mac_font_create_with_name (font_name, size);
2473 int fontsize = (int) [((NSFont *) macfont) pointSize];
2474 if (fontsize != size) size = fontsize;
2480 font_object = font_make_object (VECSIZE (struct macfont_info), entity, size);
2481 ASET (font_object, FONT_TYPE_INDEX, macfont_driver.type);
2482 len = font_unparse_xlfd (entity, size, name, 256);
2484 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
2485 len = font_unparse_fcname (entity, size, name, 256);
2487 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
2489 ASET (font_object, FONT_FULLNAME_INDEX,
2490 AREF (font_object, FONT_NAME_INDEX));
2491 font = XFONT_OBJECT (font_object);
2492 font->pixel_size = size;
2493 font->driver = &macfont_driver;
2494 font->encoding_charset = font->repertory_charset = -1;
2498 macfont_info = (struct macfont_info *) font;
2499 macfont_info->macfont = macfont;
2500 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2502 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2503 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2504 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2507 macfont_info->screen_font = NULL;
2508 macfont_info->cache = macfont_lookup_cache (font_name);
2509 macfont_retain_cache (macfont_info->cache);
2510 macfont_info->metrics = NULL;
2511 macfont_info->metrics_nrows = 0;
2512 macfont_info->synthetic_italic_p = 0;
2513 macfont_info->synthetic_bold_p = 0;
2514 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2515 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2516 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2517 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2518 macfont_info->synthetic_italic_p = 1;
2519 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2520 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2521 macfont_info->synthetic_bold_p = 1;
2522 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2523 macfont_info->spacing = MACFONT_SPACING_MONO;
2524 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2525 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2526 == FONT_SPACING_SYNTHETIC_MONO))
2527 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2528 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2529 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2532 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2534 macfont_info->antialias =
2535 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2537 macfont_info->color_bitmap_p = 0;
2538 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2539 macfont_info->color_bitmap_p = 1;
2541 glyph = macfont_get_glyph_for_character (font, ' ');
2542 if (glyph != kCGFontIndexInvalid)
2543 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2545 /* dirty workaround */
2546 font->space_width = pixel_size;
2548 total_width = font->space_width;
2549 for (i = 1; i < 95; i++)
2551 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2552 if (glyph == kCGFontIndexInvalid)
2554 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2557 font->average_width = total_width / 95;
2559 font->average_width = font->space_width; /* XXX */
2561 if (!(macfont_info->screen_font
2562 && mac_screen_font_get_metrics (macfont_info->screen_font,
2563 &ascent, &descent, &leading)))
2565 CFStringRef family_name;
2567 ascent = mac_font_get_ascent (macfont);
2568 descent = mac_font_get_descent (macfont);
2569 leading = mac_font_get_leading (macfont);
2570 /* AppKit and WebKit do some adjustment to the heights of
2571 Courier, Helvetica, and Times. */
2572 family_name = mac_font_copy_family_name (macfont);
2575 if ((CFStringCompare (family_name, CFSTR ("Courier"), 0)
2576 == kCFCompareEqualTo)
2577 || (CFStringCompare (family_name, CFSTR ("Helvetica"), 0)
2578 == kCFCompareEqualTo)
2579 || (CFStringCompare (family_name, CFSTR ("Times"), 0)
2580 == kCFCompareEqualTo))
2581 ascent += (ascent + descent) * .15f;
2582 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2587 CFRelease (family_name);
2590 font->ascent = ascent + 0.5f;
2591 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2592 if (CONSP (val) && !NILP (XCDR (val)))
2593 font->descent = descent + 0.5f;
2595 font->descent = descent + leading + 0.5f;
2596 font->height = font->ascent + font->descent;
2598 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2599 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2603 /* Unfortunately Xft doesn't provide a way to get minimum char
2604 width. So, we use space_width instead. */
2605 font->min_width = font->max_width = font->space_width; /* XXX */
2607 font->baseline_offset = 0;
2608 font->relative_compose = 0;
2609 font->default_ascent = 0;
2610 font->vertical_centering = 0;
2616 macfont_close (struct font *font)
2618 struct macfont_info *macfont_info = (struct macfont_info *) font;
2620 if (macfont_info->cache)
2625 CFRelease (macfont_info->macfont);
2626 CGFontRelease (macfont_info->cgfont);
2627 if (macfont_info->screen_font)
2628 CFRelease (macfont_info->screen_font);
2629 macfont_release_cache (macfont_info->cache);
2630 for (i = 0; i < macfont_info->metrics_nrows; i++)
2631 if (macfont_info->metrics[i])
2632 xfree (macfont_info->metrics[i]);
2633 if (macfont_info->metrics)
2634 xfree (macfont_info->metrics);
2635 macfont_info->cache = NULL;
2641 macfont_has_char (Lisp_Object font, int c)
2644 CFCharacterSetRef charset;
2647 if (FONT_ENTITY_P (font))
2652 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2654 name = XSAVE_POINTER (val, 0);
2655 charset = macfont_get_cf_charset_for_name (name);
2658 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2660 result = CFCharacterSetIsLongCharacterMember (charset, c);
2667 macfont_encode_char (struct font *font, int c)
2669 struct macfont_info *macfont_info = (struct macfont_info *) font;
2673 glyph = macfont_get_glyph_for_character (font, c);
2676 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2680 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2681 struct font_metrics *metrics)
2686 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2687 for (i = 1; i < nglyphs; i++)
2689 struct font_metrics m;
2690 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2695 if (width + m.lbearing < metrics->lbearing)
2696 metrics->lbearing = width + m.lbearing;
2697 if (width + m.rbearing > metrics->rbearing)
2698 metrics->rbearing = width + m.rbearing;
2699 if (m.ascent > metrics->ascent)
2700 metrics->ascent = m.ascent;
2701 if (m.descent > metrics->descent)
2702 metrics->descent = m.descent;
2709 metrics->width = width;
2715 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2716 bool with_background)
2718 struct frame * f = s->f;
2719 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2720 FontRef macfont = macfont_info->macfont;
2721 CGContextRef context;
2722 BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
2723 int end = isComposite ? s->cmp_to : s->nchars;
2724 int len = end - s->cmp_from;
2725 struct face *face = s->face;
2730 context = [[NSGraphicsContext currentContext] graphicsPort];
2731 CGContextSaveGState (context);
2734 if (s->num_clips > 0)
2738 for (i = 0; i < s->num_clips; i++)
2739 clips[i] = mac_rect_make (f, s->clip[i].left, s->clip[i].top,
2740 s->clip[i].right - s->clip[i].left,
2741 s->clip[i].bottom - s->clip[i].top);
2742 CGContextClipToRects (context, clips, s->num_clips);
2746 if (with_background)
2748 if (s->hl == DRAW_MOUSE_FACE)
2750 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2752 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2755 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2756 CGContextFillRect (context,
2758 s->width, FONT_HEIGHT (s->font)));
2761 if (macfont_info->cgfont)
2763 CGGlyph *glyphs = alloca (sizeof (CGGlyph) * len);
2764 CGPoint *positions = alloca (sizeof (CGPoint) * len);
2765 CGFloat total_width = 0;
2766 CGFloat font_size = mac_font_get_size (macfont);
2767 CGAffineTransform atfm;
2768 CGFloat advance_delta = 0;
2769 int y_draw = -s->ybase;
2770 int no_antialias_p =
2771 (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2772 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2773 && font_size <= macfont_antialias_threshold));
2775 for (i = 0; i < len; i++)
2779 glyphs[i] = *(s->char2b + s->cmp_from + i);
2780 width = (s->padding_p ? 1
2781 : macfont_glyph_extents (s->font, glyphs[i],
2782 NULL, &advance_delta,
2784 positions[i].x = total_width + advance_delta;
2786 total_width += width;
2789 CGContextScaleCTM (context, 1, -1);
2790 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2791 if (macfont_info->synthetic_italic_p)
2792 atfm = synthetic_italic_atfm;
2794 atfm = CGAffineTransformIdentity;
2795 if (macfont_info->synthetic_bold_p)
2797 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2798 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2799 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2802 CGContextSetShouldAntialias (context, false);
2804 CGContextSetTextMatrix (context, atfm);
2805 CGContextSetTextPosition (context, x, y_draw);
2807 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2808 if (macfont_info->color_bitmap_p
2809 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2810 && CTFontDrawGlyphs != NULL
2816 CTFontDrawGlyphs (macfont, glyphs, positions, len, context);
2820 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2822 CGContextSetFont (context, macfont_info->cgfont);
2823 CGContextSetFontSize (context, font_size);
2824 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2828 CGContextRestoreGState (context);
2836 macfont_shape (Lisp_Object lgstring)
2839 struct macfont_info *macfont_info;
2841 ptrdiff_t glyph_len, len, i, j;
2844 CFIndex *nonbmp_indices;
2847 struct mac_glyph_layout *glyph_layouts;
2849 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2850 macfont_info = (struct macfont_info *) font;
2851 macfont = macfont_info->macfont;
2853 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2855 for (i = 0; i < glyph_len; i++)
2857 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2861 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2867 if (INT_MAX / 2 < len)
2868 memory_full (SIZE_MAX);
2870 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2871 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2872 for (i = j = 0; i < len; i++)
2874 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2876 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2878 nonbmp_indices[j] = i + j;
2882 nonbmp_indices[j] = len + j; /* sentinel */
2886 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2890 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2891 if (macfont_info->screen_font)
2892 used = mac_screen_font_shape (macfont_info->screen_font, string,
2893 glyph_layouts, glyph_len);
2895 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2906 for (i = 0; i < used; i++)
2908 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2909 struct mac_glyph_layout *gl = glyph_layouts + i;
2911 struct font_metrics metrics;
2912 int xoff, yoff, wadjust;
2916 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2917 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2920 from = gl->comp_range.location;
2921 /* Convert UTF-16 index to UTF-32. */
2923 while (nonbmp_indices[j] < from)
2926 LGLYPH_SET_FROM (lglyph, from);
2928 to = gl->comp_range.location + gl->comp_range.length;
2929 /* Convert UTF-16 index to UTF-32. */
2930 while (nonbmp_indices[j] < to)
2933 LGLYPH_SET_TO (lglyph, to - 1);
2935 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2936 the composition is trivial. */
2940 if (unichars[gl->string_index] >= 0xD800
2941 && unichars[gl->string_index] < 0xDC00)
2942 c = (((unichars[gl->string_index] - 0xD800) << 10)
2943 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2945 c = unichars[gl->string_index];
2946 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2948 LGLYPH_SET_CHAR (lglyph, c);
2952 unsigned long cc = gl->glyph_id;
2953 LGLYPH_SET_CODE (lglyph, cc);
2956 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2957 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2958 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2959 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2960 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2961 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2963 xoff = lround (gl->advance_delta);
2964 yoff = lround (- gl->baseline_delta);
2965 wadjust = lround (gl->advance);
2966 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2970 vec = Fmake_vector (make_number (3), Qnil);
2971 ASET (vec, 0, make_number (xoff));
2972 ASET (vec, 1, make_number (yoff));
2973 ASET (vec, 2, make_number (wadjust));
2974 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2980 return make_number (used);
2983 /* Structures for the UVS subtable (format 14) in the cmap table. */
2984 typedef UInt8 UINT24[3];
2986 #pragma pack(push, 1)
2987 struct variation_selector_record
2989 UINT24 var_selector;
2990 UInt32 default_uvs_offset, non_default_uvs_offset;
2995 UInt32 length, num_var_selector_records;
2996 struct variation_selector_record variation_selector_records[1];
2998 #define SIZEOF_UVS_TABLE_HEADER \
2999 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
3001 struct unicode_value_range
3003 UINT24 start_unicode_value;
3004 UInt8 additional_count;
3006 struct default_uvs_table {
3007 UInt32 num_unicode_value_ranges;
3008 struct unicode_value_range unicode_value_ranges[1];
3010 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3011 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3015 UINT24 unicode_value;
3018 struct non_default_uvs_table
3020 UInt32 num_uvs_mappings;
3021 struct uvs_mapping uvs_mappings[1];
3023 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3024 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3027 /* Read big endian values. The argument LVAL must be an lvalue. */
3028 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3029 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3030 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3031 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3032 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3033 /* Succeeding one byte should also be accessible. */
3034 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3035 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3037 /* Return UVS subtable for the specified FONT. If the subtable is not
3038 found or ill-formatted, then return NULL. */
3041 mac_font_copy_uvs_table (FontRef font)
3043 CFDataRef cmap_table, uvs_table = NULL;
3045 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3048 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3049 struct uvs_table *uvs;
3050 struct variation_selector_record *records;
3051 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3054 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3058 cmap_len = CFDataGetLength (cmap_table);
3059 if (sizeof_sfntCMapHeader > cmap_len)
3062 ntables = BUINT16_VALUE (cmap->numTables);
3063 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3064 / sizeof_sfntCMapEncoding))
3067 for (i = 0; i < ntables; i++)
3068 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3069 == kFontUnicodePlatform)
3070 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3071 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3073 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3077 || uvs_offset > cmap_len
3078 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3081 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3082 uvs_len = BUINT32_VALUE (uvs->length);
3083 if (uvs_len > cmap_len - uvs_offset
3084 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3087 if (BUINT16_VALUE (uvs->format) != 14)
3090 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3091 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3092 / sizeof (struct variation_selector_record)))
3095 records = uvs->variation_selector_records;
3096 for (i = 0; i < nrecords; i++)
3098 UInt32 default_uvs_offset, non_default_uvs_offset;
3100 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3101 if (default_uvs_offset)
3103 struct default_uvs_table *default_uvs;
3106 if (default_uvs_offset > uvs_len
3107 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3108 > uvs_len - default_uvs_offset))
3111 default_uvs = ((struct default_uvs_table *)
3112 ((UInt8 *) uvs + default_uvs_offset));
3113 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3114 if (nranges > ((uvs_len - default_uvs_offset
3115 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3116 / sizeof (struct unicode_value_range)))
3118 /* Now 2 * nranges can't overflow, so we can safely use
3119 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3120 mac_font_get_glyphs_for_variants. */
3123 non_default_uvs_offset =
3124 BUINT32_VALUE (records[i].non_default_uvs_offset);
3125 if (non_default_uvs_offset)
3127 struct non_default_uvs_table *non_default_uvs;
3130 if (non_default_uvs_offset > uvs_len
3131 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3132 > uvs_len - non_default_uvs_offset))
3135 non_default_uvs = ((struct non_default_uvs_table *)
3136 ((UInt8 *) uvs + non_default_uvs_offset));
3137 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3138 if (nmappings > ((uvs_len - non_default_uvs_offset
3139 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3140 / sizeof (struct uvs_mapping)))
3142 /* Now 2 * nmappings can't overflow, so we can safely
3143 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3144 in mac_font_get_glyphs_for_variants. */
3148 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3151 CFRelease (cmap_table);
3157 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3158 sequence consisting of the given base character C and each
3159 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3160 result (explained below) into the corresponding GLYPHS[i]. If the
3161 entry is found in the Default UVS Table, then the result is 0. If
3162 the entry is found in the Non-Default UVS Table, then the result is
3163 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3164 elements in SELECTORS must be sorted in strictly increasing
3168 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3169 const UTF32Char selectors[], CGGlyph glyphs[],
3172 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3173 struct variation_selector_record *records = uvs->variation_selector_records;
3175 UInt32 ir, nrecords;
3176 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3177 dispatch_queue_t queue =
3178 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3179 dispatch_group_t group = dispatch_group_create ();
3182 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3185 while (i < count && ir < nrecords)
3187 UInt32 default_uvs_offset, non_default_uvs_offset;
3189 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3191 glyphs[i++] = kCGFontIndexInvalid;
3194 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3200 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3201 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3202 non_default_uvs_offset =
3203 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3204 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3205 dispatch_group_async (group, queue, ^{
3207 glyphs[i] = kCGFontIndexInvalid;
3209 if (default_uvs_offset)
3211 struct default_uvs_table *default_uvs =
3212 (struct default_uvs_table *) ((UInt8 *) uvs
3213 + default_uvs_offset);
3214 struct unicode_value_range *ranges =
3215 default_uvs->unicode_value_ranges;
3219 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3222 UInt32 mid = (lo + hi) / 2;
3224 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3230 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3231 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3235 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3237 struct non_default_uvs_table *non_default_uvs =
3238 (struct non_default_uvs_table *) ((UInt8 *) uvs
3239 + non_default_uvs_offset);
3240 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3244 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3247 UInt32 mid = (lo + hi) / 2;
3249 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3255 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3256 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3258 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3265 glyphs[i++] = kCGFontIndexInvalid;
3266 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3267 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3268 dispatch_release (group);
3273 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3275 CFDataRef uvs_table;
3276 CharacterCollection uvs_collection;
3280 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3284 UTF32Char selectors[256];
3285 CGGlyph glyphs[256];
3287 for (i = 0; i < 16; i++)
3288 selectors[i] = 0xFE00 + i;
3289 for (; i < 256; i++)
3290 selectors[i] = 0xE0100 + (i - 16);
3291 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3292 for (i = 0; i < 256; i++)
3294 CGGlyph glyph = glyphs[i];
3296 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3297 && glyph != kCGFontIndexInvalid)
3298 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3299 if (glyph == kCGFontIndexInvalid)
3303 variations[i] = (glyph ? glyph
3304 : macfont_get_glyph_for_character (font, c));
3314 static const char *const macfont_booleans[] = {
3320 static const char *const macfont_non_booleans[] = {
3328 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3330 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3334 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3335 CFArrayRef languages)
3337 Boolean result = true;
3338 CFArrayRef desc_languages =
3339 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3341 if (desc_languages == NULL)
3345 CFIndex desc_languages_count, i, languages_count;
3347 desc_languages_count = CFArrayGetCount (desc_languages);
3348 languages_count = CFArrayGetCount (languages);
3349 for (i = 0; i < languages_count; i++)
3350 if (!CFArrayContainsValue (desc_languages,
3351 CFRangeMake (0, desc_languages_count),
3352 CFArrayGetValueAtIndex (languages, i)))
3357 CFRelease (desc_languages);
3364 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3366 CFStringRef result = NULL;
3367 CFStringRef charset_string =
3368 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3370 if (charset_string && CFStringGetLength (charset_string) > 0)
3372 CFStringRef keys[] = {
3373 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3374 kCTLanguageAttributeName
3376 CFSTR ("NSLanguage")
3379 CFTypeRef values[] = {NULL};
3380 CFIndex num_values = 0;
3381 CFArrayRef languages
3382 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3384 if (languages && CFArrayGetCount (languages) > 0)
3386 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3387 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3390 CFCharacterSetRef charset =
3391 CFDictionaryGetValue (attributes,
3392 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3394 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3399 CFAttributedStringRef attr_string = NULL;
3400 CTLineRef ctline = NULL;
3401 CFDictionaryRef attrs
3402 = CFDictionaryCreate (NULL, (const void **) keys,
3403 (const void **) values, num_values,
3404 &kCFTypeDictionaryKeyCallBacks,
3405 &kCFTypeDictionaryValueCallBacks);
3409 attr_string = CFAttributedStringCreate (NULL, charset_string,
3415 ctline = CTLineCreateWithAttributedString (attr_string);
3416 CFRelease (attr_string);
3420 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3421 CFIndex i, nruns = CFArrayGetCount (runs);
3424 for (i = 0; i < nruns; i++)
3426 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3427 CFDictionaryRef attributes = CTRunGetAttributes (run);
3428 CTFontRef font_in_run;
3430 if (attributes == NULL)
3433 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3434 if (font_in_run == NULL)
3438 else if (!mac_ctfont_equal_in_postscript_name (font,
3442 if (nruns > 0 && i == nruns)
3443 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3452 static inline double
3453 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3455 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3459 static inline CGRect
3460 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3462 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3467 mac_ctfont_create_available_families (void)
3469 CFMutableArrayRef families = NULL;
3471 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3472 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3473 if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3476 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3480 CFIndex i, count = CFArrayGetCount (orig_families);
3482 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3484 for (i = 0; i < count; i++)
3486 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3488 if (!CFStringHasPrefix (family, CFSTR ("."))
3489 && (CTFontManagerCompareFontFamilyNames (family,
3490 CFSTR ("LastResort"),
3492 != kCFCompareEqualTo))
3493 CFArrayAppendValue (families, family);
3495 CFRelease (orig_families);
3498 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3499 else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3501 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3502 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3504 CTFontCollectionRef collection;
3505 CFArrayRef descs = NULL;
3507 collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3510 descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3511 CFRelease (collection);
3515 CFIndex i, count = CFArrayGetCount (descs);
3517 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3519 for (i = 0; i < count; i++)
3521 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3523 mac_font_descriptor_copy_attribute (desc,
3524 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3528 CFIndex p, limit = CFArrayGetCount (families);
3530 p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3531 (const void *) name,
3532 mac_font_family_compare, NULL);
3534 CFArrayAppendValue (families, name);
3535 else if (mac_font_family_compare
3536 (CFArrayGetValueAtIndex (families, p),
3537 name, NULL) != kCFCompareEqualTo)
3538 CFArrayInsertValueAtIndex (families, p, name);
3551 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3554 CFStringRef name1, name2;
3560 name1 = CTFontCopyPostScriptName (font1);
3563 name2 = CTFontCopyPostScriptName (font2);
3566 result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo);
3576 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3579 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3580 CFTypeRef values[] = {NULL, NULL};
3581 CFDictionaryRef attributes = NULL;
3582 CFAttributedStringRef attr_string = NULL;
3583 CTLineRef ctline = NULL;
3584 float float_zero = 0.0f;
3586 values[0] = macfont;
3587 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3590 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3591 (const void **) values,
3592 sizeof (keys) / sizeof (keys[0]),
3593 &kCFTypeDictionaryKeyCallBacks,
3594 &kCFTypeDictionaryValueCallBacks);
3595 CFRelease (values[1]);
3599 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3600 CFRelease (attributes);
3604 ctline = CTLineCreateWithAttributedString (attr_string);
3605 CFRelease (attr_string);
3609 /* Abandon if ctline contains some fonts other than the
3611 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3612 CFIndex i, nruns = CFArrayGetCount (runs);
3614 for (i = 0; i < nruns; i++)
3616 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3617 CFDictionaryRef attributes = CTRunGetAttributes (run);
3618 CTFontRef font_in_run;
3620 if (attributes == NULL)
3623 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3624 if (font_in_run == NULL)
3626 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3640 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3641 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3643 CFIndex used, result = 0;
3644 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3649 used = CTLineGetGlyphCount (ctline);
3650 if (used <= glyph_len)
3652 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3653 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3654 CGFloat total_advance = 0;
3655 CFIndex total_glyph_count = 0;
3657 for (k = 0; k < ctrun_count; k++)
3659 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3660 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3661 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3662 CFRange string_range, comp_range, range;
3663 CFIndex *permutation;
3665 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3666 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3670 #define RIGHT_TO_LEFT_P permutation
3672 /* Now the `comp_range' member of struct mac_glyph_layout is
3673 temporarily used as a work area such that:
3674 glbuf[i].comp_range.location =
3675 min {compRange[i + 1].location, ...,
3676 compRange[glyph_count - 1].location,
3677 maxRange (stringRangeForCTRun)}
3678 glbuf[i].comp_range.length = maxRange (compRange[i])
3679 where compRange[i] is the range of composed characters
3680 containing i-th glyph. */
3681 string_range = CTRunGetStringRange (ctrun);
3682 min_location = string_range.location + string_range.length;
3683 for (i = 0; i < glyph_count; i++)
3685 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3686 CFIndex glyph_index;
3689 if (!RIGHT_TO_LEFT_P)
3690 glyph_index = glyph_count - i - 1;
3693 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3696 CFStringGetRangeOfComposedCharactersAtIndex (string,
3698 gl->comp_range.location = min_location;
3699 gl->comp_range.length = rng.location + rng.length;
3700 if (rng.location < min_location)
3701 min_location = rng.location;
3704 /* Fill the `comp_range' member of struct mac_glyph_layout,
3705 and setup a permutation for right-to-left text. */
3706 comp_range = CFRangeMake (string_range.location, 0);
3707 range = CFRangeMake (0, 0);
3710 struct mac_glyph_layout *gl =
3711 glbuf + range.location + range.length;
3713 if (gl->comp_range.length
3714 > comp_range.location + comp_range.length)
3715 comp_range.length = gl->comp_range.length - comp_range.location;
3716 min_location = gl->comp_range.location;
3719 if (min_location >= comp_range.location + comp_range.length)
3721 comp_range.length = min_location - comp_range.location;
3722 for (i = 0; i < range.length; i++)
3724 glbuf[range.location + i].comp_range = comp_range;
3725 if (RIGHT_TO_LEFT_P)
3726 permutation[range.location + i] =
3727 range.location + range.length - i - 1;
3730 comp_range = CFRangeMake (min_location, 0);
3731 range.location += range.length;
3733 if (range.location == glyph_count)
3738 /* Then fill the remaining members. */
3739 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3742 struct mac_glyph_layout *gl;
3745 if (!RIGHT_TO_LEFT_P)
3746 gl = glbuf + range.location;
3751 src = glyph_count - 1 - range.location;
3752 dest = permutation[src];
3756 CFIndex tmp = gl->string_index;
3758 gl->string_index = glbuf[src].string_index;
3759 glbuf[src].string_index = tmp;
3762 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3764 CTRunGetPositions (ctrun, range, &position);
3765 gl->advance_delta = position.x - total_advance;
3766 gl->baseline_delta = position.y;
3767 gl->advance = (gl->advance_delta
3768 + CTRunGetTypographicBounds (ctrun, range,
3770 total_advance += gl->advance;
3773 if (RIGHT_TO_LEFT_P)
3774 xfree (permutation);
3776 #undef RIGHT_TO_LEFT_P
3778 total_glyph_count += glyph_count;
3788 /* The function below seems to cause a memory leak for the CFString
3789 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3790 10.6.3. For now, we use the NSGlyphInfo version instead. */
3791 #if USE_CT_GLYPH_INFO
3793 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3796 CGGlyph result = kCGFontIndexInvalid;
3797 UniChar characters[] = {0xfffd};
3799 CFAttributedStringRef attr_string = NULL;
3800 CTLineRef ctline = NULL;
3802 string = CFStringCreateWithCharacters (NULL, characters,
3804 / sizeof (characters[0]));
3807 CTGlyphInfoRef glyph_info =
3808 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3809 CFDictionaryRef attributes = NULL;
3813 CFStringRef keys[] = {kCTFontAttributeName,
3814 kCTGlyphInfoAttributeName};
3815 CFTypeRef values[] = {font, glyph_info};
3817 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3818 (const void **) values,
3819 sizeof (keys) / sizeof (keys[0]),
3820 &kCFTypeDictionaryKeyCallBacks,
3821 &kCFTypeDictionaryValueCallBacks);
3822 CFRelease (glyph_info);
3826 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3827 CFRelease (attributes);
3833 ctline = CTLineCreateWithAttributedString (attr_string);
3834 CFRelease (attr_string);
3838 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3840 if (CFArrayGetCount (runs) > 0)
3842 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3843 CFDictionaryRef attributes = CTRunGetAttributes (run);
3847 CTFontRef font_in_run =
3848 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3851 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3853 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3854 if (result >= CTFontGetGlyphCount (font))
3855 result = kCGFontIndexInvalid;
3866 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3868 mac_font_family_group (CFStringRef family)
3870 if (CFStringHasPrefix (family, CFSTR ("#")))
3876 range = CFStringFind (family, CFSTR ("Apple"),
3877 kCFCompareCaseInsensitive | kCFCompareAnchored);
3878 if (range.location != kCFNotFound)
3885 static CFComparisonResult
3886 mac_font_family_compare (const void *val1, const void *val2, void *context)
3888 CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3891 group1 = mac_font_family_group (family1);
3892 group2 = mac_font_family_group (family2);
3893 if (group1 < group2)
3894 return kCFCompareLessThan;
3895 if (group1 > group2)
3896 return kCFCompareGreaterThan;
3897 return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3899 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3902 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3904 CFArrayRef result = NULL;
3906 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3907 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3908 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3911 CTFontRef user_font =
3912 CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3916 CFArrayRef languages =
3917 CFArrayCreate (NULL, (const void **) &language, 1,
3918 &kCFTypeArrayCallBacks);
3922 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3924 CFRelease (languages);
3926 CFRelease (user_font);
3929 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3930 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3932 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3933 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3937 for (i = 0; macfont_language_default_font_names[i].language; i++)
3939 if (CFStringCompare (macfont_language_default_font_names[i].language,
3940 language, 0) == kCFCompareEqualTo)
3942 CFMutableArrayRef descriptors =
3943 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3950 macfont_language_default_font_names[i].font_names[j];
3953 CFDictionaryRef attributes =
3954 CFDictionaryCreate (NULL,
3956 &MAC_FONT_NAME_ATTRIBUTE),
3958 &macfont_language_default_font_names[i].font_names[j]),
3959 1, &kCFTypeDictionaryKeyCallBacks,
3960 &kCFTypeDictionaryValueCallBacks);
3964 FontDescriptorRef pat_desc =
3965 mac_font_descriptor_create_with_attributes (attributes);
3969 FontDescriptorRef descriptor =
3970 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3974 CFArrayAppendValue (descriptors, descriptor);
3975 CFRelease (descriptor);
3977 CFRelease (pat_desc);
3979 CFRelease (attributes);
3982 result = descriptors;
3994 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3995 CFArrayRef languages)
3997 CFStringRef result = NULL;
3998 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3999 CFArrayRef descriptors =
4000 mac_font_copy_default_descriptors_for_language (language);
4004 CFIndex i, count = CFArrayGetCount (descriptors);
4006 for (i = 0; i < count; i++)
4008 FontDescriptorRef descriptor =
4009 CFArrayGetValueAtIndex (descriptors, i);
4011 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4014 CFStringRef family =
4015 mac_font_descriptor_copy_attribute (descriptor,
4016 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
4019 if (!CFStringHasPrefix (family, CFSTR ("."))
4020 && (CFStringCompare (family, CFSTR ("LastResort"), 0)
4021 != kCFCompareEqualTo))
4031 CFRelease (descriptors);
4038 macfont_get_nsctfont (struct font *font)
4040 struct macfont_info *macfont_info = (struct macfont_info *) font;
4041 FontRef macfont = macfont_info->macfont;
4043 return (void *) macfont;
4047 mac_register_font_driver (struct frame *f)
4049 register_font_driver (&macfont_driver, f);
4052 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4056 syms_of_macfont (void)
4058 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4059 static struct font_driver mac_font_driver;
4061 DEFSYM (Qmac_ct, "mac-ct");
4062 macfont_driver.type = Qmac_ct;
4063 register_font_driver (&macfont_driver, NULL);
4065 DEFSYM (QCdestination, ":destination");
4066 DEFSYM (QCminspace, ":minspace");