1 /* Font driver on Mac OSX Core text.
2 Copyright (C) 2009-2014 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
41 #include <libkern/OSByteOrder.h>
43 static struct font_driver macfont_driver;
45 /* Core Text, for Mac OS X 10.5 and later. */
46 static Lisp_Object Qmac_ct;
48 static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
49 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
50 static CFArrayRef mac_ctfont_create_available_families (void);
51 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
52 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
54 static CFComparisonResult mac_font_family_compare (const void *,
55 const void *, void *);
56 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
58 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
59 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
60 struct mac_glyph_layout *, CFIndex);
62 mac_font_copy_default_descriptors_for_language (CFStringRef language);
65 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
66 CFArrayRef languages);
69 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
70 CTCharacterCollection,
74 /* The font property key specifying the font design destination. The
75 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
76 text. (See the documentation of X Logical Font Description
77 Conventions.) In the Mac font driver, 1 means the screen font is
78 used for calculating some glyph metrics. You can see the
79 difference with Monaco 8pt or 9pt, for example. */
80 static Lisp_Object QCdestination;
82 /* The boolean-valued font property key specifying the use of
84 static Lisp_Object QCminspace;
86 struct macfont_metrics;
88 /* The actual structure for Mac font that can be cast to struct font. */
95 ScreenFontRef screen_font;
96 struct macfont_cache *cache;
97 struct macfont_metrics **metrics;
99 bool_bf synthetic_italic_p : 1;
100 bool_bf synthetic_bold_p : 1;
101 unsigned spacing : 2;
102 unsigned antialias : 2;
103 bool_bf color_bitmap_p : 1;
106 /* Values for the `spacing' member in `struct macfont_info'. */
110 MACFONT_SPACING_PROPORTIONAL,
111 MACFONT_SPACING_MONO,
112 MACFONT_SPACING_SYNTHETIC_MONO,
115 /* Values for the `antialias' member in `struct macfont_info'. */
119 MACFONT_ANTIALIAS_DEFAULT,
120 MACFONT_ANTIALIAS_OFF,
121 MACFONT_ANTIALIAS_ON,
124 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
125 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
126 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
128 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
129 static const CGFloat synthetic_bold_factor = 0.024;
131 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
132 FontSymbolicTraits *);
133 static void macfont_store_descriptor_attributes (FontDescriptorRef,
135 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
138 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
139 static int macfont_glyph_extents (struct font *, CGGlyph,
140 struct font_metrics *, CGFloat *, int);
141 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
142 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
146 static CFIndex macfont_closest_traits_index (CFArrayRef,
148 static CFDataRef mac_font_copy_uvs_table (FontRef);
149 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
151 CGGlyph [], CFIndex);
153 /* From CFData to a lisp string. Always returns a unibyte string. */
156 cfdata_to_lisp (CFDataRef data)
158 CFIndex len = CFDataGetLength (data);
159 Lisp_Object result = make_uninit_string (len);
161 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
168 /* From CFString to a lisp string. Returns a unibyte string
169 containing a UTF-8 byte sequence. */
172 cfstring_to_lisp_nodecode (CFStringRef string)
174 Lisp_Object result = Qnil;
176 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
180 CFIndex i, length = CFStringGetLength (string);
182 for (i = 0; i < length; i++)
183 if (CFStringGetCharacterAtIndex (string, i) == 0)
187 return make_unibyte_string (s, strlen (s));
190 data = CFStringCreateExternalRepresentation (NULL, string,
191 kCFStringEncodingUTF8, '?');
194 result = cfdata_to_lisp (data);
201 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
202 cfstring_create_with_utf8_cstring, this function preserves NUL
206 cfstring_create_with_string_noencode (Lisp_Object s)
208 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
209 kCFStringEncodingUTF8, false);
212 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
213 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
214 kCFStringEncodingMacRoman, false);
220 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
222 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
224 return advancement.width;
228 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
231 #if USE_CT_GLYPH_INFO
232 return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
235 CGGlyph result = kCGFontIndexInvalid;
236 NSFont *nsFont = (NSFont *) font;
237 unichar characters[] = {0xfffd};
239 [NSString stringWithCharacters:characters
240 length: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_); \
653 /* Mac font driver. */
659 /* characters to distinguish the charset from the others */
661 /* additional constraint by language */
664 CFCharacterSetRef cf_charset;
665 CFStringRef cf_charset_string;
666 } cf_charset_table[] =
667 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
668 { "iso8859-2", { 0x00A0, 0x010E }},
669 { "iso8859-3", { 0x00A0, 0x0108 }},
670 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
671 { "iso8859-5", { 0x00A0, 0x0401 }},
672 { "iso8859-6", { 0x00A0, 0x060C }},
673 { "iso8859-7", { 0x00A0, 0x0384 }},
674 { "iso8859-8", { 0x00A0, 0x05D0 }},
675 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
676 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
677 { "iso8859-11", { 0x00A0, 0x0E01 }},
678 { "iso8859-13", { 0x00A0, 0x201C }},
679 { "iso8859-14", { 0x00A0, 0x0174 }},
680 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
681 { "iso8859-16", { 0x00A0, 0x0218}},
682 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
683 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
684 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
685 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
686 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
687 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
688 { "cns11643.1992-3", { 0x201A9 }},
689 { "cns11643.1992-4", { 0x20057 }},
690 { "cns11643.1992-5", { 0x20000 }},
691 { "cns11643.1992-6", { 0x20003 }},
692 { "cns11643.1992-7", { 0x20055 }},
693 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
694 { "jisx0212.1990-0", { 0x4E44 }},
695 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
696 { "jisx0213.2000-2", { 0xFA49 }},
697 { "jisx0213.2004-1", { 0x20B9F }},
698 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
699 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
700 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
701 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
702 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
703 { "unicode-sip", { 0x20000 }},
707 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
710 CFStringRef language;
711 CFStringRef font_names[3];
712 } macfont_language_default_font_names[] = {
713 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
714 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
716 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
717 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
719 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
720 CFSTR ("STXihei"), /* 10.4 - 10.5 */
722 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
723 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
729 static CGFloat macfont_antialias_threshold;
732 macfont_update_antialias_threshold (void)
738 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
739 kCFPreferencesCurrentApplication,
742 macfont_antialias_threshold = threshold;
745 static inline Lisp_Object
746 macfont_intern_prop_cfstring (CFStringRef cfstring)
748 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
750 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
753 static inline CFIndex
754 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
765 unichars[0] = (c >> 10) + 0xD800;
766 unichars[1] = (c & 0x3FF) + 0xDC00;
773 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
774 FontSymbolicTraits *sym_traits)
778 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
779 OS X 10.6 when the value is greater than or equal to 1 << 31. */
780 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
782 *sym_traits = (FontSymbolicTraits) sint64_value;
791 macfont_store_descriptor_attributes (FontDescriptorRef desc,
792 Lisp_Object spec_or_entity)
795 CFDictionaryRef dict;
799 str = mac_font_descriptor_copy_attribute (desc,
800 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
803 ASET (spec_or_entity, FONT_FAMILY_INDEX,
804 macfont_intern_prop_cfstring (str));
807 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
811 enum font_property_index index;
815 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
816 {{-0.4, 50}, /* light */
817 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
818 {0, 100}, /* normal */
819 {0.24, 140}, /* (semi-bold + normal) / 2 */
820 {0.4, 200}, /* bold */
821 {CGFLOAT_MAX, CGFLOAT_MAX}}},
822 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
823 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
824 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
825 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
828 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
830 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
831 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
833 CGPoint *point = numeric_traits[i].points;
835 while (point->x < floatval)
837 if (point == numeric_traits[i].points)
839 else if (point->x == CGFLOAT_MAX)
841 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
842 * ((point->y - (point - 1)->y)
843 / (point->x - (point - 1)->x)));
844 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
845 make_number (lround (floatval)));
849 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
852 FontSymbolicTraits sym_traits;
855 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
856 spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
857 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
858 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
863 num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
864 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
865 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
867 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
873 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
874 FontSymbolicTraits synth_sym_traits)
877 CFDictionaryRef dict;
878 FontSymbolicTraits sym_traits = 0;
881 entity = font_make_entity ();
883 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
884 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
886 macfont_store_descriptor_attributes (desc, entity);
888 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
891 CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
894 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
897 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
898 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
899 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
900 name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
901 font_put_extra (entity, QCfont_entity,
902 make_save_ptr_int ((void *) name, sym_traits));
903 if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
904 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
905 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
906 if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
907 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
908 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
909 if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
910 ASET (entity, FONT_SPACING_INDEX,
911 make_number (FONT_SPACING_SYNTHETIC_MONO));
917 macfont_create_family_with_symbol (Lisp_Object symbol)
919 static CFArrayRef families = NULL;
920 CFStringRef result = NULL, family_name;
921 int using_cache_p = 1;
922 CFComparatorFunction family_name_comparator;
924 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
925 if (family_name == NULL)
928 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
929 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
930 if (CTFontManagerCompareFontFamilyNames != NULL)
933 family_name_comparator = CTFontManagerCompareFontFamilyNames;
935 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
936 else /* CTFontManagerCompareFontFamilyNames == NULL */
938 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
939 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
941 family_name_comparator = mac_font_family_compare;
945 if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
946 == kCFCompareEqualTo)
947 result = CFSTR ("LastResort");
953 if (families == NULL)
955 families = mac_font_create_available_families ();
957 if (families == NULL)
961 count = CFArrayGetCount (families);
962 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
963 (const void *) family_name,
964 family_name_comparator, NULL);
967 CFStringRef name = CFArrayGetValueAtIndex (families, i);
969 if ((*family_name_comparator) (name, family_name, NULL)
970 == kCFCompareEqualTo)
971 result = CFRetain (name);
974 if (result || !using_cache_p)
978 CFRelease (families);
983 CFRelease (family_name);
988 #define WIDTH_FRAC_BITS (4)
989 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
991 struct macfont_metrics
993 unsigned char lbearing_low, rbearing_low;
994 signed lbearing_high : 4, rbearing_high : 4;
995 unsigned char ascent_low, descent_low;
996 signed ascent_high : 4, descent_high : 4;
998 /* These two members are used for fixed-point representation of
999 glyph width. The `width_int' member is an integer that is
1000 closest to the width. The `width_frac' member is the fractional
1001 adjustment representing a value in [-.5, .5], multiplied by
1002 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
1003 the advance delta for centering instead of the glyph width. */
1004 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
1007 #define METRICS_VALUE(metrics, member) \
1008 (((metrics)->member##_high << 8) | (metrics)->member##_low)
1009 #define METRICS_SET_VALUE(metrics, member, value) \
1010 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
1011 (metrics)->member##_high = tmp >> 8;} while (0)
1015 METRICS_INVALID = -1, /* metrics entry is invalid */
1016 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1019 #define METRICS_STATUS(metrics) \
1020 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1021 #define METRICS_SET_STATUS(metrics, status) \
1022 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1023 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1025 #define METRICS_NCOLS_PER_ROW (128)
1026 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1027 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1030 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1031 struct font_metrics *metrics, CGFloat *advance_delta,
1032 int force_integral_p)
1034 struct macfont_info *macfont_info = (struct macfont_info *) font;
1035 FontRef macfont = macfont_info->macfont;
1037 struct macfont_metrics *cache;
1040 row = glyph / METRICS_NCOLS_PER_ROW;
1041 col = glyph % METRICS_NCOLS_PER_ROW;
1042 if (row >= macfont_info->metrics_nrows)
1044 macfont_info->metrics =
1045 xrealloc (macfont_info->metrics,
1046 sizeof (struct macfont_metrics *) * (row + 1));
1047 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1048 (sizeof (struct macfont_metrics *)
1049 * (row + 1 - macfont_info->metrics_nrows)));
1050 macfont_info->metrics_nrows = row + 1;
1052 if (macfont_info->metrics[row] == NULL)
1054 struct macfont_metrics *new;
1057 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1058 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1059 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1060 macfont_info->metrics[row] = new;
1062 cache = macfont_info->metrics[row] + col;
1064 if (METRICS_STATUS (cache) == METRICS_INVALID)
1068 if (macfont_info->screen_font)
1069 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1071 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1073 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1074 advance delta value. */
1075 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1076 fwidth = (font->pixel_size - fwidth) / 2;
1077 cache->width_int = lround (fwidth);
1078 cache->width_frac = lround ((fwidth - cache->width_int)
1079 * WIDTH_FRAC_SCALE);
1080 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1082 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1083 width = font->pixel_size;
1085 width = cache->width_int;
1089 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1091 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1093 if (macfont_info->synthetic_italic_p)
1095 /* We assume the members a, b, c, and d in
1096 synthetic_italic_atfm are non-negative. */
1098 CGPointApplyAffineTransform (bounds.origin,
1099 synthetic_italic_atfm);
1101 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1103 if (macfont_info->synthetic_bold_p)
1106 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1108 bounds = CGRectInset (bounds, d, d);
1110 switch (macfont_info->spacing)
1112 case MACFONT_SPACING_PROPORTIONAL:
1113 bounds.origin.x += - (cache->width_frac
1114 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1116 case MACFONT_SPACING_MONO:
1118 case MACFONT_SPACING_SYNTHETIC_MONO:
1119 bounds.origin.x += (cache->width_int
1120 + (cache->width_frac
1121 / (CGFloat) WIDTH_FRAC_SCALE));
1124 if (bounds.size.width > 0)
1126 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1127 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1128 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1130 bounds = CGRectIntegral (bounds);
1131 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1132 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1133 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1134 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1136 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1137 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1138 metrics->width = width;
1139 metrics->ascent = METRICS_VALUE (cache, ascent);
1140 metrics->descent = METRICS_VALUE (cache, descent);
1145 switch (macfont_info->spacing)
1147 case MACFONT_SPACING_PROPORTIONAL:
1148 *advance_delta = (force_integral_p ? 0
1149 : - (cache->width_frac
1150 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1152 case MACFONT_SPACING_MONO:
1155 case MACFONT_SPACING_SYNTHETIC_MONO:
1156 *advance_delta = (force_integral_p ? cache->width_int
1158 + (cache->width_frac
1159 / (CGFloat) WIDTH_FRAC_SCALE)));
1167 static CFMutableDictionaryRef macfont_cache_dictionary;
1169 /* Threshold used in row_nkeys_or_perm. This must be less than or
1170 equal to the number of rows that are invalid as BMP (i.e., from
1171 U+D800 to U+DFFF). */
1172 #define ROW_PERM_OFFSET (8)
1174 /* The number of glyphs that can be stored in a value for a single
1175 entry of CFDictionary. */
1176 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1178 struct macfont_cache
1180 int reference_count;
1181 CFCharacterSetRef cf_charset;
1183 /* The cached glyph for a BMP character c is stored in
1184 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1185 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1186 unsigned char row_nkeys_or_perm[256];
1189 /* Number of rows for which the BMP cache is allocated so far.
1190 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1193 /* The cached glyph for a character c is stored as the (c %
1194 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1195 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1196 not stored here if row_nkeys_or_perm[c / 256] >=
1198 CFMutableDictionaryRef dictionary;
1202 /* UVS (Unicode Variation Sequence) subtable data, which is of
1203 type CFDataRef if available. NULL means it is not initialized
1204 yet. kCFNull means the subtable is not found and there is no
1205 suitable fallback table for this font. */
1208 /* Character collection specifying the destination of the mapping
1209 provided by `table' above. If `table' is obtained from the UVS
1210 subtable in the font cmap table, then the value of this member
1211 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1212 CharacterCollection collection;
1216 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1217 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1218 static void macfont_release_cache (struct macfont_cache *);
1219 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1220 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1221 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1222 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1223 CharacterCollection, CGFontIndex);
1224 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1226 static struct macfont_cache *
1227 macfont_lookup_cache (CFStringRef key)
1229 struct macfont_cache *cache;
1231 if (macfont_cache_dictionary == NULL)
1233 macfont_cache_dictionary =
1234 CFDictionaryCreateMutable (NULL, 0,
1235 &kCFTypeDictionaryKeyCallBacks, NULL);
1239 cache = ((struct macfont_cache *)
1240 CFDictionaryGetValue (macfont_cache_dictionary, key));
1244 FontRef macfont = mac_font_create_with_name (key, 0);
1248 cache = xzalloc (sizeof (struct macfont_cache));
1249 /* Treat the LastResort font as if it contained glyphs for
1250 all characters. This may look too rough, but neither
1251 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1252 for this font is correct for non-BMP characters on Mac OS
1254 if (CFEqual (key, CFSTR ("LastResort")))
1256 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1259 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1261 if (cache->cf_charset == NULL)
1262 cache->cf_charset = mac_font_copy_character_set (macfont);
1263 CFDictionaryAddValue (macfont_cache_dictionary, key,
1264 (const void *) cache);
1265 CFRelease (macfont);
1272 static struct macfont_cache *
1273 macfont_retain_cache (struct macfont_cache *cache)
1275 cache->reference_count++;
1281 macfont_release_cache (struct macfont_cache *cache)
1283 if (--cache->reference_count == 0)
1287 for (i = 0; i < cache->glyph.nrows; i++)
1288 xfree (cache->glyph.matrix[i]);
1289 xfree (cache->glyph.matrix);
1290 if (cache->glyph.dictionary)
1291 CFRelease (cache->glyph.dictionary);
1292 memset (&cache->glyph, 0, sizeof (cache->glyph));
1293 if (cache->uvs.table)
1294 CFRelease (cache->uvs.table);
1295 memset (&cache->uvs, 0, sizeof (cache->uvs));
1299 static CFCharacterSetRef
1300 macfont_get_cf_charset (struct font *font)
1302 struct macfont_info *macfont_info = (struct macfont_info *) font;
1304 return macfont_info->cache->cf_charset;
1307 static CFCharacterSetRef
1308 macfont_get_cf_charset_for_name (CFStringRef name)
1310 struct macfont_cache *cache = macfont_lookup_cache (name);
1312 return cache->cf_charset;
1316 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1318 struct macfont_info *macfont_info = (struct macfont_info *) font;
1319 FontRef macfont = macfont_info->macfont;
1320 struct macfont_cache *cache = macfont_info->cache;
1322 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1325 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1327 if (nkeys_or_perm < ROW_PERM_OFFSET)
1329 UniChar unichars[256], ch;
1333 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1334 dispatch_queue_t queue;
1335 dispatch_group_t group = NULL;
1342 CFMutableDictionaryRef dictionary;
1343 uintptr_t key, value;
1347 if (cache->glyph.dictionary == NULL)
1348 cache->glyph.dictionary =
1349 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1350 dictionary = cache->glyph.dictionary;
1351 key = c / NGLYPHS_IN_VALUE;
1352 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1353 value = ((uintptr_t)
1354 CFDictionaryGetValue (dictionary, (const void *) key));
1355 glyph = (value >> nshifts);
1359 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1362 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1365 glyph = kCGFontIndexInvalid;
1368 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1369 value |= ((uintptr_t) glyph << nshifts);
1370 CFDictionarySetValue (dictionary, (const void *) key,
1371 (const void *) value);
1376 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1378 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1379 group = dispatch_group_create ();
1380 dispatch_group_async (group, queue, ^{
1384 nkeys = nkeys_or_perm;
1385 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1386 if (CFDictionaryContainsKey (dictionary,
1387 (const void *) key))
1389 CFDictionaryRemoveValue (dictionary,
1390 (const void *) key);
1394 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1400 for (i = 0; i < 256; i++)
1403 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1404 unichars[len++] = ch;
1407 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1410 mac_font_get_glyphs_for_characters (macfont, unichars,
1414 int next = unichars[len - 1] % 256;
1417 glyphs[i] = kCGFontIndexInvalid;
1420 glyphs[i] = glyphs[len];
1427 glyphs[i] = kCGFontIndexInvalid;
1429 nrows = cache->glyph.nrows;
1430 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1431 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1433 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1434 sizeof (CGGlyph *) * nrows);
1435 cache->glyph.matrix[nrows - 1] = glyphs;
1436 cache->glyph.nrows = nrows;
1438 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1441 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1442 dispatch_release (group);
1447 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1451 uintptr_t key, value;
1455 if (cache->glyph.dictionary == NULL)
1456 cache->glyph.dictionary =
1457 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1458 key = c / NGLYPHS_IN_VALUE;
1459 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1460 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1461 (const void *) key);
1462 glyph = (value >> nshifts);
1465 UniChar unichars[2];
1467 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1469 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1473 glyph = kCGFontIndexInvalid;
1475 value |= ((uintptr_t) glyph << nshifts);
1476 CFDictionarySetValue (cache->glyph.dictionary,
1477 (const void *) key, (const void *) value);
1485 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1488 struct macfont_info *macfont_info = (struct macfont_info *) font;
1489 FontRef macfont = macfont_info->macfont;
1492 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1496 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1498 struct macfont_info *macfont_info = (struct macfont_info *) font;
1499 FontRef macfont = macfont_info->macfont;
1500 struct macfont_cache *cache = macfont_info->cache;
1501 CFDataRef result = NULL;
1503 if (cache->uvs.table == NULL)
1505 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1506 CharacterCollection uvs_collection =
1507 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1509 if (uvs_table == NULL
1510 && mac_font_get_glyph_for_cid (macfont,
1511 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1512 6480) != kCGFontIndexInvalid)
1514 /* If the glyph for U+4E55 is accessible via its CID 6480,
1515 then we use the Adobe-Japan1 UVS table, which maps a
1516 variation sequence to a CID, as a fallback. */
1517 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1519 if (mac_uvs_table_adobe_japan1 == NULL)
1520 mac_uvs_table_adobe_japan1 =
1521 CFDataCreateWithBytesNoCopy (NULL,
1522 mac_uvs_table_adobe_japan1_bytes,
1523 sizeof (mac_uvs_table_adobe_japan1_bytes),
1525 if (mac_uvs_table_adobe_japan1)
1527 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1528 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1531 if (uvs_table == NULL)
1532 cache->uvs.table = kCFNull;
1534 cache->uvs.table = uvs_table;
1535 cache->uvs.collection = uvs_collection;
1538 if (cache->uvs.table != kCFNull)
1540 result = cache->uvs.table;
1541 *collection = cache->uvs.collection;
1547 static Lisp_Object macfont_get_cache (struct frame *);
1548 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1549 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1550 static Lisp_Object macfont_list_family (struct frame *);
1551 static void macfont_free_entity (Lisp_Object);
1552 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1553 static void macfont_close (struct font *);
1554 static int macfont_has_char (Lisp_Object, int);
1555 static unsigned macfont_encode_char (struct font *, int);
1556 static int macfont_text_extents (struct font *, unsigned int *, int,
1557 struct font_metrics *);
1558 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1559 static Lisp_Object macfont_shape (Lisp_Object);
1560 static int macfont_variation_glyphs (struct font *, int c,
1561 unsigned variations[256]);
1562 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1564 static struct font_driver macfont_driver =
1566 LISP_INITIALLY_ZERO, /* Qmac_ct */
1567 0, /* case insensitive */
1571 macfont_list_family,
1572 macfont_free_entity,
1575 NULL, /* prepare_face */
1576 NULL, /* done_face */
1578 macfont_encode_char,
1579 macfont_text_extents,
1581 NULL, /* get_bitmap */
1582 NULL, /* free_bitmap */
1583 NULL, /* get_outline */
1584 NULL, /* free_outline */
1585 NULL, /* anchor_point */
1586 NULL, /* otf_capability */
1587 NULL, /* otf_drive */
1588 NULL, /* start_for_frame */
1589 NULL, /* end_for_frame */
1592 macfont_variation_glyphs,
1593 macfont_filter_properties,
1597 macfont_get_cache (struct frame * f)
1599 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1601 return (dpyinfo->name_list_element);
1605 macfont_get_charset (Lisp_Object registry)
1607 char *str = SSDATA (SYMBOL_NAME (registry));
1608 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1612 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1616 else if (str[i] == '*')
1623 regexp = make_unibyte_string (re, j);
1624 for (i = 0; cf_charset_table[i].name; i++)
1625 if (fast_c_string_match_ignore_case
1626 (regexp, cf_charset_table[i].name,
1627 strlen (cf_charset_table[i].name)) >= 0)
1629 if (! cf_charset_table[i].name)
1631 if (! cf_charset_table[i].cf_charset)
1633 int *uniquifier = cf_charset_table[i].uniquifier;
1634 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1637 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1641 for (j = 0; uniquifier[j]; j++)
1643 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1645 CFCharacterSetAddCharactersInRange (charset,
1646 CFRangeMake (uniquifier[j], 1));
1649 string = CFStringCreateWithCharacters (NULL, unichars, count);
1652 CFRelease (charset);
1655 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1657 CFRelease (charset);
1658 /* CFCharacterSetCreateWithCharactersInString does not handle
1659 surrogate pairs properly as of Mac OS X 10.5. */
1660 cf_charset_table[i].cf_charset_string = string;
1668 unsigned int script_tag, langsys_tag;
1670 unsigned int *features[2];
1673 #define OTF_SYM_TAG(SYM, TAG) \
1675 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1676 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1679 #define OTF_TAG_STR(TAG, P) \
1681 (P)[0] = (char) (TAG >> 24); \
1682 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1683 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1684 (P)[3] = (char) (TAG & 0xFF); \
1688 static struct OpenTypeSpec *
1689 macfont_get_open_type_spec (Lisp_Object otf_spec)
1691 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1698 spec->script = XCAR (otf_spec);
1699 if (! NILP (spec->script))
1701 OTF_SYM_TAG (spec->script, spec->script_tag);
1702 val = assq_no_quit (spec->script, Votf_script_alist);
1703 if (CONSP (val) && SYMBOLP (XCDR (val)))
1704 spec->script = XCDR (val);
1706 spec->script = Qnil;
1709 spec->script_tag = 0x44464C54; /* "DFLT" */
1710 otf_spec = XCDR (otf_spec);
1711 spec->langsys_tag = 0;
1712 if (! NILP (otf_spec))
1714 val = XCAR (otf_spec);
1716 OTF_SYM_TAG (val, spec->langsys_tag);
1717 otf_spec = XCDR (otf_spec);
1719 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1720 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1724 val = XCAR (otf_spec);
1727 len = Flength (val);
1729 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1731 : malloc (XINT (len) * sizeof *spec->features[i]));
1732 if (! spec->features[i])
1734 if (i > 0 && spec->features[0])
1735 free (spec->features[0]);
1739 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1741 if (NILP (XCAR (val)))
1747 OTF_SYM_TAG (XCAR (val), tag);
1748 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1751 spec->nfeatures[i] = j;
1756 static CFMutableDictionaryRef
1757 macfont_create_attributes_with_spec (Lisp_Object spec)
1759 Lisp_Object tmp, extra;
1760 CFMutableArrayRef langarray = NULL;
1761 CFCharacterSetRef charset = NULL;
1762 CFStringRef charset_string = NULL;
1763 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1764 Lisp_Object script = Qnil;
1765 Lisp_Object registry;
1766 int cf_charset_idx, i;
1767 struct OpenTypeSpec *otspec = NULL;
1769 enum font_property_index index;
1772 } numeric_traits[] =
1773 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1774 {{-0.4, 50}, /* light */
1775 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1776 {0, 100}, /* normal */
1777 {0.24, 140}, /* (semi-bold + normal) / 2 */
1778 {0.4, 200}, /* bold */
1779 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1780 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1781 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1782 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1783 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1785 registry = AREF (spec, FONT_REGISTRY_INDEX);
1787 || EQ (registry, Qascii_0)
1788 || EQ (registry, Qiso10646_1)
1789 || EQ (registry, Qunicode_bmp))
1790 cf_charset_idx = -1;
1795 cf_charset_idx = macfont_get_charset (registry);
1796 if (cf_charset_idx < 0)
1798 charset = cf_charset_table[cf_charset_idx].cf_charset;
1799 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1800 lang = cf_charset_table[cf_charset_idx].lang;
1803 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1806 CFArrayAppendValue (langarray, lang);
1810 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1811 CONSP (extra); extra = XCDR (extra))
1813 Lisp_Object key, val;
1816 key = XCAR (tmp), val = XCDR (tmp);
1817 if (EQ (key, QClang))
1820 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1825 for (; CONSP (val); val = XCDR (val))
1826 if (SYMBOLP (XCAR (val)))
1829 cfstring_create_with_string_noencode (SYMBOL_NAME
1834 CFArrayAppendValue (langarray, lang);
1838 else if (EQ (key, QCotf))
1840 otspec = macfont_get_open_type_spec (val);
1843 script = otspec->script;
1845 else if (EQ (key, QCscript))
1849 if (! NILP (script) && ! charset)
1851 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1853 if (CONSP (chars) && CONSP (CDR (chars)))
1855 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1856 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1858 if (! string || !cs)
1866 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1867 if (CHARACTERP (XCAR (chars)))
1869 UniChar unichars[2];
1871 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1873 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1875 CFStringAppendCharacters (string, unichars, count);
1876 CFCharacterSetAddCharactersInRange (cs, range);
1879 /* CFCharacterSetCreateWithCharactersInString does not
1880 handle surrogate pairs properly as of Mac OS X 10.5. */
1881 charset_string = string;
1885 attributes = CFDictionaryCreateMutable (NULL, 0,
1886 &kCFTypeDictionaryKeyCallBacks,
1887 &kCFTypeDictionaryValueCallBacks);
1891 tmp = AREF (spec, FONT_FAMILY_INDEX);
1892 if (SYMBOLP (tmp) && ! NILP (tmp))
1894 CFStringRef family = macfont_create_family_with_symbol (tmp);
1898 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1903 traits = CFDictionaryCreateMutable (NULL, 4,
1904 &kCFTypeDictionaryKeyCallBacks,
1905 &kCFTypeDictionaryValueCallBacks);
1909 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1911 tmp = AREF (spec, numeric_traits[i].index);
1914 CGPoint *point = numeric_traits[i].points;
1915 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1918 while (point->y < floatval)
1920 if (point == numeric_traits[i].points)
1922 else if (point->y == CGFLOAT_MAX)
1924 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1925 * ((point->x - (point - 1)->x)
1926 / (point->y - (point - 1)->y)));
1929 else if (floatval < -1.0)
1931 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1934 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1938 if (CFDictionaryGetCount (traits))
1939 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1942 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1945 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1948 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1955 CFRelease (attributes);
1960 if (langarray) CFRelease (langarray);
1961 if (charset && cf_charset_idx < 0) CFRelease (charset);
1962 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1963 if (traits) CFRelease (traits);
1966 if (otspec->nfeatures[0] > 0)
1967 free (otspec->features[0]);
1968 if (otspec->nfeatures[1] > 0)
1969 free (otspec->features[1]);
1977 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1978 CFCharacterSetRef charset,
1980 CFArrayRef languages)
1982 Boolean result = true;
1984 if (charset || VECTORP (chars))
1986 CFCharacterSetRef desc_charset =
1987 mac_font_descriptor_copy_attribute (desc,
1988 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1990 if (desc_charset == NULL)
1995 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1996 else /* VECTORP (chars) */
2000 for (j = 0; j < ASIZE (chars); j++)
2001 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2002 && CFCharacterSetIsLongCharacterMember (desc_charset,
2003 XFASTINT (AREF (chars, j))))
2005 if (j == ASIZE (chars))
2008 CFRelease (desc_charset);
2011 if (result && languages)
2012 result = mac_font_descriptor_supports_languages (desc, languages);
2018 macfont_closest_traits_index (CFArrayRef traits_array,
2019 FontSymbolicTraits target)
2021 CFIndex i, result = -1, count = CFArrayGetCount (traits_array);
2022 int min_distance = (1 << 3);
2024 for (i = 0; i < count; i++)
2026 FontSymbolicTraits traits, diff;
2029 traits = ((FontSymbolicTraits) (uintptr_t)
2030 CFArrayGetValueAtIndex (traits_array, i));
2031 diff = (target ^ traits);
2032 /* We prefer synthetic bold of italic to synthetic italic of
2033 bold when both bold and italic are available but bold-italic
2034 is not available. */
2035 if (diff & MAC_FONT_TRAIT_BOLD)
2036 distance |= (1 << 0);
2037 if (diff & MAC_FONT_TRAIT_ITALIC)
2038 distance |= (1 << 1);
2039 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2040 distance |= (1 << 2);
2041 if (distance < min_distance)
2043 min_distance = distance;
2052 macfont_list (struct frame *f, Lisp_Object spec)
2054 Lisp_Object val = Qnil, family, extra;
2056 CFStringRef family_name = NULL;
2057 CFMutableDictionaryRef attributes = NULL, traits;
2058 Lisp_Object chars = Qnil;
2060 FontSymbolicTraits synth_sym_traits = 0;
2061 CFArrayRef families;
2062 CFIndex families_count;
2063 CFCharacterSetRef charset = NULL;
2064 CFArrayRef languages = NULL;
2068 family = AREF (spec, FONT_FAMILY_INDEX);
2069 if (! NILP (family))
2071 family_name = macfont_create_family_with_symbol (family);
2072 if (family_name == NULL)
2076 attributes = macfont_create_attributes_with_spec (spec);
2080 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2082 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2083 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2085 traits = ((CFMutableDictionaryRef)
2086 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2088 n = FONT_SLANT_NUMERIC (spec);
2089 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2091 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2093 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2096 n = FONT_WEIGHT_NUMERIC (spec);
2097 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2099 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2101 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2105 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2107 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2109 if (CFStringHasPrefix (language, CFSTR ("ja"))
2110 || CFStringHasPrefix (language, CFSTR ("ko"))
2111 || CFStringHasPrefix (language, CFSTR ("zh")))
2112 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2115 /* Create array of families. */
2117 families = CFArrayCreate (NULL, (const void **) &family_name,
2118 1, &kCFTypeArrayCallBacks);
2121 CFStringRef pref_family;
2122 CFIndex families_count, pref_family_index = -1;
2124 families = mac_font_create_available_families ();
2125 if (families == NULL)
2128 families_count = CFArrayGetCount (families);
2130 /* Move preferred family to the front if exists. */
2132 mac_font_create_preferred_family_for_attributes (attributes);
2136 CFArrayGetFirstIndexOfValue (families,
2137 CFRangeMake (0, families_count),
2139 CFRelease (pref_family);
2141 if (pref_family_index > 0)
2143 CFMutableArrayRef mutable_families =
2144 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2146 if (mutable_families)
2148 CFArrayAppendValue (mutable_families,
2149 CFArrayGetValueAtIndex (families,
2150 pref_family_index));
2151 CFArrayAppendArray (mutable_families, families,
2152 CFRangeMake (0, pref_family_index));
2153 if (pref_family_index + 1 < families_count)
2154 CFArrayAppendArray (mutable_families, families,
2155 CFRangeMake (pref_family_index + 1,
2157 - (pref_family_index + 1)));
2158 CFRelease (families);
2159 families = mutable_families;
2164 charset = CFDictionaryGetValue (attributes,
2165 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2169 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2173 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2176 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2177 if (CONSP (val) && VECTORP (XCDR (val)))
2185 CFRetain (languages);
2186 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2190 extra = AREF (spec, FONT_EXTRA_INDEX);
2191 families_count = CFArrayGetCount (families);
2192 for (i = 0; i < families_count; i++)
2194 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2195 FontDescriptorRef pat_desc;
2197 CFIndex descs_count;
2198 CFMutableArrayRef filtered_descs, traits_array;
2202 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2204 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2208 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2209 10.7 returns NULL if pat_desc represents the LastResort font.
2210 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2211 trailing "s") for such a font. */
2212 if (!CFEqual (family_name, CFSTR ("LastResort")))
2213 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2217 FontDescriptorRef lr_desc =
2218 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2222 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2223 &kCFTypeArrayCallBacks);
2224 CFRelease (lr_desc);
2229 CFRelease (pat_desc);
2233 descs_count = CFArrayGetCount (descs);
2234 if (descs_count == 0
2235 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2244 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2245 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2246 for (j = 0; j < descs_count; j++)
2248 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2249 CFDictionaryRef dict;
2251 FontSymbolicTraits sym_traits;
2253 dict = mac_font_descriptor_copy_attribute (desc,
2254 MAC_FONT_TRAITS_ATTRIBUTE);
2258 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2261 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2265 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2266 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2267 != (spacing >= FONT_SPACING_MONO)))
2270 /* Don't use a color bitmap font unless its family is
2271 explicitly specified. */
2272 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2276 && !macfont_supports_charset_and_languages_p (desc, charset,
2280 CFArrayAppendValue (filtered_descs, desc);
2281 CFArrayAppendValue (traits_array,
2282 (const void *) (uintptr_t) sym_traits);
2286 descs = filtered_descs;
2287 descs_count = CFArrayGetCount (descs);
2289 for (j = 0; j < descs_count; j++)
2291 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2292 FontSymbolicTraits sym_traits =
2293 ((FontSymbolicTraits) (uintptr_t)
2294 CFArrayGetValueAtIndex (traits_array, j));
2295 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2297 mask_min = ((synth_sym_traits ^ sym_traits)
2298 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2299 if (FONT_SLANT_NUMERIC (spec) < 0)
2300 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2301 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2302 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2304 mask_max = (synth_sym_traits & ~sym_traits);
2305 /* Synthetic bold does not work for bitmap-only fonts on Mac
2307 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2309 CFNumberRef format =
2310 mac_font_descriptor_copy_attribute (desc,
2311 MAC_FONT_FORMAT_ATTRIBUTE);
2315 uint32_t format_val;
2317 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2319 && format_val == MAC_FONT_FORMAT_BITMAP)
2320 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2324 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2326 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2327 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2328 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2329 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2330 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2331 bmask += MAC_FONT_TRAIT_BOLD)
2332 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2333 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2334 imask += MAC_FONT_TRAIT_ITALIC)
2336 FontSymbolicTraits synth = (imask | bmask | mmask);
2339 || j == macfont_closest_traits_index (traits_array,
2340 (sym_traits | synth)))
2342 entity = macfont_descriptor_entity (desc, extra, synth);
2343 if (! NILP (entity))
2344 val = Fcons (entity, val);
2349 CFRelease (traits_array);
2353 CFRelease (families);
2354 val = Fnreverse (val);
2360 FONT_ADD_LOG ("macfont-list", spec, val);
2361 if (charset) CFRelease (charset);
2362 if (languages) CFRelease (languages);
2363 if (attributes) CFRelease (attributes);
2364 if (family_name) CFRelease (family_name);
2372 macfont_match (struct frame * frame, Lisp_Object spec)
2374 Lisp_Object entity = Qnil;
2375 CFMutableDictionaryRef attributes;
2376 FontDescriptorRef pat_desc = NULL, desc = NULL;
2380 attributes = macfont_create_attributes_with_spec (spec);
2383 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2384 CFRelease (attributes);
2388 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2390 CFRelease (pat_desc);
2394 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2400 FONT_ADD_LOG ("macfont-match", spec, entity);
2405 macfont_list_family (struct frame *frame)
2407 Lisp_Object list = Qnil;
2408 CFArrayRef families;
2412 families = mac_font_create_available_families ();
2415 CFIndex i, count = CFArrayGetCount (families);
2417 for (i = 0; i < count; i++)
2418 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2419 CFRelease (families);
2428 macfont_free_entity (Lisp_Object entity)
2430 Lisp_Object val = assq_no_quit (QCfont_entity,
2431 AREF (entity, FONT_EXTRA_INDEX));
2432 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2440 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2442 Lisp_Object val, font_object;
2443 CFStringRef font_name;
2444 struct macfont_info *macfont_info = NULL;
2448 FontSymbolicTraits sym_traits;
2450 int len, i, total_width;
2452 CGFloat ascent, descent, leading;
2454 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2456 || XTYPE (XCDR (val)) != Lisp_Misc
2457 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2459 font_name = XSAVE_POINTER (XCDR (val), 0);
2460 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2462 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2467 macfont = mac_font_create_with_name (font_name, size);
2470 int fontsize = (int) [((NSFont *) macfont) pointSize];
2471 if (fontsize != size) size = fontsize;
2477 font_object = font_make_object (VECSIZE (struct macfont_info), entity, size);
2478 ASET (font_object, FONT_TYPE_INDEX, macfont_driver.type);
2479 len = font_unparse_xlfd (entity, size, name, 256);
2481 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
2482 len = font_unparse_fcname (entity, size, name, 256);
2484 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
2486 ASET (font_object, FONT_FULLNAME_INDEX,
2487 AREF (font_object, FONT_NAME_INDEX));
2488 font = XFONT_OBJECT (font_object);
2489 font->pixel_size = size;
2490 font->driver = &macfont_driver;
2491 font->encoding_charset = font->repertory_charset = -1;
2495 macfont_info = (struct macfont_info *) font;
2496 macfont_info->macfont = macfont;
2497 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2499 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2500 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2501 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2504 macfont_info->screen_font = NULL;
2505 macfont_info->cache = macfont_lookup_cache (font_name);
2506 macfont_retain_cache (macfont_info->cache);
2507 macfont_info->metrics = NULL;
2508 macfont_info->metrics_nrows = 0;
2509 macfont_info->synthetic_italic_p = 0;
2510 macfont_info->synthetic_bold_p = 0;
2511 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2512 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2513 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2514 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2515 macfont_info->synthetic_italic_p = 1;
2516 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2517 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2518 macfont_info->synthetic_bold_p = 1;
2519 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2520 macfont_info->spacing = MACFONT_SPACING_MONO;
2521 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2522 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2523 == FONT_SPACING_SYNTHETIC_MONO))
2524 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2525 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2526 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2529 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2531 macfont_info->antialias =
2532 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2534 macfont_info->color_bitmap_p = 0;
2535 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2536 macfont_info->color_bitmap_p = 1;
2538 glyph = macfont_get_glyph_for_character (font, ' ');
2539 if (glyph != kCGFontIndexInvalid)
2540 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2542 /* dirty workaround */
2543 font->space_width = pixel_size;
2545 total_width = font->space_width;
2546 for (i = 1; i < 95; i++)
2548 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2549 if (glyph == kCGFontIndexInvalid)
2551 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2554 font->average_width = total_width / 95;
2556 font->average_width = font->space_width; /* XXX */
2558 if (!(macfont_info->screen_font
2559 && mac_screen_font_get_metrics (macfont_info->screen_font,
2560 &ascent, &descent, &leading)))
2562 CFStringRef family_name;
2564 ascent = mac_font_get_ascent (macfont);
2565 descent = mac_font_get_descent (macfont);
2566 leading = mac_font_get_leading (macfont);
2567 /* AppKit and WebKit do some adjustment to the heights of
2568 Courier, Helvetica, and Times. */
2569 family_name = mac_font_copy_family_name (macfont);
2572 if (CFEqual (family_name, CFSTR ("Courier"))
2573 || CFEqual (family_name, CFSTR ("Helvetica"))
2574 || CFEqual (family_name, CFSTR ("Times")))
2575 ascent += (ascent + descent) * .15f;
2576 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2581 CFRelease (family_name);
2584 font->ascent = ascent + 0.5f;
2585 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2586 if (CONSP (val) && !NILP (XCDR (val)))
2587 font->descent = descent + 0.5f;
2589 font->descent = descent + leading + 0.5f;
2590 font->height = font->ascent + font->descent;
2592 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2593 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2597 /* Unfortunately Xft doesn't provide a way to get minimum char
2598 width. So, we use space_width instead. */
2599 font->min_width = font->max_width = font->space_width; /* XXX */
2601 font->baseline_offset = 0;
2602 font->relative_compose = 0;
2603 font->default_ascent = 0;
2604 font->vertical_centering = 0;
2610 macfont_close (struct font *font)
2612 struct macfont_info *macfont_info = (struct macfont_info *) font;
2616 CFRelease (macfont_info->macfont);
2617 CGFontRelease (macfont_info->cgfont);
2618 if (macfont_info->screen_font)
2619 CFRelease (macfont_info->screen_font);
2620 macfont_release_cache (macfont_info->cache);
2621 for (i = 0; i < macfont_info->metrics_nrows; i++)
2622 if (macfont_info->metrics[i])
2623 xfree (macfont_info->metrics[i]);
2624 if (macfont_info->metrics)
2625 xfree (macfont_info->metrics);
2630 macfont_has_char (Lisp_Object font, int c)
2633 CFCharacterSetRef charset;
2636 if (FONT_ENTITY_P (font))
2641 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2643 name = XSAVE_POINTER (val, 0);
2644 charset = macfont_get_cf_charset_for_name (name);
2647 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2649 result = CFCharacterSetIsLongCharacterMember (charset, c);
2656 macfont_encode_char (struct font *font, int c)
2658 struct macfont_info *macfont_info = (struct macfont_info *) font;
2662 glyph = macfont_get_glyph_for_character (font, c);
2665 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2669 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2670 struct font_metrics *metrics)
2675 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2676 for (i = 1; i < nglyphs; i++)
2678 struct font_metrics m;
2679 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2684 if (width + m.lbearing < metrics->lbearing)
2685 metrics->lbearing = width + m.lbearing;
2686 if (width + m.rbearing > metrics->rbearing)
2687 metrics->rbearing = width + m.rbearing;
2688 if (m.ascent > metrics->ascent)
2689 metrics->ascent = m.ascent;
2690 if (m.descent > metrics->descent)
2691 metrics->descent = m.descent;
2698 metrics->width = width;
2704 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2705 bool with_background)
2707 struct frame * f = s->f;
2708 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2709 CGRect background_rect;
2710 CGPoint text_position;
2713 CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2714 bool no_antialias_p =
2715 (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2716 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2717 && font_size <= macfont_antialias_threshold));
2718 int len = to - from;
2719 struct face *face = s->face;
2720 CGContextRef context;
2724 if (with_background)
2725 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2726 s->width, FONT_HEIGHT (s->font));
2728 background_rect = CGRectNull;
2730 text_position = CGPointMake (x, -y);
2731 glyphs = xmalloc (sizeof (CGGlyph) * len);
2733 CGFloat advance_delta;
2735 CGFloat total_width = 0;
2737 positions = xmalloc (sizeof (CGPoint) * len);
2738 for (i = 0; i < len; i++)
2742 glyphs[i] = s->char2b[from + i];
2743 width = (s->padding_p ? 1
2744 : macfont_glyph_extents (s->font, glyphs[i],
2745 NULL, &advance_delta,
2747 positions[i].x = total_width + advance_delta;
2749 total_width += width;
2753 context = [[NSGraphicsContext currentContext] graphicsPort];
2754 CGContextSaveGState (context);
2756 if (!CGRectIsNull (background_rect))
2758 if (s->hl == DRAW_MOUSE_FACE)
2760 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2762 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2764 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2765 CGContextFillRects (context, &background_rect, 1);
2768 if (macfont_info->cgfont)
2770 CGAffineTransform atfm;
2771 CGContextScaleCTM (context, 1, -1);
2772 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2773 if (macfont_info->synthetic_italic_p)
2774 atfm = synthetic_italic_atfm;
2776 atfm = CGAffineTransformIdentity;
2777 if (macfont_info->synthetic_bold_p)
2779 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2780 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2781 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2784 CGContextSetShouldAntialias (context, false);
2786 CGContextSetTextMatrix (context, atfm);
2787 CGContextSetTextPosition (context, text_position.x, text_position.y);
2789 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2790 if (macfont_info->color_bitmap_p
2791 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2792 && CTFontDrawGlyphs != NULL
2798 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2803 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2805 CGContextSetFont (context, macfont_info->cgfont);
2806 CGContextSetFontSize (context, font_size);
2807 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2813 CGContextRestoreGState (context);
2821 macfont_shape (Lisp_Object lgstring)
2824 struct macfont_info *macfont_info;
2826 ptrdiff_t glyph_len, len, i, j;
2829 CFIndex *nonbmp_indices;
2832 struct mac_glyph_layout *glyph_layouts;
2834 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2835 macfont_info = (struct macfont_info *) font;
2836 macfont = macfont_info->macfont;
2838 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2840 for (i = 0; i < glyph_len; i++)
2842 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2846 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2852 if (INT_MAX / 2 < len)
2853 memory_full (SIZE_MAX);
2855 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2856 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2857 for (i = j = 0; i < len; i++)
2859 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2861 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2863 nonbmp_indices[j] = i + j;
2867 nonbmp_indices[j] = len + j; /* sentinel */
2871 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2875 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2876 if (macfont_info->screen_font)
2877 used = mac_screen_font_shape (macfont_info->screen_font, string,
2878 glyph_layouts, glyph_len);
2880 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2891 for (i = 0; i < used; i++)
2893 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2894 struct mac_glyph_layout *gl = glyph_layouts + i;
2896 struct font_metrics metrics;
2897 int xoff, yoff, wadjust;
2901 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2902 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2905 from = gl->comp_range.location;
2906 /* Convert UTF-16 index to UTF-32. */
2908 while (nonbmp_indices[j] < from)
2911 LGLYPH_SET_FROM (lglyph, from);
2913 to = gl->comp_range.location + gl->comp_range.length;
2914 /* Convert UTF-16 index to UTF-32. */
2915 while (nonbmp_indices[j] < to)
2918 LGLYPH_SET_TO (lglyph, to - 1);
2920 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2921 the composition is trivial. */
2925 if (unichars[gl->string_index] >= 0xD800
2926 && unichars[gl->string_index] < 0xDC00)
2927 c = (((unichars[gl->string_index] - 0xD800) << 10)
2928 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2930 c = unichars[gl->string_index];
2931 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2933 LGLYPH_SET_CHAR (lglyph, c);
2937 unsigned long cc = gl->glyph_id;
2938 LGLYPH_SET_CODE (lglyph, cc);
2941 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2942 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2943 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2944 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2945 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2946 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2948 xoff = lround (gl->advance_delta);
2949 yoff = lround (- gl->baseline_delta);
2950 wadjust = lround (gl->advance);
2951 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2955 vec = Fmake_vector (make_number (3), Qnil);
2956 ASET (vec, 0, make_number (xoff));
2957 ASET (vec, 1, make_number (yoff));
2958 ASET (vec, 2, make_number (wadjust));
2959 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2965 return make_number (used);
2968 /* Structures for the UVS subtable (format 14) in the cmap table. */
2969 typedef UInt8 UINT24[3];
2971 #pragma pack(push, 1)
2972 struct variation_selector_record
2974 UINT24 var_selector;
2975 UInt32 default_uvs_offset, non_default_uvs_offset;
2980 UInt32 length, num_var_selector_records;
2981 struct variation_selector_record variation_selector_records[1];
2983 #define SIZEOF_UVS_TABLE_HEADER \
2984 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2986 struct unicode_value_range
2988 UINT24 start_unicode_value;
2989 UInt8 additional_count;
2991 struct default_uvs_table {
2992 UInt32 num_unicode_value_ranges;
2993 struct unicode_value_range unicode_value_ranges[1];
2995 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2996 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
3000 UINT24 unicode_value;
3003 struct non_default_uvs_table
3005 UInt32 num_uvs_mappings;
3006 struct uvs_mapping uvs_mappings[1];
3008 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
3009 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
3012 /* Read big endian values. The argument LVAL must be an lvalue. */
3013 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3014 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3015 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3016 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3017 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3018 /* Succeeding one byte should also be accessible. */
3019 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3020 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3022 /* Return UVS subtable for the specified FONT. If the subtable is not
3023 found or ill-formatted, then return NULL. */
3026 mac_font_copy_uvs_table (FontRef font)
3028 CFDataRef cmap_table, uvs_table = NULL;
3030 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3033 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3034 struct uvs_table *uvs;
3035 struct variation_selector_record *records;
3036 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3039 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3043 cmap_len = CFDataGetLength (cmap_table);
3044 if (sizeof_sfntCMapHeader > cmap_len)
3047 ntables = BUINT16_VALUE (cmap->numTables);
3048 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3049 / sizeof_sfntCMapEncoding))
3052 for (i = 0; i < ntables; i++)
3053 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3054 == kFontUnicodePlatform)
3055 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3056 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3058 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3062 || uvs_offset > cmap_len
3063 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3066 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3067 uvs_len = BUINT32_VALUE (uvs->length);
3068 if (uvs_len > cmap_len - uvs_offset
3069 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3072 if (BUINT16_VALUE (uvs->format) != 14)
3075 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3076 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3077 / sizeof (struct variation_selector_record)))
3080 records = uvs->variation_selector_records;
3081 for (i = 0; i < nrecords; i++)
3083 UInt32 default_uvs_offset, non_default_uvs_offset;
3085 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3086 if (default_uvs_offset)
3088 struct default_uvs_table *default_uvs;
3091 if (default_uvs_offset > uvs_len
3092 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3093 > uvs_len - default_uvs_offset))
3096 default_uvs = ((struct default_uvs_table *)
3097 ((UInt8 *) uvs + default_uvs_offset));
3098 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3099 if (nranges > ((uvs_len - default_uvs_offset
3100 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3101 / sizeof (struct unicode_value_range)))
3103 /* Now 2 * nranges can't overflow, so we can safely use
3104 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3105 mac_font_get_glyphs_for_variants. */
3108 non_default_uvs_offset =
3109 BUINT32_VALUE (records[i].non_default_uvs_offset);
3110 if (non_default_uvs_offset)
3112 struct non_default_uvs_table *non_default_uvs;
3115 if (non_default_uvs_offset > uvs_len
3116 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3117 > uvs_len - non_default_uvs_offset))
3120 non_default_uvs = ((struct non_default_uvs_table *)
3121 ((UInt8 *) uvs + non_default_uvs_offset));
3122 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3123 if (nmappings > ((uvs_len - non_default_uvs_offset
3124 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3125 / sizeof (struct uvs_mapping)))
3127 /* Now 2 * nmappings can't overflow, so we can safely
3128 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3129 in mac_font_get_glyphs_for_variants. */
3133 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3136 CFRelease (cmap_table);
3142 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3143 sequence consisting of the given base character C and each
3144 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3145 result (explained below) into the corresponding GLYPHS[i]. If the
3146 entry is found in the Default UVS Table, then the result is 0. If
3147 the entry is found in the Non-Default UVS Table, then the result is
3148 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3149 elements in SELECTORS must be sorted in strictly increasing
3153 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3154 const UTF32Char selectors[], CGGlyph glyphs[],
3157 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3158 struct variation_selector_record *records = uvs->variation_selector_records;
3160 UInt32 ir, nrecords;
3161 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3162 dispatch_queue_t queue =
3163 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3164 dispatch_group_t group = dispatch_group_create ();
3167 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3170 while (i < count && ir < nrecords)
3172 UInt32 default_uvs_offset, non_default_uvs_offset;
3174 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3176 glyphs[i++] = kCGFontIndexInvalid;
3179 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3185 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3186 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3187 non_default_uvs_offset =
3188 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3189 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3190 dispatch_group_async (group, queue, ^{
3192 glyphs[i] = kCGFontIndexInvalid;
3194 if (default_uvs_offset)
3196 struct default_uvs_table *default_uvs =
3197 (struct default_uvs_table *) ((UInt8 *) uvs
3198 + default_uvs_offset);
3199 struct unicode_value_range *ranges =
3200 default_uvs->unicode_value_ranges;
3204 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3207 UInt32 mid = (lo + hi) / 2;
3209 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3215 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3216 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3220 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3222 struct non_default_uvs_table *non_default_uvs =
3223 (struct non_default_uvs_table *) ((UInt8 *) uvs
3224 + non_default_uvs_offset);
3225 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3229 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3232 UInt32 mid = (lo + hi) / 2;
3234 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3240 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3241 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3243 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3250 glyphs[i++] = kCGFontIndexInvalid;
3251 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3252 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3253 dispatch_release (group);
3258 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3260 CFDataRef uvs_table;
3261 CharacterCollection uvs_collection;
3265 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3269 UTF32Char selectors[256];
3270 CGGlyph glyphs[256];
3272 for (i = 0; i < 16; i++)
3273 selectors[i] = 0xFE00 + i;
3274 for (; i < 256; i++)
3275 selectors[i] = 0xE0100 + (i - 16);
3276 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3277 for (i = 0; i < 256; i++)
3279 CGGlyph glyph = glyphs[i];
3281 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3282 && glyph != kCGFontIndexInvalid)
3283 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3284 if (glyph == kCGFontIndexInvalid)
3288 variations[i] = (glyph ? glyph
3289 : macfont_get_glyph_for_character (font, c));
3299 static const char *const macfont_booleans[] = {
3305 static const char *const macfont_non_booleans[] = {
3313 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3315 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3319 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3320 CFArrayRef languages)
3322 Boolean result = true;
3323 CFArrayRef desc_languages =
3324 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3326 if (desc_languages == NULL)
3330 CFIndex desc_languages_count, i, languages_count;
3332 desc_languages_count = CFArrayGetCount (desc_languages);
3333 languages_count = CFArrayGetCount (languages);
3334 for (i = 0; i < languages_count; i++)
3335 if (!CFArrayContainsValue (desc_languages,
3336 CFRangeMake (0, desc_languages_count),
3337 CFArrayGetValueAtIndex (languages, i)))
3342 CFRelease (desc_languages);
3349 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3351 CFStringRef result = NULL;
3352 CFStringRef charset_string =
3353 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3355 if (charset_string && CFStringGetLength (charset_string) > 0)
3357 CFStringRef keys[] = {
3358 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3359 kCTLanguageAttributeName
3361 CFSTR ("NSLanguage")
3364 CFTypeRef values[] = {NULL};
3365 CFIndex num_values = 0;
3366 CFArrayRef languages
3367 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3369 if (languages && CFArrayGetCount (languages) > 0)
3371 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3372 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3375 CFCharacterSetRef charset =
3376 CFDictionaryGetValue (attributes,
3377 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3379 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3384 CFAttributedStringRef attr_string = NULL;
3385 CTLineRef ctline = NULL;
3386 CFDictionaryRef attrs
3387 = CFDictionaryCreate (NULL, (const void **) keys,
3388 (const void **) values, num_values,
3389 &kCFTypeDictionaryKeyCallBacks,
3390 &kCFTypeDictionaryValueCallBacks);
3394 attr_string = CFAttributedStringCreate (NULL, charset_string,
3400 ctline = CTLineCreateWithAttributedString (attr_string);
3401 CFRelease (attr_string);
3405 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3406 CFIndex i, nruns = CFArrayGetCount (runs);
3409 for (i = 0; i < nruns; i++)
3411 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3412 CFDictionaryRef attributes = CTRunGetAttributes (run);
3413 CTFontRef font_in_run;
3415 if (attributes == NULL)
3418 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3419 if (font_in_run == NULL)
3423 else if (!mac_ctfont_equal_in_postscript_name (font,
3427 if (nruns > 0 && i == nruns)
3428 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3437 static inline double
3438 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3440 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3444 static inline CGRect
3445 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3447 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3452 mac_ctfont_create_available_families (void)
3454 CFMutableArrayRef families = NULL;
3456 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3457 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3458 if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3461 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3465 CFIndex i, count = CFArrayGetCount (orig_families);
3467 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3469 for (i = 0; i < count; i++)
3471 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3473 if (!CFStringHasPrefix (family, CFSTR ("."))
3474 && (CTFontManagerCompareFontFamilyNames (family,
3475 CFSTR ("LastResort"),
3477 != kCFCompareEqualTo))
3478 CFArrayAppendValue (families, family);
3480 CFRelease (orig_families);
3483 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3484 else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3486 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3487 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3489 CTFontCollectionRef collection;
3490 CFArrayRef descs = NULL;
3492 collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3495 descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3496 CFRelease (collection);
3500 CFIndex i, count = CFArrayGetCount (descs);
3502 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3504 for (i = 0; i < count; i++)
3506 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3508 mac_font_descriptor_copy_attribute (desc,
3509 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3513 CFIndex p, limit = CFArrayGetCount (families);
3515 p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3516 (const void *) name,
3517 mac_font_family_compare, NULL);
3519 CFArrayAppendValue (families, name);
3520 else if (mac_font_family_compare
3521 (CFArrayGetValueAtIndex (families, p),
3522 name, NULL) != kCFCompareEqualTo)
3523 CFArrayInsertValueAtIndex (families, p, name);
3536 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3539 CFStringRef name1, name2;
3545 name1 = CTFontCopyPostScriptName (font1);
3548 name2 = CTFontCopyPostScriptName (font2);
3551 result = CFEqual (name1, name2);
3561 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3564 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3565 CFTypeRef values[] = {NULL, NULL};
3566 CFDictionaryRef attributes = NULL;
3567 CFAttributedStringRef attr_string = NULL;
3568 CTLineRef ctline = NULL;
3569 float float_zero = 0.0f;
3571 values[0] = macfont;
3572 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3575 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3576 (const void **) values,
3578 &kCFTypeDictionaryKeyCallBacks,
3579 &kCFTypeDictionaryValueCallBacks);
3580 CFRelease (values[1]);
3584 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3585 CFRelease (attributes);
3589 ctline = CTLineCreateWithAttributedString (attr_string);
3590 CFRelease (attr_string);
3594 /* Abandon if ctline contains some fonts other than the
3596 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3597 CFIndex i, nruns = CFArrayGetCount (runs);
3599 for (i = 0; i < nruns; i++)
3601 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3602 CFDictionaryRef attributes = CTRunGetAttributes (run);
3603 CTFontRef font_in_run;
3605 if (attributes == NULL)
3608 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3609 if (font_in_run == NULL)
3611 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3625 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3626 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3628 CFIndex used, result = 0;
3629 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3634 used = CTLineGetGlyphCount (ctline);
3635 if (used <= glyph_len)
3637 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3638 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3639 CGFloat total_advance = 0;
3640 CFIndex total_glyph_count = 0;
3642 for (k = 0; k < ctrun_count; k++)
3644 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3645 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3646 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3647 CFRange string_range, comp_range, range;
3648 CFIndex *permutation;
3650 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3651 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3655 #define RIGHT_TO_LEFT_P permutation
3657 /* Now the `comp_range' member of struct mac_glyph_layout is
3658 temporarily used as a work area such that:
3659 glbuf[i].comp_range.location =
3660 min {compRange[i + 1].location, ...,
3661 compRange[glyph_count - 1].location,
3662 maxRange (stringRangeForCTRun)}
3663 glbuf[i].comp_range.length = maxRange (compRange[i])
3664 where compRange[i] is the range of composed characters
3665 containing i-th glyph. */
3666 string_range = CTRunGetStringRange (ctrun);
3667 min_location = string_range.location + string_range.length;
3668 for (i = 0; i < glyph_count; i++)
3670 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3671 CFIndex glyph_index;
3674 if (!RIGHT_TO_LEFT_P)
3675 glyph_index = glyph_count - i - 1;
3678 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3681 CFStringGetRangeOfComposedCharactersAtIndex (string,
3683 gl->comp_range.location = min_location;
3684 gl->comp_range.length = rng.location + rng.length;
3685 if (rng.location < min_location)
3686 min_location = rng.location;
3689 /* Fill the `comp_range' member of struct mac_glyph_layout,
3690 and setup a permutation for right-to-left text. */
3691 comp_range = CFRangeMake (string_range.location, 0);
3692 range = CFRangeMake (0, 0);
3695 struct mac_glyph_layout *gl =
3696 glbuf + range.location + range.length;
3698 if (gl->comp_range.length
3699 > comp_range.location + comp_range.length)
3700 comp_range.length = gl->comp_range.length - comp_range.location;
3701 min_location = gl->comp_range.location;
3704 if (min_location >= comp_range.location + comp_range.length)
3706 comp_range.length = min_location - comp_range.location;
3707 for (i = 0; i < range.length; i++)
3709 glbuf[range.location + i].comp_range = comp_range;
3710 if (RIGHT_TO_LEFT_P)
3711 permutation[range.location + i] =
3712 range.location + range.length - i - 1;
3715 comp_range = CFRangeMake (min_location, 0);
3716 range.location += range.length;
3718 if (range.location == glyph_count)
3723 /* Then fill the remaining members. */
3724 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3727 struct mac_glyph_layout *gl;
3730 if (!RIGHT_TO_LEFT_P)
3731 gl = glbuf + range.location;
3736 src = glyph_count - 1 - range.location;
3737 dest = permutation[src];
3741 CFIndex tmp = gl->string_index;
3743 gl->string_index = glbuf[src].string_index;
3744 glbuf[src].string_index = tmp;
3747 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3749 CTRunGetPositions (ctrun, range, &position);
3750 gl->advance_delta = position.x - total_advance;
3751 gl->baseline_delta = position.y;
3752 gl->advance = (gl->advance_delta
3753 + CTRunGetTypographicBounds (ctrun, range,
3755 total_advance += gl->advance;
3758 if (RIGHT_TO_LEFT_P)
3759 xfree (permutation);
3761 #undef RIGHT_TO_LEFT_P
3763 total_glyph_count += glyph_count;
3773 /* The function below seems to cause a memory leak for the CFString
3774 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3775 10.6.3. For now, we use the NSGlyphInfo version instead. */
3776 #if USE_CT_GLYPH_INFO
3778 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3781 CGGlyph result = kCGFontIndexInvalid;
3782 UniChar characters[] = {0xfffd};
3784 CFAttributedStringRef attr_string = NULL;
3785 CTLineRef ctline = NULL;
3787 string = CFStringCreateWithCharacters (NULL, characters,
3788 ARRAYELTS (characters));
3792 CTGlyphInfoRef glyph_info =
3793 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3794 CFDictionaryRef attributes = NULL;
3798 CFStringRef keys[] = {kCTFontAttributeName,
3799 kCTGlyphInfoAttributeName};
3800 CFTypeRef values[] = {font, glyph_info};
3802 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3803 (const void **) values,
3805 &kCFTypeDictionaryKeyCallBacks,
3806 &kCFTypeDictionaryValueCallBacks);
3807 CFRelease (glyph_info);
3811 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3812 CFRelease (attributes);
3818 ctline = CTLineCreateWithAttributedString (attr_string);
3819 CFRelease (attr_string);
3823 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3825 if (CFArrayGetCount (runs) > 0)
3827 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3828 CFDictionaryRef attributes = CTRunGetAttributes (run);
3832 CTFontRef font_in_run =
3833 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3836 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3838 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3839 if (result >= CTFontGetGlyphCount (font))
3840 result = kCGFontIndexInvalid;
3851 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3853 mac_font_family_group (CFStringRef family)
3855 if (CFStringHasPrefix (family, CFSTR ("#")))
3861 range = CFStringFind (family, CFSTR ("Apple"),
3862 kCFCompareCaseInsensitive | kCFCompareAnchored);
3863 if (range.location != kCFNotFound)
3870 static CFComparisonResult
3871 mac_font_family_compare (const void *val1, const void *val2, void *context)
3873 CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3876 group1 = mac_font_family_group (family1);
3877 group2 = mac_font_family_group (family2);
3878 if (group1 < group2)
3879 return kCFCompareLessThan;
3880 if (group1 > group2)
3881 return kCFCompareGreaterThan;
3882 return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3884 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3887 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3889 CFArrayRef result = NULL;
3891 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3892 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3893 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3896 CTFontRef user_font =
3897 CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3901 CFArrayRef languages =
3902 CFArrayCreate (NULL, (const void **) &language, 1,
3903 &kCFTypeArrayCallBacks);
3907 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3909 CFRelease (languages);
3911 CFRelease (user_font);
3914 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3915 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3917 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3918 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3922 for (i = 0; macfont_language_default_font_names[i].language; i++)
3924 if (CFEqual (macfont_language_default_font_names[i].language,
3927 CFMutableArrayRef descriptors =
3928 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3935 macfont_language_default_font_names[i].font_names[j];
3938 CFDictionaryRef attributes =
3939 CFDictionaryCreate (NULL,
3941 &MAC_FONT_NAME_ATTRIBUTE),
3943 &macfont_language_default_font_names[i].font_names[j]),
3944 1, &kCFTypeDictionaryKeyCallBacks,
3945 &kCFTypeDictionaryValueCallBacks);
3949 FontDescriptorRef pat_desc =
3950 mac_font_descriptor_create_with_attributes (attributes);
3954 FontDescriptorRef descriptor =
3955 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3959 CFArrayAppendValue (descriptors, descriptor);
3960 CFRelease (descriptor);
3962 CFRelease (pat_desc);
3964 CFRelease (attributes);
3967 result = descriptors;
3979 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3980 CFArrayRef languages)
3982 CFStringRef result = NULL;
3983 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3984 CFArrayRef descriptors =
3985 mac_font_copy_default_descriptors_for_language (language);
3989 CFIndex i, count = CFArrayGetCount (descriptors);
3991 for (i = 0; i < count; i++)
3993 FontDescriptorRef descriptor =
3994 CFArrayGetValueAtIndex (descriptors, i);
3996 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3999 CFStringRef family =
4000 mac_font_descriptor_copy_attribute (descriptor,
4001 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
4004 if (!CFStringHasPrefix (family, CFSTR ("."))
4005 && !CFEqual (family, CFSTR ("LastResort")))
4015 CFRelease (descriptors);
4022 macfont_get_nsctfont (struct font *font)
4024 struct macfont_info *macfont_info = (struct macfont_info *) font;
4025 FontRef macfont = macfont_info->macfont;
4027 return (void *) macfont;
4031 mac_register_font_driver (struct frame *f)
4033 register_font_driver (&macfont_driver, f);
4036 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4040 syms_of_macfont (void)
4042 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4043 static struct font_driver mac_font_driver;
4045 DEFSYM (Qmac_ct, "mac-ct");
4046 macfont_driver.type = Qmac_ct;
4047 register_font_driver (&macfont_driver, NULL);
4049 DEFSYM (QCdestination, ":destination");
4050 DEFSYM (QCminspace, ":minspace");