comparison src/xfont.c @ 94940:061d44df20b7

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.
author Kenichi Handa <handa@m17n.org>
date Wed, 14 May 2008 01:42:33 +0000
parents 1e28008a13e5
children 8971ddf55736
comparison
equal deleted inserted replaced
94939:da7871784939 94940:061d44df20b7
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */ 22 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"
29 #include "dispextern.h" 30 #include "dispextern.h"
30 #include "xterm.h" 31 #include "xterm.h"
32 #include "blockinput.h" 33 #include "blockinput.h"
33 #include "character.h" 34 #include "character.h"
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
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 57
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. */
91 61
152 return ((pcm == NULL 122 return ((pcm == NULL
153 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)) 123 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
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,
179 xfont_list_family, 184 xfont_list_family,
180 NULL, 185 NULL,
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;
192 199
193 static Lisp_Object 200 static Lisp_Object
198 205
199 return (dpyinfo->name_list_element); 206 return (dpyinfo->name_list_element);
200 } 207 }
201 208
202 extern Lisp_Object Vface_alternative_font_registry_alist; 209 extern Lisp_Object Vface_alternative_font_registry_alist;
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 *));
203 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;
207 Display *display; 222 Display *display;
228 if (num_fonts < limit) 243 if (num_fonts < limit)
229 break; 244 break;
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; 251
237 252 for (i = 0; i < num_fonts; i++)
238 ASET (entity, FONT_TYPE_INDEX, Qx); 253 indices[i] = names[i];
239 ASET (entity, FONT_FRAME_INDEX, frame); 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) 257 {
243 { 258 Lisp_Object entity;
244 /* This may be an alias name. Try to get the full XLFD name 259 int result;
245 from XA_FONT property of the font. */ 260
246 XFontStruct *font = XLoadQueryFont (display, names[i]); 261 if (i > 0 && strcasecmp (indices[i - 1], indices[i]) == 0)
247 unsigned long value;
248
249 if (! font)
250 continue; 262 continue;
251 if (XGetFontProperty (font, XA_FONT, &value)) 263
264 entity = font_make_entity ();
265 ASET (entity, FONT_TYPE_INDEX, Qx);
266
267 result = font_parse_xlfd (indices[i], entity);
268 if (result < 0)
252 { 269 {
253 char *name = (char *) XGetAtomName (display, (Atom) value); 270 /* This may be an alias name. Try to get the full XLFD name
254 int len = strlen (name); 271 from XA_FONT property of the font. */
255 272 XFontStruct *font = XLoadQueryFont (display, indices[i]);
256 /* If DXPC (a Differential X Protocol Compressor) 273 unsigned long value;
257 Ver.3.7 is running, XGetAtomName will return null 274
258 string. We must avoid such a name. */ 275 if (! font)
259 if (len > 0) 276 continue;
260 result = font_parse_xlfd (name, entity); 277 if (XGetFontProperty (font, XA_FONT, &value))
261 XFree (name); 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);
262 } 290 }
263 XFreeFont (display, font); 291
264 } 292 if (result == 0
265 293 /* Avoid auto-scaled fonts. */
266 if (result == 0) 294 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
267 { 295 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
268 Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX); 296 list = Fcons (entity, list);
269 char *p = (char *) SDATA (SYMBOL_NAME (val));
270
271 /* P == "RESX-RESY-SPACING-AVGWIDTH. We rejust this font if
272 it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0). */
273 if (atoi (p) > 0)
274 {
275 p += SBYTES (SYMBOL_NAME (val));
276 while (p[-1] != '-') p--;
277 if (atoi (p) == 0)
278 continue;
279 }
280 list = Fcons (entity, list);
281 } 297 }
282 } 298 }
283 299
284 x_uncatch_errors (); 300 x_uncatch_errors ();
285 UNBLOCK_INPUT; 301 UNBLOCK_INPUT;
291 xfont_list (frame, spec) 307 xfont_list (frame, spec)
292 Lisp_Object frame, spec; 308 Lisp_Object 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); 329 }
314 if (CONSP (val)) 330
315 font_name = XCDR (val); 331 registry = AREF (spec, FONT_REGISTRY_INDEX);
316 } 332 if (NILP (registry))
317 333 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
318 if (STRINGP (font_name) 334 len = font_unparse_xlfd (spec, 0, name, 256);
319 && ! strchr ((char *) SDATA (font_name), ':')) 335 ASET (spec, FONT_REGISTRY_INDEX, registry);
320 list = xfont_list_pattern (frame, display, (char *) SDATA (font_name)); 336 if (len < 0)
321 else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0) 337 return Qnil;
322 return null_vector; 338 list = xfont_list_pattern (frame, display, name);
323 else 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) */
327 { 343
328 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX); 344 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
329 Lisp_Object alter; 345 {
330 346 strcpy (r, "iso10646-1");
331 if (! NILP (registry) 347 list = xfont_list_pattern (frame, display, name);
332 && (alter = Fassoc (SYMBOL_NAME (registry), 348 }
333 Vface_alternative_font_registry_alist), 349 }
334 CONSP (alter))) 350 if (NILP (list) && ! NILP (registry))
335 { 351 {
336 /* Pointer to REGISTRY-ENCODING field. */ 352 Lisp_Object alter;
337 char *r = name + len - SBYTES (SYMBOL_NAME (registry)); 353
338 354 if ((alter = Fassoc (SYMBOL_NAME (registry),
339 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter)) 355 Vface_alternative_font_registry_alist),
340 if (STRINGP (XCAR (alter)) 356 CONSP (alter)))
341 && ((r - name) + SBYTES (XCAR (alter))) < 255) 357 {
342 { 358 /* Pointer to REGISTRY-ENCODING field. */
343 strcpy (r, (char *) SDATA (XCAR (alter))); 359 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
344 list = xfont_list_pattern (frame, display, name); 360
345 if (! NILP (list)) 361 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
346 break; 362 if (STRINGP (XCAR (alter))
347 } 363 && ((r - name) + SBYTES (XCAR (alter))) < 256)
348 } 364 {
349 } 365 strcpy (r, (char *) SDATA (XCAR (alter)));
350 } 366 list = xfont_list_pattern (frame, display, name);
351 367 if (! NILP (list))
352 return (NILP (list) ? null_vector : Fvconcat (1, &list)); 368 break;
369 }
370 }
371 }
372
373 return list;
353 } 374 }
354 375
355 static Lisp_Object 376 static Lisp_Object
356 xfont_match (frame, spec) 377 xfont_match (frame, spec)
357 Lisp_Object frame, spec; 378 Lisp_Object frame, spec;
358 { 379 {
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 {
377 if (XGetFontProperty (xfont, XA_FONT, &value)) 403 if (XGetFontProperty (xfont, XA_FONT, &value))
378 { 404 {
384 /* If DXPC (a Differential X Protocol Compressor) 410 /* If DXPC (a Differential X Protocol Compressor)
385 Ver.3.7 is running, XGetAtomName will return null 411 Ver.3.7 is running, XGetAtomName will return null
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 }
395 XFree (name); 420 XFree (name);
396 } 421 }
451 if (last_len == p1 - p0 476 if (last_len == p1 - p0
452 && bcmp (last_family, p0, last_len) == 0) 477 && bcmp (last_family, p0, last_len) == 0)
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
461 XFreeFontNames (names); 486 XFreeFontNames (names);
462 x_uncatch_errors (); 487 x_uncatch_errors ();
463 UNBLOCK_INPUT; 488 UNBLOCK_INPUT;
464 489
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;
472 int pixel_size; 499 int pixel_size;
473 { 500 {
476 char name[256]; 503 char name[256];
477 int len; 504 int len;
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);
498 xfont = XLoadQueryFont (display, name); 534 xfont = XLoadQueryFont (display, name);
499 if (x_had_errors_p (display)) 535 if (x_had_errors_p (display))
501 /* This error is perhaps due to insufficient memory on X server. 537 /* This error is perhaps due to insufficient memory on X server.
502 Let's just ignore it. */ 538 Let's just ignore it. */
503 x_clear_errors (display); 539 x_clear_errors (display);
504 xfont = NULL; 540 xfont = NULL;
505 } 541 }
506 x_uncatch_errors (); 542 fullname = Qnil;
507 UNBLOCK_INPUT; 543 /* Try to get the full name of FONT. */
508 544 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
509 if (! xfont) 545 {
510 return NULL; 546 char *p0, *p;
511 font = malloc (sizeof (struct font));
512 font->format = Qx;
513 font->font.font = xfont;
514 font->entity = entity;
515 font->pixel_size = pixel_size;
516 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;
527 font->repertory_charset = repertory ? repertory->id : -1;
528 font->ascent = xfont->ascent;
529 font->descent = xfont->descent;
530
531 if (xfont->min_bounds.width == xfont->max_bounds.width)
532 {
533 /* Fixed width font. */
534 font->font.average_width = font->font.space_width
535 = xfont->min_bounds.width;
536 }
537 else
538 {
539 XChar2b char2b;
540 XCharStruct *pcm;
541
542 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
543 pcm = xfont_get_pcm (xfont, &char2b);
544 if (pcm)
545 font->font.space_width = pcm->width;
546 else
547 font->font.space_width = xfont->max_bounds.width;
548
549 font->font.average_width
550 = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
551 ? (long) value / 10 : 0);
552 if (font->font.average_width < 0)
553 font->font.average_width = - font->font.average_width;
554 if (font->font.average_width == 0)
555 {
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; 547 int dashes = 0;
578 548
579 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);; 549 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
580 /* Count the number of dashes in the "full name". 550 /* Count the number of dashes in the "full name".
581 If it is too few, this isn't really the font's full name, 551 If it is too few, this isn't really the font's full name,
588 dashes++; 558 dashes++;
589 p++; 559 p++;
590 } 560 }
591 561
592 if (dashes >= 13) 562 if (dashes >= 13)
593 { 563 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
594 full_name = (char *) malloc (p - p0 + 1);
595 if (full_name)
596 bcopy (p0, full_name, p - p0 + 1);
597 }
598 XFree (p0); 564 XFree (p0);
599 565 }
600 if (full_name) 566 x_uncatch_errors ();
601 font->font.full_name = full_name; 567 UNBLOCK_INPUT;
568
569 if (! xfont)
570 return Qnil;
571
572 font_object = font_make_object (VECSIZE (struct xfont_info));
573 ASET (font_object, FONT_TYPE_INDEX, Qx);
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);
589 font->pixel_size = pixel_size;
590 font->driver = &xfont_driver;
591 font->encoding_charset = encoding->id;
592 font->repertory_charset = repertory ? repertory->id : -1;
593 font->ascent = xfont->ascent;
594 font->descent = xfont->descent;
595 font->height = font->ascent + font->descent;
596 font->min_width = xfont->min_bounds.width;
597 if (xfont->min_bounds.width == xfont->max_bounds.width)
598 {
599 /* Fixed width font. */
600 font->average_width = font->space_width = xfont->min_bounds.width;
601 }
602 else
603 {
604 XCharStruct *pcm;
605 XChar2b char2b;
606 Lisp_Object val;
607
608 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
609 pcm = xfont_get_pcm (xfont, &char2b);
610 if (pcm)
611 font->space_width = pcm->width;
602 else 612 else
603 font->font.full_name = font->font.name; 613 font->space_width = 0;
604 } 614
605 font->file_name = NULL; 615 val = Ffont_get (font_object, QCavgwidth);
606 616 if (INTEGERP (val))
607 font->font.size = xfont->max_bounds.width; 617 font->average_width = XINT (val);
608 font->font.height = xfont->ascent + xfont->descent; 618 if (font->average_width < 0)
609 font->font.baseline_offset 619 font->average_width = - font->average_width;
620 if (font->average_width == 0
621 && encoding->ascii_compatible_p)
622 {
623 int width = font->space_width, n = pcm != NULL;
624
625 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
626 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
627 width += pcm->width, n++;
628 font->average_width = width / n;
629 }
630 }
631
632 BLOCK_INPUT;
633 font->underline_thickness
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 648 UNBLOCK_INPUT;
649
650 if (NILP (fullname))
651 fullname = AREF (font_object, FONT_NAME_INDEX);
652 font->vertical_centering
619 = (STRINGP (Vvertical_centering_font_regexp) 653 = (STRINGP (Vvertical_centering_font_regexp)
620 && (fast_c_string_match_ignore_case 654 && (fast_string_match_ignore_case
621 (Vvertical_centering_font_regexp, font->font.full_name) >= 0)); 655 (Vvertical_centering_font_regexp, fullname) >= 0));
622 656
623 UNBLOCK_INPUT; 657 return font_object;
624
625 dpyinfo->n_fonts++;
626
627 /* Set global flag fonts_changed_p to non-zero if the font loaded
628 has a character with a smaller width than any other character
629 before, or if the font loaded has a smaller height than any other
630 font loaded before. If this happens, it will make a glyph matrix
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
646 return font;
647 } 658 }
648 659
649 static void 660 static void
650 xfont_close (f, font) 661 xfont_close (f, font)
651 FRAME_PTR f; 662 FRAME_PTR f;
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
666 xfont_prepare_face (f, face) 671 xfont_prepare_face (f, face)
667 FRAME_PTR f; 672 FRAME_PTR f;
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
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 682
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;
696 int c; 686 int c;
708 static unsigned 698 static unsigned
709 xfont_encode_char (font, c) 699 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;
716 707
717 charset = CHARSET_FROM_ID (font->encoding_charset); 708 charset = CHARSET_FROM_ID (font->encoding_charset);
724 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset) 715 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
725 ? code : FONT_INVALID_CODE); 716 ? code : FONT_INVALID_CODE);
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
733 xfont_text_extents (font, code, nglyphs, metrics) 724 xfont_text_extents (font, code, nglyphs, metrics)
734 struct font *font; 725 struct font *font;
735 unsigned *code; 726 unsigned *code;
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
742 if (metrics) 734 if (metrics)
743 bzero (metrics, sizeof (struct font_metrics)); 735 bzero (metrics, sizeof (struct font_metrics));
747 static XCharStruct *pcm; 739 static XCharStruct *pcm;
748 740
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)
756 metrics->lbearing = width + pcm->lbearing; 748 metrics->lbearing = width + pcm->lbearing;
757 if (metrics->rbearing < width + pcm->rbearing) 749 if (metrics->rbearing < width + pcm->rbearing)
770 static int 762 static int
771 xfont_draw (s, from, to, x, y, with_background) 763 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
792 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0) 779 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
793 { 780 {
847 UNBLOCK_INPUT; 834 UNBLOCK_INPUT;
848 835
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 ()
855 { 852 {
856 xfont_driver.type = Qx; 853 xfont_driver.type = Qx;