aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2005-10-01 11:11:32 +0000
committerYAMAMOTO Mitsuharu2005-10-01 11:11:32 +0000
commitc3bd8190a26087ee8e6095b7b1f1a11ff5120125 (patch)
tree0b8737a6b0753f8fa98d1baab5ece7bc0c8b75a2 /src
parent04904a238eda88318e50c3d9b121ff492fb0cb72 (diff)
downloademacs-c3bd8190a26087ee8e6095b7b1f1a11ff5120125.tar.gz
emacs-c3bd8190a26087ee8e6095b7b1f1a11ff5120125.zip
(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.
Diffstat (limited to 'src')
-rw-r--r--src/macterm.c657
1 files 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)
658#endif 658#endif
659 659
660 660
661#if USE_ATSUI
662static OSStatus
663atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
664 ConstUniCharArrayPtr text;
665 UniCharCount text_length;
666 ATSUStyle style;
667 ATSUTextLayout *text_layout;
668{
669 OSStatus err;
670 static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
671
672 if (saved_text_layout == NULL)
673 {
674 UniCharCount lengths[] = {kATSUToTextEnd};
675 ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
676 ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
677 static ATSLineLayoutOptions line_layout =
678#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
679 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
680#else
681 kATSLineIsDisplayOnly
682#endif
683 ;
684 ATSUAttributeValuePtr values[] = {&line_layout};
685
686 err = ATSUCreateTextLayoutWithTextPtr (text,
687 kATSUFromTextBeginning,
688 kATSUToTextEnd,
689 text_length,
690 1, lengths, &style,
691 &saved_text_layout);
692 if (err == noErr)
693 err = ATSUSetLayoutControls (saved_text_layout,
694 sizeof (tags) / sizeof (tags[0]),
695 tags, sizes, values);
696 /* XXX: Should we do this? */
697 if (err == noErr)
698 err = ATSUSetTransientFontMatching (saved_text_layout, true);
699 }
700 else
701 {
702 err = ATSUSetRunStyle (saved_text_layout, style,
703 kATSUFromTextBeginning, kATSUToTextEnd);
704 if (err == noErr)
705 err = ATSUSetTextPointerLocation (saved_text_layout, text,
706 kATSUFromTextBeginning,
707 kATSUToTextEnd,
708 text_length);
709 }
710
711 if (err == noErr)
712 *text_layout = saved_text_layout;
713 return err;
714}
715#endif
716
661static void 717static void
662mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode, 718mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
663 bytes_per_char) 719 bytes_per_char)
@@ -682,6 +738,89 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
682 if (mode != srcOr) 738 if (mode != srcOr)
683 RGBBackColor (GC_BACK_COLOR (gc)); 739 RGBBackColor (GC_BACK_COLOR (gc));
684 740
741#if USE_ATSUI
742 if (GC_FONT (gc)->mac_style)
743 {
744 OSErr err;
745 ATSUTextLayout text_layout;
746
747 xassert (bytes_per_char == 2);
748
749#ifndef WORDS_BIG_ENDIAN
750 {
751 int i;
752 Unichar *text = (Unichar *)buf;
753
754 for (i = 0; i < nchars; i++)
755 text[i] = buf[2*i] << 8 | buf[2*i+1];
756 }
757#endif
758 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
759 nchars,
760 GC_FONT (gc)->mac_style,
761 &text_layout);
762 if (err == noErr)
763 {
764#ifdef MAC_OSX
765 if (NILP (Vmac_use_core_graphics))
766 {
767#endif
768 MoveTo (x, y);
769 ATSUDrawText (text_layout,
770 kATSUFromTextBeginning, kATSUToTextEnd,
771 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
772#ifdef MAC_OSX
773 }
774 else
775 {
776 CGrafPtr port;
777 CGContextRef context;
778 Rect rect;
779 RgnHandle region = NewRgn ();
780 float port_height;
781 ATSUAttributeTag tags[] = {kATSUCGContextTag};
782 ByteCount sizes[] = {sizeof (CGContextRef)};
783 ATSUAttributeValuePtr values[] = {&context};
784
785 GetPort (&port);
786 QDBeginCGContext (port, &context);
787 GetPortBounds (port, &rect);
788 port_height = rect.bottom - rect.top;
789 GetClip (region);
790 GetRegionBounds (region, &rect);
791 /* XXX: This is not correct if the clip region is not a
792 simple rectangle. */
793 CGContextClipToRect (context,
794 CGRectMake (rect.left,
795 port_height - rect.bottom,
796 rect.right - rect.left,
797 rect.bottom - rect.top));
798 DisposeRgn (region);
799 CGContextSetRGBFillColor
800 (context,
801 RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
802 GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
803 BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
804 1.0);
805 err = ATSUSetLayoutControls (text_layout,
806 sizeof (tags) / sizeof (tags[0]),
807 tags, sizes, values);
808 if (err == noErr)
809 ATSUDrawText (text_layout,
810 kATSUFromTextBeginning, kATSUToTextEnd,
811 Long2Fix (x), Long2Fix (port_height - y));
812 ATSUClearLayoutControls (text_layout,
813 sizeof (tags) / sizeof (tags[0]),
814 tags);
815 CGContextSynchronize (context);
816 QDEndCGContext (port, &context);
817 }
818#endif
819 }
820 }
821 else
822 {
823#endif
685 TextFont (GC_FONT (gc)->mac_fontnum); 824 TextFont (GC_FONT (gc)->mac_fontnum);
686 TextSize (GC_FONT (gc)->mac_fontsize); 825 TextSize (GC_FONT (gc)->mac_fontsize);
687 TextFace (GC_FONT (gc)->mac_fontface); 826 TextFace (GC_FONT (gc)->mac_fontface);
@@ -689,6 +828,9 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
689 828
690 MoveTo (x, y); 829 MoveTo (x, y);
691 DrawText (buf, 0, nchars * bytes_per_char); 830 DrawText (buf, 0, nchars * bytes_per_char);
831#if USE_ATSUI
832 }
833#endif
692 834
693 if (mode != srcOr) 835 if (mode != srcOr)
694 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w))); 836 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
@@ -1549,6 +1691,61 @@ x_per_char_metric (font, char2b)
1549 1691
1550 xassert (font && char2b); 1692 xassert (font && char2b);
1551 1693
1694#if USE_ATSUI
1695 if (font->mac_style)
1696 {
1697 if (char2b->byte1 >= font->min_byte1
1698 && char2b->byte1 <= font->max_byte1
1699 && char2b->byte2 >= font->min_char_or_byte2
1700 && char2b->byte2 <= font->max_char_or_byte2)
1701 {
1702 pcm = (font->per_char
1703 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1704 * (char2b->byte1 - font->min_byte1))
1705 + (char2b->byte2 - font->min_char_or_byte2));
1706 }
1707
1708 if (pcm && !pcm->valid_p)
1709 {
1710 OSErr err;
1711 ATSUTextLayout text_layout;
1712 UniChar c;
1713 int char_width;
1714 ATSTrapezoid glyph_bounds;
1715 Rect char_bounds;
1716
1717 c = (char2b->byte1 << 8) + char2b->byte2;
1718 BLOCK_INPUT;
1719 err = atsu_get_text_layout_with_text_ptr (&c, 1,
1720 font->mac_style,
1721 &text_layout);
1722 if (err == noErr)
1723 err = ATSUMeasureTextImage (text_layout,
1724 kATSUFromTextBeginning, kATSUToTextEnd,
1725 0, 0, &char_bounds);
1726
1727 if (err == noErr)
1728 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1729 kATSUFromTextBeginning, kATSUToTextEnd,
1730 kATSUseFractionalOrigins, 1,
1731 &glyph_bounds, NULL);
1732 UNBLOCK_INPUT;
1733 if (err != noErr)
1734 pcm = NULL;
1735 else
1736 {
1737 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1738 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1739
1740 char_width = Fix2Long (glyph_bounds.upperRight.x
1741 - glyph_bounds.upperLeft.x);
1742 STORE_XCHARSTRUCT (*pcm, char_width, char_bounds);
1743 }
1744 }
1745 }
1746 else
1747 {
1748#endif
1552 if (font->per_char != NULL) 1749 if (font->per_char != NULL)
1553 { 1750 {
1554 if (font->min_byte1 == 0 && font->max_byte1 == 0) 1751 if (font->min_byte1 == 0 && font->max_byte1 == 0)
@@ -1600,6 +1797,9 @@ x_per_char_metric (font, char2b)
1600 && char2b->byte2 <= font->max_char_or_byte2) 1797 && char2b->byte2 <= font->max_char_or_byte2)
1601 pcm = &font->max_bounds; 1798 pcm = &font->max_bounds;
1602 } 1799 }
1800#if USE_ATSUI
1801 }
1802#endif
1603 1803
1604 return ((pcm == NULL 1804 return ((pcm == NULL
1605 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)) 1805 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
@@ -1925,6 +2125,35 @@ mac_compute_glyph_string_overhangs (s)
1925 Rect r; 2125 Rect r;
1926 MacFontStruct *font = s->font; 2126 MacFontStruct *font = s->font;
1927 2127
2128#if USE_ATSUI
2129 if (font->mac_style)
2130 {
2131 OSErr err;
2132 ATSUTextLayout text_layout;
2133 UniChar *buf;
2134 int i;
2135
2136 SetRect (&r, 0, 0, 0, 0);
2137 buf = xmalloc (sizeof (UniChar) * s->nchars);
2138 if (buf)
2139 {
2140 for (i = 0; i < s->nchars; i++)
2141 buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2;
2142
2143 err = atsu_get_text_layout_with_text_ptr (buf, s->nchars,
2144 font->mac_style,
2145 &text_layout);
2146 if (err == noErr)
2147 err = ATSUMeasureTextImage (text_layout,
2148 kATSUFromTextBeginning,
2149 kATSUToTextEnd,
2150 0, 0, &r);
2151 xfree (buf);
2152 }
2153 }
2154 else
2155 {
2156#endif
1928 TextFont (font->mac_fontnum); 2157 TextFont (font->mac_fontnum);
1929 TextSize (font->mac_fontsize); 2158 TextSize (font->mac_fontsize);
1930 TextFace (font->mac_fontface); 2159 TextFace (font->mac_fontface);
@@ -1946,6 +2175,9 @@ mac_compute_glyph_string_overhangs (s)
1946 xfree (buf); 2175 xfree (buf);
1947 } 2176 }
1948 } 2177 }
2178#if USE_ATSUI
2179 }
2180#endif
1949 2181
1950 s->right_overhang = r.right > s->width ? r.right - s->width : 0; 2182 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
1951 s->left_overhang = r.left < 0 ? -r.left : 0; 2183 s->left_overhang = r.left < 0 ? -r.left : 0;
@@ -2003,7 +2235,7 @@ x_draw_glyph_string_background (s, force_p)
2003 } 2235 }
2004 else 2236 else
2005#endif 2237#endif
2006#ifdef MAC_OS8 2238#if defined (MAC_OS8) && !USE_ATSUI
2007 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width 2239 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2008 || s->font_not_found_p 2240 || s->font_not_found_p
2009 || s->extends_to_end_of_line_p 2241 || s->extends_to_end_of_line_p
@@ -2057,11 +2289,15 @@ x_draw_glyph_string_foreground (s)
2057 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff; 2289 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2058 2290
2059 /* If we can use 8-bit functions, condense S->char2b. */ 2291 /* If we can use 8-bit functions, condense S->char2b. */
2060 if (!s->two_byte_p) 2292 if (!s->two_byte_p
2293#if USE_ATSUI
2294 && GC_FONT (s->gc)->mac_style == NULL
2295#endif
2296 )
2061 for (i = 0; i < s->nchars; ++i) 2297 for (i = 0; i < s->nchars; ++i)
2062 char1b[i] = s->char2b[i].byte2; 2298 char1b[i] = s->char2b[i].byte2;
2063 2299
2064#ifdef MAC_OS8 2300#if defined (MAC_OS8) && !USE_ATSUI
2065 /* Draw text with XDrawString if background has already been 2301 /* Draw text with XDrawString if background has already been
2066 filled. Otherwise, use XDrawImageString. (Note that 2302 filled. Otherwise, use XDrawImageString. (Note that
2067 XDrawImageString is usually faster than XDrawString.) Always 2303 XDrawImageString is usually faster than XDrawString.) Always
@@ -2072,14 +2308,18 @@ x_draw_glyph_string_foreground (s)
2072#endif 2308#endif
2073 { 2309 {
2074 /* Draw characters with 16-bit or 8-bit functions. */ 2310 /* Draw characters with 16-bit or 8-bit functions. */
2075 if (s->two_byte_p) 2311 if (s->two_byte_p
2312#if USE_ATSUI
2313 || GC_FONT (s->gc)->mac_style
2314#endif
2315 )
2076 XDrawString16 (s->display, s->window, s->gc, x, 2316 XDrawString16 (s->display, s->window, s->gc, x,
2077 s->ybase - boff, s->char2b, s->nchars); 2317 s->ybase - boff, s->char2b, s->nchars);
2078 else 2318 else
2079 XDrawString (s->display, s->window, s->gc, x, 2319 XDrawString (s->display, s->window, s->gc, x,
2080 s->ybase - boff, char1b, s->nchars); 2320 s->ybase - boff, char1b, s->nchars);
2081 } 2321 }
2082#ifdef MAC_OS8 2322#if defined (MAC_OS8) && !USE_ATSUI
2083 else 2323 else
2084 { 2324 {
2085 if (s->two_byte_p) 2325 if (s->two_byte_p)
@@ -6431,6 +6671,10 @@ static char **font_name_table = NULL;
6431static int font_name_table_size = 0; 6671static int font_name_table_size = 0;
6432static int font_name_count = 0; 6672static int font_name_count = 0;
6433 6673
6674#if USE_ATSUI
6675static Lisp_Object atsu_font_id_hash;
6676#endif
6677
6434/* Alist linking character set strings to Mac text encoding and Emacs 6678/* Alist linking character set strings to Mac text encoding and Emacs
6435 coding system. */ 6679 coding system. */
6436static Lisp_Object Vmac_charset_info_alist; 6680static Lisp_Object Vmac_charset_info_alist;
@@ -6630,6 +6874,74 @@ init_font_name_table ()
6630 Lisp_Object text_encoding_info_alist; 6874 Lisp_Object text_encoding_info_alist;
6631 struct gcpro gcpro1; 6875 struct gcpro gcpro1;
6632 6876
6877 text_encoding_info_alist = create_text_encoding_info_alist ();
6878
6879#if USE_ATSUI
6880 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
6881 text_encoding_info_alist)))
6882 {
6883 OSErr err;
6884 ItemCount nfonts, i;
6885 ATSUFontID *font_ids = NULL;
6886 Ptr name, prev_name = NULL;
6887 ByteCount name_len;
6888
6889 atsu_font_id_hash =
6890 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
6891 make_float (DEFAULT_REHASH_SIZE),
6892 make_float (DEFAULT_REHASH_THRESHOLD),
6893 Qnil, Qnil, Qnil);;
6894 err = ATSUFontCount (&nfonts);
6895 if (err == noErr)
6896 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
6897 if (font_ids)
6898 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
6899 if (err == noErr)
6900 for (i = 0; i < nfonts; i++)
6901 {
6902 err = ATSUFindFontName (font_ids[i], kFontFamilyName,
6903 kFontMacintoshPlatform, kFontNoScript,
6904 kFontNoLanguage, 0, NULL, &name_len, NULL);
6905 if (err != noErr)
6906 continue;
6907 name = xmalloc (name_len + 1);
6908 if (name == NULL)
6909 continue;
6910 name[name_len] = '\0';
6911 err = ATSUFindFontName (font_ids[i], kFontFamilyName,
6912 kFontMacintoshPlatform, kFontNoScript,
6913 kFontNoLanguage, name_len, name,
6914 NULL, NULL);
6915 if (err == noErr
6916 && *name != '.'
6917 && (prev_name == NULL
6918 || strcmp (name, prev_name) != 0))
6919 {
6920 static char *cs = "iso10646-1";
6921
6922 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6923 normal, cs));
6924 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6925 italic, cs));
6926 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6927 bold, cs));
6928 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6929 italic | bold, cs));
6930 Fputhash (Fdowncase (make_unibyte_string (name, name_len)),
6931 long_to_cons (font_ids[i]), atsu_font_id_hash);
6932 xfree (prev_name);
6933 prev_name = name;
6934 }
6935 else
6936 xfree (name);
6937 }
6938 if (prev_name)
6939 xfree (prev_name);
6940 if (font_ids)
6941 xfree (font_ids);
6942 }
6943#endif
6944
6633 /* Create a dummy instance iterator here to avoid creating and 6945 /* Create a dummy instance iterator here to avoid creating and
6634 destroying it in the loop. */ 6946 destroying it in the loop. */
6635 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr) 6947 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
@@ -6642,8 +6954,6 @@ init_font_name_table ()
6642 return; 6954 return;
6643 } 6955 }
6644 6956
6645 text_encoding_info_alist = create_text_encoding_info_alist ();
6646
6647 GCPRO1 (text_encoding_info_alist); 6957 GCPRO1 (text_encoding_info_alist);
6648 6958
6649 while (FMGetNextFontFamily (&ffi, &ff) == noErr) 6959 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
@@ -7140,6 +7450,9 @@ XLoadQueryFont (Display *dpy, char *fontname)
7140 Str255 mfontname, mfontname_decoded; 7450 Str255 mfontname, mfontname_decoded;
7141 Str31 charset; 7451 Str31 charset;
7142 SInt16 fontnum; 7452 SInt16 fontnum;
7453#if USE_ATSUI
7454 ATSUStyle mac_style = NULL;
7455#endif
7143 Style fontface; 7456 Style fontface;
7144#if TARGET_API_MAC_CARBON 7457#if TARGET_API_MAC_CARBON
7145 TextEncoding encoding; 7458 TextEncoding encoding;
@@ -7191,6 +7504,48 @@ XLoadQueryFont (Display *dpy, char *fontname)
7191 7504
7192 x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded, 7505 x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded,
7193 &fontface, charset); 7506 &fontface, charset);
7507#if USE_ATSUI
7508 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7509 {
7510 OSErr err;
7511 ATSUAttributeTag tags[] = {kATSUFontTag, kATSUSizeTag,
7512 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7513 ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
7514 sizeof (Boolean), sizeof (Boolean)};
7515 static ATSUFontID font_id;
7516 static Fixed size_fixed;
7517 static Boolean bold_p, italic_p;
7518 ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
7519 &bold_p, &italic_p};
7520 ATSUFontFeatureType types[] = {kAllTypographicFeaturesType};
7521 ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector};
7522 Lisp_Object font_id_cons;
7523
7524 font_id_cons = Fgethash (Fdowncase
7525 (make_unibyte_string (mfontname,
7526 strlen (mfontname))),
7527 atsu_font_id_hash, Qnil);
7528 if (NILP (font_id_cons))
7529 return NULL;
7530 font_id = cons_to_long (font_id_cons);
7531 size_fixed = Long2Fix (size);
7532 bold_p = (fontface & bold) != 0;
7533 italic_p = (fontface & italic) != 0;
7534 err = ATSUCreateStyle (&mac_style);
7535 if (err != noErr)
7536 return NULL;
7537 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7538 types, selectors);
7539 if (err != noErr)
7540 return NULL;
7541 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7542 tags, sizes, values);
7543 fontnum = -1;
7544 scriptcode = kTextEncodingMacUnicode;
7545 }
7546 else
7547 {
7548#endif
7194 c2pstr (mfontname); 7549 c2pstr (mfontname);
7195#if TARGET_API_MAC_CARBON 7550#if TARGET_API_MAC_CARBON
7196 fontnum = FMGetFontFamilyFromName (mfontname); 7551 fontnum = FMGetFontFamilyFromName (mfontname);
@@ -7204,6 +7559,9 @@ XLoadQueryFont (Display *dpy, char *fontname)
7204 return NULL; 7559 return NULL;
7205 scriptcode = FontToScript (fontnum); 7560 scriptcode = FontToScript (fontnum);
7206#endif 7561#endif
7562#if USE_ATSUI
7563 }
7564#endif
7207 7565
7208 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct)); 7566 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7209 7567
@@ -7211,6 +7569,9 @@ XLoadQueryFont (Display *dpy, char *fontname)
7211 font->mac_fontsize = size; 7569 font->mac_fontsize = size;
7212 font->mac_fontface = fontface; 7570 font->mac_fontface = fontface;
7213 font->mac_scriptcode = scriptcode; 7571 font->mac_scriptcode = scriptcode;
7572#if USE_ATSUI
7573 font->mac_style = mac_style;
7574#endif
7214 7575
7215 /* Apple Japanese (SJIS) font is listed as both 7576 /* Apple Japanese (SJIS) font is listed as both
7216 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0" 7577 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
@@ -7221,6 +7582,91 @@ XLoadQueryFont (Display *dpy, char *fontname)
7221 7582
7222 font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset); 7583 font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset);
7223 7584
7585#if USE_ATSUI
7586 if (font->mac_style)
7587 {
7588 OSErr err;
7589 ATSUTextLayout text_layout;
7590 UniChar c = 0x20;
7591 Rect char_bounds, min_bounds, max_bounds;
7592 int min_width, max_width;
7593 ATSTrapezoid glyph_bounds;
7594
7595 font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000);
7596 if (font->per_char == NULL)
7597 {
7598 mac_unload_font (&one_mac_display_info, font);
7599 return NULL;
7600 }
7601 bzero (font->per_char, sizeof (XCharStruct) * 0x10000);
7602
7603 err = atsu_get_text_layout_with_text_ptr (&c, 1,
7604 font->mac_style,
7605 &text_layout);
7606 if (err != noErr)
7607 {
7608 mac_unload_font (&one_mac_display_info, font);
7609 return NULL;
7610 }
7611
7612 for (c = 0x20; c <= 0x7e; c++)
7613 {
7614 err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning);
7615 if (err == noErr)
7616 err = ATSUMeasureTextImage (text_layout,
7617 kATSUFromTextBeginning, kATSUToTextEnd,
7618 0, 0, &char_bounds);
7619 if (err == noErr)
7620 err = ATSUGetGlyphBounds (text_layout, 0, 0,
7621 kATSUFromTextBeginning, kATSUToTextEnd,
7622 kATSUseFractionalOrigins, 1,
7623 &glyph_bounds, NULL);
7624 if (err == noErr)
7625 {
7626 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
7627 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
7628
7629 char_width = Fix2Long (glyph_bounds.upperRight.x
7630 - glyph_bounds.upperLeft.x);
7631 STORE_XCHARSTRUCT (font->per_char[c],
7632 char_width, char_bounds);
7633 if (c == 0x20)
7634 {
7635 min_width = max_width = char_width;
7636 min_bounds = max_bounds = char_bounds;
7637 font->ascent = -Fix2Long (glyph_bounds.upperLeft.y);
7638 font->descent = Fix2Long (glyph_bounds.lowerLeft.y);
7639 }
7640 else
7641 {
7642 if (char_width > 0)
7643 {
7644 min_width = min (min_width, char_width);
7645 max_width = max (max_width, char_width);
7646 }
7647 if (!EmptyRect (&char_bounds))
7648 {
7649 SetRect (&min_bounds,
7650 max (min_bounds.left, char_bounds.left),
7651 max (min_bounds.top, char_bounds.top),
7652 min (min_bounds.right, char_bounds.right),
7653 min (min_bounds.bottom, char_bounds.bottom));
7654 UnionRect (&max_bounds, &char_bounds, &max_bounds);
7655 }
7656 }
7657 }
7658 }
7659 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
7660 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
7661
7662 font->min_byte1 = 0;
7663 font->max_byte1 = 0xff;
7664 font->min_char_or_byte2 = 0;
7665 font->max_char_or_byte2 = 0xff;
7666 }
7667 else
7668 {
7669#endif
7224 is_two_byte_font = font->mac_scriptcode == smJapanese || 7670 is_two_byte_font = font->mac_scriptcode == smJapanese ||
7225 font->mac_scriptcode == smTradChinese || 7671 font->mac_scriptcode == smTradChinese ||
7226 font->mac_scriptcode == smSimpChinese || 7672 font->mac_scriptcode == smSimpChinese ||
@@ -7235,24 +7681,26 @@ XLoadQueryFont (Display *dpy, char *fontname)
7235 font->ascent = the_fontinfo.ascent; 7681 font->ascent = the_fontinfo.ascent;
7236 font->descent = the_fontinfo.descent; 7682 font->descent = the_fontinfo.descent;
7237 7683
7238 font->min_byte1 = 0;
7239 if (is_two_byte_font)
7240 font->max_byte1 = 1;
7241 else
7242 font->max_byte1 = 0;
7243 font->min_char_or_byte2 = 0x20;
7244 font->max_char_or_byte2 = 0xff;
7245
7246 if (is_two_byte_font) 7684 if (is_two_byte_font)
7247 { 7685 {
7686 font->min_byte1 = 0xa1;
7687 font->max_byte1 = 0xfe;
7688 font->min_char_or_byte2 = 0xa1;
7689 font->max_char_or_byte2 = 0xfe;
7690
7248 /* Use the width of an "ideographic space" of that font because 7691 /* Use the width of an "ideographic space" of that font because
7249 the_fontinfo.widMax returns the wrong width for some fonts. */ 7692 the_fontinfo.widMax returns the wrong width for some fonts. */
7250 switch (font->mac_scriptcode) 7693 switch (font->mac_scriptcode)
7251 { 7694 {
7252 case smJapanese: 7695 case smJapanese:
7696 font->min_byte1 = 0x81;
7697 font->max_byte1 = 0xfc;
7698 font->min_char_or_byte2 = 0x40;
7699 font->max_char_or_byte2 = 0xfc;
7253 char_width = StringWidth("\p\x81\x40"); 7700 char_width = StringWidth("\p\x81\x40");
7254 break; 7701 break;
7255 case smTradChinese: 7702 case smTradChinese:
7703 font->min_char_or_byte2 = 0x40;
7256 char_width = StringWidth("\p\xa1\x40"); 7704 char_width = StringWidth("\p\xa1\x40");
7257 break; 7705 break;
7258 case smSimpChinese: 7706 case smSimpChinese:
@@ -7264,9 +7712,15 @@ XLoadQueryFont (Display *dpy, char *fontname)
7264 } 7712 }
7265 } 7713 }
7266 else 7714 else
7267 /* Do this instead of use the_fontinfo.widMax, which incorrectly 7715 {
7268 returns 15 for 12-point Monaco! */ 7716 font->min_byte1 = font->max_byte1 = 0;
7269 char_width = CharWidth ('m'); 7717 font->min_char_or_byte2 = 0x20;
7718 font->max_char_or_byte2 = 0xff;
7719
7720 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7721 returns 15 for 12-point Monaco! */
7722 char_width = CharWidth ('m');
7723 }
7270 7724
7271 if (is_two_byte_font) 7725 if (is_two_byte_font)
7272 { 7726 {
@@ -7285,55 +7739,56 @@ XLoadQueryFont (Display *dpy, char *fontname)
7285 } 7739 }
7286 else 7740 else
7287 { 7741 {
7288 font->per_char = (XCharStruct *) 7742 int c, min_width, max_width;
7289 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); 7743 Rect char_bounds, min_bounds, max_bounds;
7290 { 7744 char ch;
7291 int c, min_width, max_width; 7745
7292 Rect char_bounds, min_bounds, max_bounds; 7746 font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
7293 char ch; 7747
7294 7748 min_width = max_width = char_width;
7295 min_width = max_width = char_width; 7749 SetRect (&min_bounds, -32767, -32767, 32767, 32767);
7296 SetRect (&min_bounds, -32767, -32767, 32767, 32767); 7750 SetRect (&max_bounds, 0, 0, 0, 0);
7297 SetRect (&max_bounds, 0, 0, 0, 0); 7751 for (c = 0x20; c <= 0xff; c++)
7298 for (c = 0x20; c <= 0xff; c++) 7752 {
7299 { 7753 ch = c;
7300 ch = c; 7754 char_width = CharWidth (ch);
7301 char_width = CharWidth (ch); 7755 QDTextBounds (1, &ch, &char_bounds);
7302 QDTextBounds (1, &ch, &char_bounds); 7756 STORE_XCHARSTRUCT (font->per_char[c - 0x20],
7303 STORE_XCHARSTRUCT (font->per_char[c - 0x20], 7757 char_width, char_bounds);
7304 char_width, char_bounds); 7758 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7305 /* Some Japanese fonts (in SJIS encoding) return 0 as the 7759 character width of 0x7f. */
7306 character width of 0x7f. */ 7760 if (char_width > 0)
7307 if (char_width > 0) 7761 {
7308 { 7762 min_width = min (min_width, char_width);
7309 min_width = min (min_width, char_width); 7763 max_width = max (max_width, char_width);
7310 max_width = max (max_width, char_width); 7764 }
7311 } 7765 if (!EmptyRect (&char_bounds))
7312 if (!EmptyRect (&char_bounds)) 7766 {
7313 { 7767 SetRect (&min_bounds,
7314 SetRect (&min_bounds, 7768 max (min_bounds.left, char_bounds.left),
7315 max (min_bounds.left, char_bounds.left), 7769 max (min_bounds.top, char_bounds.top),
7316 max (min_bounds.top, char_bounds.top), 7770 min (min_bounds.right, char_bounds.right),
7317 min (min_bounds.right, char_bounds.right), 7771 min (min_bounds.bottom, char_bounds.bottom));
7318 min (min_bounds.bottom, char_bounds.bottom)); 7772 UnionRect (&max_bounds, &char_bounds, &max_bounds);
7319 UnionRect (&max_bounds, &char_bounds, &max_bounds); 7773 }
7320 } 7774 }
7321 } 7775 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
7322 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); 7776 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
7323 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); 7777 if (min_width == max_width
7324 if (min_width == max_width 7778 && max_bounds.left >= 0 && max_bounds.right <= max_width)
7325 && max_bounds.left >= 0 && max_bounds.right <= max_width) 7779 {
7326 { 7780 /* Fixed width and no overhangs. */
7327 /* Fixed width and no overhangs. */ 7781 xfree (font->per_char);
7328 xfree (font->per_char); 7782 font->per_char = NULL;
7329 font->per_char = NULL; 7783 }
7330 }
7331 }
7332 } 7784 }
7333 7785
7334 TextFont (old_fontnum); /* restore previous font number, size and face */ 7786 TextFont (old_fontnum); /* restore previous font number, size and face */
7335 TextSize (old_fontsize); 7787 TextSize (old_fontsize);
7336 TextFace (old_fontface); 7788 TextFace (old_fontface);
7789#if USE_ATSUI
7790 }
7791#endif
7337 7792
7338 return font; 7793 return font;
7339} 7794}
@@ -7347,6 +7802,10 @@ mac_unload_font (dpyinfo, font)
7347 xfree (font->full_name); 7802 xfree (font->full_name);
7348 if (font->per_char) 7803 if (font->per_char)
7349 xfree (font->per_char); 7804 xfree (font->per_char);
7805#if USE_ATSUI
7806 if (font->mac_style)
7807 ATSUDisposeStyle (font->mac_style);
7808#endif
7350 xfree (font); 7809 xfree (font);
7351} 7810}
7352 7811
@@ -10189,75 +10648,6 @@ init_quit_char_handler ()
10189 10648
10190 mac_determine_quit_char_modifiers(); 10649 mac_determine_quit_char_modifiers();
10191} 10650}
10192
10193static Boolean
10194quit_char_comp (EventRef inEvent, void *inCompData)
10195{
10196 if (GetEventClass(inEvent) != kEventClassKeyboard)
10197 return false;
10198 if (GetEventKind(inEvent) != kEventRawKeyDown)
10199 return false;
10200 {
10201 UInt32 keyCode;
10202 UInt32 keyModifiers;
10203 GetEventParameter(inEvent, kEventParamKeyCode,
10204 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
10205 if (keyCode != mac_quit_char_keycode)
10206 return false;
10207 GetEventParameter(inEvent, kEventParamKeyModifiers,
10208 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
10209 if (keyModifiers != mac_quit_char_modifiers)
10210 return false;
10211 }
10212 return true;
10213}
10214
10215void
10216mac_check_for_quit_char ()
10217{
10218 EventRef event;
10219 static EMACS_TIME last_check_time = { 0, 0 };
10220 static EMACS_TIME one_second = { 1, 0 };
10221 EMACS_TIME now, t;
10222
10223 /* If windows are not initialized, return immediately (keep it bouncin'). */
10224 if (!mac_quit_char_modifiers)
10225 return;
10226
10227 /* Don't check if last check is less than a second ago. */
10228 EMACS_GET_TIME (now);
10229 EMACS_SUB_TIME (t, now, last_check_time);
10230 if (EMACS_TIME_LT (t, one_second))
10231 return;
10232 last_check_time = now;
10233
10234 /* Redetermine modifiers because they are based on lisp variables */
10235 mac_determine_quit_char_modifiers ();
10236
10237 /* Fill the queue with events */
10238 BLOCK_INPUT;
10239 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
10240 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
10241 NULL);
10242 UNBLOCK_INPUT;
10243 if (event)
10244 {
10245 struct input_event e;
10246
10247 /* Use an input_event to emulate what the interrupt handler does. */
10248 EVENT_INIT (e);
10249 e.kind = ASCII_KEYSTROKE_EVENT;
10250 e.code = quit_char;
10251 e.arg = Qnil;
10252 e.modifiers = NULL;
10253 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
10254 XSETFRAME (e.frame_or_window, mac_focus_frame (&one_mac_display_info));
10255 /* Remove event from queue to prevent looping. */
10256 RemoveEventFromQueue (GetMainEventQueue (), event);
10257 ReleaseEvent (event);
10258 kbd_buffer_store_event (&e);
10259 }
10260}
10261#endif /* MAC_OSX */ 10651#endif /* MAC_OSX */
10262 10652
10263static void 10653static void
@@ -10435,6 +10825,11 @@ syms_of_macterm ()
10435 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop"); 10825 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
10436 staticpro (&Qmac_ready_for_drag_n_drop); 10826 staticpro (&Qmac_ready_for_drag_n_drop);
10437 10827
10828#if USE_ATSUI
10829 staticpro (&atsu_font_id_hash);
10830 atsu_font_id_hash = Qnil;
10831#endif
10832
10438 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, 10833 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10439 doc: /* If not nil, Emacs uses toolkit scroll bars. */); 10834 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
10440#ifdef USE_TOOLKIT_SCROLL_BARS 10835#ifdef USE_TOOLKIT_SCROLL_BARS