diff options
| author | Kenichi Handa | 2008-05-14 01:42:33 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2008-05-14 01:42:33 +0000 |
| commit | f0c557507cae98312e85c88e88562e6fbe52496d (patch) | |
| tree | 6751e3a0281371655a60847fd7c6d263787e26f0 /src | |
| parent | b51238f5ce0a25760f1779655e587f1f284caaa4 (diff) | |
| download | emacs-f0c557507cae98312e85c88e88562e6fbe52496d.tar.gz emacs-f0c557507cae98312e85c88e88562e6fbe52496d.zip | |
Include <stdlib.h> and "ccl.h".
(struct xfont_info): New structure.
(xfont_query_font): Deleted.
(xfont_find_ccl_program): Renamed from x_find_ccl_program and
moved from xterm.c.
(xfont_driver): Adjusted for the change of struct font_driver.
(compare_font_names): New function.
(xfont_list_pattern): Sort font names case insensitively. Make
font_entity by calling font_make_entity. Avoid auto-scaled fonts.
(xfont_list): Return a list, not vector.
(xfont_match): If the font doesn't have QCname property, generate
a name from the other font properties.
(xfont_open): Return a font-ojbect. Adjusted for the change of
struct font. Get underline_thickness and underline_position from
font property. Don't update dpyinfo->smallest_font_height and
dpyinfo->smallest_char_width.
(xfont_close): Don't free struct font.
(xfont_prepare_face): Adjusted for the change of struct font.
(xfont_done_face): Deleted.
(xfont_has_char): Adjusted for the change of struct font.
(xfont_encode_char, xfont_draw): Likewise.
(xfont_check): New function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfont.c | 537 |
1 files changed, 267 insertions, 270 deletions
diff --git a/src/xfont.c b/src/xfont.c index f13f3e5e36c..8f400687a8a 100644 --- a/src/xfont.c +++ b/src/xfont.c | |||
| @@ -23,6 +23,7 @@ Boston, MA 02110-1301, USA. */ | |||
| 23 | 23 | ||
| 24 | #include <config.h> | 24 | #include <config.h> |
| 25 | #include <stdio.h> | 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> | ||
| 26 | #include <X11/Xlib.h> | 27 | #include <X11/Xlib.h> |
| 27 | 28 | ||
| 28 | #include "lisp.h" | 29 | #include "lisp.h" |
| @@ -34,57 +35,26 @@ Boston, MA 02110-1301, USA. */ | |||
| 34 | #include "charset.h" | 35 | #include "charset.h" |
| 35 | #include "fontset.h" | 36 | #include "fontset.h" |
| 36 | #include "font.h" | 37 | #include "font.h" |
| 38 | #include "ccl.h" | ||
| 37 | 39 | ||
| 38 | 40 | ||
| 39 | /* X core font driver. */ | 41 | /* X core font driver. */ |
| 40 | 42 | ||
| 43 | struct xfont_info | ||
| 44 | { | ||
| 45 | struct font font; | ||
| 46 | Display *display; | ||
| 47 | XFontStruct *xfont; | ||
| 48 | }; | ||
| 49 | |||
| 41 | /* Prototypes of support functions. */ | 50 | /* Prototypes of support functions. */ |
| 42 | extern void x_clear_errors P_ ((Display *)); | 51 | extern void x_clear_errors P_ ((Display *)); |
| 43 | 52 | ||
| 44 | static char *xfont_query_font P_ ((Display *, char *, Lisp_Object)); | ||
| 45 | static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *)); | 53 | static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *)); |
| 54 | static void xfont_find_ccl_program P_ ((struct font *)); | ||
| 46 | static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **, | 55 | static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **, |
| 47 | struct charset **)); | 56 | struct charset **)); |
| 48 | 57 | ||
| 49 | static char * | ||
| 50 | xfont_query_font (display, name, spec) | ||
| 51 | Display *display; | ||
| 52 | char *name; | ||
| 53 | Lisp_Object spec; | ||
| 54 | { | ||
| 55 | XFontStruct *font; | ||
| 56 | |||
| 57 | BLOCK_INPUT; | ||
| 58 | x_catch_errors (display); | ||
| 59 | font = XLoadQueryFont (display, name); | ||
| 60 | name = NULL; | ||
| 61 | if (x_had_errors_p (display)) | ||
| 62 | { | ||
| 63 | /* This error is perhaps due to insufficient memory on X | ||
| 64 | server. Let's just ignore it. */ | ||
| 65 | x_clear_errors (display); | ||
| 66 | } | ||
| 67 | else if (font) | ||
| 68 | { | ||
| 69 | unsigned long value; | ||
| 70 | |||
| 71 | if (XGetFontProperty (font, XA_FONT, &value)) | ||
| 72 | { | ||
| 73 | char *n = (char *) XGetAtomName (display, (Atom) value); | ||
| 74 | |||
| 75 | if (font_parse_xlfd (n, spec) >= 0) | ||
| 76 | name = n; | ||
| 77 | else | ||
| 78 | XFree (n); | ||
| 79 | } | ||
| 80 | XFreeFont (display, font); | ||
| 81 | } | ||
| 82 | x_uncatch_errors (); | ||
| 83 | UNBLOCK_INPUT; | ||
| 84 | |||
| 85 | return name; | ||
| 86 | } | ||
| 87 | |||
| 88 | 58 | ||
| 89 | /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B | 59 | /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B |
| 90 | is not contained in the font. */ | 60 | is not contained in the font. */ |
| @@ -154,25 +124,60 @@ xfont_get_pcm (xfont, char2b) | |||
| 154 | ? NULL : pcm); | 124 | ? NULL : pcm); |
| 155 | } | 125 | } |
| 156 | 126 | ||
| 127 | /* Find a CCL program for a font specified by FONTP, and set the member | ||
| 128 | `encoder' of the structure. */ | ||
| 129 | |||
| 130 | static void | ||
| 131 | xfont_find_ccl_program (font) | ||
| 132 | struct font *font; | ||
| 133 | { | ||
| 134 | Lisp_Object list, elt; | ||
| 135 | |||
| 136 | elt = Qnil; | ||
| 137 | for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list)) | ||
| 138 | { | ||
| 139 | elt = XCAR (list); | ||
| 140 | if (CONSP (elt) | ||
| 141 | && STRINGP (XCAR (elt)) | ||
| 142 | && ((fast_string_match_ignore_case (XCAR (elt), | ||
| 143 | font->props[FONT_NAME_INDEX]) | ||
| 144 | >= 0) | ||
| 145 | || (fast_string_match_ignore_case (XCAR (elt), | ||
| 146 | font->props[FONT_FULLNAME_INDEX]) | ||
| 147 | >= 0))) | ||
| 148 | break; | ||
| 149 | } | ||
| 150 | |||
| 151 | if (! NILP (list)) | ||
| 152 | { | ||
| 153 | struct ccl_program *ccl | ||
| 154 | = (struct ccl_program *) xmalloc (sizeof (struct ccl_program)); | ||
| 155 | |||
| 156 | if (setup_ccl_program (ccl, XCDR (elt)) < 0) | ||
| 157 | xfree (ccl); | ||
| 158 | else | ||
| 159 | font->font_encoder = ccl; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 157 | static Lisp_Object xfont_get_cache P_ ((FRAME_PTR)); | 163 | static Lisp_Object xfont_get_cache P_ ((FRAME_PTR)); |
| 158 | static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object)); | 164 | static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object)); |
| 159 | static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object)); | 165 | static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object)); |
| 160 | static Lisp_Object xfont_list_family P_ ((Lisp_Object)); | 166 | static Lisp_Object xfont_list_family P_ ((Lisp_Object)); |
| 161 | static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int)); | 167 | static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int)); |
| 162 | static void xfont_close P_ ((FRAME_PTR, struct font *)); | 168 | static void xfont_close P_ ((FRAME_PTR, struct font *)); |
| 163 | static int xfont_prepare_face P_ ((FRAME_PTR, struct face *)); | 169 | static int xfont_prepare_face P_ ((FRAME_PTR, struct face *)); |
| 164 | #if 0 | ||
| 165 | static void xfont_done_face P_ ((FRAME_PTR, struct face *)); | ||
| 166 | #endif | ||
| 167 | static int xfont_has_char P_ ((Lisp_Object, int)); | 170 | static int xfont_has_char P_ ((Lisp_Object, int)); |
| 168 | static unsigned xfont_encode_char P_ ((struct font *, int)); | 171 | static unsigned xfont_encode_char P_ ((struct font *, int)); |
| 169 | static int xfont_text_extents P_ ((struct font *, unsigned *, int, | 172 | static int xfont_text_extents P_ ((struct font *, unsigned *, int, |
| 170 | struct font_metrics *)); | 173 | struct font_metrics *)); |
| 171 | static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int)); | 174 | static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int)); |
| 175 | static int xfont_check P_ ((FRAME_PTR, struct font *)); | ||
| 172 | 176 | ||
| 173 | struct font_driver xfont_driver = | 177 | struct font_driver xfont_driver = |
| 174 | { | 178 | { |
| 175 | 0, /* Qx */ | 179 | 0, /* Qx */ |
| 180 | 0, /* case insensitive */ | ||
| 176 | xfont_get_cache, | 181 | xfont_get_cache, |
| 177 | xfont_list, | 182 | xfont_list, |
| 178 | xfont_match, | 183 | xfont_match, |
| @@ -181,11 +186,13 @@ struct font_driver xfont_driver = | |||
| 181 | xfont_open, | 186 | xfont_open, |
| 182 | xfont_close, | 187 | xfont_close, |
| 183 | xfont_prepare_face, | 188 | xfont_prepare_face, |
| 184 | NULL /*xfont_done_face*/, | 189 | NULL, |
| 185 | xfont_has_char, | 190 | xfont_has_char, |
| 186 | xfont_encode_char, | 191 | xfont_encode_char, |
| 187 | xfont_text_extents, | 192 | xfont_text_extents, |
| 188 | xfont_draw | 193 | xfont_draw, |
| 194 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
| 195 | xfont_check | ||
| 189 | }; | 196 | }; |
| 190 | 197 | ||
| 191 | extern Lisp_Object QCname; | 198 | extern Lisp_Object QCname; |
| @@ -201,6 +208,14 @@ xfont_get_cache (f) | |||
| 201 | 208 | ||
| 202 | extern Lisp_Object Vface_alternative_font_registry_alist; | 209 | extern Lisp_Object Vface_alternative_font_registry_alist; |
| 203 | 210 | ||
| 211 | static int | ||
| 212 | compare_font_names (const void *name1, const void *name2) | ||
| 213 | { | ||
| 214 | return strcasecmp (*(const char **) name1, *(const char **) name2); | ||
| 215 | } | ||
| 216 | |||
| 217 | static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *)); | ||
| 218 | |||
| 204 | static Lisp_Object | 219 | static Lisp_Object |
| 205 | xfont_list_pattern (frame, display, pattern) | 220 | xfont_list_pattern (frame, display, pattern) |
| 206 | Lisp_Object frame; | 221 | Lisp_Object frame; |
| @@ -230,54 +245,55 @@ xfont_list_pattern (frame, display, pattern) | |||
| 230 | XFreeFontNames (names); | 245 | XFreeFontNames (names); |
| 231 | } | 246 | } |
| 232 | 247 | ||
| 233 | for (i = 0; i < num_fonts; i++) | 248 | if (num_fonts > 0) |
| 234 | { | 249 | { |
| 235 | Lisp_Object entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil); | 250 | char **indices = alloca (sizeof (char *) * num_fonts); |
| 236 | int result; | ||
| 237 | 251 | ||
| 238 | ASET (entity, FONT_TYPE_INDEX, Qx); | 252 | for (i = 0; i < num_fonts; i++) |
| 239 | ASET (entity, FONT_FRAME_INDEX, frame); | 253 | indices[i] = names[i]; |
| 254 | qsort (indices, num_fonts, sizeof (char *), compare_font_names); | ||
| 240 | 255 | ||
| 241 | result = font_parse_xlfd (names[i], entity); | 256 | for (i = 0; i < num_fonts; i++) |
| 242 | if (result < 0) | ||
| 243 | { | 257 | { |
| 244 | /* This may be an alias name. Try to get the full XLFD name | 258 | Lisp_Object entity; |
| 245 | from XA_FONT property of the font. */ | 259 | int result; |
| 246 | XFontStruct *font = XLoadQueryFont (display, names[i]); | ||
| 247 | unsigned long value; | ||
| 248 | 260 | ||
| 249 | if (! font) | 261 | if (i > 0 && strcasecmp (indices[i - 1], indices[i]) == 0) |
| 250 | continue; | 262 | continue; |
| 251 | if (XGetFontProperty (font, XA_FONT, &value)) | ||
| 252 | { | ||
| 253 | char *name = (char *) XGetAtomName (display, (Atom) value); | ||
| 254 | int len = strlen (name); | ||
| 255 | |||
| 256 | /* If DXPC (a Differential X Protocol Compressor) | ||
| 257 | Ver.3.7 is running, XGetAtomName will return null | ||
| 258 | string. We must avoid such a name. */ | ||
| 259 | if (len > 0) | ||
| 260 | result = font_parse_xlfd (name, entity); | ||
| 261 | XFree (name); | ||
| 262 | } | ||
| 263 | XFreeFont (display, font); | ||
| 264 | } | ||
| 265 | 263 | ||
| 266 | if (result == 0) | 264 | entity = font_make_entity (); |
| 267 | { | 265 | ASET (entity, FONT_TYPE_INDEX, Qx); |
| 268 | Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX); | ||
| 269 | char *p = (char *) SDATA (SYMBOL_NAME (val)); | ||
| 270 | 266 | ||
| 271 | /* P == "RESX-RESY-SPACING-AVGWIDTH. We rejust this font if | 267 | result = font_parse_xlfd (indices[i], entity); |
| 272 | it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0). */ | 268 | if (result < 0) |
| 273 | if (atoi (p) > 0) | ||
| 274 | { | 269 | { |
| 275 | p += SBYTES (SYMBOL_NAME (val)); | 270 | /* This may be an alias name. Try to get the full XLFD name |
| 276 | while (p[-1] != '-') p--; | 271 | from XA_FONT property of the font. */ |
| 277 | if (atoi (p) == 0) | 272 | XFontStruct *font = XLoadQueryFont (display, indices[i]); |
| 273 | unsigned long value; | ||
| 274 | |||
| 275 | if (! font) | ||
| 278 | continue; | 276 | continue; |
| 277 | if (XGetFontProperty (font, XA_FONT, &value)) | ||
| 278 | { | ||
| 279 | char *name = (char *) XGetAtomName (display, (Atom) value); | ||
| 280 | int len = strlen (name); | ||
| 281 | |||
| 282 | /* If DXPC (a Differential X Protocol Compressor) | ||
| 283 | Ver.3.7 is running, XGetAtomName will return null | ||
| 284 | string. We must avoid such a name. */ | ||
| 285 | if (len > 0) | ||
| 286 | result = font_parse_xlfd (name, entity); | ||
| 287 | XFree (name); | ||
| 288 | } | ||
| 289 | XFreeFont (display, font); | ||
| 279 | } | 290 | } |
| 280 | list = Fcons (entity, list); | 291 | |
| 292 | if (result == 0 | ||
| 293 | /* Avoid auto-scaled fonts. */ | ||
| 294 | && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0 | ||
| 295 | || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0)) | ||
| 296 | list = Fcons (entity, list); | ||
| 281 | } | 297 | } |
| 282 | } | 298 | } |
| 283 | 299 | ||
| @@ -293,63 +309,68 @@ xfont_list (frame, spec) | |||
| 293 | { | 309 | { |
| 294 | FRAME_PTR f = XFRAME (frame); | 310 | FRAME_PTR f = XFRAME (frame); |
| 295 | Display *display = FRAME_X_DISPLAY_INFO (f)->display; | 311 | Display *display = FRAME_X_DISPLAY_INFO (f)->display; |
| 296 | Lisp_Object list, val, extra, font_name; | 312 | Lisp_Object registry, list, val, extra, font_name; |
| 313 | Lisp_Object dpi, avgwidth; | ||
| 297 | int len; | 314 | int len; |
| 298 | char name[256]; | 315 | char name[256]; |
| 299 | 316 | ||
| 300 | extra = AREF (spec, FONT_EXTRA_INDEX); | 317 | extra = AREF (spec, FONT_EXTRA_INDEX); |
| 301 | font_name = Qnil; | ||
| 302 | if (CONSP (extra)) | 318 | if (CONSP (extra)) |
| 303 | { | 319 | { |
| 304 | val = assq_no_quit (QCotf, extra); | 320 | val = assq_no_quit (QCotf, extra); |
| 305 | if (! NILP (val)) | 321 | if (! NILP (val)) |
| 306 | return null_vector; | 322 | return Qnil; |
| 307 | val = assq_no_quit (QCscript, extra); | 323 | val = assq_no_quit (QCscript, extra); |
| 308 | if (! NILP (val)) | 324 | if (! NILP (val)) |
| 309 | return null_vector; | 325 | return Qnil; |
| 310 | val = assq_no_quit (QClanguage, extra); | 326 | val = assq_no_quit (QClang, extra); |
| 311 | if (! NILP (val)) | 327 | if (! NILP (val)) |
| 312 | return null_vector; | 328 | return Qnil; |
| 313 | val = assq_no_quit (QCname, extra); | ||
| 314 | if (CONSP (val)) | ||
| 315 | font_name = XCDR (val); | ||
| 316 | } | 329 | } |
| 317 | 330 | ||
| 318 | if (STRINGP (font_name) | 331 | registry = AREF (spec, FONT_REGISTRY_INDEX); |
| 319 | && ! strchr ((char *) SDATA (font_name), ':')) | 332 | if (NILP (registry)) |
| 320 | list = xfont_list_pattern (frame, display, (char *) SDATA (font_name)); | 333 | ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1); |
| 321 | else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0) | 334 | len = font_unparse_xlfd (spec, 0, name, 256); |
| 322 | return null_vector; | 335 | ASET (spec, FONT_REGISTRY_INDEX, registry); |
| 323 | else | 336 | if (len < 0) |
| 337 | return Qnil; | ||
| 338 | list = xfont_list_pattern (frame, display, name); | ||
| 339 | if (NILP (list) && NILP (registry)) | ||
| 324 | { | 340 | { |
| 325 | list = xfont_list_pattern (frame, display, name); | 341 | /* Try iso10646-1 */ |
| 326 | if (NILP (list)) | 342 | char *r = name + len - 9; /* 9 == strlen (iso8859-1) */ |
| 343 | |||
| 344 | if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */ | ||
| 327 | { | 345 | { |
| 328 | Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX); | 346 | strcpy (r, "iso10646-1"); |
| 329 | Lisp_Object alter; | 347 | list = xfont_list_pattern (frame, display, name); |
| 348 | } | ||
| 349 | } | ||
| 350 | if (NILP (list) && ! NILP (registry)) | ||
| 351 | { | ||
| 352 | Lisp_Object alter; | ||
| 330 | 353 | ||
| 331 | if (! NILP (registry) | 354 | if ((alter = Fassoc (SYMBOL_NAME (registry), |
| 332 | && (alter = Fassoc (SYMBOL_NAME (registry), | 355 | Vface_alternative_font_registry_alist), |
| 333 | Vface_alternative_font_registry_alist), | 356 | CONSP (alter))) |
| 334 | CONSP (alter))) | 357 | { |
| 335 | { | 358 | /* Pointer to REGISTRY-ENCODING field. */ |
| 336 | /* Pointer to REGISTRY-ENCODING field. */ | 359 | char *r = name + len - SBYTES (SYMBOL_NAME (registry)); |
| 337 | char *r = name + len - SBYTES (SYMBOL_NAME (registry)); | 360 | |
| 338 | 361 | for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter)) | |
| 339 | for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter)) | 362 | if (STRINGP (XCAR (alter)) |
| 340 | if (STRINGP (XCAR (alter)) | 363 | && ((r - name) + SBYTES (XCAR (alter))) < 256) |
| 341 | && ((r - name) + SBYTES (XCAR (alter))) < 255) | 364 | { |
| 342 | { | 365 | strcpy (r, (char *) SDATA (XCAR (alter))); |
| 343 | strcpy (r, (char *) SDATA (XCAR (alter))); | 366 | list = xfont_list_pattern (frame, display, name); |
| 344 | list = xfont_list_pattern (frame, display, name); | 367 | if (! NILP (list)) |
| 345 | if (! NILP (list)) | 368 | break; |
| 346 | break; | 369 | } |
| 347 | } | ||
| 348 | } | ||
| 349 | } | 370 | } |
| 350 | } | 371 | } |
| 351 | 372 | ||
| 352 | return (NILP (list) ? null_vector : Fvconcat (1, &list)); | 373 | return list; |
| 353 | } | 374 | } |
| 354 | 375 | ||
| 355 | static Lisp_Object | 376 | static Lisp_Object |
| @@ -359,18 +380,23 @@ xfont_match (frame, spec) | |||
| 359 | FRAME_PTR f = XFRAME (frame); | 380 | FRAME_PTR f = XFRAME (frame); |
| 360 | Display *display = FRAME_X_DISPLAY_INFO (f)->display; | 381 | Display *display = FRAME_X_DISPLAY_INFO (f)->display; |
| 361 | Lisp_Object extra, val, entity; | 382 | Lisp_Object extra, val, entity; |
| 362 | char *name; | 383 | char buf[256], *name; |
| 363 | XFontStruct *xfont; | 384 | XFontStruct *xfont; |
| 364 | unsigned long value; | 385 | unsigned long value; |
| 365 | 386 | ||
| 366 | extra = AREF (spec, FONT_EXTRA_INDEX); | 387 | extra = AREF (spec, FONT_EXTRA_INDEX); |
| 367 | val = assq_no_quit (QCname, extra); | 388 | val = assq_no_quit (QCname, extra); |
| 368 | if (! CONSP (val) || ! STRINGP (XCDR (val))) | 389 | if (! CONSP (val) || ! STRINGP (XCDR (val))) |
| 369 | return Qnil; | 390 | { |
| 391 | if (font_unparse_xlfd (spec, 0, buf, 256) < 0) | ||
| 392 | return Qnil; | ||
| 393 | name = buf; | ||
| 394 | } | ||
| 395 | else | ||
| 396 | name = (char *) SDATA (XCDR (val)); | ||
| 370 | 397 | ||
| 371 | BLOCK_INPUT; | 398 | BLOCK_INPUT; |
| 372 | entity = Qnil; | 399 | entity = Qnil; |
| 373 | name = (char *) SDATA (XCDR (val)); | ||
| 374 | xfont = XLoadQueryFont (display, name); | 400 | xfont = XLoadQueryFont (display, name); |
| 375 | if (xfont) | 401 | if (xfont) |
| 376 | { | 402 | { |
| @@ -386,9 +412,8 @@ xfont_match (frame, spec) | |||
| 386 | string. We must avoid such a name. */ | 412 | string. We must avoid such a name. */ |
| 387 | if (len > 0) | 413 | if (len > 0) |
| 388 | { | 414 | { |
| 389 | entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil); | 415 | entity = font_make_entity (); |
| 390 | ASET (entity, FONT_TYPE_INDEX, Qx); | 416 | ASET (entity, FONT_TYPE_INDEX, Qx); |
| 391 | ASET (entity, FONT_FRAME_INDEX, frame); | ||
| 392 | if (font_parse_xlfd (name, entity) < 0) | 417 | if (font_parse_xlfd (name, entity) < 0) |
| 393 | entity = Qnil; | 418 | entity = Qnil; |
| 394 | } | 419 | } |
| @@ -453,8 +478,8 @@ xfont_list_family (frame) | |||
| 453 | continue; | 478 | continue; |
| 454 | last_len = p1 - p0; | 479 | last_len = p1 - p0; |
| 455 | last_family = p0; | 480 | last_family = p0; |
| 456 | family = intern_downcase (p0, last_len); | 481 | family = make_unibyte_string (p0, last_len); |
| 457 | if (! memq_no_quit (family, list)) | 482 | if (NILP (Fassoc_string (family, list, Qt))) |
| 458 | list = Fcons (family, list); | 483 | list = Fcons (family, list); |
| 459 | } | 484 | } |
| 460 | 485 | ||
| @@ -465,7 +490,9 @@ xfont_list_family (frame) | |||
| 465 | return list; | 490 | return list; |
| 466 | } | 491 | } |
| 467 | 492 | ||
| 468 | static struct font * | 493 | extern Lisp_Object QCavgwidth; |
| 494 | |||
| 495 | static Lisp_Object | ||
| 469 | xfont_open (f, entity, pixel_size) | 496 | xfont_open (f, entity, pixel_size) |
| 470 | FRAME_PTR f; | 497 | FRAME_PTR f; |
| 471 | Lisp_Object entity; | 498 | Lisp_Object entity; |
| @@ -478,20 +505,29 @@ xfont_open (f, entity, pixel_size) | |||
| 478 | unsigned long value; | 505 | unsigned long value; |
| 479 | Lisp_Object registry; | 506 | Lisp_Object registry; |
| 480 | struct charset *encoding, *repertory; | 507 | struct charset *encoding, *repertory; |
| 508 | Lisp_Object font_object, fullname; | ||
| 481 | struct font *font; | 509 | struct font *font; |
| 482 | XFontStruct *xfont; | 510 | XFontStruct *xfont; |
| 511 | int i; | ||
| 483 | 512 | ||
| 484 | /* At first, check if we know how to encode characters for this | 513 | /* At first, check if we know how to encode characters for this |
| 485 | font. */ | 514 | font. */ |
| 486 | registry = AREF (entity, FONT_REGISTRY_INDEX); | 515 | registry = AREF (entity, FONT_REGISTRY_INDEX); |
| 487 | if (font_registry_charsets (registry, &encoding, &repertory) < 0) | 516 | if (font_registry_charsets (registry, &encoding, &repertory) < 0) |
| 488 | return NULL; | 517 | return Qnil; |
| 489 | 518 | ||
| 490 | if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0) | 519 | if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0) |
| 491 | pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX)); | 520 | pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX)); |
| 521 | else if (pixel_size == 0) | ||
| 522 | { | ||
| 523 | if (FRAME_FONT (f)) | ||
| 524 | pixel_size = FRAME_FONT (f)->pixel_size; | ||
| 525 | else | ||
| 526 | pixel_size = 14; | ||
| 527 | } | ||
| 492 | len = font_unparse_xlfd (entity, pixel_size, name, 256); | 528 | len = font_unparse_xlfd (entity, pixel_size, name, 256); |
| 493 | if (len <= 0) | 529 | if (len <= 0) |
| 494 | return NULL; | 530 | return Qnil; |
| 495 | 531 | ||
| 496 | BLOCK_INPUT; | 532 | BLOCK_INPUT; |
| 497 | x_catch_errors (display); | 533 | x_catch_errors (display); |
| @@ -503,147 +539,122 @@ xfont_open (f, entity, pixel_size) | |||
| 503 | x_clear_errors (display); | 539 | x_clear_errors (display); |
| 504 | xfont = NULL; | 540 | xfont = NULL; |
| 505 | } | 541 | } |
| 542 | fullname = Qnil; | ||
| 543 | /* Try to get the full name of FONT. */ | ||
| 544 | if (xfont && XGetFontProperty (xfont, XA_FONT, &value)) | ||
| 545 | { | ||
| 546 | char *p0, *p; | ||
| 547 | int dashes = 0; | ||
| 548 | |||
| 549 | p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);; | ||
| 550 | /* Count the number of dashes in the "full name". | ||
| 551 | If it is too few, this isn't really the font's full name, | ||
| 552 | so don't use it. | ||
| 553 | In X11R4, the fonts did not come with their canonical names | ||
| 554 | stored in them. */ | ||
| 555 | while (*p) | ||
| 556 | { | ||
| 557 | if (*p == '-') | ||
| 558 | dashes++; | ||
| 559 | p++; | ||
| 560 | } | ||
| 561 | |||
| 562 | if (dashes >= 13) | ||
| 563 | fullname = Fdowncase (make_unibyte_string (p0, p - p0)); | ||
| 564 | XFree (p0); | ||
| 565 | } | ||
| 506 | x_uncatch_errors (); | 566 | x_uncatch_errors (); |
| 507 | UNBLOCK_INPUT; | 567 | UNBLOCK_INPUT; |
| 508 | 568 | ||
| 509 | if (! xfont) | 569 | if (! xfont) |
| 510 | return NULL; | 570 | return Qnil; |
| 511 | font = malloc (sizeof (struct font)); | 571 | |
| 512 | font->format = Qx; | 572 | font_object = font_make_object (VECSIZE (struct xfont_info)); |
| 513 | font->font.font = xfont; | 573 | ASET (font_object, FONT_TYPE_INDEX, Qx); |
| 514 | font->entity = entity; | 574 | if (STRINGP (fullname)) |
| 575 | font_parse_xlfd (SDATA (fullname), font_object); | ||
| 576 | for (i = 1; i < FONT_ENTITY_MAX; i++) | ||
| 577 | ASET (font_object, i, AREF (entity, i)); | ||
| 578 | ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size)); | ||
| 579 | if (STRINGP (fullname)) | ||
| 580 | ASET (font_object, FONT_NAME_INDEX, fullname); | ||
| 581 | else | ||
| 582 | ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len)); | ||
| 583 | ASET (font_object, FONT_FULLNAME_INDEX, fullname); | ||
| 584 | ASET (font_object, FONT_FILE_INDEX, Qnil); | ||
| 585 | ASET (font_object, FONT_FORMAT_INDEX, Qx); | ||
| 586 | font = XFONT_OBJECT (font_object); | ||
| 587 | ((struct xfont_info *) font)->xfont = xfont; | ||
| 588 | ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f); | ||
| 515 | font->pixel_size = pixel_size; | 589 | font->pixel_size = pixel_size; |
| 516 | font->driver = &xfont_driver; | 590 | font->driver = &xfont_driver; |
| 517 | font->font.name = malloc (len + 1); | ||
| 518 | if (! font->font.name) | ||
| 519 | { | ||
| 520 | XFreeFont (display, xfont); | ||
| 521 | free (font); | ||
| 522 | return NULL; | ||
| 523 | } | ||
| 524 | bcopy (name, font->font.name, len + 1); | ||
| 525 | font->font.charset = encoding->id; | ||
| 526 | font->encoding_charset = encoding->id; | 591 | font->encoding_charset = encoding->id; |
| 527 | font->repertory_charset = repertory ? repertory->id : -1; | 592 | font->repertory_charset = repertory ? repertory->id : -1; |
| 528 | font->ascent = xfont->ascent; | 593 | font->ascent = xfont->ascent; |
| 529 | font->descent = xfont->descent; | 594 | font->descent = xfont->descent; |
| 530 | 595 | font->height = font->ascent + font->descent; | |
| 596 | font->min_width = xfont->min_bounds.width; | ||
| 531 | if (xfont->min_bounds.width == xfont->max_bounds.width) | 597 | if (xfont->min_bounds.width == xfont->max_bounds.width) |
| 532 | { | 598 | { |
| 533 | /* Fixed width font. */ | 599 | /* Fixed width font. */ |
| 534 | font->font.average_width = font->font.space_width | 600 | font->average_width = font->space_width = xfont->min_bounds.width; |
| 535 | = xfont->min_bounds.width; | ||
| 536 | } | 601 | } |
| 537 | else | 602 | else |
| 538 | { | 603 | { |
| 539 | XChar2b char2b; | ||
| 540 | XCharStruct *pcm; | 604 | XCharStruct *pcm; |
| 605 | XChar2b char2b; | ||
| 606 | Lisp_Object val; | ||
| 541 | 607 | ||
| 542 | char2b.byte1 = 0x00, char2b.byte2 = 0x20; | 608 | char2b.byte1 = 0x00, char2b.byte2 = 0x20; |
| 543 | pcm = xfont_get_pcm (xfont, &char2b); | 609 | pcm = xfont_get_pcm (xfont, &char2b); |
| 544 | if (pcm) | 610 | if (pcm) |
| 545 | font->font.space_width = pcm->width; | 611 | font->space_width = pcm->width; |
| 546 | else | 612 | else |
| 547 | font->font.space_width = xfont->max_bounds.width; | 613 | font->space_width = 0; |
| 548 | 614 | ||
| 549 | font->font.average_width | 615 | val = Ffont_get (font_object, QCavgwidth); |
| 550 | = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value) | 616 | if (INTEGERP (val)) |
| 551 | ? (long) value / 10 : 0); | 617 | font->average_width = XINT (val); |
| 552 | if (font->font.average_width < 0) | 618 | if (font->average_width < 0) |
| 553 | font->font.average_width = - font->font.average_width; | 619 | font->average_width = - font->average_width; |
| 554 | if (font->font.average_width == 0) | 620 | if (font->average_width == 0 |
| 555 | { | 621 | && encoding->ascii_compatible_p) |
| 556 | if (pcm) | ||
| 557 | { | ||
| 558 | int width = pcm->width; | ||
| 559 | for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++) | ||
| 560 | if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL) | ||
| 561 | width += pcm->width; | ||
| 562 | font->font.average_width = width / 95; | ||
| 563 | } | ||
| 564 | else | ||
| 565 | font->font.average_width = xfont->max_bounds.width; | ||
| 566 | } | ||
| 567 | } | ||
| 568 | font->min_width = xfont->min_bounds.width; | ||
| 569 | if (font->min_width <= 0) | ||
| 570 | font->min_width = font->font.space_width; | ||
| 571 | |||
| 572 | BLOCK_INPUT; | ||
| 573 | /* Try to get the full name of FONT. Put it in FULL_NAME. */ | ||
| 574 | if (XGetFontProperty (xfont, XA_FONT, &value)) | ||
| 575 | { | ||
| 576 | char *full_name = NULL, *p0, *p; | ||
| 577 | int dashes = 0; | ||
| 578 | |||
| 579 | p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);; | ||
| 580 | /* Count the number of dashes in the "full name". | ||
| 581 | If it is too few, this isn't really the font's full name, | ||
| 582 | so don't use it. | ||
| 583 | In X11R4, the fonts did not come with their canonical names | ||
| 584 | stored in them. */ | ||
| 585 | while (*p) | ||
| 586 | { | 622 | { |
| 587 | if (*p == '-') | 623 | int width = font->space_width, n = pcm != NULL; |
| 588 | dashes++; | ||
| 589 | p++; | ||
| 590 | } | ||
| 591 | 624 | ||
| 592 | if (dashes >= 13) | 625 | for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++) |
| 593 | { | 626 | if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL) |
| 594 | full_name = (char *) malloc (p - p0 + 1); | 627 | width += pcm->width, n++; |
| 595 | if (full_name) | 628 | font->average_width = width / n; |
| 596 | bcopy (p0, full_name, p - p0 + 1); | ||
| 597 | } | 629 | } |
| 598 | XFree (p0); | ||
| 599 | |||
| 600 | if (full_name) | ||
| 601 | font->font.full_name = full_name; | ||
| 602 | else | ||
| 603 | font->font.full_name = font->font.name; | ||
| 604 | } | 630 | } |
| 605 | font->file_name = NULL; | ||
| 606 | 631 | ||
| 607 | font->font.size = xfont->max_bounds.width; | 632 | BLOCK_INPUT; |
| 608 | font->font.height = xfont->ascent + xfont->descent; | 633 | font->underline_thickness |
| 609 | font->font.baseline_offset | 634 | = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value) |
| 635 | ? (long) value : 0); | ||
| 636 | font->underline_position | ||
| 637 | = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value) | ||
| 638 | ? (long) value : -1); | ||
| 639 | font->baseline_offset | ||
| 610 | = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) | 640 | = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) |
| 611 | ? (long) value : 0); | 641 | ? (long) value : 0); |
| 612 | font->font.relative_compose | 642 | font->relative_compose |
| 613 | = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) | 643 | = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) |
| 614 | ? (long) value : 0); | 644 | ? (long) value : 0); |
| 615 | font->font.default_ascent | 645 | font->default_ascent |
| 616 | = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) | 646 | = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) |
| 617 | ? (long) value : 0); | 647 | ? (long) value : 0); |
| 618 | font->font.vertical_centering | ||
| 619 | = (STRINGP (Vvertical_centering_font_regexp) | ||
| 620 | && (fast_c_string_match_ignore_case | ||
| 621 | (Vvertical_centering_font_regexp, font->font.full_name) >= 0)); | ||
| 622 | |||
| 623 | UNBLOCK_INPUT; | 648 | UNBLOCK_INPUT; |
| 624 | 649 | ||
| 625 | dpyinfo->n_fonts++; | 650 | if (NILP (fullname)) |
| 626 | 651 | fullname = AREF (font_object, FONT_NAME_INDEX); | |
| 627 | /* Set global flag fonts_changed_p to non-zero if the font loaded | 652 | font->vertical_centering |
| 628 | has a character with a smaller width than any other character | 653 | = (STRINGP (Vvertical_centering_font_regexp) |
| 629 | before, or if the font loaded has a smaller height than any other | 654 | && (fast_string_match_ignore_case |
| 630 | font loaded before. If this happens, it will make a glyph matrix | 655 | (Vvertical_centering_font_regexp, fullname) >= 0)); |
| 631 | reallocation necessary. */ | ||
| 632 | if (dpyinfo->n_fonts == 1) | ||
| 633 | { | ||
| 634 | dpyinfo->smallest_font_height = font->font.height; | ||
| 635 | dpyinfo->smallest_char_width = font->min_width; | ||
| 636 | fonts_changed_p = 1; | ||
| 637 | } | ||
| 638 | else | ||
| 639 | { | ||
| 640 | if (dpyinfo->smallest_font_height > font->font.height) | ||
| 641 | dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1; | ||
| 642 | if (dpyinfo->smallest_char_width > font->min_width) | ||
| 643 | dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1; | ||
| 644 | } | ||
| 645 | 656 | ||
| 646 | return font; | 657 | return font_object; |
| 647 | } | 658 | } |
| 648 | 659 | ||
| 649 | static void | 660 | static void |
| @@ -652,14 +663,8 @@ xfont_close (f, font) | |||
| 652 | struct font *font; | 663 | struct font *font; |
| 653 | { | 664 | { |
| 654 | BLOCK_INPUT; | 665 | BLOCK_INPUT; |
| 655 | XFreeFont (FRAME_X_DISPLAY (f), font->font.font); | 666 | XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont); |
| 656 | UNBLOCK_INPUT; | 667 | UNBLOCK_INPUT; |
| 657 | |||
| 658 | if (font->font.name != font->font.full_name) | ||
| 659 | free (font->font.full_name); | ||
| 660 | free (font->font.name); | ||
| 661 | free (font); | ||
| 662 | FRAME_X_DISPLAY_INFO (f)->n_fonts--; | ||
| 663 | } | 668 | } |
| 664 | 669 | ||
| 665 | static int | 670 | static int |
| @@ -668,28 +673,13 @@ xfont_prepare_face (f, face) | |||
| 668 | struct face *face; | 673 | struct face *face; |
| 669 | { | 674 | { |
| 670 | BLOCK_INPUT; | 675 | BLOCK_INPUT; |
| 671 | XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid); | 676 | XSetFont (FRAME_X_DISPLAY (f), face->gc, |
| 677 | ((struct xfont_info *) face->font)->xfont->fid); | ||
| 672 | UNBLOCK_INPUT; | 678 | UNBLOCK_INPUT; |
| 673 | 679 | ||
| 674 | return 0; | 680 | return 0; |
| 675 | } | 681 | } |
| 676 | 682 | ||
| 677 | #if 0 | ||
| 678 | static void | ||
| 679 | xfont_done_face (f, face) | ||
| 680 | FRAME_PTR f; | ||
| 681 | struct face *face; | ||
| 682 | { | ||
| 683 | if (face->extra) | ||
| 684 | { | ||
| 685 | BLOCK_INPUT; | ||
| 686 | XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra); | ||
| 687 | UNBLOCK_INPUT; | ||
| 688 | face->extra = NULL; | ||
| 689 | } | ||
| 690 | } | ||
| 691 | #endif /* 0 */ | ||
| 692 | |||
| 693 | static int | 683 | static int |
| 694 | xfont_has_char (entity, c) | 684 | xfont_has_char (entity, c) |
| 695 | Lisp_Object entity; | 685 | Lisp_Object entity; |
| @@ -710,6 +700,7 @@ xfont_encode_char (font, c) | |||
| 710 | struct font *font; | 700 | struct font *font; |
| 711 | int c; | 701 | int c; |
| 712 | { | 702 | { |
| 703 | XFontStruct *xfont = ((struct xfont_info *) font)->xfont; | ||
| 713 | struct charset *charset; | 704 | struct charset *charset; |
| 714 | unsigned code; | 705 | unsigned code; |
| 715 | XChar2b char2b; | 706 | XChar2b char2b; |
| @@ -726,7 +717,7 @@ xfont_encode_char (font, c) | |||
| 726 | } | 717 | } |
| 727 | char2b.byte1 = code >> 8; | 718 | char2b.byte1 = code >> 8; |
| 728 | char2b.byte2 = code & 0xFF; | 719 | char2b.byte2 = code & 0xFF; |
| 729 | return (xfont_get_pcm (font->font.font, &char2b) ? code : FONT_INVALID_CODE); | 720 | return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE); |
| 730 | } | 721 | } |
| 731 | 722 | ||
| 732 | static int | 723 | static int |
| @@ -736,6 +727,7 @@ xfont_text_extents (font, code, nglyphs, metrics) | |||
| 736 | int nglyphs; | 727 | int nglyphs; |
| 737 | struct font_metrics *metrics; | 728 | struct font_metrics *metrics; |
| 738 | { | 729 | { |
| 730 | XFontStruct *xfont = ((struct xfont_info *) font)->xfont; | ||
| 739 | int width = 0; | 731 | int width = 0; |
| 740 | int i, x; | 732 | int i, x; |
| 741 | 733 | ||
| @@ -749,7 +741,7 @@ xfont_text_extents (font, code, nglyphs, metrics) | |||
| 749 | if (code[i] >= 0x10000) | 741 | if (code[i] >= 0x10000) |
| 750 | continue; | 742 | continue; |
| 751 | char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF; | 743 | char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF; |
| 752 | pcm = xfont_get_pcm (font->font.font, &char2b); | 744 | pcm = xfont_get_pcm (xfont, &char2b); |
| 753 | if (! pcm) | 745 | if (! pcm) |
| 754 | continue; | 746 | continue; |
| 755 | if (metrics->lbearing > width + pcm->lbearing) | 747 | if (metrics->lbearing > width + pcm->lbearing) |
| @@ -772,20 +764,15 @@ xfont_draw (s, from, to, x, y, with_background) | |||
| 772 | struct glyph_string *s; | 764 | struct glyph_string *s; |
| 773 | int from, to, x, y, with_background; | 765 | int from, to, x, y, with_background; |
| 774 | { | 766 | { |
| 775 | XFontStruct *xfont = s->face->font; | 767 | XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont; |
| 776 | int len = to - from; | 768 | int len = to - from; |
| 777 | GC gc = s->gc; | 769 | GC gc = s->gc; |
| 778 | int i; | 770 | int i; |
| 779 | 771 | ||
| 780 | if (gc != s->face->gc) | 772 | if (s->gc != s->face->gc) |
| 781 | { | 773 | { |
| 782 | XGCValues xgcv; | ||
| 783 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (s->f); | ||
| 784 | |||
| 785 | BLOCK_INPUT; | 774 | BLOCK_INPUT; |
| 786 | XGetGCValues (s->display, gc, GCFont, &xgcv); | 775 | XSetFont (s->display, gc, xfont->fid); |
| 787 | if (xgcv.font != xfont->fid) | ||
| 788 | XSetFont (s->display, gc, xfont->fid); | ||
| 789 | UNBLOCK_INPUT; | 776 | UNBLOCK_INPUT; |
| 790 | } | 777 | } |
| 791 | 778 | ||
| @@ -849,6 +836,16 @@ xfont_draw (s, from, to, x, y, with_background) | |||
| 849 | return len; | 836 | return len; |
| 850 | } | 837 | } |
| 851 | 838 | ||
| 839 | static int | ||
| 840 | xfont_check (f, font) | ||
| 841 | FRAME_PTR f; | ||
| 842 | struct font *font; | ||
| 843 | { | ||
| 844 | struct xfont_info *xfont = (struct xfont_info *) font; | ||
| 845 | |||
| 846 | return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1); | ||
| 847 | } | ||
| 848 | |||
| 852 | 849 | ||
| 853 | void | 850 | void |
| 854 | syms_of_xfont () | 851 | syms_of_xfont () |