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 WYSIWIG, 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) \
627 CGContextSetFillColorWithColor (context, \
628 get_cgcolor (NS_FACE_FOREGROUND (s->face), \
631 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, s) \
632 CGContextSetFillColorWithColor (context, \
633 get_cgcolor (NS_FACE_BACKGROUND (s->face), \
636 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, s) \
637 CGContextSetStrokeColorWithColor (context, \
638 get_cgcolor (NS_FACE_FOREGROUND (s->face),\
642 /* Mac font driver. */
648 /* characters to distinguish the charset from the others */
650 /* additional constraint by language */
653 CFCharacterSetRef cf_charset;
654 CFStringRef cf_charset_string;
655 } cf_charset_table[] =
656 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
657 { "iso8859-2", { 0x00A0, 0x010E }},
658 { "iso8859-3", { 0x00A0, 0x0108 }},
659 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
660 { "iso8859-5", { 0x00A0, 0x0401 }},
661 { "iso8859-6", { 0x00A0, 0x060C }},
662 { "iso8859-7", { 0x00A0, 0x0384 }},
663 { "iso8859-8", { 0x00A0, 0x05D0 }},
664 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
665 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
666 { "iso8859-11", { 0x00A0, 0x0E01 }},
667 { "iso8859-13", { 0x00A0, 0x201C }},
668 { "iso8859-14", { 0x00A0, 0x0174 }},
669 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
670 { "iso8859-16", { 0x00A0, 0x0218}},
671 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
672 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0xF7E5 }, CFSTR ("zh-Hant") },
673 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
674 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
675 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
676 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
677 { "cns11643.1992-3", { 0x201A9 }},
678 { "cns11643.1992-4", { 0x20057 }},
679 { "cns11643.1992-5", { 0x20000 }},
680 { "cns11643.1992-6", { 0x20003 }},
681 { "cns11643.1992-7", { 0x20055 }},
682 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
683 { "jisx0212.1990-0", { 0x4E44 }},
684 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
685 { "jisx0213.2000-2", { 0xFA49 }},
686 { "jisx0213.2004-1", { 0x20B9F }},
687 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
688 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
689 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
690 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
691 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
692 { "unicode-sip", { 0x20000 }},
696 static CGFloat macfont_antialias_threshold;
699 macfont_update_antialias_threshold (void)
705 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
706 kCFPreferencesCurrentApplication,
709 macfont_antialias_threshold = threshold;
712 static inline Lisp_Object
713 macfont_intern_prop_cfstring (CFStringRef cfstring)
715 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
717 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
720 static inline CFIndex
721 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
732 unichars[0] = (c >> 10) + 0xD800;
733 unichars[1] = (c & 0x3FF) + 0xDC00;
740 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
741 FontSymbolicTraits *sym_traits)
745 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
746 OS 10.6 when the value is greater than or equal to 1 << 31. */
747 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
749 *sym_traits = (FontSymbolicTraits) sint64_value;
758 macfont_store_descriptor_attributes (FontDescriptorRef desc,
759 Lisp_Object spec_or_entity)
762 CFDictionaryRef dict;
766 str = mac_font_descriptor_copy_attribute (desc,
767 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
770 ASET (spec_or_entity, FONT_FAMILY_INDEX,
771 macfont_intern_prop_cfstring (str));
774 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
778 enum font_property_index index;
782 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
783 {{-0.4, 50}, /* light */
784 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
785 {0, 100}, /* normal */
786 {0.24, 140}, /* (semi-bold + normal) / 2 */
787 {0.4, 200}, /* bold */
788 {CGFLOAT_MAX, CGFLOAT_MAX}}},
789 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
790 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
791 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
792 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
795 for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
797 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
798 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
800 CGPoint *point = numeric_traits[i].points;
802 while (point->x < floatval)
804 if (point == numeric_traits[i].points)
806 else if (point->x == CGFLOAT_MAX)
808 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
809 * ((point->y - (point - 1)->y)
810 / (point->x - (point - 1)->x)));
811 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
812 make_number (lround (floatval)));
816 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
819 FontSymbolicTraits sym_traits;
822 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
823 spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
824 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
825 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
830 num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
831 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
832 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
834 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
840 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
841 FontSymbolicTraits synth_sym_traits)
844 CFDictionaryRef dict;
845 FontSymbolicTraits sym_traits = 0;
848 entity = font_make_entity ();
850 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
851 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
853 macfont_store_descriptor_attributes (desc, entity);
855 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
858 CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
861 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
864 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
865 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
866 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
867 name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
868 font_put_extra (entity, QCfont_entity,
869 make_save_ptr_int ((void *) name, sym_traits));
870 if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
871 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
872 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
873 if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
874 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
875 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
876 if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
877 ASET (entity, FONT_SPACING_INDEX,
878 make_number (FONT_SPACING_SYNTHETIC_MONO));
884 macfont_create_family_with_symbol (Lisp_Object symbol)
886 static CFArrayRef families = NULL;
887 CFStringRef result = NULL, family_name;
888 int using_cache_p = 1;
889 CFComparatorFunction family_name_comparator;
891 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
892 if (family_name == NULL)
895 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
896 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
897 if (CTFontManagerCompareFontFamilyNames != NULL)
900 family_name_comparator = CTFontManagerCompareFontFamilyNames;
902 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
903 else /* CTFontManagerCompareFontFamilyNames == NULL */
905 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
906 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
908 family_name_comparator = mac_font_family_compare;
912 if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
913 == kCFCompareEqualTo)
914 result = CFSTR ("LastResort");
920 if (families == NULL)
922 families = mac_font_create_available_families ();
924 if (families == NULL)
928 count = CFArrayGetCount (families);
929 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
930 (const void *) family_name,
931 family_name_comparator, NULL);
934 CFStringRef name = CFArrayGetValueAtIndex (families, i);
936 if ((*family_name_comparator) (name, family_name, NULL)
937 == kCFCompareEqualTo)
938 result = CFRetain (name);
941 if (result || !using_cache_p)
945 CFRelease (families);
950 CFRelease (family_name);
955 #define WIDTH_FRAC_BITS (4)
956 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
958 struct macfont_metrics
960 unsigned char lbearing_low, rbearing_low;
961 signed lbearing_high : 4, rbearing_high : 4;
962 unsigned char ascent_low, descent_low;
963 signed ascent_high : 4, descent_high : 4;
965 /* These two members are used for fixed-point representation of
966 glyph width. The `width_int' member is an integer that is
967 closest to the width. The `width_frac' member is the fractional
968 adjustment representing a value in [-.5, .5], multiplied by
969 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
970 the advance delta for centering instead of the glyph width. */
971 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
974 #define METRICS_VALUE(metrics, member) \
975 (((metrics)->member##_high << 8) | (metrics)->member##_low)
976 #define METRICS_SET_VALUE(metrics, member, value) \
977 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
978 (metrics)->member##_high = tmp >> 8;} while (0)
982 METRICS_INVALID = -1, /* metrics entry is invalid */
983 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
986 #define METRICS_STATUS(metrics) \
987 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
988 #define METRICS_SET_STATUS(metrics, status) \
989 do {METRICS_SET_VALUE (metrics, ascent, 0); \
990 METRICS_SET_VALUE (metrics, descent, status);} while (0)
992 #define METRICS_NCOLS_PER_ROW (128)
993 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
994 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
997 macfont_glyph_extents (struct font *font, CGGlyph glyph,
998 struct font_metrics *metrics, CGFloat *advance_delta,
999 int force_integral_p)
1001 struct macfont_info *macfont_info = (struct macfont_info *) font;
1002 FontRef macfont = macfont_info->macfont;
1004 struct macfont_metrics *cache;
1007 row = glyph / METRICS_NCOLS_PER_ROW;
1008 col = glyph % METRICS_NCOLS_PER_ROW;
1009 if (row >= macfont_info->metrics_nrows)
1011 macfont_info->metrics =
1012 xrealloc (macfont_info->metrics,
1013 sizeof (struct macfont_metrics *) * (row + 1));
1014 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1015 (sizeof (struct macfont_metrics *)
1016 * (row + 1 - macfont_info->metrics_nrows)));
1017 macfont_info->metrics_nrows = row + 1;
1019 if (macfont_info->metrics[row] == NULL)
1021 struct macfont_metrics *new;
1024 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1025 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1026 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1027 macfont_info->metrics[row] = new;
1029 cache = macfont_info->metrics[row] + col;
1031 if (METRICS_STATUS (cache) == METRICS_INVALID)
1035 if (macfont_info->screen_font)
1036 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1038 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1040 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1041 advance delta value. */
1042 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1043 fwidth = (font->pixel_size - fwidth) / 2;
1044 cache->width_int = lround (fwidth);
1045 cache->width_frac = lround ((fwidth - cache->width_int)
1046 * WIDTH_FRAC_SCALE);
1047 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1049 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1050 width = font->pixel_size;
1052 width = cache->width_int;
1056 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1058 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1060 if (macfont_info->synthetic_italic_p)
1062 /* We assume the members a, b, c, and d in
1063 synthetic_italic_atfm are non-negative. */
1065 CGPointApplyAffineTransform (bounds.origin,
1066 synthetic_italic_atfm);
1068 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1070 if (macfont_info->synthetic_bold_p)
1073 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1075 bounds = CGRectInset (bounds, d, d);
1077 switch (macfont_info->spacing)
1079 case MACFONT_SPACING_PROPORTIONAL:
1080 bounds.origin.x += - (cache->width_frac
1081 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1083 case MACFONT_SPACING_MONO:
1085 case MACFONT_SPACING_SYNTHETIC_MONO:
1086 bounds.origin.x += (cache->width_int
1087 + (cache->width_frac
1088 / (CGFloat) WIDTH_FRAC_SCALE));
1091 if (bounds.size.width > 0)
1093 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1094 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1095 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1097 bounds = CGRectIntegral (bounds);
1098 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1099 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1100 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1101 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1103 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1104 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1105 metrics->width = width;
1106 metrics->ascent = METRICS_VALUE (cache, ascent);
1107 metrics->descent = METRICS_VALUE (cache, descent);
1112 switch (macfont_info->spacing)
1114 case MACFONT_SPACING_PROPORTIONAL:
1115 *advance_delta = (force_integral_p ? 0
1116 : - (cache->width_frac
1117 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1119 case MACFONT_SPACING_MONO:
1122 case MACFONT_SPACING_SYNTHETIC_MONO:
1123 *advance_delta = (force_integral_p ? cache->width_int
1125 + (cache->width_frac
1126 / (CGFloat) WIDTH_FRAC_SCALE)));
1134 static CFMutableDictionaryRef macfont_cache_dictionary;
1136 /* Threshold used in row_nkeys_or_perm. This must be less than or
1137 equal to the number of rows that are invalid as BMP (i.e., from
1138 U+D800 to U+DFFF). */
1139 #define ROW_PERM_OFFSET (8)
1141 /* The number of glyphs that can be stored in a value for a single
1142 entry of CFDictionary. */
1143 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1145 struct macfont_cache
1147 int reference_count;
1148 CFCharacterSetRef cf_charset;
1150 /* The cached glyph for a BMP character c is stored in
1151 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1152 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1153 unsigned char row_nkeys_or_perm[256];
1156 /* Number of rows for which the BMP cache is allocated so far.
1157 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1160 /* The cached glyph for a character c is stored as the (c %
1161 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1162 NGLYPHS_IN_VALUE). However, the glyph for a BMP characrer c is
1163 not stored here if row_nkeys_or_perm[c / 256] >=
1165 CFMutableDictionaryRef dictionary;
1169 /* UVS (Unicode Variation Sequence) subtable data, which is of
1170 type CFDataRef if available. NULL means it is not initialized
1171 yet. kCFNull means the subtable is not found and there is no
1172 suitable fallback table for this font. */
1175 /* Character collection specifying the destination of the mapping
1176 provided by `table' above. If `table' is obtained from the UVS
1177 subtable in the font cmap table, then the value of this member
1178 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1179 CharacterCollection collection;
1183 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1184 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1185 static void macfont_release_cache (struct macfont_cache *);
1186 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1187 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1188 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1189 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1190 CharacterCollection, CGFontIndex);
1191 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1193 static struct macfont_cache *
1194 macfont_lookup_cache (CFStringRef key)
1196 struct macfont_cache *cache;
1198 if (macfont_cache_dictionary == NULL)
1200 macfont_cache_dictionary =
1201 CFDictionaryCreateMutable (NULL, 0,
1202 &kCFTypeDictionaryKeyCallBacks, NULL);
1206 cache = ((struct macfont_cache *)
1207 CFDictionaryGetValue (macfont_cache_dictionary, key));
1211 FontRef macfont = mac_font_create_with_name (key, 0);
1215 cache = xzalloc (sizeof (struct macfont_cache));
1216 /* Treat the LastResort font as if it contained glyphs for
1217 all characters. This may look too rough, but neither
1218 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1219 for this font is correct for non-BMP characters on Mac OS
1221 if (CFStringCompare (key, CFSTR ("LastResort"), 0)
1222 == kCFCompareEqualTo)
1224 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1227 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1229 if (cache->cf_charset == NULL)
1230 cache->cf_charset = mac_font_copy_character_set (macfont);
1231 CFDictionaryAddValue (macfont_cache_dictionary, key,
1232 (const void *) cache);
1233 CFRelease (macfont);
1240 static struct macfont_cache *
1241 macfont_retain_cache (struct macfont_cache *cache)
1243 cache->reference_count++;
1249 macfont_release_cache (struct macfont_cache *cache)
1251 if (--cache->reference_count == 0)
1255 for (i = 0; i < cache->glyph.nrows; i++)
1256 xfree (cache->glyph.matrix[i]);
1257 xfree (cache->glyph.matrix);
1258 if (cache->glyph.dictionary)
1259 CFRelease (cache->glyph.dictionary);
1260 memset (&cache->glyph, 0, sizeof (cache->glyph));
1261 if (cache->uvs.table)
1262 CFRelease (cache->uvs.table);
1263 memset (&cache->uvs, 0, sizeof (cache->uvs));
1267 static CFCharacterSetRef
1268 macfont_get_cf_charset (struct font *font)
1270 struct macfont_info *macfont_info = (struct macfont_info *) font;
1272 return macfont_info->cache->cf_charset;
1275 static CFCharacterSetRef
1276 macfont_get_cf_charset_for_name (CFStringRef name)
1278 struct macfont_cache *cache = macfont_lookup_cache (name);
1280 return cache->cf_charset;
1284 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1286 struct macfont_info *macfont_info = (struct macfont_info *) font;
1287 FontRef macfont = macfont_info->macfont;
1288 struct macfont_cache *cache = macfont_info->cache;
1290 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1293 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1295 if (nkeys_or_perm < ROW_PERM_OFFSET)
1297 UniChar unichars[256], ch;
1301 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1302 dispatch_queue_t queue;
1303 dispatch_group_t group = NULL;
1310 CFMutableDictionaryRef dictionary;
1311 uintptr_t key, value;
1315 if (cache->glyph.dictionary == NULL)
1316 cache->glyph.dictionary =
1317 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1318 dictionary = cache->glyph.dictionary;
1319 key = c / NGLYPHS_IN_VALUE;
1320 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1321 value = ((uintptr_t)
1322 CFDictionaryGetValue (dictionary, (const void *) key));
1323 glyph = (value >> nshifts);
1327 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1330 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1333 glyph = kCGFontIndexInvalid;
1336 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1337 value |= ((uintptr_t) glyph << nshifts);
1338 CFDictionarySetValue (dictionary, (const void *) key,
1339 (const void *) value);
1344 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1346 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1347 group = dispatch_group_create ();
1348 dispatch_group_async (group, queue, ^{
1352 nkeys = nkeys_or_perm;
1353 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1354 if (CFDictionaryContainsKey (dictionary,
1355 (const void *) key))
1357 CFDictionaryRemoveValue (dictionary,
1358 (const void *) key);
1362 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1368 for (i = 0; i < 256; i++)
1371 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1372 unichars[len++] = ch;
1375 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1378 mac_font_get_glyphs_for_characters (macfont, unichars,
1382 int next = unichars[len - 1] % 256;
1385 glyphs[i] = kCGFontIndexInvalid;
1388 glyphs[i] = glyphs[len];
1395 glyphs[i] = kCGFontIndexInvalid;
1397 nrows = cache->glyph.nrows;
1398 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1399 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1401 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1402 sizeof (CGGlyph *) * nrows);
1403 cache->glyph.matrix[nrows - 1] = glyphs;
1404 cache->glyph.nrows = nrows;
1406 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
1409 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1410 dispatch_release (group);
1415 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1419 uintptr_t key, value;
1423 if (cache->glyph.dictionary == NULL)
1424 cache->glyph.dictionary =
1425 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1426 key = c / NGLYPHS_IN_VALUE;
1427 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1428 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1429 (const void *) key);
1430 glyph = (value >> nshifts);
1433 UniChar unichars[2];
1435 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1437 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1441 glyph = kCGFontIndexInvalid;
1443 value |= ((uintptr_t) glyph << nshifts);
1444 CFDictionarySetValue (cache->glyph.dictionary,
1445 (const void *) key, (const void *) value);
1453 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1456 struct macfont_info *macfont_info = (struct macfont_info *) font;
1457 FontRef macfont = macfont_info->macfont;
1460 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1464 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1466 struct macfont_info *macfont_info = (struct macfont_info *) font;
1467 FontRef macfont = macfont_info->macfont;
1468 struct macfont_cache *cache = macfont_info->cache;
1469 CFDataRef result = NULL;
1471 if (cache->uvs.table == NULL)
1473 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1474 CharacterCollection uvs_collection =
1475 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1477 if (uvs_table == NULL
1478 && mac_font_get_glyph_for_cid (macfont,
1479 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1480 6480) != kCGFontIndexInvalid)
1482 /* If the glyph for U+4E55 is accessible via its CID 6480,
1483 then we use the Adobe-Japan1 UVS table, which maps a
1484 variation sequence to a CID, as a fallback. */
1485 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1487 if (mac_uvs_table_adobe_japan1 == NULL)
1488 mac_uvs_table_adobe_japan1 =
1489 CFDataCreateWithBytesNoCopy (NULL,
1490 mac_uvs_table_adobe_japan1_bytes,
1491 sizeof (mac_uvs_table_adobe_japan1_bytes),
1493 if (mac_uvs_table_adobe_japan1)
1495 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1496 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1499 if (uvs_table == NULL)
1500 cache->uvs.table = kCFNull;
1502 cache->uvs.table = uvs_table;
1503 cache->uvs.collection = uvs_collection;
1506 if (cache->uvs.table != kCFNull)
1508 result = cache->uvs.table;
1509 *collection = cache->uvs.collection;
1515 static Lisp_Object macfont_get_cache (struct frame *);
1516 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1517 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1518 static Lisp_Object macfont_list_family (struct frame *);
1519 static void macfont_free_entity (Lisp_Object);
1520 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1521 static void macfont_close (struct frame *, struct font *);
1522 static int macfont_has_char (Lisp_Object, int);
1523 static unsigned macfont_encode_char (struct font *, int);
1524 static int macfont_text_extents (struct font *, unsigned int *, int,
1525 struct font_metrics *);
1526 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1527 static Lisp_Object macfont_shape (Lisp_Object);
1528 static int macfont_variation_glyphs (struct font *, int c,
1529 unsigned variations[256]);
1530 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1532 static struct font_driver macfont_driver =
1534 LISP_INITIALLY_ZERO, /* Qmac_ct */
1535 0, /* case insensitive */
1539 macfont_list_family,
1540 macfont_free_entity,
1543 NULL, /* prepare_face */
1544 NULL, /* done_face */
1546 macfont_encode_char,
1547 macfont_text_extents,
1549 NULL, /* get_bitmap */
1550 NULL, /* free_bitmap */
1551 NULL, /* get_outline */
1552 NULL, /* free_outline */
1553 NULL, /* anchor_point */
1554 NULL, /* otf_capability */
1555 NULL, /* otf_drive */
1556 NULL, /* start_for_frame */
1557 NULL, /* end_for_frame */
1560 macfont_variation_glyphs,
1561 macfont_filter_properties,
1565 macfont_get_cache (struct frame * f)
1567 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1569 return (dpyinfo->name_list_element);
1573 macfont_get_charset (Lisp_Object registry)
1575 char *str = SSDATA (SYMBOL_NAME (registry));
1576 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1580 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1584 else if (str[i] == '*')
1591 regexp = make_unibyte_string (re, j);
1592 for (i = 0; cf_charset_table[i].name; i++)
1593 if (fast_c_string_match_ignore_case
1594 (regexp, cf_charset_table[i].name,
1595 strlen (cf_charset_table[i].name)) >= 0)
1597 if (! cf_charset_table[i].name)
1599 if (! cf_charset_table[i].cf_charset)
1601 int *uniquifier = cf_charset_table[i].uniquifier;
1602 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1605 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1609 for (j = 0; uniquifier[j]; j++)
1611 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1613 CFCharacterSetAddCharactersInRange (charset,
1614 CFRangeMake (uniquifier[j], 1));
1617 string = CFStringCreateWithCharacters (NULL, unichars, count);
1620 CFRelease (charset);
1623 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1625 CFRelease (charset);
1626 /* CFCharacterSetCreateWithCharactersInString does not handle
1627 surrogate pairs properly as of Mac OS X 10.5. */
1628 cf_charset_table[i].cf_charset_string = string;
1636 unsigned int script_tag, langsys_tag;
1638 unsigned int *features[2];
1641 #define OTF_SYM_TAG(SYM, TAG) \
1643 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1644 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1647 #define OTF_TAG_STR(TAG, P) \
1649 (P)[0] = (char) (TAG >> 24); \
1650 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1651 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1652 (P)[3] = (char) (TAG & 0xFF); \
1656 static struct OpenTypeSpec *
1657 macfont_get_open_type_spec (Lisp_Object otf_spec)
1659 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1666 spec->script = XCAR (otf_spec);
1667 if (! NILP (spec->script))
1669 OTF_SYM_TAG (spec->script, spec->script_tag);
1670 val = assq_no_quit (spec->script, Votf_script_alist);
1671 if (CONSP (val) && SYMBOLP (XCDR (val)))
1672 spec->script = XCDR (val);
1674 spec->script = Qnil;
1677 spec->script_tag = 0x44464C54; /* "DFLT" */
1678 otf_spec = XCDR (otf_spec);
1679 spec->langsys_tag = 0;
1680 if (! NILP (otf_spec))
1682 val = XCAR (otf_spec);
1684 OTF_SYM_TAG (val, spec->langsys_tag);
1685 otf_spec = XCDR (otf_spec);
1687 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1688 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1692 val = XCAR (otf_spec);
1695 len = Flength (val);
1697 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1699 : malloc (XINT (len) * sizeof *spec->features[i]));
1700 if (! spec->features[i])
1702 if (i > 0 && spec->features[0])
1703 free (spec->features[0]);
1707 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1709 if (NILP (XCAR (val)))
1715 OTF_SYM_TAG (XCAR (val), tag);
1716 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1719 spec->nfeatures[i] = j;
1724 static CFMutableDictionaryRef
1725 macfont_create_attributes_with_spec (Lisp_Object spec)
1727 Lisp_Object tmp, extra;
1728 CFMutableArrayRef langarray = NULL;
1729 CFCharacterSetRef charset = NULL;
1730 CFStringRef charset_string = NULL;
1731 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1732 Lisp_Object script = Qnil;
1733 Lisp_Object registry;
1734 int cf_charset_idx, i;
1735 struct OpenTypeSpec *otspec = NULL;
1737 enum font_property_index index;
1740 } numeric_traits[] =
1741 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1742 {{-0.4, 50}, /* light */
1743 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1744 {0, 100}, /* normal */
1745 {0.24, 140}, /* (semi-bold + normal) / 2 */
1746 {0.4, 200}, /* bold */
1747 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1748 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1749 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1750 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1751 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1753 registry = AREF (spec, FONT_REGISTRY_INDEX);
1755 || EQ (registry, Qascii_0)
1756 || EQ (registry, Qiso10646_1)
1757 || EQ (registry, Qunicode_bmp))
1758 cf_charset_idx = -1;
1763 cf_charset_idx = macfont_get_charset (registry);
1764 if (cf_charset_idx < 0)
1766 charset = cf_charset_table[cf_charset_idx].cf_charset;
1767 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1768 lang = cf_charset_table[cf_charset_idx].lang;
1771 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1774 CFArrayAppendValue (langarray, lang);
1778 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1779 CONSP (extra); extra = XCDR (extra))
1781 Lisp_Object key, val;
1784 key = XCAR (tmp), val = XCDR (tmp);
1785 if (EQ (key, QClang))
1788 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1793 for (; CONSP (val); val = XCDR (val))
1794 if (SYMBOLP (XCAR (val)))
1797 cfstring_create_with_string_noencode (SYMBOL_NAME
1802 CFArrayAppendValue (langarray, lang);
1806 else if (EQ (key, QCotf))
1808 otspec = macfont_get_open_type_spec (val);
1811 script = otspec->script;
1813 else if (EQ (key, QCscript))
1817 if (! NILP (script) && ! charset)
1819 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1821 if (CONSP (chars) && CONSP (CDR (chars)))
1823 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1824 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1826 if (! string || !cs)
1834 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1835 if (CHARACTERP (XCAR (chars)))
1837 UniChar unichars[2];
1839 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1841 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1843 CFStringAppendCharacters (string, unichars, count);
1844 CFCharacterSetAddCharactersInRange (cs, range);
1847 /* CFCharacterSetCreateWithCharactersInString does not
1848 handle surrogate pairs properly as of Mac OS X 10.5. */
1849 charset_string = string;
1853 attributes = CFDictionaryCreateMutable (NULL, 0,
1854 &kCFTypeDictionaryKeyCallBacks,
1855 &kCFTypeDictionaryValueCallBacks);
1859 tmp = AREF (spec, FONT_FAMILY_INDEX);
1860 if (SYMBOLP (tmp) && ! NILP (tmp))
1862 CFStringRef family = macfont_create_family_with_symbol (tmp);
1866 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1871 traits = CFDictionaryCreateMutable (NULL, 4,
1872 &kCFTypeDictionaryKeyCallBacks,
1873 &kCFTypeDictionaryValueCallBacks);
1877 for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++)
1879 tmp = AREF (spec, numeric_traits[i].index);
1882 CGPoint *point = numeric_traits[i].points;
1883 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1886 while (point->y < floatval)
1888 if (point == numeric_traits[i].points)
1890 else if (point->y == CGFLOAT_MAX)
1892 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1893 * ((point->x - (point - 1)->x)
1894 / (point->y - (point - 1)->y)));
1897 else if (floatval < -1.0)
1899 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1902 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1906 if (CFDictionaryGetCount (traits))
1907 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1910 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1913 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1916 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1923 CFRelease (attributes);
1928 if (langarray) CFRelease (langarray);
1929 if (charset && cf_charset_idx < 0) CFRelease (charset);
1930 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1931 if (traits) CFRelease (traits);
1934 if (otspec->nfeatures[0] > 0)
1935 free (otspec->features[0]);
1936 if (otspec->nfeatures[1] > 0)
1937 free (otspec->features[1]);
1945 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1946 CFCharacterSetRef charset,
1948 CFArrayRef languages)
1950 Boolean result = true;
1952 if (charset || VECTORP (chars))
1954 CFCharacterSetRef desc_charset =
1955 mac_font_descriptor_copy_attribute (desc,
1956 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1958 if (desc_charset == NULL)
1963 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1964 else /* VECTORP (chars) */
1968 for (j = 0; j < ASIZE (chars); j++)
1969 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
1970 && CFCharacterSetIsLongCharacterMember (desc_charset,
1971 XFASTINT (AREF (chars, j))))
1973 if (j == ASIZE (chars))
1976 CFRelease (desc_charset);
1979 if (result && languages)
1980 result = mac_font_descriptor_supports_languages (desc, languages);
1986 macfont_closest_traits_index (CFArrayRef traits_array,
1987 FontSymbolicTraits target)
1989 CFIndex i, result = -1, count = CFArrayGetCount (traits_array);
1990 int min_distance = (1 << 3);
1992 for (i = 0; i < count; i++)
1994 FontSymbolicTraits traits, diff;
1997 traits = ((FontSymbolicTraits) (uintptr_t)
1998 CFArrayGetValueAtIndex (traits_array, i));
1999 diff = (target ^ traits);
2000 /* We prefer synthetic bold of italic to synthetic italic of
2001 bold when both bold and italic are available but bold-italic
2002 is not available. */
2003 if (diff & MAC_FONT_TRAIT_BOLD)
2004 distance |= (1 << 0);
2005 if (diff & MAC_FONT_TRAIT_ITALIC)
2006 distance |= (1 << 1);
2007 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
2008 distance |= (1 << 2);
2009 if (distance < min_distance)
2011 min_distance = distance;
2020 macfont_list (struct frame *f, Lisp_Object spec)
2022 Lisp_Object val = Qnil, family, extra;
2024 CFStringRef family_name = NULL;
2025 CFMutableDictionaryRef attributes = NULL, traits;
2026 Lisp_Object chars = Qnil;
2028 FontSymbolicTraits synth_sym_traits = 0;
2029 CFArrayRef families;
2030 CFIndex families_count;
2031 CFCharacterSetRef charset = NULL;
2032 CFArrayRef languages = NULL;
2036 family = AREF (spec, FONT_FAMILY_INDEX);
2037 if (! NILP (family))
2039 family_name = macfont_create_family_with_symbol (family);
2040 if (family_name == NULL)
2044 attributes = macfont_create_attributes_with_spec (spec);
2048 charset = ((CFCharacterSetRef)
2049 CFDictionaryGetValue (attributes,
2050 MAC_FONT_CHARACTER_SET_ATTRIBUTE));
2054 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2058 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2061 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2062 if (CONSP (val) && VECTORP (XCDR (val)))
2068 languages = ((CFArrayRef)
2069 CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE));
2072 CFRetain (languages);
2073 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2076 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2077 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2079 traits = ((CFMutableDictionaryRef)
2080 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2082 n = FONT_SLANT_NUMERIC (spec);
2083 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2085 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2087 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2090 n = FONT_WEIGHT_NUMERIC (spec);
2091 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2093 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2095 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2099 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2101 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2103 if (CFStringHasPrefix (language, CFSTR ("ja"))
2104 || CFStringHasPrefix (language, CFSTR ("ko"))
2105 || CFStringHasPrefix (language, CFSTR ("zh")))
2106 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2109 /* Create array of families. */
2111 families = CFArrayCreate (NULL, (const void **) &family_name,
2112 1, &kCFTypeArrayCallBacks);
2115 CFStringRef pref_family;
2116 CFIndex families_count, pref_family_index = -1;
2118 families = mac_font_create_available_families ();
2119 if (families == NULL)
2122 families_count = CFArrayGetCount (families);
2124 /* Move preferred family to the front if exists. */
2126 mac_font_create_preferred_family_for_attributes (attributes);
2130 CFArrayGetFirstIndexOfValue (families,
2131 CFRangeMake (0, families_count),
2133 CFRelease (pref_family);
2135 if (pref_family_index > 0)
2137 CFMutableArrayRef mutable_families =
2138 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2140 if (mutable_families)
2142 CFArrayAppendValue (mutable_families,
2143 CFArrayGetValueAtIndex (families,
2144 pref_family_index));
2145 CFArrayAppendArray (mutable_families, families,
2146 CFRangeMake (0, pref_family_index));
2147 if (pref_family_index + 1 < families_count)
2148 CFArrayAppendArray (mutable_families, families,
2149 CFRangeMake (pref_family_index + 1,
2151 - (pref_family_index + 1)));
2152 CFRelease (families);
2153 families = mutable_families;
2159 extra = AREF (spec, FONT_EXTRA_INDEX);
2160 families_count = CFArrayGetCount (families);
2161 for (i = 0; i < families_count; i++)
2163 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2164 FontDescriptorRef pat_desc;
2166 CFIndex descs_count;
2167 CFMutableArrayRef filtered_descs, traits_array;
2171 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2173 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2177 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2178 10.7 returns NULL if pat_desc represents the LastResort font.
2179 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2180 trailing "s") for such a font. */
2181 if (CFStringCompare (family_name, CFSTR ("LastResort"), 0)
2182 != kCFCompareEqualTo)
2183 descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc,
2187 FontDescriptorRef lr_desc =
2188 mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2192 descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1,
2193 &kCFTypeArrayCallBacks);
2194 CFRelease (lr_desc);
2199 CFRelease (pat_desc);
2203 descs_count = CFArrayGetCount (descs);
2204 if (descs_count == 0
2205 || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0),
2214 CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks);
2215 traits_array = CFArrayCreateMutable (NULL, descs_count, NULL);
2216 for (j = 0; j < descs_count; j++)
2218 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2219 CFDictionaryRef dict;
2221 FontSymbolicTraits sym_traits;
2223 dict = mac_font_descriptor_copy_attribute (desc,
2224 MAC_FONT_TRAITS_ATTRIBUTE);
2228 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
2231 || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits))
2235 && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2236 && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0)
2237 != (spacing >= FONT_SPACING_MONO)))
2240 /* Don't use a color bitmap font unless its family is
2241 explicitly specified. */
2242 if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family))
2246 && !macfont_supports_charset_and_languages_p (desc, charset,
2250 CFArrayAppendValue (filtered_descs, desc);
2251 CFArrayAppendValue (traits_array,
2252 (const void *) (uintptr_t) sym_traits);
2256 descs = filtered_descs;
2257 descs_count = CFArrayGetCount (descs);
2259 for (j = 0; j < descs_count; j++)
2261 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j);
2262 FontSymbolicTraits sym_traits =
2263 ((FontSymbolicTraits) (uintptr_t)
2264 CFArrayGetValueAtIndex (traits_array, j));
2265 FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask;
2267 mask_min = ((synth_sym_traits ^ sym_traits)
2268 & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD));
2269 if (FONT_SLANT_NUMERIC (spec) < 0)
2270 mask_min &= ~MAC_FONT_TRAIT_ITALIC;
2271 if (FONT_WEIGHT_NUMERIC (spec) < 0)
2272 mask_min &= ~MAC_FONT_TRAIT_BOLD;
2274 mask_max = (synth_sym_traits & ~sym_traits);
2275 /* Synthetic bold does not work for bitmap-only fonts on Mac
2277 if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD)
2279 CFNumberRef format =
2280 mac_font_descriptor_copy_attribute (desc,
2281 MAC_FONT_FORMAT_ATTRIBUTE);
2285 uint32_t format_val;
2287 if (CFNumberGetValue (format, kCFNumberSInt32Type,
2289 && format_val == MAC_FONT_FORMAT_BITMAP)
2290 mask_max &= ~MAC_FONT_TRAIT_BOLD;
2294 mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2296 for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE);
2297 mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE);
2298 mmask += MAC_FONT_TRAIT_MONO_SPACE)
2299 for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD);
2300 bmask <= (mask_max & MAC_FONT_TRAIT_BOLD);
2301 bmask += MAC_FONT_TRAIT_BOLD)
2302 for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC);
2303 imask <= (mask_max & MAC_FONT_TRAIT_ITALIC);
2304 imask += MAC_FONT_TRAIT_ITALIC)
2306 FontSymbolicTraits synth = (imask | bmask | mmask);
2309 || j == macfont_closest_traits_index (traits_array,
2310 (sym_traits | synth)))
2312 entity = macfont_descriptor_entity (desc, extra, synth);
2313 if (! NILP (entity))
2314 val = Fcons (entity, val);
2319 CFRelease (traits_array);
2323 CFRelease (families);
2324 val = Fnreverse (val);
2330 FONT_ADD_LOG ("macfont-list", spec, val);
2331 if (charset) CFRelease (charset);
2332 if (languages) CFRelease (languages);
2333 if (attributes) CFRelease (attributes);
2334 if (family_name) CFRelease (family_name);
2342 macfont_match (struct frame * frame, Lisp_Object spec)
2344 Lisp_Object entity = Qnil;
2345 CFMutableDictionaryRef attributes;
2346 FontDescriptorRef pat_desc = NULL, desc = NULL;
2350 attributes = macfont_create_attributes_with_spec (spec);
2353 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2354 CFRelease (attributes);
2358 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2360 CFRelease (pat_desc);
2364 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2370 FONT_ADD_LOG ("macfont-match", spec, entity);
2375 macfont_list_family (struct frame *frame)
2377 Lisp_Object list = Qnil;
2378 CFArrayRef families;
2382 families = mac_font_create_available_families ();
2385 CFIndex i, count = CFArrayGetCount (families);
2387 for (i = 0; i < count; i++)
2388 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2389 CFRelease (families);
2398 macfont_free_entity (Lisp_Object entity)
2400 Lisp_Object val = assq_no_quit (QCfont_entity,
2401 AREF (entity, FONT_EXTRA_INDEX));
2402 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2410 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2412 Lisp_Object val, font_object;
2413 CFStringRef font_name;
2414 struct macfont_info *macfont_info = NULL;
2418 FontSymbolicTraits sym_traits;
2420 int len, i, total_width;
2422 CGFloat ascent, descent, leading;
2424 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2426 || XTYPE (XCDR (val)) != Lisp_Misc
2427 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2429 font_name = XSAVE_POINTER (XCDR (val), 0);
2430 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2432 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2437 macfont = mac_font_create_with_name (font_name, size);
2440 int fontsize = (int) [((NSFont *) macfont) pointSize];
2441 if (fontsize != size) size = fontsize;
2447 font_object = font_make_object (VECSIZE (struct macfont_info), entity, size);
2448 ASET (font_object, FONT_TYPE_INDEX, macfont_driver.type);
2449 len = font_unparse_xlfd (entity, size, name, 256);
2451 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
2452 len = font_unparse_fcname (entity, size, name, 256);
2454 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
2456 ASET (font_object, FONT_FULLNAME_INDEX,
2457 AREF (font_object, FONT_NAME_INDEX));
2458 font = XFONT_OBJECT (font_object);
2459 font->pixel_size = size;
2460 font->driver = &macfont_driver;
2461 font->encoding_charset = font->repertory_charset = -1;
2465 macfont_info = (struct macfont_info *) font;
2466 macfont_info->macfont = macfont;
2467 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2469 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2470 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2471 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2474 macfont_info->screen_font = NULL;
2475 macfont_info->cache = macfont_lookup_cache (font_name);
2476 macfont_retain_cache (macfont_info->cache);
2477 macfont_info->metrics = NULL;
2478 macfont_info->metrics_nrows = 0;
2479 macfont_info->synthetic_italic_p = 0;
2480 macfont_info->synthetic_bold_p = 0;
2481 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2482 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2483 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2484 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2485 macfont_info->synthetic_italic_p = 1;
2486 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2487 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2488 macfont_info->synthetic_bold_p = 1;
2489 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2490 macfont_info->spacing = MACFONT_SPACING_MONO;
2491 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2492 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2493 == FONT_SPACING_SYNTHETIC_MONO))
2494 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2495 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2496 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2499 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2501 macfont_info->antialias =
2502 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2504 macfont_info->color_bitmap_p = 0;
2505 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2506 macfont_info->color_bitmap_p = 1;
2508 glyph = macfont_get_glyph_for_character (font, ' ');
2509 if (glyph != kCGFontIndexInvalid)
2510 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2512 /* dirty workaround */
2513 font->space_width = pixel_size;
2515 total_width = font->space_width;
2516 for (i = 1; i < 95; i++)
2518 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2519 if (glyph == kCGFontIndexInvalid)
2521 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2524 font->average_width = total_width / 95;
2526 font->average_width = font->space_width; /* XXX */
2528 if (!(macfont_info->screen_font
2529 && mac_screen_font_get_metrics (macfont_info->screen_font,
2530 &ascent, &descent, &leading)))
2532 CFStringRef family_name;
2534 ascent = mac_font_get_ascent (macfont);
2535 descent = mac_font_get_descent (macfont);
2536 leading = mac_font_get_leading (macfont);
2537 /* AppKit and WebKit do some adjustment to the heights of
2538 Courier, Helvetica, and Times. */
2539 family_name = mac_font_copy_family_name (macfont);
2542 if ((CFStringCompare (family_name, CFSTR ("Courier"), 0)
2543 == kCFCompareEqualTo)
2544 || (CFStringCompare (family_name, CFSTR ("Helvetica"), 0)
2545 == kCFCompareEqualTo)
2546 || (CFStringCompare (family_name, CFSTR ("Times"), 0)
2547 == kCFCompareEqualTo))
2548 ascent += (ascent + descent) * .15f;
2549 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2554 CFRelease (family_name);
2557 font->ascent = ascent + 0.5f;
2558 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2559 if (CONSP (val) && !NILP (XCDR (val)))
2560 font->descent = descent + 0.5f;
2562 font->descent = descent + leading + 0.5f;
2563 font->height = font->ascent + font->descent;
2565 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2566 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2570 /* Unfortunately Xft doesn't provide a way to get minimum char
2571 width. So, we use space_width instead. */
2572 font->min_width = font->max_width = font->space_width; /* XXX */
2574 font->baseline_offset = 0;
2575 font->relative_compose = 0;
2576 font->default_ascent = 0;
2577 font->vertical_centering = 0;
2583 macfont_close (struct frame * f, struct font *font)
2585 struct macfont_info *macfont_info = (struct macfont_info *) font;
2589 CFRelease (macfont_info->macfont);
2590 CGFontRelease (macfont_info->cgfont);
2591 if (macfont_info->screen_font)
2592 CFRelease (macfont_info->screen_font);
2593 macfont_release_cache (macfont_info->cache);
2594 for (i = 0; i < macfont_info->metrics_nrows; i++)
2595 if (macfont_info->metrics[i])
2596 xfree (macfont_info->metrics[i]);
2597 if (macfont_info->metrics)
2598 xfree (macfont_info->metrics);
2603 macfont_has_char (Lisp_Object font, int c)
2606 CFCharacterSetRef charset;
2609 if (FONT_ENTITY_P (font))
2614 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2616 name = XSAVE_POINTER (val, 0);
2617 charset = macfont_get_cf_charset_for_name (name);
2620 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2622 result = CFCharacterSetIsLongCharacterMember (charset, c);
2629 macfont_encode_char (struct font *font, int c)
2631 struct macfont_info *macfont_info = (struct macfont_info *) font;
2635 glyph = macfont_get_glyph_for_character (font, c);
2638 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2642 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2643 struct font_metrics *metrics)
2648 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2649 for (i = 1; i < nglyphs; i++)
2651 struct font_metrics m;
2652 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2657 if (width + m.lbearing < metrics->lbearing)
2658 metrics->lbearing = width + m.lbearing;
2659 if (width + m.rbearing > metrics->rbearing)
2660 metrics->rbearing = width + m.rbearing;
2661 if (m.ascent > metrics->ascent)
2662 metrics->ascent = m.ascent;
2663 if (m.descent > metrics->descent)
2664 metrics->descent = m.descent;
2671 metrics->width = width;
2677 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2678 bool with_background)
2680 struct frame * f = s->f;
2681 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2682 FontRef macfont = macfont_info->macfont;
2683 CGContextRef context;
2684 BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
2685 int end = isComposite ? s->cmp_to : s->nchars;
2686 int len = end - s->cmp_from;
2691 context = [[NSGraphicsContext currentContext] graphicsPort];
2692 CGContextSaveGState (context);
2695 if (s->num_clips > 0)
2699 for (i = 0; i < s->num_clips; i++)
2700 clips[i] = mac_rect_make (f, s->clip[i].left, s->clip[i].top,
2701 s->clip[i].right - s->clip[i].left,
2702 s->clip[i].bottom - s->clip[i].top);
2703 CGContextClipToRects (context, clips, s->num_clips);
2707 if (with_background)
2709 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, s);
2710 CGContextFillRect (context,
2712 s->width, FONT_HEIGHT (s->font)));
2715 if (macfont_info->cgfont)
2717 CGGlyph *glyphs = alloca (sizeof (CGGlyph) * len);
2718 CGPoint *positions = alloca (sizeof (CGPoint) * len);
2719 CGFloat total_width = 0;
2720 CGFloat font_size = mac_font_get_size (macfont);
2721 CGAffineTransform atfm;
2722 CGFloat advance_delta = 0;
2723 int y_draw = -y-FONT_BASE (s->font);
2724 int no_antialias_p =
2725 (macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2726 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2727 && font_size <= macfont_antialias_threshold));
2729 for (i = 0; i < len; i++)
2733 glyphs[i] = *(s->char2b + s->cmp_from + i);
2734 width = (s->padding_p ? 1
2735 : macfont_glyph_extents (s->font, glyphs[i],
2736 NULL, &advance_delta,
2738 positions[i].x = total_width + advance_delta;
2740 total_width += width;
2743 CGContextScaleCTM (context, 1, -1);
2744 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, s);
2745 if (macfont_info->synthetic_italic_p)
2746 atfm = synthetic_italic_atfm;
2748 atfm = CGAffineTransformIdentity;
2749 if (macfont_info->synthetic_bold_p)
2751 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2752 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2753 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, s);
2756 CGContextSetShouldAntialias (context, false);
2758 CGContextSetTextMatrix (context, atfm);
2759 CGContextSetTextPosition (context, x, y_draw);
2761 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2762 if (macfont_info->color_bitmap_p
2763 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2764 && CTFontDrawGlyphs != NULL
2770 CTFontDrawGlyphs (macfont, glyphs, positions, len, context);
2774 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2776 CGContextSetFont (context, macfont_info->cgfont);
2777 CGContextSetFontSize (context, font_size);
2778 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2782 CGContextRestoreGState (context);
2790 macfont_shape (Lisp_Object lgstring)
2793 struct macfont_info *macfont_info;
2795 ptrdiff_t glyph_len, len, i, j;
2798 CFIndex *nonbmp_indices;
2801 struct mac_glyph_layout *glyph_layouts;
2803 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2804 macfont_info = (struct macfont_info *) font;
2805 macfont = macfont_info->macfont;
2807 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2809 for (i = 0; i < glyph_len; i++)
2811 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2815 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2820 lint_assume (len <= TYPE_MAXIMUM (EMACS_INT) - 2);
2822 if (INT_MAX / 2 < len)
2823 memory_full (SIZE_MAX);
2825 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2826 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2827 for (i = j = 0; i < len; i++)
2829 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2831 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2833 nonbmp_indices[j] = i + j;
2837 nonbmp_indices[j] = len + j; /* sentinel */
2841 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2845 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2846 if (macfont_info->screen_font)
2847 used = mac_screen_font_shape (macfont_info->screen_font, string,
2848 glyph_layouts, glyph_len);
2850 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2861 for (i = 0; i < used; i++)
2863 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2864 struct mac_glyph_layout *gl = glyph_layouts + i;
2866 struct font_metrics metrics;
2867 int xoff, yoff, wadjust;
2871 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2872 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2875 from = gl->comp_range.location;
2876 /* Convert UTF-16 index to UTF-32. */
2878 while (nonbmp_indices[j] < from)
2881 LGLYPH_SET_FROM (lglyph, from);
2883 to = gl->comp_range.location + gl->comp_range.length;
2884 /* Convert UTF-16 index to UTF-32. */
2885 while (nonbmp_indices[j] < to)
2888 LGLYPH_SET_TO (lglyph, to - 1);
2890 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2891 the composition is trivial. */
2895 if (unichars[gl->string_index] >= 0xD800
2896 && unichars[gl->string_index] < 0xDC00)
2897 c = (((unichars[gl->string_index] - 0xD800) << 10)
2898 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2900 c = unichars[gl->string_index];
2901 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2903 LGLYPH_SET_CHAR (lglyph, c);
2907 unsigned long cc = gl->glyph_id;
2908 LGLYPH_SET_CODE (lglyph, cc);
2911 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2912 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2913 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2914 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2915 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2916 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2918 xoff = lround (gl->advance_delta);
2919 yoff = lround (- gl->baseline_delta);
2920 wadjust = lround (gl->advance);
2921 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2925 vec = Fmake_vector (make_number (3), Qnil);
2926 ASET (vec, 0, make_number (xoff));
2927 ASET (vec, 1, make_number (yoff));
2928 ASET (vec, 2, make_number (wadjust));
2929 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2935 return make_number (used);
2938 /* Structures for the UVS subtable (format 14) in the cmap table. */
2939 typedef UInt8 UINT24[3];
2941 #pragma pack(push, 1)
2942 struct variation_selector_record
2944 UINT24 var_selector;
2945 UInt32 default_uvs_offset, non_default_uvs_offset;
2950 UInt32 length, num_var_selector_records;
2951 struct variation_selector_record variation_selector_records[1];
2953 #define SIZEOF_UVS_TABLE_HEADER \
2954 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2956 struct unicode_value_range
2958 UINT24 start_unicode_value;
2959 UInt8 additional_count;
2961 struct default_uvs_table {
2962 UInt32 num_unicode_value_ranges;
2963 struct unicode_value_range unicode_value_ranges[1];
2965 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2966 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2970 UINT24 unicode_value;
2973 struct non_default_uvs_table
2975 UInt32 num_uvs_mappings;
2976 struct uvs_mapping uvs_mappings[1];
2978 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
2979 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2982 /* Read big endian values. The argument LVAL must be an lvalue. */
2983 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
2984 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
2985 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
2986 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
2987 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
2988 /* Succeeding one byte should also be accessible. */
2989 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
2990 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
2992 /* Return UVS subtable for the specified FONT. If the subtable is not
2993 found or ill-formated, then return NULL. */
2996 mac_font_copy_uvs_table (FontRef font)
2998 CFDataRef cmap_table, uvs_table = NULL;
3000 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3003 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3004 struct uvs_table *uvs;
3005 struct variation_selector_record *records;
3006 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3009 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3013 cmap_len = CFDataGetLength (cmap_table);
3014 if (sizeof_sfntCMapHeader > cmap_len)
3017 ntables = BUINT16_VALUE (cmap->numTables);
3018 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3019 / sizeof_sfntCMapEncoding))
3022 for (i = 0; i < ntables; i++)
3023 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3024 == kFontUnicodePlatform)
3025 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3026 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3028 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3032 || uvs_offset > cmap_len
3033 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3036 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3037 uvs_len = BUINT32_VALUE (uvs->length);
3038 if (uvs_len > cmap_len - uvs_offset
3039 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3042 if (BUINT16_VALUE (uvs->format) != 14)
3045 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3046 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3047 / sizeof (struct variation_selector_record)))
3050 records = uvs->variation_selector_records;
3051 for (i = 0; i < nrecords; i++)
3053 UInt32 default_uvs_offset, non_default_uvs_offset;
3055 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3056 if (default_uvs_offset)
3058 struct default_uvs_table *default_uvs;
3061 if (default_uvs_offset > uvs_len
3062 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3063 > uvs_len - default_uvs_offset))
3066 default_uvs = ((struct default_uvs_table *)
3067 ((UInt8 *) uvs + default_uvs_offset));
3068 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3069 if (nranges > ((uvs_len - default_uvs_offset
3070 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3071 / sizeof (struct unicode_value_range)))
3073 /* Now 2 * nranges can't overflow, so we can safely use
3074 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3075 mac_font_get_glyphs_for_variants. */
3078 non_default_uvs_offset =
3079 BUINT32_VALUE (records[i].non_default_uvs_offset);
3080 if (non_default_uvs_offset)
3082 struct non_default_uvs_table *non_default_uvs;
3085 if (non_default_uvs_offset > uvs_len
3086 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3087 > uvs_len - non_default_uvs_offset))
3090 non_default_uvs = ((struct non_default_uvs_table *)
3091 ((UInt8 *) uvs + non_default_uvs_offset));
3092 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3093 if (nmappings > ((uvs_len - non_default_uvs_offset
3094 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3095 / sizeof (struct uvs_mapping)))
3097 /* Now 2 * nmappings can't overflow, so we can safely
3098 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3099 in mac_font_get_glyphs_for_variants. */
3103 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3106 CFRelease (cmap_table);
3112 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3113 sequence consisting of the given base character C and each
3114 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3115 result (explained below) into the corresponding GLYPHS[i]. If the
3116 entry is found in the Default UVS Table, then the result is 0. If
3117 the entry is found in the Non-Default UVS Table, then the result is
3118 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3119 elements in SELECTORS must be sorted in strictly increasing
3123 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3124 const UTF32Char selectors[], CGGlyph glyphs[],
3127 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3128 struct variation_selector_record *records = uvs->variation_selector_records;
3130 UInt32 ir, nrecords;
3131 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3132 dispatch_queue_t queue =
3133 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3134 dispatch_group_t group = dispatch_group_create ();
3137 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3140 while (i < count && ir < nrecords)
3142 UInt32 default_uvs_offset, non_default_uvs_offset;
3144 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3146 glyphs[i++] = kCGFontIndexInvalid;
3149 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3155 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3156 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3157 non_default_uvs_offset =
3158 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3159 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3160 dispatch_group_async (group, queue, ^{
3162 glyphs[i] = kCGFontIndexInvalid;
3164 if (default_uvs_offset)
3166 struct default_uvs_table *default_uvs =
3167 (struct default_uvs_table *) ((UInt8 *) uvs
3168 + default_uvs_offset);
3169 struct unicode_value_range *ranges =
3170 default_uvs->unicode_value_ranges;
3174 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3177 UInt32 mid = (lo + hi) / 2;
3179 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3185 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3186 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3190 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3192 struct non_default_uvs_table *non_default_uvs =
3193 (struct non_default_uvs_table *) ((UInt8 *) uvs
3194 + non_default_uvs_offset);
3195 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3199 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3202 UInt32 mid = (lo + hi) / 2;
3204 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3210 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3211 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3213 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3220 glyphs[i++] = kCGFontIndexInvalid;
3221 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3222 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3223 dispatch_release (group);
3228 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3230 CFDataRef uvs_table;
3231 CharacterCollection uvs_collection;
3235 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3239 UTF32Char selectors[256];
3240 CGGlyph glyphs[256];
3242 for (i = 0; i < 16; i++)
3243 selectors[i] = 0xFE00 + i;
3244 for (; i < 256; i++)
3245 selectors[i] = 0xE0100 + (i - 16);
3246 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3247 for (i = 0; i < 256; i++)
3249 CGGlyph glyph = glyphs[i];
3251 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3252 && glyph != kCGFontIndexInvalid)
3253 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3254 if (glyph == kCGFontIndexInvalid)
3258 variations[i] = (glyph ? glyph
3259 : macfont_get_glyph_for_character (font, c));
3269 static const char *const macfont_booleans[] = {
3275 static const char *const macfont_non_booleans[] = {
3283 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3285 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3289 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3290 CFArrayRef languages)
3292 Boolean result = true;
3293 CFArrayRef desc_languages =
3294 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3296 if (desc_languages == NULL)
3300 CFIndex desc_languages_count, i, languages_count;
3302 desc_languages_count = CFArrayGetCount (desc_languages);
3303 languages_count = CFArrayGetCount (languages);
3304 for (i = 0; i < languages_count; i++)
3305 if (!CFArrayContainsValue (desc_languages,
3306 CFRangeMake (0, desc_languages_count),
3307 CFArrayGetValueAtIndex (languages, i)))
3312 CFRelease (desc_languages);
3319 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3321 CFStringRef result = NULL;
3322 CFStringRef charset_string =
3323 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3327 && (length = CFStringGetLength (charset_string)) > 0)
3329 CFAttributedStringRef attr_string = NULL;
3330 CTLineRef ctline = NULL;
3331 CFDictionaryRef attrs =
3332 CFDictionaryCreate (NULL, NULL, NULL, 0,
3333 &kCFTypeDictionaryKeyCallBacks,
3334 &kCFTypeDictionaryValueCallBacks);
3338 attr_string = CFAttributedStringCreate (NULL, charset_string, attrs);
3343 ctline = CTLineCreateWithAttributedString (attr_string);
3344 CFRelease (attr_string);
3348 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3349 CFIndex i, nruns = CFArrayGetCount (runs);
3352 for (i = 0; i < nruns; i++)
3354 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3355 CFDictionaryRef attributes = CTRunGetAttributes (run);
3356 CTFontRef font_in_run;
3358 if (attributes == NULL)
3361 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3362 if (font_in_run == NULL)
3366 else if (!mac_ctfont_equal_in_postscript_name (font, font_in_run))
3369 if (nruns > 0 && i == nruns)
3370 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3378 static inline double
3379 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3381 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3385 static inline CGRect
3386 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3388 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3393 mac_ctfont_create_available_families (void)
3395 CFMutableArrayRef families = NULL;
3397 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3398 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3399 if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3402 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3406 CFIndex i, count = CFArrayGetCount (orig_families);
3408 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3410 for (i = 0; i < count; i++)
3412 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3414 if (!CFStringHasPrefix (family, CFSTR ("."))
3415 && (CTFontManagerCompareFontFamilyNames (family,
3416 CFSTR ("LastResort"),
3418 != kCFCompareEqualTo))
3419 CFArrayAppendValue (families, family);
3421 CFRelease (orig_families);
3424 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3425 else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3427 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3428 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3430 CTFontCollectionRef collection;
3431 CFArrayRef descs = NULL;
3433 collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3436 descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3437 CFRelease (collection);
3441 CFIndex i, count = CFArrayGetCount (descs);
3443 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3445 for (i = 0; i < count; i++)
3447 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3449 mac_font_descriptor_copy_attribute (desc,
3450 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3454 CFIndex p, limit = CFArrayGetCount (families);
3456 p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3457 (const void *) name,
3458 mac_font_family_compare, NULL);
3460 CFArrayAppendValue (families, name);
3461 else if (mac_font_family_compare
3462 (CFArrayGetValueAtIndex (families, p),
3463 name, NULL) != kCFCompareEqualTo)
3464 CFArrayInsertValueAtIndex (families, p, name);
3477 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3480 CFStringRef name1, name2;
3486 name1 = CTFontCopyPostScriptName (font1);
3489 name2 = CTFontCopyPostScriptName (font2);
3492 result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo);
3502 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3505 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3506 CFTypeRef values[] = {NULL, NULL};
3507 CFDictionaryRef attributes = NULL;
3508 CFAttributedStringRef attr_string = NULL;
3509 CTLineRef ctline = NULL;
3510 float float_zero = 0.0f;
3512 values[0] = macfont;
3513 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3516 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3517 (const void **) values,
3518 sizeof (keys) / sizeof (keys[0]),
3519 &kCFTypeDictionaryKeyCallBacks,
3520 &kCFTypeDictionaryValueCallBacks);
3521 CFRelease (values[1]);
3525 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3526 CFRelease (attributes);
3530 ctline = CTLineCreateWithAttributedString (attr_string);
3531 CFRelease (attr_string);
3535 /* Abandon if ctline contains some fonts other than the
3537 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3538 CFIndex i, nruns = CFArrayGetCount (runs);
3540 for (i = 0; i < nruns; i++)
3542 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3543 CFDictionaryRef attributes = CTRunGetAttributes (run);
3544 CTFontRef font_in_run;
3546 if (attributes == NULL)
3549 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3550 if (font_in_run == NULL)
3552 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3566 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3567 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3569 CFIndex used, result = 0;
3570 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3575 used = CTLineGetGlyphCount (ctline);
3576 if (used <= glyph_len)
3578 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3579 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3580 CGFloat total_advance = 0;
3581 CFIndex total_glyph_count = 0;
3583 for (k = 0; k < ctrun_count; k++)
3585 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3586 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3587 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3588 CFRange string_range, comp_range, range;
3589 CFIndex *permutation;
3591 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3592 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3596 #define RIGHT_TO_LEFT_P permutation
3598 /* Now the `comp_range' member of struct mac_glyph_layout is
3599 temporarily used as a work area such that:
3600 glbuf[i].comp_range.location =
3601 min {compRange[i + 1].location, ...,
3602 compRange[glyph_count - 1].location,
3603 maxRange (stringRangeForCTRun)}
3604 glbuf[i].comp_range.length = maxRange (compRange[i])
3605 where compRange[i] is the range of composed characters
3606 containing i-th glyph. */
3607 string_range = CTRunGetStringRange (ctrun);
3608 min_location = string_range.location + string_range.length;
3609 for (i = 0; i < glyph_count; i++)
3611 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3612 CFIndex glyph_index;
3615 if (!RIGHT_TO_LEFT_P)
3616 glyph_index = glyph_count - i - 1;
3619 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3622 CFStringGetRangeOfComposedCharactersAtIndex (string,
3624 gl->comp_range.location = min_location;
3625 gl->comp_range.length = rng.location + rng.length;
3626 if (rng.location < min_location)
3627 min_location = rng.location;
3630 /* Fill the `comp_range' member of struct mac_glyph_layout,
3631 and setup a permutation for right-to-left text. */
3632 comp_range = CFRangeMake (string_range.location, 0);
3633 range = CFRangeMake (0, 0);
3636 struct mac_glyph_layout *gl =
3637 glbuf + range.location + range.length;
3639 if (gl->comp_range.length
3640 > comp_range.location + comp_range.length)
3641 comp_range.length = gl->comp_range.length - comp_range.location;
3642 min_location = gl->comp_range.location;
3645 if (min_location >= comp_range.location + comp_range.length)
3647 comp_range.length = min_location - comp_range.location;
3648 for (i = 0; i < range.length; i++)
3650 glbuf[range.location + i].comp_range = comp_range;
3651 if (RIGHT_TO_LEFT_P)
3652 permutation[range.location + i] =
3653 range.location + range.length - i - 1;
3656 comp_range = CFRangeMake (min_location, 0);
3657 range.location += range.length;
3659 if (range.location == glyph_count)
3664 /* Then fill the remaining members. */
3665 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3668 struct mac_glyph_layout *gl;
3671 if (!RIGHT_TO_LEFT_P)
3672 gl = glbuf + range.location;
3677 src = glyph_count - 1 - range.location;
3678 dest = permutation[src];
3682 CFIndex tmp = gl->string_index;
3684 gl->string_index = glbuf[src].string_index;
3685 glbuf[src].string_index = tmp;
3688 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3690 CTRunGetPositions (ctrun, range, &position);
3691 gl->advance_delta = position.x - total_advance;
3692 gl->baseline_delta = position.y;
3693 gl->advance = (gl->advance_delta
3694 + CTRunGetTypographicBounds (ctrun, range,
3696 total_advance += gl->advance;
3699 if (RIGHT_TO_LEFT_P)
3700 xfree (permutation);
3702 #undef RIGHT_TO_LEFT_P
3704 total_glyph_count += glyph_count;
3714 /* The function below seems to cause a memory leak for the CFString
3715 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3716 10.6.3. For now, we use the NSGlyphInfo version instead. */
3717 #if USE_CT_GLYPH_INFO
3719 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3722 CGGlyph result = kCGFontIndexInvalid;
3723 UniChar characters[] = {0xfffd};
3725 CFAttributedStringRef attr_string = NULL;
3726 CTLineRef ctline = NULL;
3728 string = CFStringCreateWithCharacters (NULL, characters,
3730 / sizeof (characters[0]));
3733 CTGlyphInfoRef glyph_info =
3734 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3735 CFDictionaryRef attributes = NULL;
3739 CFStringRef keys[] = {kCTFontAttributeName,
3740 kCTGlyphInfoAttributeName};
3741 CFTypeRef values[] = {font, glyph_info};
3743 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3744 (const void **) values,
3745 sizeof (keys) / sizeof (keys[0]),
3746 &kCFTypeDictionaryKeyCallBacks,
3747 &kCFTypeDictionaryValueCallBacks);
3748 CFRelease (glyph_info);
3752 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3753 CFRelease (attributes);
3759 ctline = CTLineCreateWithAttributedString (attr_string);
3760 CFRelease (attr_string);
3764 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3766 if (CFArrayGetCount (runs) > 0)
3768 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3769 CFDictionaryRef attributes = CTRunGetAttributes (run);
3773 CTFontRef font_in_run =
3774 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3777 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3779 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3780 if (result >= CTFontGetGlyphCount (font))
3781 result = kCGFontIndexInvalid;
3792 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3794 mac_font_family_group (CFStringRef family)
3796 if (CFStringHasPrefix (family, CFSTR ("#")))
3802 range = CFStringFind (family, CFSTR ("Apple"),
3803 kCFCompareCaseInsensitive | kCFCompareAnchored);
3804 if (range.location != kCFNotFound)
3812 mac_font_family_compare (const void *val1, const void *val2, void *context)
3814 CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3817 group1 = mac_font_family_group (family1);
3818 group2 = mac_font_family_group (family2);
3819 if (group1 < group2)
3820 return kCFCompareLessThan;
3821 if (group1 > group2)
3822 return kCFCompareGreaterThan;
3823 return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3825 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3828 macfont_get_nsctfont (struct font *font)
3830 struct macfont_info *macfont_info = (struct macfont_info *) font;
3831 FontRef macfont = macfont_info->macfont;
3833 return (void *) macfont;
3837 mac_register_font_driver (struct frame *f)
3839 register_font_driver (&macfont_driver, f);
3842 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
3846 syms_of_macfont (void)
3848 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
3849 static struct font_driver mac_font_driver;
3851 DEFSYM (Qmac_ct, "mac-ct");
3852 macfont_driver.type = Qmac_ct;
3853 register_font_driver (&macfont_driver, NULL);
3855 DEFSYM (QCdestination, ":destination");
3856 DEFSYM (QCminspace, ":minspace");