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 #include <libkern/OSByteOrder.h>
41 static struct font_driver macfont_driver;
43 /* Core Text, for Mac OS X. */
44 static Lisp_Object Qmac_ct;
46 static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
47 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
48 static CFArrayRef mac_ctfont_create_available_families (void);
49 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
50 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
52 static CFComparisonResult mac_font_family_compare (const void *,
53 const void *, void *);
54 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
56 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
57 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
58 struct mac_glyph_layout *, CFIndex);
60 mac_font_copy_default_descriptors_for_language (CFStringRef language);
63 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
64 CFArrayRef languages);
67 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
68 CTCharacterCollection,
72 /* The font property key specifying the font design destination. The
73 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
74 text. (See the documentation of X Logical Font Description
75 Conventions.) In the Mac font driver, 1 means the screen font is
76 used for calculating some glyph metrics. You can see the
77 difference with Monaco 8pt or 9pt, for example. */
78 static Lisp_Object QCdestination;
80 /* The boolean-valued font property key specifying the use of
82 static Lisp_Object QCminspace;
84 struct macfont_metrics;
86 /* The actual structure for Mac font that can be cast to struct font. */
93 ScreenFontRef screen_font;
94 struct macfont_cache *cache;
95 struct macfont_metrics **metrics;
97 bool_bf synthetic_italic_p : 1;
98 bool_bf synthetic_bold_p : 1;
100 unsigned antialias : 2;
101 bool_bf color_bitmap_p : 1;
104 /* Values for the `spacing' member in `struct macfont_info'. */
108 MACFONT_SPACING_PROPORTIONAL,
109 MACFONT_SPACING_MONO,
110 MACFONT_SPACING_SYNTHETIC_MONO,
113 /* Values for the `antialias' member in `struct macfont_info'. */
117 MACFONT_ANTIALIAS_DEFAULT,
118 MACFONT_ANTIALIAS_OFF,
119 MACFONT_ANTIALIAS_ON,
122 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
123 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
124 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
126 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
127 static const CGFloat synthetic_bold_factor = 0.024;
129 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
130 FontSymbolicTraits *);
131 static void macfont_store_descriptor_attributes (FontDescriptorRef,
133 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
136 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
137 static int macfont_glyph_extents (struct font *, CGGlyph,
138 struct font_metrics *, CGFloat *, int);
139 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
140 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
144 static Boolean macfont_closest_traits_index_p (CFArrayRef, FontSymbolicTraits,
146 static CFDataRef mac_font_copy_uvs_table (FontRef);
147 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
149 CGGlyph [], CFIndex);
151 /* From CFData to a lisp string. Always returns a unibyte string. */
154 cfdata_to_lisp (CFDataRef data)
156 CFIndex len = CFDataGetLength (data);
157 Lisp_Object result = make_uninit_string (len);
159 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
166 /* From CFString to a lisp string. Returns a unibyte string
167 containing a UTF-8 byte sequence. */
170 cfstring_to_lisp_nodecode (CFStringRef string)
172 Lisp_Object result = Qnil;
174 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
178 CFIndex i, length = CFStringGetLength (string);
180 for (i = 0; i < length; i++)
181 if (CFStringGetCharacterAtIndex (string, i) == 0)
185 return make_unibyte_string (s, strlen (s));
188 data = CFStringCreateExternalRepresentation (NULL, string,
189 kCFStringEncodingUTF8, '?');
192 result = cfdata_to_lisp (data);
199 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
200 cfstring_create_with_utf8_cstring, this function preserves NUL
204 cfstring_create_with_string_noencode (Lisp_Object s)
206 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
207 kCFStringEncodingUTF8, false);
210 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
211 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
212 kCFStringEncodingMacRoman, false);
218 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
220 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
222 return advancement.width;
226 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
229 #if USE_CT_GLYPH_INFO
230 return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
233 CGGlyph result = kCGFontIndexInvalid;
234 NSFont *nsFont = (NSFont *) font;
235 unichar characters[] = {0xfffd};
237 [NSString stringWithCharacters:characters
238 length:ARRAYELTS (characters)];
239 NSGlyphInfo *glyphInfo =
240 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
241 collection:collection
243 NSDictionary *attributes =
244 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
245 glyphInfo,NSGlyphInfoAttributeName,nil];
246 NSTextStorage *textStorage =
247 [[NSTextStorage alloc] initWithString:string
248 attributes:attributes];
249 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
250 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
251 NSFont *fontInTextStorage;
253 [layoutManager addTextContainer:textContainer];
254 [textContainer release];
255 [textStorage addLayoutManager:layoutManager];
256 [layoutManager release];
259 (void) [layoutManager glyphRangeForTextContainer:textContainer];
261 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
262 effectiveRange:NULL];
263 if (fontInTextStorage == nsFont
264 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
266 NSGlyph glyph = [layoutManager glyphAtIndex:0];
268 if (glyph < [nsFont numberOfGlyphs])
272 [textStorage release];
280 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
282 NSFont *result, *font;
284 font = [NSFont fontWithName:((NSString *) name) size:size];
285 result = [font screenFont];
287 return (ScreenFontRef)[result retain];
292 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
293 CGFloat *descent, CGFloat *leading)
295 NSFont *nsFont = [(NSFont *)font printerFont];
296 NSTextStorage *textStorage;
297 NSLayoutManager *layoutManager;
298 NSTextContainer *textContainer;
300 NSPoint spaceLocation;
303 textStorage = [[NSTextStorage alloc] initWithString:@" "];
304 layoutManager = [[NSLayoutManager alloc] init];
305 textContainer = [[NSTextContainer alloc] init];
307 [textStorage setFont:nsFont];
308 [textContainer setLineFragmentPadding:0];
309 [layoutManager setUsesScreenFonts:YES];
311 [layoutManager addTextContainer:textContainer];
312 [textContainer release];
313 [textStorage addLayoutManager:layoutManager];
314 [layoutManager release];
316 if (!(textStorage && layoutManager && textContainer))
318 [textStorage release];
323 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
324 effectiveRange:NULL];
325 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
326 [textStorage release];
328 *ascent = spaceLocation.y;
329 *descent = NSHeight (usedRect) - spaceLocation.y;
331 descender = [nsFont descender];
332 if (- descender < *descent)
334 *leading = *descent + descender;
335 *descent = - descender;
342 mac_font_shape_1 (NSFont *font, NSString *string,
343 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
348 NSTextStorage *textStorage;
349 NSLayoutManager *layoutManager;
350 NSTextContainer *textContainer;
351 NSUInteger stringLength;
352 NSPoint spaceLocation;
353 NSUInteger used, numberOfGlyphs;
355 textStorage = [[NSTextStorage alloc] initWithString:string];
356 layoutManager = [[NSLayoutManager alloc] init];
357 textContainer = [[NSTextContainer alloc] init];
359 /* Append a trailing space to measure baseline position. */
360 [textStorage appendAttributedString:([[[NSAttributedString alloc]
361 initWithString:@" "] autorelease])];
362 [textStorage setFont:font];
363 [textContainer setLineFragmentPadding:0];
364 [layoutManager setUsesScreenFonts:screen_font_p];
366 [layoutManager addTextContainer:textContainer];
367 [textContainer release];
368 [textStorage addLayoutManager:layoutManager];
369 [layoutManager release];
371 if (!(textStorage && layoutManager && textContainer))
373 [textStorage release];
378 stringLength = [string length];
381 (void) [layoutManager glyphRangeForTextContainer:textContainer];
383 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
385 /* Remove the appended trailing space because otherwise it may
386 generate a wrong result for a right-to-left text. */
387 [textStorage beginEditing];
388 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
389 [textStorage endEditing];
390 (void) [layoutManager glyphRangeForTextContainer:textContainer];
393 while (i < stringLength)
396 NSFont *fontInTextStorage =
397 [textStorage attribute:NSFontAttributeName atIndex:i
398 longestEffectiveRange:&range
399 inRange:(NSMakeRange (0, stringLength))];
401 if (!(fontInTextStorage == font
402 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
404 i = NSMaxRange (range);
406 if (i < stringLength)
407 /* Make the test `used <= glyph_len' below fail if textStorage
408 contained some fonts other than the specified one. */
409 used = glyph_len + 1;
412 NSRange range = NSMakeRange (0, stringLength);
414 range = [layoutManager glyphRangeForCharacterRange:range
415 actualCharacterRange:NULL];
416 numberOfGlyphs = NSMaxRange (range);
417 used = numberOfGlyphs;
418 for (i = 0; i < numberOfGlyphs; i++)
419 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
423 if (0 < used && used <= glyph_len)
425 NSUInteger glyphIndex, prevGlyphIndex;
426 unsigned char bidiLevel;
427 NSUInteger *permutation;
428 NSRange compRange, range;
429 CGFloat totalAdvance;
432 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
435 /* For now we assume the direction is not changed within the
437 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
438 glyphs:NULL characterIndexes:NULL
439 glyphInscriptions:NULL elasticBits:NULL
440 bidiLevels:&bidiLevel];
442 permutation = xmalloc (sizeof (NSUInteger) * used);
446 #define RIGHT_TO_LEFT_P permutation
448 /* Fill the `comp_range' member of struct mac_glyph_layout, and
449 setup a permutation for right-to-left text. */
450 compRange = NSMakeRange (0, 0);
451 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
454 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
455 NSUInteger characterIndex =
456 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
458 gl->string_index = characterIndex;
460 if (characterIndex >= NSMaxRange (compRange))
462 compRange.location = NSMaxRange (compRange);
465 NSRange characterRange =
467 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
470 NSMaxRange (characterRange) - compRange.location;
471 [layoutManager glyphRangeForCharacterRange:compRange
472 actualCharacterRange:&characterRange];
473 characterIndex = NSMaxRange (characterRange) - 1;
475 while (characterIndex >= NSMaxRange (compRange));
478 for (i = 0; i < range.length; i++)
479 permutation[range.location + i] = NSMaxRange (range) - i - 1;
481 range = NSMakeRange (NSMaxRange (range), 0);
484 gl->comp_range.location = compRange.location;
485 gl->comp_range.length = compRange.length;
487 while (++glyphIndex < numberOfGlyphs)
488 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
492 for (i = 0; i < range.length; i++)
493 permutation[range.location + i] = NSMaxRange (range) - i - 1;
495 /* Then fill the remaining members. */
496 glyphIndex = prevGlyphIndex = 0;
497 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
500 if (!RIGHT_TO_LEFT_P)
507 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
508 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
509 inTextContainer:textContainer rectCount:&nrects];
511 totalAdvance = NSMaxX (glyphRects[0]);
514 for (i = 0; i < used; i++)
516 struct mac_glyph_layout *gl;
518 NSUInteger nextGlyphIndex;
523 if (!RIGHT_TO_LEFT_P)
524 gl = glyph_layouts + i;
527 NSUInteger dest = permutation[i];
529 gl = glyph_layouts + dest;
532 CFIndex tmp = gl->string_index;
534 gl->string_index = glyph_layouts[i].string_index;
535 glyph_layouts[i].string_index = tmp;
538 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
540 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
541 gl->baseline_delta = spaceLocation.y - location.y;
543 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
546 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
549 if (!RIGHT_TO_LEFT_P)
553 if (prevGlyphIndex == 0)
554 glyphRange = NSMakeRange (0, nextGlyphIndex);
556 glyphRange = NSMakeRange (glyphIndex,
557 nextGlyphIndex - glyphIndex);
560 rectArrayForGlyphRange:glyphRange
561 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
562 inTextContainer:textContainer rectCount:&nrects];
563 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
564 gl->advance_delta = location.x - totalAdvance;
565 gl->advance = maxX - totalAdvance;
572 if (nextGlyphIndex == numberOfGlyphs)
573 glyphRange = NSMakeRange (prevGlyphIndex,
574 numberOfGlyphs - prevGlyphIndex);
576 glyphRange = NSMakeRange (prevGlyphIndex,
577 glyphIndex + 1 - prevGlyphIndex);
580 rectArrayForGlyphRange:glyphRange
581 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
582 inTextContainer:textContainer rectCount:&nrects];
583 minX = min (NSMinX (glyphRects[0]), totalAdvance);
584 gl->advance = totalAdvance - minX;
586 gl->advance_delta = location.x - totalAdvance;
589 prevGlyphIndex = glyphIndex + 1;
590 glyphIndex = nextGlyphIndex;
596 #undef RIGHT_TO_LEFT_P
600 [textStorage release];
606 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
607 struct mac_glyph_layout *glyph_layouts,
610 return mac_font_shape_1 ([(NSFont *)font printerFont],
612 glyph_layouts, glyph_len, YES);
616 get_cgcolor(unsigned long idx, struct frame *f)
618 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
620 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
621 NSInteger noc = [nsColor numberOfComponents];
622 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
625 [nsColor getComponents: components];
626 cgColor = CGColorCreate (colorSpace, components);
631 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
633 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
634 CGContextSetFillColorWithColor (context, refcol_) ; \
635 CGColorRelease (refcol_); \
637 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
639 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
640 CGContextSetFillColorWithColor (context, refcol_); \
641 CGColorRelease (refcol_); \
643 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
645 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
646 CGContextSetStrokeColorWithColor (context, refcol_); \
647 CGColorRelease (refcol_); \
652 /* Mac font driver. */
658 /* characters to distinguish the charset from the others */
660 /* additional constraint by language */
663 CFCharacterSetRef cf_charset;
664 CFStringRef cf_charset_string;
665 } cf_charset_table[] =
666 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
667 { "iso8859-2", { 0x00A0, 0x010E }},
668 { "iso8859-3", { 0x00A0, 0x0108 }},
669 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
670 { "iso8859-5", { 0x00A0, 0x0401 }},
671 { "iso8859-6", { 0x00A0, 0x060C }},
672 { "iso8859-7", { 0x00A0, 0x0384 }},
673 { "iso8859-8", { 0x00A0, 0x05D0 }},
674 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
675 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
676 { "iso8859-11", { 0x00A0, 0x0E01 }},
677 { "iso8859-13", { 0x00A0, 0x201C }},
678 { "iso8859-14", { 0x00A0, 0x0174 }},
679 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
680 { "iso8859-16", { 0x00A0, 0x0218}},
681 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
682 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
683 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
684 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
685 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
686 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
687 { "cns11643.1992-3", { 0x201A9 }},
688 { "cns11643.1992-4", { 0x20057 }},
689 { "cns11643.1992-5", { 0x20000 }},
690 { "cns11643.1992-6", { 0x20003 }},
691 { "cns11643.1992-7", { 0x20055 }},
692 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
693 { "jisx0212.1990-0", { 0x4E44 }},
694 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
695 { "jisx0213.2000-2", { 0xFA49 }},
696 { "jisx0213.2004-1", { 0x20B9F }},
697 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
698 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
699 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
700 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
701 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
702 { "unicode-sip", { 0x20000 }},
706 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
709 CFStringRef language;
710 CFStringRef font_names[3];
711 } macfont_language_default_font_names[] = {
712 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
713 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
715 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
716 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
718 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
719 CFSTR ("STXihei"), /* 10.4 - 10.5 */
721 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
722 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
728 static CGFloat macfont_antialias_threshold;
731 macfont_update_antialias_threshold (void)
737 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
738 kCFPreferencesCurrentApplication,
741 macfont_antialias_threshold = threshold;
744 static inline Lisp_Object
745 macfont_intern_prop_cfstring (CFStringRef cfstring)
747 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
749 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
752 static inline CFIndex
753 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
764 unichars[0] = (c >> 10) + 0xD800;
765 unichars[1] = (c & 0x3FF) + 0xDC00;
772 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
773 FontSymbolicTraits *sym_traits)
777 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
778 OS X 10.6 when the value is greater than or equal to 1 << 31. */
779 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
781 *sym_traits = (FontSymbolicTraits) sint64_value;
790 macfont_store_descriptor_attributes (FontDescriptorRef desc,
791 Lisp_Object spec_or_entity)
794 CFDictionaryRef dict;
798 str = mac_font_descriptor_copy_attribute (desc,
799 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
802 ASET (spec_or_entity, FONT_FAMILY_INDEX,
803 macfont_intern_prop_cfstring (str));
806 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
810 enum font_property_index index;
814 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
815 {{-0.4, 50}, /* light */
816 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
817 {0, 100}, /* normal */
818 {0.24, 140}, /* (semi-bold + normal) / 2 */
819 {0.4, 200}, /* bold */
820 {CGFLOAT_MAX, CGFLOAT_MAX}}},
821 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
822 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
823 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
824 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
827 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
829 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
830 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
832 CGPoint *point = numeric_traits[i].points;
834 while (point->x < floatval)
836 if (point == numeric_traits[i].points)
838 else if (point->x == CGFLOAT_MAX)
840 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
841 * ((point->y - (point - 1)->y)
842 / (point->x - (point - 1)->x)));
843 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
844 make_number (lround (floatval)));
848 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
851 FontSymbolicTraits sym_traits;
854 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
855 spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
856 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
857 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
862 num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
863 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
864 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
866 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
872 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
873 FontSymbolicTraits synth_sym_traits)
876 CFDictionaryRef dict;
877 FontSymbolicTraits sym_traits = 0;
880 entity = font_make_entity ();
882 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
883 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
885 macfont_store_descriptor_attributes (desc, entity);
887 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
890 CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
893 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
896 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
897 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
898 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
899 name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
900 font_put_extra (entity, QCfont_entity,
901 make_save_ptr_int ((void *) name, sym_traits));
902 if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
903 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
904 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
905 if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
906 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
907 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
908 if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
909 ASET (entity, FONT_SPACING_INDEX,
910 make_number (FONT_SPACING_SYNTHETIC_MONO));
916 macfont_create_family_with_symbol (Lisp_Object symbol)
918 static CFArrayRef families = NULL;
919 CFStringRef result = NULL, family_name;
920 int using_cache_p = 1;
921 CFComparatorFunction family_name_comparator;
923 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
924 if (family_name == NULL)
928 family_name_comparator = CTFontManagerCompareFontFamilyNames;
931 if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
932 == kCFCompareEqualTo)
933 result = CFSTR ("LastResort");
939 if (families == NULL)
941 families = mac_font_create_available_families ();
943 if (families == NULL)
947 count = CFArrayGetCount (families);
948 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
949 (const void *) family_name,
950 family_name_comparator, NULL);
953 CFStringRef name = CFArrayGetValueAtIndex (families, i);
955 if ((*family_name_comparator) (name, family_name, NULL)
956 == kCFCompareEqualTo)
957 result = CFRetain (name);
960 if (result || !using_cache_p)
964 CFRelease (families);
969 CFRelease (family_name);
974 #define WIDTH_FRAC_BITS (4)
975 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
977 struct macfont_metrics
979 unsigned char lbearing_low, rbearing_low;
980 signed lbearing_high : 4, rbearing_high : 4;
981 unsigned char ascent_low, descent_low;
982 signed ascent_high : 4, descent_high : 4;
984 /* These two members are used for fixed-point representation of
985 glyph width. The `width_int' member is an integer that is
986 closest to the width. The `width_frac' member is the fractional
987 adjustment representing a value in [-.5, .5], multiplied by
988 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
989 the advance delta for centering instead of the glyph width. */
990 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
993 #define METRICS_VALUE(metrics, member) \
994 (((metrics)->member##_high << 8) | (metrics)->member##_low)
995 #define METRICS_SET_VALUE(metrics, member, value) \
996 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
997 (metrics)->member##_high = tmp >> 8;} while (0)
1001 METRICS_INVALID = -1, /* metrics entry is invalid */
1002 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
1005 #define METRICS_STATUS(metrics) \
1006 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
1007 #define METRICS_SET_STATUS(metrics, status) \
1008 do {METRICS_SET_VALUE (metrics, ascent, 0); \
1009 METRICS_SET_VALUE (metrics, descent, status);} while (0)
1011 #define METRICS_NCOLS_PER_ROW (128)
1012 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1013 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1016 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1017 struct font_metrics *metrics, CGFloat *advance_delta,
1018 int force_integral_p)
1020 struct macfont_info *macfont_info = (struct macfont_info *) font;
1021 FontRef macfont = macfont_info->macfont;
1023 struct macfont_metrics *cache;
1026 row = glyph / METRICS_NCOLS_PER_ROW;
1027 col = glyph % METRICS_NCOLS_PER_ROW;
1028 if (row >= macfont_info->metrics_nrows)
1030 macfont_info->metrics =
1031 xrealloc (macfont_info->metrics,
1032 sizeof (struct macfont_metrics *) * (row + 1));
1033 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1034 (sizeof (struct macfont_metrics *)
1035 * (row + 1 - macfont_info->metrics_nrows)));
1036 macfont_info->metrics_nrows = row + 1;
1038 if (macfont_info->metrics[row] == NULL)
1040 struct macfont_metrics *new;
1043 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1044 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1045 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1046 macfont_info->metrics[row] = new;
1048 cache = macfont_info->metrics[row] + col;
1050 if (METRICS_STATUS (cache) == METRICS_INVALID)
1054 if (macfont_info->screen_font)
1055 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1057 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1059 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1060 advance delta value. */
1061 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1062 fwidth = (font->pixel_size - fwidth) / 2;
1063 cache->width_int = lround (fwidth);
1064 cache->width_frac = lround ((fwidth - cache->width_int)
1065 * WIDTH_FRAC_SCALE);
1066 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1068 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1069 width = font->pixel_size;
1071 width = cache->width_int;
1075 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1077 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1079 if (macfont_info->synthetic_italic_p)
1081 /* We assume the members a, b, c, and d in
1082 synthetic_italic_atfm are non-negative. */
1084 CGPointApplyAffineTransform (bounds.origin,
1085 synthetic_italic_atfm);
1087 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1089 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1092 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1094 bounds = CGRectInset (bounds, d, d);
1096 switch (macfont_info->spacing)
1098 case MACFONT_SPACING_PROPORTIONAL:
1099 bounds.origin.x += - (cache->width_frac
1100 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1102 case MACFONT_SPACING_MONO:
1104 case MACFONT_SPACING_SYNTHETIC_MONO:
1105 bounds.origin.x += (cache->width_int
1106 + (cache->width_frac
1107 / (CGFloat) WIDTH_FRAC_SCALE));
1110 if (bounds.size.width > 0)
1112 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1113 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1114 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1116 bounds = CGRectIntegral (bounds);
1117 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1118 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1119 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1120 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1122 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1123 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1124 metrics->width = width;
1125 metrics->ascent = METRICS_VALUE (cache, ascent);
1126 metrics->descent = METRICS_VALUE (cache, descent);
1131 switch (macfont_info->spacing)
1133 case MACFONT_SPACING_PROPORTIONAL:
1134 *advance_delta = (force_integral_p ? 0
1135 : - (cache->width_frac
1136 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1138 case MACFONT_SPACING_MONO:
1141 case MACFONT_SPACING_SYNTHETIC_MONO:
1142 *advance_delta = (force_integral_p ? cache->width_int
1144 + (cache->width_frac
1145 / (CGFloat) WIDTH_FRAC_SCALE)));
1153 static CFMutableDictionaryRef macfont_cache_dictionary;
1155 /* Threshold used in row_nkeys_or_perm. This must be less than or
1156 equal to the number of rows that are invalid as BMP (i.e., from
1157 U+D800 to U+DFFF). */
1158 #define ROW_PERM_OFFSET (8)
1160 /* The number of glyphs that can be stored in a value for a single
1161 entry of CFDictionary. */
1162 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1164 struct macfont_cache
1166 int reference_count;
1167 CFCharacterSetRef cf_charset;
1169 /* The cached glyph for a BMP character c is stored in
1170 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1171 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1172 unsigned char row_nkeys_or_perm[256];
1175 /* Number of rows for which the BMP cache is allocated so far.
1176 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1179 /* The cached glyph for a character c is stored as the (c %
1180 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1181 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1182 not stored here if row_nkeys_or_perm[c / 256] >=
1184 CFMutableDictionaryRef dictionary;
1188 /* UVS (Unicode Variation Sequence) subtable data, which is of
1189 type CFDataRef if available. NULL means it is not initialized
1190 yet. kCFNull means the subtable is not found and there is no
1191 suitable fallback table for this font. */
1194 /* Character collection specifying the destination of the mapping
1195 provided by `table' above. If `table' is obtained from the UVS
1196 subtable in the font cmap table, then the value of this member
1197 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1198 CharacterCollection collection;
1202 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1203 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1204 static void macfont_release_cache (struct macfont_cache *);
1205 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1206 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1207 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1208 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1209 CharacterCollection, CGFontIndex);
1210 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1212 static struct macfont_cache *
1213 macfont_lookup_cache (CFStringRef key)
1215 struct macfont_cache *cache;
1217 if (macfont_cache_dictionary == NULL)
1219 macfont_cache_dictionary =
1220 CFDictionaryCreateMutable (NULL, 0,
1221 &kCFTypeDictionaryKeyCallBacks, NULL);
1225 cache = ((struct macfont_cache *)
1226 CFDictionaryGetValue (macfont_cache_dictionary, key));
1230 FontRef macfont = mac_font_create_with_name (key, 0);
1234 cache = xzalloc (sizeof (struct macfont_cache));
1235 /* Treat the LastResort font as if it contained glyphs for
1236 all characters. This may look too rough, but neither
1237 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1238 for this font is correct for non-BMP characters on Mac OS
1240 if (CFEqual (key, CFSTR ("LastResort")))
1242 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1245 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1247 if (cache->cf_charset == NULL)
1248 cache->cf_charset = mac_font_copy_character_set (macfont);
1249 CFDictionaryAddValue (macfont_cache_dictionary, key,
1250 (const void *) cache);
1251 CFRelease (macfont);
1258 static struct macfont_cache *
1259 macfont_retain_cache (struct macfont_cache *cache)
1261 cache->reference_count++;
1267 macfont_release_cache (struct macfont_cache *cache)
1269 if (--cache->reference_count == 0)
1273 for (i = 0; i < cache->glyph.nrows; i++)
1274 xfree (cache->glyph.matrix[i]);
1275 xfree (cache->glyph.matrix);
1276 if (cache->glyph.dictionary)
1277 CFRelease (cache->glyph.dictionary);
1278 memset (&cache->glyph, 0, sizeof (cache->glyph));
1279 if (cache->uvs.table)
1280 CFRelease (cache->uvs.table);
1281 memset (&cache->uvs, 0, sizeof (cache->uvs));
1285 static CFCharacterSetRef
1286 macfont_get_cf_charset (struct font *font)
1288 struct macfont_info *macfont_info = (struct macfont_info *) font;
1290 return macfont_info->cache->cf_charset;
1293 static CFCharacterSetRef
1294 macfont_get_cf_charset_for_name (CFStringRef name)
1296 struct macfont_cache *cache = macfont_lookup_cache (name);
1298 return cache->cf_charset;
1302 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1304 struct macfont_info *macfont_info = (struct macfont_info *) font;
1305 FontRef macfont = macfont_info->macfont;
1306 struct macfont_cache *cache = macfont_info->cache;
1308 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1311 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1313 if (nkeys_or_perm < ROW_PERM_OFFSET)
1315 UniChar unichars[256], ch;
1319 dispatch_queue_t queue;
1320 dispatch_group_t group = NULL;
1324 CFMutableDictionaryRef dictionary;
1325 uintptr_t key, value;
1329 if (cache->glyph.dictionary == NULL)
1330 cache->glyph.dictionary =
1331 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1332 dictionary = cache->glyph.dictionary;
1333 key = c / NGLYPHS_IN_VALUE;
1334 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1335 value = ((uintptr_t)
1336 CFDictionaryGetValue (dictionary, (const void *) key));
1337 glyph = (value >> nshifts);
1341 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1344 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1347 glyph = kCGFontIndexInvalid;
1350 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1351 value |= ((uintptr_t) glyph << nshifts);
1352 CFDictionarySetValue (dictionary, (const void *) key,
1353 (const void *) value);
1359 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1360 group = dispatch_group_create ();
1361 dispatch_group_async (group, queue, ^{
1364 nkeys = nkeys_or_perm;
1365 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1366 if (CFDictionaryContainsKey (dictionary,
1367 (const void *) key))
1369 CFDictionaryRemoveValue (dictionary,
1370 (const void *) key);
1378 for (i = 0; i < 256; i++)
1381 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1382 unichars[len++] = ch;
1385 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1388 mac_font_get_glyphs_for_characters (macfont, unichars,
1392 int next = unichars[len - 1] % 256;
1395 glyphs[i] = kCGFontIndexInvalid;
1398 glyphs[i] = glyphs[len];
1405 glyphs[i] = kCGFontIndexInvalid;
1407 nrows = cache->glyph.nrows;
1408 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1409 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1411 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1412 sizeof (CGGlyph *) * nrows);
1413 cache->glyph.matrix[nrows - 1] = glyphs;
1414 cache->glyph.nrows = nrows;
1418 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1419 dispatch_release (group);
1423 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1427 uintptr_t key, value;
1431 if (cache->glyph.dictionary == NULL)
1432 cache->glyph.dictionary =
1433 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1434 key = c / NGLYPHS_IN_VALUE;
1435 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1436 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1437 (const void *) key);
1438 glyph = (value >> nshifts);
1441 UniChar unichars[2];
1443 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1445 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1449 glyph = kCGFontIndexInvalid;
1451 value |= ((uintptr_t) glyph << nshifts);
1452 CFDictionarySetValue (cache->glyph.dictionary,
1453 (const void *) key, (const void *) value);
1461 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1464 struct macfont_info *macfont_info = (struct macfont_info *) font;
1465 FontRef macfont = macfont_info->macfont;
1468 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1472 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1474 struct macfont_info *macfont_info = (struct macfont_info *) font;
1475 FontRef macfont = macfont_info->macfont;
1476 struct macfont_cache *cache = macfont_info->cache;
1477 CFDataRef result = NULL;
1479 if (cache->uvs.table == NULL)
1481 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1482 CharacterCollection uvs_collection =
1483 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1485 if (uvs_table == NULL
1486 && mac_font_get_glyph_for_cid (macfont,
1487 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1488 6480) != kCGFontIndexInvalid)
1490 /* If the glyph for U+4E55 is accessible via its CID 6480,
1491 then we use the Adobe-Japan1 UVS table, which maps a
1492 variation sequence to a CID, as a fallback. */
1493 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1495 if (mac_uvs_table_adobe_japan1 == NULL)
1496 mac_uvs_table_adobe_japan1 =
1497 CFDataCreateWithBytesNoCopy (NULL,
1498 mac_uvs_table_adobe_japan1_bytes,
1499 sizeof (mac_uvs_table_adobe_japan1_bytes),
1501 if (mac_uvs_table_adobe_japan1)
1503 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1504 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1507 if (uvs_table == NULL)
1508 cache->uvs.table = kCFNull;
1510 cache->uvs.table = uvs_table;
1511 cache->uvs.collection = uvs_collection;
1514 if (cache->uvs.table != kCFNull)
1516 result = cache->uvs.table;
1517 *collection = cache->uvs.collection;
1523 static Lisp_Object macfont_get_cache (struct frame *);
1524 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1525 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1526 static Lisp_Object macfont_list_family (struct frame *);
1527 static void macfont_free_entity (Lisp_Object);
1528 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1529 static void macfont_close (struct font *);
1530 static int macfont_has_char (Lisp_Object, int);
1531 static unsigned macfont_encode_char (struct font *, int);
1532 static void macfont_text_extents (struct font *, unsigned int *, int,
1533 struct font_metrics *);
1534 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1535 static Lisp_Object macfont_shape (Lisp_Object);
1536 static int macfont_variation_glyphs (struct font *, int c,
1537 unsigned variations[256]);
1538 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1540 static struct font_driver macfont_driver =
1542 LISP_INITIALLY_ZERO, /* Qmac_ct */
1543 0, /* case insensitive */
1547 macfont_list_family,
1548 macfont_free_entity,
1551 NULL, /* prepare_face */
1552 NULL, /* done_face */
1554 macfont_encode_char,
1555 macfont_text_extents,
1557 NULL, /* get_bitmap */
1558 NULL, /* free_bitmap */
1559 NULL, /* anchor_point */
1560 NULL, /* otf_capability */
1561 NULL, /* otf_drive */
1562 NULL, /* start_for_frame */
1563 NULL, /* end_for_frame */
1566 macfont_variation_glyphs,
1567 macfont_filter_properties,
1571 macfont_get_cache (struct frame * f)
1573 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1575 return (dpyinfo->name_list_element);
1579 macfont_get_charset (Lisp_Object registry)
1581 char *str = SSDATA (SYMBOL_NAME (registry));
1582 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1586 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1590 else if (str[i] == '*')
1597 regexp = make_unibyte_string (re, j);
1598 for (i = 0; cf_charset_table[i].name; i++)
1599 if (fast_c_string_match_ignore_case
1600 (regexp, cf_charset_table[i].name,
1601 strlen (cf_charset_table[i].name)) >= 0)
1603 if (! cf_charset_table[i].name)
1605 if (! cf_charset_table[i].cf_charset)
1607 int *uniquifier = cf_charset_table[i].uniquifier;
1608 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1611 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1615 for (j = 0; uniquifier[j]; j++)
1617 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1619 CFCharacterSetAddCharactersInRange (charset,
1620 CFRangeMake (uniquifier[j], 1));
1623 string = CFStringCreateWithCharacters (NULL, unichars, count);
1626 CFRelease (charset);
1629 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1631 CFRelease (charset);
1632 /* CFCharacterSetCreateWithCharactersInString does not handle
1633 surrogate pairs properly as of Mac OS X 10.5. */
1634 cf_charset_table[i].cf_charset_string = string;
1642 unsigned int script_tag, langsys_tag;
1644 unsigned int *features[2];
1647 #define OTF_SYM_TAG(SYM, TAG) \
1649 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1650 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1653 #define OTF_TAG_STR(TAG, P) \
1655 (P)[0] = (char) (TAG >> 24); \
1656 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1657 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1658 (P)[3] = (char) (TAG & 0xFF); \
1662 static struct OpenTypeSpec *
1663 macfont_get_open_type_spec (Lisp_Object otf_spec)
1665 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1672 spec->script = XCAR (otf_spec);
1673 if (! NILP (spec->script))
1675 OTF_SYM_TAG (spec->script, spec->script_tag);
1676 val = assq_no_quit (spec->script, Votf_script_alist);
1677 if (CONSP (val) && SYMBOLP (XCDR (val)))
1678 spec->script = XCDR (val);
1680 spec->script = Qnil;
1683 spec->script_tag = 0x44464C54; /* "DFLT" */
1684 otf_spec = XCDR (otf_spec);
1685 spec->langsys_tag = 0;
1686 if (! NILP (otf_spec))
1688 val = XCAR (otf_spec);
1690 OTF_SYM_TAG (val, spec->langsys_tag);
1691 otf_spec = XCDR (otf_spec);
1693 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1694 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1698 val = XCAR (otf_spec);
1701 len = Flength (val);
1703 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1705 : malloc (XINT (len) * sizeof *spec->features[i]));
1706 if (! spec->features[i])
1708 if (i > 0 && spec->features[0])
1709 free (spec->features[0]);
1713 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1715 if (NILP (XCAR (val)))
1721 OTF_SYM_TAG (XCAR (val), tag);
1722 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1725 spec->nfeatures[i] = j;
1730 static CFMutableDictionaryRef
1731 macfont_create_attributes_with_spec (Lisp_Object spec)
1733 Lisp_Object tmp, extra;
1734 CFMutableArrayRef langarray = NULL;
1735 CFCharacterSetRef charset = NULL;
1736 CFStringRef charset_string = NULL;
1737 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1738 Lisp_Object script = Qnil;
1739 Lisp_Object registry;
1740 int cf_charset_idx, i;
1741 struct OpenTypeSpec *otspec = NULL;
1743 enum font_property_index index;
1746 } numeric_traits[] =
1747 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1748 {{-0.4, 50}, /* light */
1749 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1750 {0, 100}, /* normal */
1751 {0.24, 140}, /* (semi-bold + normal) / 2 */
1752 {0.4, 200}, /* bold */
1753 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1754 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1755 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1756 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1757 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1759 registry = AREF (spec, FONT_REGISTRY_INDEX);
1761 || EQ (registry, Qascii_0)
1762 || EQ (registry, Qiso10646_1)
1763 || EQ (registry, Qunicode_bmp))
1764 cf_charset_idx = -1;
1769 cf_charset_idx = macfont_get_charset (registry);
1770 if (cf_charset_idx < 0)
1772 charset = cf_charset_table[cf_charset_idx].cf_charset;
1773 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1774 lang = cf_charset_table[cf_charset_idx].lang;
1777 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1780 CFArrayAppendValue (langarray, lang);
1784 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1785 CONSP (extra); extra = XCDR (extra))
1787 Lisp_Object key, val;
1790 key = XCAR (tmp), val = XCDR (tmp);
1791 if (EQ (key, QClang))
1794 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1799 for (; CONSP (val); val = XCDR (val))
1800 if (SYMBOLP (XCAR (val)))
1803 cfstring_create_with_string_noencode (SYMBOL_NAME
1808 CFArrayAppendValue (langarray, lang);
1812 else if (EQ (key, QCotf))
1814 otspec = macfont_get_open_type_spec (val);
1817 script = otspec->script;
1819 else if (EQ (key, QCscript))
1823 if (! NILP (script) && ! charset)
1825 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1827 if (CONSP (chars) && CONSP (CDR (chars)))
1829 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1830 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1832 if (! string || !cs)
1840 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1841 if (CHARACTERP (XCAR (chars)))
1843 UniChar unichars[2];
1845 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1847 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1849 CFStringAppendCharacters (string, unichars, count);
1850 CFCharacterSetAddCharactersInRange (cs, range);
1853 /* CFCharacterSetCreateWithCharactersInString does not
1854 handle surrogate pairs properly as of Mac OS X 10.5. */
1855 charset_string = string;
1859 attributes = CFDictionaryCreateMutable (NULL, 0,
1860 &kCFTypeDictionaryKeyCallBacks,
1861 &kCFTypeDictionaryValueCallBacks);
1865 tmp = AREF (spec, FONT_FAMILY_INDEX);
1866 if (SYMBOLP (tmp) && ! NILP (tmp))
1868 CFStringRef family = macfont_create_family_with_symbol (tmp);
1872 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1877 traits = CFDictionaryCreateMutable (NULL, 4,
1878 &kCFTypeDictionaryKeyCallBacks,
1879 &kCFTypeDictionaryValueCallBacks);
1883 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1885 tmp = AREF (spec, numeric_traits[i].index);
1888 CGPoint *point = numeric_traits[i].points;
1889 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1892 while (point->y < floatval)
1894 if (point == numeric_traits[i].points)
1896 else if (point->y == CGFLOAT_MAX)
1898 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1899 * ((point->x - (point - 1)->x)
1900 / (point->y - (point - 1)->y)));
1903 else if (floatval < -1.0)
1905 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1908 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1912 if (CFDictionaryGetCount (traits))
1913 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1916 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1919 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1922 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1929 CFRelease (attributes);
1934 if (langarray) CFRelease (langarray);
1935 if (charset && cf_charset_idx < 0) CFRelease (charset);
1936 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1937 if (traits) CFRelease (traits);
1940 if (otspec->nfeatures[0] > 0)
1941 free (otspec->features[0]);
1942 if (otspec->nfeatures[1] > 0)
1943 free (otspec->features[1]);
1951 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1952 CFCharacterSetRef charset,
1954 CFArrayRef languages)
1956 Boolean result = true;
1958 if (charset || VECTORP (chars))
1960 CFCharacterSetRef desc_charset =
1961 mac_font_descriptor_copy_attribute (desc,
1962 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1964 if (desc_charset == NULL)
1969 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1970 else /* VECTORP (chars) */
1974 for (j = 0; j < ASIZE (chars); j++)
1975 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
1976 && CFCharacterSetIsLongCharacterMember (desc_charset,
1977 XFASTINT (AREF (chars, j))))
1979 if (j == ASIZE (chars))
1982 CFRelease (desc_charset);
1985 if (result && languages)
1986 result = mac_font_descriptor_supports_languages (desc, languages);
1992 macfont_traits_distance (FontSymbolicTraits sym_traits1,
1993 FontSymbolicTraits sym_traits2)
1995 FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
1998 /* We prefer synthetic bold of italic to synthetic italic of bold
1999 when both bold and italic are available but bold-italic is not
2001 if (diff & MAC_FONT_TRAIT_BOLD)
2002 distance |= (1 << 0);
2003 if (diff & MAC_FONT_TRAIT_ITALIC)
2004 distance |= (1 << 1);
2005 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2006 distance |= (1 << 2);
2012 macfont_closest_traits_index_p (CFArrayRef traits_array,
2013 FontSymbolicTraits target,
2016 CFIndex i, count = CFArrayGetCount (traits_array);
2017 FontSymbolicTraits traits;
2020 traits = ((FontSymbolicTraits) (uintptr_t)
2021 CFArrayGetValueAtIndex (traits_array, index));
2022 my_distance = macfont_traits_distance (target, traits);
2024 for (i = 0; i < count; i++)
2027 traits = ((FontSymbolicTraits) (uintptr_t)
2028 CFArrayGetValueAtIndex (traits_array, i));
2029 if (macfont_traits_distance (target, traits) < my_distance)
2037 macfont_list (struct frame *f, Lisp_Object spec)
2039 Lisp_Object val = Qnil, family, extra;
2041 CFStringRef family_name = NULL;
2042 CFMutableDictionaryRef attributes = NULL, traits;
2043 Lisp_Object chars = Qnil;
2045 FontSymbolicTraits synth_sym_traits = 0;
2046 CFArrayRef families;
2047 CFIndex families_count;
2048 CFCharacterSetRef charset = NULL;
2049 CFArrayRef languages = NULL;
2053 family = AREF (spec, FONT_FAMILY_INDEX);
2054 if (! NILP (family))
2056 family_name = macfont_create_family_with_symbol (family);
2057 if (family_name == NULL)
2061 attributes = macfont_create_attributes_with_spec (spec);
2065 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2067 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2068 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2070 traits = ((CFMutableDictionaryRef)
2071 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2073 n = FONT_SLANT_NUMERIC (spec);
2074 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2076 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2078 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2081 n = FONT_WEIGHT_NUMERIC (spec);
2082 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2084 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2086 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2090 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2092 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2094 if (CFStringHasPrefix (language, CFSTR ("ja"))
2095 || CFStringHasPrefix (language, CFSTR ("ko"))
2096 || CFStringHasPrefix (language, CFSTR ("zh")))
2097 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2100 /* Create array of families. */
2102 families = CFArrayCreate (NULL, (const void **) &family_name,
2103 1, &kCFTypeArrayCallBacks);
2106 CFStringRef pref_family;
2107 CFIndex families_count, pref_family_index = -1;
2109 families = mac_font_create_available_families ();
2110 if (families == NULL)
2113 families_count = CFArrayGetCount (families);
2115 /* Move preferred family to the front if exists. */
2117 mac_font_create_preferred_family_for_attributes (attributes);
2121 CFArrayGetFirstIndexOfValue (families,
2122 CFRangeMake (0, families_count),
2124 CFRelease (pref_family);
2126 if (pref_family_index > 0)
2128 CFMutableArrayRef mutable_families =
2129 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2131 if (mutable_families)
2133 CFArrayAppendValue (mutable_families,
2134 CFArrayGetValueAtIndex (families,
2135 pref_family_index));
2136 CFArrayAppendArray (mutable_families, families,
2137 CFRangeMake (0, pref_family_index));
2138 if (pref_family_index + 1 < families_count)
2139 CFArrayAppendArray (mutable_families, families,
2140 CFRangeMake (pref_family_index + 1,
2142 - (pref_family_index + 1)));
2143 CFRelease (families);
2144 families = mutable_families;
2149 charset = CFDictionaryGetValue (attributes,
2150 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2154 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2158 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2161 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2162 if (CONSP (val) && VECTORP (XCDR (val)))
2170 CFRetain (languages);
2171 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2175 extra = AREF (spec, FONT_EXTRA_INDEX);
2176 families_count = CFArrayGetCount (families);
2177 for (i = 0; i < families_count; i++)
2179 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2180 FontDescriptorRef pat_desc;
2182 CFIndex descs_count;
2183 CFMutableArrayRef filtered_descs, traits_array;
2187 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2189 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2193 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2194 10.7 returns NULL if pat_desc represents the LastResort font.
2195 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2196 trailing "s") for such a font. */
2197 if (!CFEqual (family_name, CFSTR ("LastResort")))
2198 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2202 FontDescriptorRef lr_desc =
2203 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2207 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2208 &kCFTypeArrayCallBacks);
2209 CFRelease (lr_desc);
2214 CFRelease (pat_desc);
2218 descs_count = CFArrayGetCount (descs);
2219 if (descs_count == 0
2220 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2229 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2230 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2231 for (j = 0; j < descs_count; j++)
2233 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2234 CFDictionaryRef dict;
2236 FontSymbolicTraits sym_traits;
2238 dict = mac_font_descriptor_copy_attribute (desc,
2239 MAC_FONT_TRAITS_ATTRIBUTE);
2243 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2246 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2250 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2251 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2252 != (spacing >= FONT_SPACING_MONO)))
2255 /* Don't use a color bitmap font unless its family is
2256 explicitly specified. */
2257 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2261 && !macfont_supports_charset_and_languages_p (desc, charset,
2265 CFArrayAppendValue (filtered_descs, desc);
2266 CFArrayAppendValue (traits_array,
2267 (const void *) (uintptr_t) sym_traits);
2271 descs = filtered_descs;
2272 descs_count = CFArrayGetCount (descs);
2274 for (j = 0; j < descs_count; j++)
2276 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2277 FontSymbolicTraits sym_traits =
2278 ((FontSymbolicTraits) (uintptr_t)
2279 CFArrayGetValueAtIndex (traits_array, j));
2280 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2282 mask_min = ((synth_sym_traits ^ sym_traits)
2283 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2284 if (FONT_SLANT_NUMERIC (spec) < 0)
2285 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2286 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2287 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2289 mask_max = (synth_sym_traits & ~sym_traits);
2290 /* Synthetic bold does not work for bitmap-only fonts on Mac
2292 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2294 CFNumberRef format =
2295 mac_font_descriptor_copy_attribute (desc,
2296 MAC_FONT_FORMAT_ATTRIBUTE);
2300 uint32_t format_val;
2302 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2304 && format_val == MAC_FONT_FORMAT_BITMAP)
2305 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2309 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2311 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2312 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2313 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2314 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2315 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2316 bmask += MAC_FONT_TRAIT_BOLD)
2317 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2318 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2319 imask += MAC_FONT_TRAIT_ITALIC)
2321 FontSymbolicTraits synth = (imask | bmask | mmask);
2324 || macfont_closest_traits_index_p (traits_array,
2325 (sym_traits | synth),
2328 entity = macfont_descriptor_entity (desc, extra, synth);
2329 if (! NILP (entity))
2330 val = Fcons (entity, val);
2335 CFRelease (traits_array);
2339 CFRelease (families);
2340 val = Fnreverse (val);
2346 FONT_ADD_LOG ("macfont-list", spec, val);
2347 if (charset) CFRelease (charset);
2348 if (languages) CFRelease (languages);
2349 if (attributes) CFRelease (attributes);
2350 if (family_name) CFRelease (family_name);
2358 macfont_match (struct frame * frame, Lisp_Object spec)
2360 Lisp_Object entity = Qnil;
2361 CFMutableDictionaryRef attributes;
2362 FontDescriptorRef pat_desc = NULL, desc = NULL;
2366 attributes = macfont_create_attributes_with_spec (spec);
2369 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2370 CFRelease (attributes);
2374 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2376 CFRelease (pat_desc);
2380 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2386 FONT_ADD_LOG ("macfont-match", spec, entity);
2391 macfont_list_family (struct frame *frame)
2393 Lisp_Object list = Qnil;
2394 CFArrayRef families;
2398 families = mac_font_create_available_families ();
2401 CFIndex i, count = CFArrayGetCount (families);
2403 for (i = 0; i < count; i++)
2404 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2405 CFRelease (families);
2414 macfont_free_entity (Lisp_Object entity)
2416 Lisp_Object val = assq_no_quit (QCfont_entity,
2417 AREF (entity, FONT_EXTRA_INDEX));
2418 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2426 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2428 Lisp_Object val, font_object;
2429 CFStringRef font_name;
2430 struct macfont_info *macfont_info = NULL;
2434 FontSymbolicTraits sym_traits;
2436 int len, i, total_width;
2438 CGFloat ascent, descent, leading;
2440 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2442 || XTYPE (XCDR (val)) != Lisp_Misc
2443 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2445 font_name = XSAVE_POINTER (XCDR (val), 0);
2446 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2448 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2453 macfont = mac_font_create_with_name (font_name, size);
2456 int fontsize = (int) [((NSFont *) macfont) pointSize];
2457 if (fontsize != size) size = fontsize;
2463 font_object = font_build_object (VECSIZE (struct macfont_info),
2464 Qmac_ct, entity, size);
2465 font = XFONT_OBJECT (font_object);
2466 font->pixel_size = size;
2467 font->driver = &macfont_driver;
2468 font->encoding_charset = font->repertory_charset = -1;
2472 macfont_info = (struct macfont_info *) font;
2473 macfont_info->macfont = macfont;
2474 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2476 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2477 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2478 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2481 macfont_info->screen_font = NULL;
2482 macfont_info->cache = macfont_lookup_cache (font_name);
2483 macfont_retain_cache (macfont_info->cache);
2484 macfont_info->metrics = NULL;
2485 macfont_info->metrics_nrows = 0;
2486 macfont_info->synthetic_italic_p = 0;
2487 macfont_info->synthetic_bold_p = 0;
2488 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2489 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2490 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2491 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2492 macfont_info->synthetic_italic_p = 1;
2493 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2494 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2495 macfont_info->synthetic_bold_p = 1;
2496 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2497 macfont_info->spacing = MACFONT_SPACING_MONO;
2498 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2499 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2500 == FONT_SPACING_SYNTHETIC_MONO))
2501 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2502 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2503 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2506 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2508 macfont_info->antialias =
2509 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2511 macfont_info->color_bitmap_p = 0;
2512 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2513 macfont_info->color_bitmap_p = 1;
2515 glyph = macfont_get_glyph_for_character (font, ' ');
2516 if (glyph != kCGFontIndexInvalid)
2517 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2519 /* dirty workaround */
2520 font->space_width = pixel_size;
2522 total_width = font->space_width;
2523 for (i = 1; i < 95; i++)
2525 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2526 if (glyph == kCGFontIndexInvalid)
2528 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2531 font->average_width = total_width / 95;
2533 font->average_width = font->space_width; /* XXX */
2535 if (!(macfont_info->screen_font
2536 && mac_screen_font_get_metrics (macfont_info->screen_font,
2537 &ascent, &descent, &leading)))
2539 CFStringRef family_name;
2541 ascent = mac_font_get_ascent (macfont);
2542 descent = mac_font_get_descent (macfont);
2543 leading = mac_font_get_leading (macfont);
2544 /* AppKit and WebKit do some adjustment to the heights of
2545 Courier, Helvetica, and Times. */
2546 family_name = mac_font_copy_family_name (macfont);
2549 if (CFEqual (family_name, CFSTR ("Courier"))
2550 || CFEqual (family_name, CFSTR ("Helvetica"))
2551 || CFEqual (family_name, CFSTR ("Times")))
2552 ascent += (ascent + descent) * .15f;
2553 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2558 CFRelease (family_name);
2561 font->ascent = ascent + 0.5f;
2562 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2563 if (CONSP (val) && !NILP (XCDR (val)))
2564 font->descent = descent + 0.5f;
2566 font->descent = descent + leading + 0.5f;
2567 font->height = font->ascent + font->descent;
2569 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2570 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2574 /* Unfortunately Xft doesn't provide a way to get minimum char
2575 width. So, we use space_width instead. */
2576 font->min_width = font->max_width = font->space_width; /* XXX */
2578 font->baseline_offset = 0;
2579 font->relative_compose = 0;
2580 font->default_ascent = 0;
2581 font->vertical_centering = 0;
2587 macfont_close (struct font *font)
2589 struct macfont_info *macfont_info = (struct macfont_info *) font;
2591 if (macfont_info->cache)
2596 CFRelease (macfont_info->macfont);
2597 CGFontRelease (macfont_info->cgfont);
2598 if (macfont_info->screen_font)
2599 CFRelease (macfont_info->screen_font);
2600 macfont_release_cache (macfont_info->cache);
2601 for (i = 0; i < macfont_info->metrics_nrows; i++)
2602 if (macfont_info->metrics[i])
2603 xfree (macfont_info->metrics[i]);
2604 if (macfont_info->metrics)
2605 xfree (macfont_info->metrics);
2606 macfont_info->cache = NULL;
2612 macfont_has_char (Lisp_Object font, int c)
2615 CFCharacterSetRef charset;
2618 if (FONT_ENTITY_P (font))
2623 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2625 name = XSAVE_POINTER (val, 0);
2626 charset = macfont_get_cf_charset_for_name (name);
2629 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2631 result = CFCharacterSetIsLongCharacterMember (charset, c);
2638 macfont_encode_char (struct font *font, int c)
2640 struct macfont_info *macfont_info = (struct macfont_info *) font;
2644 glyph = macfont_get_glyph_for_character (font, c);
2647 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2651 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2652 struct font_metrics *metrics)
2657 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2658 for (i = 1; i < nglyphs; i++)
2660 struct font_metrics m;
2661 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2666 if (width + m.lbearing < metrics->lbearing)
2667 metrics->lbearing = width + m.lbearing;
2668 if (width + m.rbearing > metrics->rbearing)
2669 metrics->rbearing = width + m.rbearing;
2670 if (m.ascent > metrics->ascent)
2671 metrics->ascent = m.ascent;
2672 if (m.descent > metrics->descent)
2673 metrics->descent = m.descent;
2680 metrics->width = width;
2684 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2685 bool with_background)
2687 struct frame * f = s->f;
2688 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2689 CGRect background_rect;
2690 CGPoint text_position;
2693 CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2694 bool no_antialias_p =
2695 (NILP (ns_antialias_text)
2696 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2697 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2698 && font_size <= macfont_antialias_threshold));
2699 int len = to - from;
2700 struct face *face = s->face;
2701 CGContextRef context;
2705 if (with_background)
2706 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2707 s->width, FONT_HEIGHT (s->font));
2709 background_rect = CGRectNull;
2711 text_position = CGPointMake (x, -y);
2712 glyphs = xmalloc (sizeof (CGGlyph) * len);
2714 CGFloat advance_delta = 0;
2716 CGFloat total_width = 0;
2718 positions = xmalloc (sizeof (CGPoint) * len);
2719 for (i = 0; i < len; i++)
2723 glyphs[i] = s->char2b[from + i];
2724 width = (s->padding_p ? 1
2725 : macfont_glyph_extents (s->font, glyphs[i],
2726 NULL, &advance_delta,
2728 positions[i].x = total_width + advance_delta;
2730 total_width += width;
2734 context = [[NSGraphicsContext currentContext] graphicsPort];
2735 CGContextSaveGState (context);
2737 if (!CGRectIsNull (background_rect))
2739 if (s->hl == DRAW_MOUSE_FACE)
2741 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2743 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2745 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2746 CGContextFillRects (context, &background_rect, 1);
2749 if (macfont_info->cgfont)
2751 CGAffineTransform atfm;
2753 CGContextScaleCTM (context, 1, -1);
2754 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2755 if (macfont_info->synthetic_italic_p)
2756 atfm = synthetic_italic_atfm;
2758 atfm = CGAffineTransformIdentity;
2759 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2761 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2762 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2763 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2766 CGContextSetShouldAntialias (context, false);
2768 CGContextSetTextMatrix (context, atfm);
2769 CGContextSetTextPosition (context, text_position.x, text_position.y);
2771 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2772 if (macfont_info->color_bitmap_p
2773 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2774 && CTFontDrawGlyphs != NULL
2780 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2785 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2787 CGContextSetFont (context, macfont_info->cgfont);
2788 CGContextSetFontSize (context, font_size);
2789 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2796 CGContextRestoreGState (context);
2804 macfont_shape (Lisp_Object lgstring)
2807 struct macfont_info *macfont_info;
2809 ptrdiff_t glyph_len, len, i, j;
2812 CFIndex *nonbmp_indices;
2815 struct mac_glyph_layout *glyph_layouts;
2817 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2818 macfont_info = (struct macfont_info *) font;
2819 macfont = macfont_info->macfont;
2821 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2823 for (i = 0; i < glyph_len; i++)
2825 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2829 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2835 if (INT_MAX / 2 < len)
2836 memory_full (SIZE_MAX);
2838 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2839 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2840 for (i = j = 0; i < len; i++)
2842 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2844 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2846 nonbmp_indices[j] = i + j;
2850 nonbmp_indices[j] = len + j; /* sentinel */
2854 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2858 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2859 if (macfont_info->screen_font)
2860 used = mac_screen_font_shape (macfont_info->screen_font, string,
2861 glyph_layouts, glyph_len);
2863 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2874 for (i = 0; i < used; i++)
2876 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2877 struct mac_glyph_layout *gl = glyph_layouts + i;
2879 struct font_metrics metrics;
2880 int xoff, yoff, wadjust;
2884 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2885 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2888 from = gl->comp_range.location;
2889 /* Convert UTF-16 index to UTF-32. */
2891 while (nonbmp_indices[j] < from)
2894 LGLYPH_SET_FROM (lglyph, from);
2896 to = gl->comp_range.location + gl->comp_range.length;
2897 /* Convert UTF-16 index to UTF-32. */
2898 while (nonbmp_indices[j] < to)
2901 LGLYPH_SET_TO (lglyph, to - 1);
2903 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2904 the composition is trivial. */
2908 if (unichars[gl->string_index] >= 0xD800
2909 && unichars[gl->string_index] < 0xDC00)
2910 c = (((unichars[gl->string_index] - 0xD800) << 10)
2911 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2913 c = unichars[gl->string_index];
2914 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2916 LGLYPH_SET_CHAR (lglyph, c);
2920 unsigned long cc = gl->glyph_id;
2921 LGLYPH_SET_CODE (lglyph, cc);
2924 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2925 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2926 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2927 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2928 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2929 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2931 xoff = lround (gl->advance_delta);
2932 yoff = lround (- gl->baseline_delta);
2933 wadjust = lround (gl->advance);
2934 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2938 vec = Fmake_vector (make_number (3), Qnil);
2939 ASET (vec, 0, make_number (xoff));
2940 ASET (vec, 1, make_number (yoff));
2941 ASET (vec, 2, make_number (wadjust));
2942 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2948 return make_number (used);
2951 /* Structures for the UVS subtable (format 14) in the cmap table. */
2952 typedef UInt8 UINT24[3];
2954 #pragma pack(push, 1)
2955 struct variation_selector_record
2957 UINT24 var_selector;
2958 UInt32 default_uvs_offset, non_default_uvs_offset;
2963 UInt32 length, num_var_selector_records;
2964 struct variation_selector_record variation_selector_records[1];
2966 #define SIZEOF_UVS_TABLE_HEADER \
2967 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2969 struct unicode_value_range
2971 UINT24 start_unicode_value;
2972 UInt8 additional_count;
2974 struct default_uvs_table {
2975 UInt32 num_unicode_value_ranges;
2976 struct unicode_value_range unicode_value_ranges[1];
2978 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2979 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2983 UINT24 unicode_value;
2986 struct non_default_uvs_table
2988 UInt32 num_uvs_mappings;
2989 struct uvs_mapping uvs_mappings[1];
2991 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
2992 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2995 /* Read big endian values. The argument LVAL must be an lvalue. */
2996 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
2997 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
2998 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
2999 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
3000 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3001 /* Succeeding one byte should also be accessible. */
3002 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3003 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3005 /* Return UVS subtable for the specified FONT. If the subtable is not
3006 found or ill-formatted, then return NULL. */
3009 mac_font_copy_uvs_table (FontRef font)
3011 CFDataRef cmap_table, uvs_table = NULL;
3013 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3016 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3017 struct uvs_table *uvs;
3018 struct variation_selector_record *records;
3019 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3022 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3026 cmap_len = CFDataGetLength (cmap_table);
3027 if (sizeof_sfntCMapHeader > cmap_len)
3030 ntables = BUINT16_VALUE (cmap->numTables);
3031 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3032 / sizeof_sfntCMapEncoding))
3035 for (i = 0; i < ntables; i++)
3036 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3037 == kFontUnicodePlatform)
3038 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3039 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3041 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3045 || uvs_offset > cmap_len
3046 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3049 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3050 uvs_len = BUINT32_VALUE (uvs->length);
3051 if (uvs_len > cmap_len - uvs_offset
3052 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3055 if (BUINT16_VALUE (uvs->format) != 14)
3058 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3059 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3060 / sizeof (struct variation_selector_record)))
3063 records = uvs->variation_selector_records;
3064 for (i = 0; i < nrecords; i++)
3066 UInt32 default_uvs_offset, non_default_uvs_offset;
3068 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3069 if (default_uvs_offset)
3071 struct default_uvs_table *default_uvs;
3074 if (default_uvs_offset > uvs_len
3075 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3076 > uvs_len - default_uvs_offset))
3079 default_uvs = ((struct default_uvs_table *)
3080 ((UInt8 *) uvs + default_uvs_offset));
3081 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3082 if (nranges > ((uvs_len - default_uvs_offset
3083 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3084 / sizeof (struct unicode_value_range)))
3086 /* Now 2 * nranges can't overflow, so we can safely use
3087 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3088 mac_font_get_glyphs_for_variants. */
3091 non_default_uvs_offset =
3092 BUINT32_VALUE (records[i].non_default_uvs_offset);
3093 if (non_default_uvs_offset)
3095 struct non_default_uvs_table *non_default_uvs;
3098 if (non_default_uvs_offset > uvs_len
3099 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3100 > uvs_len - non_default_uvs_offset))
3103 non_default_uvs = ((struct non_default_uvs_table *)
3104 ((UInt8 *) uvs + non_default_uvs_offset));
3105 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3106 if (nmappings > ((uvs_len - non_default_uvs_offset
3107 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3108 / sizeof (struct uvs_mapping)))
3110 /* Now 2 * nmappings can't overflow, so we can safely
3111 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3112 in mac_font_get_glyphs_for_variants. */
3116 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3119 CFRelease (cmap_table);
3125 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3126 sequence consisting of the given base character C and each
3127 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3128 result (explained below) into the corresponding GLYPHS[i]. If the
3129 entry is found in the Default UVS Table, then the result is 0. If
3130 the entry is found in the Non-Default UVS Table, then the result is
3131 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3132 elements in SELECTORS must be sorted in strictly increasing
3136 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3137 const UTF32Char selectors[], CGGlyph glyphs[],
3140 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3141 struct variation_selector_record *records = uvs->variation_selector_records;
3143 UInt32 ir, nrecords;
3144 dispatch_queue_t queue =
3145 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3146 dispatch_group_t group = dispatch_group_create ();
3148 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3151 while (i < count && ir < nrecords)
3153 UInt32 default_uvs_offset, non_default_uvs_offset;
3155 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3157 glyphs[i++] = kCGFontIndexInvalid;
3160 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3166 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3167 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3168 non_default_uvs_offset =
3169 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3170 dispatch_group_async (group, queue, ^{
3171 glyphs[i] = kCGFontIndexInvalid;
3173 if (default_uvs_offset)
3175 struct default_uvs_table *default_uvs =
3176 (struct default_uvs_table *) ((UInt8 *) uvs
3177 + default_uvs_offset);
3178 struct unicode_value_range *ranges =
3179 default_uvs->unicode_value_ranges;
3183 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3186 UInt32 mid = (lo + hi) / 2;
3188 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3194 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3195 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3199 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3201 struct non_default_uvs_table *non_default_uvs =
3202 (struct non_default_uvs_table *) ((UInt8 *) uvs
3203 + non_default_uvs_offset);
3204 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3208 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3211 UInt32 mid = (lo + hi) / 2;
3213 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3219 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3220 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3227 glyphs[i++] = kCGFontIndexInvalid;
3228 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3229 dispatch_release (group);
3233 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3235 CFDataRef uvs_table;
3236 CharacterCollection uvs_collection;
3240 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3244 UTF32Char selectors[256];
3245 CGGlyph glyphs[256];
3247 for (i = 0; i < 16; i++)
3248 selectors[i] = 0xFE00 + i;
3249 for (; i < 256; i++)
3250 selectors[i] = 0xE0100 + (i - 16);
3251 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3252 for (i = 0; i < 256; i++)
3254 CGGlyph glyph = glyphs[i];
3256 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3257 && glyph != kCGFontIndexInvalid)
3258 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3259 if (glyph == kCGFontIndexInvalid)
3263 variations[i] = (glyph ? glyph
3264 : macfont_get_glyph_for_character (font, c));
3274 static const char *const macfont_booleans[] = {
3280 static const char *const macfont_non_booleans[] = {
3288 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3290 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3294 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3295 CFArrayRef languages)
3297 Boolean result = true;
3298 CFArrayRef desc_languages =
3299 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3301 if (desc_languages == NULL)
3305 CFIndex desc_languages_count, i, languages_count;
3307 desc_languages_count = CFArrayGetCount (desc_languages);
3308 languages_count = CFArrayGetCount (languages);
3309 for (i = 0; i < languages_count; i++)
3310 if (!CFArrayContainsValue (desc_languages,
3311 CFRangeMake (0, desc_languages_count),
3312 CFArrayGetValueAtIndex (languages, i)))
3317 CFRelease (desc_languages);
3324 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3326 CFStringRef result = NULL;
3327 CFStringRef charset_string =
3328 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3330 if (charset_string && CFStringGetLength (charset_string) > 0)
3332 CFStringRef keys[] = {
3333 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3334 kCTLanguageAttributeName
3336 CFSTR ("NSLanguage")
3339 CFTypeRef values[] = {NULL};
3340 CFIndex num_values = 0;
3341 CFArrayRef languages
3342 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3344 if (languages && CFArrayGetCount (languages) > 0)
3346 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3347 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3350 CFCharacterSetRef charset =
3351 CFDictionaryGetValue (attributes,
3352 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3354 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3359 CFAttributedStringRef attr_string = NULL;
3360 CTLineRef ctline = NULL;
3361 CFDictionaryRef attrs
3362 = CFDictionaryCreate (NULL, (const void **) keys,
3363 (const void **) values, num_values,
3364 &kCFTypeDictionaryKeyCallBacks,
3365 &kCFTypeDictionaryValueCallBacks);
3369 attr_string = CFAttributedStringCreate (NULL, charset_string,
3375 ctline = CTLineCreateWithAttributedString (attr_string);
3376 CFRelease (attr_string);
3380 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3381 CFIndex i, nruns = CFArrayGetCount (runs);
3384 for (i = 0; i < nruns; i++)
3386 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3387 CFDictionaryRef attributes = CTRunGetAttributes (run);
3388 CTFontRef font_in_run;
3390 if (attributes == NULL)
3393 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3394 if (font_in_run == NULL)
3398 else if (!mac_ctfont_equal_in_postscript_name (font,
3402 if (nruns > 0 && i == nruns)
3403 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3412 static inline double
3413 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3415 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3419 static inline CGRect
3420 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3422 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3427 mac_ctfont_create_available_families (void)
3429 CFMutableArrayRef families = NULL;
3432 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3436 CFIndex i, count = CFArrayGetCount (orig_families);
3438 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3440 for (i = 0; i < count; i++)
3442 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3444 if (!CFStringHasPrefix (family, CFSTR ("."))
3445 && (CTFontManagerCompareFontFamilyNames (family,
3446 CFSTR ("LastResort"),
3448 != kCFCompareEqualTo))
3449 CFArrayAppendValue (families, family);
3451 CFRelease (orig_families);
3459 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3462 CFStringRef name1, name2;
3468 name1 = CTFontCopyPostScriptName (font1);
3471 name2 = CTFontCopyPostScriptName (font2);
3474 result = CFEqual (name1, name2);
3484 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3487 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3488 CFTypeRef values[] = {NULL, NULL};
3489 CFDictionaryRef attributes = NULL;
3490 CFAttributedStringRef attr_string = NULL;
3491 CTLineRef ctline = NULL;
3492 float float_zero = 0.0f;
3494 values[0] = macfont;
3495 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3498 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3499 (const void **) values,
3501 &kCFTypeDictionaryKeyCallBacks,
3502 &kCFTypeDictionaryValueCallBacks);
3503 CFRelease (values[1]);
3507 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3508 CFRelease (attributes);
3512 ctline = CTLineCreateWithAttributedString (attr_string);
3513 CFRelease (attr_string);
3517 /* Abandon if ctline contains some fonts other than the
3519 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3520 CFIndex i, nruns = CFArrayGetCount (runs);
3522 for (i = 0; i < nruns; i++)
3524 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3525 CFDictionaryRef attributes = CTRunGetAttributes (run);
3526 CTFontRef font_in_run;
3528 if (attributes == NULL)
3531 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3532 if (font_in_run == NULL)
3534 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3548 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3549 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3551 CFIndex used, result = 0;
3552 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3557 used = CTLineGetGlyphCount (ctline);
3558 if (used <= glyph_len)
3560 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3561 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3562 CGFloat total_advance = 0;
3563 CFIndex total_glyph_count = 0;
3565 for (k = 0; k < ctrun_count; k++)
3567 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3568 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3569 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3570 CFRange string_range, comp_range, range;
3571 CFIndex *permutation;
3573 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3574 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3578 #define RIGHT_TO_LEFT_P permutation
3580 /* Now the `comp_range' member of struct mac_glyph_layout is
3581 temporarily used as a work area such that:
3582 glbuf[i].comp_range.location =
3583 min {compRange[i + 1].location, ...,
3584 compRange[glyph_count - 1].location,
3585 maxRange (stringRangeForCTRun)}
3586 glbuf[i].comp_range.length = maxRange (compRange[i])
3587 where compRange[i] is the range of composed characters
3588 containing i-th glyph. */
3589 string_range = CTRunGetStringRange (ctrun);
3590 min_location = string_range.location + string_range.length;
3591 for (i = 0; i < glyph_count; i++)
3593 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3594 CFIndex glyph_index;
3597 if (!RIGHT_TO_LEFT_P)
3598 glyph_index = glyph_count - i - 1;
3601 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3604 CFStringGetRangeOfComposedCharactersAtIndex (string,
3606 gl->comp_range.location = min_location;
3607 gl->comp_range.length = rng.location + rng.length;
3608 if (rng.location < min_location)
3609 min_location = rng.location;
3612 /* Fill the `comp_range' member of struct mac_glyph_layout,
3613 and setup a permutation for right-to-left text. */
3614 comp_range = CFRangeMake (string_range.location, 0);
3615 range = CFRangeMake (0, 0);
3618 struct mac_glyph_layout *gl =
3619 glbuf + range.location + range.length;
3621 if (gl->comp_range.length
3622 > comp_range.location + comp_range.length)
3623 comp_range.length = gl->comp_range.length - comp_range.location;
3624 min_location = gl->comp_range.location;
3627 if (min_location >= comp_range.location + comp_range.length)
3629 comp_range.length = min_location - comp_range.location;
3630 for (i = 0; i < range.length; i++)
3632 glbuf[range.location + i].comp_range = comp_range;
3633 if (RIGHT_TO_LEFT_P)
3634 permutation[range.location + i] =
3635 range.location + range.length - i - 1;
3638 comp_range = CFRangeMake (min_location, 0);
3639 range.location += range.length;
3641 if (range.location == glyph_count)
3646 /* Then fill the remaining members. */
3647 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3650 struct mac_glyph_layout *gl;
3653 if (!RIGHT_TO_LEFT_P)
3654 gl = glbuf + range.location;
3659 src = glyph_count - 1 - range.location;
3660 dest = permutation[src];
3664 CFIndex tmp = gl->string_index;
3666 gl->string_index = glbuf[src].string_index;
3667 glbuf[src].string_index = tmp;
3670 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3672 CTRunGetPositions (ctrun, range, &position);
3673 gl->advance_delta = position.x - total_advance;
3674 gl->baseline_delta = position.y;
3675 gl->advance = (gl->advance_delta
3676 + CTRunGetTypographicBounds (ctrun, range,
3678 total_advance += gl->advance;
3681 if (RIGHT_TO_LEFT_P)
3682 xfree (permutation);
3684 #undef RIGHT_TO_LEFT_P
3686 total_glyph_count += glyph_count;
3696 /* The function below seems to cause a memory leak for the CFString
3697 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3698 10.6.3. For now, we use the NSGlyphInfo version instead. */
3699 #if USE_CT_GLYPH_INFO
3701 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3704 CGGlyph result = kCGFontIndexInvalid;
3705 UniChar characters[] = {0xfffd};
3707 CFAttributedStringRef attr_string = NULL;
3708 CTLineRef ctline = NULL;
3710 string = CFStringCreateWithCharacters (NULL, characters,
3711 ARRAYELTS (characters));
3715 CTGlyphInfoRef glyph_info =
3716 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3717 CFDictionaryRef attributes = NULL;
3721 CFStringRef keys[] = {kCTFontAttributeName,
3722 kCTGlyphInfoAttributeName};
3723 CFTypeRef values[] = {font, glyph_info};
3725 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3726 (const void **) values,
3728 &kCFTypeDictionaryKeyCallBacks,
3729 &kCFTypeDictionaryValueCallBacks);
3730 CFRelease (glyph_info);
3734 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3735 CFRelease (attributes);
3741 ctline = CTLineCreateWithAttributedString (attr_string);
3742 CFRelease (attr_string);
3746 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3748 if (CFArrayGetCount (runs) > 0)
3750 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3751 CFDictionaryRef attributes = CTRunGetAttributes (run);
3755 CTFontRef font_in_run =
3756 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3759 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3761 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3762 if (result >= CTFontGetGlyphCount (font))
3763 result = kCGFontIndexInvalid;
3775 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3777 CFArrayRef result = NULL;
3779 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3780 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3781 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3784 CTFontRef user_font =
3785 CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3789 CFArrayRef languages =
3790 CFArrayCreate (NULL, (const void **) &language, 1,
3791 &kCFTypeArrayCallBacks);
3795 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3797 CFRelease (languages);
3799 CFRelease (user_font);
3802 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3803 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3805 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3806 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3810 for (i = 0; macfont_language_default_font_names[i].language; i++)
3812 if (CFEqual (macfont_language_default_font_names[i].language,
3815 CFMutableArrayRef descriptors =
3816 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3823 macfont_language_default_font_names[i].font_names[j];
3826 CFDictionaryRef attributes =
3827 CFDictionaryCreate (NULL,
3829 &MAC_FONT_NAME_ATTRIBUTE),
3831 &macfont_language_default_font_names[i].font_names[j]),
3832 1, &kCFTypeDictionaryKeyCallBacks,
3833 &kCFTypeDictionaryValueCallBacks);
3837 FontDescriptorRef pat_desc =
3838 mac_font_descriptor_create_with_attributes (attributes);
3842 FontDescriptorRef descriptor =
3843 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3847 CFArrayAppendValue (descriptors, descriptor);
3848 CFRelease (descriptor);
3850 CFRelease (pat_desc);
3852 CFRelease (attributes);
3855 result = descriptors;
3867 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3868 CFArrayRef languages)
3870 CFStringRef result = NULL;
3871 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3872 CFArrayRef descriptors =
3873 mac_font_copy_default_descriptors_for_language (language);
3877 CFIndex i, count = CFArrayGetCount (descriptors);
3879 for (i = 0; i < count; i++)
3881 FontDescriptorRef descriptor =
3882 CFArrayGetValueAtIndex (descriptors, i);
3884 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3887 CFStringRef family =
3888 mac_font_descriptor_copy_attribute (descriptor,
3889 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3892 if (!CFStringHasPrefix (family, CFSTR ("."))
3893 && !CFEqual (family, CFSTR ("LastResort")))
3903 CFRelease (descriptors);
3910 macfont_get_nsctfont (struct font *font)
3912 struct macfont_info *macfont_info = (struct macfont_info *) font;
3913 FontRef macfont = macfont_info->macfont;
3915 return (void *) macfont;
3919 mac_register_font_driver (struct frame *f)
3921 register_font_driver (&macfont_driver, f);
3926 syms_of_macfont (void)
3928 static struct font_driver mac_font_driver;
3930 DEFSYM (Qmac_ct, "mac-ct");
3931 macfont_driver.type = Qmac_ct;
3932 register_font_driver (&macfont_driver, NULL);
3934 DEFSYM (QCdestination, ":destination");
3935 DEFSYM (QCminspace, ":minspace");