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 = -s->ybase;
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)
2821 if (INT_MAX / 2 < len)
2822 memory_full (SIZE_MAX);
2824 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2825 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2826 for (i = j = 0; i < len; i++)
2828 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2830 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2832 nonbmp_indices[j] = i + j;
2836 nonbmp_indices[j] = len + j; /* sentinel */
2840 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2844 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2845 if (macfont_info->screen_font)
2846 used = mac_screen_font_shape (macfont_info->screen_font, string,
2847 glyph_layouts, glyph_len);
2849 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2860 for (i = 0; i < used; i++)
2862 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2863 struct mac_glyph_layout *gl = glyph_layouts + i;
2865 struct font_metrics metrics;
2866 int xoff, yoff, wadjust;
2870 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2871 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2874 from = gl->comp_range.location;
2875 /* Convert UTF-16 index to UTF-32. */
2877 while (nonbmp_indices[j] < from)
2880 LGLYPH_SET_FROM (lglyph, from);
2882 to = gl->comp_range.location + gl->comp_range.length;
2883 /* Convert UTF-16 index to UTF-32. */
2884 while (nonbmp_indices[j] < to)
2887 LGLYPH_SET_TO (lglyph, to - 1);
2889 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2890 the composition is trivial. */
2894 if (unichars[gl->string_index] >= 0xD800
2895 && unichars[gl->string_index] < 0xDC00)
2896 c = (((unichars[gl->string_index] - 0xD800) << 10)
2897 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2899 c = unichars[gl->string_index];
2900 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2902 LGLYPH_SET_CHAR (lglyph, c);
2906 unsigned long cc = gl->glyph_id;
2907 LGLYPH_SET_CODE (lglyph, cc);
2910 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2911 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2912 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2913 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2914 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2915 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2917 xoff = lround (gl->advance_delta);
2918 yoff = lround (- gl->baseline_delta);
2919 wadjust = lround (gl->advance);
2920 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2924 vec = Fmake_vector (make_number (3), Qnil);
2925 ASET (vec, 0, make_number (xoff));
2926 ASET (vec, 1, make_number (yoff));
2927 ASET (vec, 2, make_number (wadjust));
2928 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2934 return make_number (used);
2937 /* Structures for the UVS subtable (format 14) in the cmap table. */
2938 typedef UInt8 UINT24[3];
2940 #pragma pack(push, 1)
2941 struct variation_selector_record
2943 UINT24 var_selector;
2944 UInt32 default_uvs_offset, non_default_uvs_offset;
2949 UInt32 length, num_var_selector_records;
2950 struct variation_selector_record variation_selector_records[1];
2952 #define SIZEOF_UVS_TABLE_HEADER \
2953 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2955 struct unicode_value_range
2957 UINT24 start_unicode_value;
2958 UInt8 additional_count;
2960 struct default_uvs_table {
2961 UInt32 num_unicode_value_ranges;
2962 struct unicode_value_range unicode_value_ranges[1];
2964 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2965 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2969 UINT24 unicode_value;
2972 struct non_default_uvs_table
2974 UInt32 num_uvs_mappings;
2975 struct uvs_mapping uvs_mappings[1];
2977 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
2978 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2981 /* Read big endian values. The argument LVAL must be an lvalue. */
2982 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
2983 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
2984 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
2985 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
2986 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
2987 /* Succeeding one byte should also be accessible. */
2988 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
2989 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
2991 /* Return UVS subtable for the specified FONT. If the subtable is not
2992 found or ill-formated, then return NULL. */
2995 mac_font_copy_uvs_table (FontRef font)
2997 CFDataRef cmap_table, uvs_table = NULL;
2999 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
3002 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
3003 struct uvs_table *uvs;
3004 struct variation_selector_record *records;
3005 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3008 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3012 cmap_len = CFDataGetLength (cmap_table);
3013 if (sizeof_sfntCMapHeader > cmap_len)
3016 ntables = BUINT16_VALUE (cmap->numTables);
3017 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3018 / sizeof_sfntCMapEncoding))
3021 for (i = 0; i < ntables; i++)
3022 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3023 == kFontUnicodePlatform)
3024 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3025 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3027 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3031 || uvs_offset > cmap_len
3032 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3035 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3036 uvs_len = BUINT32_VALUE (uvs->length);
3037 if (uvs_len > cmap_len - uvs_offset
3038 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3041 if (BUINT16_VALUE (uvs->format) != 14)
3044 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3045 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3046 / sizeof (struct variation_selector_record)))
3049 records = uvs->variation_selector_records;
3050 for (i = 0; i < nrecords; i++)
3052 UInt32 default_uvs_offset, non_default_uvs_offset;
3054 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3055 if (default_uvs_offset)
3057 struct default_uvs_table *default_uvs;
3060 if (default_uvs_offset > uvs_len
3061 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3062 > uvs_len - default_uvs_offset))
3065 default_uvs = ((struct default_uvs_table *)
3066 ((UInt8 *) uvs + default_uvs_offset));
3067 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3068 if (nranges > ((uvs_len - default_uvs_offset
3069 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3070 / sizeof (struct unicode_value_range)))
3072 /* Now 2 * nranges can't overflow, so we can safely use
3073 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3074 mac_font_get_glyphs_for_variants. */
3077 non_default_uvs_offset =
3078 BUINT32_VALUE (records[i].non_default_uvs_offset);
3079 if (non_default_uvs_offset)
3081 struct non_default_uvs_table *non_default_uvs;
3084 if (non_default_uvs_offset > uvs_len
3085 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3086 > uvs_len - non_default_uvs_offset))
3089 non_default_uvs = ((struct non_default_uvs_table *)
3090 ((UInt8 *) uvs + non_default_uvs_offset));
3091 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3092 if (nmappings > ((uvs_len - non_default_uvs_offset
3093 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3094 / sizeof (struct uvs_mapping)))
3096 /* Now 2 * nmappings can't overflow, so we can safely
3097 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3098 in mac_font_get_glyphs_for_variants. */
3102 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3105 CFRelease (cmap_table);
3111 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3112 sequence consisting of the given base character C and each
3113 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3114 result (explained below) into the corresponding GLYPHS[i]. If the
3115 entry is found in the Default UVS Table, then the result is 0. If
3116 the entry is found in the Non-Default UVS Table, then the result is
3117 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3118 elements in SELECTORS must be sorted in strictly increasing
3122 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3123 const UTF32Char selectors[], CGGlyph glyphs[],
3126 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3127 struct variation_selector_record *records = uvs->variation_selector_records;
3129 UInt32 ir, nrecords;
3130 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3131 dispatch_queue_t queue =
3132 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3133 dispatch_group_t group = dispatch_group_create ();
3136 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3139 while (i < count && ir < nrecords)
3141 UInt32 default_uvs_offset, non_default_uvs_offset;
3143 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3145 glyphs[i++] = kCGFontIndexInvalid;
3148 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3154 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3155 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3156 non_default_uvs_offset =
3157 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3158 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3159 dispatch_group_async (group, queue, ^{
3161 glyphs[i] = kCGFontIndexInvalid;
3163 if (default_uvs_offset)
3165 struct default_uvs_table *default_uvs =
3166 (struct default_uvs_table *) ((UInt8 *) uvs
3167 + default_uvs_offset);
3168 struct unicode_value_range *ranges =
3169 default_uvs->unicode_value_ranges;
3173 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3176 UInt32 mid = (lo + hi) / 2;
3178 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3184 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3185 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3189 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3191 struct non_default_uvs_table *non_default_uvs =
3192 (struct non_default_uvs_table *) ((UInt8 *) uvs
3193 + non_default_uvs_offset);
3194 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3198 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3201 UInt32 mid = (lo + hi) / 2;
3203 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3209 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3210 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3212 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3219 glyphs[i++] = kCGFontIndexInvalid;
3220 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
3221 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3222 dispatch_release (group);
3227 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3229 CFDataRef uvs_table;
3230 CharacterCollection uvs_collection;
3234 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3238 UTF32Char selectors[256];
3239 CGGlyph glyphs[256];
3241 for (i = 0; i < 16; i++)
3242 selectors[i] = 0xFE00 + i;
3243 for (; i < 256; i++)
3244 selectors[i] = 0xE0100 + (i - 16);
3245 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3246 for (i = 0; i < 256; i++)
3248 CGGlyph glyph = glyphs[i];
3250 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3251 && glyph != kCGFontIndexInvalid)
3252 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3253 if (glyph == kCGFontIndexInvalid)
3257 variations[i] = (glyph ? glyph
3258 : macfont_get_glyph_for_character (font, c));
3268 static const char *const macfont_booleans[] = {
3274 static const char *const macfont_non_booleans[] = {
3282 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3284 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3288 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3289 CFArrayRef languages)
3291 Boolean result = true;
3292 CFArrayRef desc_languages =
3293 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3295 if (desc_languages == NULL)
3299 CFIndex desc_languages_count, i, languages_count;
3301 desc_languages_count = CFArrayGetCount (desc_languages);
3302 languages_count = CFArrayGetCount (languages);
3303 for (i = 0; i < languages_count; i++)
3304 if (!CFArrayContainsValue (desc_languages,
3305 CFRangeMake (0, desc_languages_count),
3306 CFArrayGetValueAtIndex (languages, i)))
3311 CFRelease (desc_languages);
3318 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3320 CFStringRef result = NULL;
3321 CFStringRef charset_string =
3322 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3324 if (charset_string && CFStringGetLength (charset_string) > 0)
3326 CFAttributedStringRef attr_string = NULL;
3327 CTLineRef ctline = NULL;
3328 CFDictionaryRef attrs =
3329 CFDictionaryCreate (NULL, NULL, NULL, 0,
3330 &kCFTypeDictionaryKeyCallBacks,
3331 &kCFTypeDictionaryValueCallBacks);
3335 attr_string = CFAttributedStringCreate (NULL, charset_string, attrs);
3340 ctline = CTLineCreateWithAttributedString (attr_string);
3341 CFRelease (attr_string);
3345 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3346 CFIndex i, nruns = CFArrayGetCount (runs);
3349 for (i = 0; i < nruns; i++)
3351 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3352 CFDictionaryRef attributes = CTRunGetAttributes (run);
3353 CTFontRef font_in_run;
3355 if (attributes == NULL)
3358 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3359 if (font_in_run == NULL)
3363 else if (!mac_ctfont_equal_in_postscript_name (font, font_in_run))
3366 if (nruns > 0 && i == nruns)
3367 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3375 static inline double
3376 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3378 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3382 static inline CGRect
3383 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3385 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3390 mac_ctfont_create_available_families (void)
3392 CFMutableArrayRef families = NULL;
3394 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
3395 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3396 if (CTFontManagerCopyAvailableFontFamilyNames != NULL)
3399 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3403 CFIndex i, count = CFArrayGetCount (orig_families);
3405 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3407 for (i = 0; i < count; i++)
3409 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3411 if (!CFStringHasPrefix (family, CFSTR ("."))
3412 && (CTFontManagerCompareFontFamilyNames (family,
3413 CFSTR ("LastResort"),
3415 != kCFCompareEqualTo))
3416 CFArrayAppendValue (families, family);
3418 CFRelease (orig_families);
3421 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3422 else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */
3424 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
3425 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3427 CTFontCollectionRef collection;
3428 CFArrayRef descs = NULL;
3430 collection = CTFontCollectionCreateFromAvailableFonts (NULL);
3433 descs = CTFontCollectionCreateMatchingFontDescriptors (collection);
3434 CFRelease (collection);
3438 CFIndex i, count = CFArrayGetCount (descs);
3440 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3442 for (i = 0; i < count; i++)
3444 FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i);
3446 mac_font_descriptor_copy_attribute (desc,
3447 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3451 CFIndex p, limit = CFArrayGetCount (families);
3453 p = CFArrayBSearchValues (families, CFRangeMake (0, limit),
3454 (const void *) name,
3455 mac_font_family_compare, NULL);
3457 CFArrayAppendValue (families, name);
3458 else if (mac_font_family_compare
3459 (CFArrayGetValueAtIndex (families, p),
3460 name, NULL) != kCFCompareEqualTo)
3461 CFArrayInsertValueAtIndex (families, p, name);
3474 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3477 CFStringRef name1, name2;
3483 name1 = CTFontCopyPostScriptName (font1);
3486 name2 = CTFontCopyPostScriptName (font2);
3489 result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo);
3499 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3502 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3503 CFTypeRef values[] = {NULL, NULL};
3504 CFDictionaryRef attributes = NULL;
3505 CFAttributedStringRef attr_string = NULL;
3506 CTLineRef ctline = NULL;
3507 float float_zero = 0.0f;
3509 values[0] = macfont;
3510 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3513 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3514 (const void **) values,
3515 sizeof (keys) / sizeof (keys[0]),
3516 &kCFTypeDictionaryKeyCallBacks,
3517 &kCFTypeDictionaryValueCallBacks);
3518 CFRelease (values[1]);
3522 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3523 CFRelease (attributes);
3527 ctline = CTLineCreateWithAttributedString (attr_string);
3528 CFRelease (attr_string);
3532 /* Abandon if ctline contains some fonts other than the
3534 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3535 CFIndex i, nruns = CFArrayGetCount (runs);
3537 for (i = 0; i < nruns; i++)
3539 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3540 CFDictionaryRef attributes = CTRunGetAttributes (run);
3541 CTFontRef font_in_run;
3543 if (attributes == NULL)
3546 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3547 if (font_in_run == NULL)
3549 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3563 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3564 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3566 CFIndex used, result = 0;
3567 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3572 used = CTLineGetGlyphCount (ctline);
3573 if (used <= glyph_len)
3575 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3576 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3577 CGFloat total_advance = 0;
3578 CFIndex total_glyph_count = 0;
3580 for (k = 0; k < ctrun_count; k++)
3582 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3583 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3584 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3585 CFRange string_range, comp_range, range;
3586 CFIndex *permutation;
3588 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3589 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3593 #define RIGHT_TO_LEFT_P permutation
3595 /* Now the `comp_range' member of struct mac_glyph_layout is
3596 temporarily used as a work area such that:
3597 glbuf[i].comp_range.location =
3598 min {compRange[i + 1].location, ...,
3599 compRange[glyph_count - 1].location,
3600 maxRange (stringRangeForCTRun)}
3601 glbuf[i].comp_range.length = maxRange (compRange[i])
3602 where compRange[i] is the range of composed characters
3603 containing i-th glyph. */
3604 string_range = CTRunGetStringRange (ctrun);
3605 min_location = string_range.location + string_range.length;
3606 for (i = 0; i < glyph_count; i++)
3608 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3609 CFIndex glyph_index;
3612 if (!RIGHT_TO_LEFT_P)
3613 glyph_index = glyph_count - i - 1;
3616 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3619 CFStringGetRangeOfComposedCharactersAtIndex (string,
3621 gl->comp_range.location = min_location;
3622 gl->comp_range.length = rng.location + rng.length;
3623 if (rng.location < min_location)
3624 min_location = rng.location;
3627 /* Fill the `comp_range' member of struct mac_glyph_layout,
3628 and setup a permutation for right-to-left text. */
3629 comp_range = CFRangeMake (string_range.location, 0);
3630 range = CFRangeMake (0, 0);
3633 struct mac_glyph_layout *gl =
3634 glbuf + range.location + range.length;
3636 if (gl->comp_range.length
3637 > comp_range.location + comp_range.length)
3638 comp_range.length = gl->comp_range.length - comp_range.location;
3639 min_location = gl->comp_range.location;
3642 if (min_location >= comp_range.location + comp_range.length)
3644 comp_range.length = min_location - comp_range.location;
3645 for (i = 0; i < range.length; i++)
3647 glbuf[range.location + i].comp_range = comp_range;
3648 if (RIGHT_TO_LEFT_P)
3649 permutation[range.location + i] =
3650 range.location + range.length - i - 1;
3653 comp_range = CFRangeMake (min_location, 0);
3654 range.location += range.length;
3656 if (range.location == glyph_count)
3661 /* Then fill the remaining members. */
3662 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3665 struct mac_glyph_layout *gl;
3668 if (!RIGHT_TO_LEFT_P)
3669 gl = glbuf + range.location;
3674 src = glyph_count - 1 - range.location;
3675 dest = permutation[src];
3679 CFIndex tmp = gl->string_index;
3681 gl->string_index = glbuf[src].string_index;
3682 glbuf[src].string_index = tmp;
3685 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3687 CTRunGetPositions (ctrun, range, &position);
3688 gl->advance_delta = position.x - total_advance;
3689 gl->baseline_delta = position.y;
3690 gl->advance = (gl->advance_delta
3691 + CTRunGetTypographicBounds (ctrun, range,
3693 total_advance += gl->advance;
3696 if (RIGHT_TO_LEFT_P)
3697 xfree (permutation);
3699 #undef RIGHT_TO_LEFT_P
3701 total_glyph_count += glyph_count;
3711 /* The function below seems to cause a memory leak for the CFString
3712 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3713 10.6.3. For now, we use the NSGlyphInfo version instead. */
3714 #if USE_CT_GLYPH_INFO
3716 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3719 CGGlyph result = kCGFontIndexInvalid;
3720 UniChar characters[] = {0xfffd};
3722 CFAttributedStringRef attr_string = NULL;
3723 CTLineRef ctline = NULL;
3725 string = CFStringCreateWithCharacters (NULL, characters,
3727 / sizeof (characters[0]));
3730 CTGlyphInfoRef glyph_info =
3731 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3732 CFDictionaryRef attributes = NULL;
3736 CFStringRef keys[] = {kCTFontAttributeName,
3737 kCTGlyphInfoAttributeName};
3738 CFTypeRef values[] = {font, glyph_info};
3740 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3741 (const void **) values,
3742 sizeof (keys) / sizeof (keys[0]),
3743 &kCFTypeDictionaryKeyCallBacks,
3744 &kCFTypeDictionaryValueCallBacks);
3745 CFRelease (glyph_info);
3749 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3750 CFRelease (attributes);
3756 ctline = CTLineCreateWithAttributedString (attr_string);
3757 CFRelease (attr_string);
3761 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3763 if (CFArrayGetCount (runs) > 0)
3765 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3766 CFDictionaryRef attributes = CTRunGetAttributes (run);
3770 CTFontRef font_in_run =
3771 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3774 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3776 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3777 if (result >= CTFontGetGlyphCount (font))
3778 result = kCGFontIndexInvalid;
3789 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
3791 mac_font_family_group (CFStringRef family)
3793 if (CFStringHasPrefix (family, CFSTR ("#")))
3799 range = CFStringFind (family, CFSTR ("Apple"),
3800 kCFCompareCaseInsensitive | kCFCompareAnchored);
3801 if (range.location != kCFNotFound)
3809 mac_font_family_compare (const void *val1, const void *val2, void *context)
3811 CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2;
3814 group1 = mac_font_family_group (family1);
3815 group2 = mac_font_family_group (family2);
3816 if (group1 < group2)
3817 return kCFCompareLessThan;
3818 if (group1 > group2)
3819 return kCFCompareGreaterThan;
3820 return CFStringCompare (family1, family2, kCFCompareCaseInsensitive);
3822 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
3825 macfont_get_nsctfont (struct font *font)
3827 struct macfont_info *macfont_info = (struct macfont_info *) font;
3828 FontRef macfont = macfont_info->macfont;
3830 return (void *) macfont;
3834 mac_register_font_driver (struct frame *f)
3836 register_font_driver (&macfont_driver, f);
3839 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
3843 syms_of_macfont (void)
3845 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
3846 static struct font_driver mac_font_driver;
3848 DEFSYM (Qmac_ct, "mac-ct");
3849 macfont_driver.type = Qmac_ct;
3850 register_font_driver (&macfont_driver, NULL);
3852 DEFSYM (QCdestination, ":destination");
3853 DEFSYM (QCminspace, ":minspace");