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 Boolean macfont_closest_traits_index_p (CFArrayRef, FontSymbolicTraits,
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:ARRAYELTS (characters)];
241 NSGlyphInfo *glyphInfo =
242 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
243 collection:collection
245 NSDictionary *attributes =
246 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
247 glyphInfo,NSGlyphInfoAttributeName,nil];
248 NSTextStorage *textStorage =
249 [[NSTextStorage alloc] initWithString:string
250 attributes:attributes];
251 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
252 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
253 NSFont *fontInTextStorage;
255 [layoutManager addTextContainer:textContainer];
256 [textContainer release];
257 [textStorage addLayoutManager:layoutManager];
258 [layoutManager release];
261 (void) [layoutManager glyphRangeForTextContainer:textContainer];
263 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
264 effectiveRange:NULL];
265 if (fontInTextStorage == nsFont
266 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
268 NSGlyph glyph = [layoutManager glyphAtIndex:0];
270 if (glyph < [nsFont numberOfGlyphs])
274 [textStorage release];
282 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
284 NSFont *result, *font;
286 font = [NSFont fontWithName:((NSString *) name) size:size];
287 result = [font screenFont];
289 return (ScreenFontRef)[result retain];
294 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
295 CGFloat *descent, CGFloat *leading)
297 NSFont *nsFont = [(NSFont *)font printerFont];
298 NSTextStorage *textStorage;
299 NSLayoutManager *layoutManager;
300 NSTextContainer *textContainer;
302 NSPoint spaceLocation;
305 textStorage = [[NSTextStorage alloc] initWithString:@" "];
306 layoutManager = [[NSLayoutManager alloc] init];
307 textContainer = [[NSTextContainer alloc] init];
309 [textStorage setFont:nsFont];
310 [textContainer setLineFragmentPadding:0];
311 [layoutManager setUsesScreenFonts:YES];
313 [layoutManager addTextContainer:textContainer];
314 [textContainer release];
315 [textStorage addLayoutManager:layoutManager];
316 [layoutManager release];
318 if (!(textStorage && layoutManager && textContainer))
320 [textStorage release];
325 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
326 effectiveRange:NULL];
327 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
328 [textStorage release];
330 *ascent = spaceLocation.y;
331 *descent = NSHeight (usedRect) - spaceLocation.y;
333 descender = [nsFont descender];
334 if (- descender < *descent)
336 *leading = *descent + descender;
337 *descent = - descender;
344 mac_font_shape_1 (NSFont *font, NSString *string,
345 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
350 NSTextStorage *textStorage;
351 NSLayoutManager *layoutManager;
352 NSTextContainer *textContainer;
353 NSUInteger stringLength;
354 NSPoint spaceLocation;
355 NSUInteger used, numberOfGlyphs;
357 textStorage = [[NSTextStorage alloc] initWithString:string];
358 layoutManager = [[NSLayoutManager alloc] init];
359 textContainer = [[NSTextContainer alloc] init];
361 /* Append a trailing space to measure baseline position. */
362 [textStorage appendAttributedString:([[[NSAttributedString alloc]
363 initWithString:@" "] autorelease])];
364 [textStorage setFont:font];
365 [textContainer setLineFragmentPadding:0];
366 [layoutManager setUsesScreenFonts:screen_font_p];
368 [layoutManager addTextContainer:textContainer];
369 [textContainer release];
370 [textStorage addLayoutManager:layoutManager];
371 [layoutManager release];
373 if (!(textStorage && layoutManager && textContainer))
375 [textStorage release];
380 stringLength = [string length];
383 (void) [layoutManager glyphRangeForTextContainer:textContainer];
385 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
387 /* Remove the appended trailing space because otherwise it may
388 generate a wrong result for a right-to-left text. */
389 [textStorage beginEditing];
390 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
391 [textStorage endEditing];
392 (void) [layoutManager glyphRangeForTextContainer:textContainer];
395 while (i < stringLength)
398 NSFont *fontInTextStorage =
399 [textStorage attribute:NSFontAttributeName atIndex:i
400 longestEffectiveRange:&range
401 inRange:(NSMakeRange (0, stringLength))];
403 if (!(fontInTextStorage == font
404 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
406 i = NSMaxRange (range);
408 if (i < stringLength)
409 /* Make the test `used <= glyph_len' below fail if textStorage
410 contained some fonts other than the specified one. */
411 used = glyph_len + 1;
414 NSRange range = NSMakeRange (0, stringLength);
416 range = [layoutManager glyphRangeForCharacterRange:range
417 actualCharacterRange:NULL];
418 numberOfGlyphs = NSMaxRange (range);
419 used = numberOfGlyphs;
420 for (i = 0; i < numberOfGlyphs; i++)
421 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
425 if (0 < used && used <= glyph_len)
427 NSUInteger glyphIndex, prevGlyphIndex;
428 unsigned char bidiLevel;
429 NSUInteger *permutation;
430 NSRange compRange, range;
431 CGFloat totalAdvance;
434 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
437 /* For now we assume the direction is not changed within the
439 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
440 glyphs:NULL characterIndexes:NULL
441 glyphInscriptions:NULL elasticBits:NULL
442 bidiLevels:&bidiLevel];
444 permutation = xmalloc (sizeof (NSUInteger) * used);
448 #define RIGHT_TO_LEFT_P permutation
450 /* Fill the `comp_range' member of struct mac_glyph_layout, and
451 setup a permutation for right-to-left text. */
452 compRange = NSMakeRange (0, 0);
453 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
456 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
457 NSUInteger characterIndex =
458 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
460 gl->string_index = characterIndex;
462 if (characterIndex >= NSMaxRange (compRange))
464 compRange.location = NSMaxRange (compRange);
467 NSRange characterRange =
469 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
472 NSMaxRange (characterRange) - compRange.location;
473 [layoutManager glyphRangeForCharacterRange:compRange
474 actualCharacterRange:&characterRange];
475 characterIndex = NSMaxRange (characterRange) - 1;
477 while (characterIndex >= NSMaxRange (compRange));
480 for (i = 0; i < range.length; i++)
481 permutation[range.location + i] = NSMaxRange (range) - i - 1;
483 range = NSMakeRange (NSMaxRange (range), 0);
486 gl->comp_range.location = compRange.location;
487 gl->comp_range.length = compRange.length;
489 while (++glyphIndex < numberOfGlyphs)
490 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
494 for (i = 0; i < range.length; i++)
495 permutation[range.location + i] = NSMaxRange (range) - i - 1;
497 /* Then fill the remaining members. */
498 glyphIndex = prevGlyphIndex = 0;
499 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
502 if (!RIGHT_TO_LEFT_P)
509 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
510 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
511 inTextContainer:textContainer rectCount:&nrects];
513 totalAdvance = NSMaxX (glyphRects[0]);
516 for (i = 0; i < used; i++)
518 struct mac_glyph_layout *gl;
520 NSUInteger nextGlyphIndex;
525 if (!RIGHT_TO_LEFT_P)
526 gl = glyph_layouts + i;
529 NSUInteger dest = permutation[i];
531 gl = glyph_layouts + dest;
534 CFIndex tmp = gl->string_index;
536 gl->string_index = glyph_layouts[i].string_index;
537 glyph_layouts[i].string_index = tmp;
540 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
542 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
543 gl->baseline_delta = spaceLocation.y - location.y;
545 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
548 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
551 if (!RIGHT_TO_LEFT_P)
555 if (prevGlyphIndex == 0)
556 glyphRange = NSMakeRange (0, nextGlyphIndex);
558 glyphRange = NSMakeRange (glyphIndex,
559 nextGlyphIndex - glyphIndex);
562 rectArrayForGlyphRange:glyphRange
563 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
564 inTextContainer:textContainer rectCount:&nrects];
565 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
566 gl->advance_delta = location.x - totalAdvance;
567 gl->advance = maxX - totalAdvance;
574 if (nextGlyphIndex == numberOfGlyphs)
575 glyphRange = NSMakeRange (prevGlyphIndex,
576 numberOfGlyphs - prevGlyphIndex);
578 glyphRange = NSMakeRange (prevGlyphIndex,
579 glyphIndex + 1 - prevGlyphIndex);
582 rectArrayForGlyphRange:glyphRange
583 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
584 inTextContainer:textContainer rectCount:&nrects];
585 minX = min (NSMinX (glyphRects[0]), totalAdvance);
586 gl->advance = totalAdvance - minX;
588 gl->advance_delta = location.x - totalAdvance;
591 prevGlyphIndex = glyphIndex + 1;
592 glyphIndex = nextGlyphIndex;
598 #undef RIGHT_TO_LEFT_P
602 [textStorage release];
608 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
609 struct mac_glyph_layout *glyph_layouts,
612 return mac_font_shape_1 ([(NSFont *)font printerFont],
614 glyph_layouts, glyph_len, YES);
618 get_cgcolor(unsigned long idx, struct frame *f)
620 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
622 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
623 NSInteger noc = [nsColor numberOfComponents];
624 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
627 [nsColor getComponents: components];
628 cgColor = CGColorCreate (colorSpace, components);
633 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
635 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
636 CGContextSetFillColorWithColor (context, refcol_) ; \
637 CGColorRelease (refcol_); \
639 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
641 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
642 CGContextSetFillColorWithColor (context, refcol_); \
643 CGColorRelease (refcol_); \
645 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
647 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
648 CGContextSetStrokeColorWithColor (context, refcol_); \
649 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 X 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 < ARRAYELTS (numeric_traits); 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 (CFEqual (key, CFSTR ("LastResort")))
1257 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1260 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1262 if (cache->cf_charset == NULL)
1263 cache->cf_charset = mac_font_copy_character_set (macfont);
1264 CFDictionaryAddValue (macfont_cache_dictionary, key,
1265 (const void *) cache);
1266 CFRelease (macfont);
1273 static struct macfont_cache *
1274 macfont_retain_cache (struct macfont_cache *cache)
1276 cache->reference_count++;
1282 macfont_release_cache (struct macfont_cache *cache)
1284 if (--cache->reference_count == 0)
1288 for (i = 0; i < cache->glyph.nrows; i++)
1289 xfree (cache->glyph.matrix[i]);
1290 xfree (cache->glyph.matrix);
1291 if (cache->glyph.dictionary)
1292 CFRelease (cache->glyph.dictionary);
1293 memset (&cache->glyph, 0, sizeof (cache->glyph));
1294 if (cache->uvs.table)
1295 CFRelease (cache->uvs.table);
1296 memset (&cache->uvs, 0, sizeof (cache->uvs));
1300 static CFCharacterSetRef
1301 macfont_get_cf_charset (struct font *font)
1303 struct macfont_info *macfont_info = (struct macfont_info *) font;
1305 return macfont_info->cache->cf_charset;
1308 static CFCharacterSetRef
1309 macfont_get_cf_charset_for_name (CFStringRef name)
1311 struct macfont_cache *cache = macfont_lookup_cache (name);
1313 return cache->cf_charset;
1317 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1319 struct macfont_info *macfont_info = (struct macfont_info *) font;
1320 FontRef macfont = macfont_info->macfont;
1321 struct macfont_cache *cache = macfont_info->cache;
1323 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1326 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1328 if (nkeys_or_perm < ROW_PERM_OFFSET)
1330 UniChar unichars[256], ch;
1334 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1335 dispatch_queue_t queue;
1336 dispatch_group_t group = NULL;
1343 CFMutableDictionaryRef dictionary;
1344 uintptr_t key, value;
1348 if (cache->glyph.dictionary == NULL)
1349 cache->glyph.dictionary =
1350 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1351 dictionary = cache->glyph.dictionary;
1352 key = c / NGLYPHS_IN_VALUE;
1353 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1354 value = ((uintptr_t)
1355 CFDictionaryGetValue (dictionary, (const void *) key));
1356 glyph = (value >> nshifts);
1360 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1363 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1366 glyph = kCGFontIndexInvalid;
1369 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1370 value |= ((uintptr_t) glyph << nshifts);
1371 CFDictionarySetValue (dictionary, (const void *) key,
1372 (const void *) value);
1377 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1379 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1380 group = dispatch_group_create ();
1381 dispatch_group_async (group, queue, ^{
1385 nkeys = nkeys_or_perm;
1386 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1387 if (CFDictionaryContainsKey (dictionary,
1388 (const void *) key))
1390 CFDictionaryRemoveValue (dictionary,
1391 (const void *) key);
1395 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1401 for (i = 0; i < 256; i++)
1404 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1405 unichars[len++] = ch;
1408 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1411 mac_font_get_glyphs_for_characters (macfont, unichars,
1415 int next = unichars[len - 1] % 256;
1418 glyphs[i] = kCGFontIndexInvalid;
1421 glyphs[i] = glyphs[len];
1428 glyphs[i] = kCGFontIndexInvalid;
1430 nrows = cache->glyph.nrows;
1431 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1432 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1434 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1435 sizeof (CGGlyph *) * nrows);
1436 cache->glyph.matrix[nrows - 1] = glyphs;
1437 cache->glyph.nrows = nrows;
1439 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1442 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1443 dispatch_release (group);
1448 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1452 uintptr_t key, value;
1456 if (cache->glyph.dictionary == NULL)
1457 cache->glyph.dictionary =
1458 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1459 key = c / NGLYPHS_IN_VALUE;
1460 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1461 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1462 (const void *) key);
1463 glyph = (value >> nshifts);
1466 UniChar unichars[2];
1468 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1470 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1474 glyph = kCGFontIndexInvalid;
1476 value |= ((uintptr_t) glyph << nshifts);
1477 CFDictionarySetValue (cache->glyph.dictionary,
1478 (const void *) key, (const void *) value);
1486 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1489 struct macfont_info *macfont_info = (struct macfont_info *) font;
1490 FontRef macfont = macfont_info->macfont;
1493 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1497 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1499 struct macfont_info *macfont_info = (struct macfont_info *) font;
1500 FontRef macfont = macfont_info->macfont;
1501 struct macfont_cache *cache = macfont_info->cache;
1502 CFDataRef result = NULL;
1504 if (cache->uvs.table == NULL)
1506 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1507 CharacterCollection uvs_collection =
1508 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1510 if (uvs_table == NULL
1511 && mac_font_get_glyph_for_cid (macfont,
1512 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1513 6480) != kCGFontIndexInvalid)
1515 /* If the glyph for U+4E55 is accessible via its CID 6480,
1516 then we use the Adobe-Japan1 UVS table, which maps a
1517 variation sequence to a CID, as a fallback. */
1518 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1520 if (mac_uvs_table_adobe_japan1 == NULL)
1521 mac_uvs_table_adobe_japan1 =
1522 CFDataCreateWithBytesNoCopy (NULL,
1523 mac_uvs_table_adobe_japan1_bytes,
1524 sizeof (mac_uvs_table_adobe_japan1_bytes),
1526 if (mac_uvs_table_adobe_japan1)
1528 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1529 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1532 if (uvs_table == NULL)
1533 cache->uvs.table = kCFNull;
1535 cache->uvs.table = uvs_table;
1536 cache->uvs.collection = uvs_collection;
1539 if (cache->uvs.table != kCFNull)
1541 result = cache->uvs.table;
1542 *collection = cache->uvs.collection;
1548 static Lisp_Object macfont_get_cache (struct frame *);
1549 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1550 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1551 static Lisp_Object macfont_list_family (struct frame *);
1552 static void macfont_free_entity (Lisp_Object);
1553 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1554 static void macfont_close (struct font *);
1555 static int macfont_has_char (Lisp_Object, int);
1556 static unsigned macfont_encode_char (struct font *, int);
1557 static void macfont_text_extents (struct font *, unsigned int *, int,
1558 struct font_metrics *);
1559 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1560 static Lisp_Object macfont_shape (Lisp_Object);
1561 static int macfont_variation_glyphs (struct font *, int c,
1562 unsigned variations[256]);
1563 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1565 static struct font_driver macfont_driver =
1567 LISP_INITIALLY_ZERO, /* Qmac_ct */
1568 0, /* case insensitive */
1572 macfont_list_family,
1573 macfont_free_entity,
1576 NULL, /* prepare_face */
1577 NULL, /* done_face */
1579 macfont_encode_char,
1580 macfont_text_extents,
1582 NULL, /* get_bitmap */
1583 NULL, /* free_bitmap */
1584 NULL, /* anchor_point */
1585 NULL, /* otf_capability */
1586 NULL, /* otf_drive */
1587 NULL, /* start_for_frame */
1588 NULL, /* end_for_frame */
1591 macfont_variation_glyphs,
1592 macfont_filter_properties,
1596 macfont_get_cache (struct frame * f)
1598 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1600 return (dpyinfo->name_list_element);
1604 macfont_get_charset (Lisp_Object registry)
1606 char *str = SSDATA (SYMBOL_NAME (registry));
1607 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1611 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1615 else if (str[i] == '*')
1622 regexp = make_unibyte_string (re, j);
1623 for (i = 0; cf_charset_table[i].name; i++)
1624 if (fast_c_string_match_ignore_case
1625 (regexp, cf_charset_table[i].name,
1626 strlen (cf_charset_table[i].name)) >= 0)
1628 if (! cf_charset_table[i].name)
1630 if (! cf_charset_table[i].cf_charset)
1632 int *uniquifier = cf_charset_table[i].uniquifier;
1633 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1636 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1640 for (j = 0; uniquifier[j]; j++)
1642 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1644 CFCharacterSetAddCharactersInRange (charset,
1645 CFRangeMake (uniquifier[j], 1));
1648 string = CFStringCreateWithCharacters (NULL, unichars, count);
1651 CFRelease (charset);
1654 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1656 CFRelease (charset);
1657 /* CFCharacterSetCreateWithCharactersInString does not handle
1658 surrogate pairs properly as of Mac OS X 10.5. */
1659 cf_charset_table[i].cf_charset_string = string;
1667 unsigned int script_tag, langsys_tag;
1669 unsigned int *features[2];
1672 #define OTF_SYM_TAG(SYM, TAG) \
1674 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1675 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1678 #define OTF_TAG_STR(TAG, P) \
1680 (P)[0] = (char) (TAG >> 24); \
1681 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1682 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1683 (P)[3] = (char) (TAG & 0xFF); \
1687 static struct OpenTypeSpec *
1688 macfont_get_open_type_spec (Lisp_Object otf_spec)
1690 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1697 spec->script = XCAR (otf_spec);
1698 if (! NILP (spec->script))
1700 OTF_SYM_TAG (spec->script, spec->script_tag);
1701 val = assq_no_quit (spec->script, Votf_script_alist);
1702 if (CONSP (val) && SYMBOLP (XCDR (val)))
1703 spec->script = XCDR (val);
1705 spec->script = Qnil;
1708 spec->script_tag = 0x44464C54; /* "DFLT" */
1709 otf_spec = XCDR (otf_spec);
1710 spec->langsys_tag = 0;
1711 if (! NILP (otf_spec))
1713 val = XCAR (otf_spec);
1715 OTF_SYM_TAG (val, spec->langsys_tag);
1716 otf_spec = XCDR (otf_spec);
1718 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1719 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1723 val = XCAR (otf_spec);
1726 len = Flength (val);
1728 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1730 : malloc (XINT (len) * sizeof *spec->features[i]));
1731 if (! spec->features[i])
1733 if (i > 0 && spec->features[0])
1734 free (spec->features[0]);
1738 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1740 if (NILP (XCAR (val)))
1746 OTF_SYM_TAG (XCAR (val), tag);
1747 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1750 spec->nfeatures[i] = j;
1755 static CFMutableDictionaryRef
1756 macfont_create_attributes_with_spec (Lisp_Object spec)
1758 Lisp_Object tmp, extra;
1759 CFMutableArrayRef langarray = NULL;
1760 CFCharacterSetRef charset = NULL;
1761 CFStringRef charset_string = NULL;
1762 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1763 Lisp_Object script = Qnil;
1764 Lisp_Object registry;
1765 int cf_charset_idx, i;
1766 struct OpenTypeSpec *otspec = NULL;
1768 enum font_property_index index;
1771 } numeric_traits[] =
1772 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1773 {{-0.4, 50}, /* light */
1774 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1775 {0, 100}, /* normal */
1776 {0.24, 140}, /* (semi-bold + normal) / 2 */
1777 {0.4, 200}, /* bold */
1778 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1779 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1780 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1781 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1782 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1784 registry = AREF (spec, FONT_REGISTRY_INDEX);
1786 || EQ (registry, Qascii_0)
1787 || EQ (registry, Qiso10646_1)
1788 || EQ (registry, Qunicode_bmp))
1789 cf_charset_idx = -1;
1794 cf_charset_idx = macfont_get_charset (registry);
1795 if (cf_charset_idx < 0)
1797 charset = cf_charset_table[cf_charset_idx].cf_charset;
1798 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1799 lang = cf_charset_table[cf_charset_idx].lang;
1802 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1805 CFArrayAppendValue (langarray, lang);
1809 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1810 CONSP (extra); extra = XCDR (extra))
1812 Lisp_Object key, val;
1815 key = XCAR (tmp), val = XCDR (tmp);
1816 if (EQ (key, QClang))
1819 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1824 for (; CONSP (val); val = XCDR (val))
1825 if (SYMBOLP (XCAR (val)))
1828 cfstring_create_with_string_noencode (SYMBOL_NAME
1833 CFArrayAppendValue (langarray, lang);
1837 else if (EQ (key, QCotf))
1839 otspec = macfont_get_open_type_spec (val);
1842 script = otspec->script;
1844 else if (EQ (key, QCscript))
1848 if (! NILP (script) && ! charset)
1850 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1852 if (CONSP (chars) && CONSP (CDR (chars)))
1854 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1855 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1857 if (! string || !cs)
1865 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1866 if (CHARACTERP (XCAR (chars)))
1868 UniChar unichars[2];
1870 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1872 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1874 CFStringAppendCharacters (string, unichars, count);
1875 CFCharacterSetAddCharactersInRange (cs, range);
1878 /* CFCharacterSetCreateWithCharactersInString does not
1879 handle surrogate pairs properly as of Mac OS X 10.5. */
1880 charset_string = string;
1884 attributes = CFDictionaryCreateMutable (NULL, 0,
1885 &kCFTypeDictionaryKeyCallBacks,
1886 &kCFTypeDictionaryValueCallBacks);
1890 tmp = AREF (spec, FONT_FAMILY_INDEX);
1891 if (SYMBOLP (tmp) && ! NILP (tmp))
1893 CFStringRef family = macfont_create_family_with_symbol (tmp);
1897 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1902 traits = CFDictionaryCreateMutable (NULL, 4,
1903 &kCFTypeDictionaryKeyCallBacks,
1904 &kCFTypeDictionaryValueCallBacks);
1908 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1910 tmp = AREF (spec, numeric_traits[i].index);
1913 CGPoint *point = numeric_traits[i].points;
1914 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1917 while (point->y < floatval)
1919 if (point == numeric_traits[i].points)
1921 else if (point->y == CGFLOAT_MAX)
1923 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1924 * ((point->x - (point - 1)->x)
1925 / (point->y - (point - 1)->y)));
1928 else if (floatval < -1.0)
1930 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1933 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1937 if (CFDictionaryGetCount (traits))
1938 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1941 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1944 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1947 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1954 CFRelease (attributes);
1959 if (langarray) CFRelease (langarray);
1960 if (charset && cf_charset_idx < 0) CFRelease (charset);
1961 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1962 if (traits) CFRelease (traits);
1965 if (otspec->nfeatures[0] > 0)
1966 free (otspec->features[0]);
1967 if (otspec->nfeatures[1] > 0)
1968 free (otspec->features[1]);
1976 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1977 CFCharacterSetRef charset,
1979 CFArrayRef languages)
1981 Boolean result = true;
1983 if (charset || VECTORP (chars))
1985 CFCharacterSetRef desc_charset =
1986 mac_font_descriptor_copy_attribute (desc,
1987 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1989 if (desc_charset == NULL)
1994 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1995 else /* VECTORP (chars) */
1999 for (j = 0; j < ASIZE (chars); j++)
2000 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2001 && CFCharacterSetIsLongCharacterMember (desc_charset,
2002 XFASTINT (AREF (chars, j))))
2004 if (j == ASIZE (chars))
2007 CFRelease (desc_charset);
2010 if (result && languages)
2011 result = mac_font_descriptor_supports_languages (desc, languages);
2017 macfont_traits_distance (FontSymbolicTraits sym_traits1,
2018 FontSymbolicTraits sym_traits2)
2020 FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
2023 /* We prefer synthetic bold of italic to synthetic italic of bold
2024 when both bold and italic are available but bold-italic is not
2026 if (diff & MAC_FONT_TRAIT_BOLD)
2027 distance |= (1 << 0);
2028 if (diff & MAC_FONT_TRAIT_ITALIC)
2029 distance |= (1 << 1);
2030 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2031 distance |= (1 << 2);
2037 macfont_closest_traits_index_p (CFArrayRef traits_array,
2038 FontSymbolicTraits target,
2041 CFIndex i, count = CFArrayGetCount (traits_array);
2042 FontSymbolicTraits traits;
2045 traits = ((FontSymbolicTraits) (uintptr_t)
2046 CFArrayGetValueAtIndex (traits_array, index));
2047 my_distance = macfont_traits_distance (target, traits);
2049 for (i = 0; i < count; i++)
2052 traits = ((FontSymbolicTraits) (uintptr_t)
2053 CFArrayGetValueAtIndex (traits_array, i));
2054 if (macfont_traits_distance (target, traits) < my_distance)
2062 macfont_list (struct frame *f, Lisp_Object spec)
2064 Lisp_Object val = Qnil, family, extra;
2066 CFStringRef family_name = NULL;
2067 CFMutableDictionaryRef attributes = NULL, traits;
2068 Lisp_Object chars = Qnil;
2070 FontSymbolicTraits synth_sym_traits = 0;
2071 CFArrayRef families;
2072 CFIndex families_count;
2073 CFCharacterSetRef charset = NULL;
2074 CFArrayRef languages = NULL;
2078 family = AREF (spec, FONT_FAMILY_INDEX);
2079 if (! NILP (family))
2081 family_name = macfont_create_family_with_symbol (family);
2082 if (family_name == NULL)
2086 attributes = macfont_create_attributes_with_spec (spec);
2090 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2092 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2093 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2095 traits = ((CFMutableDictionaryRef)
2096 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2098 n = FONT_SLANT_NUMERIC (spec);
2099 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2101 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2103 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2106 n = FONT_WEIGHT_NUMERIC (spec);
2107 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2109 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2111 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2115 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2117 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2119 if (CFStringHasPrefix (language, CFSTR ("ja"))
2120 || CFStringHasPrefix (language, CFSTR ("ko"))
2121 || CFStringHasPrefix (language, CFSTR ("zh")))
2122 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2125 /* Create array of families. */
2127 families = CFArrayCreate (NULL, (const void **) &family_name,
2128 1, &kCFTypeArrayCallBacks);
2131 CFStringRef pref_family;
2132 CFIndex families_count, pref_family_index = -1;
2134 families = mac_font_create_available_families ();
2135 if (families == NULL)
2138 families_count = CFArrayGetCount (families);
2140 /* Move preferred family to the front if exists. */
2142 mac_font_create_preferred_family_for_attributes (attributes);
2146 CFArrayGetFirstIndexOfValue (families,
2147 CFRangeMake (0, families_count),
2149 CFRelease (pref_family);
2151 if (pref_family_index > 0)
2153 CFMutableArrayRef mutable_families =
2154 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2156 if (mutable_families)
2158 CFArrayAppendValue (mutable_families,
2159 CFArrayGetValueAtIndex (families,
2160 pref_family_index));
2161 CFArrayAppendArray (mutable_families, families,
2162 CFRangeMake (0, pref_family_index));
2163 if (pref_family_index + 1 < families_count)
2164 CFArrayAppendArray (mutable_families, families,
2165 CFRangeMake (pref_family_index + 1,
2167 - (pref_family_index + 1)));
2168 CFRelease (families);
2169 families = mutable_families;
2174 charset = CFDictionaryGetValue (attributes,
2175 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2179 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2183 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2186 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2187 if (CONSP (val) && VECTORP (XCDR (val)))
2195 CFRetain (languages);
2196 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2200 extra = AREF (spec, FONT_EXTRA_INDEX);
2201 families_count = CFArrayGetCount (families);
2202 for (i = 0; i < families_count; i++)
2204 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2205 FontDescriptorRef pat_desc;
2207 CFIndex descs_count;
2208 CFMutableArrayRef filtered_descs, traits_array;
2212 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2214 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2218 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2219 10.7 returns NULL if pat_desc represents the LastResort font.
2220 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2221 trailing "s") for such a font. */
2222 if (!CFEqual (family_name, CFSTR ("LastResort")))
2223 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2227 FontDescriptorRef lr_desc =
2228 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2232 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2233 &kCFTypeArrayCallBacks);
2234 CFRelease (lr_desc);
2239 CFRelease (pat_desc);
2243 descs_count = CFArrayGetCount (descs);
2244 if (descs_count == 0
2245 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2254 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2255 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2256 for (j = 0; j < descs_count; j++)
2258 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2259 CFDictionaryRef dict;
2261 FontSymbolicTraits sym_traits;
2263 dict = mac_font_descriptor_copy_attribute (desc,
2264 MAC_FONT_TRAITS_ATTRIBUTE);
2268 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2271 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2275 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2276 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2277 != (spacing >= FONT_SPACING_MONO)))
2280 /* Don't use a color bitmap font unless its family is
2281 explicitly specified. */
2282 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2286 && !macfont_supports_charset_and_languages_p (desc, charset,
2290 CFArrayAppendValue (filtered_descs, desc);
2291 CFArrayAppendValue (traits_array,
2292 (const void *) (uintptr_t) sym_traits);
2296 descs = filtered_descs;
2297 descs_count = CFArrayGetCount (descs);
2299 for (j = 0; j < descs_count; j++)
2301 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2302 FontSymbolicTraits sym_traits =
2303 ((FontSymbolicTraits) (uintptr_t)
2304 CFArrayGetValueAtIndex (traits_array, j));
2305 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2307 mask_min = ((synth_sym_traits ^ sym_traits)
2308 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2309 if (FONT_SLANT_NUMERIC (spec) < 0)
2310 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2311 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2312 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2314 mask_max = (synth_sym_traits & ~sym_traits);
2315 /* Synthetic bold does not work for bitmap-only fonts on Mac
2317 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2319 CFNumberRef format =
2320 mac_font_descriptor_copy_attribute (desc,
2321 MAC_FONT_FORMAT_ATTRIBUTE);
2325 uint32_t format_val;
2327 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2329 && format_val == MAC_FONT_FORMAT_BITMAP)
2330 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2334 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2336 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2337 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2338 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2339 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2340 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2341 bmask += MAC_FONT_TRAIT_BOLD)
2342 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2343 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2344 imask += MAC_FONT_TRAIT_ITALIC)
2346 FontSymbolicTraits synth = (imask | bmask | mmask);
2349 || macfont_closest_traits_index_p (traits_array,
2350 (sym_traits | synth),
2353 entity = macfont_descriptor_entity (desc, extra, synth);
2354 if (! NILP (entity))
2355 val = Fcons (entity, val);
2360 CFRelease (traits_array);
2364 CFRelease (families);
2365 val = Fnreverse (val);
2371 FONT_ADD_LOG ("macfont-list", spec, val);
2372 if (charset) CFRelease (charset);
2373 if (languages) CFRelease (languages);
2374 if (attributes) CFRelease (attributes);
2375 if (family_name) CFRelease (family_name);
2383 macfont_match (struct frame * frame, Lisp_Object spec)
2385 Lisp_Object entity = Qnil;
2386 CFMutableDictionaryRef attributes;
2387 FontDescriptorRef pat_desc = NULL, desc = NULL;
2391 attributes = macfont_create_attributes_with_spec (spec);
2394 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2395 CFRelease (attributes);
2399 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2401 CFRelease (pat_desc);
2405 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2411 FONT_ADD_LOG ("macfont-match", spec, entity);
2416 macfont_list_family (struct frame *frame)
2418 Lisp_Object list = Qnil;
2419 CFArrayRef families;
2423 families = mac_font_create_available_families ();
2426 CFIndex i, count = CFArrayGetCount (families);
2428 for (i = 0; i < count; i++)
2429 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2430 CFRelease (families);
2439 macfont_free_entity (Lisp_Object entity)
2441 Lisp_Object val = assq_no_quit (QCfont_entity,
2442 AREF (entity, FONT_EXTRA_INDEX));
2443 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2451 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2453 Lisp_Object val, font_object;
2454 CFStringRef font_name;
2455 struct macfont_info *macfont_info = NULL;
2459 FontSymbolicTraits sym_traits;
2461 int len, i, total_width;
2463 CGFloat ascent, descent, leading;
2465 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2467 || XTYPE (XCDR (val)) != Lisp_Misc
2468 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2470 font_name = XSAVE_POINTER (XCDR (val), 0);
2471 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2473 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2478 macfont = mac_font_create_with_name (font_name, size);
2481 int fontsize = (int) [((NSFont *) macfont) pointSize];
2482 if (fontsize != size) size = fontsize;
2488 font_object = font_build_object (VECSIZE (struct macfont_info),
2489 Qmac_ct, entity, size);
2490 font = XFONT_OBJECT (font_object);
2491 font->pixel_size = size;
2492 font->driver = &macfont_driver;
2493 font->encoding_charset = font->repertory_charset = -1;
2497 macfont_info = (struct macfont_info *) font;
2498 macfont_info->macfont = macfont;
2499 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2501 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2502 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2503 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2506 macfont_info->screen_font = NULL;
2507 macfont_info->cache = macfont_lookup_cache (font_name);
2508 macfont_retain_cache (macfont_info->cache);
2509 macfont_info->metrics = NULL;
2510 macfont_info->metrics_nrows = 0;
2511 macfont_info->synthetic_italic_p = 0;
2512 macfont_info->synthetic_bold_p = 0;
2513 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2514 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2515 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2516 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2517 macfont_info->synthetic_italic_p = 1;
2518 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2519 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2520 macfont_info->synthetic_bold_p = 1;
2521 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2522 macfont_info->spacing = MACFONT_SPACING_MONO;
2523 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2524 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2525 == FONT_SPACING_SYNTHETIC_MONO))
2526 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2527 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2528 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2531 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2533 macfont_info->antialias =
2534 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2536 macfont_info->color_bitmap_p = 0;
2537 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2538 macfont_info->color_bitmap_p = 1;
2540 glyph = macfont_get_glyph_for_character (font, ' ');
2541 if (glyph != kCGFontIndexInvalid)
2542 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2544 /* dirty workaround */
2545 font->space_width = pixel_size;
2547 total_width = font->space_width;
2548 for (i = 1; i < 95; i++)
2550 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2551 if (glyph == kCGFontIndexInvalid)
2553 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2556 font->average_width = total_width / 95;
2558 font->average_width = font->space_width; /* XXX */
2560 if (!(macfont_info->screen_font
2561 && mac_screen_font_get_metrics (macfont_info->screen_font,
2562 &ascent, &descent, &leading)))
2564 CFStringRef family_name;
2566 ascent = mac_font_get_ascent (macfont);
2567 descent = mac_font_get_descent (macfont);
2568 leading = mac_font_get_leading (macfont);
2569 /* AppKit and WebKit do some adjustment to the heights of
2570 Courier, Helvetica, and Times. */
2571 family_name = mac_font_copy_family_name (macfont);
2574 if (CFEqual (family_name, CFSTR ("Courier"))
2575 || CFEqual (family_name, CFSTR ("Helvetica"))
2576 || CFEqual (family_name, CFSTR ("Times")))
2577 ascent += (ascent + descent) * .15f;
2578 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2583 CFRelease (family_name);
2586 font->ascent = ascent + 0.5f;
2587 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2588 if (CONSP (val) && !NILP (XCDR (val)))
2589 font->descent = descent + 0.5f;
2591 font->descent = descent + leading + 0.5f;
2592 font->height = font->ascent + font->descent;
2594 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2595 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2599 /* Unfortunately Xft doesn't provide a way to get minimum char
2600 width. So, we use space_width instead. */
2601 font->min_width = font->max_width = font->space_width; /* XXX */
2603 font->baseline_offset = 0;
2604 font->relative_compose = 0;
2605 font->default_ascent = 0;
2606 font->vertical_centering = 0;
2612 macfont_close (struct font *font)
2614 struct macfont_info *macfont_info = (struct macfont_info *) font;
2616 if (macfont_info->cache)
2621 CFRelease (macfont_info->macfont);
2622 CGFontRelease (macfont_info->cgfont);
2623 if (macfont_info->screen_font)
2624 CFRelease (macfont_info->screen_font);
2625 macfont_release_cache (macfont_info->cache);
2626 for (i = 0; i < macfont_info->metrics_nrows; i++)
2627 if (macfont_info->metrics[i])
2628 xfree (macfont_info->metrics[i]);
2629 if (macfont_info->metrics)
2630 xfree (macfont_info->metrics);
2631 macfont_info->cache = NULL;
2637 macfont_has_char (Lisp_Object font, int c)
2640 CFCharacterSetRef charset;
2643 if (FONT_ENTITY_P (font))
2648 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2650 name = XSAVE_POINTER (val, 0);
2651 charset = macfont_get_cf_charset_for_name (name);
2654 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2656 result = CFCharacterSetIsLongCharacterMember (charset, c);
2663 macfont_encode_char (struct font *font, int c)
2665 struct macfont_info *macfont_info = (struct macfont_info *) font;
2669 glyph = macfont_get_glyph_for_character (font, c);
2672 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2676 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2677 struct font_metrics *metrics)
2682 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2683 for (i = 1; i < nglyphs; i++)
2685 struct font_metrics m;
2686 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2691 if (width + m.lbearing < metrics->lbearing)
2692 metrics->lbearing = width + m.lbearing;
2693 if (width + m.rbearing > metrics->rbearing)
2694 metrics->rbearing = width + m.rbearing;
2695 if (m.ascent > metrics->ascent)
2696 metrics->ascent = m.ascent;
2697 if (m.descent > metrics->descent)
2698 metrics->descent = m.descent;
2705 metrics->width = width;
2709 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2710 bool with_background)
2712 struct frame * f = s->f;
2713 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2714 CGRect background_rect;
2715 CGPoint text_position;
2718 CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2719 bool no_antialias_p =
2720 (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2721 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2722 && font_size <= macfont_antialias_threshold));
2723 int len = to - from;
2724 struct face *face = s->face;
2725 CGContextRef context;
2729 if (with_background)
2730 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2731 s->width, FONT_HEIGHT (s->font));
2733 background_rect = CGRectNull;
2735 text_position = CGPointMake (x, -y);
2736 glyphs = xmalloc (sizeof (CGGlyph) * len);
2738 CGFloat advance_delta = 0;
2740 CGFloat total_width = 0;
2742 positions = xmalloc (sizeof (CGPoint) * len);
2743 for (i = 0; i < len; i++)
2747 glyphs[i] = s->char2b[from + i];
2748 width = (s->padding_p ? 1
2749 : macfont_glyph_extents (s->font, glyphs[i],
2750 NULL, &advance_delta,
2752 positions[i].x = total_width + advance_delta;
2754 total_width += width;
2758 context = [[NSGraphicsContext currentContext] graphicsPort];
2759 CGContextSaveGState (context);
2761 if (!CGRectIsNull (background_rect))
2763 if (s->hl == DRAW_MOUSE_FACE)
2765 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2767 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2769 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2770 CGContextFillRects (context, &background_rect, 1);
2773 if (macfont_info->cgfont)
2775 CGAffineTransform atfm;
2777 CGContextScaleCTM (context, 1, -1);
2778 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2779 if (macfont_info->synthetic_italic_p)
2780 atfm = synthetic_italic_atfm;
2782 atfm = CGAffineTransformIdentity;
2783 if (macfont_info->synthetic_bold_p)
2785 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2786 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2787 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2790 CGContextSetShouldAntialias (context, false);
2792 CGContextSetTextMatrix (context, atfm);
2793 CGContextSetTextPosition (context, text_position.x, text_position.y);
2795 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2796 if (macfont_info->color_bitmap_p
2797 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2798 && CTFontDrawGlyphs != NULL
2804 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2809 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2811 CGContextSetFont (context, macfont_info->cgfont);
2812 CGContextSetFontSize (context, font_size);
2813 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2820 CGContextRestoreGState (context);
2828 macfont_shape (Lisp_Object lgstring)
2831 struct macfont_info *macfont_info;
2833 ptrdiff_t glyph_len, len, i, j;
2836 CFIndex *nonbmp_indices;
2839 struct mac_glyph_layout *glyph_layouts;
2841 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2842 macfont_info = (struct macfont_info *) font;
2843 macfont = macfont_info->macfont;
2845 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2847 for (i = 0; i < glyph_len; i++)
2849 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2853 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2859 if (INT_MAX / 2 < len)
2860 memory_full (SIZE_MAX);
2862 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2863 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2864 for (i = j = 0; i < len; i++)
2866 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2868 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2870 nonbmp_indices[j] = i + j;
2874 nonbmp_indices[j] = len + j; /* sentinel */
2878 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2882 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2883 if (macfont_info->screen_font)
2884 used = mac_screen_font_shape (macfont_info->screen_font, string,
2885 glyph_layouts, glyph_len);
2887 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2898 for (i = 0; i < used; i++)
2900 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2901 struct mac_glyph_layout *gl = glyph_layouts + i;
2903 struct font_metrics metrics;
2904 int xoff, yoff, wadjust;
2908 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2909 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2912 from = gl->comp_range.location;
2913 /* Convert UTF-16 index to UTF-32. */
2915 while (nonbmp_indices[j] < from)
2918 LGLYPH_SET_FROM (lglyph, from);
2920 to = gl->comp_range.location + gl->comp_range.length;
2921 /* Convert UTF-16 index to UTF-32. */
2922 while (nonbmp_indices[j] < to)
2925 LGLYPH_SET_TO (lglyph, to - 1);
2927 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2928 the composition is trivial. */
2932 if (unichars[gl->string_index] >= 0xD800
2933 && unichars[gl->string_index] < 0xDC00)
2934 c = (((unichars[gl->string_index] - 0xD800) << 10)
2935 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2937 c = unichars[gl->string_index];
2938 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2940 LGLYPH_SET_CHAR (lglyph, c);
2944 unsigned long cc = gl->glyph_id;
2945 LGLYPH_SET_CODE (lglyph, cc);
2948 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2949 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2950 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2951 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2952 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2953 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2955 xoff = lround (gl->advance_delta);
2956 yoff = lround (- gl->baseline_delta);
2957 wadjust = lround (gl->advance);
2958 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2962 vec = Fmake_vector (make_number (3), Qnil);
2963 ASET (vec, 0, make_number (xoff));
2964 ASET (vec, 1, make_number (yoff));
2965 ASET (vec, 2, make_number (wadjust));
2966 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2972 return make_number (used);
2975 /* Structures for the UVS subtable (format 14) in the cmap table. */
2976 typedef UInt8 UINT24[3];
2978 #pragma pack(push, 1)
2979 struct variation_selector_record
2981 UINT24 var_selector;
2982 UInt32 default_uvs_offset, non_default_uvs_offset;
2987 UInt32 length, num_var_selector_records;
2988 struct variation_selector_record variation_selector_records[1];
2990 #define SIZEOF_UVS_TABLE_HEADER \
2991 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2993 struct unicode_value_range
2995 UINT24 start_unicode_value;
2996 UInt8 additional_count;
2998 struct default_uvs_table {
2999 UInt32 num_unicode_value_ranges;
3000 struct unicode_value_range unicode_value_ranges[1];
3002 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
3003 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3007 UINT24 unicode_value;
3010 struct non_default_uvs_table
3012 UInt32 num_uvs_mappings;
3013 struct uvs_mapping uvs_mappings[1];
3015 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3016 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3019 /* Read big endian values. The argument LVAL must be an lvalue. */
3020 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3021 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3022 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3023 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3024 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3025 /* Succeeding one byte should also be accessible. */
3026 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3027 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3029 /* Return UVS subtable for the specified FONT. If the subtable is not
3030 found or ill-formatted, then return NULL. */
3033 mac_font_copy_uvs_table (FontRef font)
3035 CFDataRef cmap_table, uvs_table = NULL;
3037 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3040 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3041 struct uvs_table *uvs;
3042 struct variation_selector_record *records;
3043 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3046 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3050 cmap_len = CFDataGetLength (cmap_table);
3051 if (sizeof_sfntCMapHeader > cmap_len)
3054 ntables = BUINT16_VALUE (cmap->numTables);
3055 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3056 / sizeof_sfntCMapEncoding))
3059 for (i = 0; i < ntables; i++)
3060 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3061 == kFontUnicodePlatform)
3062 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3063 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3065 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3069 || uvs_offset > cmap_len
3070 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3073 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3074 uvs_len = BUINT32_VALUE (uvs->length);
3075 if (uvs_len > cmap_len - uvs_offset
3076 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3079 if (BUINT16_VALUE (uvs->format) != 14)
3082 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3083 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3084 / sizeof (struct variation_selector_record)))
3087 records = uvs->variation_selector_records;
3088 for (i = 0; i < nrecords; i++)
3090 UInt32 default_uvs_offset, non_default_uvs_offset;
3092 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3093 if (default_uvs_offset)
3095 struct default_uvs_table *default_uvs;
3098 if (default_uvs_offset > uvs_len
3099 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3100 > uvs_len - default_uvs_offset))
3103 default_uvs = ((struct default_uvs_table *)
3104 ((UInt8 *) uvs + default_uvs_offset));
3105 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3106 if (nranges > ((uvs_len - default_uvs_offset
3107 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3108 / sizeof (struct unicode_value_range)))
3110 /* Now 2 * nranges can't overflow, so we can safely use
3111 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3112 mac_font_get_glyphs_for_variants. */
3115 non_default_uvs_offset =
3116 BUINT32_VALUE (records[i].non_default_uvs_offset);
3117 if (non_default_uvs_offset)
3119 struct non_default_uvs_table *non_default_uvs;
3122 if (non_default_uvs_offset > uvs_len
3123 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3124 > uvs_len - non_default_uvs_offset))
3127 non_default_uvs = ((struct non_default_uvs_table *)
3128 ((UInt8 *) uvs + non_default_uvs_offset));
3129 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3130 if (nmappings > ((uvs_len - non_default_uvs_offset
3131 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3132 / sizeof (struct uvs_mapping)))
3134 /* Now 2 * nmappings can't overflow, so we can safely
3135 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3136 in mac_font_get_glyphs_for_variants. */
3140 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3143 CFRelease (cmap_table);
3149 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3150 sequence consisting of the given base character C and each
3151 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3152 result (explained below) into the corresponding GLYPHS[i]. If the
3153 entry is found in the Default UVS Table, then the result is 0. If
3154 the entry is found in the Non-Default UVS Table, then the result is
3155 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3156 elements in SELECTORS must be sorted in strictly increasing
3160 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3161 const UTF32Char selectors[], CGGlyph glyphs[],
3164 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3165 struct variation_selector_record *records = uvs->variation_selector_records;
3167 UInt32 ir, nrecords;
3168 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3169 dispatch_queue_t queue =
3170 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3171 dispatch_group_t group = dispatch_group_create ();
3174 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3177 while (i < count && ir < nrecords)
3179 UInt32 default_uvs_offset, non_default_uvs_offset;
3181 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3183 glyphs[i++] = kCGFontIndexInvalid;
3186 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3192 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3193 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3194 non_default_uvs_offset =
3195 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3196 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3197 dispatch_group_async (group, queue, ^{
3199 glyphs[i] = kCGFontIndexInvalid;
3201 if (default_uvs_offset)
3203 struct default_uvs_table *default_uvs =
3204 (struct default_uvs_table *) ((UInt8 *) uvs
3205 + default_uvs_offset);
3206 struct unicode_value_range *ranges =
3207 default_uvs->unicode_value_ranges;
3211 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3214 UInt32 mid = (lo + hi) / 2;
3216 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3222 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3223 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3227 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3229 struct non_default_uvs_table *non_default_uvs =
3230 (struct non_default_uvs_table *) ((UInt8 *) uvs
3231 + non_default_uvs_offset);
3232 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3236 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3239 UInt32 mid = (lo + hi) / 2;
3241 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3247 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3248 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3250 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3257 glyphs[i++] = kCGFontIndexInvalid;
3258 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3259 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3260 dispatch_release (group);
3265 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3267 CFDataRef uvs_table;
3268 CharacterCollection uvs_collection;
3272 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3276 UTF32Char selectors[256];
3277 CGGlyph glyphs[256];
3279 for (i = 0; i < 16; i++)
3280 selectors[i] = 0xFE00 + i;
3281 for (; i < 256; i++)
3282 selectors[i] = 0xE0100 + (i - 16);
3283 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3284 for (i = 0; i < 256; i++)
3286 CGGlyph glyph = glyphs[i];
3288 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3289 && glyph != kCGFontIndexInvalid)
3290 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3291 if (glyph == kCGFontIndexInvalid)
3295 variations[i] = (glyph ? glyph
3296 : macfont_get_glyph_for_character (font, c));
3306 static const char *const macfont_booleans[] = {
3312 static const char *const macfont_non_booleans[] = {
3320 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3322 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3326 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3327 CFArrayRef languages)
3329 Boolean result = true;
3330 CFArrayRef desc_languages =
3331 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3333 if (desc_languages == NULL)
3337 CFIndex desc_languages_count, i, languages_count;
3339 desc_languages_count = CFArrayGetCount (desc_languages);
3340 languages_count = CFArrayGetCount (languages);
3341 for (i = 0; i < languages_count; i++)
3342 if (!CFArrayContainsValue (desc_languages,
3343 CFRangeMake (0, desc_languages_count),
3344 CFArrayGetValueAtIndex (languages, i)))
3349 CFRelease (desc_languages);
3356 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3358 CFStringRef result = NULL;
3359 CFStringRef charset_string =
3360 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3362 if (charset_string && CFStringGetLength (charset_string) > 0)
3364 CFStringRef keys[] = {
3365 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3366 kCTLanguageAttributeName
3368 CFSTR ("NSLanguage")
3371 CFTypeRef values[] = {NULL};
3372 CFIndex num_values = 0;
3373 CFArrayRef languages
3374 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3376 if (languages && CFArrayGetCount (languages) > 0)
3378 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3379 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3382 CFCharacterSetRef charset =
3383 CFDictionaryGetValue (attributes,
3384 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3386 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3391 CFAttributedStringRef attr_string = NULL;
3392 CTLineRef ctline = NULL;
3393 CFDictionaryRef attrs
3394 = CFDictionaryCreate (NULL, (const void **) keys,
3395 (const void **) values, num_values,
3396 &kCFTypeDictionaryKeyCallBacks,
3397 &kCFTypeDictionaryValueCallBacks);
3401 attr_string = CFAttributedStringCreate (NULL, charset_string,
3407 ctline = CTLineCreateWithAttributedString (attr_string);
3408 CFRelease (attr_string);
3412 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3413 CFIndex i, nruns = CFArrayGetCount (runs);
3416 for (i = 0; i < nruns; i++)
3418 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3419 CFDictionaryRef attributes = CTRunGetAttributes (run);
3420 CTFontRef font_in_run;
3422 if (attributes == NULL)
3425 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3426 if (font_in_run == NULL)
3430 else if (!mac_ctfont_equal_in_postscript_name (font,
3434 if (nruns > 0 && i == nruns)
3435 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3444 static inline double
3445 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3447 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3451 static inline CGRect
3452 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3454 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3459 mac_ctfont_create_available_families (void)
3461 CFMutableArrayRef families = NULL;
3463 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3464 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3465 if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3468 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3472 CFIndex i, count = CFArrayGetCount (orig_families);
3474 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3476 for (i = 0; i < count; i++)
3478 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3480 if (!CFStringHasPrefix (family, CFSTR ("."))
3481 && (CTFontManagerCompareFontFamilyNames (family,
3482 CFSTR ("LastResort"),
3484 != kCFCompareEqualTo))
3485 CFArrayAppendValue (families, family);
3487 CFRelease (orig_families);
3490 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3491 else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3493 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3494 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3496 CTFontCollectionRef collection;
3497 CFArrayRef descs = NULL;
3499 collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3502 descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3503 CFRelease (collection);
3507 CFIndex i, count = CFArrayGetCount (descs);
3509 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3511 for (i = 0; i < count; i++)
3513 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3515 mac_font_descriptor_copy_attribute (desc,
3516 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3520 CFIndex p, limit = CFArrayGetCount (families);
3522 p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3523 (const void *) name,
3524 mac_font_family_compare, NULL);
3526 CFArrayAppendValue (families, name);
3527 else if (mac_font_family_compare
3528 (CFArrayGetValueAtIndex (families, p),
3529 name, NULL) != kCFCompareEqualTo)
3530 CFArrayInsertValueAtIndex (families, p, name);
3543 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3546 CFStringRef name1, name2;
3552 name1 = CTFontCopyPostScriptName (font1);
3555 name2 = CTFontCopyPostScriptName (font2);
3558 result = CFEqual (name1, name2);
3568 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3571 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3572 CFTypeRef values[] = {NULL, NULL};
3573 CFDictionaryRef attributes = NULL;
3574 CFAttributedStringRef attr_string = NULL;
3575 CTLineRef ctline = NULL;
3576 float float_zero = 0.0f;
3578 values[0] = macfont;
3579 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3582 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3583 (const void **) values,
3585 &kCFTypeDictionaryKeyCallBacks,
3586 &kCFTypeDictionaryValueCallBacks);
3587 CFRelease (values[1]);
3591 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3592 CFRelease (attributes);
3596 ctline = CTLineCreateWithAttributedString (attr_string);
3597 CFRelease (attr_string);
3601 /* Abandon if ctline contains some fonts other than the
3603 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3604 CFIndex i, nruns = CFArrayGetCount (runs);
3606 for (i = 0; i < nruns; i++)
3608 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3609 CFDictionaryRef attributes = CTRunGetAttributes (run);
3610 CTFontRef font_in_run;
3612 if (attributes == NULL)
3615 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3616 if (font_in_run == NULL)
3618 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3632 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3633 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3635 CFIndex used, result = 0;
3636 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3641 used = CTLineGetGlyphCount (ctline);
3642 if (used <= glyph_len)
3644 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3645 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3646 CGFloat total_advance = 0;
3647 CFIndex total_glyph_count = 0;
3649 for (k = 0; k < ctrun_count; k++)
3651 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3652 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3653 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3654 CFRange string_range, comp_range, range;
3655 CFIndex *permutation;
3657 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3658 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3662 #define RIGHT_TO_LEFT_P permutation
3664 /* Now the `comp_range' member of struct mac_glyph_layout is
3665 temporarily used as a work area such that:
3666 glbuf[i].comp_range.location =
3667 min {compRange[i + 1].location, ...,
3668 compRange[glyph_count - 1].location,
3669 maxRange (stringRangeForCTRun)}
3670 glbuf[i].comp_range.length = maxRange (compRange[i])
3671 where compRange[i] is the range of composed characters
3672 containing i-th glyph. */
3673 string_range = CTRunGetStringRange (ctrun);
3674 min_location = string_range.location + string_range.length;
3675 for (i = 0; i < glyph_count; i++)
3677 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3678 CFIndex glyph_index;
3681 if (!RIGHT_TO_LEFT_P)
3682 glyph_index = glyph_count - i - 1;
3685 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3688 CFStringGetRangeOfComposedCharactersAtIndex (string,
3690 gl->comp_range.location = min_location;
3691 gl->comp_range.length = rng.location + rng.length;
3692 if (rng.location < min_location)
3693 min_location = rng.location;
3696 /* Fill the `comp_range' member of struct mac_glyph_layout,
3697 and setup a permutation for right-to-left text. */
3698 comp_range = CFRangeMake (string_range.location, 0);
3699 range = CFRangeMake (0, 0);
3702 struct mac_glyph_layout *gl =
3703 glbuf + range.location + range.length;
3705 if (gl->comp_range.length
3706 > comp_range.location + comp_range.length)
3707 comp_range.length = gl->comp_range.length - comp_range.location;
3708 min_location = gl->comp_range.location;
3711 if (min_location >= comp_range.location + comp_range.length)
3713 comp_range.length = min_location - comp_range.location;
3714 for (i = 0; i < range.length; i++)
3716 glbuf[range.location + i].comp_range = comp_range;
3717 if (RIGHT_TO_LEFT_P)
3718 permutation[range.location + i] =
3719 range.location + range.length - i - 1;
3722 comp_range = CFRangeMake (min_location, 0);
3723 range.location += range.length;
3725 if (range.location == glyph_count)
3730 /* Then fill the remaining members. */
3731 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3734 struct mac_glyph_layout *gl;
3737 if (!RIGHT_TO_LEFT_P)
3738 gl = glbuf + range.location;
3743 src = glyph_count - 1 - range.location;
3744 dest = permutation[src];
3748 CFIndex tmp = gl->string_index;
3750 gl->string_index = glbuf[src].string_index;
3751 glbuf[src].string_index = tmp;
3754 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3756 CTRunGetPositions (ctrun, range, &position);
3757 gl->advance_delta = position.x - total_advance;
3758 gl->baseline_delta = position.y;
3759 gl->advance = (gl->advance_delta
3760 + CTRunGetTypographicBounds (ctrun, range,
3762 total_advance += gl->advance;
3765 if (RIGHT_TO_LEFT_P)
3766 xfree (permutation);
3768 #undef RIGHT_TO_LEFT_P
3770 total_glyph_count += glyph_count;
3780 /* The function below seems to cause a memory leak for the CFString
3781 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3782 10.6.3. For now, we use the NSGlyphInfo version instead. */
3783 #if USE_CT_GLYPH_INFO
3785 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3788 CGGlyph result = kCGFontIndexInvalid;
3789 UniChar characters[] = {0xfffd};
3791 CFAttributedStringRef attr_string = NULL;
3792 CTLineRef ctline = NULL;
3794 string = CFStringCreateWithCharacters (NULL, characters,
3795 ARRAYELTS (characters));
3799 CTGlyphInfoRef glyph_info =
3800 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3801 CFDictionaryRef attributes = NULL;
3805 CFStringRef keys[] = {kCTFontAttributeName,
3806 kCTGlyphInfoAttributeName};
3807 CFTypeRef values[] = {font, glyph_info};
3809 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3810 (const void **) values,
3812 &kCFTypeDictionaryKeyCallBacks,
3813 &kCFTypeDictionaryValueCallBacks);
3814 CFRelease (glyph_info);
3818 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3819 CFRelease (attributes);
3825 ctline = CTLineCreateWithAttributedString (attr_string);
3826 CFRelease (attr_string);
3830 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3832 if (CFArrayGetCount (runs) > 0)
3834 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3835 CFDictionaryRef attributes = CTRunGetAttributes (run);
3839 CTFontRef font_in_run =
3840 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3843 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3845 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3846 if (result >= CTFontGetGlyphCount (font))
3847 result = kCGFontIndexInvalid;
3858 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3860 mac_font_family_group (CFStringRef family)
3862 if (CFStringHasPrefix (family, CFSTR ("#")))
3868 range = CFStringFind (family, CFSTR ("Apple"),
3869 kCFCompareCaseInsensitive | kCFCompareAnchored);
3870 if (range.location != kCFNotFound)
3877 static CFComparisonResult
3878 mac_font_family_compare (const void *val1, const void *val2, void *context)
3880 CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3883 group1 = mac_font_family_group (family1);
3884 group2 = mac_font_family_group (family2);
3885 if (group1 < group2)
3886 return kCFCompareLessThan;
3887 if (group1 > group2)
3888 return kCFCompareGreaterThan;
3889 return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3891 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3894 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3896 CFArrayRef result = NULL;
3898 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3899 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3900 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3903 CTFontRef user_font =
3904 CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3908 CFArrayRef languages =
3909 CFArrayCreate (NULL, (const void **) &language, 1,
3910 &kCFTypeArrayCallBacks);
3914 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3916 CFRelease (languages);
3918 CFRelease (user_font);
3921 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3922 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3924 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3925 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3929 for (i = 0; macfont_language_default_font_names[i].language; i++)
3931 if (CFEqual (macfont_language_default_font_names[i].language,
3934 CFMutableArrayRef descriptors =
3935 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3942 macfont_language_default_font_names[i].font_names[j];
3945 CFDictionaryRef attributes =
3946 CFDictionaryCreate (NULL,
3948 &MAC_FONT_NAME_ATTRIBUTE),
3950 &macfont_language_default_font_names[i].font_names[j]),
3951 1, &kCFTypeDictionaryKeyCallBacks,
3952 &kCFTypeDictionaryValueCallBacks);
3956 FontDescriptorRef pat_desc =
3957 mac_font_descriptor_create_with_attributes (attributes);
3961 FontDescriptorRef descriptor =
3962 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3966 CFArrayAppendValue (descriptors, descriptor);
3967 CFRelease (descriptor);
3969 CFRelease (pat_desc);
3971 CFRelease (attributes);
3974 result = descriptors;
3986 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3987 CFArrayRef languages)
3989 CFStringRef result = NULL;
3990 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3991 CFArrayRef descriptors =
3992 mac_font_copy_default_descriptors_for_language (language);
3996 CFIndex i, count = CFArrayGetCount (descriptors);
3998 for (i = 0; i < count; i++)
4000 FontDescriptorRef descriptor =
4001 CFArrayGetValueAtIndex (descriptors, i);
4003 if (macfont_supports_charset_and_languages_p (descriptor, charset,
4006 CFStringRef family =
4007 mac_font_descriptor_copy_attribute (descriptor,
4008 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
4011 if (!CFStringHasPrefix (family, CFSTR ("."))
4012 && !CFEqual (family, CFSTR ("LastResort")))
4022 CFRelease (descriptors);
4029 macfont_get_nsctfont (struct font *font)
4031 struct macfont_info *macfont_info = (struct macfont_info *) font;
4032 FontRef macfont = macfont_info->macfont;
4034 return (void *) macfont;
4038 mac_register_font_driver (struct frame *f)
4040 register_font_driver (&macfont_driver, f);
4043 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4047 syms_of_macfont (void)
4049 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4050 static struct font_driver mac_font_driver;
4052 DEFSYM (Qmac_ct, "mac-ct");
4053 macfont_driver.type = Qmac_ct;
4054 register_font_driver (&macfont_driver, NULL);
4056 DEFSYM (QCdestination, ":destination");
4057 DEFSYM (QCminspace, ":minspace");