Mercurial > emacs
comparison src/macterm.c @ 67733:330ac31a0c82
(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.
author | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> |
---|---|
date | Thu, 22 Dec 2005 08:17:10 +0000 |
parents | ea51bc4acb2e |
children | 114d965dfb60 |
comparison
equal
deleted
inserted
replaced
67732:caacdc1a999e | 67733:330ac31a0c82 |
---|---|
257 enum scroll_bar_part *, | 257 enum scroll_bar_part *, |
258 Lisp_Object *, Lisp_Object *, | 258 Lisp_Object *, 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. */ |
266 extern void menubar_selection_callback (FRAME_PTR, int); | 266 extern void menubar_selection_callback (FRAME_PTR, int); |
267 | 267 |
866 { | 866 { |
867 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcCopy, 2); | 867 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcCopy, 2); |
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; |
873 | 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; | |
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 |
877 init_cg_text_anti_aliasing_threshold () | 1027 init_cg_text_anti_aliasing_threshold () |
878 { | 1028 { |
908 gy = port_height - y; | 1058 gy = port_height - y; |
909 glyphs = (CGGlyph *)buf; | 1059 glyphs = (CGGlyph *)buf; |
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++; |
917 } | 1069 } |
918 | 1070 |
1722 xassert (font && char2b); | 1874 xassert (font && char2b); |
1723 | 1875 |
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 { |
1787 /* min_char_or_byte2 specifies the linear character index | 1908 /* min_char_or_byte2 specifies the linear character index |
1788 corresponding to the first element of the per_char array, | 1909 corresponding to the first element of the per_char array, |
1791 A character with byte2 less than min_char_or_byte2 or | 1912 A character with byte2 less than min_char_or_byte2 or |
1792 greater max_char_or_byte2 is not in the font. */ | 1913 greater max_char_or_byte2 is not in the font. */ |
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 { |
1800 /* If either min_byte1 or max_byte1 are nonzero, both | 1922 /* If either min_byte1 or max_byte1 are nonzero, both |
1801 min_char_or_byte2 and max_char_or_byte2 are less than | 1923 min_char_or_byte2 and max_char_or_byte2 are less than |
1813 if (char2b->byte1 >= font->min_byte1 | 1935 if (char2b->byte1 >= font->min_byte1 |
1814 && char2b->byte1 <= font->max_byte1 | 1936 && char2b->byte1 <= font->max_byte1 |
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)); |
1822 } | 1944 } |
1823 } | 1945 } |
2155 mac_compute_glyph_string_overhangs (s) | 2277 mac_compute_glyph_string_overhangs (s) |
2156 struct glyph_string *s; | 2278 struct glyph_string *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; | 2289 |
2171 | 2290 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs); |
2172 SetRect (&r, 0, 0, 0, 0); | 2291 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; |
2173 buf = xmalloc (sizeof (UniChar) * s->nchars); | 2292 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; |
2174 if (buf) | 2293 } |
2175 { | 2294 else |
2176 for (i = 0; i < s->nchars; i++) | 2295 { |
2177 buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2; | 2296 Rect r; |
2178 | 2297 MacFontStruct *font = s->font; |
2179 err = atsu_get_text_layout_with_text_ptr (buf, s->nchars, | 2298 |
2180 font->mac_style, | 2299 TextFont (font->mac_fontnum); |
2181 &text_layout); | 2300 TextSize (font->mac_fontsize); |
2182 if (err == noErr) | 2301 TextFace (font->mac_fontface); |
2183 err = ATSUMeasureTextImage (text_layout, | 2302 |
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 | |
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 | 2304 |
2200 { | 2305 s->right_overhang = r.right > s->width ? r.right - s->width : 0; |
2201 int i; | 2306 s->left_overhang = r.left < 0 ? -r.left : 0; |
2202 char *buf = xmalloc (s->nchars); | 2307 } |
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 | |
2218 s->right_overhang = r.right > s->width ? r.right - s->width : 0; | |
2219 s->left_overhang = r.left < 0 ? -r.left : 0; | |
2220 } | |
2221 } | 2308 } |
2222 | 2309 |
2223 | 2310 |
2224 /* Fill rectangle X, Y, W, H with background color of glyph string S. */ | 2311 /* Fill rectangle X, Y, W, H with background color of glyph string S. */ |
2225 | 2312 |
7373 and store them in the returned MacFontStruct. */ | 7460 and store them in the returned MacFontStruct. */ |
7374 | 7461 |
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; |
7382 SInt16 fontnum; | 7469 SInt16 fontnum; |
7383 #if USE_ATSUI | 7470 #if USE_ATSUI |
7390 int scriptcode; | 7477 int scriptcode; |
7391 #else | 7478 #else |
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; |
7398 else | 7486 else |
7399 { | 7487 { |
7486 | 7574 |
7487 #if USE_ATSUI | 7575 #if USE_ATSUI |
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; | 7580 |
7493 Rect char_bounds, min_bounds, max_bounds; | 7581 font->min_byte1 = 0; |
7494 int min_width, max_width; | 7582 font->max_byte1 = 0xff; |
7495 ATSTrapezoid glyph_bounds; | 7583 font->min_char_or_byte2 = 0; |
7496 | 7584 font->max_char_or_byte2 = 0xff; |
7497 font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000); | 7585 |
7498 if (font->per_char == NULL) | 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 { |
7507 FMFontFamily font_family; | 7603 FMFontFamily font_family; |
7508 FMFontStyle style; | 7604 FMFontStyle style; |
7523 if (font->cg_font) | 7619 if (font->cg_font) |
7524 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100); | 7620 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100); |
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 } |
7537 | 7640 XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20); |
7538 for (c = 0x20; c <= 0xff; c++) | 7641 |
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); |
7663 | |
7664 #if USE_CG_TEXT_DRAWING | |
7665 if (font->cg_glyphs && font->cg_glyphs[c] == 0) | |
7566 { | 7666 { |
7567 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x | 7667 /* Don't use CG text drawing if font substitution occurs in |
7568 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); | 7668 ASCII or Latin-1 characters. */ |
7569 | 7669 CGFontRelease (font->cg_font); |
7570 char_width = Fix2Long (glyph_bounds.upperRight.x | 7670 font->cg_font = NULL; |
7571 - glyph_bounds.upperLeft.x); | 7671 xfree (font->cg_glyphs); |
7572 STORE_XCHARSTRUCT (font->per_char[c], | 7672 font->cg_glyphs = NULL; |
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 } | 7673 } |
7599 #if USE_CG_TEXT_DRAWING | |
7600 if (err == noErr && char_width > 0 && font->cg_font) | |
7601 { | |
7602 ATSUGlyphInfoArray glyph_info_array; | |
7603 ByteCount count = sizeof (ATSUGlyphInfoArray); | |
7604 | |
7605 err = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning, | |
7606 kATSUToTextEnd, NULL, NULL, NULL); | |
7607 if (err == noErr) | |
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 } | |
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 |
7633 { | 7679 { |
7634 GrafPtr port; | 7680 GrafPtr port; |
7663 || font->mac_scriptcode == smSimpChinese | 7709 || font->mac_scriptcode == smSimpChinese |
7664 || font->mac_scriptcode == smKorean); | 7710 || font->mac_scriptcode == smKorean); |
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; |
7671 font->max_char_or_byte2 = 0xfe; | 7719 font->max_char_or_byte2 = 0xfe; |
7672 | 7720 |
7691 break; | 7739 break; |
7692 case smKorean: | 7740 case smKorean: |
7693 char_width = StringWidth("\p\xa1\xa1"); | 7741 char_width = StringWidth("\p\xa1\xa1"); |
7694 break; | 7742 break; |
7695 } | 7743 } |
7696 } | 7744 |
7697 else | 7745 font->bounds.per_char = NULL; |
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 | |
7708 if (is_two_byte_font) | |
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; |
7714 else | 7749 else |
7715 font->max_bounds.rbearing = char_width; | 7750 font->max_bounds.rbearing = char_width; |
7720 | 7755 |
7721 font->min_bounds = font->max_bounds; | 7756 font->min_bounds = font->max_bounds; |
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; | 7761 |
7727 char ch; | 7762 font->min_byte1 = font->max_byte1 = 0; |
7728 | 7763 font->min_char_or_byte2 = 0x20; |
7729 font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); | 7764 font->max_char_or_byte2 = 0xff; |
7730 bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1)); | 7765 |
7731 | 7766 font->bounds.per_char = |
7732 min_width = max_width = char_width; | 7767 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); |
7733 SetRect (&min_bounds, -32767, -32767, 32767, 32767); | 7768 if (font->bounds.per_char == NULL) |
7734 SetRect (&max_bounds, 0, 0, 0, 0); | |
7735 for (c = 0x20; c <= 0xff; c++) | |
7736 { | 7769 { |
7737 if (c == 0x7f) | 7770 mac_unload_font (&one_mac_display_info, font); |
7738 { | 7771 return NULL; |
7739 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); | |
7740 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); | |
7741 continue; | |
7742 } | |
7743 | |
7744 ch = c; | |
7745 char_width = CharWidth (ch); | |
7746 QDTextBounds (1, &ch, &char_bounds); | |
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 } | 7772 } |
7766 if (min_width == max_width | 7773 bzero (font->bounds.per_char, |
7767 && max_bounds.left >= 0 && max_bounds.right <= max_width) | 7774 sizeof (XCharStruct) * (0xff - 0x20 + 1)); |
7768 { | 7775 |
7769 /* Fixed width and no overhangs. */ | 7776 space_bounds = font->bounds.per_char; |
7770 xfree (font->per_char); | 7777 mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent, |
7771 font->per_char = NULL; | 7778 space_bounds, NULL); |
7772 } | 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. */ |
7776 TextFont (old_fontnum); | 7785 TextFont (old_fontnum); |
7777 TextSize (old_fontsize); | 7786 TextSize (old_fontsize); |
7778 TextFace (old_fontface); | 7787 TextFace (old_fontface); |
7788 } | |
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 } | |
7779 } | 7828 } |
7780 | 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 |
7795 mac_unload_font (dpyinfo, font) | 7844 mac_unload_font (dpyinfo, font) |
7796 struct mac_display_info *dpyinfo; | 7845 struct mac_display_info *dpyinfo; |
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 | |
7811 #endif | 7869 #endif |
7812 xfree (font); | 7870 xfree (font); |
7813 } | 7871 } |
7814 | 7872 |
7815 | 7873 |