summaryrefslogtreecommitdiff
path: root/src/macfont.m
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2022-09-25 16:15:16 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2022-09-25 16:15:16 -0400
commit650c20f1ca4e07591a727e1cfcc74b3363d15985 (patch)
tree85d11f6437cde22f410c25e0e5f71a3131ebd07d /src/macfont.m
parent8869332684c2302b5ba1ead4568bbc7ba1c0183e (diff)
parent4b85ae6a24380fb67a3315eaec9233f17a872473 (diff)
downloademacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.gz
emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.bz2
emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.zip
Merge 'master' into noverlay
Diffstat (limited to 'src/macfont.m')
-rw-r--r--src/macfont.m483
1 files changed, 302 insertions, 181 deletions
diff --git a/src/macfont.m b/src/macfont.m
index 97879506ba4..4de056cb361 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -1,5 +1,5 @@
/* Font driver on macOS Core text.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -35,9 +35,16 @@ Original author: YAMAMOTO Mitsuharu
#include "nsterm.h"
#include "macfont.h"
#include "macuvs.h"
+#include "pdumper.h"
#include <libkern/OSByteOrder.h>
+/* Values for `dir' argument to shaper functions. */
+enum lgstring_direction
+ {
+ DIR_R2L = -1, DIR_UNKNOWN = 0, DIR_L2R = 1,
+ };
+
static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
static CFArrayRef mac_font_create_available_families (void);
@@ -48,9 +55,12 @@ static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
CFArrayRef);
static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
static CFIndex mac_font_shape (CTFontRef, CFStringRef,
- struct mac_glyph_layout *, CFIndex);
+ struct mac_glyph_layout *, CFIndex,
+ enum lgstring_direction);
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
+#endif
#if USE_CT_GLYPH_INFO
static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
CGFontIndex);
@@ -317,7 +327,8 @@ mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
static CFIndex
mac_font_shape_1 (NSFont *font, NSString *string,
- struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
+ struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
+ enum lgstring_direction dir)
{
NSUInteger i;
CFIndex result = 0;
@@ -581,17 +592,32 @@ mac_font_shape_1 (NSFont *font, NSString *string,
static CFIndex
mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
struct mac_glyph_layout *glyph_layouts,
- CFIndex glyph_len)
+ CFIndex glyph_len, enum lgstring_direction dir)
{
return mac_font_shape_1 ([(NSFont *)font printerFont],
(NSString *) string,
- glyph_layouts, glyph_len);
+ glyph_layouts, glyph_len, dir);
+}
+
+static CGColorRef
+get_cgcolor(unsigned long color)
+{
+ NSColor *nsColor = [NSColor colorWithUnsignedLong:color];
+ [nsColor set];
+ CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
+ NSInteger noc = [nsColor numberOfComponents];
+ CGFloat *components = xmalloc (sizeof(CGFloat)*(1+noc));
+ CGColorRef cgColor;
+
+ [nsColor getComponents: components];
+ cgColor = CGColorCreate (colorSpace, components);
+ xfree (components);
+ return cgColor;
}
static CGColorRef
-get_cgcolor(unsigned long idx, struct frame *f)
+get_cgcolor_from_nscolor (NSColor *nsColor, struct frame *f)
{
- NSColor *nsColor = ns_lookup_indexed_color (idx, f);
[nsColor set];
CGColorSpaceRef colorSpace = [[nsColor colorSpace] CGColorSpace];
NSInteger noc = [nsColor numberOfComponents];
@@ -604,21 +630,21 @@ get_cgcolor(unsigned long idx, struct frame *f)
return cgColor;
}
-#define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
+#define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face) \
do { \
- CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
+ CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face)); \
CGContextSetFillColorWithColor (context, refcol_) ; \
CGColorRelease (refcol_); \
} while (0)
-#define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face, f) \
+#define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face) \
do { \
- CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face), f); \
+ CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face)); \
CGContextSetFillColorWithColor (context, refcol_); \
CGColorRelease (refcol_); \
} while (0)
-#define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face, f) \
+#define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face) \
do { \
- CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face), f); \
+ CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face)); \
CGContextSetStrokeColorWithColor (context, refcol_); \
CGColorRelease (refcol_); \
} while (0)
@@ -655,7 +681,7 @@ static struct
{ "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
{ "iso8859-16", { 0x00A0, 0x0218}},
{ "gb2312.1980-0", { 0x4E13 }, CFSTR ("zh-Hans")},
- { "big5-0", { /* 0xF6B1 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
+ { "big5-0", { /* 0x9C21 in ftfont.c */ 0x4EDC }, CFSTR ("zh-Hant") },
{ "jisx0208.1983-0", { 0x4E55 }, CFSTR ("ja")},
{ "ksc5601.1987-0", { 0xAC00 }, CFSTR ("ko")},
{ "cns11643.1992-1", { 0xFE32 }, CFSTR ("zh-Hant")},
@@ -821,7 +847,7 @@ macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
{{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
{{-0.4, 50}, /* light */
{-0.24, 87.5}, /* (semi-light + normal) / 2 */
- {0, 100}, /* normal */
+ {0, 80}, /* normal */
{0.24, 140}, /* (semi-bold + normal) / 2 */
{0.4, 200}, /* bold */
{CGFLOAT_MAX, CGFLOAT_MAX}},
@@ -851,7 +877,7 @@ macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
* ((point->y - (point - 1)->y)
/ (point->x - (point - 1)->x)));
FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index,
- make_number (lround (floatval)));
+ make_fixnum (lround (floatval)));
}
}
@@ -864,16 +890,16 @@ macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
spacing = (sym_traits & kCTFontTraitMonoSpace
? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL);
- ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing));
+ ASET (spec_or_entity, FONT_SPACING_INDEX, make_fixnum (spacing));
}
CFRelease (dict);
}
num = CTFontDescriptorCopyAttribute (desc, kCTFontSizeAttribute);
if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval))
- ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (floatval));
+ ASET (spec_or_entity, FONT_SIZE_INDEX, make_fixnum (floatval));
else
- ASET (spec_or_entity, FONT_SIZE_INDEX, make_number (0));
+ ASET (spec_or_entity, FONT_SIZE_INDEX, make_fixnum (0));
if (num)
CFRelease (num);
}
@@ -903,21 +929,22 @@ macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
CFRelease (dict);
}
- if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0)))
- ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
+ if (BASE_EQ (AREF (entity, FONT_SIZE_INDEX), make_fixnum (0)))
+ ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
font_put_extra (entity, QCfont_entity,
- make_save_ptr_int ((void *) name, sym_traits));
+ Fcons (make_mint_ptr ((void *) name),
+ make_fixnum (sym_traits)));
if (synth_sym_traits & kCTFontTraitItalic)
FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
- make_number (FONT_SLANT_SYNTHETIC_ITALIC));
+ make_fixnum (FONT_SLANT_SYNTHETIC_ITALIC));
if (synth_sym_traits & kCTFontTraitBold)
FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
- make_number (FONT_WEIGHT_SYNTHETIC_BOLD));
+ make_fixnum (FONT_WEIGHT_SYNTHETIC_BOLD));
if (synth_sym_traits & kCTFontTraitMonoSpace)
ASET (entity, FONT_SPACING_INDEX,
- make_number (FONT_SPACING_SYNTHETIC_MONO));
+ make_fixnum (FONT_SPACING_SYNTHETIC_MONO));
return entity;
}
@@ -943,8 +970,8 @@ macfont_invalidate_family_cache (void)
{
Lisp_Object value = HASH_VALUE (h, i);
- if (SAVE_VALUEP (value))
- CFRelease (XSAVE_POINTER (value, 0));
+ if (mint_ptrp (value))
+ CFRelease (xmint_pointer (value));
}
macfont_family_cache = Qnil;
}
@@ -962,7 +989,7 @@ macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
{
Lisp_Object value = HASH_VALUE (h, i);
- *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
+ *string = mint_ptrp (value) ? xmint_pointer (value) : NULL;
return true;
}
@@ -976,21 +1003,20 @@ macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
{
struct Lisp_Hash_Table *h;
ptrdiff_t i;
- EMACS_UINT hash;
- Lisp_Object value;
+ Lisp_Object hash, value;
if (!HASH_TABLE_P (macfont_family_cache))
macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
h = XHASH_TABLE (macfont_family_cache);
i = hash_lookup (h, symbol, &hash);
- value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
+ value = string ? make_mint_ptr ((void *) CFRetain (string)) : Qnil;
if (i >= 0)
{
Lisp_Object old_value = HASH_VALUE (h, i);
- if (SAVE_VALUEP (old_value))
- CFRelease (XSAVE_POINTER (old_value, 0));
+ if (mint_ptrp (old_value))
+ CFRelease (xmint_pointer (old_value));
set_hash_value_slot (h, i, value);
}
else
@@ -1028,12 +1054,12 @@ macfont_handle_font_change_notification (CFNotificationCenterRef center,
static void
macfont_init_font_change_handler (void)
{
- static bool initialized = false;
+ static bool xinitialized = false;
- if (initialized)
+ if (xinitialized)
return;
- initialized = true;
+ xinitialized = true;
CFNotificationCenterAddObserver
(CFNotificationCenterGetLocalCenter (), NULL,
macfont_handle_font_change_notification,
@@ -1111,13 +1137,17 @@ struct macfont_metrics
glyph width. The `width_int' member is an integer that is
closest to the width. The `width_frac' member is the fractional
adjustment representing a value in [-.5, .5], multiplied by
- WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
+ WIDTH_FRAC_SCALE. For monospace fonts, non-zero `width_frac'
+ means `width_int' is further adjusted to a multiple of the
+ (rounded) font width, and `width_frac' represents adjustment per
+ unit character. For synthetic monospace fonts, they represent
the advance delta for centering instead of the glyph width. */
signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
};
#define METRICS_VALUE(metrics, member) \
- (((metrics)->member##_high << 8) | (metrics)->member##_low)
+ ((int) (((unsigned int) (metrics)->member##_high << 8) \
+ | (metrics)->member##_low))
#define METRICS_SET_VALUE(metrics, member, value) \
do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \
(metrics)->member##_high = tmp >> 8;} while (0)
@@ -1138,6 +1168,27 @@ enum metrics_status
#define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
#define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
+/* If FONT is monospace and WIDTH can be regarded as a multiple of its
+ width where the multiplier is greater than 1, then return the
+ multiplier. Otherwise return 0. */
+static int
+macfont_monospace_width_multiplier (struct font *font, CGFloat width)
+{
+ struct macfont_info *macfont_info = (struct macfont_info *) font;
+ int multiplier = 0;
+
+ if (macfont_info->spacing == MACFONT_SPACING_MONO
+ && font->space_width != 0)
+ {
+ multiplier = lround (width / font->space_width);
+ if (multiplier == 1
+ || lround (width / multiplier) != font->space_width)
+ multiplier = 0;
+ }
+
+ return multiplier;
+}
+
static int
macfont_glyph_extents (struct font *font, CGGlyph glyph,
struct font_metrics *metrics, CGFloat *advance_delta,
@@ -1182,13 +1233,38 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
else
fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
- /* For synthetic mono fonts, cache->width_{int,frac} holds the
- advance delta value. */
- if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
- fwidth = (font->pixel_size - fwidth) / 2;
- cache->width_int = lround (fwidth);
- cache->width_frac = lround ((fwidth - cache->width_int)
- * WIDTH_FRAC_SCALE);
+ if (macfont_info->spacing == MACFONT_SPACING_MONO)
+ {
+ /* Some monospace fonts for programming languages contain
+ wider ligature glyphs consisting of multiple characters.
+ For such glyphs, simply rounding the combined fractional
+ width to an integer can result in a value that is not a
+ multiple of the (rounded) font width. */
+ int multiplier = macfont_monospace_width_multiplier (font, fwidth);
+
+ if (multiplier)
+ {
+ cache->width_int = font->space_width * multiplier;
+ cache->width_frac = lround ((fwidth / multiplier
+ - font->space_width)
+ * WIDTH_FRAC_SCALE);
+ }
+ else
+ {
+ cache->width_int = lround (fwidth);
+ cache->width_frac = 0;
+ }
+ }
+ else
+ {
+ /* For synthetic mono fonts, cache->width_{int,frac} holds
+ the advance delta value. */
+ if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
+ fwidth = (font->pixel_size - fwidth) / 2;
+ cache->width_int = lround (fwidth);
+ cache->width_frac = lround ((fwidth - cache->width_int)
+ * WIDTH_FRAC_SCALE);
+ }
METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
}
if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
@@ -1225,6 +1301,10 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
/ (CGFloat) (WIDTH_FRAC_SCALE * 2));
break;
case MACFONT_SPACING_MONO:
+ if (cache->width_frac)
+ bounds.origin.x += - ((cache->width_frac
+ / (CGFloat) (WIDTH_FRAC_SCALE * 2))
+ * (cache->width_int / font->space_width));
break;
case MACFONT_SPACING_SYNTHETIC_MONO:
bounds.origin.x += (cache->width_int
@@ -1261,7 +1341,16 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
/ (CGFloat) (WIDTH_FRAC_SCALE * 2)));
break;
case MACFONT_SPACING_MONO:
- *advance_delta = 0;
+ if (cache->width_frac)
+ *advance_delta = 0;
+ else
+ {
+ CGFloat delta = - ((cache->width_frac
+ / (CGFloat) (WIDTH_FRAC_SCALE * 2))
+ * (cache->width_int / font->space_width));
+
+ *advance_delta = (force_integral_p ? round (delta) : delta);
+ }
break;
case MACFONT_SPACING_SYNTHETIC_MONO:
*advance_delta = (force_integral_p ? cache->width_int
@@ -1441,8 +1530,7 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
CGGlyph *glyphs;
int i, len;
int nrows;
- dispatch_queue_t queue;
- dispatch_group_t group = NULL;
+ int nkeys;
if (row != 0)
{
@@ -1479,23 +1567,16 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
return glyph;
}
- queue =
- dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- group = dispatch_group_create ();
- dispatch_group_async (group, queue, ^{
- int nkeys;
- uintptr_t key;
- nkeys = nkeys_or_perm;
- for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
- if (CFDictionaryContainsKey (dictionary,
- (const void *) key))
- {
- CFDictionaryRemoveValue (dictionary,
- (const void *) key);
- if (--nkeys == 0)
- break;
- }
- });
+ nkeys = nkeys_or_perm;
+ for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++)
+ if (CFDictionaryContainsKey (dictionary,
+ (const void *) key))
+ {
+ CFDictionaryRemoveValue (dictionary,
+ (const void *) key);
+ if (--nkeys == 0)
+ break;
+ }
}
len = 0;
@@ -1535,12 +1616,6 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
sizeof (CGGlyph *) * nrows);
cache->glyph.matrix[nrows - 1] = glyphs;
cache->glyph.nrows = nrows;
-
- if (group)
- {
- dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
- dispatch_release (group);
- }
}
return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256];
@@ -1651,15 +1726,15 @@ static Lisp_Object macfont_open (struct frame *, Lisp_Object, int);
static void macfont_close (struct font *);
static int macfont_has_char (Lisp_Object, int);
static unsigned macfont_encode_char (struct font *, int);
-static void macfont_text_extents (struct font *, unsigned int *, int,
+static void macfont_text_extents (struct font *, const unsigned int *, int,
struct font_metrics *);
static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
-static Lisp_Object macfont_shape (Lisp_Object);
+static Lisp_Object macfont_shape (Lisp_Object, Lisp_Object);
static int macfont_variation_glyphs (struct font *, int c,
unsigned variations[256]);
static void macfont_filter_properties (Lisp_Object, Lisp_Object);
-static struct font_driver const macfont_driver =
+static struct font_driver macfont_driver =
{
.type = LISPSYM_INITIALLY (Qmac_ct),
.get_cache = macfont_get_cache,
@@ -1667,8 +1742,8 @@ static struct font_driver const macfont_driver =
.match = macfont_match,
.list_family = macfont_list_family,
.free_entity = macfont_free_entity,
- .open = macfont_open,
- .close = macfont_close,
+ .open_font = macfont_open,
+ .close_font = macfont_close,
.has_char = macfont_has_char,
.encode_char = macfont_encode_char,
.text_extents = macfont_text_extents,
@@ -1804,16 +1879,14 @@ macfont_get_open_type_spec (Lisp_Object otf_spec)
spec->nfeatures[0] = spec->nfeatures[1] = 0;
for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
{
- Lisp_Object len;
-
val = XCAR (otf_spec);
if (NILP (val))
continue;
- len = Flength (val);
+ ptrdiff_t len = list_length (val);
spec->features[i] =
- (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
+ (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < len
? 0
- : malloc (XINT (len) * sizeof *spec->features[i]));
+ : malloc (len * sizeof *spec->features[i]));
if (! spec->features[i])
{
if (i > 0 && spec->features[0])
@@ -1830,7 +1903,7 @@ macfont_get_open_type_spec (Lisp_Object otf_spec)
unsigned int tag;
OTF_SYM_TAG (XCAR (val), tag);
- spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
+ spec->features[i][j++] = negative ? tag | 0x80000000 : tag;
}
}
spec->nfeatures[i] = j;
@@ -1953,9 +2026,9 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
{
UniChar unichars[2];
CFIndex count =
- macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)),
+ macfont_store_utf32char_to_unichars (XFIXNAT (XCAR (chars)),
unichars);
- CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1);
+ CFRange range = CFRangeMake (XFIXNAT (XCAR (chars)), 1);
CFStringAppendCharacters (string, unichars, count);
CFCharacterSetAddCharactersInRange (cs, range);
@@ -1994,10 +2067,10 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
for (i = 0; i < ARRAYELTS (numeric_traits); i++)
{
tmp = AREF (spec, numeric_traits[i].index);
- if (INTEGERP (tmp))
+ if (FIXNUMP (tmp))
{
CGPoint *point = numeric_traits[i].points;
- CGFloat floatval = (XINT (tmp) >> 8); // XXX
+ CGFloat floatval = (XFIXNUM (tmp) >> 8); // XXX
CFNumberRef num;
while (point->y < floatval)
@@ -2082,9 +2155,9 @@ macfont_supports_charset_and_languages_p (CTFontDescriptorRef desc,
ptrdiff_t j;
for (j = 0; j < ASIZE (chars); j++)
- if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j))
+ if (RANGED_FIXNUMP (0, AREF (chars, j), MAX_UNICODE_CHAR)
&& CFCharacterSetIsLongCharacterMember (desc_charset,
- XFASTINT (AREF (chars, j))))
+ XFIXNAT (AREF (chars, j))))
break;
if (j == ASIZE (chars))
result = false;
@@ -2174,8 +2247,8 @@ macfont_list (struct frame *f, Lisp_Object spec)
languages = CFDictionaryGetValue (attributes, kCTFontLanguagesAttribute);
- if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
- spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
+ if (FIXNUMP (AREF (spec, FONT_SPACING_INDEX)))
+ spacing = XFIXNUM (AREF (spec, FONT_SPACING_INDEX));
traits = ((CFMutableDictionaryRef)
CFDictionaryGetValue (attributes, kCTFontTraitsAttribute));
@@ -2358,9 +2431,13 @@ macfont_list (struct frame *f, Lisp_Object spec)
!= (spacing >= FONT_SPACING_MONO)))
continue;
- /* Don't use a color bitmap font until it is supported on
- free platforms. */
- if (sym_traits & kCTFontTraitColorGlyphs)
+ /* Don't use a color bitmap font unless its family is
+ explicitly specified or we're looking for a font for
+ emoji. */
+ if ((sym_traits & kCTFontTraitColorGlyphs)
+ && NILP (family)
+ && !EQ (CDR_SAFE (assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX))),
+ Qemoji))
continue;
if (j > 0
@@ -2519,7 +2596,7 @@ macfont_free_entity (Lisp_Object entity)
{
Lisp_Object val = assq_no_quit (QCfont_entity,
AREF (entity, FONT_EXTRA_INDEX));
- CFStringRef name = XSAVE_POINTER (XCDR (val), 0);
+ CFStringRef name = xmint_pointer (XCAR (XCDR (val)));
block_input ();
CFRelease (name);
@@ -2542,13 +2619,12 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
if (! CONSP (val)
- || XTYPE (XCDR (val)) != Lisp_Misc
- || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
+ || ! CONSP (XCDR (val)))
return Qnil;
- font_name = XSAVE_POINTER (XCDR (val), 0);
- sym_traits = XSAVE_INTEGER (XCDR (val), 1);
+ font_name = xmint_pointer (XCAR (XCDR (val)));
+ sym_traits = XFIXNUM (XCDR (XCDR (val)));
- size = XINT (AREF (entity, FONT_SIZE_INDEX));
+ size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
if (size == 0)
size = pixel_size;
@@ -2569,6 +2645,9 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
font->pixel_size = size;
font->driver = &macfont_driver;
font->encoding_charset = font->repertory_charset = -1;
+ /* Clear font->space_width so macfont_monospace_width_multiplier may
+ not be confused by an uninitialized value. */
+ font->space_width = 0;
block_input ();
@@ -2577,7 +2656,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
- if (CONSP (val) && EQ (XCDR (val), make_number (1)))
+ if (CONSP (val) && BASE_EQ (XCDR (val), make_fixnum (1)))
macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
size);
else
@@ -2598,8 +2677,8 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
macfont_info->synthetic_bold_p = 1;
if (sym_traits & kCTFontTraitMonoSpace)
macfont_info->spacing = MACFONT_SPACING_MONO;
- else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))
- && (XINT (AREF (entity, FONT_SPACING_INDEX))
+ else if (FIXNUMP (AREF (entity, FONT_SPACING_INDEX))
+ && (XFIXNUM (AREF (entity, FONT_SPACING_INDEX))
== FONT_SPACING_SYNTHETIC_MONO))
macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO;
if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p)
@@ -2717,6 +2796,9 @@ macfont_has_char (Lisp_Object font, int c)
int result;
CFCharacterSetRef charset;
+ if (c < 0 || c > MAX_UNICODE_CHAR)
+ return false;
+
block_input ();
if (FONT_ENTITY_P (font))
{
@@ -2725,7 +2807,7 @@ macfont_has_char (Lisp_Object font, int c)
val = assq_no_quit (QCfont_entity, AREF (font, FONT_EXTRA_INDEX));
val = XCDR (val);
- name = XSAVE_POINTER (val, 0);
+ name = xmint_pointer (XCAR (val));
charset = macfont_get_cf_charset_for_name (name);
}
else
@@ -2750,7 +2832,7 @@ macfont_encode_char (struct font *font, int c)
}
static void
-macfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
+macfont_text_extents (struct font *font, const unsigned int *code, int nglyphs,
struct font_metrics *metrics)
{
int width, i;
@@ -2833,19 +2915,30 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
}
}
- context = [[NSGraphicsContext currentContext] graphicsPort];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
+ if ([[NSGraphicsContext currentContext] respondsToSelector:@selector(CGContext)])
+#endif
+ context = [[NSGraphicsContext currentContext] CGContext];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
+ else
+#endif
+#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
+ context = [[NSGraphicsContext currentContext] graphicsPort];
+#endif
CGContextSaveGState (context);
if (!CGRectIsNull (background_rect))
{
- if (s->hl == DRAW_MOUSE_FACE)
+ if (s->hl == DRAW_CURSOR)
{
- face = FACE_FROM_ID_OR_NULL (s->f,
- MOUSE_HL_INFO (s->f)->mouse_face_face_id);
- if (!face)
- face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+ CGColorRef colorref = get_cgcolor_from_nscolor (FRAME_CURSOR_COLOR (f), f);
+ CGContextSetFillColorWithColor (context, colorref);
+ CGColorRelease (colorref);
}
- CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f);
+ else
+ CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face);
CGContextFillRects (context, &background_rect, 1);
}
@@ -2854,7 +2947,14 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
CGAffineTransform atfm;
CGContextScaleCTM (context, 1, -1);
- CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f);
+ if (s->hl == DRAW_CURSOR)
+ {
+ CGColorRef colorref = get_cgcolor_from_nscolor (FRAME_BACKGROUND_COLOR (f), f);
+ CGContextSetFillColorWithColor (context, colorref);
+ CGColorRelease (colorref);
+ }
+ else
+ CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face);
if (macfont_info->synthetic_italic_p)
atfm = synthetic_italic_atfm;
else
@@ -2883,7 +2983,7 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
CGContextSetLineWidth (context, synthetic_bold_factor * font_size);
#endif
- CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f);
+ CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face);
}
if (no_antialias_p)
CGContextSetShouldAntialias (context, false);
@@ -2930,7 +3030,7 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
}
static Lisp_Object
-macfont_shape (Lisp_Object lgstring)
+macfont_shape (Lisp_Object lgstring, Lisp_Object direction)
{
struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
struct macfont_info *macfont_info = (struct macfont_info *) font;
@@ -2980,12 +3080,18 @@ macfont_shape (Lisp_Object lgstring)
kCFAllocatorNull);
if (string)
{
+ enum lgstring_direction dir = DIR_UNKNOWN;
+
+ if (EQ (direction, QL2R))
+ dir = DIR_L2R;
+ else if (EQ (direction, QR2L))
+ dir = DIR_R2L;
glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
if (macfont_info->screen_font)
used = mac_screen_font_shape (macfont_info->screen_font, string,
- glyph_layouts, glyph_len);
+ glyph_layouts, glyph_len, dir);
else
- used = mac_font_shape (macfont, string, glyph_layouts, glyph_len);
+ used = mac_font_shape (macfont, string, glyph_layouts, glyph_len, dir);
CFRelease (string);
}
@@ -3002,11 +3108,11 @@ macfont_shape (Lisp_Object lgstring)
struct mac_glyph_layout *gl = glyph_layouts + i;
EMACS_INT from, to;
struct font_metrics metrics;
- int xoff, yoff, wadjust;
+ int xoff, yoff, wadjust, multiplier;
if (NILP (lglyph))
{
- lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
+ lglyph = LGLYPH_NEW ();
LGSTRING_SET_GLYPH (lgstring, i, lglyph);
}
@@ -3055,22 +3161,22 @@ macfont_shape (Lisp_Object lgstring)
xoff = lround (gl->advance_delta);
yoff = lround (- gl->baseline_delta);
- wadjust = lround (gl->advance);
+ multiplier = macfont_monospace_width_multiplier (font, gl->advance);
+ if (multiplier)
+ wadjust = font->space_width * multiplier;
+ else
+ wadjust = lround (gl->advance);
if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
{
- Lisp_Object vec;
-
- vec = Fmake_vector (make_number (3), Qnil);
- ASET (vec, 0, make_number (xoff));
- ASET (vec, 1, make_number (yoff));
- ASET (vec, 2, make_number (wadjust));
+ Lisp_Object vec = CALLN (Fvector, make_fixnum (xoff),
+ make_fixnum (yoff), make_fixnum (wadjust));
LGLYPH_SET_ADJUSTMENT (lglyph, vec);
}
}
unblock_input ();
- return make_number (used);
+ return make_fixnum (used);
}
/* Structures for the UVS subtable (format 14) in the cmap table. */
@@ -3267,9 +3373,6 @@ mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
struct variation_selector_record *records = uvs->variation_selector_records;
CFIndex i;
UInt32 ir, nrecords;
- dispatch_queue_t queue =
- dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_group_t group = dispatch_group_create ();
nrecords = BUINT32_VALUE (uvs->num_var_selector_records);
i = 0;
@@ -3293,66 +3396,63 @@ mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c,
default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset);
non_default_uvs_offset =
BUINT32_VALUE (records[ir].non_default_uvs_offset);
- dispatch_group_async (group, queue, ^{
- glyphs[i] = kCGFontIndexInvalid;
- if (default_uvs_offset)
+ glyphs[i] = kCGFontIndexInvalid;
+
+ if (default_uvs_offset)
+ {
+ struct default_uvs_table *default_uvs =
+ (struct default_uvs_table *) ((UInt8 *) uvs
+ + default_uvs_offset);
+ struct unicode_value_range *ranges =
+ default_uvs->unicode_value_ranges;
+ UInt32 lo, hi;
+
+ lo = 0;
+ hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
+ while (lo < hi)
{
- struct default_uvs_table *default_uvs =
- (struct default_uvs_table *) ((UInt8 *) uvs
- + default_uvs_offset);
- struct unicode_value_range *ranges =
- default_uvs->unicode_value_ranges;
- UInt32 lo, hi;
-
- lo = 0;
- hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges);
- while (lo < hi)
- {
- UInt32 mid = (lo + hi) / 2;
+ UInt32 mid = (lo + hi) / 2;
- if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
- hi = mid;
- else
- lo = mid + 1;
- }
- if (hi > 0
- && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
- + BUINT8_VALUE (ranges[hi - 1].additional_count))))
- glyphs[i] = 0;
+ if (c < BUINT24_VALUE (ranges[mid].start_unicode_value))
+ hi = mid;
+ else
+ lo = mid + 1;
}
+ if (hi > 0
+ && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value)
+ + BUINT8_VALUE (ranges[hi - 1].additional_count))))
+ glyphs[i] = 0;
+ }
- if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
+ if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset)
+ {
+ struct non_default_uvs_table *non_default_uvs =
+ (struct non_default_uvs_table *) ((UInt8 *) uvs
+ + non_default_uvs_offset);
+ struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
+ UInt32 lo, hi;
+
+ lo = 0;
+ hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
+ while (lo < hi)
{
- struct non_default_uvs_table *non_default_uvs =
- (struct non_default_uvs_table *) ((UInt8 *) uvs
- + non_default_uvs_offset);
- struct uvs_mapping *mappings = non_default_uvs->uvs_mappings;
- UInt32 lo, hi;
-
- lo = 0;
- hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings);
- while (lo < hi)
- {
- UInt32 mid = (lo + hi) / 2;
+ UInt32 mid = (lo + hi) / 2;
- if (c < BUINT24_VALUE (mappings[mid].unicode_value))
- hi = mid;
- else
- lo = mid + 1;
- }
- if (hi > 0 &&
- BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
- glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
+ if (c < BUINT24_VALUE (mappings[mid].unicode_value))
+ hi = mid;
+ else
+ lo = mid + 1;
}
- });
+ if (hi > 0 &&
+ BUINT24_VALUE (mappings[hi - 1].unicode_value) == c)
+ glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id);
+ }
i++;
ir++;
}
while (i < count)
glyphs[i++] = kCGFontIndexInvalid;
- dispatch_group_wait (group, DISPATCH_TIME_FOREVER);
- dispatch_release (group);
}
static int
@@ -3475,15 +3575,17 @@ mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
if (languages && CFArrayGetCount (languages) > 0)
{
- if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
- values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
- else
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+ if (CTGetCoreTextVersion () < kCTVersionNumber10_9)
{
CFCharacterSetRef charset =
CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
}
+ else
+#endif
+ values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
}
if (result == NULL)
{
@@ -3674,7 +3776,8 @@ mac_font_create_line_with_string_and_font (CFStringRef string,
static CFIndex
mac_font_shape (CTFontRef font, CFStringRef string,
- struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
+ struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
+ enum lgstring_direction dir)
{
CFIndex used, result = 0;
CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
@@ -3901,6 +4004,7 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
}
#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
static CFArrayRef
mac_font_copy_default_descriptors_for_language (CFStringRef language)
{
@@ -4035,6 +4139,7 @@ mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
return result;
}
+#endif
void *
macfont_get_nsctfont (struct font *font)
@@ -4052,12 +4157,14 @@ mac_register_font_driver (struct frame *f)
}
+
+static void syms_of_macfont_for_pdumper (void);
+
void
syms_of_macfont (void)
{
/* Core Text, for macOS. */
DEFSYM (Qmac_ct, "mac-ct");
- register_font_driver (&macfont_driver, NULL);
/* The font property key specifying the font design destination. The
value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
@@ -4072,4 +4179,18 @@ syms_of_macfont (void)
macfont_family_cache = Qnil;
staticpro (&macfont_family_cache);
+
+ pdumper_do_now_and_after_load (syms_of_macfont_for_pdumper);
+}
+
+static void
+syms_of_macfont_for_pdumper (void)
+{
+ if (dumped_with_pdumper_p ())
+ macfont_family_cache = Qnil;
+ else
+ eassert (NILP (macfont_family_cache));
+
+ macfont_driver.type = Qmac_ct;
+ register_font_driver (&macfont_driver, NULL);
}