[USE_CG_TEXT_DRAWING] (mac_draw_string_cg): New function.
(x_draw_glyph_string_foreground) [USE_CG_TEXT_DRAWING]: Use it. (XLoadQueryFont) [USE_CG_TEXT_DRAWING]: Set members cg_font and cg_glyphs in struct MacFontStruct if synthesized bold or italic is not used and font substitution never occurs for ASCII and Latin-1 characters. (XLoadQueryFont): Maximum and minimum metrics are now those among ASCII characters. (XLoadQueryFont) [!MAC_OS8 || USE_ATSUI]: Apply WebKit-style height adjustments for Courier, Helvetica, and Times.
This commit is contained in:
252
src/macterm.c
252
src/macterm.c
@@ -86,7 +86,7 @@ Boston, MA 02110-1301, USA. */
|
||||
#include "intervals.h"
|
||||
#include "atimer.h"
|
||||
#include "keymap.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* Non-nil means Emacs uses toolkit scroll bars. */
|
||||
@@ -771,7 +771,7 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char)
|
||||
QDEndCGContext (port, &context);
|
||||
#if 0
|
||||
/* This doesn't work on Mac OS X 10.1. */
|
||||
ATSUClearLayoutControls (text_layout,
|
||||
ATSUClearLayoutControls (text_layout,
|
||||
sizeof (tags) / sizeof (tags[0]),
|
||||
tags);
|
||||
#else
|
||||
@@ -864,6 +864,77 @@ mac_draw_image_string_16 (f, gc, x, y, buf, nchars)
|
||||
}
|
||||
|
||||
|
||||
#if USE_CG_TEXT_DRAWING
|
||||
static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
|
||||
|
||||
static int
|
||||
mac_draw_string_cg (f, gc, x, y, buf, nchars)
|
||||
struct frame *f;
|
||||
GC gc;
|
||||
int x, y;
|
||||
XChar2b *buf;
|
||||
int nchars;
|
||||
{
|
||||
CGrafPtr port;
|
||||
float port_height, gx, gy;
|
||||
int i;
|
||||
CGContextRef context;
|
||||
CGGlyph *glyphs;
|
||||
CGSize *advances;
|
||||
|
||||
if (NILP (Vmac_use_core_graphics) || GC_FONT (gc)->cg_font == NULL)
|
||||
return 0;
|
||||
|
||||
port = GetWindowPort (FRAME_MAC_WINDOW (f));
|
||||
port_height = FRAME_PIXEL_HEIGHT (f);
|
||||
gx = x;
|
||||
gy = port_height - y;
|
||||
glyphs = (CGGlyph *)buf;
|
||||
advances = xmalloc (sizeof (CGSize) * nchars);
|
||||
for (i = 0; i < nchars; i++)
|
||||
{
|
||||
advances[i].width = x_per_char_metric (GC_FONT (gc), buf)->width;
|
||||
advances[i].height = 0;
|
||||
glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
|
||||
buf++;
|
||||
}
|
||||
|
||||
QDBeginCGContext (port, &context);
|
||||
if (gc->n_clip_rects)
|
||||
{
|
||||
CGContextTranslateCTM (context, 0, port_height);
|
||||
CGContextScaleCTM (context, 1, -1);
|
||||
CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
|
||||
CGContextScaleCTM (context, 1, -1);
|
||||
CGContextTranslateCTM (context, 0, -port_height);
|
||||
}
|
||||
CGContextSetRGBFillColor (context,
|
||||
RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
|
||||
GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
|
||||
BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
|
||||
1.0);
|
||||
CGContextSetFont (context, GC_FONT (gc)->cg_font);
|
||||
CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
|
||||
CGContextSetTextPosition (context, gx, gy);
|
||||
CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
|
||||
#else
|
||||
for (i = 0; i < nchars; i++)
|
||||
{
|
||||
CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
|
||||
gx += advances[i].width;
|
||||
}
|
||||
#endif
|
||||
CGContextSynchronize (context);
|
||||
QDEndCGContext (port, &context);
|
||||
|
||||
xfree (advances);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Mac replacement for XCopyArea: dest must be window. */
|
||||
|
||||
static void
|
||||
@@ -2258,6 +2329,13 @@ x_draw_glyph_string_foreground (s)
|
||||
|| GC_FONT (s->gc)->mac_style
|
||||
#endif
|
||||
)
|
||||
#if USE_CG_TEXT_DRAWING
|
||||
if (!s->two_byte_p
|
||||
&& mac_draw_string_cg (s->f, s->gc, x, s->ybase - boff,
|
||||
s->char2b, s->nchars))
|
||||
;
|
||||
else
|
||||
#endif
|
||||
mac_draw_string_16 (s->f, s->gc, x, s->ybase - boff,
|
||||
s->char2b, s->nchars);
|
||||
else
|
||||
@@ -7281,6 +7359,7 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
Str31 charset;
|
||||
SInt16 fontnum;
|
||||
#if USE_ATSUI
|
||||
static ATSUFontID font_id;
|
||||
ATSUStyle mac_style = NULL;
|
||||
#endif
|
||||
Style fontface;
|
||||
@@ -7315,7 +7394,6 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
kATSUQDBoldfaceTag, kATSUQDItalicTag};
|
||||
ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
|
||||
sizeof (Boolean), sizeof (Boolean)};
|
||||
static ATSUFontID font_id;
|
||||
static Fixed size_fixed;
|
||||
static Boolean bold_p, italic_p;
|
||||
ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
|
||||
@@ -7369,6 +7447,10 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
font->mac_scriptcode = scriptcode;
|
||||
#if USE_ATSUI
|
||||
font->mac_style = mac_style;
|
||||
#if USE_CG_TEXT_DRAWING
|
||||
font->cg_font = NULL;
|
||||
font->cg_glyphs = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Apple Japanese (SJIS) font is listed as both
|
||||
@@ -7398,6 +7480,30 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
}
|
||||
bzero (font->per_char, sizeof (XCharStruct) * 0x10000);
|
||||
|
||||
#if USE_CG_TEXT_DRAWING
|
||||
{
|
||||
FMFontFamily font_family;
|
||||
FMFontStyle style;
|
||||
ATSFontRef ats_font;
|
||||
|
||||
err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style);
|
||||
if (err == noErr)
|
||||
err = FMGetFontFromFontFamilyInstance (font_family, fontface,
|
||||
&font_id, &style);
|
||||
/* Use CG text drawing if italic/bold is not synthesized. */
|
||||
if (err == noErr && style == fontface)
|
||||
{
|
||||
ats_font = FMGetATSFontRefFromFont (font_id);
|
||||
font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
|
||||
}
|
||||
}
|
||||
|
||||
if (font->cg_font)
|
||||
font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
|
||||
if (font->cg_glyphs)
|
||||
bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
|
||||
#endif
|
||||
|
||||
err = atsu_get_text_layout_with_text_ptr (&c, 1,
|
||||
font->mac_style,
|
||||
&text_layout);
|
||||
@@ -7407,8 +7513,19 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (c = 0x20; c <= 0x7e; c++)
|
||||
for (c = 0x20; c <= 0xff; c++)
|
||||
{
|
||||
if (c == 0xad)
|
||||
/* Soft hyphen is not supported in ATSUI. */
|
||||
continue;
|
||||
else if (c == 0x7f)
|
||||
{
|
||||
STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
|
||||
STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
|
||||
c = 0x9f;
|
||||
continue;
|
||||
}
|
||||
|
||||
err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning);
|
||||
if (err == noErr)
|
||||
err = ATSUMeasureTextImage (text_layout,
|
||||
@@ -7457,9 +7574,32 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
}
|
||||
}
|
||||
}
|
||||
#if USE_CG_TEXT_DRAWING
|
||||
if (err == noErr && char_width > 0 && font->cg_font)
|
||||
{
|
||||
ATSUGlyphInfoArray glyph_info_array;
|
||||
ByteCount count = sizeof (ATSUGlyphInfoArray);
|
||||
|
||||
err = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
|
||||
kATSUToTextEnd, NULL, NULL, NULL);
|
||||
if (err == noErr)
|
||||
err = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
|
||||
kATSUToTextEnd, &count,
|
||||
&glyph_info_array);
|
||||
if (err == noErr)
|
||||
font->cg_glyphs[c] = glyph_info_array.glyphs[0].glyphID;
|
||||
else
|
||||
{
|
||||
/* Don't use CG text drawing if font substitution
|
||||
occurs in ASCII or Latin-1 characters. */
|
||||
CGFontRelease (font->cg_font);
|
||||
font->cg_font = NULL;
|
||||
xfree (font->cg_glyphs);
|
||||
font->cg_glyphs = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
|
||||
STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
|
||||
|
||||
font->min_byte1 = 0;
|
||||
font->max_byte1 = 0xff;
|
||||
@@ -7572,6 +7712,13 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
SetRect (&max_bounds, 0, 0, 0, 0);
|
||||
for (c = 0x20; c <= 0xff; c++)
|
||||
{
|
||||
if (c == 0x7f)
|
||||
{
|
||||
STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
|
||||
STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
|
||||
continue;
|
||||
}
|
||||
|
||||
ch = c;
|
||||
char_width = CharWidth (ch);
|
||||
QDTextBounds (1, &ch, &char_bounds);
|
||||
@@ -7594,8 +7741,6 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
UnionRect (&max_bounds, &char_bounds, &max_bounds);
|
||||
}
|
||||
}
|
||||
STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
|
||||
STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
|
||||
if (min_width == max_width
|
||||
&& max_bounds.left >= 0 && max_bounds.right <= max_width)
|
||||
{
|
||||
@@ -7611,6 +7756,15 @@ XLoadQueryFont (Display *dpy, char *fontname)
|
||||
TextFace (old_fontface);
|
||||
}
|
||||
|
||||
#if !defined (MAC_OS8) || USE_ATSUI
|
||||
/* AppKit and WebKit do some adjustment to the heights of Courier,
|
||||
Helvetica, and Times. This only works on the environments where
|
||||
the XDrawImageString counterpart is never used. */
|
||||
if (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
|
||||
|| strcmp (family, "times") == 0)
|
||||
font->ascent += (font->ascent + font->descent) * .15 + 0.5;
|
||||
#endif
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
@@ -7626,6 +7780,12 @@ mac_unload_font (dpyinfo, font)
|
||||
#if USE_ATSUI
|
||||
if (font->mac_style)
|
||||
ATSUDisposeStyle (font->mac_style);
|
||||
#if USE_CG_TEXT_DRAWING
|
||||
if (font->cg_font)
|
||||
CGFontRelease (font->cg_font);
|
||||
if (font->cg_glyphs)
|
||||
xfree (font->cg_glyphs);
|
||||
#endif
|
||||
#endif
|
||||
xfree (font);
|
||||
}
|
||||
@@ -8000,16 +8160,16 @@ mac_to_emacs_modifiers (EventModifiers mods)
|
||||
unsigned int result = 0;
|
||||
if (mods & shiftKey)
|
||||
result |= shift_modifier;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Deactivated to simplify configuration:
|
||||
if Vmac_option_modifier is non-NIL, we fully process the Option
|
||||
key. Otherwise, we only process it if an additional Ctrl or Command
|
||||
is pressed. That way the system may convert the character to a
|
||||
is pressed. That way the system may convert the character to a
|
||||
composed one.
|
||||
if ((mods & optionKey) &&
|
||||
(( !NILP(Vmac_option_modifier) ||
|
||||
(( !NILP(Vmac_option_modifier) ||
|
||||
((mods & cmdKey) || (mods & controlKey))))) */
|
||||
|
||||
if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
|
||||
@@ -8021,21 +8181,21 @@ mac_to_emacs_modifiers (EventModifiers mods)
|
||||
Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
|
||||
if (INTEGERP(val))
|
||||
result |= XUINT(val);
|
||||
}
|
||||
}
|
||||
if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
|
||||
Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
|
||||
if (INTEGERP(val))
|
||||
result |= XUINT(val);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAC_OSX
|
||||
if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
|
||||
Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
|
||||
if (INTEGERP(val))
|
||||
result |= XUINT(val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -9407,7 +9567,7 @@ static unsigned char keycode_to_xkeysym_table[] = {
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
static int
|
||||
keycode_to_xkeysym (int keyCode, int *xKeySym)
|
||||
{
|
||||
*xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
|
||||
@@ -9448,7 +9608,7 @@ static int
|
||||
convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
|
||||
{
|
||||
#ifdef MAC_OSX
|
||||
/* Use the special map to translate keys when function modifier is
|
||||
/* Use the special map to translate keys when function modifier is
|
||||
to be caught. KeyTranslate can't be used in that case.
|
||||
We can't detect the function key using the input_event.modifiers,
|
||||
because this uses the high word of an UInt32. Therefore,
|
||||
@@ -9464,7 +9624,7 @@ convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
|
||||
|
||||
- The table is meant for English language keyboards, and it will work
|
||||
for many others with the exception of key combinations like Fn-ö on
|
||||
a German keyboard, which is currently mapped to Fn-;.
|
||||
a German keyboard, which is currently mapped to Fn-;.
|
||||
How to solve this without keeping separate tables for all keyboards
|
||||
around? KeyTranslate isn't of much help here, as it only takes a 16-bit
|
||||
value for keycode with the modifiers in he high byte, i.e. no room for the
|
||||
@@ -9473,13 +9633,13 @@ convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
|
||||
*/
|
||||
|
||||
UInt32 mods = 0;
|
||||
if (!NILP(Vmac_function_modifier))
|
||||
if (!NILP(Vmac_function_modifier))
|
||||
{
|
||||
GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
|
||||
sizeof (UInt32), NULL, &mods);
|
||||
if (mods & kEventKeyModifierFnMask)
|
||||
if (mods & kEventKeyModifierFnMask)
|
||||
{ *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
|
||||
|
||||
|
||||
return (*newCode != 0);
|
||||
}
|
||||
}
|
||||
@@ -9487,12 +9647,12 @@ convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
backtranslate_modified_keycode(int mods, int keycode, int def)
|
||||
static int
|
||||
backtranslate_modified_keycode(int mods, int keycode, int def)
|
||||
{
|
||||
if (mods &
|
||||
(controlKey |
|
||||
(NILP (Vmac_option_modifier) ? 0 : optionKey) |
|
||||
if (mods &
|
||||
(controlKey |
|
||||
(NILP (Vmac_option_modifier) ? 0 : optionKey) |
|
||||
cmdKey))
|
||||
{
|
||||
/* This code comes from Keyboard Resource,
|
||||
@@ -9504,12 +9664,12 @@ backtranslate_modified_keycode(int mods, int keycode, int def)
|
||||
here also.
|
||||
|
||||
Not done for combinations with the option key (alt)
|
||||
unless it is to be caught by Emacs: this is
|
||||
unless it is to be caught by Emacs: this is
|
||||
to preserve key combinations translated by the OS
|
||||
such as Alt-3.
|
||||
*/
|
||||
/* mask off option and command */
|
||||
int new_modifiers = mods & 0xe600;
|
||||
int new_modifiers = mods & 0xe600;
|
||||
/* set high byte of keycode to modifier high byte*/
|
||||
int new_keycode = keycode | new_modifiers;
|
||||
Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
|
||||
@@ -10126,26 +10286,26 @@ XTread_socket (sd, expected, hold_quit)
|
||||
{
|
||||
inev.code = xkeysym;
|
||||
/* this doesn't work - tried to add shift modifiers */
|
||||
inev.code =
|
||||
backtranslate_modified_keycode(er.modifiers & (~0x2200),
|
||||
xkeysym | 0x80, xkeysym);
|
||||
inev.code =
|
||||
backtranslate_modified_keycode(er.modifiers & (~0x2200),
|
||||
xkeysym | 0x80, xkeysym);
|
||||
inev.kind = ASCII_KEYSTROKE_EVENT;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (keycode_to_xkeysym (keycode, &xkeysym))
|
||||
{
|
||||
inev.code = 0xff00 | xkeysym;
|
||||
inev.kind = NON_ASCII_KEYSTROKE_EVENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
|
||||
inev.code =
|
||||
backtranslate_modified_keycode(er.modifiers, keycode,
|
||||
inev.code =
|
||||
backtranslate_modified_keycode(er.modifiers, keycode,
|
||||
er.message & charCodeMask);
|
||||
inev.kind = ASCII_KEYSTROKE_EVENT;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10587,7 +10747,7 @@ mac_determine_quit_char_modifiers()
|
||||
/* Map modifiers */
|
||||
mac_quit_char_modifiers = 0;
|
||||
if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= controlKey;
|
||||
if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
|
||||
if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
|
||||
if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= optionKey;
|
||||
}
|
||||
|
||||
@@ -10748,7 +10908,7 @@ syms_of_macterm ()
|
||||
Qctrl = intern ("ctrl");
|
||||
Fput (Qctrl, Qmodifier_value, make_number (ctrl_modifier));
|
||||
Qmeta = intern ("meta");
|
||||
Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
|
||||
Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
|
||||
Qalt = intern ("alt");
|
||||
Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
|
||||
Qhyper = intern ("hyper");
|
||||
@@ -10800,13 +10960,13 @@ syms_of_macterm ()
|
||||
|
||||
staticpro (&last_mouse_motion_frame);
|
||||
last_mouse_motion_frame = Qnil;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Variables to configure modifier key assignment. */
|
||||
|
||||
|
||||
DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
|
||||
doc: /* Modifier key assumed when the Mac control key is pressed.
|
||||
doc: /* Modifier key assumed when the Mac control key is pressed.
|
||||
The value can be `alt', `ctrl', `hyper', or `super' for the respective
|
||||
modifier. The default is `ctrl'. */);
|
||||
Vmac_control_modifier = Qctrl;
|
||||
@@ -10815,18 +10975,18 @@ modifier. The default is `ctrl'. */);
|
||||
doc: /* Modifier key assumed when the Mac alt/option key is pressed.
|
||||
The value can be `alt', `ctrl', `hyper', or `super' for the respective
|
||||
modifier. If the value is nil then the key will act as the normal
|
||||
Mac control modifier, and the option key can be used to compose
|
||||
Mac control modifier, and the option key can be used to compose
|
||||
characters depending on the chosen Mac keyboard setting. */);
|
||||
Vmac_option_modifier = Qnil;
|
||||
|
||||
DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
|
||||
doc: /* Modifier key assumed when the Mac command key is pressed.
|
||||
doc: /* Modifier key assumed when the Mac command key is pressed.
|
||||
The value can be `alt', `ctrl', `hyper', or `super' for the respective
|
||||
modifier. The default is `meta'. */);
|
||||
Vmac_command_modifier = Qmeta;
|
||||
|
||||
DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
|
||||
doc: /* Modifier key assumed when the Mac function key is pressed.
|
||||
doc: /* Modifier key assumed when the Mac function key is pressed.
|
||||
The value can be `alt', `ctrl', `hyper', or `super' for the respective
|
||||
modifier. Note that remapping the function key may lead to unexpected
|
||||
results for some keys on non-US/GB keyboards. */);
|
||||
|
||||
Reference in New Issue
Block a user