1 /* Font driver on Mac OSX Core text.
2 Copyright (C) 2009-2013 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"
38 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
40 #include <libkern/OSByteOrder.h>
42 static struct font_driver macfont_driver;
44 /* Core Text, for Mac OS X 10.5 and later. */
45 static Lisp_Object Qmac_ct;
47 static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
48 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
49 static CFArrayRef mac_ctfont_create_available_families (void);
50 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
51 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
53 static CFComparisonResult mac_font_family_compare (const void *,
54 const void *, void *);
55 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
57 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
58 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
59 struct mac_glyph_layout *, CFIndex);
61 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
62 CTCharacterCollection,
66 /* The font property key specifying the font design destination. The
67 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
68 text. (See the documentation of X Logical Font Description
69 Conventions.) In the Mac font driver, 1 means the screen font is
70 used for calculating some glyph metrics. You can see the
71 difference with Monaco 8pt or 9pt, for example. */
72 static Lisp_Object QCdestination;
74 /* The boolean-valued font property key specifying the use of
76 static Lisp_Object QCminspace;
78 struct macfont_metrics;
80 /* The actual structure for Mac font that can be casted to struct font. */
87 ScreenFontRef screen_font;
88 struct macfont_cache *cache;
89 struct macfont_metrics **metrics;
91 unsigned synthetic_italic_p : 1;
92 unsigned synthetic_bold_p : 1;
94 unsigned antialias : 2;
95 unsigned color_bitmap_p : 1;
98 /* Values for the `spacing' member in `struct macfont_info'. */
102 MACFONT_SPACING_PROPORTIONAL,
103 MACFONT_SPACING_MONO,
104 MACFONT_SPACING_SYNTHETIC_MONO,
107 /* Values for the `antialias' member in `struct macfont_info'. */
111 MACFONT_ANTIALIAS_DEFAULT,
112 MACFONT_ANTIALIAS_OFF,
113 MACFONT_ANTIALIAS_ON,
116 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
117 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
118 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
120 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
121 static const CGFloat synthetic_bold_factor = 0.024;
123 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
124 FontSymbolicTraits *);
125 static void macfont_store_descriptor_attributes (FontDescriptorRef,
127 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
130 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
131 static int macfont_glyph_extents (struct font *, CGGlyph,
132 struct font_metrics *, CGFloat *, int);
133 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
134 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
138 static CFIndex macfont_closest_traits_index (CFArrayRef,
140 static CFDataRef mac_font_copy_uvs_table (FontRef);
141 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
143 CGGlyph [], CFIndex);
145 /* From CFData to a lisp string. Always returns a unibyte string. */
148 cfdata_to_lisp (CFDataRef data)
150 CFIndex len = CFDataGetLength (data);
151 Lisp_Object result = make_uninit_string (len);
153 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
160 /* From CFString to a lisp string. Returns a unibyte string
161 containing a UTF-8 byte sequence. */
164 cfstring_to_lisp_nodecode (CFStringRef string)
166 Lisp_Object result = Qnil;
168 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
172 CFIndex i, length = CFStringGetLength (string);
174 for (i = 0; i < length; i++)
175 if (CFStringGetCharacterAtIndex (string, i) == 0)
179 return make_unibyte_string (s, strlen (s));
182 data = CFStringCreateExternalRepresentation (NULL, string,
183 kCFStringEncodingUTF8, '?');
186 result = cfdata_to_lisp (data);
193 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
194 cfstring_create_with_utf8_cstring, this function preserves NUL
198 cfstring_create_with_string_noencode (Lisp_Object s)
200 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
201 kCFStringEncodingUTF8, false);
204 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
205 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
206 kCFStringEncodingMacRoman, false);
212 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
214 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
216 return advancement.width;
220 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
223 #if USE_CT_GLYPH_INFO
224 return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
227 CGGlyph result = kCGFontIndexInvalid;
228 NSFont *nsFont = (NSFont *) font;
229 unichar characters[] = {0xfffd};
231 [NSString stringWithCharacters:characters
232 length:(sizeof (characters)
233 / sizeof (characters[0]))];
234 NSGlyphInfo *glyphInfo =
235 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
236 collection:collection
238 NSDictionary *attributes =
239 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
240 glyphInfo,NSGlyphInfoAttributeName,nil];
241 NSTextStorage *textStorage =
242 [[NSTextStorage alloc] initWithString:string
243 attributes:attributes];
244 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
245 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
246 NSFont *fontInTextStorage;
248 [layoutManager addTextContainer:textContainer];
249 [textContainer release];
250 [textStorage addLayoutManager:layoutManager];
251 [layoutManager release];
254 (void) [layoutManager glyphRangeForTextContainer:textContainer];
256 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
257 effectiveRange:NULL];
258 if (fontInTextStorage == nsFont
259 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
261 NSGlyph glyph = [layoutManager glyphAtIndex:0];
263 if (glyph < [nsFont numberOfGlyphs])
267 [textStorage release];
275 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
277 NSFont *result, *font;
279 font = [NSFont fontWithName:((NSString *) name) size:size];
280 result = [font screenFont];
282 return (ScreenFontRef)[result retain];
287 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
288 CGFloat *descent, CGFloat *leading)
290 NSFont *nsFont = [(NSFont *)font printerFont];
291 NSTextStorage *textStorage;
292 NSLayoutManager *layoutManager;
293 NSTextContainer *textContainer;
295 NSPoint spaceLocation;
298 textStorage = [[NSTextStorage alloc] initWithString:@" "];
299 layoutManager = [[NSLayoutManager alloc] init];
300 textContainer = [[NSTextContainer alloc] init];
302 [textStorage setFont:nsFont];
303 [textContainer setLineFragmentPadding:0];
304 [layoutManager setUsesScreenFonts:YES];
306 [layoutManager addTextContainer:textContainer];
307 [textContainer release];
308 [textStorage addLayoutManager:layoutManager];
309 [layoutManager release];
311 if (!(textStorage && layoutManager && textContainer))
313 [textStorage release];
318 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
319 effectiveRange:NULL];
320 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
321 [textStorage release];
323 *ascent = spaceLocation.y;
324 *descent = NSHeight (usedRect) - spaceLocation.y;
326 descender = [nsFont descender];
327 if (- descender < *descent)
329 *leading = *descent + descender;
330 *descent = - descender;
337 mac_font_shape_1 (NSFont *font, NSString *string,
338 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
343 NSTextStorage *textStorage;
344 NSLayoutManager *layoutManager;
345 NSTextContainer *textContainer;
346 NSUInteger stringLength;
347 NSPoint spaceLocation;
348 NSUInteger used, numberOfGlyphs;
350 textStorage = [[NSTextStorage alloc] initWithString:string];
351 layoutManager = [[NSLayoutManager alloc] init];
352 textContainer = [[NSTextContainer alloc] init];
354 /* Append a trailing space to measure baseline position. */
355 [textStorage appendAttributedString:([[[NSAttributedString alloc]
356 initWithString:@" "] autorelease])];
357 [textStorage setFont:font];
358 [textContainer setLineFragmentPadding:0];
359 [layoutManager setUsesScreenFonts:screen_font_p];
361 [layoutManager addTextContainer:textContainer];
362 [textContainer release];
363 [textStorage addLayoutManager:layoutManager];
364 [layoutManager release];
366 if (!(textStorage && layoutManager && textContainer))
368 [textStorage release];
373 stringLength = [string length];
376 (void) [layoutManager glyphRangeForTextContainer:textContainer];
378 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
380 /* Remove the appended trailing space because otherwise it may
381 generate a wrong result for a right-to-left text. */
382 [textStorage beginEditing];
383 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
384 [textStorage endEditing];
385 (void) [layoutManager glyphRangeForTextContainer:textContainer];
388 while (i < stringLength)
391 NSFont *fontInTextStorage =
392 [textStorage attribute:NSFontAttributeName atIndex:i
393 longestEffectiveRange:&range
394 inRange:(NSMakeRange (0, stringLength))];
396 if (!(fontInTextStorage == font
397 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
399 i = NSMaxRange (range);
401 if (i < stringLength)
402 /* Make the test `used <= glyph_len' below fail if textStorage
403 contained some fonts other than the specified one. */
404 used = glyph_len + 1;
407 NSRange range = NSMakeRange (0, stringLength);
409 range = [layoutManager glyphRangeForCharacterRange:range
410 actualCharacterRange:NULL];
411 numberOfGlyphs = NSMaxRange (range);
412 used = numberOfGlyphs;
413 for (i = 0; i < numberOfGlyphs; i++)
414 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
418 if (0 < used && used <= glyph_len)
420 NSUInteger glyphIndex, prevGlyphIndex;
421 unsigned char bidiLevel;
422 NSUInteger *permutation;
423 NSRange compRange, range;
424 CGFloat totalAdvance;
427 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
430 /* For now we assume the direction is not changed within the
432 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
433 glyphs:NULL characterIndexes:NULL
434 glyphInscriptions:NULL elasticBits:NULL
435 bidiLevels:&bidiLevel];
437 permutation = xmalloc (sizeof (NSUInteger) * used);
441 #define RIGHT_TO_LEFT_P permutation
443 /* Fill the `comp_range' member of struct mac_glyph_layout, and
444 setup a permutation for right-to-left text. */
445 compRange = NSMakeRange (0, 0);
446 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
449 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
450 NSUInteger characterIndex =
451 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
453 gl->string_index = characterIndex;
455 if (characterIndex >= NSMaxRange (compRange))
457 compRange.location = NSMaxRange (compRange);
460 NSRange characterRange =
462 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
465 NSMaxRange (characterRange) - compRange.location;
466 [layoutManager glyphRangeForCharacterRange:compRange
467 actualCharacterRange:&characterRange];
468 characterIndex = NSMaxRange (characterRange) - 1;
470 while (characterIndex >= NSMaxRange (compRange));
473 for (i = 0; i < range.length; i++)
474 permutation[range.location + i] = NSMaxRange (range) - i - 1;
476 range = NSMakeRange (NSMaxRange (range), 0);
479 gl->comp_range.location = compRange.location;
480 gl->comp_range.length = compRange.length;
482 while (++glyphIndex < numberOfGlyphs)
483 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
487 for (i = 0; i < range.length; i++)
488 permutation[range.location + i] = NSMaxRange (range) - i - 1;
490 /* Then fill the remaining members. */
491 glyphIndex = prevGlyphIndex = 0;
492 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
495 if (!RIGHT_TO_LEFT_P)
502 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
503 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
504 inTextContainer:textContainer rectCount:&nrects];
506 totalAdvance = NSMaxX (glyphRects[0]);
509 for (i = 0; i < used; i++)
511 struct mac_glyph_layout *gl;
513 NSUInteger nextGlyphIndex;
518 if (!RIGHT_TO_LEFT_P)
519 gl = glyph_layouts + i;
522 NSUInteger dest = permutation[i];
524 gl = glyph_layouts + dest;
527 CFIndex tmp = gl->string_index;
529 gl->string_index = glyph_layouts[i].string_index;
530 glyph_layouts[i].string_index = tmp;
533 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
535 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
536 gl->baseline_delta = spaceLocation.y - location.y;
538 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
541 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
544 if (!RIGHT_TO_LEFT_P)
548 if (prevGlyphIndex == 0)
549 glyphRange = NSMakeRange (0, nextGlyphIndex);
551 glyphRange = NSMakeRange (glyphIndex,
552 nextGlyphIndex - glyphIndex);
555 rectArrayForGlyphRange:glyphRange
556 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
557 inTextContainer:textContainer rectCount:&nrects];
558 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
559 gl->advance_delta = location.x - totalAdvance;
560 gl->advance = maxX - totalAdvance;
567 if (nextGlyphIndex == numberOfGlyphs)
568 glyphRange = NSMakeRange (prevGlyphIndex,
569 numberOfGlyphs - prevGlyphIndex);
571 glyphRange = NSMakeRange (prevGlyphIndex,
572 glyphIndex + 1 - prevGlyphIndex);
575 rectArrayForGlyphRange:glyphRange
576 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
577 inTextContainer:textContainer rectCount:&nrects];
578 minX = min (NSMinX (glyphRects[0]), totalAdvance);
579 gl->advance = totalAdvance - minX;
581 gl->advance_delta = location.x - totalAdvance;
584 prevGlyphIndex = glyphIndex + 1;
585 glyphIndex = nextGlyphIndex;
591 #undef RIGHT_TO_LEFT_P
595 [textStorage release];
601 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
602 struct mac_glyph_layout *glyph_layouts,
605 return mac_font_shape_1 ([(NSFont *)font printerFont],
607 glyph_layouts, glyph_len, YES);
611 get_cgcolor(unsigned long idx, struct frame *f)
613 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
615 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
616 NSInteger noc = [nsColor numberOfComponents];
617 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
620 [nsColor getComponents: components];
621 cgColor = CGColorCreate (colorSpace, components);
626 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, s) \
628 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (s->face), \
630 CGContextSetFillColorWithColor (context, refcol_) ; \
631 CGColorRelease (refcol_); \
633 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, s) \
635 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (s->face),\
637 CGContextSetFillColorWithColor (context, refcol_); \
638 CGColorRelease (refcol_); \
640 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, s) \
642 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (s->face),\
644 CGContextSetStrokeColorWithColor (context, refcol_); \
645 CGColorRelease (refcol_); \
649 /* Mac font driver. */
655 /* characters to distinguish the charset from the others */
657 /* additional constraint by language */
660 CFCharacterSetRef cf_charset;
661 CFStringRef cf_charset_string;
662 } cf_charset_table[] =
663 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
664 { "iso8859-2", { 0x00A0, 0x010E }},
665 { "iso8859-3", { 0x00A0, 0x0108 }},
666 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
667 { "iso8859-5", { 0x00A0, 0x0401 }},
668 { "iso8859-6", { 0x00A0, 0x060C }},
669 { "iso8859-7", { 0x00A0, 0x0384 }},
670 { "iso8859-8", { 0x00A0, 0x05D0 }},
671 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
672 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
673 { "iso8859-11", { 0x00A0, 0x0E01 }},
674 { "iso8859-13", { 0x00A0, 0x201C }},
675 { "iso8859-14", { 0x00A0, 0x0174 }},
676 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
677 { "iso8859-16", { 0x00A0, 0x0218}},
678 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
679 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0xF7E5 }, CFSTR ("zh-Hant") },
680 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
681 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
682 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
683 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
684 { "cns11643.1992-3", { 0x201A9 }},
685 { "cns11643.1992-4", { 0x20057 }},
686 { "cns11643.1992-5", { 0x20000 }},
687 { "cns11643.1992-6", { 0x20003 }},
688 { "cns11643.1992-7", { 0x20055 }},
689 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
690 { "jisx0212.1990-0", { 0x4E44 }},
691 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
692 { "jisx0213.2000-2", { 0xFA49 }},
693 { "jisx0213.2004-1", { 0x20B9F }},
694 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
695 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
696 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
697 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
698 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
699 { "unicode-sip", { 0x20000 }},
703 static CGFloat macfont_antialias_threshold;
706 macfont_update_antialias_threshold (void)
712 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
713 kCFPreferencesCurrentApplication,
716 macfont_antialias_threshold = threshold;
719 static inline Lisp_Object
720 macfont_intern_prop_cfstring (CFStringRef cfstring)
722 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
724 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
727 static inline CFIndex
728 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
739 unichars[0] = (c >> 10) + 0xD800;
740 unichars[1] = (c & 0x3FF) + 0xDC00;
747 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
748 FontSymbolicTraits *sym_traits)
752 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
753 OS 10.6 when the value is greater than or equal to 1 << 31. */
754 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
756 *sym_traits = (FontSymbolicTraits) sint64_value;
765 macfont_store_descriptor_attributes (FontDescriptorRef desc,
766 Lisp_Object spec_or_entity)
769 CFDictionaryRef dict;
773 str = mac_font_descriptor_copy_attribute (desc,
774 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
777 ASET (spec_or_entity, FONT_FAMILY_INDEX,
778 macfont_intern_prop_cfstring (str));
781 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
785 enum font_property_index index;
789 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
790 {{-0.4, 50}, /* light */
791 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
792 {0, 100}, /* normal */
793 {0.24, 140}, /* (semi-bold + normal) / 2 */
794 {0.4, 200}, /* bold */
795 {CGFLOAT_MAX, CGFLOAT_MAX}}},
796 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
797 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
798 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
799 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
802 for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
804 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
805 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
807 CGPoint *point = numeric_traits[i].points;
809 while (point->x < floatval)
811 if (point == numeric_traits[i].points)
813 else if (point->x == CGFLOAT_MAX)
815 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
816 * ((point->y - (point - 1)->y)
817 / (point->x - (point - 1)->x)));
818 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
819 make_number (lround (floatval)));
823 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
826 FontSymbolicTraits sym_traits;
829 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
830 spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
831 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
832 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
837 num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
838 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
839 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
841 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
847 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
848 FontSymbolicTraits synth_sym_traits)
851 CFDictionaryRef dict;
852 FontSymbolicTraits sym_traits = 0;
855 entity = font_make_entity ();
857 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
858 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
860 macfont_store_descriptor_attributes (desc, entity);
862 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
865 CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
868 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
871 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
872 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
873 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
874 name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
875 font_put_extra (entity, QCfont_entity,
876 make_save_ptr_int ((void *) name, sym_traits));
877 if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
878 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
879 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
880 if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
881 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
882 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
883 if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
884 ASET (entity, FONT_SPACING_INDEX,
885 make_number (FONT_SPACING_SYNTHETIC_MONO));
891 macfont_create_family_with_symbol (Lisp_Object symbol)
893 static CFArrayRef families = NULL;
894 CFStringRef result = NULL, family_name;
895 int using_cache_p = 1;
896 CFComparatorFunction family_name_comparator;
898 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
899 if (family_name == NULL)
902 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
903 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
904 if (CTFontManagerCompareFontFamilyNames != NULL)
907 family_name_comparator = CTFontManagerCompareFontFamilyNames;
909 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
910 else /* CTFontManagerCompareFontFamilyNames == NULL */
912 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
913 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
915 family_name_comparator = mac_font_family_compare;
919 if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
920 == kCFCompareEqualTo)
921 result = CFSTR ("LastResort");
927 if (families == NULL)
929 families = mac_font_create_available_families ();
931 if (families == NULL)
935 count = CFArrayGetCount (families);
936 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
937 (const void *) family_name,
938 family_name_comparator, NULL);
941 CFStringRef name = CFArrayGetValueAtIndex (families, i);
943 if ((*family_name_comparator) (name, family_name, NULL)
944 == kCFCompareEqualTo)
945 result = CFRetain (name);
948 if (result || !using_cache_p)
952 CFRelease (families);
957 CFRelease (family_name);
962 #define WIDTH_FRAC_BITS (4)
963 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
965 struct macfont_metrics
967 unsigned char lbearing_low, rbearing_low;
968 signed lbearing_high : 4, rbearing_high : 4;
969 unsigned char ascent_low, descent_low;
970 signed ascent_high : 4, descent_high : 4;
972 /* These two members are used for fixed-point representation of
973 glyph width. The `width_int' member is an integer that is
974 closest to the width. The `width_frac' member is the fractional
975 adjustment representing a value in [-.5, .5], multiplied by
976 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
977 the advance delta for centering instead of the glyph width. */
978 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
981 #define METRICS_VALUE(metrics, member) \
982 (((metrics)->member##_high << 8) | (metrics)->member##_low)
983 #define METRICS_SET_VALUE(metrics, member, value) \
984 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
985 (metrics)->member##_high = tmp >> 8;} while (0)
989 METRICS_INVALID = -1, /* metrics entry is invalid */
990 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
993 #define METRICS_STATUS(metrics) \
994 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
995 #define METRICS_SET_STATUS(metrics, status) \
996 do {METRICS_SET_VALUE (metrics, ascent, 0); \
997 METRICS_SET_VALUE (metrics, descent, status);} while (0)
999 #define METRICS_NCOLS_PER_ROW (128)
1000 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
1001 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1004 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1005 struct font_metrics *metrics, CGFloat *advance_delta,
1006 int force_integral_p)
1008 struct macfont_info *macfont_info = (struct macfont_info *) font;
1009 FontRef macfont = macfont_info->macfont;
1011 struct macfont_metrics *cache;
1014 row = glyph / METRICS_NCOLS_PER_ROW;
1015 col = glyph % METRICS_NCOLS_PER_ROW;
1016 if (row >= macfont_info->metrics_nrows)
1018 macfont_info->metrics =
1019 xrealloc (macfont_info->metrics,
1020 sizeof (struct macfont_metrics *) * (row + 1));
1021 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1022 (sizeof (struct macfont_metrics *)
1023 * (row + 1 - macfont_info->metrics_nrows)));
1024 macfont_info->metrics_nrows = row + 1;
1026 if (macfont_info->metrics[row] == NULL)
1028 struct macfont_metrics *new;
1031 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1032 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1033 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1034 macfont_info->metrics[row] = new;
1036 cache = macfont_info->metrics[row] + col;
1038 if (METRICS_STATUS (cache) == METRICS_INVALID)
1042 if (macfont_info->screen_font)
1043 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1045 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1047 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1048 advance delta value. */
1049 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1050 fwidth = (font->pixel_size - fwidth) / 2;
1051 cache->width_int = lround (fwidth);
1052 cache->width_frac = lround ((fwidth - cache->width_int)
1053 * WIDTH_FRAC_SCALE);
1054 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1056 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1057 width = font->pixel_size;
1059 width = cache->width_int;
1063 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1065 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1067 if (macfont_info->synthetic_italic_p)
1069 /* We assume the members a, b, c, and d in
1070 synthetic_italic_atfm are non-negative. */
1072 CGPointApplyAffineTransform (bounds.origin,
1073 synthetic_italic_atfm);
1075 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1077 if (macfont_info->synthetic_bold_p)
1080 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1082 bounds = CGRectInset (bounds, d, d);
1084 switch (macfont_info->spacing)
1086 case MACFONT_SPACING_PROPORTIONAL:
1087 bounds.origin.x += - (cache->width_frac
1088 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1090 case MACFONT_SPACING_MONO:
1092 case MACFONT_SPACING_SYNTHETIC_MONO:
1093 bounds.origin.x += (cache->width_int
1094 + (cache->width_frac
1095 / (CGFloat) WIDTH_FRAC_SCALE));
1098 if (bounds.size.width > 0)
1100 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1101 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1102 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1104 bounds = CGRectIntegral (bounds);
1105 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1106 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1107 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1108 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1110 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1111 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1112 metrics->width = width;
1113 metrics->ascent = METRICS_VALUE (cache, ascent);
1114 metrics->descent = METRICS_VALUE (cache, descent);
1119 switch (macfont_info->spacing)
1121 case MACFONT_SPACING_PROPORTIONAL:
1122 *advance_delta = (force_integral_p ? 0
1123 : - (cache->width_frac
1124 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1126 case MACFONT_SPACING_MONO:
1129 case MACFONT_SPACING_SYNTHETIC_MONO:
1130 *advance_delta = (force_integral_p ? cache->width_int
1132 + (cache->width_frac
1133 / (CGFloat) WIDTH_FRAC_SCALE)));
1141 static CFMutableDictionaryRef macfont_cache_dictionary;
1143 /* Threshold used in row_nkeys_or_perm. This must be less than or
1144 equal to the number of rows that are invalid as BMP (i.e., from
1145 U+D800 to U+DFFF). */
1146 #define ROW_PERM_OFFSET (8)
1148 /* The number of glyphs that can be stored in a value for a single
1149 entry of CFDictionary. */
1150 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1152 struct macfont_cache
1154 int reference_count;
1155 CFCharacterSetRef cf_charset;
1157 /* The cached glyph for a BMP character c is stored in
1158 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1159 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1160 unsigned char row_nkeys_or_perm[256];
1163 /* Number of rows for which the BMP cache is allocated so far.
1164 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1167 /* The cached glyph for a character c is stored as the (c %
1168 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1169 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1170 not stored here if row_nkeys_or_perm[c / 256] >=
1172 CFMutableDictionaryRef dictionary;
1176 /* UVS (Unicode Variation Sequence) subtable data, which is of
1177 type CFDataRef if available. NULL means it is not initialized
1178 yet. kCFNull means the subtable is not found and there is no
1179 suitable fallback table for this font. */
1182 /* Character collection specifying the destination of the mapping
1183 provided by `table' above. If `table' is obtained from the UVS
1184 subtable in the font cmap table, then the value of this member
1185 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1186 CharacterCollection collection;
1190 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1191 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1192 static void macfont_release_cache (struct macfont_cache *);
1193 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1194 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1195 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1196 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1197 CharacterCollection, CGFontIndex);
1198 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1200 static struct macfont_cache *
1201 macfont_lookup_cache (CFStringRef key)
1203 struct macfont_cache *cache;
1205 if (macfont_cache_dictionary == NULL)
1207 macfont_cache_dictionary =
1208 CFDictionaryCreateMutable (NULL, 0,
1209 &kCFTypeDictionaryKeyCallBacks, NULL);
1213 cache = ((struct macfont_cache *)
1214 CFDictionaryGetValue (macfont_cache_dictionary, key));
1218 FontRef macfont = mac_font_create_with_name (key, 0);
1222 cache = xzalloc (sizeof (struct macfont_cache));
1223 /* Treat the LastResort font as if it contained glyphs for
1224 all characters. This may look too rough, but neither
1225 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1226 for this font is correct for non-BMP characters on Mac OS
1228 if (CFStringCompare (key, CFSTR ("LastResort"), 0)
1229 == kCFCompareEqualTo)
1231 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1234 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1236 if (cache->cf_charset == NULL)
1237 cache->cf_charset = mac_font_copy_character_set (macfont);
1238 CFDictionaryAddValue (macfont_cache_dictionary, key,
1239 (const void *) cache);
1240 CFRelease (macfont);
1247 static struct macfont_cache *
1248 macfont_retain_cache (struct macfont_cache *cache)
1250 cache->reference_count++;
1256 macfont_release_cache (struct macfont_cache *cache)
1258 if (--cache->reference_count == 0)
1262 for (i = 0; i < cache->glyph.nrows; i++)
1263 xfree (cache->glyph.matrix[i]);
1264 xfree (cache->glyph.matrix);
1265 if (cache->glyph.dictionary)
1266 CFRelease (cache->glyph.dictionary);
1267 memset (&cache->glyph, 0, sizeof (cache->glyph));
1268 if (cache->uvs.table)
1269 CFRelease (cache->uvs.table);
1270 memset (&cache->uvs, 0, sizeof (cache->uvs));
1274 static CFCharacterSetRef
1275 macfont_get_cf_charset (struct font *font)
1277 struct macfont_info *macfont_info = (struct macfont_info *) font;
1279 return macfont_info->cache->cf_charset;
1282 static CFCharacterSetRef
1283 macfont_get_cf_charset_for_name (CFStringRef name)
1285 struct macfont_cache *cache = macfont_lookup_cache (name);
1287 return cache->cf_charset;
1291 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1293 struct macfont_info *macfont_info = (struct macfont_info *) font;
1294 FontRef macfont = macfont_info->macfont;
1295 struct macfont_cache *cache = macfont_info->cache;
1297 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1300 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1302 if (nkeys_or_perm < ROW_PERM_OFFSET)
1304 UniChar unichars[256], ch;
1308 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1309 dispatch_queue_t queue;
1310 dispatch_group_t group = NULL;
1317 CFMutableDictionaryRef dictionary;
1318 uintptr_t key, value;
1322 if (cache->glyph.dictionary == NULL)
1323 cache->glyph.dictionary =
1324 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1325 dictionary = cache->glyph.dictionary;
1326 key = c / NGLYPHS_IN_VALUE;
1327 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1328 value = ((uintptr_t)
1329 CFDictionaryGetValue (dictionary, (const void *) key));
1330 glyph = (value >> nshifts);
1334 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1337 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1340 glyph = kCGFontIndexInvalid;
1343 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1344 value |= ((uintptr_t) glyph << nshifts);
1345 CFDictionarySetValue (dictionary, (const void *) key,
1346 (const void *) value);
1351 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1353 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1354 group = dispatch_group_create ();
1355 dispatch_group_async (group, queue, ^{
1359 nkeys = nkeys_or_perm;
1360 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1361 if (CFDictionaryContainsKey (dictionary,
1362 (const void *) key))
1364 CFDictionaryRemoveValue (dictionary,
1365 (const void *) key);
1369 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1375 for (i = 0; i < 256; i++)
1378 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1379 unichars[len++] = ch;
1382 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1385 mac_font_get_glyphs_for_characters (macfont, unichars,
1389 int next = unichars[len - 1] % 256;
1392 glyphs[i] = kCGFontIndexInvalid;
1395 glyphs[i] = glyphs[len];
1402 glyphs[i] = kCGFontIndexInvalid;
1404 nrows = cache->glyph.nrows;
1405 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1406 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1408 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1409 sizeof (CGGlyph *) * nrows);
1410 cache->glyph.matrix[nrows - 1] = glyphs;
1411 cache->glyph.nrows = nrows;
1413 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1416 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1417 dispatch_release (group);
1422 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1426 uintptr_t key, value;
1430 if (cache->glyph.dictionary == NULL)
1431 cache->glyph.dictionary =
1432 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1433 key = c / NGLYPHS_IN_VALUE;
1434 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1435 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1436 (const void *) key);
1437 glyph = (value >> nshifts);
1440 UniChar unichars[2];
1442 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1444 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1448 glyph = kCGFontIndexInvalid;
1450 value |= ((uintptr_t) glyph << nshifts);
1451 CFDictionarySetValue (cache->glyph.dictionary,
1452 (const void *) key, (const void *) value);
1460 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1463 struct macfont_info *macfont_info = (struct macfont_info *) font;
1464 FontRef macfont = macfont_info->macfont;
1467 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1471 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1473 struct macfont_info *macfont_info = (struct macfont_info *) font;
1474 FontRef macfont = macfont_info->macfont;
1475 struct macfont_cache *cache = macfont_info->cache;
1476 CFDataRef result = NULL;
1478 if (cache->uvs.table == NULL)
1480 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1481 CharacterCollection uvs_collection =
1482 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1484 if (uvs_table == NULL
1485 && mac_font_get_glyph_for_cid (macfont,
1486 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1487 6480) != kCGFontIndexInvalid)
1489 /* If the glyph for U+4E55 is accessible via its CID 6480,
1490 then we use the Adobe-Japan1 UVS table, which maps a
1491 variation sequence to a CID, as a fallback. */
1492 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1494 if (mac_uvs_table_adobe_japan1 == NULL)
1495 mac_uvs_table_adobe_japan1 =
1496 CFDataCreateWithBytesNoCopy (NULL,
1497 mac_uvs_table_adobe_japan1_bytes,
1498 sizeof (mac_uvs_table_adobe_japan1_bytes),
1500 if (mac_uvs_table_adobe_japan1)
1502 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1503 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1506 if (uvs_table == NULL)
1507 cache->uvs.table = kCFNull;
1509 cache->uvs.table = uvs_table;
1510 cache->uvs.collection = uvs_collection;
1513 if (cache->uvs.table != kCFNull)
1515 result = cache->uvs.table;
1516 *collection = cache->uvs.collection;
1522 static Lisp_Object macfont_get_cache (struct frame *);
1523 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1524 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1525 static Lisp_Object macfont_list_family (struct frame *);
1526 static void macfont_free_entity (Lisp_Object);
1527 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1528 static void macfont_close (struct font *);
1529 static int macfont_has_char (Lisp_Object, int);
1530 static unsigned macfont_encode_char (struct font *, int);
1531 static int macfont_text_extents (struct font *, unsigned int *, int,
1532 struct font_metrics *);
1533 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1534 static Lisp_Object macfont_shape (Lisp_Object);
1535 static int macfont_variation_glyphs (struct font *, int c,
1536 unsigned variations[256]);
1537 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1539 static struct font_driver macfont_driver =
1541 LISP_INITIALLY_ZERO, /* Qmac_ct */
1542 0, /* case insensitive */
1546 macfont_list_family,
1547 macfont_free_entity,
1550 NULL, /* prepare_face */
1551 NULL, /* done_face */
1553 macfont_encode_char,
1554 macfont_text_extents,
1556 NULL, /* get_bitmap */
1557 NULL, /* free_bitmap */
1558 NULL, /* get_outline */
1559 NULL, /* free_outline */
1560 NULL, /* anchor_point */
1561 NULL, /* otf_capability */
1562 NULL, /* otf_drive */
1563 NULL, /* start_for_frame */
1564 NULL, /* end_for_frame */
1567 macfont_variation_glyphs,
1568 macfont_filter_properties,
1572 macfont_get_cache (struct frame * f)
1574 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1576 return (dpyinfo->name_list_element);
1580 macfont_get_charset (Lisp_Object registry)
1582 char *str = SSDATA (SYMBOL_NAME (registry));
1583 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1587 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1591 else if (str[i] == '*')
1598 regexp = make_unibyte_string (re, j);
1599 for (i = 0; cf_charset_table[i].name; i++)
1600 if (fast_c_string_match_ignore_case
1601 (regexp, cf_charset_table[i].name,
1602 strlen (cf_charset_table[i].name)) >= 0)
1604 if (! cf_charset_table[i].name)
1606 if (! cf_charset_table[i].cf_charset)
1608 int *uniquifier = cf_charset_table[i].uniquifier;
1609 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1612 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1616 for (j = 0; uniquifier[j]; j++)
1618 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1620 CFCharacterSetAddCharactersInRange (charset,
1621 CFRangeMake (uniquifier[j], 1));
1624 string = CFStringCreateWithCharacters (NULL, unichars, count);
1627 CFRelease (charset);
1630 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1632 CFRelease (charset);
1633 /* CFCharacterSetCreateWithCharactersInString does not handle
1634 surrogate pairs properly as of Mac OS X 10.5. */
1635 cf_charset_table[i].cf_charset_string = string;
1643 unsigned int script_tag, langsys_tag;
1645 unsigned int *features[2];
1648 #define OTF_SYM_TAG(SYM, TAG) \
1650 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1651 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1654 #define OTF_TAG_STR(TAG, P) \
1656 (P)[0] = (char) (TAG >> 24); \
1657 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1658 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1659 (P)[3] = (char) (TAG & 0xFF); \
1663 static struct OpenTypeSpec *
1664 macfont_get_open_type_spec (Lisp_Object otf_spec)
1666 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1673 spec->script = XCAR (otf_spec);
1674 if (! NILP (spec->script))
1676 OTF_SYM_TAG (spec->script, spec->script_tag);
1677 val = assq_no_quit (spec->script, Votf_script_alist);
1678 if (CONSP (val) && SYMBOLP (XCDR (val)))
1679 spec->script = XCDR (val);
1681 spec->script = Qnil;
1684 spec->script_tag = 0x44464C54; /* "DFLT" */
1685 otf_spec = XCDR (otf_spec);
1686 spec->langsys_tag = 0;
1687 if (! NILP (otf_spec))
1689 val = XCAR (otf_spec);
1691 OTF_SYM_TAG (val, spec->langsys_tag);
1692 otf_spec = XCDR (otf_spec);
1694 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1695 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1699 val = XCAR (otf_spec);
1702 len = Flength (val);
1704 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1706 : malloc (XINT (len) * sizeof *spec->features[i]));
1707 if (! spec->features[i])
1709 if (i > 0 && spec->features[0])
1710 free (spec->features[0]);
1714 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1716 if (NILP (XCAR (val)))
1722 OTF_SYM_TAG (XCAR (val), tag);
1723 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1726 spec->nfeatures[i] = j;
1731 static CFMutableDictionaryRef
1732 macfont_create_attributes_with_spec (Lisp_Object spec)
1734 Lisp_Object tmp, extra;
1735 CFMutableArrayRef langarray = NULL;
1736 CFCharacterSetRef charset = NULL;
1737 CFStringRef charset_string = NULL;
1738 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1739 Lisp_Object script = Qnil;
1740 Lisp_Object registry;
1741 int cf_charset_idx, i;
1742 struct OpenTypeSpec *otspec = NULL;
1744 enum font_property_index index;
1747 } numeric_traits[] =
1748 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1749 {{-0.4, 50}, /* light */
1750 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1751 {0, 100}, /* normal */
1752 {0.24, 140}, /* (semi-bold + normal) / 2 */
1753 {0.4, 200}, /* bold */
1754 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1755 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1756 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1757 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1758 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1760 registry = AREF (spec, FONT_REGISTRY_INDEX);
1762 || EQ (registry, Qascii_0)
1763 || EQ (registry, Qiso10646_1)
1764 || EQ (registry, Qunicode_bmp))
1765 cf_charset_idx = -1;
1770 cf_charset_idx = macfont_get_charset (registry);
1771 if (cf_charset_idx < 0)
1773 charset = cf_charset_table[cf_charset_idx].cf_charset;
1774 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1775 lang = cf_charset_table[cf_charset_idx].lang;
1778 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1781 CFArrayAppendValue (langarray, lang);
1785 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1786 CONSP (extra); extra = XCDR (extra))
1788 Lisp_Object key, val;
1791 key = XCAR (tmp), val = XCDR (tmp);
1792 if (EQ (key, QClang))
1795 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1800 for (; CONSP (val); val = XCDR (val))
1801 if (SYMBOLP (XCAR (val)))
1804 cfstring_create_with_string_noencode (SYMBOL_NAME
1809 CFArrayAppendValue (langarray, lang);
1813 else if (EQ (key, QCotf))
1815 otspec = macfont_get_open_type_spec (val);
1818 script = otspec->script;
1820 else if (EQ (key, QCscript))
1824 if (! NILP (script) && ! charset)
1826 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1828 if (CONSP (chars) && CONSP (CDR (chars)))
1830 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1831 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1833 if (! string || !cs)
1841 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1842 if (CHARACTERP (XCAR (chars)))
1844 UniChar unichars[2];
1846 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1848 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1850 CFStringAppendCharacters (string, unichars, count);
1851 CFCharacterSetAddCharactersInRange (cs, range);
1854 /* CFCharacterSetCreateWithCharactersInString does not
1855 handle surrogate pairs properly as of Mac OS X 10.5. */
1856 charset_string = string;
1860 attributes = CFDictionaryCreateMutable (NULL, 0,
1861 &kCFTypeDictionaryKeyCallBacks,
1862 &kCFTypeDictionaryValueCallBacks);
1866 tmp = AREF (spec, FONT_FAMILY_INDEX);
1867 if (SYMBOLP (tmp) && ! NILP (tmp))
1869 CFStringRef family = macfont_create_family_with_symbol (tmp);
1873 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1878 traits = CFDictionaryCreateMutable (NULL, 4,
1879 &kCFTypeDictionaryKeyCallBacks,
1880 &kCFTypeDictionaryValueCallBacks);
1884 for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
1886 tmp = AREF (spec, numeric_traits[i].index);
1889 CGPoint *point = numeric_traits[i].points;
1890 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1893 while (point->y < floatval)
1895 if (point == numeric_traits[i].points)
1897 else if (point->y == CGFLOAT_MAX)
1899 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1900 * ((point->x - (point - 1)->x)
1901 / (point->y - (point - 1)->y)));
1904 else if (floatval < -1.0)
1906 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1909 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1913 if (CFDictionaryGetCount (traits))
1914 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1917 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1920 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1923 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1930 CFRelease (attributes);
1935 if (langarray) CFRelease (langarray);
1936 if (charset && cf_charset_idx < 0) CFRelease (charset);
1937 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1938 if (traits) CFRelease (traits);
1941 if (otspec->nfeatures[0] > 0)
1942 free (otspec->features[0]);
1943 if (otspec->nfeatures[1] > 0)
1944 free (otspec->features[1]);
1952 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1953 CFCharacterSetRef charset,
1955 CFArrayRef languages)
1957 Boolean result = true;
1959 if (charset || VECTORP (chars))
1961 CFCharacterSetRef desc_charset =
1962 mac_font_descriptor_copy_attribute (desc,
1963 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1965 if (desc_charset == NULL)
1970 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1971 else /* VECTORP (chars) */
1975 for (j = 0; j < ASIZE (chars); j++)
1976 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
1977 && CFCharacterSetIsLongCharacterMember (desc_charset,
1978 XFASTINT (AREF (chars, j))))
1980 if (j == ASIZE (chars))
1983 CFRelease (desc_charset);
1986 if (result && languages)
1987 result = mac_font_descriptor_supports_languages (desc, languages);
1993 macfont_closest_traits_index (CFArrayRef traits_array,
1994 FontSymbolicTraits target)
1996 CFIndex i, result = -1, count = CFArrayGetCount (traits_array);
1997 int min_distance = (1 << 3);
1999 for (i = 0; i < count; i++)
2001 FontSymbolicTraits traits, diff;
2004 traits = ((FontSymbolicTraits) (uintptr_t)
2005 CFArrayGetValueAtIndex (traits_array, i));
2006 diff = (target ^ traits);
2007 /* We prefer synthetic bold of italic to synthetic italic of
2008 bold when both bold and italic are available but bold-italic
2009 is not available. */
2010 if (diff & MAC_FONT_TRAIT_BOLD)
2011 distance |= (1 << 0);
2012 if (diff & MAC_FONT_TRAIT_ITALIC)
2013 distance |= (1 << 1);
2014 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2015 distance |= (1 << 2);
2016 if (distance < min_distance)
2018 min_distance = distance;
2027 macfont_list (struct frame *f, Lisp_Object spec)
2029 Lisp_Object val = Qnil, family, extra;
2031 CFStringRef family_name = NULL;
2032 CFMutableDictionaryRef attributes = NULL, traits;
2033 Lisp_Object chars = Qnil;
2035 FontSymbolicTraits synth_sym_traits = 0;
2036 CFArrayRef families;
2037 CFIndex families_count;
2038 CFCharacterSetRef charset = NULL;
2039 CFArrayRef languages = NULL;
2043 family = AREF (spec, FONT_FAMILY_INDEX);
2044 if (! NILP (family))
2046 family_name = macfont_create_family_with_symbol (family);
2047 if (family_name == NULL)
2051 attributes = macfont_create_attributes_with_spec (spec);
2055 charset = ((CFCharacterSetRef)
2056 CFDictionaryGetValue (attributes,
2057 MAC_FONT_CHARACTER_SET_ATTRIBUTE));
2061 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2065 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2068 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2069 if (CONSP (val) && VECTORP (XCDR (val)))
2075 languages = ((CFArrayRef)
2076 CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE));
2079 CFRetain (languages);
2080 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2083 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2084 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2086 traits = ((CFMutableDictionaryRef)
2087 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2089 n = FONT_SLANT_NUMERIC (spec);
2090 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2092 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2094 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2097 n = FONT_WEIGHT_NUMERIC (spec);
2098 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2100 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2102 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2106 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2108 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2110 if (CFStringHasPrefix (language, CFSTR ("ja"))
2111 || CFStringHasPrefix (language, CFSTR ("ko"))
2112 || CFStringHasPrefix (language, CFSTR ("zh")))
2113 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2116 /* Create array of families. */
2118 families = CFArrayCreate (NULL, (const void **) &family_name,
2119 1, &kCFTypeArrayCallBacks);
2122 CFStringRef pref_family;
2123 CFIndex families_count, pref_family_index = -1;
2125 families = mac_font_create_available_families ();
2126 if (families == NULL)
2129 families_count = CFArrayGetCount (families);
2131 /* Move preferred family to the front if exists. */
2133 mac_font_create_preferred_family_for_attributes (attributes);
2137 CFArrayGetFirstIndexOfValue (families,
2138 CFRangeMake (0, families_count),
2140 CFRelease (pref_family);
2142 if (pref_family_index > 0)
2144 CFMutableArrayRef mutable_families =
2145 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2147 if (mutable_families)
2149 CFArrayAppendValue (mutable_families,
2150 CFArrayGetValueAtIndex (families,
2151 pref_family_index));
2152 CFArrayAppendArray (mutable_families, families,
2153 CFRangeMake (0, pref_family_index));
2154 if (pref_family_index + 1 < families_count)
2155 CFArrayAppendArray (mutable_families, families,
2156 CFRangeMake (pref_family_index + 1,
2158 - (pref_family_index + 1)));
2159 CFRelease (families);
2160 families = mutable_families;
2166 extra = AREF (spec, FONT_EXTRA_INDEX);
2167 families_count = CFArrayGetCount (families);
2168 for (i = 0; i < families_count; i++)
2170 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2171 FontDescriptorRef pat_desc;
2173 CFIndex descs_count;
2174 CFMutableArrayRef filtered_descs, traits_array;
2178 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2180 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2184 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2185 10.7 returns NULL if pat_desc represents the LastResort font.
2186 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2187 trailing "s") for such a font. */
2188 if (CFStringCompare (family_name, CFSTR ("LastResort"), 0)
2189 != kCFCompareEqualTo)
2190 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2194 FontDescriptorRef lr_desc =
2195 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2199 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2200 &kCFTypeArrayCallBacks);
2201 CFRelease (lr_desc);
2206 CFRelease (pat_desc);
2210 descs_count = CFArrayGetCount (descs);
2211 if (descs_count == 0
2212 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2221 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2222 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2223 for (j = 0; j < descs_count; j++)
2225 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2226 CFDictionaryRef dict;
2228 FontSymbolicTraits sym_traits;
2230 dict = mac_font_descriptor_copy_attribute (desc,
2231 MAC_FONT_TRAITS_ATTRIBUTE);
2235 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2238 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2242 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2243 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2244 != (spacing >= FONT_SPACING_MONO)))
2247 /* Don't use a color bitmap font unless its family is
2248 explicitly specified. */
2249 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2253 && !macfont_supports_charset_and_languages_p (desc, charset,
2257 CFArrayAppendValue (filtered_descs, desc);
2258 CFArrayAppendValue (traits_array,
2259 (const void *) (uintptr_t) sym_traits);
2263 descs = filtered_descs;
2264 descs_count = CFArrayGetCount (descs);
2266 for (j = 0; j < descs_count; j++)
2268 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2269 FontSymbolicTraits sym_traits =
2270 ((FontSymbolicTraits) (uintptr_t)
2271 CFArrayGetValueAtIndex (traits_array, j));
2272 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2274 mask_min = ((synth_sym_traits ^ sym_traits)
2275 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2276 if (FONT_SLANT_NUMERIC (spec) < 0)
2277 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2278 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2279 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2281 mask_max = (synth_sym_traits & ~sym_traits);
2282 /* Synthetic bold does not work for bitmap-only fonts on Mac
2284 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2286 CFNumberRef format =
2287 mac_font_descriptor_copy_attribute (desc,
2288 MAC_FONT_FORMAT_ATTRIBUTE);
2292 uint32_t format_val;
2294 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2296 && format_val == MAC_FONT_FORMAT_BITMAP)
2297 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2301 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2303 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2304 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2305 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2306 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2307 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2308 bmask += MAC_FONT_TRAIT_BOLD)
2309 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2310 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2311 imask += MAC_FONT_TRAIT_ITALIC)
2313 FontSymbolicTraits synth = (imask | bmask | mmask);
2316 || j == macfont_closest_traits_index (traits_array,
2317 (sym_traits | synth)))
2319 entity = macfont_descriptor_entity (desc, extra, synth);
2320 if (! NILP (entity))
2321 val = Fcons (entity, val);
2326 CFRelease (traits_array);
2330 CFRelease (families);
2331 val = Fnreverse (val);
2337 FONT_ADD_LOG ("macfont-list", spec, val);
2338 if (charset) CFRelease (charset);
2339 if (languages) CFRelease (languages);
2340 if (attributes) CFRelease (attributes);
2341 if (family_name) CFRelease (family_name);
2349 macfont_match (struct frame * frame, Lisp_Object spec)
2351 Lisp_Object entity = Qnil;
2352 CFMutableDictionaryRef attributes;
2353 FontDescriptorRef pat_desc = NULL, desc = NULL;
2357 attributes = macfont_create_attributes_with_spec (spec);
2360 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2361 CFRelease (attributes);
2365 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2367 CFRelease (pat_desc);
2371 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2377 FONT_ADD_LOG ("macfont-match", spec, entity);
2382 macfont_list_family (struct frame *frame)
2384 Lisp_Object list = Qnil;
2385 CFArrayRef families;
2389 families = mac_font_create_available_families ();
2392 CFIndex i, count = CFArrayGetCount (families);
2394 for (i = 0; i < count; i++)
2395 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2396 CFRelease (families);
2405 macfont_free_entity (Lisp_Object entity)
2407 Lisp_Object val = assq_no_quit (QCfont_entity,
2408 AREF (entity, FONT_EXTRA_INDEX));
2409 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2417 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2419 Lisp_Object val, font_object;
2420 CFStringRef font_name;
2421 struct macfont_info *macfont_info = NULL;
2425 FontSymbolicTraits sym_traits;
2427 int len, i, total_width;
2429 CGFloat ascent, descent, leading;
2431 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2433 || XTYPE (XCDR (val)) != Lisp_Misc
2434 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2436 font_name = XSAVE_POINTER (XCDR (val), 0);
2437 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2439 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2444 macfont = mac_font_create_with_name (font_name, size);
2447 int fontsize = (int) [((NSFont *) macfont) pointSize];
2448 if (fontsize != size) size = fontsize;
2454 font_object = font_make_object (VECSIZE (struct macfont_info), entity, size);
2455 ASET (font_object, FONT_TYPE_INDEX, macfont_driver.type);
2456 len = font_unparse_xlfd (entity, size, name, 256);
2458 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
2459 len = font_unparse_fcname (entity, size, name, 256);
2461 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
2463 ASET (font_object, FONT_FULLNAME_INDEX,
2464 AREF (font_object, FONT_NAME_INDEX));
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 ((CFStringCompare (family_name, CFSTR ("Courier"), 0)
2550 == kCFCompareEqualTo)
2551 || (CFStringCompare (family_name, CFSTR ("Helvetica"), 0)
2552 == kCFCompareEqualTo)
2553 || (CFStringCompare (family_name, CFSTR ("Times"), 0)
2554 == kCFCompareEqualTo))
2555 ascent += (ascent + descent) * .15f;
2556 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2561 CFRelease (family_name);
2564 font->ascent = ascent + 0.5f;
2565 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2566 if (CONSP (val) && !NILP (XCDR (val)))
2567 font->descent = descent + 0.5f;
2569 font->descent = descent + leading + 0.5f;
2570 font->height = font->ascent + font->descent;
2572 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2573 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2577 /* Unfortunately Xft doesn't provide a way to get minimum char
2578 width. So, we use space_width instead. */
2579 font->min_width = font->max_width = font->space_width; /* XXX */
2581 font->baseline_offset = 0;
2582 font->relative_compose = 0;
2583 font->default_ascent = 0;
2584 font->vertical_centering = 0;
2590 macfont_close (struct font *font)
2592 struct macfont_info *macfont_info = (struct macfont_info *) font;
2594 if (macfont_info->cache)
2599 CFRelease (macfont_info->macfont);
2600 CGFontRelease (macfont_info->cgfont);
2601 if (macfont_info->screen_font)
2602 CFRelease (macfont_info->screen_font);
2603 macfont_release_cache (macfont_info->cache);
2604 macfont_info->cache = NULL;
2605 for (i = 0; i < macfont_info->metrics_nrows; i++)
2606 if (macfont_info->metrics[i])
2607 xfree (macfont_info->metrics[i]);
2608 if (macfont_info->metrics)
2609 xfree (macfont_info->metrics);
2615 macfont_has_char (Lisp_Object font, int c)
2618 CFCharacterSetRef charset;
2621 if (FONT_ENTITY_P (font))
2626 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2628 name = XSAVE_POINTER (val, 0);
2629 charset = macfont_get_cf_charset_for_name (name);
2632 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2634 result = CFCharacterSetIsLongCharacterMember (charset, c);
2641 macfont_encode_char (struct font *font, int c)
2643 struct macfont_info *macfont_info = (struct macfont_info *) font;
2647 glyph = macfont_get_glyph_for_character (font, c);
2650 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2654 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2655 struct font_metrics *metrics)
2660 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2661 for (i = 1; i < nglyphs; i++)
2663 struct font_metrics m;
2664 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2669 if (width + m.lbearing < metrics->lbearing)
2670 metrics->lbearing = width + m.lbearing;
2671 if (width + m.rbearing > metrics->rbearing)
2672 metrics->rbearing = width + m.rbearing;
2673 if (m.ascent > metrics->ascent)
2674 metrics->ascent = m.ascent;
2675 if (m.descent > metrics->descent)
2676 metrics->descent = m.descent;
2683 metrics->width = width;
2689 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2690 bool with_background)
2692 struct frame * f = s->f;
2693 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2694 FontRef macfont = macfont_info->macfont;
2695 CGContextRef context;
2696 BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
2697 int end = isComposite ? s->cmp_to : s->nchars;
2698 int len = end - s->cmp_from;
2703 context = [[NSGraphicsContext currentContext] graphicsPort];
2704 CGContextSaveGState (context);
2707 if (s->num_clips > 0)
2711 for (i = 0; i < s->num_clips; i++)
2712 clips[i] = mac_rect_make (f, s->clip[i].left, s->clip[i].top,
2713 s->clip[i].right - s->clip[i].left,
2714 s->clip[i].bottom - s->clip[i].top);
2715 CGContextClipToRects (context, clips, s->num_clips);
2719 if (with_background)
2721 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, s);
2722 CGContextFillRect (context,
2724 s->width, FONT_HEIGHT (s->font)));
2727 if (macfont_info->cgfont)
2729 CGGlyph *glyphs = alloca (sizeof (CGGlyph) * len);
2730 CGPoint *positions = alloca (sizeof (CGPoint) * len);
2731 CGFloat total_width = 0;
2732 CGFloat font_size = mac_font_get_size (macfont);
2733 CGAffineTransform atfm;
2734 CGFloat advance_delta = 0;
2735 int y_draw = -s->ybase;
2736 int no_antialias_p =
2737 (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2738 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2739 && font_size <= macfont_antialias_threshold));
2741 for (i = 0; i < len; i++)
2745 glyphs[i] = *(s->char2b + s->cmp_from + i);
2746 width = (s->padding_p ? 1
2747 : macfont_glyph_extents (s->font, glyphs[i],
2748 NULL, &advance_delta,
2750 positions[i].x = total_width + advance_delta;
2752 total_width += width;
2755 CGContextScaleCTM (context, 1, -1);
2756 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, s);
2757 if (macfont_info->synthetic_italic_p)
2758 atfm = synthetic_italic_atfm;
2760 atfm = CGAffineTransformIdentity;
2761 if (macfont_info->synthetic_bold_p)
2763 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2764 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2765 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, s);
2768 CGContextSetShouldAntialias (context, false);
2770 CGContextSetTextMatrix (context, atfm);
2771 CGContextSetTextPosition (context, x, y_draw);
2773 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2774 if (macfont_info->color_bitmap_p
2775 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2776 && CTFontDrawGlyphs != NULL
2782 CTFontDrawGlyphs (macfont, glyphs, positions, len, context);
2786 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2788 CGContextSetFont (context, macfont_info->cgfont);
2789 CGContextSetFontSize (context, font_size);
2790 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2794 CGContextRestoreGState (context);
2802 macfont_shape (Lisp_Object lgstring)
2805 struct macfont_info *macfont_info;
2807 ptrdiff_t glyph_len, len, i, j;
2810 CFIndex *nonbmp_indices;
2813 struct mac_glyph_layout *glyph_layouts;
2815 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2816 macfont_info = (struct macfont_info *) font;
2817 macfont = macfont_info->macfont;
2819 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2821 for (i = 0; i < glyph_len; i++)
2823 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2827 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2833 if (INT_MAX / 2 < len)
2834 memory_full (SIZE_MAX);
2836 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2837 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2838 for (i = j = 0; i < len; i++)
2840 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2842 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2844 nonbmp_indices[j] = i + j;
2848 nonbmp_indices[j] = len + j; /* sentinel */
2852 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2856 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2857 if (macfont_info->screen_font)
2858 used = mac_screen_font_shape (macfont_info->screen_font, string,
2859 glyph_layouts, glyph_len);
2861 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2872 for (i = 0; i < used; i++)
2874 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2875 struct mac_glyph_layout *gl = glyph_layouts + i;
2877 struct font_metrics metrics;
2878 int xoff, yoff, wadjust;
2882 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2883 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2886 from = gl->comp_range.location;
2887 /* Convert UTF-16 index to UTF-32. */
2889 while (nonbmp_indices[j] < from)
2892 LGLYPH_SET_FROM (lglyph, from);
2894 to = gl->comp_range.location + gl->comp_range.length;
2895 /* Convert UTF-16 index to UTF-32. */
2896 while (nonbmp_indices[j] < to)
2899 LGLYPH_SET_TO (lglyph, to - 1);
2901 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2902 the composition is trivial. */
2906 if (unichars[gl->string_index] >= 0xD800
2907 && unichars[gl->string_index] < 0xDC00)
2908 c = (((unichars[gl->string_index] - 0xD800) << 10)
2909 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2911 c = unichars[gl->string_index];
2912 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2914 LGLYPH_SET_CHAR (lglyph, c);
2918 unsigned long cc = gl->glyph_id;
2919 LGLYPH_SET_CODE (lglyph, cc);
2922 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2923 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2924 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2925 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2926 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2927 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2929 xoff = lround (gl->advance_delta);
2930 yoff = lround (- gl->baseline_delta);
2931 wadjust = lround (gl->advance);
2932 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2936 vec = Fmake_vector (make_number (3), Qnil);
2937 ASET (vec, 0, make_number (xoff));
2938 ASET (vec, 1, make_number (yoff));
2939 ASET (vec, 2, make_number (wadjust));
2940 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2946 return make_number (used);
2949 /* Structures for the UVS subtable (format 14) in the cmap table. */
2950 typedef UInt8 UINT24[3];
2952 #pragma pack(push, 1)
2953 struct variation_selector_record
2955 UINT24 var_selector;
2956 UInt32 default_uvs_offset, non_default_uvs_offset;
2961 UInt32 length, num_var_selector_records;
2962 struct variation_selector_record variation_selector_records[1];
2964 #define SIZEOF_UVS_TABLE_HEADER \
2965 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2967 struct unicode_value_range
2969 UINT24 start_unicode_value;
2970 UInt8 additional_count;
2972 struct default_uvs_table {
2973 UInt32 num_unicode_value_ranges;
2974 struct unicode_value_range unicode_value_ranges[1];
2976 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2977 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2981 UINT24 unicode_value;
2984 struct non_default_uvs_table
2986 UInt32 num_uvs_mappings;
2987 struct uvs_mapping uvs_mappings[1];
2989 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
2990 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2993 /* Read big endian values. The argument LVAL must be an lvalue. */
2994 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
2995 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
2996 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
2997 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
2998 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
2999 /* Succeeding one byte should also be accessible. */
3000 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
3001 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
3003 /* Return UVS subtable for the specified FONT. If the subtable is not
3004 found or ill-formatted, then return NULL. */
3007 mac_font_copy_uvs_table (FontRef font)
3009 CFDataRef cmap_table, uvs_table = NULL;
3011 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3014 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3015 struct uvs_table *uvs;
3016 struct variation_selector_record *records;
3017 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3020 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3024 cmap_len = CFDataGetLength (cmap_table);
3025 if (sizeof_sfntCMapHeader > cmap_len)
3028 ntables = BUINT16_VALUE (cmap->numTables);
3029 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3030 / sizeof_sfntCMapEncoding))
3033 for (i = 0; i < ntables; i++)
3034 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3035 == kFontUnicodePlatform)
3036 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3037 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3039 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3043 || uvs_offset > cmap_len
3044 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3047 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3048 uvs_len = BUINT32_VALUE (uvs->length);
3049 if (uvs_len > cmap_len - uvs_offset
3050 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3053 if (BUINT16_VALUE (uvs->format) != 14)
3056 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3057 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3058 / sizeof (struct variation_selector_record)))
3061 records = uvs->variation_selector_records;
3062 for (i = 0; i < nrecords; i++)
3064 UInt32 default_uvs_offset, non_default_uvs_offset;
3066 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3067 if (default_uvs_offset)
3069 struct default_uvs_table *default_uvs;
3072 if (default_uvs_offset > uvs_len
3073 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3074 > uvs_len - default_uvs_offset))
3077 default_uvs = ((struct default_uvs_table *)
3078 ((UInt8 *) uvs + default_uvs_offset));
3079 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3080 if (nranges > ((uvs_len - default_uvs_offset
3081 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3082 / sizeof (struct unicode_value_range)))
3084 /* Now 2 * nranges can't overflow, so we can safely use
3085 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3086 mac_font_get_glyphs_for_variants. */
3089 non_default_uvs_offset =
3090 BUINT32_VALUE (records[i].non_default_uvs_offset);
3091 if (non_default_uvs_offset)
3093 struct non_default_uvs_table *non_default_uvs;
3096 if (non_default_uvs_offset > uvs_len
3097 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3098 > uvs_len - non_default_uvs_offset))
3101 non_default_uvs = ((struct non_default_uvs_table *)
3102 ((UInt8 *) uvs + non_default_uvs_offset));
3103 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3104 if (nmappings > ((uvs_len - non_default_uvs_offset
3105 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3106 / sizeof (struct uvs_mapping)))
3108 /* Now 2 * nmappings can't overflow, so we can safely
3109 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3110 in mac_font_get_glyphs_for_variants. */
3114 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3117 CFRelease (cmap_table);
3123 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3124 sequence consisting of the given base character C and each
3125 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3126 result (explained below) into the corresponding GLYPHS[i]. If the
3127 entry is found in the Default UVS Table, then the result is 0. If
3128 the entry is found in the Non-Default UVS Table, then the result is
3129 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3130 elements in SELECTORS must be sorted in strictly increasing
3134 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3135 const UTF32Char selectors[], CGGlyph glyphs[],
3138 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3139 struct variation_selector_record *records = uvs->variation_selector_records;
3141 UInt32 ir, nrecords;
3142 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3143 dispatch_queue_t queue =
3144 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3145 dispatch_group_t group = dispatch_group_create ();
3148 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3151 while (i < count && ir < nrecords)
3153 UInt32 default_uvs_offset, non_default_uvs_offset;
3155 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3157 glyphs[i++] = kCGFontIndexInvalid;
3160 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3166 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3167 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3168 non_default_uvs_offset =
3169 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3170 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3171 dispatch_group_async (group, queue, ^{
3173 glyphs[i] = kCGFontIndexInvalid;
3175 if (default_uvs_offset)
3177 struct default_uvs_table *default_uvs =
3178 (struct default_uvs_table *) ((UInt8 *) uvs
3179 + default_uvs_offset);
3180 struct unicode_value_range *ranges =
3181 default_uvs->unicode_value_ranges;
3185 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3188 UInt32 mid = (lo + hi) / 2;
3190 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3196 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3197 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3201 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3203 struct non_default_uvs_table *non_default_uvs =
3204 (struct non_default_uvs_table *) ((UInt8 *) uvs
3205 + non_default_uvs_offset);
3206 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3210 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3213 UInt32 mid = (lo + hi) / 2;
3215 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3221 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3222 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3224 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3231 glyphs[i++] = kCGFontIndexInvalid;
3232 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3233 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3234 dispatch_release (group);
3239 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3241 CFDataRef uvs_table;
3242 CharacterCollection uvs_collection;
3246 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3250 UTF32Char selectors[256];
3251 CGGlyph glyphs[256];
3253 for (i = 0; i < 16; i++)
3254 selectors[i] = 0xFE00 + i;
3255 for (; i < 256; i++)
3256 selectors[i] = 0xE0100 + (i - 16);
3257 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3258 for (i = 0; i < 256; i++)
3260 CGGlyph glyph = glyphs[i];
3262 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3263 && glyph != kCGFontIndexInvalid)
3264 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3265 if (glyph == kCGFontIndexInvalid)
3269 variations[i] = (glyph ? glyph
3270 : macfont_get_glyph_for_character (font, c));
3280 static const char *const macfont_booleans[] = {
3286 static const char *const macfont_non_booleans[] = {
3294 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3296 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3300 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3301 CFArrayRef languages)
3303 Boolean result = true;
3304 CFArrayRef desc_languages =
3305 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3307 if (desc_languages == NULL)
3311 CFIndex desc_languages_count, i, languages_count;
3313 desc_languages_count = CFArrayGetCount (desc_languages);
3314 languages_count = CFArrayGetCount (languages);
3315 for (i = 0; i < languages_count; i++)
3316 if (!CFArrayContainsValue (desc_languages,
3317 CFRangeMake (0, desc_languages_count),
3318 CFArrayGetValueAtIndex (languages, i)))
3323 CFRelease (desc_languages);
3330 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3332 CFStringRef result = NULL;
3333 CFStringRef charset_string =
3334 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3336 if (charset_string && CFStringGetLength (charset_string) > 0)
3338 CFAttributedStringRef attr_string = NULL;
3339 CTLineRef ctline = NULL;
3340 CFDictionaryRef attrs =
3341 CFDictionaryCreate (NULL, NULL, NULL, 0,
3342 &kCFTypeDictionaryKeyCallBacks,
3343 &kCFTypeDictionaryValueCallBacks);
3347 attr_string = CFAttributedStringCreate (NULL, charset_string, attrs);
3352 ctline = CTLineCreateWithAttributedString (attr_string);
3353 CFRelease (attr_string);
3357 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3358 CFIndex i, nruns = CFArrayGetCount (runs);
3361 for (i = 0; i < nruns; i++)
3363 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3364 CFDictionaryRef attributes = CTRunGetAttributes (run);
3365 CTFontRef font_in_run;
3367 if (attributes == NULL)
3370 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3371 if (font_in_run == NULL)
3375 else if (!mac_ctfont_equal_in_postscript_name (font, font_in_run))
3378 if (nruns > 0 && i == nruns)
3379 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3387 static inline double
3388 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3390 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3394 static inline CGRect
3395 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3397 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3402 mac_ctfont_create_available_families (void)
3404 CFMutableArrayRef families = NULL;
3406 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3407 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3408 if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3411 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3415 CFIndex i, count = CFArrayGetCount (orig_families);
3417 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3419 for (i = 0; i < count; i++)
3421 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3423 if (!CFStringHasPrefix (family, CFSTR ("."))
3424 && (CTFontManagerCompareFontFamilyNames (family,
3425 CFSTR ("LastResort"),
3427 != kCFCompareEqualTo))
3428 CFArrayAppendValue (families, family);
3430 CFRelease (orig_families);
3433 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3434 else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3436 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3437 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3439 CTFontCollectionRef collection;
3440 CFArrayRef descs = NULL;
3442 collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3445 descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3446 CFRelease (collection);
3450 CFIndex i, count = CFArrayGetCount (descs);
3452 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3454 for (i = 0; i < count; i++)
3456 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3458 mac_font_descriptor_copy_attribute (desc,
3459 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3463 CFIndex p, limit = CFArrayGetCount (families);
3465 p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3466 (const void *) name,
3467 mac_font_family_compare, NULL);
3469 CFArrayAppendValue (families, name);
3470 else if (mac_font_family_compare
3471 (CFArrayGetValueAtIndex (families, p),
3472 name, NULL) != kCFCompareEqualTo)
3473 CFArrayInsertValueAtIndex (families, p, name);
3486 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3489 CFStringRef name1, name2;
3495 name1 = CTFontCopyPostScriptName (font1);
3498 name2 = CTFontCopyPostScriptName (font2);
3501 result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo);
3511 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3514 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3515 CFTypeRef values[] = {NULL, NULL};
3516 CFDictionaryRef attributes = NULL;
3517 CFAttributedStringRef attr_string = NULL;
3518 CTLineRef ctline = NULL;
3519 float float_zero = 0.0f;
3521 values[0] = macfont;
3522 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3525 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3526 (const void **) values,
3527 sizeof (keys) / sizeof (keys[0]),
3528 &kCFTypeDictionaryKeyCallBacks,
3529 &kCFTypeDictionaryValueCallBacks);
3530 CFRelease (values[1]);
3534 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3535 CFRelease (attributes);
3539 ctline = CTLineCreateWithAttributedString (attr_string);
3540 CFRelease (attr_string);
3544 /* Abandon if ctline contains some fonts other than the
3546 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3547 CFIndex i, nruns = CFArrayGetCount (runs);
3549 for (i = 0; i < nruns; i++)
3551 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3552 CFDictionaryRef attributes = CTRunGetAttributes (run);
3553 CTFontRef font_in_run;
3555 if (attributes == NULL)
3558 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3559 if (font_in_run == NULL)
3561 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3575 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3576 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3578 CFIndex used, result = 0;
3579 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3584 used = CTLineGetGlyphCount (ctline);
3585 if (used <= glyph_len)
3587 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3588 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3589 CGFloat total_advance = 0;
3590 CFIndex total_glyph_count = 0;
3592 for (k = 0; k < ctrun_count; k++)
3594 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3595 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3596 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3597 CFRange string_range, comp_range, range;
3598 CFIndex *permutation;
3600 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3601 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3605 #define RIGHT_TO_LEFT_P permutation
3607 /* Now the `comp_range' member of struct mac_glyph_layout is
3608 temporarily used as a work area such that:
3609 glbuf[i].comp_range.location =
3610 min {compRange[i + 1].location, ...,
3611 compRange[glyph_count - 1].location,
3612 maxRange (stringRangeForCTRun)}
3613 glbuf[i].comp_range.length = maxRange (compRange[i])
3614 where compRange[i] is the range of composed characters
3615 containing i-th glyph. */
3616 string_range = CTRunGetStringRange (ctrun);
3617 min_location = string_range.location + string_range.length;
3618 for (i = 0; i < glyph_count; i++)
3620 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3621 CFIndex glyph_index;
3624 if (!RIGHT_TO_LEFT_P)
3625 glyph_index = glyph_count - i - 1;
3628 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3631 CFStringGetRangeOfComposedCharactersAtIndex (string,
3633 gl->comp_range.location = min_location;
3634 gl->comp_range.length = rng.location + rng.length;
3635 if (rng.location < min_location)
3636 min_location = rng.location;
3639 /* Fill the `comp_range' member of struct mac_glyph_layout,
3640 and setup a permutation for right-to-left text. */
3641 comp_range = CFRangeMake (string_range.location, 0);
3642 range = CFRangeMake (0, 0);
3645 struct mac_glyph_layout *gl =
3646 glbuf + range.location + range.length;
3648 if (gl->comp_range.length
3649 > comp_range.location + comp_range.length)
3650 comp_range.length = gl->comp_range.length - comp_range.location;
3651 min_location = gl->comp_range.location;
3654 if (min_location >= comp_range.location + comp_range.length)
3656 comp_range.length = min_location - comp_range.location;
3657 for (i = 0; i < range.length; i++)
3659 glbuf[range.location + i].comp_range = comp_range;
3660 if (RIGHT_TO_LEFT_P)
3661 permutation[range.location + i] =
3662 range.location + range.length - i - 1;
3665 comp_range = CFRangeMake (min_location, 0);
3666 range.location += range.length;
3668 if (range.location == glyph_count)
3673 /* Then fill the remaining members. */
3674 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3677 struct mac_glyph_layout *gl;
3680 if (!RIGHT_TO_LEFT_P)
3681 gl = glbuf + range.location;
3686 src = glyph_count - 1 - range.location;
3687 dest = permutation[src];
3691 CFIndex tmp = gl->string_index;
3693 gl->string_index = glbuf[src].string_index;
3694 glbuf[src].string_index = tmp;
3697 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3699 CTRunGetPositions (ctrun, range, &position);
3700 gl->advance_delta = position.x - total_advance;
3701 gl->baseline_delta = position.y;
3702 gl->advance = (gl->advance_delta
3703 + CTRunGetTypographicBounds (ctrun, range,
3705 total_advance += gl->advance;
3708 if (RIGHT_TO_LEFT_P)
3709 xfree (permutation);
3711 #undef RIGHT_TO_LEFT_P
3713 total_glyph_count += glyph_count;
3723 /* The function below seems to cause a memory leak for the CFString
3724 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3725 10.6.3. For now, we use the NSGlyphInfo version instead. */
3726 #if USE_CT_GLYPH_INFO
3728 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3731 CGGlyph result = kCGFontIndexInvalid;
3732 UniChar characters[] = {0xfffd};
3734 CFAttributedStringRef attr_string = NULL;
3735 CTLineRef ctline = NULL;
3737 string = CFStringCreateWithCharacters (NULL, characters,
3739 / sizeof (characters[0]));
3742 CTGlyphInfoRef glyph_info =
3743 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3744 CFDictionaryRef attributes = NULL;
3748 CFStringRef keys[] = {kCTFontAttributeName,
3749 kCTGlyphInfoAttributeName};
3750 CFTypeRef values[] = {font, glyph_info};
3752 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3753 (const void **) values,
3754 sizeof (keys) / sizeof (keys[0]),
3755 &kCFTypeDictionaryKeyCallBacks,
3756 &kCFTypeDictionaryValueCallBacks);
3757 CFRelease (glyph_info);
3761 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3762 CFRelease (attributes);
3768 ctline = CTLineCreateWithAttributedString (attr_string);
3769 CFRelease (attr_string);
3773 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3775 if (CFArrayGetCount (runs) > 0)
3777 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3778 CFDictionaryRef attributes = CTRunGetAttributes (run);
3782 CTFontRef font_in_run =
3783 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3786 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3788 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3789 if (result >= CTFontGetGlyphCount (font))
3790 result = kCGFontIndexInvalid;
3801 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3803 mac_font_family_group (CFStringRef family)
3805 if (CFStringHasPrefix (family, CFSTR ("#")))
3811 range = CFStringFind (family, CFSTR ("Apple"),
3812 kCFCompareCaseInsensitive | kCFCompareAnchored);
3813 if (range.location != kCFNotFound)
3821 mac_font_family_compare (const void *val1, const void *val2, void *context)
3823 CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3826 group1 = mac_font_family_group (family1);
3827 group2 = mac_font_family_group (family2);
3828 if (group1 < group2)
3829 return kCFCompareLessThan;
3830 if (group1 > group2)
3831 return kCFCompareGreaterThan;
3832 return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3834 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3837 macfont_get_nsctfont (struct font *font)
3839 struct macfont_info *macfont_info = (struct macfont_info *) font;
3840 FontRef macfont = macfont_info->macfont;
3842 return (void *) macfont;
3846 mac_register_font_driver (struct frame *f)
3848 register_font_driver (&macfont_driver, f);
3851 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
3855 syms_of_macfont (void)
3857 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
3858 static struct font_driver mac_font_driver;
3860 DEFSYM (Qmac_ct, "mac-ct");
3861 macfont_driver.type = Qmac_ct;
3862 register_font_driver (&macfont_driver, NULL);
3864 DEFSYM (QCdestination, ":destination");
3865 DEFSYM (QCminspace, ":minspace");