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 void 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, /* anchor_point */
1584 NULL, /* otf_capability */
1585 NULL, /* otf_drive */
1586 NULL, /* start_for_frame */
1587 NULL, /* end_for_frame */
1590 macfont_variation_glyphs,
1591 macfont_filter_properties,
1595 macfont_get_cache (struct frame * f)
1597 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1599 return (dpyinfo->name_list_element);
1603 macfont_get_charset (Lisp_Object registry)
1605 char *str = SSDATA (SYMBOL_NAME (registry));
1606 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1610 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1614 else if (str[i] == '*')
1621 regexp = make_unibyte_string (re, j);
1622 for (i = 0; cf_charset_table[i].name; i++)
1623 if (fast_c_string_match_ignore_case
1624 (regexp, cf_charset_table[i].name,
1625 strlen (cf_charset_table[i].name)) >= 0)
1627 if (! cf_charset_table[i].name)
1629 if (! cf_charset_table[i].cf_charset)
1631 int *uniquifier = cf_charset_table[i].uniquifier;
1632 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1635 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1639 for (j = 0; uniquifier[j]; j++)
1641 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1643 CFCharacterSetAddCharactersInRange (charset,
1644 CFRangeMake (uniquifier[j], 1));
1647 string = CFStringCreateWithCharacters (NULL, unichars, count);
1650 CFRelease (charset);
1653 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1655 CFRelease (charset);
1656 /* CFCharacterSetCreateWithCharactersInString does not handle
1657 surrogate pairs properly as of Mac OS X 10.5. */
1658 cf_charset_table[i].cf_charset_string = string;
1666 unsigned int script_tag, langsys_tag;
1668 unsigned int *features[2];
1671 #define OTF_SYM_TAG(SYM, TAG) \
1673 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1674 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1677 #define OTF_TAG_STR(TAG, P) \
1679 (P)[0] = (char) (TAG >> 24); \
1680 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1681 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1682 (P)[3] = (char) (TAG & 0xFF); \
1686 static struct OpenTypeSpec *
1687 macfont_get_open_type_spec (Lisp_Object otf_spec)
1689 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1696 spec->script = XCAR (otf_spec);
1697 if (! NILP (spec->script))
1699 OTF_SYM_TAG (spec->script, spec->script_tag);
1700 val = assq_no_quit (spec->script, Votf_script_alist);
1701 if (CONSP (val) && SYMBOLP (XCDR (val)))
1702 spec->script = XCDR (val);
1704 spec->script = Qnil;
1707 spec->script_tag = 0x44464C54; /* "DFLT" */
1708 otf_spec = XCDR (otf_spec);
1709 spec->langsys_tag = 0;
1710 if (! NILP (otf_spec))
1712 val = XCAR (otf_spec);
1714 OTF_SYM_TAG (val, spec->langsys_tag);
1715 otf_spec = XCDR (otf_spec);
1717 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1718 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1722 val = XCAR (otf_spec);
1725 len = Flength (val);
1727 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1729 : malloc (XINT (len) * sizeof *spec->features[i]));
1730 if (! spec->features[i])
1732 if (i > 0 && spec->features[0])
1733 free (spec->features[0]);
1737 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1739 if (NILP (XCAR (val)))
1745 OTF_SYM_TAG (XCAR (val), tag);
1746 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1749 spec->nfeatures[i] = j;
1754 static CFMutableDictionaryRef
1755 macfont_create_attributes_with_spec (Lisp_Object spec)
1757 Lisp_Object tmp, extra;
1758 CFMutableArrayRef langarray = NULL;
1759 CFCharacterSetRef charset = NULL;
1760 CFStringRef charset_string = NULL;
1761 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1762 Lisp_Object script = Qnil;
1763 Lisp_Object registry;
1764 int cf_charset_idx, i;
1765 struct OpenTypeSpec *otspec = NULL;
1767 enum font_property_index index;
1770 } numeric_traits[] =
1771 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1772 {{-0.4, 50}, /* light */
1773 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1774 {0, 100}, /* normal */
1775 {0.24, 140}, /* (semi-bold + normal) / 2 */
1776 {0.4, 200}, /* bold */
1777 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1778 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1779 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1780 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1781 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1783 registry = AREF (spec, FONT_REGISTRY_INDEX);
1785 || EQ (registry, Qascii_0)
1786 || EQ (registry, Qiso10646_1)
1787 || EQ (registry, Qunicode_bmp))
1788 cf_charset_idx = -1;
1793 cf_charset_idx = macfont_get_charset (registry);
1794 if (cf_charset_idx < 0)
1796 charset = cf_charset_table[cf_charset_idx].cf_charset;
1797 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1798 lang = cf_charset_table[cf_charset_idx].lang;
1801 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1804 CFArrayAppendValue (langarray, lang);
1808 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1809 CONSP (extra); extra = XCDR (extra))
1811 Lisp_Object key, val;
1814 key = XCAR (tmp), val = XCDR (tmp);
1815 if (EQ (key, QClang))
1818 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1823 for (; CONSP (val); val = XCDR (val))
1824 if (SYMBOLP (XCAR (val)))
1827 cfstring_create_with_string_noencode (SYMBOL_NAME
1832 CFArrayAppendValue (langarray, lang);
1836 else if (EQ (key, QCotf))
1838 otspec = macfont_get_open_type_spec (val);
1841 script = otspec->script;
1843 else if (EQ (key, QCscript))
1847 if (! NILP (script) && ! charset)
1849 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1851 if (CONSP (chars) && CONSP (CDR (chars)))
1853 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1854 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1856 if (! string || !cs)
1864 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1865 if (CHARACTERP (XCAR (chars)))
1867 UniChar unichars[2];
1869 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1871 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1873 CFStringAppendCharacters (string, unichars, count);
1874 CFCharacterSetAddCharactersInRange (cs, range);
1877 /* CFCharacterSetCreateWithCharactersInString does not
1878 handle surrogate pairs properly as of Mac OS X 10.5. */
1879 charset_string = string;
1883 attributes = CFDictionaryCreateMutable (NULL, 0,
1884 &kCFTypeDictionaryKeyCallBacks,
1885 &kCFTypeDictionaryValueCallBacks);
1889 tmp = AREF (spec, FONT_FAMILY_INDEX);
1890 if (SYMBOLP (tmp) && ! NILP (tmp))
1892 CFStringRef family = macfont_create_family_with_symbol (tmp);
1896 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1901 traits = CFDictionaryCreateMutable (NULL, 4,
1902 &kCFTypeDictionaryKeyCallBacks,
1903 &kCFTypeDictionaryValueCallBacks);
1907 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1909 tmp = AREF (spec, numeric_traits[i].index);
1912 CGPoint *point = numeric_traits[i].points;
1913 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1916 while (point->y < floatval)
1918 if (point == numeric_traits[i].points)
1920 else if (point->y == CGFLOAT_MAX)
1922 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1923 * ((point->x - (point - 1)->x)
1924 / (point->y - (point - 1)->y)));
1927 else if (floatval < -1.0)
1929 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1932 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1936 if (CFDictionaryGetCount (traits))
1937 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1940 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1943 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1946 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1953 CFRelease (attributes);
1958 if (langarray) CFRelease (langarray);
1959 if (charset && cf_charset_idx < 0) CFRelease (charset);
1960 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1961 if (traits) CFRelease (traits);
1964 if (otspec->nfeatures[0] > 0)
1965 free (otspec->features[0]);
1966 if (otspec->nfeatures[1] > 0)
1967 free (otspec->features[1]);
1975 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1976 CFCharacterSetRef charset,
1978 CFArrayRef languages)
1980 Boolean result = true;
1982 if (charset || VECTORP (chars))
1984 CFCharacterSetRef desc_charset =
1985 mac_font_descriptor_copy_attribute (desc,
1986 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1988 if (desc_charset == NULL)
1993 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1994 else /* VECTORP (chars) */
1998 for (j = 0; j < ASIZE (chars); j++)
1999 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
2000 && CFCharacterSetIsLongCharacterMember (desc_charset,
2001 XFASTINT (AREF (chars, j))))
2003 if (j == ASIZE (chars))
2006 CFRelease (desc_charset);
2009 if (result && languages)
2010 result = mac_font_descriptor_supports_languages (desc, languages);
2016 macfont_closest_traits_index (CFArrayRef traits_array,
2017 FontSymbolicTraits target)
2019 CFIndex i, result = -1, count = CFArrayGetCount (traits_array);
2020 int min_distance = (1 << 3);
2022 for (i = 0; i < count; i++)
2024 FontSymbolicTraits traits, diff;
2027 traits = ((FontSymbolicTraits) (uintptr_t)
2028 CFArrayGetValueAtIndex (traits_array, i));
2029 diff = (target ^ traits);
2030 /* We prefer synthetic bold of italic to synthetic italic of
2031 bold when both bold and italic are available but bold-italic
2032 is not available. */
2033 if (diff & MAC_FONT_TRAIT_BOLD)
2034 distance |= (1 << 0);
2035 if (diff & MAC_FONT_TRAIT_ITALIC)
2036 distance |= (1 << 1);
2037 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2038 distance |= (1 << 2);
2039 if (distance < min_distance)
2041 min_distance = distance;
2050 macfont_list (struct frame *f, Lisp_Object spec)
2052 Lisp_Object val = Qnil, family, extra;
2054 CFStringRef family_name = NULL;
2055 CFMutableDictionaryRef attributes = NULL, traits;
2056 Lisp_Object chars = Qnil;
2058 FontSymbolicTraits synth_sym_traits = 0;
2059 CFArrayRef families;
2060 CFIndex families_count;
2061 CFCharacterSetRef charset = NULL;
2062 CFArrayRef languages = NULL;
2066 family = AREF (spec, FONT_FAMILY_INDEX);
2067 if (! NILP (family))
2069 family_name = macfont_create_family_with_symbol (family);
2070 if (family_name == NULL)
2074 attributes = macfont_create_attributes_with_spec (spec);
2078 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2080 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2081 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2083 traits = ((CFMutableDictionaryRef)
2084 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2086 n = FONT_SLANT_NUMERIC (spec);
2087 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2089 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2091 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2094 n = FONT_WEIGHT_NUMERIC (spec);
2095 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2097 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2099 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2103 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2105 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2107 if (CFStringHasPrefix (language, CFSTR ("ja"))
2108 || CFStringHasPrefix (language, CFSTR ("ko"))
2109 || CFStringHasPrefix (language, CFSTR ("zh")))
2110 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2113 /* Create array of families. */
2115 families = CFArrayCreate (NULL, (const void **) &family_name,
2116 1, &kCFTypeArrayCallBacks);
2119 CFStringRef pref_family;
2120 CFIndex families_count, pref_family_index = -1;
2122 families = mac_font_create_available_families ();
2123 if (families == NULL)
2126 families_count = CFArrayGetCount (families);
2128 /* Move preferred family to the front if exists. */
2130 mac_font_create_preferred_family_for_attributes (attributes);
2134 CFArrayGetFirstIndexOfValue (families,
2135 CFRangeMake (0, families_count),
2137 CFRelease (pref_family);
2139 if (pref_family_index > 0)
2141 CFMutableArrayRef mutable_families =
2142 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2144 if (mutable_families)
2146 CFArrayAppendValue (mutable_families,
2147 CFArrayGetValueAtIndex (families,
2148 pref_family_index));
2149 CFArrayAppendArray (mutable_families, families,
2150 CFRangeMake (0, pref_family_index));
2151 if (pref_family_index + 1 < families_count)
2152 CFArrayAppendArray (mutable_families, families,
2153 CFRangeMake (pref_family_index + 1,
2155 - (pref_family_index + 1)));
2156 CFRelease (families);
2157 families = mutable_families;
2162 charset = CFDictionaryGetValue (attributes,
2163 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2167 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2171 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2174 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2175 if (CONSP (val) && VECTORP (XCDR (val)))
2183 CFRetain (languages);
2184 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2188 extra = AREF (spec, FONT_EXTRA_INDEX);
2189 families_count = CFArrayGetCount (families);
2190 for (i = 0; i < families_count; i++)
2192 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2193 FontDescriptorRef pat_desc;
2195 CFIndex descs_count;
2196 CFMutableArrayRef filtered_descs, traits_array;
2200 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2202 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2206 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2207 10.7 returns NULL if pat_desc represents the LastResort font.
2208 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2209 trailing "s") for such a font. */
2210 if (!CFEqual (family_name, CFSTR ("LastResort")))
2211 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2215 FontDescriptorRef lr_desc =
2216 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2220 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2221 &kCFTypeArrayCallBacks);
2222 CFRelease (lr_desc);
2227 CFRelease (pat_desc);
2231 descs_count = CFArrayGetCount (descs);
2232 if (descs_count == 0
2233 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2242 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2243 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2244 for (j = 0; j < descs_count; j++)
2246 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2247 CFDictionaryRef dict;
2249 FontSymbolicTraits sym_traits;
2251 dict = mac_font_descriptor_copy_attribute (desc,
2252 MAC_FONT_TRAITS_ATTRIBUTE);
2256 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2259 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2263 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2264 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2265 != (spacing >= FONT_SPACING_MONO)))
2268 /* Don't use a color bitmap font unless its family is
2269 explicitly specified. */
2270 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2274 && !macfont_supports_charset_and_languages_p (desc, charset,
2278 CFArrayAppendValue (filtered_descs, desc);
2279 CFArrayAppendValue (traits_array,
2280 (const void *) (uintptr_t) sym_traits);
2284 descs = filtered_descs;
2285 descs_count = CFArrayGetCount (descs);
2287 for (j = 0; j < descs_count; j++)
2289 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2290 FontSymbolicTraits sym_traits =
2291 ((FontSymbolicTraits) (uintptr_t)
2292 CFArrayGetValueAtIndex (traits_array, j));
2293 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2295 mask_min = ((synth_sym_traits ^ sym_traits)
2296 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2297 if (FONT_SLANT_NUMERIC (spec) < 0)
2298 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2299 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2300 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2302 mask_max = (synth_sym_traits & ~sym_traits);
2303 /* Synthetic bold does not work for bitmap-only fonts on Mac
2305 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2307 CFNumberRef format =
2308 mac_font_descriptor_copy_attribute (desc,
2309 MAC_FONT_FORMAT_ATTRIBUTE);
2313 uint32_t format_val;
2315 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2317 && format_val == MAC_FONT_FORMAT_BITMAP)
2318 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2322 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2324 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2325 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2326 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2327 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2328 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2329 bmask += MAC_FONT_TRAIT_BOLD)
2330 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2331 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2332 imask += MAC_FONT_TRAIT_ITALIC)
2334 FontSymbolicTraits synth = (imask | bmask | mmask);
2337 || j == macfont_closest_traits_index (traits_array,
2338 (sym_traits | synth)))
2340 entity = macfont_descriptor_entity (desc, extra, synth);
2341 if (! NILP (entity))
2342 val = Fcons (entity, val);
2347 CFRelease (traits_array);
2351 CFRelease (families);
2352 val = Fnreverse (val);
2358 FONT_ADD_LOG ("macfont-list", spec, val);
2359 if (charset) CFRelease (charset);
2360 if (languages) CFRelease (languages);
2361 if (attributes) CFRelease (attributes);
2362 if (family_name) CFRelease (family_name);
2370 macfont_match (struct frame * frame, Lisp_Object spec)
2372 Lisp_Object entity = Qnil;
2373 CFMutableDictionaryRef attributes;
2374 FontDescriptorRef pat_desc = NULL, desc = NULL;
2378 attributes = macfont_create_attributes_with_spec (spec);
2381 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2382 CFRelease (attributes);
2386 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2388 CFRelease (pat_desc);
2392 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2398 FONT_ADD_LOG ("macfont-match", spec, entity);
2403 macfont_list_family (struct frame *frame)
2405 Lisp_Object list = Qnil;
2406 CFArrayRef families;
2410 families = mac_font_create_available_families ();
2413 CFIndex i, count = CFArrayGetCount (families);
2415 for (i = 0; i < count; i++)
2416 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2417 CFRelease (families);
2426 macfont_free_entity (Lisp_Object entity)
2428 Lisp_Object val = assq_no_quit (QCfont_entity,
2429 AREF (entity, FONT_EXTRA_INDEX));
2430 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2438 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2440 Lisp_Object val, font_object;
2441 CFStringRef font_name;
2442 struct macfont_info *macfont_info = NULL;
2446 FontSymbolicTraits sym_traits;
2449 CGFloat ascent, descent, leading;
2451 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2453 || XTYPE (XCDR (val)) != Lisp_Misc
2454 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2456 font_name = XSAVE_POINTER (XCDR (val), 0);
2457 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2459 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2464 macfont = mac_font_create_with_name (font_name, size);
2467 int fontsize = (int) [((NSFont *) macfont) pointSize];
2468 if (fontsize != size) size = fontsize;
2474 font_object = font_build_object (VECSIZE (struct macfont_info),
2475 Qmac_ct, entity, size);
2476 font = XFONT_OBJECT (font_object);
2477 font->pixel_size = size;
2478 font->driver = &macfont_driver;
2479 font->encoding_charset = font->repertory_charset = -1;
2483 macfont_info = (struct macfont_info *) font;
2484 macfont_info->macfont = macfont;
2485 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2487 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2488 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2489 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2492 macfont_info->screen_font = NULL;
2493 macfont_info->cache = macfont_lookup_cache (font_name);
2494 macfont_retain_cache (macfont_info->cache);
2495 macfont_info->metrics = NULL;
2496 macfont_info->metrics_nrows = 0;
2497 macfont_info->synthetic_italic_p = 0;
2498 macfont_info->synthetic_bold_p = 0;
2499 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2500 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2501 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2502 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2503 macfont_info->synthetic_italic_p = 1;
2504 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2505 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2506 macfont_info->synthetic_bold_p = 1;
2507 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2508 macfont_info->spacing = MACFONT_SPACING_MONO;
2509 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2510 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2511 == FONT_SPACING_SYNTHETIC_MONO))
2512 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2513 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2514 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2517 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2519 macfont_info->antialias =
2520 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2522 macfont_info->color_bitmap_p = 0;
2523 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2524 macfont_info->color_bitmap_p = 1;
2526 glyph = macfont_get_glyph_for_character (font, ' ');
2527 if (glyph != kCGFontIndexInvalid)
2528 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2530 /* dirty workaround */
2531 font->space_width = pixel_size;
2533 total_width = font->space_width;
2534 for (i = 1; i < 95; i++)
2536 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2537 if (glyph == kCGFontIndexInvalid)
2539 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2542 font->average_width = total_width / 95;
2544 font->average_width = font->space_width; /* XXX */
2546 if (!(macfont_info->screen_font
2547 && mac_screen_font_get_metrics (macfont_info->screen_font,
2548 &ascent, &descent, &leading)))
2550 CFStringRef family_name;
2552 ascent = mac_font_get_ascent (macfont);
2553 descent = mac_font_get_descent (macfont);
2554 leading = mac_font_get_leading (macfont);
2555 /* AppKit and WebKit do some adjustment to the heights of
2556 Courier, Helvetica, and Times. */
2557 family_name = mac_font_copy_family_name (macfont);
2560 if (CFEqual (family_name, CFSTR ("Courier"))
2561 || CFEqual (family_name, CFSTR ("Helvetica"))
2562 || CFEqual (family_name, CFSTR ("Times")))
2563 ascent += (ascent + descent) * .15f;
2564 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2569 CFRelease (family_name);
2572 font->ascent = ascent + 0.5f;
2573 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2574 if (CONSP (val) && !NILP (XCDR (val)))
2575 font->descent = descent + 0.5f;
2577 font->descent = descent + leading + 0.5f;
2578 font->height = font->ascent + font->descent;
2580 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2581 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2585 /* Unfortunately Xft doesn't provide a way to get minimum char
2586 width. So, we use space_width instead. */
2587 font->min_width = font->max_width = font->space_width; /* XXX */
2589 font->baseline_offset = 0;
2590 font->relative_compose = 0;
2591 font->default_ascent = 0;
2592 font->vertical_centering = 0;
2598 macfont_close (struct font *font)
2600 struct macfont_info *macfont_info = (struct macfont_info *) font;
2602 if (macfont_info->cache)
2607 CFRelease (macfont_info->macfont);
2608 CGFontRelease (macfont_info->cgfont);
2609 if (macfont_info->screen_font)
2610 CFRelease (macfont_info->screen_font);
2611 macfont_release_cache (macfont_info->cache);
2612 for (i = 0; i < macfont_info->metrics_nrows; i++)
2613 if (macfont_info->metrics[i])
2614 xfree (macfont_info->metrics[i]);
2615 if (macfont_info->metrics)
2616 xfree (macfont_info->metrics);
2617 macfont_info->cache = NULL;
2623 macfont_has_char (Lisp_Object font, int c)
2626 CFCharacterSetRef charset;
2629 if (FONT_ENTITY_P (font))
2634 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2636 name = XSAVE_POINTER (val, 0);
2637 charset = macfont_get_cf_charset_for_name (name);
2640 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2642 result = CFCharacterSetIsLongCharacterMember (charset, c);
2649 macfont_encode_char (struct font *font, int c)
2651 struct macfont_info *macfont_info = (struct macfont_info *) font;
2655 glyph = macfont_get_glyph_for_character (font, c);
2658 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2662 macfont_text_extents (struct font *font, unsigned int *code,
2663 int nglyphs, struct font_metrics *metrics)
2668 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2669 for (i = 1; i < nglyphs; i++)
2671 struct font_metrics m;
2672 int w = macfont_glyph_extents (font, code[i], &m, NULL, 0);
2674 if (width + m.lbearing < metrics->lbearing)
2675 metrics->lbearing = width + m.lbearing;
2676 if (width + m.rbearing > metrics->rbearing)
2677 metrics->rbearing = width + m.rbearing;
2678 if (m.ascent > metrics->ascent)
2679 metrics->ascent = m.ascent;
2680 if (m.descent > metrics->descent)
2681 metrics->descent = m.descent;
2686 metrics->width = width;
2690 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2691 bool with_background)
2693 struct frame * f = s->f;
2694 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2695 CGRect background_rect;
2696 CGPoint text_position;
2699 CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2700 bool no_antialias_p =
2701 (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2702 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2703 && font_size <= macfont_antialias_threshold));
2704 int len = to - from;
2705 struct face *face = s->face;
2706 CGContextRef context;
2710 if (with_background)
2711 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2712 s->width, FONT_HEIGHT (s->font));
2714 background_rect = CGRectNull;
2716 text_position = CGPointMake (x, -y);
2717 glyphs = xmalloc (sizeof (CGGlyph) * len);
2719 CGFloat advance_delta;
2721 CGFloat total_width = 0;
2723 positions = xmalloc (sizeof (CGPoint) * len);
2724 for (i = 0; i < len; i++)
2728 glyphs[i] = s->char2b[from + i];
2729 width = (s->padding_p ? 1
2730 : macfont_glyph_extents (s->font, glyphs[i],
2731 NULL, &advance_delta,
2733 positions[i].x = total_width + advance_delta;
2735 total_width += width;
2739 context = [[NSGraphicsContext currentContext] graphicsPort];
2740 CGContextSaveGState (context);
2742 if (!CGRectIsNull (background_rect))
2744 if (s->hl == DRAW_MOUSE_FACE)
2746 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2748 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2750 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2751 CGContextFillRects (context, &background_rect, 1);
2754 if (macfont_info->cgfont)
2756 CGAffineTransform atfm;
2757 CGContextScaleCTM (context, 1, -1);
2758 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2759 if (macfont_info->synthetic_italic_p)
2760 atfm = synthetic_italic_atfm;
2762 atfm = CGAffineTransformIdentity;
2763 if (macfont_info->synthetic_bold_p)
2765 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2766 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2767 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2770 CGContextSetShouldAntialias (context, false);
2772 CGContextSetTextMatrix (context, atfm);
2773 CGContextSetTextPosition (context, text_position.x, text_position.y);
2775 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2776 if (macfont_info->color_bitmap_p
2777 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2778 && CTFontDrawGlyphs != NULL
2784 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2789 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2791 CGContextSetFont (context, macfont_info->cgfont);
2792 CGContextSetFontSize (context, font_size);
2793 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2800 CGContextRestoreGState (context);
2808 macfont_shape (Lisp_Object lgstring)
2811 struct macfont_info *macfont_info;
2813 ptrdiff_t glyph_len, len, i, j;
2816 CFIndex *nonbmp_indices;
2819 struct mac_glyph_layout *glyph_layouts;
2821 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2822 macfont_info = (struct macfont_info *) font;
2823 macfont = macfont_info->macfont;
2825 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2827 for (i = 0; i < glyph_len; i++)
2829 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2833 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2839 if (INT_MAX / 2 < len)
2840 memory_full (SIZE_MAX);
2842 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2843 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2844 for (i = j = 0; i < len; i++)
2846 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2848 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2850 nonbmp_indices[j] = i + j;
2854 nonbmp_indices[j] = len + j; /* sentinel */
2858 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2862 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2863 if (macfont_info->screen_font)
2864 used = mac_screen_font_shape (macfont_info->screen_font, string,
2865 glyph_layouts, glyph_len);
2867 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2878 for (i = 0; i < used; i++)
2880 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2881 struct mac_glyph_layout *gl = glyph_layouts + i;
2883 struct font_metrics metrics;
2884 int xoff, yoff, wadjust;
2888 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2889 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2892 from = gl->comp_range.location;
2893 /* Convert UTF-16 index to UTF-32. */
2895 while (nonbmp_indices[j] < from)
2898 LGLYPH_SET_FROM (lglyph, from);
2900 to = gl->comp_range.location + gl->comp_range.length;
2901 /* Convert UTF-16 index to UTF-32. */
2902 while (nonbmp_indices[j] < to)
2905 LGLYPH_SET_TO (lglyph, to - 1);
2907 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2908 the composition is trivial. */
2912 if (unichars[gl->string_index] >= 0xD800
2913 && unichars[gl->string_index] < 0xDC00)
2914 c = (((unichars[gl->string_index] - 0xD800) << 10)
2915 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2917 c = unichars[gl->string_index];
2918 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2920 LGLYPH_SET_CHAR (lglyph, c);
2924 unsigned long cc = gl->glyph_id;
2925 LGLYPH_SET_CODE (lglyph, cc);
2928 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2929 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2930 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2931 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2932 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2933 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2935 xoff = lround (gl->advance_delta);
2936 yoff = lround (- gl->baseline_delta);
2937 wadjust = lround (gl->advance);
2938 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2942 vec = Fmake_vector (make_number (3), Qnil);
2943 ASET (vec, 0, make_number (xoff));
2944 ASET (vec, 1, make_number (yoff));
2945 ASET (vec, 2, make_number (wadjust));
2946 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2952 return make_number (used);
2955 /* Structures for the UVS subtable (format 14) in the cmap table. */
2956 typedef UInt8 UINT24[3];
2958 #pragma pack(push, 1)
2959 struct variation_selector_record
2961 UINT24 var_selector;
2962 UInt32 default_uvs_offset, non_default_uvs_offset;
2967 UInt32 length, num_var_selector_records;
2968 struct variation_selector_record variation_selector_records[1];
2970 #define SIZEOF_UVS_TABLE_HEADER \
2971 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2973 struct unicode_value_range
2975 UINT24 start_unicode_value;
2976 UInt8 additional_count;
2978 struct default_uvs_table {
2979 UInt32 num_unicode_value_ranges;
2980 struct unicode_value_range unicode_value_ranges[1];
2982 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2983 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2987 UINT24 unicode_value;
2990 struct non_default_uvs_table
2992 UInt32 num_uvs_mappings;
2993 struct uvs_mapping uvs_mappings[1];
2995 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
2996 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2999 /* Read big endian values. The argument LVAL must be an lvalue. */
3000 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
3001 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
3002 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
3003 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3004 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3005 /* Succeeding one byte should also be accessible. */
3006 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3007 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3009 /* Return UVS subtable for the specified FONT. If the subtable is not
3010 found or ill-formatted, then return NULL. */
3013 mac_font_copy_uvs_table (FontRef font)
3015 CFDataRef cmap_table, uvs_table = NULL;
3017 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3020 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3021 struct uvs_table *uvs;
3022 struct variation_selector_record *records;
3023 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3026 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3030 cmap_len = CFDataGetLength (cmap_table);
3031 if (sizeof_sfntCMapHeader > cmap_len)
3034 ntables = BUINT16_VALUE (cmap->numTables);
3035 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3036 / sizeof_sfntCMapEncoding))
3039 for (i = 0; i < ntables; i++)
3040 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3041 == kFontUnicodePlatform)
3042 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3043 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3045 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3049 || uvs_offset > cmap_len
3050 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3053 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3054 uvs_len = BUINT32_VALUE (uvs->length);
3055 if (uvs_len > cmap_len - uvs_offset
3056 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3059 if (BUINT16_VALUE (uvs->format) != 14)
3062 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3063 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3064 / sizeof (struct variation_selector_record)))
3067 records = uvs->variation_selector_records;
3068 for (i = 0; i < nrecords; i++)
3070 UInt32 default_uvs_offset, non_default_uvs_offset;
3072 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3073 if (default_uvs_offset)
3075 struct default_uvs_table *default_uvs;
3078 if (default_uvs_offset > uvs_len
3079 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3080 > uvs_len - default_uvs_offset))
3083 default_uvs = ((struct default_uvs_table *)
3084 ((UInt8 *) uvs + default_uvs_offset));
3085 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3086 if (nranges > ((uvs_len - default_uvs_offset
3087 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3088 / sizeof (struct unicode_value_range)))
3090 /* Now 2 * nranges can't overflow, so we can safely use
3091 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3092 mac_font_get_glyphs_for_variants. */
3095 non_default_uvs_offset =
3096 BUINT32_VALUE (records[i].non_default_uvs_offset);
3097 if (non_default_uvs_offset)
3099 struct non_default_uvs_table *non_default_uvs;
3102 if (non_default_uvs_offset > uvs_len
3103 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3104 > uvs_len - non_default_uvs_offset))
3107 non_default_uvs = ((struct non_default_uvs_table *)
3108 ((UInt8 *) uvs + non_default_uvs_offset));
3109 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3110 if (nmappings > ((uvs_len - non_default_uvs_offset
3111 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3112 / sizeof (struct uvs_mapping)))
3114 /* Now 2 * nmappings can't overflow, so we can safely
3115 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3116 in mac_font_get_glyphs_for_variants. */
3120 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3123 CFRelease (cmap_table);
3129 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3130 sequence consisting of the given base character C and each
3131 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3132 result (explained below) into the corresponding GLYPHS[i]. If the
3133 entry is found in the Default UVS Table, then the result is 0. If
3134 the entry is found in the Non-Default UVS Table, then the result is
3135 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3136 elements in SELECTORS must be sorted in strictly increasing
3140 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3141 const UTF32Char selectors[], CGGlyph glyphs[],
3144 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3145 struct variation_selector_record *records = uvs->variation_selector_records;
3147 UInt32 ir, nrecords;
3148 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3149 dispatch_queue_t queue =
3150 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3151 dispatch_group_t group = dispatch_group_create ();
3154 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3157 while (i < count && ir < nrecords)
3159 UInt32 default_uvs_offset, non_default_uvs_offset;
3161 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3163 glyphs[i++] = kCGFontIndexInvalid;
3166 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3172 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3173 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3174 non_default_uvs_offset =
3175 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3176 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3177 dispatch_group_async (group, queue, ^{
3179 glyphs[i] = kCGFontIndexInvalid;
3181 if (default_uvs_offset)
3183 struct default_uvs_table *default_uvs =
3184 (struct default_uvs_table *) ((UInt8 *) uvs
3185 + default_uvs_offset);
3186 struct unicode_value_range *ranges =
3187 default_uvs->unicode_value_ranges;
3191 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3194 UInt32 mid = (lo + hi) / 2;
3196 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3202 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3203 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3207 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3209 struct non_default_uvs_table *non_default_uvs =
3210 (struct non_default_uvs_table *) ((UInt8 *) uvs
3211 + non_default_uvs_offset);
3212 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3216 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3219 UInt32 mid = (lo + hi) / 2;
3221 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3227 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3228 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3230 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3237 glyphs[i++] = kCGFontIndexInvalid;
3238 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3239 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3240 dispatch_release (group);
3245 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3247 CFDataRef uvs_table;
3248 CharacterCollection uvs_collection;
3252 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3256 UTF32Char selectors[256];
3257 CGGlyph glyphs[256];
3259 for (i = 0; i < 16; i++)
3260 selectors[i] = 0xFE00 + i;
3261 for (; i < 256; i++)
3262 selectors[i] = 0xE0100 + (i - 16);
3263 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3264 for (i = 0; i < 256; i++)
3266 CGGlyph glyph = glyphs[i];
3268 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3269 && glyph != kCGFontIndexInvalid)
3270 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3271 if (glyph == kCGFontIndexInvalid)
3275 variations[i] = (glyph ? glyph
3276 : macfont_get_glyph_for_character (font, c));
3286 static const char *const macfont_booleans[] = {
3292 static const char *const macfont_non_booleans[] = {
3300 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3302 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3306 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3307 CFArrayRef languages)
3309 Boolean result = true;
3310 CFArrayRef desc_languages =
3311 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3313 if (desc_languages == NULL)
3317 CFIndex desc_languages_count, i, languages_count;
3319 desc_languages_count = CFArrayGetCount (desc_languages);
3320 languages_count = CFArrayGetCount (languages);
3321 for (i = 0; i < languages_count; i++)
3322 if (!CFArrayContainsValue (desc_languages,
3323 CFRangeMake (0, desc_languages_count),
3324 CFArrayGetValueAtIndex (languages, i)))
3329 CFRelease (desc_languages);
3336 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3338 CFStringRef result = NULL;
3339 CFStringRef charset_string =
3340 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3342 if (charset_string && CFStringGetLength (charset_string) > 0)
3344 CFStringRef keys[] = {
3345 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3346 kCTLanguageAttributeName
3348 CFSTR ("NSLanguage")
3351 CFTypeRef values[] = {NULL};
3352 CFIndex num_values = 0;
3353 CFArrayRef languages
3354 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3356 if (languages && CFArrayGetCount (languages) > 0)
3358 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3359 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3362 CFCharacterSetRef charset =
3363 CFDictionaryGetValue (attributes,
3364 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3366 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3371 CFAttributedStringRef attr_string = NULL;
3372 CTLineRef ctline = NULL;
3373 CFDictionaryRef attrs
3374 = CFDictionaryCreate (NULL, (const void **) keys,
3375 (const void **) values, num_values,
3376 &kCFTypeDictionaryKeyCallBacks,
3377 &kCFTypeDictionaryValueCallBacks);
3381 attr_string = CFAttributedStringCreate (NULL, charset_string,
3387 ctline = CTLineCreateWithAttributedString (attr_string);
3388 CFRelease (attr_string);
3392 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3393 CFIndex i, nruns = CFArrayGetCount (runs);
3396 for (i = 0; i < nruns; i++)
3398 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3399 CFDictionaryRef attributes = CTRunGetAttributes (run);
3400 CTFontRef font_in_run;
3402 if (attributes == NULL)
3405 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3406 if (font_in_run == NULL)
3410 else if (!mac_ctfont_equal_in_postscript_name (font,
3414 if (nruns > 0 && i == nruns)
3415 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3424 static inline double
3425 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3427 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3431 static inline CGRect
3432 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3434 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3439 mac_ctfont_create_available_families (void)
3441 CFMutableArrayRef families = NULL;
3443 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3444 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3445 if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3448 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3452 CFIndex i, count = CFArrayGetCount (orig_families);
3454 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3456 for (i = 0; i < count; i++)
3458 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3460 if (!CFStringHasPrefix (family, CFSTR ("."))
3461 && (CTFontManagerCompareFontFamilyNames (family,
3462 CFSTR ("LastResort"),
3464 != kCFCompareEqualTo))
3465 CFArrayAppendValue (families, family);
3467 CFRelease (orig_families);
3470 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3471 else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3473 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3474 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3476 CTFontCollectionRef collection;
3477 CFArrayRef descs = NULL;
3479 collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3482 descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3483 CFRelease (collection);
3487 CFIndex i, count = CFArrayGetCount (descs);
3489 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3491 for (i = 0; i < count; i++)
3493 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3495 mac_font_descriptor_copy_attribute (desc,
3496 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3500 CFIndex p, limit = CFArrayGetCount (families);
3502 p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3503 (const void *) name,
3504 mac_font_family_compare, NULL);
3506 CFArrayAppendValue (families, name);
3507 else if (mac_font_family_compare
3508 (CFArrayGetValueAtIndex (families, p),
3509 name, NULL) != kCFCompareEqualTo)
3510 CFArrayInsertValueAtIndex (families, p, name);
3523 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3526 CFStringRef name1, name2;
3532 name1 = CTFontCopyPostScriptName (font1);
3535 name2 = CTFontCopyPostScriptName (font2);
3538 result = CFEqual (name1, name2);
3548 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3551 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3552 CFTypeRef values[] = {NULL, NULL};
3553 CFDictionaryRef attributes = NULL;
3554 CFAttributedStringRef attr_string = NULL;
3555 CTLineRef ctline = NULL;
3556 float float_zero = 0.0f;
3558 values[0] = macfont;
3559 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3562 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3563 (const void **) values,
3565 &kCFTypeDictionaryKeyCallBacks,
3566 &kCFTypeDictionaryValueCallBacks);
3567 CFRelease (values[1]);
3571 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3572 CFRelease (attributes);
3576 ctline = CTLineCreateWithAttributedString (attr_string);
3577 CFRelease (attr_string);
3581 /* Abandon if ctline contains some fonts other than the
3583 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3584 CFIndex i, nruns = CFArrayGetCount (runs);
3586 for (i = 0; i < nruns; i++)
3588 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3589 CFDictionaryRef attributes = CTRunGetAttributes (run);
3590 CTFontRef font_in_run;
3592 if (attributes == NULL)
3595 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3596 if (font_in_run == NULL)
3598 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3612 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3613 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3615 CFIndex used, result = 0;
3616 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3621 used = CTLineGetGlyphCount (ctline);
3622 if (used <= glyph_len)
3624 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3625 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3626 CGFloat total_advance = 0;
3627 CFIndex total_glyph_count = 0;
3629 for (k = 0; k < ctrun_count; k++)
3631 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3632 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3633 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3634 CFRange string_range, comp_range, range;
3635 CFIndex *permutation;
3637 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3638 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3642 #define RIGHT_TO_LEFT_P permutation
3644 /* Now the `comp_range' member of struct mac_glyph_layout is
3645 temporarily used as a work area such that:
3646 glbuf[i].comp_range.location =
3647 min {compRange[i + 1].location, ...,
3648 compRange[glyph_count - 1].location,
3649 maxRange (stringRangeForCTRun)}
3650 glbuf[i].comp_range.length = maxRange (compRange[i])
3651 where compRange[i] is the range of composed characters
3652 containing i-th glyph. */
3653 string_range = CTRunGetStringRange (ctrun);
3654 min_location = string_range.location + string_range.length;
3655 for (i = 0; i < glyph_count; i++)
3657 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3658 CFIndex glyph_index;
3661 if (!RIGHT_TO_LEFT_P)
3662 glyph_index = glyph_count - i - 1;
3665 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3668 CFStringGetRangeOfComposedCharactersAtIndex (string,
3670 gl->comp_range.location = min_location;
3671 gl->comp_range.length = rng.location + rng.length;
3672 if (rng.location < min_location)
3673 min_location = rng.location;
3676 /* Fill the `comp_range' member of struct mac_glyph_layout,
3677 and setup a permutation for right-to-left text. */
3678 comp_range = CFRangeMake (string_range.location, 0);
3679 range = CFRangeMake (0, 0);
3682 struct mac_glyph_layout *gl =
3683 glbuf + range.location + range.length;
3685 if (gl->comp_range.length
3686 > comp_range.location + comp_range.length)
3687 comp_range.length = gl->comp_range.length - comp_range.location;
3688 min_location = gl->comp_range.location;
3691 if (min_location >= comp_range.location + comp_range.length)
3693 comp_range.length = min_location - comp_range.location;
3694 for (i = 0; i < range.length; i++)
3696 glbuf[range.location + i].comp_range = comp_range;
3697 if (RIGHT_TO_LEFT_P)
3698 permutation[range.location + i] =
3699 range.location + range.length - i - 1;
3702 comp_range = CFRangeMake (min_location, 0);
3703 range.location += range.length;
3705 if (range.location == glyph_count)
3710 /* Then fill the remaining members. */
3711 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3714 struct mac_glyph_layout *gl;
3717 if (!RIGHT_TO_LEFT_P)
3718 gl = glbuf + range.location;
3723 src = glyph_count - 1 - range.location;
3724 dest = permutation[src];
3728 CFIndex tmp = gl->string_index;
3730 gl->string_index = glbuf[src].string_index;
3731 glbuf[src].string_index = tmp;
3734 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3736 CTRunGetPositions (ctrun, range, &position);
3737 gl->advance_delta = position.x - total_advance;
3738 gl->baseline_delta = position.y;
3739 gl->advance = (gl->advance_delta
3740 + CTRunGetTypographicBounds (ctrun, range,
3742 total_advance += gl->advance;
3745 if (RIGHT_TO_LEFT_P)
3746 xfree (permutation);
3748 #undef RIGHT_TO_LEFT_P
3750 total_glyph_count += glyph_count;
3760 /* The function below seems to cause a memory leak for the CFString
3761 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3762 10.6.3. For now, we use the NSGlyphInfo version instead. */
3763 #if USE_CT_GLYPH_INFO
3765 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3768 CGGlyph result = kCGFontIndexInvalid;
3769 UniChar characters[] = {0xfffd};
3771 CFAttributedStringRef attr_string = NULL;
3772 CTLineRef ctline = NULL;
3774 string = CFStringCreateWithCharacters (NULL, characters,
3775 ARRAYELTS (characters));
3779 CTGlyphInfoRef glyph_info =
3780 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3781 CFDictionaryRef attributes = NULL;
3785 CFStringRef keys[] = {kCTFontAttributeName,
3786 kCTGlyphInfoAttributeName};
3787 CFTypeRef values[] = {font, glyph_info};
3789 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3790 (const void **) values,
3792 &kCFTypeDictionaryKeyCallBacks,
3793 &kCFTypeDictionaryValueCallBacks);
3794 CFRelease (glyph_info);
3798 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3799 CFRelease (attributes);
3805 ctline = CTLineCreateWithAttributedString (attr_string);
3806 CFRelease (attr_string);
3810 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3812 if (CFArrayGetCount (runs) > 0)
3814 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3815 CFDictionaryRef attributes = CTRunGetAttributes (run);
3819 CTFontRef font_in_run =
3820 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3823 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3825 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3826 if (result >= CTFontGetGlyphCount (font))
3827 result = kCGFontIndexInvalid;
3838 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3840 mac_font_family_group (CFStringRef family)
3842 if (CFStringHasPrefix (family, CFSTR ("#")))
3848 range = CFStringFind (family, CFSTR ("Apple"),
3849 kCFCompareCaseInsensitive | kCFCompareAnchored);
3850 if (range.location != kCFNotFound)
3857 static CFComparisonResult
3858 mac_font_family_compare (const void *val1, const void *val2, void *context)
3860 CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3863 group1 = mac_font_family_group (family1);
3864 group2 = mac_font_family_group (family2);
3865 if (group1 < group2)
3866 return kCFCompareLessThan;
3867 if (group1 > group2)
3868 return kCFCompareGreaterThan;
3869 return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3871 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3874 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3876 CFArrayRef result = NULL;
3878 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3879 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3880 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3883 CTFontRef user_font =
3884 CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3888 CFArrayRef languages =
3889 CFArrayCreate (NULL, (const void **) &language, 1,
3890 &kCFTypeArrayCallBacks);
3894 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3896 CFRelease (languages);
3898 CFRelease (user_font);
3901 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3902 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3904 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3905 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3909 for (i = 0; macfont_language_default_font_names[i].language; i++)
3911 if (CFEqual (macfont_language_default_font_names[i].language,
3914 CFMutableArrayRef descriptors =
3915 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3922 macfont_language_default_font_names[i].font_names[j];
3925 CFDictionaryRef attributes =
3926 CFDictionaryCreate (NULL,
3928 &MAC_FONT_NAME_ATTRIBUTE),
3930 &macfont_language_default_font_names[i].font_names[j]),
3931 1, &kCFTypeDictionaryKeyCallBacks,
3932 &kCFTypeDictionaryValueCallBacks);
3936 FontDescriptorRef pat_desc =
3937 mac_font_descriptor_create_with_attributes (attributes);
3941 FontDescriptorRef descriptor =
3942 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3946 CFArrayAppendValue (descriptors, descriptor);
3947 CFRelease (descriptor);
3949 CFRelease (pat_desc);
3951 CFRelease (attributes);
3954 result = descriptors;
3966 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3967 CFArrayRef languages)
3969 CFStringRef result = NULL;
3970 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3971 CFArrayRef descriptors =
3972 mac_font_copy_default_descriptors_for_language (language);
3976 CFIndex i, count = CFArrayGetCount (descriptors);
3978 for (i = 0; i < count; i++)
3980 FontDescriptorRef descriptor =
3981 CFArrayGetValueAtIndex (descriptors, i);
3983 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3986 CFStringRef family =
3987 mac_font_descriptor_copy_attribute (descriptor,
3988 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3991 if (!CFStringHasPrefix (family, CFSTR ("."))
3992 && !CFEqual (family, CFSTR ("LastResort")))
4002 CFRelease (descriptors);
4009 macfont_get_nsctfont (struct font *font)
4011 struct macfont_info *macfont_info = (struct macfont_info *) font;
4012 FontRef macfont = macfont_info->macfont;
4014 return (void *) macfont;
4018 mac_register_font_driver (struct frame *f)
4020 register_font_driver (&macfont_driver, f);
4023 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4027 syms_of_macfont (void)
4029 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
4030 static struct font_driver mac_font_driver;
4032 DEFSYM (Qmac_ct, "mac-ct");
4033 macfont_driver.type = Qmac_ct;
4034 register_font_driver (&macfont_driver, NULL);
4036 DEFSYM (QCdestination, ":destination");
4037 DEFSYM (QCminspace, ":minspace");