diff options
| author | YAMAMOTO Mitsuharu | 2005-12-22 08:17:30 +0000 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2005-12-22 08:17:30 +0000 |
| commit | b73e4d84e08e1f7212f42fd582ab4191027ba6db (patch) | |
| tree | 6cd193d5e90b83f1aeeb24d323637bcd1b65648a | |
| parent | 06505fd8488e37789078acca9868c264f559afc6 (diff) | |
| download | emacs-b73e4d84e08e1f7212f42fd582ab4191027ba6db.tar.gz emacs-b73e4d84e08e1f7212f42fd582ab4191027ba6db.zip | |
(mac_per_char_metric): Add prototype.
(x_per_char_metric) [USE_CG_TEXT_DRAWING]: Remove prototype.
(mac_query_char_extents): New function.
(x_per_char_metric): Use it.
(XLoadQueryFont): Likewise. Consolidate min/max_bounds calculations.
[USE_CG_TEXT_DRAWING] (mac_draw_string_cg): Use
mac_per_char_metric instead of x_per_char_metric.
(mac_text_extents_16): New function.
(mac_compute_glyph_string_overhangs): Use it.
(mac_unload_font): Free member `bounds' in struct MacFontStruct.
| -rw-r--r-- | src/ChangeLog | 26 | ||||
| -rw-r--r-- | src/macterm.c | 570 |
2 files changed, 340 insertions, 256 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index e7bb3584912..8245a8b5119 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,29 @@ | |||
| 1 | 2005-12-22 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | ||
| 2 | |||
| 3 | * mac.c (Fmac_coerce_ae_data) [MAC_OSX]: Fix memory leak. | ||
| 4 | |||
| 5 | * macgui.h (XCharStruct): Remove member `valid_p'. | ||
| 6 | (STORE_XCHARSTRUCT): Don't set member `valid_p'. | ||
| 7 | (XCharStructRow): New typedef. | ||
| 8 | (XCHARSTRUCTROW_CHAR_VALID_P, XCHARSTRUCTROW_SET_CHAR_VALID): New | ||
| 9 | macros. | ||
| 10 | (struct MacFontStruct): Add member `bounds'. Remove member | ||
| 11 | `per_char'. All uses for QuichDraw Text fonts are changed to | ||
| 12 | `bounds.per_char'. ATSUI font bounds are represented as an array | ||
| 13 | `bounds.rows' of XCharStructRow's, each of which consists of a | ||
| 14 | bitmap of valid entries and an array of char bounds. | ||
| 15 | |||
| 16 | * macterm.c (mac_per_char_metric): Add prototype. | ||
| 17 | (x_per_char_metric) [USE_CG_TEXT_DRAWING]: Remove prototype. | ||
| 18 | (mac_query_char_extents): New function. | ||
| 19 | (x_per_char_metric): Use it. | ||
| 20 | (XLoadQueryFont): Likewise. Consolidate min/max_bounds calculations. | ||
| 21 | [USE_CG_TEXT_DRAWING] (mac_draw_string_cg): Use | ||
| 22 | mac_per_char_metric instead of x_per_char_metric. | ||
| 23 | (mac_text_extents_16): New function. | ||
| 24 | (mac_compute_glyph_string_overhangs): Use it. | ||
| 25 | (mac_unload_font): Free member `bounds' in struct MacFontStruct. | ||
| 26 | |||
| 1 | 2005-12-21 Stefan Monnier <monnier@iro.umontreal.ca> | 27 | 2005-12-21 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 28 | ||
| 3 | * minibuf.c (Fdisplay_completion_list): Use XCAR/XCDR. | 29 | * minibuf.c (Fdisplay_completion_list): Use XCAR/XCDR. |
diff --git a/src/macterm.c b/src/macterm.c index cec51c0227f..c8fc77b20ff 100644 --- a/src/macterm.c +++ b/src/macterm.c | |||
| @@ -259,7 +259,7 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, | |||
| 259 | unsigned long *)); | 259 | unsigned long *)); |
| 260 | 260 | ||
| 261 | static int is_emacs_window P_ ((WindowPtr)); | 261 | static int is_emacs_window P_ ((WindowPtr)); |
| 262 | 262 | static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int)); | |
| 263 | static void XSetFont P_ ((Display *, GC, XFontStruct *)); | 263 | static void XSetFont P_ ((Display *, GC, XFontStruct *)); |
| 264 | 264 | ||
| 265 | /* Defined in macmenu.h. */ | 265 | /* Defined in macmenu.h. */ |
| @@ -868,9 +868,159 @@ mac_draw_image_string_16 (f, gc, x, y, buf, nchars) | |||
| 868 | } | 868 | } |
| 869 | 869 | ||
| 870 | 870 | ||
| 871 | /* Mac replacement for XQueryTextExtents, but takes a character. If | ||
| 872 | STYLE is NULL, measurement is done by QuickDraw Text routines for | ||
| 873 | the font of the current graphics port. If CG_GLYPH is not NULL, | ||
| 874 | *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */ | ||
| 875 | |||
| 876 | static OSErr | ||
| 877 | mac_query_char_extents (style, c, | ||
| 878 | font_ascent_return, font_descent_return, | ||
| 879 | overall_return, cg_glyph) | ||
| 880 | #if USE_ATSUI | ||
| 881 | ATSUStyle style; | ||
| 882 | #else | ||
| 883 | void *style; | ||
| 884 | #endif | ||
| 885 | int c; | ||
| 886 | int *font_ascent_return, *font_descent_return; | ||
| 887 | XCharStruct *overall_return; | ||
| 871 | #if USE_CG_TEXT_DRAWING | 888 | #if USE_CG_TEXT_DRAWING |
| 872 | static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *)); | 889 | CGGlyph *cg_glyph; |
| 890 | #else | ||
| 891 | void *cg_glyph; | ||
| 892 | #endif | ||
| 893 | { | ||
| 894 | OSErr err = noErr; | ||
| 895 | int width; | ||
| 896 | Rect char_bounds; | ||
| 897 | |||
| 898 | #if USE_ATSUI | ||
| 899 | if (style) | ||
| 900 | { | ||
| 901 | ATSUTextLayout text_layout; | ||
| 902 | UniChar ch = c; | ||
| 903 | |||
| 904 | err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout); | ||
| 905 | if (err == noErr) | ||
| 906 | { | ||
| 907 | ATSTrapezoid glyph_bounds; | ||
| 908 | |||
| 909 | err = ATSUGetGlyphBounds (text_layout, 0, 0, | ||
| 910 | kATSUFromTextBeginning, kATSUToTextEnd, | ||
| 911 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 | ||
| 912 | kATSUseFractionalOrigins, | ||
| 913 | #else | ||
| 914 | kATSUseDeviceOrigins, | ||
| 915 | #endif | ||
| 916 | 1, &glyph_bounds, NULL); | ||
| 917 | if (err == noErr) | ||
| 918 | { | ||
| 919 | xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x | ||
| 920 | == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); | ||
| 921 | |||
| 922 | width = Fix2Long (glyph_bounds.upperRight.x | ||
| 923 | - glyph_bounds.upperLeft.x); | ||
| 924 | if (font_ascent_return) | ||
| 925 | *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y); | ||
| 926 | if (font_descent_return) | ||
| 927 | *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y); | ||
| 928 | } | ||
| 929 | } | ||
| 930 | if (err == noErr && overall_return) | ||
| 931 | { | ||
| 932 | err = ATSUMeasureTextImage (text_layout, | ||
| 933 | kATSUFromTextBeginning, kATSUToTextEnd, | ||
| 934 | 0, 0, &char_bounds); | ||
| 935 | if (err == noErr) | ||
| 936 | STORE_XCHARSTRUCT (*overall_return, width, char_bounds); | ||
| 937 | #if USE_CG_TEXT_DRAWING | ||
| 938 | if (err == noErr && cg_glyph) | ||
| 939 | { | ||
| 940 | OSErr err1; | ||
| 941 | ATSUGlyphInfoArray glyph_info_array; | ||
| 942 | ByteCount count = sizeof (ATSUGlyphInfoArray); | ||
| 943 | |||
| 944 | err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning, | ||
| 945 | kATSUToTextEnd, NULL, NULL, NULL); | ||
| 946 | if (err1 == noErr) | ||
| 947 | err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning, | ||
| 948 | kATSUToTextEnd, &count, | ||
| 949 | &glyph_info_array); | ||
| 950 | if (err1 == noErr) | ||
| 951 | { | ||
| 952 | xassert (glyph_info_array.glyphs[0].glyphID); | ||
| 953 | *cg_glyph = glyph_info_array.glyphs[0].glyphID; | ||
| 954 | } | ||
| 955 | else | ||
| 956 | *cg_glyph = 0; | ||
| 957 | } | ||
| 958 | #endif | ||
| 959 | } | ||
| 960 | } | ||
| 961 | else | ||
| 962 | #endif | ||
| 963 | { | ||
| 964 | if (font_ascent_return || font_descent_return) | ||
| 965 | { | ||
| 966 | FontInfo font_info; | ||
| 967 | |||
| 968 | GetFontInfo (&font_info); | ||
| 969 | if (font_ascent_return) | ||
| 970 | *font_ascent_return = font_info.ascent; | ||
| 971 | if (font_descent_return) | ||
| 972 | *font_descent_return = font_info.descent; | ||
| 973 | } | ||
| 974 | if (overall_return) | ||
| 975 | { | ||
| 976 | char ch = c; | ||
| 873 | 977 | ||
| 978 | width = CharWidth (ch); | ||
| 979 | QDTextBounds (1, &ch, &char_bounds); | ||
| 980 | STORE_XCHARSTRUCT (*overall_return, width, char_bounds); | ||
| 981 | } | ||
| 982 | } | ||
| 983 | |||
| 984 | return err; | ||
| 985 | } | ||
| 986 | |||
| 987 | |||
| 988 | /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */ | ||
| 989 | |||
| 990 | static int | ||
| 991 | mac_text_extents_16 (font_struct, string, nchars, overall_return) | ||
| 992 | XFontStruct *font_struct; | ||
| 993 | XChar2b *string; | ||
| 994 | int nchars; | ||
| 995 | XCharStruct *overall_return; | ||
| 996 | { | ||
| 997 | int i; | ||
| 998 | short width = 0, lbearing = 0, rbearing = 0; | ||
| 999 | XCharStruct *pcm; | ||
| 1000 | |||
| 1001 | for (i = 0; i < nchars; i++) | ||
| 1002 | { | ||
| 1003 | pcm = mac_per_char_metric (font_struct, string, 0); | ||
| 1004 | if (pcm == NULL) | ||
| 1005 | width += FONT_WIDTH (font_struct); | ||
| 1006 | else | ||
| 1007 | { | ||
| 1008 | lbearing = min (lbearing, width + pcm->lbearing); | ||
| 1009 | rbearing = max (rbearing, width + pcm->rbearing); | ||
| 1010 | width += pcm->width; | ||
| 1011 | } | ||
| 1012 | string++; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | overall_return->lbearing = lbearing; | ||
| 1016 | overall_return->rbearing = rbearing; | ||
| 1017 | overall_return->width = width; | ||
| 1018 | |||
| 1019 | /* What's the meaning of the return value of XTextExtents16? */ | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | |||
| 1023 | #if USE_CG_TEXT_DRAWING | ||
| 874 | static int cg_text_anti_aliasing_threshold = 8; | 1024 | static int cg_text_anti_aliasing_threshold = 8; |
| 875 | 1025 | ||
| 876 | static void | 1026 | static void |
| @@ -910,7 +1060,9 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars) | |||
| 910 | advances = xmalloc (sizeof (CGSize) * nchars); | 1060 | advances = xmalloc (sizeof (CGSize) * nchars); |
| 911 | for (i = 0; i < nchars; i++) | 1061 | for (i = 0; i < nchars; i++) |
| 912 | { | 1062 | { |
| 913 | advances[i].width = x_per_char_metric (GC_FONT (gc), buf)->width; | 1063 | XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0); |
| 1064 | |||
| 1065 | advances[i].width = pcm->width; | ||
| 914 | advances[i].height = 0; | 1066 | advances[i].height = 0; |
| 915 | glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2]; | 1067 | glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2]; |
| 916 | buf++; | 1068 | buf++; |
| @@ -1724,63 +1876,32 @@ x_per_char_metric (font, char2b) | |||
| 1724 | #if USE_ATSUI | 1876 | #if USE_ATSUI |
| 1725 | if (font->mac_style) | 1877 | if (font->mac_style) |
| 1726 | { | 1878 | { |
| 1727 | if (char2b->byte1 >= font->min_byte1 | 1879 | XCharStructRow **row = font->bounds.rows + char2b->byte1; |
| 1728 | && char2b->byte1 <= font->max_byte1 | 1880 | |
| 1729 | && char2b->byte2 >= font->min_char_or_byte2 | 1881 | if (*row == NULL) |
| 1730 | && char2b->byte2 <= font->max_char_or_byte2) | ||
| 1731 | { | 1882 | { |
| 1732 | pcm = (font->per_char | 1883 | *row = xmalloc (sizeof (XCharStructRow)); |
| 1733 | + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) | 1884 | if (*row) |
| 1734 | * (char2b->byte1 - font->min_byte1)) | 1885 | bzero (*row, sizeof (XCharStructRow)); |
| 1735 | + (char2b->byte2 - font->min_char_or_byte2)); | ||
| 1736 | } | 1886 | } |
| 1737 | 1887 | if (*row) | |
| 1738 | if (pcm && !pcm->valid_p) | ||
| 1739 | { | 1888 | { |
| 1740 | OSErr err; | 1889 | pcm = (*row)->per_char + char2b->byte2; |
| 1741 | ATSUTextLayout text_layout; | 1890 | if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2)) |
| 1742 | UniChar c; | ||
| 1743 | int char_width; | ||
| 1744 | ATSTrapezoid glyph_bounds; | ||
| 1745 | Rect char_bounds; | ||
| 1746 | |||
| 1747 | c = (char2b->byte1 << 8) + char2b->byte2; | ||
| 1748 | BLOCK_INPUT; | ||
| 1749 | err = atsu_get_text_layout_with_text_ptr (&c, 1, | ||
| 1750 | font->mac_style, | ||
| 1751 | &text_layout); | ||
| 1752 | if (err == noErr) | ||
| 1753 | err = ATSUMeasureTextImage (text_layout, | ||
| 1754 | kATSUFromTextBeginning, kATSUToTextEnd, | ||
| 1755 | 0, 0, &char_bounds); | ||
| 1756 | |||
| 1757 | if (err == noErr) | ||
| 1758 | err = ATSUGetGlyphBounds (text_layout, 0, 0, | ||
| 1759 | kATSUFromTextBeginning, kATSUToTextEnd, | ||
| 1760 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 | ||
| 1761 | kATSUseFractionalOrigins, | ||
| 1762 | #else | ||
| 1763 | kATSUseDeviceOrigins, | ||
| 1764 | #endif | ||
| 1765 | 1, &glyph_bounds, NULL); | ||
| 1766 | UNBLOCK_INPUT; | ||
| 1767 | if (err != noErr) | ||
| 1768 | pcm = NULL; | ||
| 1769 | else | ||
| 1770 | { | 1891 | { |
| 1771 | xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x | 1892 | BLOCK_INPUT; |
| 1772 | == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); | 1893 | mac_query_char_extents (font->mac_style, |
| 1773 | 1894 | (char2b->byte1 << 8) + char2b->byte2, | |
| 1774 | char_width = Fix2Long (glyph_bounds.upperRight.x | 1895 | NULL, NULL, pcm, NULL); |
| 1775 | - glyph_bounds.upperLeft.x); | 1896 | UNBLOCK_INPUT; |
| 1776 | STORE_XCHARSTRUCT (*pcm, char_width, char_bounds); | 1897 | XCHARSTRUCTROW_SET_CHAR_VALID (*row, char2b->byte2); |
| 1777 | } | 1898 | } |
| 1778 | } | 1899 | } |
| 1779 | } | 1900 | } |
| 1780 | else | 1901 | else |
| 1781 | { | 1902 | { |
| 1782 | #endif | 1903 | #endif |
| 1783 | if (font->per_char != NULL) | 1904 | if (font->bounds.per_char != NULL) |
| 1784 | { | 1905 | { |
| 1785 | if (font->min_byte1 == 0 && font->max_byte1 == 0) | 1906 | if (font->min_byte1 == 0 && font->max_byte1 == 0) |
| 1786 | { | 1907 | { |
| @@ -1793,7 +1914,8 @@ x_per_char_metric (font, char2b) | |||
| 1793 | if (char2b->byte1 == 0 | 1914 | if (char2b->byte1 == 0 |
| 1794 | && char2b->byte2 >= font->min_char_or_byte2 | 1915 | && char2b->byte2 >= font->min_char_or_byte2 |
| 1795 | && char2b->byte2 <= font->max_char_or_byte2) | 1916 | && char2b->byte2 <= font->max_char_or_byte2) |
| 1796 | pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2; | 1917 | pcm = font->bounds.per_char |
| 1918 | + (char2b->byte2 - font->min_char_or_byte2); | ||
| 1797 | } | 1919 | } |
| 1798 | else | 1920 | else |
| 1799 | { | 1921 | { |
| @@ -1815,7 +1937,7 @@ x_per_char_metric (font, char2b) | |||
| 1815 | && char2b->byte2 >= font->min_char_or_byte2 | 1937 | && char2b->byte2 >= font->min_char_or_byte2 |
| 1816 | && char2b->byte2 <= font->max_char_or_byte2) | 1938 | && char2b->byte2 <= font->max_char_or_byte2) |
| 1817 | { | 1939 | { |
| 1818 | pcm = (font->per_char | 1940 | pcm = (font->bounds.per_char |
| 1819 | + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) | 1941 | + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) |
| 1820 | * (char2b->byte1 - font->min_byte1)) | 1942 | * (char2b->byte1 - font->min_byte1)) |
| 1821 | + (char2b->byte2 - font->min_char_or_byte2)); | 1943 | + (char2b->byte2 - font->min_char_or_byte2)); |
| @@ -2157,67 +2279,32 @@ mac_compute_glyph_string_overhangs (s) | |||
| 2157 | { | 2279 | { |
| 2158 | if (s->cmp == NULL | 2280 | if (s->cmp == NULL |
| 2159 | && s->first_glyph->type == CHAR_GLYPH) | 2281 | && s->first_glyph->type == CHAR_GLYPH) |
| 2160 | { | 2282 | if (!s->two_byte_p |
| 2161 | Rect r; | ||
| 2162 | MacFontStruct *font = s->font; | ||
| 2163 | |||
| 2164 | #if USE_ATSUI | 2283 | #if USE_ATSUI |
| 2165 | if (font->mac_style) | 2284 | || s->font->mac_style |
| 2166 | { | 2285 | #endif |
| 2167 | OSErr err; | 2286 | ) |
| 2168 | ATSUTextLayout text_layout; | 2287 | { |
| 2169 | UniChar *buf; | 2288 | XCharStruct cs; |
| 2170 | int i; | ||
| 2171 | 2289 | ||
| 2172 | SetRect (&r, 0, 0, 0, 0); | 2290 | mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs); |
| 2173 | buf = xmalloc (sizeof (UniChar) * s->nchars); | 2291 | s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; |
| 2174 | if (buf) | 2292 | s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; |
| 2175 | { | 2293 | } |
| 2176 | for (i = 0; i < s->nchars; i++) | 2294 | else |
| 2177 | buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2; | 2295 | { |
| 2296 | Rect r; | ||
| 2297 | MacFontStruct *font = s->font; | ||
| 2178 | 2298 | ||
| 2179 | err = atsu_get_text_layout_with_text_ptr (buf, s->nchars, | 2299 | TextFont (font->mac_fontnum); |
| 2180 | font->mac_style, | 2300 | TextSize (font->mac_fontsize); |
| 2181 | &text_layout); | 2301 | TextFace (font->mac_fontface); |
| 2182 | if (err == noErr) | ||
| 2183 | err = ATSUMeasureTextImage (text_layout, | ||
| 2184 | kATSUFromTextBeginning, | ||
| 2185 | kATSUToTextEnd, | ||
| 2186 | 0, 0, &r); | ||
| 2187 | xfree (buf); | ||
| 2188 | } | ||
| 2189 | } | ||
| 2190 | else | ||
| 2191 | { | ||
| 2192 | #endif | ||
| 2193 | TextFont (font->mac_fontnum); | ||
| 2194 | TextSize (font->mac_fontsize); | ||
| 2195 | TextFace (font->mac_fontface); | ||
| 2196 | 2302 | ||
| 2197 | if (s->two_byte_p) | ||
| 2198 | QDTextBounds (s->nchars * 2, (char *)s->char2b, &r); | 2303 | QDTextBounds (s->nchars * 2, (char *)s->char2b, &r); |
| 2199 | else | ||
| 2200 | { | ||
| 2201 | int i; | ||
| 2202 | char *buf = xmalloc (s->nchars); | ||
| 2203 | |||
| 2204 | if (buf == NULL) | ||
| 2205 | SetRect (&r, 0, 0, 0, 0); | ||
| 2206 | else | ||
| 2207 | { | ||
| 2208 | for (i = 0; i < s->nchars; ++i) | ||
| 2209 | buf[i] = s->char2b[i].byte2; | ||
| 2210 | QDTextBounds (s->nchars, buf, &r); | ||
| 2211 | xfree (buf); | ||
| 2212 | } | ||
| 2213 | } | ||
| 2214 | #if USE_ATSUI | ||
| 2215 | } | ||
| 2216 | #endif | ||
| 2217 | 2304 | ||
| 2218 | s->right_overhang = r.right > s->width ? r.right - s->width : 0; | 2305 | s->right_overhang = r.right > s->width ? r.right - s->width : 0; |
| 2219 | s->left_overhang = r.left < 0 ? -r.left : 0; | 2306 | s->left_overhang = r.left < 0 ? -r.left : 0; |
| 2220 | } | 2307 | } |
| 2221 | } | 2308 | } |
| 2222 | 2309 | ||
| 2223 | 2310 | ||
| @@ -7375,7 +7462,7 @@ is_fully_specified_xlfd (char *p) | |||
| 7375 | static MacFontStruct * | 7462 | static MacFontStruct * |
| 7376 | XLoadQueryFont (Display *dpy, char *fontname) | 7463 | XLoadQueryFont (Display *dpy, char *fontname) |
| 7377 | { | 7464 | { |
| 7378 | int i, size, char_width; | 7465 | int size; |
| 7379 | char *name; | 7466 | char *name; |
| 7380 | Str255 family; | 7467 | Str255 family; |
| 7381 | Str31 charset; | 7468 | Str31 charset; |
| @@ -7392,6 +7479,7 @@ XLoadQueryFont (Display *dpy, char *fontname) | |||
| 7392 | short scriptcode; | 7479 | short scriptcode; |
| 7393 | #endif | 7480 | #endif |
| 7394 | MacFontStruct *font; | 7481 | MacFontStruct *font; |
| 7482 | XCharStruct *space_bounds = NULL, *pcm; | ||
| 7395 | 7483 | ||
| 7396 | if (is_fully_specified_xlfd (fontname)) | 7484 | if (is_fully_specified_xlfd (fontname)) |
| 7397 | name = fontname; | 7485 | name = fontname; |
| @@ -7488,19 +7576,27 @@ XLoadQueryFont (Display *dpy, char *fontname) | |||
| 7488 | if (font->mac_style) | 7576 | if (font->mac_style) |
| 7489 | { | 7577 | { |
| 7490 | OSErr err; | 7578 | OSErr err; |
| 7491 | ATSUTextLayout text_layout; | 7579 | UniChar c; |
| 7492 | UniChar c = 0x20; | ||
| 7493 | Rect char_bounds, min_bounds, max_bounds; | ||
| 7494 | int min_width, max_width; | ||
| 7495 | ATSTrapezoid glyph_bounds; | ||
| 7496 | 7580 | ||
| 7497 | font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000); | 7581 | font->min_byte1 = 0; |
| 7498 | if (font->per_char == NULL) | 7582 | font->max_byte1 = 0xff; |
| 7583 | font->min_char_or_byte2 = 0; | ||
| 7584 | font->max_char_or_byte2 = 0xff; | ||
| 7585 | |||
| 7586 | font->bounds.rows = xmalloc (sizeof (XCharStructRow *) * 0x100); | ||
| 7587 | if (font->bounds.rows == NULL) | ||
| 7499 | { | 7588 | { |
| 7500 | mac_unload_font (&one_mac_display_info, font); | 7589 | mac_unload_font (&one_mac_display_info, font); |
| 7501 | return NULL; | 7590 | return NULL; |
| 7502 | } | 7591 | } |
| 7503 | bzero (font->per_char, sizeof (XCharStruct) * 0x10000); | 7592 | bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100); |
| 7593 | font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow)); | ||
| 7594 | if (font->bounds.rows[0] == NULL) | ||
| 7595 | { | ||
| 7596 | mac_unload_font (&one_mac_display_info, font); | ||
| 7597 | return NULL; | ||
| 7598 | } | ||
| 7599 | bzero (font->bounds.rows[0], sizeof (XCharStructRow)); | ||
| 7504 | 7600 | ||
| 7505 | #if USE_CG_TEXT_DRAWING | 7601 | #if USE_CG_TEXT_DRAWING |
| 7506 | { | 7602 | { |
| @@ -7525,108 +7621,58 @@ XLoadQueryFont (Display *dpy, char *fontname) | |||
| 7525 | if (font->cg_glyphs) | 7621 | if (font->cg_glyphs) |
| 7526 | bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100); | 7622 | bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100); |
| 7527 | #endif | 7623 | #endif |
| 7528 | 7624 | space_bounds = font->bounds.rows[0]->per_char + 0x20; | |
| 7529 | err = atsu_get_text_layout_with_text_ptr (&c, 1, | 7625 | err = mac_query_char_extents (font->mac_style, 0x20, |
| 7530 | font->mac_style, | 7626 | &font->ascent, &font->descent, |
| 7531 | &text_layout); | 7627 | space_bounds, |
| 7628 | #if USE_CG_TEXT_DRAWING | ||
| 7629 | (font->cg_glyphs ? font->cg_glyphs + 0x20 | ||
| 7630 | : NULL) | ||
| 7631 | #else | ||
| 7632 | NULL | ||
| 7633 | #endif | ||
| 7634 | ); | ||
| 7532 | if (err != noErr) | 7635 | if (err != noErr) |
| 7533 | { | 7636 | { |
| 7534 | mac_unload_font (&one_mac_display_info, font); | 7637 | mac_unload_font (&one_mac_display_info, font); |
| 7535 | return NULL; | 7638 | return NULL; |
| 7536 | } | 7639 | } |
| 7640 | XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20); | ||
| 7537 | 7641 | ||
| 7538 | for (c = 0x20; c <= 0xff; c++) | 7642 | pcm = font->bounds.rows[0]->per_char; |
| 7643 | for (c = 0x21; c <= 0xff; c++) | ||
| 7539 | { | 7644 | { |
| 7540 | if (c == 0xad) | 7645 | if (c == 0xad) |
| 7541 | /* Soft hyphen is not supported in ATSUI. */ | 7646 | /* Soft hyphen is not supported in ATSUI. */ |
| 7542 | continue; | 7647 | continue; |
| 7543 | else if (c == 0x7f) | 7648 | else if (c == 0x7f) |
| 7544 | { | 7649 | { |
| 7545 | STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); | ||
| 7546 | STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); | ||
| 7547 | c = 0x9f; | 7650 | c = 0x9f; |
| 7548 | continue; | 7651 | continue; |
| 7549 | } | 7652 | } |
| 7550 | 7653 | ||
| 7551 | err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning); | 7654 | mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c, |
| 7552 | if (err == noErr) | 7655 | #if USE_CG_TEXT_DRAWING |
| 7553 | err = ATSUMeasureTextImage (text_layout, | 7656 | (font->cg_glyphs ? font->cg_glyphs + c |
| 7554 | kATSUFromTextBeginning, kATSUToTextEnd, | 7657 | : NULL) |
| 7555 | 0, 0, &char_bounds); | ||
| 7556 | if (err == noErr) | ||
| 7557 | err = ATSUGetGlyphBounds (text_layout, 0, 0, | ||
| 7558 | kATSUFromTextBeginning, kATSUToTextEnd, | ||
| 7559 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 | ||
| 7560 | kATSUseFractionalOrigins, | ||
| 7561 | #else | 7658 | #else |
| 7562 | kATSUseDeviceOrigins, | 7659 | NULL |
| 7563 | #endif | 7660 | #endif |
| 7564 | 1, &glyph_bounds, NULL); | 7661 | ); |
| 7565 | if (err == noErr) | 7662 | XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c); |
| 7566 | { | ||
| 7567 | xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x | ||
| 7568 | == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); | ||
| 7569 | 7663 | ||
| 7570 | char_width = Fix2Long (glyph_bounds.upperRight.x | ||
| 7571 | - glyph_bounds.upperLeft.x); | ||
| 7572 | STORE_XCHARSTRUCT (font->per_char[c], | ||
| 7573 | char_width, char_bounds); | ||
| 7574 | if (c == 0x20) | ||
| 7575 | { | ||
| 7576 | min_width = max_width = char_width; | ||
| 7577 | min_bounds = max_bounds = char_bounds; | ||
| 7578 | font->ascent = -Fix2Long (glyph_bounds.upperLeft.y); | ||
| 7579 | font->descent = Fix2Long (glyph_bounds.lowerLeft.y); | ||
| 7580 | } | ||
| 7581 | else | ||
| 7582 | { | ||
| 7583 | if (char_width > 0) | ||
| 7584 | { | ||
| 7585 | min_width = min (min_width, char_width); | ||
| 7586 | max_width = max (max_width, char_width); | ||
| 7587 | } | ||
| 7588 | if (!EmptyRect (&char_bounds)) | ||
| 7589 | { | ||
| 7590 | SetRect (&min_bounds, | ||
| 7591 | max (min_bounds.left, char_bounds.left), | ||
| 7592 | max (min_bounds.top, char_bounds.top), | ||
| 7593 | min (min_bounds.right, char_bounds.right), | ||
| 7594 | min (min_bounds.bottom, char_bounds.bottom)); | ||
| 7595 | UnionRect (&max_bounds, &char_bounds, &max_bounds); | ||
| 7596 | } | ||
| 7597 | } | ||
| 7598 | } | ||
| 7599 | #if USE_CG_TEXT_DRAWING | 7664 | #if USE_CG_TEXT_DRAWING |
| 7600 | if (err == noErr && char_width > 0 && font->cg_font) | 7665 | if (font->cg_glyphs && font->cg_glyphs[c] == 0) |
| 7601 | { | 7666 | { |
| 7602 | ATSUGlyphInfoArray glyph_info_array; | 7667 | /* Don't use CG text drawing if font substitution occurs in |
| 7603 | ByteCount count = sizeof (ATSUGlyphInfoArray); | 7668 | ASCII or Latin-1 characters. */ |
| 7604 | 7669 | CGFontRelease (font->cg_font); | |
| 7605 | err = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning, | 7670 | font->cg_font = NULL; |
| 7606 | kATSUToTextEnd, NULL, NULL, NULL); | 7671 | xfree (font->cg_glyphs); |
| 7607 | if (err == noErr) | 7672 | font->cg_glyphs = NULL; |
| 7608 | err = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning, | ||
| 7609 | kATSUToTextEnd, &count, | ||
| 7610 | &glyph_info_array); | ||
| 7611 | if (err == noErr) | ||
| 7612 | font->cg_glyphs[c] = glyph_info_array.glyphs[0].glyphID; | ||
| 7613 | else | ||
| 7614 | { | ||
| 7615 | /* Don't use CG text drawing if font substitution | ||
| 7616 | occurs in ASCII or Latin-1 characters. */ | ||
| 7617 | CGFontRelease (font->cg_font); | ||
| 7618 | font->cg_font = NULL; | ||
| 7619 | xfree (font->cg_glyphs); | ||
| 7620 | font->cg_glyphs = NULL; | ||
| 7621 | } | ||
| 7622 | } | 7673 | } |
| 7623 | #endif | 7674 | #endif |
| 7624 | } | 7675 | } |
| 7625 | |||
| 7626 | font->min_byte1 = 0; | ||
| 7627 | font->max_byte1 = 0xff; | ||
| 7628 | font->min_char_or_byte2 = 0; | ||
| 7629 | font->max_char_or_byte2 = 0xff; | ||
| 7630 | } | 7676 | } |
| 7631 | else | 7677 | else |
| 7632 | #endif | 7678 | #endif |
| @@ -7665,6 +7711,8 @@ XLoadQueryFont (Display *dpy, char *fontname) | |||
| 7665 | 7711 | ||
| 7666 | if (is_two_byte_font) | 7712 | if (is_two_byte_font) |
| 7667 | { | 7713 | { |
| 7714 | int char_width; | ||
| 7715 | |||
| 7668 | font->min_byte1 = 0xa1; | 7716 | font->min_byte1 = 0xa1; |
| 7669 | font->max_byte1 = 0xfe; | 7717 | font->max_byte1 = 0xfe; |
| 7670 | font->min_char_or_byte2 = 0xa1; | 7718 | font->min_char_or_byte2 = 0xa1; |
| @@ -7693,21 +7741,8 @@ XLoadQueryFont (Display *dpy, char *fontname) | |||
| 7693 | char_width = StringWidth("\p\xa1\xa1"); | 7741 | char_width = StringWidth("\p\xa1\xa1"); |
| 7694 | break; | 7742 | break; |
| 7695 | } | 7743 | } |
| 7696 | } | ||
| 7697 | else | ||
| 7698 | { | ||
| 7699 | font->min_byte1 = font->max_byte1 = 0; | ||
| 7700 | font->min_char_or_byte2 = 0x20; | ||
| 7701 | font->max_char_or_byte2 = 0xff; | ||
| 7702 | |||
| 7703 | /* Do this instead of use the_fontinfo.widMax, which | ||
| 7704 | incorrectly returns 15 for 12-point Monaco! */ | ||
| 7705 | char_width = CharWidth ('m'); | ||
| 7706 | } | ||
| 7707 | 7744 | ||
| 7708 | if (is_two_byte_font) | 7745 | font->bounds.per_char = NULL; |
| 7709 | { | ||
| 7710 | font->per_char = NULL; | ||
| 7711 | 7746 | ||
| 7712 | if (fontface & italic) | 7747 | if (fontface & italic) |
| 7713 | font->max_bounds.rbearing = char_width + 1; | 7748 | font->max_bounds.rbearing = char_width + 1; |
| @@ -7722,54 +7757,28 @@ XLoadQueryFont (Display *dpy, char *fontname) | |||
| 7722 | } | 7757 | } |
| 7723 | else | 7758 | else |
| 7724 | { | 7759 | { |
| 7725 | int c, min_width, max_width; | 7760 | int c; |
| 7726 | Rect char_bounds, min_bounds, max_bounds; | ||
| 7727 | char ch; | ||
| 7728 | |||
| 7729 | font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); | ||
| 7730 | bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1)); | ||
| 7731 | 7761 | ||
| 7732 | min_width = max_width = char_width; | 7762 | font->min_byte1 = font->max_byte1 = 0; |
| 7733 | SetRect (&min_bounds, -32767, -32767, 32767, 32767); | 7763 | font->min_char_or_byte2 = 0x20; |
| 7734 | SetRect (&max_bounds, 0, 0, 0, 0); | 7764 | font->max_char_or_byte2 = 0xff; |
| 7735 | for (c = 0x20; c <= 0xff; c++) | ||
| 7736 | { | ||
| 7737 | if (c == 0x7f) | ||
| 7738 | { | ||
| 7739 | STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); | ||
| 7740 | STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); | ||
| 7741 | continue; | ||
| 7742 | } | ||
| 7743 | 7765 | ||
| 7744 | ch = c; | 7766 | font->bounds.per_char = |
| 7745 | char_width = CharWidth (ch); | 7767 | xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); |
| 7746 | QDTextBounds (1, &ch, &char_bounds); | 7768 | if (font->bounds.per_char == NULL) |
| 7747 | STORE_XCHARSTRUCT (font->per_char[c - 0x20], | ||
| 7748 | char_width, char_bounds); | ||
| 7749 | /* Some Japanese fonts (in SJIS encoding) return 0 as | ||
| 7750 | the character width of 0x7f. */ | ||
| 7751 | if (char_width > 0) | ||
| 7752 | { | ||
| 7753 | min_width = min (min_width, char_width); | ||
| 7754 | max_width = max (max_width, char_width); | ||
| 7755 | } | ||
| 7756 | if (!EmptyRect (&char_bounds)) | ||
| 7757 | { | ||
| 7758 | SetRect (&min_bounds, | ||
| 7759 | max (min_bounds.left, char_bounds.left), | ||
| 7760 | max (min_bounds.top, char_bounds.top), | ||
| 7761 | min (min_bounds.right, char_bounds.right), | ||
| 7762 | min (min_bounds.bottom, char_bounds.bottom)); | ||
| 7763 | UnionRect (&max_bounds, &char_bounds, &max_bounds); | ||
| 7764 | } | ||
| 7765 | } | ||
| 7766 | if (min_width == max_width | ||
| 7767 | && max_bounds.left >= 0 && max_bounds.right <= max_width) | ||
| 7768 | { | 7769 | { |
| 7769 | /* Fixed width and no overhangs. */ | 7770 | mac_unload_font (&one_mac_display_info, font); |
| 7770 | xfree (font->per_char); | 7771 | return NULL; |
| 7771 | font->per_char = NULL; | ||
| 7772 | } | 7772 | } |
| 7773 | bzero (font->bounds.per_char, | ||
| 7774 | sizeof (XCharStruct) * (0xff - 0x20 + 1)); | ||
| 7775 | |||
| 7776 | space_bounds = font->bounds.per_char; | ||
| 7777 | mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent, | ||
| 7778 | space_bounds, NULL); | ||
| 7779 | |||
| 7780 | for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++) | ||
| 7781 | mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL); | ||
| 7773 | } | 7782 | } |
| 7774 | 7783 | ||
| 7775 | /* Restore previous font number, size and face. */ | 7784 | /* Restore previous font number, size and face. */ |
| @@ -7778,6 +7787,46 @@ XLoadQueryFont (Display *dpy, char *fontname) | |||
| 7778 | TextFace (old_fontface); | 7787 | TextFace (old_fontface); |
| 7779 | } | 7788 | } |
| 7780 | 7789 | ||
| 7790 | if (space_bounds) | ||
| 7791 | { | ||
| 7792 | int c; | ||
| 7793 | |||
| 7794 | font->min_bounds = font->max_bounds = *space_bounds; | ||
| 7795 | for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++) | ||
| 7796 | if (pcm->width > 0) | ||
| 7797 | { | ||
| 7798 | font->min_bounds.lbearing = min (font->min_bounds.lbearing, | ||
| 7799 | pcm->lbearing); | ||
| 7800 | font->min_bounds.rbearing = min (font->min_bounds.rbearing, | ||
| 7801 | pcm->rbearing); | ||
| 7802 | font->min_bounds.width = min (font->min_bounds.width, | ||
| 7803 | pcm->width); | ||
| 7804 | font->min_bounds.ascent = min (font->min_bounds.ascent, | ||
| 7805 | pcm->ascent); | ||
| 7806 | |||
| 7807 | font->max_bounds.lbearing = max (font->max_bounds.lbearing, | ||
| 7808 | pcm->lbearing); | ||
| 7809 | font->max_bounds.rbearing = max (font->max_bounds.rbearing, | ||
| 7810 | pcm->rbearing); | ||
| 7811 | font->max_bounds.width = max (font->max_bounds.width, | ||
| 7812 | pcm->width); | ||
| 7813 | font->max_bounds.ascent = max (font->max_bounds.ascent, | ||
| 7814 | pcm->ascent); | ||
| 7815 | } | ||
| 7816 | if ( | ||
| 7817 | #if USE_ATSUI | ||
| 7818 | font->mac_style == NULL && | ||
| 7819 | #endif | ||
| 7820 | font->max_bounds.width == font->min_bounds.width | ||
| 7821 | && font->min_bounds.lbearing >= 0 | ||
| 7822 | && font->max_bounds.rbearing <= font->max_bounds.width) | ||
| 7823 | { | ||
| 7824 | /* Fixed width and no overhangs. */ | ||
| 7825 | xfree (font->bounds.per_char); | ||
| 7826 | font->bounds.per_char = NULL; | ||
| 7827 | } | ||
| 7828 | } | ||
| 7829 | |||
| 7781 | #if !defined (MAC_OS8) || USE_ATSUI | 7830 | #if !defined (MAC_OS8) || USE_ATSUI |
| 7782 | /* AppKit and WebKit do some adjustment to the heights of Courier, | 7831 | /* AppKit and WebKit do some adjustment to the heights of Courier, |
| 7783 | Helvetica, and Times. This only works on the environments where | 7832 | Helvetica, and Times. This only works on the environments where |
| @@ -7797,18 +7846,27 @@ mac_unload_font (dpyinfo, font) | |||
| 7797 | XFontStruct *font; | 7846 | XFontStruct *font; |
| 7798 | { | 7847 | { |
| 7799 | xfree (font->full_name); | 7848 | xfree (font->full_name); |
| 7800 | if (font->per_char) | ||
| 7801 | xfree (font->per_char); | ||
| 7802 | #if USE_ATSUI | 7849 | #if USE_ATSUI |
| 7803 | if (font->mac_style) | 7850 | if (font->mac_style) |
| 7804 | ATSUDisposeStyle (font->mac_style); | 7851 | { |
| 7852 | int i; | ||
| 7853 | |||
| 7854 | for (i = font->min_byte1; i <= font->max_byte1; i++) | ||
| 7855 | if (font->bounds.rows[i]) | ||
| 7856 | xfree (font->bounds.rows[i]); | ||
| 7857 | xfree (font->bounds.rows); | ||
| 7858 | ATSUDisposeStyle (font->mac_style); | ||
| 7859 | } | ||
| 7860 | else | ||
| 7861 | #endif | ||
| 7862 | if (font->bounds.per_char) | ||
| 7863 | xfree (font->bounds.per_char); | ||
| 7805 | #if USE_CG_TEXT_DRAWING | 7864 | #if USE_CG_TEXT_DRAWING |
| 7806 | if (font->cg_font) | 7865 | if (font->cg_font) |
| 7807 | CGFontRelease (font->cg_font); | 7866 | CGFontRelease (font->cg_font); |
| 7808 | if (font->cg_glyphs) | 7867 | if (font->cg_glyphs) |
| 7809 | xfree (font->cg_glyphs); | 7868 | xfree (font->cg_glyphs); |
| 7810 | #endif | 7869 | #endif |
| 7811 | #endif | ||
| 7812 | xfree (font); | 7870 | xfree (font); |
| 7813 | } | 7871 | } |
| 7814 | 7872 | ||