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)
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 (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2696 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2697 && font_size <= macfont_antialias_threshold));
2698 int len = to - from;
2699 struct face *face = s->face;
2700 CGContextRef context;
2704 if (with_background)
2705 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2706 s->width, FONT_HEIGHT (s->font));
2708 background_rect = CGRectNull;
2710 text_position = CGPointMake (x, -y);
2711 glyphs = xmalloc (sizeof (CGGlyph) * len);
2713 CGFloat advance_delta = 0;
2715 CGFloat total_width = 0;
2717 positions = xmalloc (sizeof (CGPoint) * len);
2718 for (i = 0; i < len; i++)
2722 glyphs[i] = s->char2b[from + i];
2723 width = (s->padding_p ? 1
2724 : macfont_glyph_extents (s->font, glyphs[i],
2725 NULL, &advance_delta,
2727 positions[i].x = total_width + advance_delta;
2729 total_width += width;
2733 context = [[NSGraphicsContext currentContext] graphicsPort];
2734 CGContextSaveGState (context);
2736 if (!CGRectIsNull (background_rect))
2738 if (s->hl == DRAW_MOUSE_FACE)
2740 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2742 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2744 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2745 CGContextFillRects (context, &background_rect, 1);
2748 if (macfont_info->cgfont)
2750 CGAffineTransform atfm;
2752 CGContextScaleCTM (context, 1, -1);
2753 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2754 if (macfont_info->synthetic_italic_p)
2755 atfm = synthetic_italic_atfm;
2757 atfm = CGAffineTransformIdentity;
2758 if (macfont_info->synthetic_bold_p)
2760 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2761 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2762 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2765 CGContextSetShouldAntialias (context, false);
2767 CGContextSetTextMatrix (context, atfm);
2768 CGContextSetTextPosition (context, text_position.x, text_position.y);
2770 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2771 if (macfont_info->color_bitmap_p
2772 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2773 && CTFontDrawGlyphs != NULL
2779 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2784 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2786 CGContextSetFont (context, macfont_info->cgfont);
2787 CGContextSetFontSize (context, font_size);
2788 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2795 CGContextRestoreGState (context);
2803 macfont_shape (Lisp_Object lgstring)
2806 struct macfont_info *macfont_info;
2808 ptrdiff_t glyph_len, len, i, j;
2811 CFIndex *nonbmp_indices;
2814 struct mac_glyph_layout *glyph_layouts;
2816 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2817 macfont_info = (struct macfont_info *) font;
2818 macfont = macfont_info->macfont;
2820 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2822 for (i = 0; i < glyph_len; i++)
2824 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2828 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2834 if (INT_MAX / 2 < len)
2835 memory_full (SIZE_MAX);
2837 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2838 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2839 for (i = j = 0; i < len; i++)
2841 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2843 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2845 nonbmp_indices[j] = i + j;
2849 nonbmp_indices[j] = len + j; /* sentinel */
2853 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2857 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2858 if (macfont_info->screen_font)
2859 used = mac_screen_font_shape (macfont_info->screen_font, string,
2860 glyph_layouts, glyph_len);
2862 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2873 for (i = 0; i < used; i++)
2875 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2876 struct mac_glyph_layout *gl = glyph_layouts + i;
2878 struct font_metrics metrics;
2879 int xoff, yoff, wadjust;
2883 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2884 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2887 from = gl->comp_range.location;
2888 /* Convert UTF-16 index to UTF-32. */
2890 while (nonbmp_indices[j] < from)
2893 LGLYPH_SET_FROM (lglyph, from);
2895 to = gl->comp_range.location + gl->comp_range.length;
2896 /* Convert UTF-16 index to UTF-32. */
2897 while (nonbmp_indices[j] < to)
2900 LGLYPH_SET_TO (lglyph, to - 1);
2902 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2903 the composition is trivial. */
2907 if (unichars[gl->string_index] >= 0xD800
2908 && unichars[gl->string_index] < 0xDC00)
2909 c = (((unichars[gl->string_index] - 0xD800) << 10)
2910 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2912 c = unichars[gl->string_index];
2913 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2915 LGLYPH_SET_CHAR (lglyph, c);
2919 unsigned long cc = gl->glyph_id;
2920 LGLYPH_SET_CODE (lglyph, cc);
2923 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2924 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2925 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2926 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2927 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2928 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2930 xoff = lround (gl->advance_delta);
2931 yoff = lround (- gl->baseline_delta);
2932 wadjust = lround (gl->advance);
2933 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2937 vec = Fmake_vector (make_number (3), Qnil);
2938 ASET (vec, 0, make_number (xoff));
2939 ASET (vec, 1, make_number (yoff));
2940 ASET (vec, 2, make_number (wadjust));
2941 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2947 return make_number (used);
2950 /* Structures for the UVS subtable (format 14) in the cmap table. */
2951 typedef UInt8 UINT24[3];
2953 #pragma pack(push, 1)
2954 struct variation_selector_record
2956 UINT24 var_selector;
2957 UInt32 default_uvs_offset, non_default_uvs_offset;
2962 UInt32 length, num_var_selector_records;
2963 struct variation_selector_record variation_selector_records[1];
2965 #define SIZEOF_UVS_TABLE_HEADER \
2966 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2968 struct unicode_value_range
2970 UINT24 start_unicode_value;
2971 UInt8 additional_count;
2973 struct default_uvs_table {
2974 UInt32 num_unicode_value_ranges;
2975 struct unicode_value_range unicode_value_ranges[1];
2977 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2978 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2982 UINT24 unicode_value;
2985 struct non_default_uvs_table
2987 UInt32 num_uvs_mappings;
2988 struct uvs_mapping uvs_mappings[1];
2990 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
2991 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2994 /* Read big endian values. The argument LVAL must be an lvalue. */
2995 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
2996 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
2997 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
2998 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
2999 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
3000 /* Succeeding one byte should also be accessible. */
3001 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3002 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3004 /* Return UVS subtable for the specified FONT. If the subtable is not
3005 found or ill-formatted, then return NULL. */
3008 mac_font_copy_uvs_table (FontRef font)
3010 CFDataRef cmap_table, uvs_table = NULL;
3012 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3015 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3016 struct uvs_table *uvs;
3017 struct variation_selector_record *records;
3018 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3021 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3025 cmap_len = CFDataGetLength (cmap_table);
3026 if (sizeof_sfntCMapHeader > cmap_len)
3029 ntables = BUINT16_VALUE (cmap->numTables);
3030 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3031 / sizeof_sfntCMapEncoding))
3034 for (i = 0; i < ntables; i++)
3035 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3036 == kFontUnicodePlatform)
3037 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3038 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3040 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3044 || uvs_offset > cmap_len
3045 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3048 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3049 uvs_len = BUINT32_VALUE (uvs->length);
3050 if (uvs_len > cmap_len - uvs_offset
3051 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3054 if (BUINT16_VALUE (uvs->format) != 14)
3057 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3058 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3059 / sizeof (struct variation_selector_record)))
3062 records = uvs->variation_selector_records;
3063 for (i = 0; i < nrecords; i++)
3065 UInt32 default_uvs_offset, non_default_uvs_offset;
3067 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3068 if (default_uvs_offset)
3070 struct default_uvs_table *default_uvs;
3073 if (default_uvs_offset > uvs_len
3074 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3075 > uvs_len - default_uvs_offset))
3078 default_uvs = ((struct default_uvs_table *)
3079 ((UInt8 *) uvs + default_uvs_offset));
3080 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3081 if (nranges > ((uvs_len - default_uvs_offset
3082 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3083 / sizeof (struct unicode_value_range)))
3085 /* Now 2 * nranges can't overflow, so we can safely use
3086 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3087 mac_font_get_glyphs_for_variants. */
3090 non_default_uvs_offset =
3091 BUINT32_VALUE (records[i].non_default_uvs_offset);
3092 if (non_default_uvs_offset)
3094 struct non_default_uvs_table *non_default_uvs;
3097 if (non_default_uvs_offset > uvs_len
3098 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3099 > uvs_len - non_default_uvs_offset))
3102 non_default_uvs = ((struct non_default_uvs_table *)
3103 ((UInt8 *) uvs + non_default_uvs_offset));
3104 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3105 if (nmappings > ((uvs_len - non_default_uvs_offset
3106 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3107 / sizeof (struct uvs_mapping)))
3109 /* Now 2 * nmappings can't overflow, so we can safely
3110 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3111 in mac_font_get_glyphs_for_variants. */
3115 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3118 CFRelease (cmap_table);
3124 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3125 sequence consisting of the given base character C and each
3126 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3127 result (explained below) into the corresponding GLYPHS[i]. If the
3128 entry is found in the Default UVS Table, then the result is 0. If
3129 the entry is found in the Non-Default UVS Table, then the result is
3130 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3131 elements in SELECTORS must be sorted in strictly increasing
3135 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3136 const UTF32Char selectors[], CGGlyph glyphs[],
3139 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3140 struct variation_selector_record *records = uvs->variation_selector_records;
3142 UInt32 ir, nrecords;
3143 dispatch_queue_t queue =
3144 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3145 dispatch_group_t group = dispatch_group_create ();
3147 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3150 while (i < count && ir < nrecords)
3152 UInt32 default_uvs_offset, non_default_uvs_offset;
3154 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3156 glyphs[i++] = kCGFontIndexInvalid;
3159 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3165 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3166 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3167 non_default_uvs_offset =
3168 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3169 dispatch_group_async (group, queue, ^{
3170 glyphs[i] = kCGFontIndexInvalid;
3172 if (default_uvs_offset)
3174 struct default_uvs_table *default_uvs =
3175 (struct default_uvs_table *) ((UInt8 *) uvs
3176 + default_uvs_offset);
3177 struct unicode_value_range *ranges =
3178 default_uvs->unicode_value_ranges;
3182 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3185 UInt32 mid = (lo + hi) / 2;
3187 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3193 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3194 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3198 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3200 struct non_default_uvs_table *non_default_uvs =
3201 (struct non_default_uvs_table *) ((UInt8 *) uvs
3202 + non_default_uvs_offset);
3203 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3207 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3210 UInt32 mid = (lo + hi) / 2;
3212 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3218 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3219 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3226 glyphs[i++] = kCGFontIndexInvalid;
3227 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3228 dispatch_release (group);
3232 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3234 CFDataRef uvs_table;
3235 CharacterCollection uvs_collection;
3239 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3243 UTF32Char selectors[256];
3244 CGGlyph glyphs[256];
3246 for (i = 0; i < 16; i++)
3247 selectors[i] = 0xFE00 + i;
3248 for (; i < 256; i++)
3249 selectors[i] = 0xE0100 + (i - 16);
3250 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3251 for (i = 0; i < 256; i++)
3253 CGGlyph glyph = glyphs[i];
3255 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3256 && glyph != kCGFontIndexInvalid)
3257 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3258 if (glyph == kCGFontIndexInvalid)
3262 variations[i] = (glyph ? glyph
3263 : macfont_get_glyph_for_character (font, c));
3273 static const char *const macfont_booleans[] = {
3279 static const char *const macfont_non_booleans[] = {
3287 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3289 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3293 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3294 CFArrayRef languages)
3296 Boolean result = true;
3297 CFArrayRef desc_languages =
3298 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3300 if (desc_languages == NULL)
3304 CFIndex desc_languages_count, i, languages_count;
3306 desc_languages_count = CFArrayGetCount (desc_languages);
3307 languages_count = CFArrayGetCount (languages);
3308 for (i = 0; i < languages_count; i++)
3309 if (!CFArrayContainsValue (desc_languages,
3310 CFRangeMake (0, desc_languages_count),
3311 CFArrayGetValueAtIndex (languages, i)))
3316 CFRelease (desc_languages);
3323 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3325 CFStringRef result = NULL;
3326 CFStringRef charset_string =
3327 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3329 if (charset_string && CFStringGetLength (charset_string) > 0)
3331 CFStringRef keys[] = {
3332 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3333 kCTLanguageAttributeName
3335 CFSTR ("NSLanguage")
3338 CFTypeRef values[] = {NULL};
3339 CFIndex num_values = 0;
3340 CFArrayRef languages
3341 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3343 if (languages && CFArrayGetCount (languages) > 0)
3345 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3346 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3349 CFCharacterSetRef charset =
3350 CFDictionaryGetValue (attributes,
3351 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3353 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3358 CFAttributedStringRef attr_string = NULL;
3359 CTLineRef ctline = NULL;
3360 CFDictionaryRef attrs
3361 = CFDictionaryCreate (NULL, (const void **) keys,
3362 (const void **) values, num_values,
3363 &kCFTypeDictionaryKeyCallBacks,
3364 &kCFTypeDictionaryValueCallBacks);
3368 attr_string = CFAttributedStringCreate (NULL, charset_string,
3374 ctline = CTLineCreateWithAttributedString (attr_string);
3375 CFRelease (attr_string);
3379 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3380 CFIndex i, nruns = CFArrayGetCount (runs);
3383 for (i = 0; i < nruns; i++)
3385 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3386 CFDictionaryRef attributes = CTRunGetAttributes (run);
3387 CTFontRef font_in_run;
3389 if (attributes == NULL)
3392 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3393 if (font_in_run == NULL)
3397 else if (!mac_ctfont_equal_in_postscript_name (font,
3401 if (nruns > 0 && i == nruns)
3402 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3411 static inline double
3412 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3414 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3418 static inline CGRect
3419 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3421 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3426 mac_ctfont_create_available_families (void)
3428 CFMutableArrayRef families = NULL;
3431 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3435 CFIndex i, count = CFArrayGetCount (orig_families);
3437 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3439 for (i = 0; i < count; i++)
3441 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3443 if (!CFStringHasPrefix (family, CFSTR ("."))
3444 && (CTFontManagerCompareFontFamilyNames (family,
3445 CFSTR ("LastResort"),
3447 != kCFCompareEqualTo))
3448 CFArrayAppendValue (families, family);
3450 CFRelease (orig_families);
3458 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3461 CFStringRef name1, name2;
3467 name1 = CTFontCopyPostScriptName (font1);
3470 name2 = CTFontCopyPostScriptName (font2);
3473 result = CFEqual (name1, name2);
3483 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3486 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3487 CFTypeRef values[] = {NULL, NULL};
3488 CFDictionaryRef attributes = NULL;
3489 CFAttributedStringRef attr_string = NULL;
3490 CTLineRef ctline = NULL;
3491 float float_zero = 0.0f;
3493 values[0] = macfont;
3494 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3497 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3498 (const void **) values,
3500 &kCFTypeDictionaryKeyCallBacks,
3501 &kCFTypeDictionaryValueCallBacks);
3502 CFRelease (values[1]);
3506 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3507 CFRelease (attributes);
3511 ctline = CTLineCreateWithAttributedString (attr_string);
3512 CFRelease (attr_string);
3516 /* Abandon if ctline contains some fonts other than the
3518 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3519 CFIndex i, nruns = CFArrayGetCount (runs);
3521 for (i = 0; i < nruns; i++)
3523 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3524 CFDictionaryRef attributes = CTRunGetAttributes (run);
3525 CTFontRef font_in_run;
3527 if (attributes == NULL)
3530 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3531 if (font_in_run == NULL)
3533 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3547 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3548 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3550 CFIndex used, result = 0;
3551 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3556 used = CTLineGetGlyphCount (ctline);
3557 if (used <= glyph_len)
3559 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3560 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3561 CGFloat total_advance = 0;
3562 CFIndex total_glyph_count = 0;
3564 for (k = 0; k < ctrun_count; k++)
3566 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3567 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3568 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3569 CFRange string_range, comp_range, range;
3570 CFIndex *permutation;
3572 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3573 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3577 #define RIGHT_TO_LEFT_P permutation
3579 /* Now the `comp_range' member of struct mac_glyph_layout is
3580 temporarily used as a work area such that:
3581 glbuf[i].comp_range.location =
3582 min {compRange[i + 1].location, ...,
3583 compRange[glyph_count - 1].location,
3584 maxRange (stringRangeForCTRun)}
3585 glbuf[i].comp_range.length = maxRange (compRange[i])
3586 where compRange[i] is the range of composed characters
3587 containing i-th glyph. */
3588 string_range = CTRunGetStringRange (ctrun);
3589 min_location = string_range.location + string_range.length;
3590 for (i = 0; i < glyph_count; i++)
3592 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3593 CFIndex glyph_index;
3596 if (!RIGHT_TO_LEFT_P)
3597 glyph_index = glyph_count - i - 1;
3600 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3603 CFStringGetRangeOfComposedCharactersAtIndex (string,
3605 gl->comp_range.location = min_location;
3606 gl->comp_range.length = rng.location + rng.length;
3607 if (rng.location < min_location)
3608 min_location = rng.location;
3611 /* Fill the `comp_range' member of struct mac_glyph_layout,
3612 and setup a permutation for right-to-left text. */
3613 comp_range = CFRangeMake (string_range.location, 0);
3614 range = CFRangeMake (0, 0);
3617 struct mac_glyph_layout *gl =
3618 glbuf + range.location + range.length;
3620 if (gl->comp_range.length
3621 > comp_range.location + comp_range.length)
3622 comp_range.length = gl->comp_range.length - comp_range.location;
3623 min_location = gl->comp_range.location;
3626 if (min_location >= comp_range.location + comp_range.length)
3628 comp_range.length = min_location - comp_range.location;
3629 for (i = 0; i < range.length; i++)
3631 glbuf[range.location + i].comp_range = comp_range;
3632 if (RIGHT_TO_LEFT_P)
3633 permutation[range.location + i] =
3634 range.location + range.length - i - 1;
3637 comp_range = CFRangeMake (min_location, 0);
3638 range.location += range.length;
3640 if (range.location == glyph_count)
3645 /* Then fill the remaining members. */
3646 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3649 struct mac_glyph_layout *gl;
3652 if (!RIGHT_TO_LEFT_P)
3653 gl = glbuf + range.location;
3658 src = glyph_count - 1 - range.location;
3659 dest = permutation[src];
3663 CFIndex tmp = gl->string_index;
3665 gl->string_index = glbuf[src].string_index;
3666 glbuf[src].string_index = tmp;
3669 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3671 CTRunGetPositions (ctrun, range, &position);
3672 gl->advance_delta = position.x - total_advance;
3673 gl->baseline_delta = position.y;
3674 gl->advance = (gl->advance_delta
3675 + CTRunGetTypographicBounds (ctrun, range,
3677 total_advance += gl->advance;
3680 if (RIGHT_TO_LEFT_P)
3681 xfree (permutation);
3683 #undef RIGHT_TO_LEFT_P
3685 total_glyph_count += glyph_count;
3695 /* The function below seems to cause a memory leak for the CFString
3696 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3697 10.6.3. For now, we use the NSGlyphInfo version instead. */
3698 #if USE_CT_GLYPH_INFO
3700 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3703 CGGlyph result = kCGFontIndexInvalid;
3704 UniChar characters[] = {0xfffd};
3706 CFAttributedStringRef attr_string = NULL;
3707 CTLineRef ctline = NULL;
3709 string = CFStringCreateWithCharacters (NULL, characters,
3710 ARRAYELTS (characters));
3714 CTGlyphInfoRef glyph_info =
3715 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3716 CFDictionaryRef attributes = NULL;
3720 CFStringRef keys[] = {kCTFontAttributeName,
3721 kCTGlyphInfoAttributeName};
3722 CFTypeRef values[] = {font, glyph_info};
3724 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3725 (const void **) values,
3727 &kCFTypeDictionaryKeyCallBacks,
3728 &kCFTypeDictionaryValueCallBacks);
3729 CFRelease (glyph_info);
3733 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3734 CFRelease (attributes);
3740 ctline = CTLineCreateWithAttributedString (attr_string);
3741 CFRelease (attr_string);
3745 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3747 if (CFArrayGetCount (runs) > 0)
3749 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3750 CFDictionaryRef attributes = CTRunGetAttributes (run);
3754 CTFontRef font_in_run =
3755 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3758 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3760 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3761 if (result >= CTFontGetGlyphCount (font))
3762 result = kCGFontIndexInvalid;
3774 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3776 CFArrayRef result = NULL;
3778 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3779 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3780 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3783 CTFontRef user_font =
3784 CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3788 CFArrayRef languages =
3789 CFArrayCreate (NULL, (const void **) &language, 1,
3790 &kCFTypeArrayCallBacks);
3794 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3796 CFRelease (languages);
3798 CFRelease (user_font);
3801 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3802 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3804 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3805 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3809 for (i = 0; macfont_language_default_font_names[i].language; i++)
3811 if (CFEqual (macfont_language_default_font_names[i].language,
3814 CFMutableArrayRef descriptors =
3815 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3822 macfont_language_default_font_names[i].font_names[j];
3825 CFDictionaryRef attributes =
3826 CFDictionaryCreate (NULL,
3828 &MAC_FONT_NAME_ATTRIBUTE),
3830 &macfont_language_default_font_names[i].font_names[j]),
3831 1, &kCFTypeDictionaryKeyCallBacks,
3832 &kCFTypeDictionaryValueCallBacks);
3836 FontDescriptorRef pat_desc =
3837 mac_font_descriptor_create_with_attributes (attributes);
3841 FontDescriptorRef descriptor =
3842 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3846 CFArrayAppendValue (descriptors, descriptor);
3847 CFRelease (descriptor);
3849 CFRelease (pat_desc);
3851 CFRelease (attributes);
3854 result = descriptors;
3866 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3867 CFArrayRef languages)
3869 CFStringRef result = NULL;
3870 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3871 CFArrayRef descriptors =
3872 mac_font_copy_default_descriptors_for_language (language);
3876 CFIndex i, count = CFArrayGetCount (descriptors);
3878 for (i = 0; i < count; i++)
3880 FontDescriptorRef descriptor =
3881 CFArrayGetValueAtIndex (descriptors, i);
3883 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3886 CFStringRef family =
3887 mac_font_descriptor_copy_attribute (descriptor,
3888 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3891 if (!CFStringHasPrefix (family, CFSTR ("."))
3892 && !CFEqual (family, CFSTR ("LastResort")))
3902 CFRelease (descriptors);
3909 macfont_get_nsctfont (struct font *font)
3911 struct macfont_info *macfont_info = (struct macfont_info *) font;
3912 FontRef macfont = macfont_info->macfont;
3914 return (void *) macfont;
3918 mac_register_font_driver (struct frame *f)
3920 register_font_driver (&macfont_driver, f);
3925 syms_of_macfont (void)
3927 static struct font_driver mac_font_driver;
3929 DEFSYM (Qmac_ct, "mac-ct");
3930 macfont_driver.type = Qmac_ct;
3931 register_font_driver (&macfont_driver, NULL);
3933 DEFSYM (QCdestination, ":destination");
3934 DEFSYM (QCminspace, ":minspace");