From c3bd8190a26087ee8e6095b7b1f1a11ff5120125 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Mitsuharu Date: Sat, 1 Oct 2005 11:11:32 +0000 Subject: [PATCH] (mac_draw_string_common, x_per_char_metric) (mac_compute_glyph_string_overhangs, init_font_name_table) (XLoadQueryFont, mac_unload_font) [USE_ATSUI]: Add ATSUI support. (atsu_get_text_layout_with_text_ptr) [USE_ATSUI]: New function. (x_draw_glyph_string_background) (x_draw_glyph_string_foreground) [MAC_OS8 && USE_ATSUI]: Don't use XDrawImageString. Always draw background and foreground separately. (x_draw_glyph_string_foreground) [USE_ATSUI]: Don't use 8-bit functions for one-byte chars when using ATSUI-compatible fonts. (atsu_font_id_hash) [USE_ATSUI]: New variable. (syms_of_macterm) [USE_ATSUI]: Initialize and staticpro it. (XLoadQueryFont): Set min_byte1, max_byte1, min_char_or_byte2, and max_char_or_byte2 more in detail. (quit_char_comp, mac_check_for_quit_char) [MAC_OSX]: Remove functions. --- src/macterm.c | 657 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 526 insertions(+), 131 deletions(-) diff --git a/src/macterm.c b/src/macterm.c index d1b5514f47d..6b37b190b1a 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -658,6 +658,62 @@ mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height) #endif +#if USE_ATSUI +static OSStatus +atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout) + ConstUniCharArrayPtr text; + UniCharCount text_length; + ATSUStyle style; + ATSUTextLayout *text_layout; +{ + OSStatus err; + static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */ + + if (saved_text_layout == NULL) + { + UniCharCount lengths[] = {kATSUToTextEnd}; + ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag}; + ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)}; + static ATSLineLayoutOptions line_layout = +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 + kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics +#else + kATSLineIsDisplayOnly +#endif + ; + ATSUAttributeValuePtr values[] = {&line_layout}; + + err = ATSUCreateTextLayoutWithTextPtr (text, + kATSUFromTextBeginning, + kATSUToTextEnd, + text_length, + 1, lengths, &style, + &saved_text_layout); + if (err == noErr) + err = ATSUSetLayoutControls (saved_text_layout, + sizeof (tags) / sizeof (tags[0]), + tags, sizes, values); + /* XXX: Should we do this? */ + if (err == noErr) + err = ATSUSetTransientFontMatching (saved_text_layout, true); + } + else + { + err = ATSUSetRunStyle (saved_text_layout, style, + kATSUFromTextBeginning, kATSUToTextEnd); + if (err == noErr) + err = ATSUSetTextPointerLocation (saved_text_layout, text, + kATSUFromTextBeginning, + kATSUToTextEnd, + text_length); + } + + if (err == noErr) + *text_layout = saved_text_layout; + return err; +} +#endif + static void mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode, bytes_per_char) @@ -682,6 +738,89 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode, if (mode != srcOr) RGBBackColor (GC_BACK_COLOR (gc)); +#if USE_ATSUI + if (GC_FONT (gc)->mac_style) + { + OSErr err; + ATSUTextLayout text_layout; + + xassert (bytes_per_char == 2); + +#ifndef WORDS_BIG_ENDIAN + { + int i; + Unichar *text = (Unichar *)buf; + + for (i = 0; i < nchars; i++) + text[i] = buf[2*i] << 8 | buf[2*i+1]; + } +#endif + err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf, + nchars, + GC_FONT (gc)->mac_style, + &text_layout); + if (err == noErr) + { +#ifdef MAC_OSX + if (NILP (Vmac_use_core_graphics)) + { +#endif + MoveTo (x, y); + ATSUDrawText (text_layout, + kATSUFromTextBeginning, kATSUToTextEnd, + kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); +#ifdef MAC_OSX + } + else + { + CGrafPtr port; + CGContextRef context; + Rect rect; + RgnHandle region = NewRgn (); + float port_height; + ATSUAttributeTag tags[] = {kATSUCGContextTag}; + ByteCount sizes[] = {sizeof (CGContextRef)}; + ATSUAttributeValuePtr values[] = {&context}; + + GetPort (&port); + QDBeginCGContext (port, &context); + GetPortBounds (port, &rect); + port_height = rect.bottom - rect.top; + GetClip (region); + GetRegionBounds (region, &rect); + /* XXX: This is not correct if the clip region is not a + simple rectangle. */ + CGContextClipToRect (context, + CGRectMake (rect.left, + port_height - rect.bottom, + rect.right - rect.left, + rect.bottom - rect.top)); + DisposeRgn (region); + 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); + err = ATSUSetLayoutControls (text_layout, + sizeof (tags) / sizeof (tags[0]), + tags, sizes, values); + if (err == noErr) + ATSUDrawText (text_layout, + kATSUFromTextBeginning, kATSUToTextEnd, + Long2Fix (x), Long2Fix (port_height - y)); + ATSUClearLayoutControls (text_layout, + sizeof (tags) / sizeof (tags[0]), + tags); + CGContextSynchronize (context); + QDEndCGContext (port, &context); + } +#endif + } + } + else + { +#endif TextFont (GC_FONT (gc)->mac_fontnum); TextSize (GC_FONT (gc)->mac_fontsize); TextFace (GC_FONT (gc)->mac_fontface); @@ -689,6 +828,9 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode, MoveTo (x, y); DrawText (buf, 0, nchars * bytes_per_char); +#if USE_ATSUI + } +#endif if (mode != srcOr) RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w))); @@ -1549,6 +1691,61 @@ x_per_char_metric (font, char2b) xassert (font && char2b); +#if USE_ATSUI + if (font->mac_style) + { + if (char2b->byte1 >= font->min_byte1 + && char2b->byte1 <= font->max_byte1 + && char2b->byte2 >= font->min_char_or_byte2 + && char2b->byte2 <= font->max_char_or_byte2) + { + pcm = (font->per_char + + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) + * (char2b->byte1 - font->min_byte1)) + + (char2b->byte2 - font->min_char_or_byte2)); + } + + if (pcm && !pcm->valid_p) + { + OSErr err; + ATSUTextLayout text_layout; + UniChar c; + int char_width; + ATSTrapezoid glyph_bounds; + Rect char_bounds; + + c = (char2b->byte1 << 8) + char2b->byte2; + BLOCK_INPUT; + err = atsu_get_text_layout_with_text_ptr (&c, 1, + font->mac_style, + &text_layout); + if (err == noErr) + err = ATSUMeasureTextImage (text_layout, + kATSUFromTextBeginning, kATSUToTextEnd, + 0, 0, &char_bounds); + + if (err == noErr) + err = ATSUGetGlyphBounds (text_layout, 0, 0, + kATSUFromTextBeginning, kATSUToTextEnd, + kATSUseFractionalOrigins, 1, + &glyph_bounds, NULL); + UNBLOCK_INPUT; + if (err != noErr) + pcm = NULL; + else + { + xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x + == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); + + char_width = Fix2Long (glyph_bounds.upperRight.x + - glyph_bounds.upperLeft.x); + STORE_XCHARSTRUCT (*pcm, char_width, char_bounds); + } + } + } + else + { +#endif if (font->per_char != NULL) { if (font->min_byte1 == 0 && font->max_byte1 == 0) @@ -1600,6 +1797,9 @@ x_per_char_metric (font, char2b) && char2b->byte2 <= font->max_char_or_byte2) pcm = &font->max_bounds; } +#if USE_ATSUI + } +#endif return ((pcm == NULL || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)) @@ -1925,6 +2125,35 @@ mac_compute_glyph_string_overhangs (s) Rect r; MacFontStruct *font = s->font; +#if USE_ATSUI + if (font->mac_style) + { + OSErr err; + ATSUTextLayout text_layout; + UniChar *buf; + int i; + + SetRect (&r, 0, 0, 0, 0); + buf = xmalloc (sizeof (UniChar) * s->nchars); + if (buf) + { + for (i = 0; i < s->nchars; i++) + buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2; + + err = atsu_get_text_layout_with_text_ptr (buf, s->nchars, + font->mac_style, + &text_layout); + if (err == noErr) + err = ATSUMeasureTextImage (text_layout, + kATSUFromTextBeginning, + kATSUToTextEnd, + 0, 0, &r); + xfree (buf); + } + } + else + { +#endif TextFont (font->mac_fontnum); TextSize (font->mac_fontsize); TextFace (font->mac_fontface); @@ -1946,6 +2175,9 @@ mac_compute_glyph_string_overhangs (s) xfree (buf); } } +#if USE_ATSUI + } +#endif s->right_overhang = r.right > s->width ? r.right - s->width : 0; s->left_overhang = r.left < 0 ? -r.left : 0; @@ -2003,7 +2235,7 @@ x_draw_glyph_string_background (s, force_p) } else #endif -#ifdef MAC_OS8 +#if defined (MAC_OS8) && !USE_ATSUI if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width || s->font_not_found_p || s->extends_to_end_of_line_p @@ -2057,11 +2289,15 @@ x_draw_glyph_string_foreground (s) boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff; /* If we can use 8-bit functions, condense S->char2b. */ - if (!s->two_byte_p) + if (!s->two_byte_p +#if USE_ATSUI + && GC_FONT (s->gc)->mac_style == NULL +#endif + ) for (i = 0; i < s->nchars; ++i) char1b[i] = s->char2b[i].byte2; -#ifdef MAC_OS8 +#if defined (MAC_OS8) && !USE_ATSUI /* Draw text with XDrawString if background has already been filled. Otherwise, use XDrawImageString. (Note that XDrawImageString is usually faster than XDrawString.) Always @@ -2072,14 +2308,18 @@ x_draw_glyph_string_foreground (s) #endif { /* Draw characters with 16-bit or 8-bit functions. */ - if (s->two_byte_p) + if (s->two_byte_p +#if USE_ATSUI + || GC_FONT (s->gc)->mac_style +#endif + ) XDrawString16 (s->display, s->window, s->gc, x, s->ybase - boff, s->char2b, s->nchars); else XDrawString (s->display, s->window, s->gc, x, s->ybase - boff, char1b, s->nchars); } -#ifdef MAC_OS8 +#if defined (MAC_OS8) && !USE_ATSUI else { if (s->two_byte_p) @@ -6431,6 +6671,10 @@ static char **font_name_table = NULL; static int font_name_table_size = 0; static int font_name_count = 0; +#if USE_ATSUI +static Lisp_Object atsu_font_id_hash; +#endif + /* Alist linking character set strings to Mac text encoding and Emacs coding system. */ static Lisp_Object Vmac_charset_info_alist; @@ -6630,6 +6874,74 @@ init_font_name_table () Lisp_Object text_encoding_info_alist; struct gcpro gcpro1; + text_encoding_info_alist = create_text_encoding_info_alist (); + +#if USE_ATSUI + if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode), + text_encoding_info_alist))) + { + OSErr err; + ItemCount nfonts, i; + ATSUFontID *font_ids = NULL; + Ptr name, prev_name = NULL; + ByteCount name_len; + + atsu_font_id_hash = + make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE), + make_float (DEFAULT_REHASH_SIZE), + make_float (DEFAULT_REHASH_THRESHOLD), + Qnil, Qnil, Qnil);; + err = ATSUFontCount (&nfonts); + if (err == noErr) + font_ids = xmalloc (sizeof (ATSUFontID) * nfonts); + if (font_ids) + err = ATSUGetFontIDs (font_ids, nfonts, NULL); + if (err == noErr) + for (i = 0; i < nfonts; i++) + { + err = ATSUFindFontName (font_ids[i], kFontFamilyName, + kFontMacintoshPlatform, kFontNoScript, + kFontNoLanguage, 0, NULL, &name_len, NULL); + if (err != noErr) + continue; + name = xmalloc (name_len + 1); + if (name == NULL) + continue; + name[name_len] = '\0'; + err = ATSUFindFontName (font_ids[i], kFontFamilyName, + kFontMacintoshPlatform, kFontNoScript, + kFontNoLanguage, name_len, name, + NULL, NULL); + if (err == noErr + && *name != '.' + && (prev_name == NULL + || strcmp (name, prev_name) != 0)) + { + static char *cs = "iso10646-1"; + + add_font_name_table_entry (mac_to_x_fontname (name, 0, + normal, cs)); + add_font_name_table_entry (mac_to_x_fontname (name, 0, + italic, cs)); + add_font_name_table_entry (mac_to_x_fontname (name, 0, + bold, cs)); + add_font_name_table_entry (mac_to_x_fontname (name, 0, + italic | bold, cs)); + Fputhash (Fdowncase (make_unibyte_string (name, name_len)), + long_to_cons (font_ids[i]), atsu_font_id_hash); + xfree (prev_name); + prev_name = name; + } + else + xfree (name); + } + if (prev_name) + xfree (prev_name); + if (font_ids) + xfree (font_ids); + } +#endif + /* Create a dummy instance iterator here to avoid creating and destroying it in the loop. */ if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr) @@ -6642,8 +6954,6 @@ init_font_name_table () return; } - text_encoding_info_alist = create_text_encoding_info_alist (); - GCPRO1 (text_encoding_info_alist); while (FMGetNextFontFamily (&ffi, &ff) == noErr) @@ -7140,6 +7450,9 @@ XLoadQueryFont (Display *dpy, char *fontname) Str255 mfontname, mfontname_decoded; Str31 charset; SInt16 fontnum; +#if USE_ATSUI + ATSUStyle mac_style = NULL; +#endif Style fontface; #if TARGET_API_MAC_CARBON TextEncoding encoding; @@ -7191,6 +7504,48 @@ XLoadQueryFont (Display *dpy, char *fontname) x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded, &fontface, charset); +#if USE_ATSUI + if (strcmp (charset, "iso10646-1") == 0) /* XXX */ + { + OSErr err; + ATSUAttributeTag tags[] = {kATSUFontTag, kATSUSizeTag, + 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, + &bold_p, &italic_p}; + ATSUFontFeatureType types[] = {kAllTypographicFeaturesType}; + ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector}; + Lisp_Object font_id_cons; + + font_id_cons = Fgethash (Fdowncase + (make_unibyte_string (mfontname, + strlen (mfontname))), + atsu_font_id_hash, Qnil); + if (NILP (font_id_cons)) + return NULL; + font_id = cons_to_long (font_id_cons); + size_fixed = Long2Fix (size); + bold_p = (fontface & bold) != 0; + italic_p = (fontface & italic) != 0; + err = ATSUCreateStyle (&mac_style); + if (err != noErr) + return NULL; + err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]), + types, selectors); + if (err != noErr) + return NULL; + err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]), + tags, sizes, values); + fontnum = -1; + scriptcode = kTextEncodingMacUnicode; + } + else + { +#endif c2pstr (mfontname); #if TARGET_API_MAC_CARBON fontnum = FMGetFontFamilyFromName (mfontname); @@ -7204,6 +7559,9 @@ XLoadQueryFont (Display *dpy, char *fontname) return NULL; scriptcode = FontToScript (fontnum); #endif +#if USE_ATSUI + } +#endif font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct)); @@ -7211,6 +7569,9 @@ XLoadQueryFont (Display *dpy, char *fontname) font->mac_fontsize = size; font->mac_fontface = fontface; font->mac_scriptcode = scriptcode; +#if USE_ATSUI + font->mac_style = mac_style; +#endif /* Apple Japanese (SJIS) font is listed as both "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0" @@ -7221,6 +7582,91 @@ XLoadQueryFont (Display *dpy, char *fontname) font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset); +#if USE_ATSUI + if (font->mac_style) + { + OSErr err; + ATSUTextLayout text_layout; + UniChar c = 0x20; + Rect char_bounds, min_bounds, max_bounds; + int min_width, max_width; + ATSTrapezoid glyph_bounds; + + font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000); + if (font->per_char == NULL) + { + mac_unload_font (&one_mac_display_info, font); + return NULL; + } + bzero (font->per_char, sizeof (XCharStruct) * 0x10000); + + err = atsu_get_text_layout_with_text_ptr (&c, 1, + font->mac_style, + &text_layout); + if (err != noErr) + { + mac_unload_font (&one_mac_display_info, font); + return NULL; + } + + for (c = 0x20; c <= 0x7e; c++) + { + err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning); + if (err == noErr) + err = ATSUMeasureTextImage (text_layout, + kATSUFromTextBeginning, kATSUToTextEnd, + 0, 0, &char_bounds); + if (err == noErr) + err = ATSUGetGlyphBounds (text_layout, 0, 0, + kATSUFromTextBeginning, kATSUToTextEnd, + kATSUseFractionalOrigins, 1, + &glyph_bounds, NULL); + if (err == noErr) + { + xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x + == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); + + char_width = Fix2Long (glyph_bounds.upperRight.x + - glyph_bounds.upperLeft.x); + STORE_XCHARSTRUCT (font->per_char[c], + char_width, char_bounds); + if (c == 0x20) + { + min_width = max_width = char_width; + min_bounds = max_bounds = char_bounds; + font->ascent = -Fix2Long (glyph_bounds.upperLeft.y); + font->descent = Fix2Long (glyph_bounds.lowerLeft.y); + } + else + { + if (char_width > 0) + { + min_width = min (min_width, char_width); + max_width = max (max_width, char_width); + } + if (!EmptyRect (&char_bounds)) + { + SetRect (&min_bounds, + max (min_bounds.left, char_bounds.left), + max (min_bounds.top, char_bounds.top), + min (min_bounds.right, char_bounds.right), + min (min_bounds.bottom, char_bounds.bottom)); + 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); + + font->min_byte1 = 0; + font->max_byte1 = 0xff; + font->min_char_or_byte2 = 0; + font->max_char_or_byte2 = 0xff; + } + else + { +#endif is_two_byte_font = font->mac_scriptcode == smJapanese || font->mac_scriptcode == smTradChinese || font->mac_scriptcode == smSimpChinese || @@ -7235,24 +7681,26 @@ XLoadQueryFont (Display *dpy, char *fontname) font->ascent = the_fontinfo.ascent; font->descent = the_fontinfo.descent; - font->min_byte1 = 0; - if (is_two_byte_font) - font->max_byte1 = 1; - else - font->max_byte1 = 0; - font->min_char_or_byte2 = 0x20; - font->max_char_or_byte2 = 0xff; - if (is_two_byte_font) { + font->min_byte1 = 0xa1; + font->max_byte1 = 0xfe; + font->min_char_or_byte2 = 0xa1; + font->max_char_or_byte2 = 0xfe; + /* Use the width of an "ideographic space" of that font because the_fontinfo.widMax returns the wrong width for some fonts. */ switch (font->mac_scriptcode) { case smJapanese: + font->min_byte1 = 0x81; + font->max_byte1 = 0xfc; + font->min_char_or_byte2 = 0x40; + font->max_char_or_byte2 = 0xfc; char_width = StringWidth("\p\x81\x40"); break; case smTradChinese: + font->min_char_or_byte2 = 0x40; char_width = StringWidth("\p\xa1\x40"); break; case smSimpChinese: @@ -7264,9 +7712,15 @@ XLoadQueryFont (Display *dpy, char *fontname) } } else - /* Do this instead of use the_fontinfo.widMax, which incorrectly - returns 15 for 12-point Monaco! */ - char_width = CharWidth ('m'); + { + font->min_byte1 = font->max_byte1 = 0; + font->min_char_or_byte2 = 0x20; + font->max_char_or_byte2 = 0xff; + + /* Do this instead of use the_fontinfo.widMax, which incorrectly + returns 15 for 12-point Monaco! */ + char_width = CharWidth ('m'); + } if (is_two_byte_font) { @@ -7285,55 +7739,56 @@ XLoadQueryFont (Display *dpy, char *fontname) } else { - font->per_char = (XCharStruct *) - xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); - { - int c, min_width, max_width; - Rect char_bounds, min_bounds, max_bounds; - char ch; - - min_width = max_width = char_width; - SetRect (&min_bounds, -32767, -32767, 32767, 32767); - SetRect (&max_bounds, 0, 0, 0, 0); - for (c = 0x20; c <= 0xff; c++) - { - ch = c; - char_width = CharWidth (ch); - QDTextBounds (1, &ch, &char_bounds); - STORE_XCHARSTRUCT (font->per_char[c - 0x20], - char_width, char_bounds); - /* Some Japanese fonts (in SJIS encoding) return 0 as the - character width of 0x7f. */ - if (char_width > 0) - { - min_width = min (min_width, char_width); - max_width = max (max_width, char_width); - } - if (!EmptyRect (&char_bounds)) - { - SetRect (&min_bounds, - max (min_bounds.left, char_bounds.left), - max (min_bounds.top, char_bounds.top), - min (min_bounds.right, char_bounds.right), - min (min_bounds.bottom, char_bounds.bottom)); - 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) - { - /* Fixed width and no overhangs. */ - xfree (font->per_char); - font->per_char = NULL; - } - } + int c, min_width, max_width; + Rect char_bounds, min_bounds, max_bounds; + char ch; + + font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); + + min_width = max_width = char_width; + SetRect (&min_bounds, -32767, -32767, 32767, 32767); + SetRect (&max_bounds, 0, 0, 0, 0); + for (c = 0x20; c <= 0xff; c++) + { + ch = c; + char_width = CharWidth (ch); + QDTextBounds (1, &ch, &char_bounds); + STORE_XCHARSTRUCT (font->per_char[c - 0x20], + char_width, char_bounds); + /* Some Japanese fonts (in SJIS encoding) return 0 as the + character width of 0x7f. */ + if (char_width > 0) + { + min_width = min (min_width, char_width); + max_width = max (max_width, char_width); + } + if (!EmptyRect (&char_bounds)) + { + SetRect (&min_bounds, + max (min_bounds.left, char_bounds.left), + max (min_bounds.top, char_bounds.top), + min (min_bounds.right, char_bounds.right), + min (min_bounds.bottom, char_bounds.bottom)); + 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) + { + /* Fixed width and no overhangs. */ + xfree (font->per_char); + font->per_char = NULL; + } } TextFont (old_fontnum); /* restore previous font number, size and face */ TextSize (old_fontsize); TextFace (old_fontface); +#if USE_ATSUI + } +#endif return font; } @@ -7347,6 +7802,10 @@ mac_unload_font (dpyinfo, font) xfree (font->full_name); if (font->per_char) xfree (font->per_char); +#if USE_ATSUI + if (font->mac_style) + ATSUDisposeStyle (font->mac_style); +#endif xfree (font); } @@ -10189,75 +10648,6 @@ init_quit_char_handler () mac_determine_quit_char_modifiers(); } - -static Boolean -quit_char_comp (EventRef inEvent, void *inCompData) -{ - if (GetEventClass(inEvent) != kEventClassKeyboard) - return false; - if (GetEventKind(inEvent) != kEventRawKeyDown) - return false; - { - UInt32 keyCode; - UInt32 keyModifiers; - GetEventParameter(inEvent, kEventParamKeyCode, - typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); - if (keyCode != mac_quit_char_keycode) - return false; - GetEventParameter(inEvent, kEventParamKeyModifiers, - typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers); - if (keyModifiers != mac_quit_char_modifiers) - return false; - } - return true; -} - -void -mac_check_for_quit_char () -{ - EventRef event; - static EMACS_TIME last_check_time = { 0, 0 }; - static EMACS_TIME one_second = { 1, 0 }; - EMACS_TIME now, t; - - /* If windows are not initialized, return immediately (keep it bouncin'). */ - if (!mac_quit_char_modifiers) - return; - - /* Don't check if last check is less than a second ago. */ - EMACS_GET_TIME (now); - EMACS_SUB_TIME (t, now, last_check_time); - if (EMACS_TIME_LT (t, one_second)) - return; - last_check_time = now; - - /* Redetermine modifiers because they are based on lisp variables */ - mac_determine_quit_char_modifiers (); - - /* Fill the queue with events */ - BLOCK_INPUT; - ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event); - event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp, - NULL); - UNBLOCK_INPUT; - if (event) - { - struct input_event e; - - /* Use an input_event to emulate what the interrupt handler does. */ - EVENT_INIT (e); - e.kind = ASCII_KEYSTROKE_EVENT; - e.code = quit_char; - e.arg = Qnil; - e.modifiers = NULL; - e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60); - XSETFRAME (e.frame_or_window, mac_focus_frame (&one_mac_display_info)); - /* Remove event from queue to prevent looping. */ - RemoveEventFromQueue (GetMainEventQueue (), event); - ReleaseEvent (event); - kbd_buffer_store_event (&e); - } -} #endif /* MAC_OSX */ static void @@ -10435,6 +10825,11 @@ syms_of_macterm () Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop"); staticpro (&Qmac_ready_for_drag_n_drop); +#if USE_ATSUI + staticpro (&atsu_font_id_hash); + atsu_font_id_hash = Qnil; +#endif + DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, doc: /* If not nil, Emacs uses toolkit scroll bars. */); #ifdef USE_TOOLKIT_SCROLL_BARS -- 2.39.2