1 /* Font driver on Mac OSX Core text.
2 Copyright (C) 2009-2015 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19 Original author: YAMAMOTO Mitsuharu
25 #include "dispextern.h"
27 #include "blockinput.h"
28 #include "character.h"
30 #include "composite.h"
39 #include <libkern/OSByteOrder.h>
41 static struct font_driver macfont_driver;
43 static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
44 static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
45 static CFArrayRef mac_ctfont_create_available_families (void);
46 static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef);
47 static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef,
49 static CFComparisonResult mac_font_family_compare (const void *,
50 const void *, void *);
51 static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef,
53 static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef);
54 static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef,
55 struct mac_glyph_layout *, CFIndex);
57 mac_font_copy_default_descriptors_for_language (CFStringRef language);
60 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
61 CFArrayRef languages);
64 static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef,
65 CTCharacterCollection,
69 struct macfont_metrics;
71 /* The actual structure for Mac font that can be cast to struct font. */
78 ScreenFontRef screen_font;
79 struct macfont_cache *cache;
80 struct macfont_metrics **metrics;
82 bool_bf synthetic_italic_p : 1;
83 bool_bf synthetic_bold_p : 1;
85 unsigned antialias : 2;
86 bool_bf color_bitmap_p : 1;
89 /* Values for the `spacing' member in `struct macfont_info'. */
93 MACFONT_SPACING_PROPORTIONAL,
95 MACFONT_SPACING_SYNTHETIC_MONO,
98 /* Values for the `antialias' member in `struct macfont_info'. */
102 MACFONT_ANTIALIAS_DEFAULT,
103 MACFONT_ANTIALIAS_OFF,
104 MACFONT_ANTIALIAS_ON,
107 enum {FONT_SLANT_SYNTHETIC_ITALIC = 200}; /* FC_SLANT_ITALIC + 100 */
108 enum {FONT_WEIGHT_SYNTHETIC_BOLD = 200}; /* FC_WEIGHT_BOLD */
109 enum {FONT_SPACING_SYNTHETIC_MONO = FONT_SPACING_MONO};
111 static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0};
112 static const CGFloat synthetic_bold_factor = 0.024;
114 static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef,
115 FontSymbolicTraits *);
116 static void macfont_store_descriptor_attributes (FontDescriptorRef,
118 static Lisp_Object macfont_descriptor_entity (FontDescriptorRef,
121 static CFStringRef macfont_create_family_with_symbol (Lisp_Object);
122 static int macfont_glyph_extents (struct font *, CGGlyph,
123 struct font_metrics *, CGFloat *, int);
124 static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object);
125 static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef,
129 static Boolean macfont_closest_traits_index_p (CFArrayRef, FontSymbolicTraits,
131 static CFDataRef mac_font_copy_uvs_table (FontRef);
132 static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char,
134 CGGlyph [], CFIndex);
136 /* From CFData to a lisp string. Always returns a unibyte string. */
139 cfdata_to_lisp (CFDataRef data)
141 CFIndex len = CFDataGetLength (data);
142 Lisp_Object result = make_uninit_string (len);
144 CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
151 /* From CFString to a lisp string. Returns a unibyte string
152 containing a UTF-8 byte sequence. */
155 cfstring_to_lisp_nodecode (CFStringRef string)
157 Lisp_Object result = Qnil;
159 const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
163 CFIndex i, length = CFStringGetLength (string);
165 for (i = 0; i < length; i++)
166 if (CFStringGetCharacterAtIndex (string, i) == 0)
170 return make_unibyte_string (s, strlen (s));
173 data = CFStringCreateExternalRepresentation (NULL, string,
174 kCFStringEncodingUTF8, '?');
177 result = cfdata_to_lisp (data);
184 /* Lisp string containing a UTF-8 byte sequence to CFString. Unlike
185 cfstring_create_with_utf8_cstring, this function preserves NUL
189 cfstring_create_with_string_noencode (Lisp_Object s)
191 CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
192 kCFStringEncodingUTF8, false);
195 /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
196 string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
197 kCFStringEncodingMacRoman, false);
203 mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
205 NSSize advancement = [(NSFont *)font advancementForGlyph:glyph];
207 return advancement.width;
211 mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection,
214 #if USE_CT_GLYPH_INFO
215 return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid);
218 CGGlyph result = kCGFontIndexInvalid;
219 NSFont *nsFont = (NSFont *) font;
220 unichar characters[] = {0xfffd};
222 [NSString stringWithCharacters:characters
223 length:ARRAYELTS (characters)];
224 NSGlyphInfo *glyphInfo =
225 [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid
226 collection:collection
228 NSDictionary *attributes =
229 [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName,
230 glyphInfo,NSGlyphInfoAttributeName,nil];
231 NSTextStorage *textStorage =
232 [[NSTextStorage alloc] initWithString:string
233 attributes:attributes];
234 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
235 NSTextContainer *textContainer = [[NSTextContainer alloc] init];
236 NSFont *fontInTextStorage;
238 [layoutManager addTextContainer:textContainer];
239 [textContainer release];
240 [textStorage addLayoutManager:layoutManager];
241 [layoutManager release];
244 (void) [layoutManager glyphRangeForTextContainer:textContainer];
246 fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0
247 effectiveRange:NULL];
248 if (fontInTextStorage == nsFont
249 || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]])
251 NSGlyph glyph = [layoutManager glyphAtIndex:0];
253 if (glyph < [nsFont numberOfGlyphs])
257 [textStorage release];
265 mac_screen_font_create_with_name (CFStringRef name, CGFloat size)
267 NSFont *result, *font;
269 font = [NSFont fontWithName:((NSString *) name) size:size];
270 result = [font screenFont];
272 return (ScreenFontRef)[result retain];
277 mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
278 CGFloat *descent, CGFloat *leading)
280 NSFont *nsFont = [(NSFont *)font printerFont];
281 NSTextStorage *textStorage;
282 NSLayoutManager *layoutManager;
283 NSTextContainer *textContainer;
285 NSPoint spaceLocation;
288 textStorage = [[NSTextStorage alloc] initWithString:@" "];
289 layoutManager = [[NSLayoutManager alloc] init];
290 textContainer = [[NSTextContainer alloc] init];
292 [textStorage setFont:nsFont];
293 [textContainer setLineFragmentPadding:0];
294 [layoutManager setUsesScreenFonts:YES];
296 [layoutManager addTextContainer:textContainer];
297 [textContainer release];
298 [textStorage addLayoutManager:layoutManager];
299 [layoutManager release];
301 if (!(textStorage && layoutManager && textContainer))
303 [textStorage release];
308 usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0
309 effectiveRange:NULL];
310 spaceLocation = [layoutManager locationForGlyphAtIndex:0];
311 [textStorage release];
313 *ascent = spaceLocation.y;
314 *descent = NSHeight (usedRect) - spaceLocation.y;
316 descender = [nsFont descender];
317 if (- descender < *descent)
319 *leading = *descent + descender;
320 *descent = - descender;
327 mac_font_shape_1 (NSFont *font, NSString *string,
328 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
333 NSTextStorage *textStorage;
334 NSLayoutManager *layoutManager;
335 NSTextContainer *textContainer;
336 NSUInteger stringLength;
337 NSPoint spaceLocation;
338 NSUInteger used, numberOfGlyphs;
340 textStorage = [[NSTextStorage alloc] initWithString:string];
341 layoutManager = [[NSLayoutManager alloc] init];
342 textContainer = [[NSTextContainer alloc] init];
344 /* Append a trailing space to measure baseline position. */
345 [textStorage appendAttributedString:([[[NSAttributedString alloc]
346 initWithString:@" "] autorelease])];
347 [textStorage setFont:font];
348 [textContainer setLineFragmentPadding:0];
349 [layoutManager setUsesScreenFonts:screen_font_p];
351 [layoutManager addTextContainer:textContainer];
352 [textContainer release];
353 [textStorage addLayoutManager:layoutManager];
354 [layoutManager release];
356 if (!(textStorage && layoutManager && textContainer))
358 [textStorage release];
363 stringLength = [string length];
366 (void) [layoutManager glyphRangeForTextContainer:textContainer];
368 spaceLocation = [layoutManager locationForGlyphAtIndex:stringLength];
370 /* Remove the appended trailing space because otherwise it may
371 generate a wrong result for a right-to-left text. */
372 [textStorage beginEditing];
373 [textStorage deleteCharactersInRange:(NSMakeRange (stringLength, 1))];
374 [textStorage endEditing];
375 (void) [layoutManager glyphRangeForTextContainer:textContainer];
378 while (i < stringLength)
381 NSFont *fontInTextStorage =
382 [textStorage attribute:NSFontAttributeName atIndex:i
383 longestEffectiveRange:&range
384 inRange:(NSMakeRange (0, stringLength))];
386 if (!(fontInTextStorage == font
387 || [[fontInTextStorage fontName] isEqualToString:[font fontName]]))
389 i = NSMaxRange (range);
391 if (i < stringLength)
392 /* Make the test `used <= glyph_len' below fail if textStorage
393 contained some fonts other than the specified one. */
394 used = glyph_len + 1;
397 NSRange range = NSMakeRange (0, stringLength);
399 range = [layoutManager glyphRangeForCharacterRange:range
400 actualCharacterRange:NULL];
401 numberOfGlyphs = NSMaxRange (range);
402 used = numberOfGlyphs;
403 for (i = 0; i < numberOfGlyphs; i++)
404 if ([layoutManager notShownAttributeForGlyphAtIndex:i])
408 if (0 < used && used <= glyph_len)
410 NSUInteger glyphIndex, prevGlyphIndex;
411 unsigned char bidiLevel;
412 NSUInteger *permutation;
413 NSRange compRange, range;
414 CGFloat totalAdvance;
417 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
420 /* For now we assume the direction is not changed within the
422 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
423 glyphs:NULL characterIndexes:NULL
424 glyphInscriptions:NULL elasticBits:NULL
425 bidiLevels:&bidiLevel];
427 permutation = xmalloc (sizeof (NSUInteger) * used);
431 #define RIGHT_TO_LEFT_P permutation
433 /* Fill the `comp_range' member of struct mac_glyph_layout, and
434 setup a permutation for right-to-left text. */
435 compRange = NSMakeRange (0, 0);
436 for (range = NSMakeRange (0, 0); NSMaxRange (range) < used;
439 struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range);
440 NSUInteger characterIndex =
441 [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
443 gl->string_index = characterIndex;
445 if (characterIndex >= NSMaxRange (compRange))
447 compRange.location = NSMaxRange (compRange);
450 NSRange characterRange =
452 rangeOfComposedCharacterSequenceAtIndex:characterIndex];
455 NSMaxRange (characterRange) - compRange.location;
456 [layoutManager glyphRangeForCharacterRange:compRange
457 actualCharacterRange:&characterRange];
458 characterIndex = NSMaxRange (characterRange) - 1;
460 while (characterIndex >= NSMaxRange (compRange));
463 for (i = 0; i < range.length; i++)
464 permutation[range.location + i] = NSMaxRange (range) - i - 1;
466 range = NSMakeRange (NSMaxRange (range), 0);
469 gl->comp_range.location = compRange.location;
470 gl->comp_range.length = compRange.length;
472 while (++glyphIndex < numberOfGlyphs)
473 if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
477 for (i = 0; i < range.length; i++)
478 permutation[range.location + i] = NSMaxRange (range) - i - 1;
480 /* Then fill the remaining members. */
481 glyphIndex = prevGlyphIndex = 0;
482 while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex])
485 if (!RIGHT_TO_LEFT_P)
492 rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs))
493 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
494 inTextContainer:textContainer rectCount:&nrects];
496 totalAdvance = NSMaxX (glyphRects[0]);
499 for (i = 0; i < used; i++)
501 struct mac_glyph_layout *gl;
503 NSUInteger nextGlyphIndex;
508 if (!RIGHT_TO_LEFT_P)
509 gl = glyph_layouts + i;
512 NSUInteger dest = permutation[i];
514 gl = glyph_layouts + dest;
517 CFIndex tmp = gl->string_index;
519 gl->string_index = glyph_layouts[i].string_index;
520 glyph_layouts[i].string_index = tmp;
523 gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex];
525 location = [layoutManager locationForGlyphAtIndex:glyphIndex];
526 gl->baseline_delta = spaceLocation.y - location.y;
528 for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs;
531 notShownAttributeForGlyphAtIndex:nextGlyphIndex])
534 if (!RIGHT_TO_LEFT_P)
538 if (prevGlyphIndex == 0)
539 glyphRange = NSMakeRange (0, nextGlyphIndex);
541 glyphRange = NSMakeRange (glyphIndex,
542 nextGlyphIndex - glyphIndex);
545 rectArrayForGlyphRange:glyphRange
546 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
547 inTextContainer:textContainer rectCount:&nrects];
548 maxX = max (NSMaxX (glyphRects[0]), totalAdvance);
549 gl->advance_delta = location.x - totalAdvance;
550 gl->advance = maxX - totalAdvance;
557 if (nextGlyphIndex == numberOfGlyphs)
558 glyphRange = NSMakeRange (prevGlyphIndex,
559 numberOfGlyphs - prevGlyphIndex);
561 glyphRange = NSMakeRange (prevGlyphIndex,
562 glyphIndex + 1 - prevGlyphIndex);
565 rectArrayForGlyphRange:glyphRange
566 withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0))
567 inTextContainer:textContainer rectCount:&nrects];
568 minX = min (NSMinX (glyphRects[0]), totalAdvance);
569 gl->advance = totalAdvance - minX;
571 gl->advance_delta = location.x - totalAdvance;
574 prevGlyphIndex = glyphIndex + 1;
575 glyphIndex = nextGlyphIndex;
581 #undef RIGHT_TO_LEFT_P
585 [textStorage release];
591 mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
592 struct mac_glyph_layout *glyph_layouts,
595 return mac_font_shape_1 ([(NSFont *)font printerFont],
597 glyph_layouts, glyph_len, YES);
601 get_cgcolor(unsigned long idx, struct frame *f)
603 NSColor *nsColor = ns_lookup_indexed_color (idx, f);
605 CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
606 NSInteger noc = [nsColor numberOfComponents];
607 CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
610 [nsColor getComponents: components];
611 cgColor = CGColorCreate (colorSpace, components);
616 #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
618 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
619 CGContextSetFillColorWithColor (context, refcol_) ; \
620 CGColorRelease (refcol_); \
622 #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
624 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
625 CGContextSetFillColorWithColor (context, refcol_); \
626 CGColorRelease (refcol_); \
628 #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
630 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
631 CGContextSetStrokeColorWithColor (context, refcol_); \
632 CGColorRelease (refcol_); \
637 /* Mac font driver. */
643 /* characters to distinguish the charset from the others */
645 /* additional constraint by language */
648 CFCharacterSetRef cf_charset;
649 CFStringRef cf_charset_string;
650 } cf_charset_table[] =
651 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
652 { "iso8859-2", { 0x00A0, 0x010E }},
653 { "iso8859-3", { 0x00A0, 0x0108 }},
654 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
655 { "iso8859-5", { 0x00A0, 0x0401 }},
656 { "iso8859-6", { 0x00A0, 0x060C }},
657 { "iso8859-7", { 0x00A0, 0x0384 }},
658 { "iso8859-8", { 0x00A0, 0x05D0 }},
659 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
660 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
661 { "iso8859-11", { 0x00A0, 0x0E01 }},
662 { "iso8859-13", { 0x00A0, 0x201C }},
663 { "iso8859-14", { 0x00A0, 0x0174 }},
664 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
665 { "iso8859-16", { 0x00A0, 0x0218}},
666 { "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
667 { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
668 { "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
669 { "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
670 { "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
671 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
672 { "cns11643.1992-3", { 0x201A9 }},
673 { "cns11643.1992-4", { 0x20057 }},
674 { "cns11643.1992-5", { 0x20000 }},
675 { "cns11643.1992-6", { 0x20003 }},
676 { "cns11643.1992-7", { 0x20055 }},
677 { "gbk-0", { 0x4E06 }, CFSTR ("zh-Hans")},
678 { "jisx0212.1990-0", { 0x4E44 }},
679 { "jisx0213.2000-1", { 0xFA10 }, CFSTR ("ja")},
680 { "jisx0213.2000-2", { 0xFA49 }},
681 { "jisx0213.2004-1", { 0x20B9F }},
682 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, CFSTR ("vi")},
683 { "tis620.2529-1", { 0x0E01 }, CFSTR ("th")},
684 { "windows-1251", { 0x0401, 0x0490 }, CFSTR ("ru")},
685 { "koi8-r", { 0x0401, 0x2219 }, CFSTR ("ru")},
686 { "mulelao-1", { 0x0E81 }, CFSTR ("lo")},
687 { "unicode-sip", { 0x20000 }},
691 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
694 CFStringRef language;
695 CFStringRef font_names[3];
696 } macfont_language_default_font_names[] = {
697 { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */
698 CFSTR ("HiraKakuPro-W3"), /* 10.4 */
700 { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */
701 CFSTR ("AppleGothic"), /* 10.4 - 10.7 */
703 { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */
704 CFSTR ("STXihei"), /* 10.4 - 10.5 */
706 { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */
707 CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */
713 static CGFloat macfont_antialias_threshold;
716 macfont_update_antialias_threshold (void)
722 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
723 kCFPreferencesCurrentApplication,
726 macfont_antialias_threshold = threshold;
729 static inline Lisp_Object
730 macfont_intern_prop_cfstring (CFStringRef cfstring)
732 Lisp_Object string = cfstring_to_lisp_nodecode (cfstring);
734 return font_intern_prop (SSDATA (string), SBYTES (string), 1);
737 static inline CFIndex
738 macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars)
749 unichars[0] = (c >> 10) + 0xD800;
750 unichars[1] = (c & 0x3FF) + 0xDC00;
757 cfnumber_get_font_symbolic_traits_value (CFNumberRef number,
758 FontSymbolicTraits *sym_traits)
762 /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac
763 OS X 10.6 when the value is greater than or equal to 1 << 31. */
764 if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value))
766 *sym_traits = (FontSymbolicTraits) sint64_value;
775 macfont_store_descriptor_attributes (FontDescriptorRef desc,
776 Lisp_Object spec_or_entity)
779 CFDictionaryRef dict;
783 str = mac_font_descriptor_copy_attribute (desc,
784 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
787 ASET (spec_or_entity, FONT_FAMILY_INDEX,
788 macfont_intern_prop_cfstring (str));
791 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
795 enum font_property_index index;
799 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
800 {{-0.4, 50}, /* light */
801 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
802 {0, 100}, /* normal */
803 {0.24, 140}, /* (semi-bold + normal) / 2 */
804 {0.4, 200}, /* bold */
805 {CGFLOAT_MAX, CGFLOAT_MAX}}},
806 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
807 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
808 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
809 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
812 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
814 num = CFDictionaryGetValue (dict, numeric_traits[i].trait);
815 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
817 CGPoint *point = numeric_traits[i].points;
819 while (point->x < floatval)
821 if (point == numeric_traits[i].points)
823 else if (point->x == CGFLOAT_MAX)
825 floatval = (point - 1)->y + ((floatval - (point - 1)->x)
826 * ((point->y - (point - 1)->y)
827 / (point->x - (point - 1)->x)));
828 FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
829 make_number (lround (floatval)));
833 num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
836 FontSymbolicTraits sym_traits;
839 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
840 spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE
841 ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
842 ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
847 num = mac_font_descriptor_copy_attribute (desc, MAC_FONT_SIZE_ATTRIBUTE);
848 if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
849 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
851 ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
857 macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
858 FontSymbolicTraits synth_sym_traits)
861 CFDictionaryRef dict;
862 FontSymbolicTraits sym_traits = 0;
865 entity = font_make_entity ();
867 ASET (entity, FONT_TYPE_INDEX, macfont_driver.type);
868 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
870 macfont_store_descriptor_attributes (desc, entity);
872 dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE);
875 CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT);
878 cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
881 if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
882 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
883 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
884 name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE);
885 font_put_extra (entity, QCfont_entity,
886 make_save_ptr_int ((void *) name, sym_traits));
887 if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC)
888 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
889 make_number (FONT_SLANT_SYNTHETIC_ITALIC));
890 if (synth_sym_traits & MAC_FONT_TRAIT_BOLD)
891 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
892 make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
893 if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
894 ASET (entity, FONT_SPACING_INDEX,
895 make_number (FONT_SPACING_SYNTHETIC_MONO));
901 macfont_create_family_with_symbol (Lisp_Object symbol)
903 static CFArrayRef families = NULL;
904 CFStringRef result = NULL, family_name;
905 int using_cache_p = 1;
906 CFComparatorFunction family_name_comparator;
908 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
909 if (family_name == NULL)
913 family_name_comparator = CTFontManagerCompareFontFamilyNames;
916 if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL)
917 == kCFCompareEqualTo)
918 result = CFSTR ("LastResort");
924 if (families == NULL)
926 families = mac_font_create_available_families ();
928 if (families == NULL)
932 count = CFArrayGetCount (families);
933 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
934 (const void *) family_name,
935 family_name_comparator, NULL);
938 CFStringRef name = CFArrayGetValueAtIndex (families, i);
940 if ((*family_name_comparator) (name, family_name, NULL)
941 == kCFCompareEqualTo)
942 result = CFRetain (name);
945 if (result || !using_cache_p)
949 CFRelease (families);
954 CFRelease (family_name);
959 #define WIDTH_FRAC_BITS (4)
960 #define WIDTH_FRAC_SCALE (2 * ((1 << (WIDTH_FRAC_BITS - 1)) - 1))
962 struct macfont_metrics
964 unsigned char lbearing_low, rbearing_low;
965 signed lbearing_high : 4, rbearing_high : 4;
966 unsigned char ascent_low, descent_low;
967 signed ascent_high : 4, descent_high : 4;
969 /* These two members are used for fixed-point representation of
970 glyph width. The `width_int' member is an integer that is
971 closest to the width. The `width_frac' member is the fractional
972 adjustment representing a value in [-.5, .5], multiplied by
973 WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
974 the advance delta for centering instead of the glyph width. */
975 signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
978 #define METRICS_VALUE(metrics, member) \
979 (((metrics)->member##_high << 8) | (metrics)->member##_low)
980 #define METRICS_SET_VALUE(metrics, member, value) \
981 do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
982 (metrics)->member##_high = tmp >> 8;} while (0)
986 METRICS_INVALID = -1, /* metrics entry is invalid */
987 METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
990 #define METRICS_STATUS(metrics) \
991 (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent))
992 #define METRICS_SET_STATUS(metrics, status) \
993 do {METRICS_SET_VALUE (metrics, ascent, 0); \
994 METRICS_SET_VALUE (metrics, descent, status);} while (0)
996 #define METRICS_NCOLS_PER_ROW (128)
997 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
998 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
1001 macfont_glyph_extents (struct font *font, CGGlyph glyph,
1002 struct font_metrics *metrics, CGFloat *advance_delta,
1003 int force_integral_p)
1005 struct macfont_info *macfont_info = (struct macfont_info *) font;
1006 FontRef macfont = macfont_info->macfont;
1008 struct macfont_metrics *cache;
1011 row = glyph / METRICS_NCOLS_PER_ROW;
1012 col = glyph % METRICS_NCOLS_PER_ROW;
1013 if (row >= macfont_info->metrics_nrows)
1015 macfont_info->metrics =
1016 xrealloc (macfont_info->metrics,
1017 sizeof (struct macfont_metrics *) * (row + 1));
1018 memset (macfont_info->metrics + macfont_info->metrics_nrows, 0,
1019 (sizeof (struct macfont_metrics *)
1020 * (row + 1 - macfont_info->metrics_nrows)));
1021 macfont_info->metrics_nrows = row + 1;
1023 if (macfont_info->metrics[row] == NULL)
1025 struct macfont_metrics *new;
1028 new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW);
1029 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
1030 METRICS_SET_STATUS (new + i, METRICS_INVALID);
1031 macfont_info->metrics[row] = new;
1033 cache = macfont_info->metrics[row] + col;
1035 if (METRICS_STATUS (cache) == METRICS_INVALID)
1039 if (macfont_info->screen_font)
1040 fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph);
1042 fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
1044 /* For synthetic mono fonts, cache->width_{int,frac} holds the
1045 advance delta value. */
1046 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1047 fwidth = (font->pixel_size - fwidth) / 2;
1048 cache->width_int = lround (fwidth);
1049 cache->width_frac = lround ((fwidth - cache->width_int)
1050 * WIDTH_FRAC_SCALE);
1051 METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
1053 if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
1054 width = font->pixel_size;
1056 width = cache->width_int;
1060 if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
1062 CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph);
1064 if (macfont_info->synthetic_italic_p)
1066 /* We assume the members a, b, c, and d in
1067 synthetic_italic_atfm are non-negative. */
1069 CGPointApplyAffineTransform (bounds.origin,
1070 synthetic_italic_atfm);
1072 CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm);
1074 if (macfont_info->synthetic_bold_p && ! force_integral_p)
1077 - synthetic_bold_factor * mac_font_get_size (macfont) / 2;
1079 bounds = CGRectInset (bounds, d, d);
1081 switch (macfont_info->spacing)
1083 case MACFONT_SPACING_PROPORTIONAL:
1084 bounds.origin.x += - (cache->width_frac
1085 / (CGFloat) (WIDTH_FRAC_SCALE * 2));
1087 case MACFONT_SPACING_MONO:
1089 case MACFONT_SPACING_SYNTHETIC_MONO:
1090 bounds.origin.x += (cache->width_int
1091 + (cache->width_frac
1092 / (CGFloat) WIDTH_FRAC_SCALE));
1095 if (bounds.size.width > 0)
1097 bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN;
1098 bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN
1099 + LCD_FONT_SMOOTHING_RIGHT_MARGIN);
1101 bounds = CGRectIntegral (bounds);
1102 METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds));
1103 METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds));
1104 METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds));
1105 METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds));
1107 metrics->lbearing = METRICS_VALUE (cache, lbearing);
1108 metrics->rbearing = METRICS_VALUE (cache, rbearing);
1109 metrics->width = width;
1110 metrics->ascent = METRICS_VALUE (cache, ascent);
1111 metrics->descent = METRICS_VALUE (cache, descent);
1116 switch (macfont_info->spacing)
1118 case MACFONT_SPACING_PROPORTIONAL:
1119 *advance_delta = (force_integral_p ? 0
1120 : - (cache->width_frac
1121 / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
1123 case MACFONT_SPACING_MONO:
1126 case MACFONT_SPACING_SYNTHETIC_MONO:
1127 *advance_delta = (force_integral_p ? cache->width_int
1129 + (cache->width_frac
1130 / (CGFloat) WIDTH_FRAC_SCALE)));
1138 static CFMutableDictionaryRef macfont_cache_dictionary;
1140 /* Threshold used in row_nkeys_or_perm. This must be less than or
1141 equal to the number of rows that are invalid as BMP (i.e., from
1142 U+D800 to U+DFFF). */
1143 #define ROW_PERM_OFFSET (8)
1145 /* The number of glyphs that can be stored in a value for a single
1146 entry of CFDictionary. */
1147 #define NGLYPHS_IN_VALUE (sizeof (void *) / sizeof (CGGlyph))
1149 struct macfont_cache
1151 int reference_count;
1152 CFCharacterSetRef cf_charset;
1154 /* The cached glyph for a BMP character c is stored in
1155 matrix[row_nkeys_or_perm[c / 256] - ROW_PERM_OFFSET][c % 256]
1156 if row_nkeys_or_perm[c / 256] >= ROW_PERM_OFFSET. */
1157 unsigned char row_nkeys_or_perm[256];
1160 /* Number of rows for which the BMP cache is allocated so far.
1161 I.e., matrix[0] ... matrix[nrows - 1] are non-NULL. */
1164 /* The cached glyph for a character c is stored as the (c %
1165 NGLYPHS_IN_VALUE)-th CGGlyph block of a value for the key (c /
1166 NGLYPHS_IN_VALUE). However, the glyph for a BMP character c is
1167 not stored here if row_nkeys_or_perm[c / 256] >=
1169 CFMutableDictionaryRef dictionary;
1173 /* UVS (Unicode Variation Sequence) subtable data, which is of
1174 type CFDataRef if available. NULL means it is not initialized
1175 yet. kCFNull means the subtable is not found and there is no
1176 suitable fallback table for this font. */
1179 /* Character collection specifying the destination of the mapping
1180 provided by `table' above. If `table' is obtained from the UVS
1181 subtable in the font cmap table, then the value of this member
1182 should be MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING. */
1183 CharacterCollection collection;
1187 static struct macfont_cache *macfont_lookup_cache (CFStringRef);
1188 static struct macfont_cache *macfont_retain_cache (struct macfont_cache *);
1189 static void macfont_release_cache (struct macfont_cache *);
1190 static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1191 static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1192 static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1193 static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1194 CharacterCollection, CGFontIndex);
1195 static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *);
1197 static struct macfont_cache *
1198 macfont_lookup_cache (CFStringRef key)
1200 struct macfont_cache *cache;
1202 if (macfont_cache_dictionary == NULL)
1204 macfont_cache_dictionary =
1205 CFDictionaryCreateMutable (NULL, 0,
1206 &kCFTypeDictionaryKeyCallBacks, NULL);
1210 cache = ((struct macfont_cache *)
1211 CFDictionaryGetValue (macfont_cache_dictionary, key));
1215 FontRef macfont = mac_font_create_with_name (key, 0);
1219 cache = xzalloc (sizeof (struct macfont_cache));
1220 /* Treat the LastResort font as if it contained glyphs for
1221 all characters. This may look too rough, but neither
1222 CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet]
1223 for this font is correct for non-BMP characters on Mac OS
1225 if (CFEqual (key, CFSTR ("LastResort")))
1227 CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1);
1230 CFCharacterSetCreateWithCharactersInRange (NULL, range);
1232 if (cache->cf_charset == NULL)
1233 cache->cf_charset = mac_font_copy_character_set (macfont);
1234 CFDictionaryAddValue (macfont_cache_dictionary, key,
1235 (const void *) cache);
1236 CFRelease (macfont);
1243 static struct macfont_cache *
1244 macfont_retain_cache (struct macfont_cache *cache)
1246 cache->reference_count++;
1252 macfont_release_cache (struct macfont_cache *cache)
1254 if (--cache->reference_count == 0)
1258 for (i = 0; i < cache->glyph.nrows; i++)
1259 xfree (cache->glyph.matrix[i]);
1260 xfree (cache->glyph.matrix);
1261 if (cache->glyph.dictionary)
1262 CFRelease (cache->glyph.dictionary);
1263 memset (&cache->glyph, 0, sizeof (cache->glyph));
1264 if (cache->uvs.table)
1265 CFRelease (cache->uvs.table);
1266 memset (&cache->uvs, 0, sizeof (cache->uvs));
1270 static CFCharacterSetRef
1271 macfont_get_cf_charset (struct font *font)
1273 struct macfont_info *macfont_info = (struct macfont_info *) font;
1275 return macfont_info->cache->cf_charset;
1278 static CFCharacterSetRef
1279 macfont_get_cf_charset_for_name (CFStringRef name)
1281 struct macfont_cache *cache = macfont_lookup_cache (name);
1283 return cache->cf_charset;
1287 macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1289 struct macfont_info *macfont_info = (struct macfont_info *) font;
1290 FontRef macfont = macfont_info->macfont;
1291 struct macfont_cache *cache = macfont_info->cache;
1293 if (c < 0xD800 || (c > 0xDFFF && c < 0x10000))
1296 int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row];
1298 if (nkeys_or_perm < ROW_PERM_OFFSET)
1300 UniChar unichars[256], ch;
1304 dispatch_queue_t queue;
1305 dispatch_group_t group = NULL;
1309 CFMutableDictionaryRef dictionary;
1310 uintptr_t key, value;
1314 if (cache->glyph.dictionary == NULL)
1315 cache->glyph.dictionary =
1316 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1317 dictionary = cache->glyph.dictionary;
1318 key = c / NGLYPHS_IN_VALUE;
1319 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1320 value = ((uintptr_t)
1321 CFDictionaryGetValue (dictionary, (const void *) key));
1322 glyph = (value >> nshifts);
1326 if (nkeys_or_perm + 1 != ROW_PERM_OFFSET)
1329 if (!mac_font_get_glyphs_for_characters (macfont, &ch,
1332 glyph = kCGFontIndexInvalid;
1335 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1;
1336 value |= ((uintptr_t) glyph << nshifts);
1337 CFDictionarySetValue (dictionary, (const void *) key,
1338 (const void *) value);
1344 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1345 group = dispatch_group_create ();
1346 dispatch_group_async (group, queue, ^{
1349 nkeys = nkeys_or_perm;
1350 for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
1351 if (CFDictionaryContainsKey (dictionary,
1352 (const void *) key))
1354 CFDictionaryRemoveValue (dictionary,
1355 (const void *) key);
1363 for (i = 0; i < 256; i++)
1366 if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch))
1367 unichars[len++] = ch;
1370 glyphs = xmalloc (sizeof (CGGlyph) * 256);
1373 mac_font_get_glyphs_for_characters (macfont, unichars,
1377 int next = unichars[len - 1] % 256;
1380 glyphs[i] = kCGFontIndexInvalid;
1383 glyphs[i] = glyphs[len];
1390 glyphs[i] = kCGFontIndexInvalid;
1392 nrows = cache->glyph.nrows;
1393 nkeys_or_perm = nrows + ROW_PERM_OFFSET;
1394 cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm;
1396 cache->glyph.matrix = xrealloc (cache->glyph.matrix,
1397 sizeof (CGGlyph *) * nrows);
1398 cache->glyph.matrix[nrows - 1] = glyphs;
1399 cache->glyph.nrows = nrows;
1403 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
1404 dispatch_release (group);
1408 return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
1412 uintptr_t key, value;
1416 if (cache->glyph.dictionary == NULL)
1417 cache->glyph.dictionary =
1418 CFDictionaryCreateMutable (NULL, 0, NULL, NULL);
1419 key = c / NGLYPHS_IN_VALUE;
1420 nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8);
1421 value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary,
1422 (const void *) key);
1423 glyph = (value >> nshifts);
1426 UniChar unichars[2];
1428 CFIndex count = macfont_store_utf32char_to_unichars (c, unichars);
1430 if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs,
1434 glyph = kCGFontIndexInvalid;
1436 value |= ((uintptr_t) glyph << nshifts);
1437 CFDictionarySetValue (cache->glyph.dictionary,
1438 (const void *) key, (const void *) value);
1446 macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection,
1449 struct macfont_info *macfont_info = (struct macfont_info *) font;
1450 FontRef macfont = macfont_info->macfont;
1453 return mac_font_get_glyph_for_cid (macfont, collection, cid);
1457 macfont_get_uvs_table (struct font *font, CharacterCollection *collection)
1459 struct macfont_info *macfont_info = (struct macfont_info *) font;
1460 FontRef macfont = macfont_info->macfont;
1461 struct macfont_cache *cache = macfont_info->cache;
1462 CFDataRef result = NULL;
1464 if (cache->uvs.table == NULL)
1466 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1467 CharacterCollection uvs_collection =
1468 MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING;
1470 if (uvs_table == NULL
1471 && mac_font_get_glyph_for_cid (macfont,
1472 MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1,
1473 6480) != kCGFontIndexInvalid)
1475 /* If the glyph for U+4E55 is accessible via its CID 6480,
1476 then we use the Adobe-Japan1 UVS table, which maps a
1477 variation sequence to a CID, as a fallback. */
1478 static CFDataRef mac_uvs_table_adobe_japan1 = NULL;
1480 if (mac_uvs_table_adobe_japan1 == NULL)
1481 mac_uvs_table_adobe_japan1 =
1482 CFDataCreateWithBytesNoCopy (NULL,
1483 mac_uvs_table_adobe_japan1_bytes,
1484 sizeof (mac_uvs_table_adobe_japan1_bytes),
1486 if (mac_uvs_table_adobe_japan1)
1488 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1489 uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1;
1492 if (uvs_table == NULL)
1493 cache->uvs.table = kCFNull;
1495 cache->uvs.table = uvs_table;
1496 cache->uvs.collection = uvs_collection;
1499 if (cache->uvs.table != kCFNull)
1501 result = cache->uvs.table;
1502 *collection = cache->uvs.collection;
1508 static Lisp_Object macfont_get_cache (struct frame *);
1509 static Lisp_Object macfont_list (struct frame *, Lisp_Object);
1510 static Lisp_Object macfont_match (struct frame *, Lisp_Object);
1511 static Lisp_Object macfont_list_family (struct frame *);
1512 static void macfont_free_entity (Lisp_Object);
1513 static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
1514 static void macfont_close (struct font *);
1515 static int macfont_has_char (Lisp_Object, int);
1516 static unsigned macfont_encode_char (struct font *, int);
1517 static void macfont_text_extents (struct font *, unsigned int *, int,
1518 struct font_metrics *);
1519 static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1520 static Lisp_Object macfont_shape (Lisp_Object);
1521 static int macfont_variation_glyphs (struct font *, int c,
1522 unsigned variations[256]);
1523 static void macfont_filter_properties (Lisp_Object, Lisp_Object);
1525 static struct font_driver macfont_driver =
1527 LISP_INITIALLY_ZERO, /* Qmac_ct */
1528 0, /* case insensitive */
1532 macfont_list_family,
1533 macfont_free_entity,
1536 NULL, /* prepare_face */
1537 NULL, /* done_face */
1539 macfont_encode_char,
1540 macfont_text_extents,
1542 NULL, /* get_bitmap */
1543 NULL, /* free_bitmap */
1544 NULL, /* anchor_point */
1545 NULL, /* otf_capability */
1546 NULL, /* otf_drive */
1547 NULL, /* start_for_frame */
1548 NULL, /* end_for_frame */
1551 macfont_variation_glyphs,
1552 macfont_filter_properties,
1556 macfont_get_cache (struct frame * f)
1558 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
1560 return (dpyinfo->name_list_element);
1564 macfont_get_charset (Lisp_Object registry)
1566 char *str = SSDATA (SYMBOL_NAME (registry));
1567 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
1571 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
1575 else if (str[i] == '*')
1582 regexp = make_unibyte_string (re, j);
1583 for (i = 0; cf_charset_table[i].name; i++)
1584 if (fast_c_string_match_ignore_case
1585 (regexp, cf_charset_table[i].name,
1586 strlen (cf_charset_table[i].name)) >= 0)
1588 if (! cf_charset_table[i].name)
1590 if (! cf_charset_table[i].cf_charset)
1592 int *uniquifier = cf_charset_table[i].uniquifier;
1593 UniChar *unichars = alloca (sizeof (cf_charset_table[i].uniquifier));
1596 CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL);
1600 for (j = 0; uniquifier[j]; j++)
1602 count += macfont_store_utf32char_to_unichars (uniquifier[j],
1604 CFCharacterSetAddCharactersInRange (charset,
1605 CFRangeMake (uniquifier[j], 1));
1608 string = CFStringCreateWithCharacters (NULL, unichars, count);
1611 CFRelease (charset);
1614 cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL,
1616 CFRelease (charset);
1617 /* CFCharacterSetCreateWithCharactersInString does not handle
1618 surrogate pairs properly as of Mac OS X 10.5. */
1619 cf_charset_table[i].cf_charset_string = string;
1627 unsigned int script_tag, langsys_tag;
1629 unsigned int *features[2];
1632 #define OTF_SYM_TAG(SYM, TAG) \
1634 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
1635 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
1638 #define OTF_TAG_STR(TAG, P) \
1640 (P)[0] = (char) (TAG >> 24); \
1641 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
1642 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
1643 (P)[3] = (char) (TAG & 0xFF); \
1647 static struct OpenTypeSpec *
1648 macfont_get_open_type_spec (Lisp_Object otf_spec)
1650 struct OpenTypeSpec *spec = xmalloc (sizeof *spec);
1657 spec->script = XCAR (otf_spec);
1658 if (! NILP (spec->script))
1660 OTF_SYM_TAG (spec->script, spec->script_tag);
1661 val = assq_no_quit (spec->script, Votf_script_alist);
1662 if (CONSP (val) && SYMBOLP (XCDR (val)))
1663 spec->script = XCDR (val);
1665 spec->script = Qnil;
1668 spec->script_tag = 0x44464C54; /* "DFLT" */
1669 otf_spec = XCDR (otf_spec);
1670 spec->langsys_tag = 0;
1671 if (! NILP (otf_spec))
1673 val = XCAR (otf_spec);
1675 OTF_SYM_TAG (val, spec->langsys_tag);
1676 otf_spec = XCDR (otf_spec);
1678 spec->nfeatures[0] = spec->nfeatures[1] = 0;
1679 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
1683 val = XCAR (otf_spec);
1686 len = Flength (val);
1688 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
1690 : malloc (XINT (len) * sizeof *spec->features[i]));
1691 if (! spec->features[i])
1693 if (i > 0 && spec->features[0])
1694 free (spec->features[0]);
1698 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
1700 if (NILP (XCAR (val)))
1706 OTF_SYM_TAG (XCAR (val), tag);
1707 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
1710 spec->nfeatures[i] = j;
1715 static CFMutableDictionaryRef
1716 macfont_create_attributes_with_spec (Lisp_Object spec)
1718 Lisp_Object tmp, extra;
1719 CFMutableArrayRef langarray = NULL;
1720 CFCharacterSetRef charset = NULL;
1721 CFStringRef charset_string = NULL;
1722 CFMutableDictionaryRef attributes = NULL, traits = NULL;
1723 Lisp_Object script = Qnil;
1724 Lisp_Object registry;
1725 int cf_charset_idx, i;
1726 struct OpenTypeSpec *otspec = NULL;
1728 enum font_property_index index;
1731 } numeric_traits[] =
1732 {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT,
1733 {{-0.4, 50}, /* light */
1734 {-0.24, 87.5}, /* (semi-light + normal) / 2 */
1735 {0, 100}, /* normal */
1736 {0.24, 140}, /* (semi-bold + normal) / 2 */
1737 {0.4, 200}, /* bold */
1738 {CGFLOAT_MAX, CGFLOAT_MAX}}},
1739 {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT,
1740 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
1741 {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT,
1742 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
1744 registry = AREF (spec, FONT_REGISTRY_INDEX);
1746 || EQ (registry, Qascii_0)
1747 || EQ (registry, Qiso10646_1)
1748 || EQ (registry, Qunicode_bmp))
1749 cf_charset_idx = -1;
1754 cf_charset_idx = macfont_get_charset (registry);
1755 if (cf_charset_idx < 0)
1757 charset = cf_charset_table[cf_charset_idx].cf_charset;
1758 charset_string = cf_charset_table[cf_charset_idx].cf_charset_string;
1759 lang = cf_charset_table[cf_charset_idx].lang;
1762 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1765 CFArrayAppendValue (langarray, lang);
1769 for (extra = AREF (spec, FONT_EXTRA_INDEX);
1770 CONSP (extra); extra = XCDR (extra))
1772 Lisp_Object key, val;
1775 key = XCAR (tmp), val = XCDR (tmp);
1776 if (EQ (key, QClang))
1779 langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
1784 for (; CONSP (val); val = XCDR (val))
1785 if (SYMBOLP (XCAR (val)))
1788 cfstring_create_with_string_noencode (SYMBOL_NAME
1793 CFArrayAppendValue (langarray, lang);
1797 else if (EQ (key, QCotf))
1799 otspec = macfont_get_open_type_spec (val);
1802 script = otspec->script;
1804 else if (EQ (key, QCscript))
1808 if (! NILP (script) && ! charset)
1810 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
1812 if (CONSP (chars) && CONSP (CDR (chars)))
1814 CFMutableStringRef string = CFStringCreateMutable (NULL, 0);
1815 CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL);
1817 if (! string || !cs)
1825 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
1826 if (CHARACTERP (XCAR (chars)))
1828 UniChar unichars[2];
1830 macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
1832 CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
1834 CFStringAppendCharacters (string, unichars, count);
1835 CFCharacterSetAddCharactersInRange (cs, range);
1838 /* CFCharacterSetCreateWithCharactersInString does not
1839 handle surrogate pairs properly as of Mac OS X 10.5. */
1840 charset_string = string;
1844 attributes = CFDictionaryCreateMutable (NULL, 0,
1845 &kCFTypeDictionaryKeyCallBacks,
1846 &kCFTypeDictionaryValueCallBacks);
1850 tmp = AREF (spec, FONT_FAMILY_INDEX);
1851 if (SYMBOLP (tmp) && ! NILP (tmp))
1853 CFStringRef family = macfont_create_family_with_symbol (tmp);
1857 CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
1862 traits = CFDictionaryCreateMutable (NULL, 4,
1863 &kCFTypeDictionaryKeyCallBacks,
1864 &kCFTypeDictionaryValueCallBacks);
1868 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
1870 tmp = AREF (spec, numeric_traits[i].index);
1873 CGPoint *point = numeric_traits[i].points;
1874 CGFloat floatval = (XINT (tmp) >> 8); // XXX
1877 while (point->y < floatval)
1879 if (point == numeric_traits[i].points)
1881 else if (point->y == CGFLOAT_MAX)
1883 floatval = (point - 1)->x + ((floatval - (point - 1)->y)
1884 * ((point->x - (point - 1)->x)
1885 / (point->y - (point - 1)->y)));
1888 else if (floatval < -1.0)
1890 num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval);
1893 CFDictionaryAddValue (traits, numeric_traits[i].trait, num);
1897 if (CFDictionaryGetCount (traits))
1898 CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits);
1901 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE,
1904 CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE,
1907 CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray);
1914 CFRelease (attributes);
1919 if (langarray) CFRelease (langarray);
1920 if (charset && cf_charset_idx < 0) CFRelease (charset);
1921 if (charset_string && cf_charset_idx < 0) CFRelease (charset_string);
1922 if (traits) CFRelease (traits);
1925 if (otspec->nfeatures[0] > 0)
1926 free (otspec->features[0]);
1927 if (otspec->nfeatures[1] > 0)
1928 free (otspec->features[1]);
1936 macfont_supports_charset_and_languages_p (FontDescriptorRef desc,
1937 CFCharacterSetRef charset,
1939 CFArrayRef languages)
1941 Boolean result = true;
1943 if (charset || VECTORP (chars))
1945 CFCharacterSetRef desc_charset =
1946 mac_font_descriptor_copy_attribute (desc,
1947 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
1949 if (desc_charset == NULL)
1954 result = CFCharacterSetIsSupersetOfSet (desc_charset, charset);
1955 else /* VECTORP (chars) */
1959 for (j = 0; j < ASIZE (chars); j++)
1960 if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
1961 && CFCharacterSetIsLongCharacterMember (desc_charset,
1962 XFASTINT (AREF (chars, j))))
1964 if (j == ASIZE (chars))
1967 CFRelease (desc_charset);
1970 if (result && languages)
1971 result = mac_font_descriptor_supports_languages (desc, languages);
1977 macfont_traits_distance (FontSymbolicTraits sym_traits1,
1978 FontSymbolicTraits sym_traits2)
1980 FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2);
1983 /* We prefer synthetic bold of italic to synthetic italic of bold
1984 when both bold and italic are available but bold-italic is not
1986 if (diff & MAC_FONT_TRAIT_BOLD)
1987 distance |= (1 << 0);
1988 if (diff & MAC_FONT_TRAIT_ITALIC)
1989 distance |= (1 << 1);
1990 if (diff & MAC_FONT_TRAIT_MONO_SPACE)
1991 distance |= (1 << 2);
1997 macfont_closest_traits_index_p (CFArrayRef traits_array,
1998 FontSymbolicTraits target,
2001 CFIndex i, count = CFArrayGetCount (traits_array);
2002 FontSymbolicTraits traits;
2005 traits = ((FontSymbolicTraits) (uintptr_t)
2006 CFArrayGetValueAtIndex (traits_array, index));
2007 my_distance = macfont_traits_distance (target, traits);
2009 for (i = 0; i < count; i++)
2012 traits = ((FontSymbolicTraits) (uintptr_t)
2013 CFArrayGetValueAtIndex (traits_array, i));
2014 if (macfont_traits_distance (target, traits) < my_distance)
2022 macfont_list (struct frame *f, Lisp_Object spec)
2024 Lisp_Object val = Qnil, family, extra;
2026 CFStringRef family_name = NULL;
2027 CFMutableDictionaryRef attributes = NULL, traits;
2028 Lisp_Object chars = Qnil;
2030 FontSymbolicTraits synth_sym_traits = 0;
2031 CFArrayRef families;
2032 CFIndex families_count;
2033 CFCharacterSetRef charset = NULL;
2034 CFArrayRef languages = NULL;
2038 family = AREF (spec, FONT_FAMILY_INDEX);
2039 if (! NILP (family))
2041 family_name = macfont_create_family_with_symbol (family);
2042 if (family_name == NULL)
2046 attributes = macfont_create_attributes_with_spec (spec);
2050 languages = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2052 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
2053 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
2055 traits = ((CFMutableDictionaryRef)
2056 CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE));
2058 n = FONT_SLANT_NUMERIC (spec);
2059 if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC)
2061 synth_sym_traits |= MAC_FONT_TRAIT_ITALIC;
2063 CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT);
2066 n = FONT_WEIGHT_NUMERIC (spec);
2067 if (n < 0 || n == FONT_WEIGHT_SYNTHETIC_BOLD)
2069 synth_sym_traits |= MAC_FONT_TRAIT_BOLD;
2071 CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT);
2075 && (spacing < 0 || spacing == FONT_SPACING_SYNTHETIC_MONO))
2077 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
2079 if (CFStringHasPrefix (language, CFSTR ("ja"))
2080 || CFStringHasPrefix (language, CFSTR ("ko"))
2081 || CFStringHasPrefix (language, CFSTR ("zh")))
2082 synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE;
2085 /* Create array of families. */
2087 families = CFArrayCreate (NULL, (const void **) &family_name,
2088 1, &kCFTypeArrayCallBacks);
2091 CFStringRef pref_family;
2092 CFIndex families_count, pref_family_index = -1;
2094 families = mac_font_create_available_families ();
2095 if (families == NULL)
2098 families_count = CFArrayGetCount (families);
2100 /* Move preferred family to the front if exists. */
2102 mac_font_create_preferred_family_for_attributes (attributes);
2106 CFArrayGetFirstIndexOfValue (families,
2107 CFRangeMake (0, families_count),
2109 CFRelease (pref_family);
2111 if (pref_family_index > 0)
2113 CFMutableArrayRef mutable_families =
2114 CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks);
2116 if (mutable_families)
2118 CFArrayAppendValue (mutable_families,
2119 CFArrayGetValueAtIndex (families,
2120 pref_family_index));
2121 CFArrayAppendArray (mutable_families, families,
2122 CFRangeMake (0, pref_family_index));
2123 if (pref_family_index + 1 < families_count)
2124 CFArrayAppendArray (mutable_families, families,
2125 CFRangeMake (pref_family_index + 1,
2127 - (pref_family_index + 1)));
2128 CFRelease (families);
2129 families = mutable_families;
2134 charset = CFDictionaryGetValue (attributes,
2135 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2139 CFDictionaryRemoveValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE);
2143 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
2146 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
2147 if (CONSP (val) && VECTORP (XCDR (val)))
2155 CFRetain (languages);
2156 CFDictionaryRemoveValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
2160 extra = AREF (spec, FONT_EXTRA_INDEX);
2161 families_count = CFArrayGetCount (families);
2162 for (i = 0; i < families_count; i++)
2164 CFStringRef family_name = CFArrayGetValueAtIndex (families, i);
2165 FontDescriptorRef pat_desc;
2167 CFIndex descs_count;
2168 CFMutableArrayRef filtered_descs, traits_array;
2172 CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE,
2174 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2178 /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X
2179 10.7 returns NULL if pat_desc represents the LastResort font.
2180 So we use CTFontDescriptorCreateMatchingFontDescriptor (no
2181 trailing "s") for such a font. */
2182 if (!CFEqual (family_name, CFSTR ("LastResort")))
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 || macfont_closest_traits_index_p (traits_array,
2310 (sym_traits | synth),
2313 entity = macfont_descriptor_entity (desc, extra, synth);
2314 if (! NILP (entity))
2315 val = Fcons (entity, val);
2320 CFRelease (traits_array);
2324 CFRelease (families);
2325 val = Fnreverse (val);
2331 FONT_ADD_LOG ("macfont-list", spec, val);
2332 if (charset) CFRelease (charset);
2333 if (languages) CFRelease (languages);
2334 if (attributes) CFRelease (attributes);
2335 if (family_name) CFRelease (family_name);
2343 macfont_match (struct frame * frame, Lisp_Object spec)
2345 Lisp_Object entity = Qnil;
2346 CFMutableDictionaryRef attributes;
2347 FontDescriptorRef pat_desc = NULL, desc = NULL;
2351 attributes = macfont_create_attributes_with_spec (spec);
2354 pat_desc = mac_font_descriptor_create_with_attributes (attributes);
2355 CFRelease (attributes);
2359 desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc,
2361 CFRelease (pat_desc);
2365 entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX),
2371 FONT_ADD_LOG ("macfont-match", spec, entity);
2376 macfont_list_family (struct frame *frame)
2378 Lisp_Object list = Qnil;
2379 CFArrayRef families;
2383 families = mac_font_create_available_families ();
2386 CFIndex i, count = CFArrayGetCount (families);
2388 for (i = 0; i < count; i++)
2389 list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list);
2390 CFRelease (families);
2399 macfont_free_entity (Lisp_Object entity)
2401 Lisp_Object val = assq_no_quit (QCfont_entity,
2402 AREF (entity, FONT_EXTRA_INDEX));
2403 CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
2411 macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2413 Lisp_Object val, font_object;
2414 CFStringRef font_name;
2415 struct macfont_info *macfont_info = NULL;
2419 FontSymbolicTraits sym_traits;
2421 int len, i, total_width;
2423 CGFloat ascent, descent, leading;
2425 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
2427 || XTYPE (XCDR (val)) != Lisp_Misc
2428 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
2430 font_name = XSAVE_POINTER (XCDR (val), 0);
2431 sym_traits = XSAVE_INTEGER (XCDR (val), 1);
2433 size = XINT (AREF (entity, FONT_SIZE_INDEX));
2438 macfont = mac_font_create_with_name (font_name, size);
2441 int fontsize = (int) [((NSFont *) macfont) pointSize];
2442 if (fontsize != size) size = fontsize;
2448 font_object = font_build_object (VECSIZE (struct macfont_info),
2449 Qmac_ct, entity, size);
2450 font = XFONT_OBJECT (font_object);
2451 font->pixel_size = size;
2452 font->driver = &macfont_driver;
2453 font->encoding_charset = font->repertory_charset = -1;
2457 macfont_info = (struct macfont_info *) font;
2458 macfont_info->macfont = macfont;
2459 macfont_info->cgfont = mac_font_copy_graphics_font (macfont);
2461 val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
2462 if (CONSP (val) && EQ (XCDR (val), make_number (1)))
2463 macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
2466 macfont_info->screen_font = NULL;
2467 macfont_info->cache = macfont_lookup_cache (font_name);
2468 macfont_retain_cache (macfont_info->cache);
2469 macfont_info->metrics = NULL;
2470 macfont_info->metrics_nrows = 0;
2471 macfont_info->synthetic_italic_p = 0;
2472 macfont_info->synthetic_bold_p = 0;
2473 macfont_info->spacing = MACFONT_SPACING_PROPORTIONAL;
2474 macfont_info->antialias = MACFONT_ANTIALIAS_DEFAULT;
2475 if (!(sym_traits & MAC_FONT_TRAIT_ITALIC)
2476 && FONT_SLANT_NUMERIC (entity) == FONT_SLANT_SYNTHETIC_ITALIC)
2477 macfont_info->synthetic_italic_p = 1;
2478 if (!(sym_traits & MAC_FONT_TRAIT_BOLD)
2479 && FONT_WEIGHT_NUMERIC (entity) == FONT_WEIGHT_SYNTHETIC_BOLD)
2480 macfont_info->synthetic_bold_p = 1;
2481 if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE)
2482 macfont_info->spacing = MACFONT_SPACING_MONO;
2483 else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
2484 && (XINT (AREF (entity, FONT_SPACING_INDEX))
2485 == FONT_SPACING_SYNTHETIC_MONO))
2486 macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
2487 if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
2488 macfont_info->antialias = MACFONT_ANTIALIAS_ON;
2491 val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX));
2493 macfont_info->antialias =
2494 NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON;
2496 macfont_info->color_bitmap_p = 0;
2497 if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS)
2498 macfont_info->color_bitmap_p = 1;
2500 glyph = macfont_get_glyph_for_character (font, ' ');
2501 if (glyph != kCGFontIndexInvalid)
2502 font->space_width = macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2504 /* dirty workaround */
2505 font->space_width = pixel_size;
2507 total_width = font->space_width;
2508 for (i = 1; i < 95; i++)
2510 glyph = macfont_get_glyph_for_character (font, ' ' + i);
2511 if (glyph == kCGFontIndexInvalid)
2513 total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0);
2516 font->average_width = total_width / 95;
2518 font->average_width = font->space_width; /* XXX */
2520 if (!(macfont_info->screen_font
2521 && mac_screen_font_get_metrics (macfont_info->screen_font,
2522 &ascent, &descent, &leading)))
2524 CFStringRef family_name;
2526 ascent = mac_font_get_ascent (macfont);
2527 descent = mac_font_get_descent (macfont);
2528 leading = mac_font_get_leading (macfont);
2529 /* AppKit and WebKit do some adjustment to the heights of
2530 Courier, Helvetica, and Times. */
2531 family_name = mac_font_copy_family_name (macfont);
2534 if (CFEqual (family_name, CFSTR ("Courier"))
2535 || CFEqual (family_name, CFSTR ("Helvetica"))
2536 || CFEqual (family_name, CFSTR ("Times")))
2537 ascent += (ascent + descent) * .15f;
2538 else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino")))
2543 CFRelease (family_name);
2546 font->ascent = ascent + 0.5f;
2547 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
2548 if (CONSP (val) && !NILP (XCDR (val)))
2549 font->descent = descent + 0.5f;
2551 font->descent = descent + leading + 0.5f;
2552 font->height = font->ascent + font->descent;
2554 font->underline_position = - mac_font_get_underline_position (macfont) + 0.5f;
2555 font->underline_thickness = mac_font_get_underline_thickness (macfont) + 0.5f;
2559 /* Unfortunately Xft doesn't provide a way to get minimum char
2560 width. So, we use space_width instead. */
2561 font->min_width = font->max_width = font->space_width; /* XXX */
2563 font->baseline_offset = 0;
2564 font->relative_compose = 0;
2565 font->default_ascent = 0;
2566 font->vertical_centering = 0;
2572 macfont_close (struct font *font)
2574 struct macfont_info *macfont_info = (struct macfont_info *) font;
2576 if (macfont_info->cache)
2581 CFRelease (macfont_info->macfont);
2582 CGFontRelease (macfont_info->cgfont);
2583 if (macfont_info->screen_font)
2584 CFRelease (macfont_info->screen_font);
2585 macfont_release_cache (macfont_info->cache);
2586 for (i = 0; i < macfont_info->metrics_nrows; i++)
2587 if (macfont_info->metrics[i])
2588 xfree (macfont_info->metrics[i]);
2589 if (macfont_info->metrics)
2590 xfree (macfont_info->metrics);
2591 macfont_info->cache = NULL;
2597 macfont_has_char (Lisp_Object font, int c)
2600 CFCharacterSetRef charset;
2603 if (FONT_ENTITY_P (font))
2608 val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
2610 name = XSAVE_POINTER (val, 0);
2611 charset = macfont_get_cf_charset_for_name (name);
2614 charset = macfont_get_cf_charset (XFONT_OBJECT (font));
2616 result = CFCharacterSetIsLongCharacterMember (charset, c);
2623 macfont_encode_char (struct font *font, int c)
2625 struct macfont_info *macfont_info = (struct macfont_info *) font;
2629 glyph = macfont_get_glyph_for_character (font, c);
2632 return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE;
2636 macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
2637 struct font_metrics *metrics)
2642 width = macfont_glyph_extents (font, code[0], metrics, NULL, 0);
2643 for (i = 1; i < nglyphs; i++)
2645 struct font_metrics m;
2646 int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL,
2651 if (width + m.lbearing < metrics->lbearing)
2652 metrics->lbearing = width + m.lbearing;
2653 if (width + m.rbearing > metrics->rbearing)
2654 metrics->rbearing = width + m.rbearing;
2655 if (m.ascent > metrics->ascent)
2656 metrics->ascent = m.ascent;
2657 if (m.descent > metrics->descent)
2658 metrics->descent = m.descent;
2665 metrics->width = width;
2669 macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2670 bool with_background)
2672 struct frame * f = s->f;
2673 struct macfont_info *macfont_info = (struct macfont_info *) s->font;
2674 CGRect background_rect;
2675 CGPoint text_position;
2678 CGFloat font_size = mac_font_get_size (macfont_info->macfont);
2679 bool no_antialias_p =
2680 (NILP (ns_antialias_text)
2681 || macfont_info->antialias == MACFONT_ANTIALIAS_OFF
2682 || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT
2683 && font_size <= macfont_antialias_threshold));
2684 int len = to - from;
2685 struct face *face = s->face;
2686 CGContextRef context;
2690 if (with_background)
2691 background_rect = CGRectMake (x, y - FONT_BASE (s->font),
2692 s->width, FONT_HEIGHT (s->font));
2694 background_rect = CGRectNull;
2696 text_position = CGPointMake (x, -y);
2697 glyphs = xmalloc (sizeof (CGGlyph) * len);
2699 CGFloat advance_delta = 0;
2701 CGFloat total_width = 0;
2703 positions = xmalloc (sizeof (CGPoint) * len);
2704 for (i = 0; i < len; i++)
2708 glyphs[i] = s->char2b[from + i];
2709 width = (s->padding_p ? 1
2710 : macfont_glyph_extents (s->font, glyphs[i],
2711 NULL, &advance_delta,
2713 positions[i].x = total_width + advance_delta;
2715 total_width += width;
2719 context = [[NSGraphicsContext currentContext] graphicsPort];
2720 CGContextSaveGState (context);
2722 if (!CGRectIsNull (background_rect))
2724 if (s->hl == DRAW_MOUSE_FACE)
2726 face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
2728 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2730 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
2731 CGContextFillRects (context, &background_rect, 1);
2734 if (macfont_info->cgfont)
2736 CGAffineTransform atfm;
2738 CGContextScaleCTM (context, 1, -1);
2739 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
2740 if (macfont_info->synthetic_italic_p)
2741 atfm = synthetic_italic_atfm;
2743 atfm = CGAffineTransformIdentity;
2744 if (macfont_info->synthetic_bold_p && ! no_antialias_p)
2746 CGContextSetTextDrawingMode (context, kCGTextFillStroke);
2747 CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
2748 CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
2751 CGContextSetShouldAntialias (context, false);
2753 CGContextSetTextMatrix (context, atfm);
2754 CGContextSetTextPosition (context, text_position.x, text_position.y);
2756 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2757 if (macfont_info->color_bitmap_p
2758 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
2759 && CTFontDrawGlyphs != NULL
2765 CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len,
2770 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
2772 CGContextSetFont (context, macfont_info->cgfont);
2773 CGContextSetFontSize (context, font_size);
2774 CGContextShowGlyphsAtPositions (context, glyphs, positions, len);
2781 CGContextRestoreGState (context);
2789 macfont_shape (Lisp_Object lgstring)
2791 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2792 struct macfont_info *macfont_info = (struct macfont_info *) font;
2793 FontRef macfont = macfont_info->macfont;
2794 ptrdiff_t glyph_len, len, i, j;
2797 CFIndex *nonbmp_indices;
2800 struct mac_glyph_layout *glyph_layouts;
2802 glyph_len = LGSTRING_GLYPH_LEN (lgstring);
2804 for (i = 0; i < glyph_len; i++)
2806 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2810 if (LGLYPH_CHAR (lglyph) >= 0x10000)
2816 if (INT_MAX / 2 < len)
2817 memory_full (SIZE_MAX);
2819 unichars = alloca (sizeof (UniChar) * (len + nonbmp_len));
2820 nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1));
2821 for (i = j = 0; i < len; i++)
2823 UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
2825 if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1)
2827 nonbmp_indices[j] = i + j;
2831 nonbmp_indices[j] = len + j; /* sentinel */
2835 string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len,
2839 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2840 if (macfont_info->screen_font)
2841 used = mac_screen_font_shape (macfont_info->screen_font, string,
2842 glyph_layouts, glyph_len);
2844 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
2855 for (i = 0; i < used; i++)
2857 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2858 struct mac_glyph_layout *gl = glyph_layouts + i;
2860 struct font_metrics metrics;
2861 int xoff, yoff, wadjust;
2865 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2866 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2869 from = gl->comp_range.location;
2870 /* Convert UTF-16 index to UTF-32. */
2872 while (nonbmp_indices[j] < from)
2875 LGLYPH_SET_FROM (lglyph, from);
2877 to = gl->comp_range.location + gl->comp_range.length;
2878 /* Convert UTF-16 index to UTF-32. */
2879 while (nonbmp_indices[j] < to)
2882 LGLYPH_SET_TO (lglyph, to - 1);
2884 /* LGLYPH_CHAR is used in `describe-char' for checking whether
2885 the composition is trivial. */
2889 if (unichars[gl->string_index] >= 0xD800
2890 && unichars[gl->string_index] < 0xDC00)
2891 c = (((unichars[gl->string_index] - 0xD800) << 10)
2892 + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000);
2894 c = unichars[gl->string_index];
2895 if (macfont_get_glyph_for_character (font, c) != gl->glyph_id)
2897 LGLYPH_SET_CHAR (lglyph, c);
2901 unsigned long cc = gl->glyph_id;
2902 LGLYPH_SET_CODE (lglyph, cc);
2905 macfont_glyph_extents (font, gl->glyph_id, &metrics, NULL, 0);
2906 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2907 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2908 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2909 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2910 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2912 xoff = lround (gl->advance_delta);
2913 yoff = lround (- gl->baseline_delta);
2914 wadjust = lround (gl->advance);
2915 if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
2919 vec = Fmake_vector (make_number (3), Qnil);
2920 ASET (vec, 0, make_number (xoff));
2921 ASET (vec, 1, make_number (yoff));
2922 ASET (vec, 2, make_number (wadjust));
2923 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2929 return make_number (used);
2932 /* Structures for the UVS subtable (format 14) in the cmap table. */
2933 typedef UInt8 UINT24[3];
2935 #pragma pack(push, 1)
2936 struct variation_selector_record
2938 UINT24 var_selector;
2939 UInt32 default_uvs_offset, non_default_uvs_offset;
2944 UInt32 length, num_var_selector_records;
2945 struct variation_selector_record variation_selector_records[1];
2947 #define SIZEOF_UVS_TABLE_HEADER \
2948 (sizeof (struct uvs_table) - sizeof (struct variation_selector_record))
2950 struct unicode_value_range
2952 UINT24 start_unicode_value;
2953 UInt8 additional_count;
2955 struct default_uvs_table {
2956 UInt32 num_unicode_value_ranges;
2957 struct unicode_value_range unicode_value_ranges[1];
2959 #define SIZEOF_DEFAULT_UVS_TABLE_HEADER \
2960 (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range))
2964 UINT24 unicode_value;
2967 struct non_default_uvs_table
2969 UInt32 num_uvs_mappings;
2970 struct uvs_mapping uvs_mappings[1];
2972 #define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \
2973 (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping))
2976 /* Read big endian values. The argument LVAL must be an lvalue. */
2977 /* I suppose OSReadBigInt* takes care of unaligned data. At least, we
2978 can find "... = OSReadBigInt32(cdb, 2);" followed by "... =
2979 OSReadBigInt16(cdb, 7);" in a sample code by Apple. */
2980 #define BUINT8_VALUE(lval) (*((UInt8 *) &(lval)))
2981 #define BUINT16_VALUE(lval) OSReadBigInt16 (&(lval), 0)
2982 /* Succeeding one byte should also be accessible. */
2983 #define BUINT24_VALUE(lval) (OSReadBigInt32 (&(lval), 0) >> 8)
2984 #define BUINT32_VALUE(lval) OSReadBigInt32 (&(lval), 0)
2986 /* Return UVS subtable for the specified FONT. If the subtable is not
2987 found or ill-formatted, then return NULL. */
2990 mac_font_copy_uvs_table (FontRef font)
2992 CFDataRef cmap_table, uvs_table = NULL;
2994 cmap_table = mac_font_copy_non_synthetic_table (font, cmapFontTableTag);
2997 sfntCMapHeader *cmap = (sfntCMapHeader *) CFDataGetBytePtr (cmap_table);
2998 struct uvs_table *uvs;
2999 struct variation_selector_record *records;
3000 UInt32 cmap_len, ntables, i, uvs_offset, uvs_len, nrecords;
3003 if (CFDataGetLength (cmap_table) > UINT32_MAX)
3007 cmap_len = CFDataGetLength (cmap_table);
3008 if (sizeof_sfntCMapHeader > cmap_len)
3011 ntables = BUINT16_VALUE (cmap->numTables);
3012 if (ntables > ((cmap_len - sizeof_sfntCMapHeader)
3013 / sizeof_sfntCMapEncoding))
3016 for (i = 0; i < ntables; i++)
3017 if ((BUINT16_VALUE (cmap->encoding[i].platformID)
3018 == kFontUnicodePlatform)
3019 && (BUINT16_VALUE (cmap->encoding[i].scriptID)
3020 == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */
3022 uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset);
3026 || uvs_offset > cmap_len
3027 || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset)
3030 uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset);
3031 uvs_len = BUINT32_VALUE (uvs->length);
3032 if (uvs_len > cmap_len - uvs_offset
3033 || SIZEOF_UVS_TABLE_HEADER > uvs_len)
3036 if (BUINT16_VALUE (uvs->format) != 14)
3039 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3040 if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER)
3041 / sizeof (struct variation_selector_record)))
3044 records = uvs->variation_selector_records;
3045 for (i = 0; i < nrecords; i++)
3047 UInt32 default_uvs_offset, non_default_uvs_offset;
3049 default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset);
3050 if (default_uvs_offset)
3052 struct default_uvs_table *default_uvs;
3055 if (default_uvs_offset > uvs_len
3056 || (SIZEOF_DEFAULT_UVS_TABLE_HEADER
3057 > uvs_len - default_uvs_offset))
3060 default_uvs = ((struct default_uvs_table *)
3061 ((UInt8 *) uvs + default_uvs_offset));
3062 nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3063 if (nranges > ((uvs_len - default_uvs_offset
3064 - SIZEOF_DEFAULT_UVS_TABLE_HEADER)
3065 / sizeof (struct unicode_value_range)))
3067 /* Now 2 * nranges can't overflow, so we can safely use
3068 `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in
3069 mac_font_get_glyphs_for_variants. */
3072 non_default_uvs_offset =
3073 BUINT32_VALUE (records[i].non_default_uvs_offset);
3074 if (non_default_uvs_offset)
3076 struct non_default_uvs_table *non_default_uvs;
3079 if (non_default_uvs_offset > uvs_len
3080 || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER
3081 > uvs_len - non_default_uvs_offset))
3084 non_default_uvs = ((struct non_default_uvs_table *)
3085 ((UInt8 *) uvs + non_default_uvs_offset));
3086 nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3087 if (nmappings > ((uvs_len - non_default_uvs_offset
3088 - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER)
3089 / sizeof (struct uvs_mapping)))
3091 /* Now 2 * nmappings can't overflow, so we can safely
3092 use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2'
3093 in mac_font_get_glyphs_for_variants. */
3097 uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len);
3100 CFRelease (cmap_table);
3106 /* Find an entry in the given UVS subtable UVS_TABLE for a variation
3107 sequence consisting of the given base character C and each
3108 variation selector SELECTORS[i] for 0 <= i < COUNT, and store the
3109 result (explained below) into the corresponding GLYPHS[i]. If the
3110 entry is found in the Default UVS Table, then the result is 0. If
3111 the entry is found in the Non-Default UVS Table, then the result is
3112 the associated glyph ID. Otherwise, kCGFontIndexInvalid. The
3113 elements in SELECTORS must be sorted in strictly increasing
3117 mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
3118 const UTF32Char selectors[], CGGlyph glyphs[],
3121 struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table);
3122 struct variation_selector_record *records = uvs->variation_selector_records;
3124 UInt32 ir, nrecords;
3125 dispatch_queue_t queue =
3126 dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3127 dispatch_group_t group = dispatch_group_create ();
3129 nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
3132 while (i < count && ir < nrecords)
3134 UInt32 default_uvs_offset, non_default_uvs_offset;
3136 if (selectors[i] < BUINT24_VALUE (records[ir].var_selector))
3138 glyphs[i++] = kCGFontIndexInvalid;
3141 else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector))
3147 /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */
3148 default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
3149 non_default_uvs_offset =
3150 BUINT32_VALUE (records[ir].non_default_uvs_offset);
3151 dispatch_group_async (group, queue, ^{
3152 glyphs[i] = kCGFontIndexInvalid;
3154 if (default_uvs_offset)
3156 struct default_uvs_table *default_uvs =
3157 (struct default_uvs_table *) ((UInt8 *) uvs
3158 + default_uvs_offset);
3159 struct unicode_value_range *ranges =
3160 default_uvs->unicode_value_ranges;
3164 hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
3167 UInt32 mid = (lo + hi) / 2;
3169 if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
3175 && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
3176 + BUINT8_VALUE (ranges[hi - 1].additional_count))))
3180 if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
3182 struct non_default_uvs_table *non_default_uvs =
3183 (struct non_default_uvs_table *) ((UInt8 *) uvs
3184 + non_default_uvs_offset);
3185 struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
3189 hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
3192 UInt32 mid = (lo + hi) / 2;
3194 if (c < BUINT24_VALUE (mappings[mid].unicode_value))
3200 BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
3201 glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
3208 glyphs[i++] = kCGFontIndexInvalid;
3209 dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
3210 dispatch_release (group);
3214 macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3216 CFDataRef uvs_table;
3217 CharacterCollection uvs_collection;
3221 uvs_table = macfont_get_uvs_table (font, &uvs_collection);
3225 UTF32Char selectors[256];
3226 CGGlyph glyphs[256];
3228 for (i = 0; i < 16; i++)
3229 selectors[i] = 0xFE00 + i;
3230 for (; i < 256; i++)
3231 selectors[i] = 0xE0100 + (i - 16);
3232 mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256);
3233 for (i = 0; i < 256; i++)
3235 CGGlyph glyph = glyphs[i];
3237 if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING
3238 && glyph != kCGFontIndexInvalid)
3239 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3240 if (glyph == kCGFontIndexInvalid)
3244 variations[i] = (glyph ? glyph
3245 : macfont_get_glyph_for_character (font, c));
3255 static const char *const macfont_booleans[] = {
3261 static const char *const macfont_non_booleans[] = {
3269 macfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3271 font_filter_properties (font, alist, macfont_booleans, macfont_non_booleans);
3275 mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor,
3276 CFArrayRef languages)
3278 Boolean result = true;
3279 CFArrayRef desc_languages =
3280 CTFontDescriptorCopyAttribute (descriptor, kCTFontLanguagesAttribute);
3282 if (desc_languages == NULL)
3286 CFIndex desc_languages_count, i, languages_count;
3288 desc_languages_count = CFArrayGetCount (desc_languages);
3289 languages_count = CFArrayGetCount (languages);
3290 for (i = 0; i < languages_count; i++)
3291 if (!CFArrayContainsValue (desc_languages,
3292 CFRangeMake (0, desc_languages_count),
3293 CFArrayGetValueAtIndex (languages, i)))
3298 CFRelease (desc_languages);
3305 mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes)
3307 CFStringRef result = NULL;
3308 CFStringRef charset_string =
3309 CFDictionaryGetValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE);
3311 if (charset_string && CFStringGetLength (charset_string) > 0)
3313 CFStringRef keys[] = {
3314 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
3315 kCTLanguageAttributeName
3317 CFSTR ("NSLanguage")
3320 CFTypeRef values[] = {NULL};
3321 CFIndex num_values = 0;
3322 CFArrayRef languages
3323 = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE);
3325 if (languages && CFArrayGetCount (languages) > 0)
3327 if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
3328 values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
3331 CFCharacterSetRef charset =
3332 CFDictionaryGetValue (attributes,
3333 MAC_FONT_CHARACTER_SET_ATTRIBUTE);
3335 result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
3340 CFAttributedStringRef attr_string = NULL;
3341 CTLineRef ctline = NULL;
3342 CFDictionaryRef attrs
3343 = CFDictionaryCreate (NULL, (const void **) keys,
3344 (const void **) values, num_values,
3345 &kCFTypeDictionaryKeyCallBacks,
3346 &kCFTypeDictionaryValueCallBacks);
3350 attr_string = CFAttributedStringCreate (NULL, charset_string,
3356 ctline = CTLineCreateWithAttributedString (attr_string);
3357 CFRelease (attr_string);
3361 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3362 CFIndex i, nruns = CFArrayGetCount (runs);
3365 for (i = 0; i < nruns; i++)
3367 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3368 CFDictionaryRef attributes = CTRunGetAttributes (run);
3369 CTFontRef font_in_run;
3371 if (attributes == NULL)
3374 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3375 if (font_in_run == NULL)
3379 else if (!mac_ctfont_equal_in_postscript_name (font,
3383 if (nruns > 0 && i == nruns)
3384 result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute);
3393 static inline double
3394 mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph)
3396 return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation,
3400 static inline CGRect
3401 mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph)
3403 return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation,
3408 mac_ctfont_create_available_families (void)
3410 CFMutableArrayRef families = NULL;
3413 CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames ();
3417 CFIndex i, count = CFArrayGetCount (orig_families);
3419 families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks);
3421 for (i = 0; i < count; i++)
3423 CFStringRef family = CFArrayGetValueAtIndex (orig_families, i);
3425 if (!CFStringHasPrefix (family, CFSTR ("."))
3426 && (CTFontManagerCompareFontFamilyNames (family,
3427 CFSTR ("LastResort"),
3429 != kCFCompareEqualTo))
3430 CFArrayAppendValue (families, family);
3432 CFRelease (orig_families);
3440 mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2)
3443 CFStringRef name1, name2;
3449 name1 = CTFontCopyPostScriptName (font1);
3452 name2 = CTFontCopyPostScriptName (font2);
3455 result = CFEqual (name1, name2);
3465 mac_ctfont_create_line_with_string_and_font (CFStringRef string,
3468 CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName};
3469 CFTypeRef values[] = {NULL, NULL};
3470 CFDictionaryRef attributes = NULL;
3471 CFAttributedStringRef attr_string = NULL;
3472 CTLineRef ctline = NULL;
3473 float float_zero = 0.0f;
3475 values[0] = macfont;
3476 values[1] = CFNumberCreate (NULL, kCFNumberFloatType, &float_zero);
3479 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3480 (const void **) values,
3482 &kCFTypeDictionaryKeyCallBacks,
3483 &kCFTypeDictionaryValueCallBacks);
3484 CFRelease (values[1]);
3488 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3489 CFRelease (attributes);
3493 ctline = CTLineCreateWithAttributedString (attr_string);
3494 CFRelease (attr_string);
3498 /* Abandon if ctline contains some fonts other than the
3500 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3501 CFIndex i, nruns = CFArrayGetCount (runs);
3503 for (i = 0; i < nruns; i++)
3505 CTRunRef run = CFArrayGetValueAtIndex (runs, i);
3506 CFDictionaryRef attributes = CTRunGetAttributes (run);
3507 CTFontRef font_in_run;
3509 if (attributes == NULL)
3512 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3513 if (font_in_run == NULL)
3515 if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run))
3529 mac_ctfont_shape (CTFontRef font, CFStringRef string,
3530 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
3532 CFIndex used, result = 0;
3533 CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font);
3538 used = CTLineGetGlyphCount (ctline);
3539 if (used <= glyph_len)
3541 CFArrayRef ctruns = CTLineGetGlyphRuns (ctline);
3542 CFIndex k, ctrun_count = CFArrayGetCount (ctruns);
3543 CGFloat total_advance = 0;
3544 CFIndex total_glyph_count = 0;
3546 for (k = 0; k < ctrun_count; k++)
3548 CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k);
3549 CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun);
3550 struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count;
3551 CFRange string_range, comp_range, range;
3552 CFIndex *permutation;
3554 if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft)
3555 permutation = xmalloc (sizeof (CFIndex) * glyph_count);
3559 #define RIGHT_TO_LEFT_P permutation
3561 /* Now the `comp_range' member of struct mac_glyph_layout is
3562 temporarily used as a work area such that:
3563 glbuf[i].comp_range.location =
3564 min {compRange[i + 1].location, ...,
3565 compRange[glyph_count - 1].location,
3566 maxRange (stringRangeForCTRun)}
3567 glbuf[i].comp_range.length = maxRange (compRange[i])
3568 where compRange[i] is the range of composed characters
3569 containing i-th glyph. */
3570 string_range = CTRunGetStringRange (ctrun);
3571 min_location = string_range.location + string_range.length;
3572 for (i = 0; i < glyph_count; i++)
3574 struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1;
3575 CFIndex glyph_index;
3578 if (!RIGHT_TO_LEFT_P)
3579 glyph_index = glyph_count - i - 1;
3582 CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1),
3585 CFStringGetRangeOfComposedCharactersAtIndex (string,
3587 gl->comp_range.location = min_location;
3588 gl->comp_range.length = rng.location + rng.length;
3589 if (rng.location < min_location)
3590 min_location = rng.location;
3593 /* Fill the `comp_range' member of struct mac_glyph_layout,
3594 and setup a permutation for right-to-left text. */
3595 comp_range = CFRangeMake (string_range.location, 0);
3596 range = CFRangeMake (0, 0);
3599 struct mac_glyph_layout *gl =
3600 glbuf + range.location + range.length;
3602 if (gl->comp_range.length
3603 > comp_range.location + comp_range.length)
3604 comp_range.length = gl->comp_range.length - comp_range.location;
3605 min_location = gl->comp_range.location;
3608 if (min_location >= comp_range.location + comp_range.length)
3610 comp_range.length = min_location - comp_range.location;
3611 for (i = 0; i < range.length; i++)
3613 glbuf[range.location + i].comp_range = comp_range;
3614 if (RIGHT_TO_LEFT_P)
3615 permutation[range.location + i] =
3616 range.location + range.length - i - 1;
3619 comp_range = CFRangeMake (min_location, 0);
3620 range.location += range.length;
3622 if (range.location == glyph_count)
3627 /* Then fill the remaining members. */
3628 for (range = CFRangeMake (0, 1); range.location < glyph_count;
3631 struct mac_glyph_layout *gl;
3634 if (!RIGHT_TO_LEFT_P)
3635 gl = glbuf + range.location;
3640 src = glyph_count - 1 - range.location;
3641 dest = permutation[src];
3645 CFIndex tmp = gl->string_index;
3647 gl->string_index = glbuf[src].string_index;
3648 glbuf[src].string_index = tmp;
3651 CTRunGetGlyphs (ctrun, range, &gl->glyph_id);
3653 CTRunGetPositions (ctrun, range, &position);
3654 gl->advance_delta = position.x - total_advance;
3655 gl->baseline_delta = position.y;
3656 gl->advance = (gl->advance_delta
3657 + CTRunGetTypographicBounds (ctrun, range,
3659 total_advance += gl->advance;
3662 if (RIGHT_TO_LEFT_P)
3663 xfree (permutation);
3665 #undef RIGHT_TO_LEFT_P
3667 total_glyph_count += glyph_count;
3677 /* The function below seems to cause a memory leak for the CFString
3678 created by CFStringCreateWithCharacters as of Mac OS X 10.5.8 and
3679 10.6.3. For now, we use the NSGlyphInfo version instead. */
3680 #if USE_CT_GLYPH_INFO
3682 mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
3685 CGGlyph result = kCGFontIndexInvalid;
3686 UniChar characters[] = {0xfffd};
3688 CFAttributedStringRef attr_string = NULL;
3689 CTLineRef ctline = NULL;
3691 string = CFStringCreateWithCharacters (NULL, characters,
3692 ARRAYELTS (characters));
3696 CTGlyphInfoRef glyph_info =
3697 CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string);
3698 CFDictionaryRef attributes = NULL;
3702 CFStringRef keys[] = {kCTFontAttributeName,
3703 kCTGlyphInfoAttributeName};
3704 CFTypeRef values[] = {font, glyph_info};
3706 attributes = CFDictionaryCreate (NULL, (const void **) keys,
3707 (const void **) values,
3709 &kCFTypeDictionaryKeyCallBacks,
3710 &kCFTypeDictionaryValueCallBacks);
3711 CFRelease (glyph_info);
3715 attr_string = CFAttributedStringCreate (NULL, string, attributes);
3716 CFRelease (attributes);
3722 ctline = CTLineCreateWithAttributedString (attr_string);
3723 CFRelease (attr_string);
3727 CFArrayRef runs = CTLineGetGlyphRuns (ctline);
3729 if (CFArrayGetCount (runs) > 0)
3731 CTRunRef run = CFArrayGetValueAtIndex (runs, 0);
3732 CFDictionaryRef attributes = CTRunGetAttributes (run);
3736 CTFontRef font_in_run =
3737 CFDictionaryGetValue (attributes, kCTFontAttributeName);
3740 && mac_ctfont_equal_in_postscript_name (font_in_run, font))
3742 CTRunGetGlyphs (run, CFRangeMake (0, 1), &result);
3743 if (result >= CTFontGetGlyphCount (font))
3744 result = kCGFontIndexInvalid;
3756 mac_font_copy_default_descriptors_for_language (CFStringRef language)
3758 CFArrayRef result = NULL;
3760 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
3761 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3762 if (CTFontCopyDefaultCascadeListForLanguages != NULL)
3765 CTFontRef user_font =
3766 CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language);
3770 CFArrayRef languages =
3771 CFArrayCreate (NULL, (const void **) &language, 1,
3772 &kCFTypeArrayCallBacks);
3776 result = CTFontCopyDefaultCascadeListForLanguages (user_font,
3778 CFRelease (languages);
3780 CFRelease (user_font);
3783 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3784 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */
3786 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 */
3787 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
3791 for (i = 0; macfont_language_default_font_names[i].language; i++)
3793 if (CFEqual (macfont_language_default_font_names[i].language,
3796 CFMutableArrayRef descriptors =
3797 CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks);
3804 macfont_language_default_font_names[i].font_names[j];
3807 CFDictionaryRef attributes =
3808 CFDictionaryCreate (NULL,
3810 &MAC_FONT_NAME_ATTRIBUTE),
3812 &macfont_language_default_font_names[i].font_names[j]),
3813 1, &kCFTypeDictionaryKeyCallBacks,
3814 &kCFTypeDictionaryValueCallBacks);
3818 FontDescriptorRef pat_desc =
3819 mac_font_descriptor_create_with_attributes (attributes);
3823 FontDescriptorRef descriptor =
3824 mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL);
3828 CFArrayAppendValue (descriptors, descriptor);
3829 CFRelease (descriptor);
3831 CFRelease (pat_desc);
3833 CFRelease (attributes);
3836 result = descriptors;
3848 mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
3849 CFArrayRef languages)
3851 CFStringRef result = NULL;
3852 CFStringRef language = CFArrayGetValueAtIndex (languages, 0);
3853 CFArrayRef descriptors =
3854 mac_font_copy_default_descriptors_for_language (language);
3858 CFIndex i, count = CFArrayGetCount (descriptors);
3860 for (i = 0; i < count; i++)
3862 FontDescriptorRef descriptor =
3863 CFArrayGetValueAtIndex (descriptors, i);
3865 if (macfont_supports_charset_and_languages_p (descriptor, charset,
3868 CFStringRef family =
3869 mac_font_descriptor_copy_attribute (descriptor,
3870 MAC_FONT_FAMILY_NAME_ATTRIBUTE);
3873 if (!CFStringHasPrefix (family, CFSTR ("."))
3874 && !CFEqual (family, CFSTR ("LastResort")))
3884 CFRelease (descriptors);
3891 macfont_get_nsctfont (struct font *font)
3893 struct macfont_info *macfont_info = (struct macfont_info *) font;
3894 FontRef macfont = macfont_info->macfont;
3896 return (void *) macfont;
3900 mac_register_font_driver (struct frame *f)
3902 register_font_driver (&macfont_driver, f);
3907 syms_of_macfont (void)
3909 static struct font_driver mac_font_driver;
3911 /* Core Text, for Mac OS X. */
3912 DEFSYM (Qmac_ct, "mac-ct");
3913 macfont_driver.type = Qmac_ct;
3914 register_font_driver (&macfont_driver, NULL);
3916 /* The font property key specifying the font design destination. The
3917 value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
3918 text. (See the documentation of X Logical Font Description
3919 Conventions.) In the Mac font driver, 1 means the screen font is
3920 used for calculating some glyph metrics. You can see the
3921 difference with Monaco 8pt or 9pt, for example. */
3922 DEFSYM (QCdestination, ":destination");
3924 /* The boolean-valued font property key specifying the use of leading. */
3925 DEFSYM (QCminspace, ":minspace");