(ftfont_open): Genarate a multibyte string if given
[bpt/emacs.git] / src / xfont.c
CommitLineData
c2f5bfd6 1/* xfont.c -- X core font driver.
77ad4cfe
GM
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
c2f5bfd6
KH
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7This file is part of GNU Emacs.
8
9ec0b715 9GNU Emacs is free software: you can redistribute it and/or modify
c2f5bfd6 10it under the terms of the GNU General Public License as published by
9ec0b715
GM
11the Free Software Foundation, either version 3 of the License, or
12(at your option) any later version.
c2f5bfd6
KH
13
14GNU Emacs is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
9ec0b715 20along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
c2f5bfd6
KH
21
22#include <config.h>
23#include <stdio.h>
f0c55750 24#include <stdlib.h>
c2f5bfd6
KH
25#include <X11/Xlib.h>
26
27#include "lisp.h"
28#include "dispextern.h"
29#include "xterm.h"
30#include "frame.h"
31#include "blockinput.h"
32#include "character.h"
33#include "charset.h"
34#include "fontset.h"
35#include "font.h"
f0c55750 36#include "ccl.h"
c2f5bfd6
KH
37
38\f
39/* X core font driver. */
40
f0c55750
KH
41struct xfont_info
42{
43 struct font font;
44 Display *display;
45 XFontStruct *xfont;
46};
47
c2f5bfd6
KH
48/* Prototypes of support functions. */
49extern void x_clear_errors P_ ((Display *));
50
c2f5bfd6 51static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
f0c55750 52static void xfont_find_ccl_program P_ ((struct font *));
c2f5bfd6
KH
53
54/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
55 is not contained in the font. */
56
57static XCharStruct *
58xfont_get_pcm (xfont, char2b)
59 XFontStruct *xfont;
60 XChar2b *char2b;
61{
62 /* The result metric information. */
63 XCharStruct *pcm = NULL;
64
960d80b9 65 font_assert (xfont && char2b);
c2f5bfd6
KH
66
67 if (xfont->per_char != NULL)
68 {
69 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
70 {
71 /* min_char_or_byte2 specifies the linear character index
72 corresponding to the first element of the per_char array,
73 max_char_or_byte2 is the index of the last character. A
74 character with non-zero CHAR2B->byte1 is not in the font.
75 A character with byte2 less than min_char_or_byte2 or
76 greater max_char_or_byte2 is not in the font. */
77 if (char2b->byte1 == 0
78 && char2b->byte2 >= xfont->min_char_or_byte2
79 && char2b->byte2 <= xfont->max_char_or_byte2)
80 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
81 }
82 else
83 {
84 /* If either min_byte1 or max_byte1 are nonzero, both
85 min_char_or_byte2 and max_char_or_byte2 are less than
86 256, and the 2-byte character index values corresponding
87 to the per_char array element N (counting from 0) are:
88
89 byte1 = N/D + min_byte1
90 byte2 = N\D + min_char_or_byte2
91
92 where:
93
94 D = max_char_or_byte2 - min_char_or_byte2 + 1
95 / = integer division
96 \ = integer modulus */
97 if (char2b->byte1 >= xfont->min_byte1
98 && char2b->byte1 <= xfont->max_byte1
99 && char2b->byte2 >= xfont->min_char_or_byte2
100 && char2b->byte2 <= xfont->max_char_or_byte2)
101 pcm = (xfont->per_char
102 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
103 * (char2b->byte1 - xfont->min_byte1))
104 + (char2b->byte2 - xfont->min_char_or_byte2));
105 }
106 }
107 else
108 {
109 /* If the per_char pointer is null, all glyphs between the first
110 and last character indexes inclusive have the same
111 information, as given by both min_bounds and max_bounds. */
112 if (char2b->byte2 >= xfont->min_char_or_byte2
113 && char2b->byte2 <= xfont->max_char_or_byte2)
114 pcm = &xfont->max_bounds;
115 }
116
117 return ((pcm == NULL
118 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
119 ? NULL : pcm);
120}
121
f0c55750
KH
122/* Find a CCL program for a font specified by FONTP, and set the member
123 `encoder' of the structure. */
124
125static void
126xfont_find_ccl_program (font)
127 struct font *font;
128{
129 Lisp_Object list, elt;
130
131 elt = Qnil;
132 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
133 {
134 elt = XCAR (list);
135 if (CONSP (elt)
136 && STRINGP (XCAR (elt))
137 && ((fast_string_match_ignore_case (XCAR (elt),
138 font->props[FONT_NAME_INDEX])
139 >= 0)
140 || (fast_string_match_ignore_case (XCAR (elt),
141 font->props[FONT_FULLNAME_INDEX])
142 >= 0)))
143 break;
144 }
145
146 if (! NILP (list))
147 {
148 struct ccl_program *ccl
149 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
150
151 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
152 xfree (ccl);
153 else
154 font->font_encoder = ccl;
155 }
156}
157
feb2737b 158static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
c2f5bfd6 159static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
6e34c9c1 160static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6 161static Lisp_Object xfont_list_family P_ ((Lisp_Object));
f0c55750 162static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
c2f5bfd6
KH
163static void xfont_close P_ ((FRAME_PTR, struct font *));
164static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
c2f5bfd6
KH
165static int xfont_has_char P_ ((Lisp_Object, int));
166static unsigned xfont_encode_char P_ ((struct font *, int));
167static int xfont_text_extents P_ ((struct font *, unsigned *, int,
168 struct font_metrics *));
169static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
f0c55750 170static int xfont_check P_ ((FRAME_PTR, struct font *));
c2f5bfd6
KH
171
172struct font_driver xfont_driver =
173 {
575abfb7 174 0, /* Qx */
f0c55750 175 0, /* case insensitive */
c2f5bfd6 176 xfont_get_cache,
c2f5bfd6 177 xfont_list,
6e34c9c1 178 xfont_match,
c2f5bfd6
KH
179 xfont_list_family,
180 NULL,
181 xfont_open,
182 xfont_close,
183 xfont_prepare_face,
f0c55750 184 NULL,
c2f5bfd6
KH
185 xfont_has_char,
186 xfont_encode_char,
187 xfont_text_extents,
f0c55750
KH
188 xfont_draw,
189 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
190 xfont_check
c2f5bfd6
KH
191 };
192
193extern Lisp_Object QCname;
194
195static Lisp_Object
feb2737b
KH
196xfont_get_cache (f)
197 FRAME_PTR f;
c2f5bfd6 198{
feb2737b 199 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
200
201 return (dpyinfo->name_list_element);
202}
203
c2f5bfd6
KH
204extern Lisp_Object Vface_alternative_font_registry_alist;
205
f0c55750
KH
206static int
207compare_font_names (const void *name1, const void *name2)
208{
7740d2c7
KH
209 return xstrcasecmp (*(const unsigned char **) name1,
210 *(const unsigned char **) name2);
f0c55750
KH
211}
212
213static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
214
c2f5bfd6 215static Lisp_Object
6c4aeab6
KH
216xfont_list_pattern (frame, display, pattern)
217 Lisp_Object frame;
218 Display *display;
219 char *pattern;
c2f5bfd6 220{
6c4aeab6
KH
221 Lisp_Object list = Qnil;
222 int i, limit, num_fonts;
223 char **names;
c2f5bfd6
KH
224
225 BLOCK_INPUT;
6c4aeab6 226 x_catch_errors (display);
c2f5bfd6 227
6c4aeab6 228 for (limit = 512; ; limit *= 2)
c2f5bfd6 229 {
6c4aeab6
KH
230 names = XListFonts (display, pattern, limit, &num_fonts);
231 if (x_had_errors_p (display))
c2f5bfd6
KH
232 {
233 /* This error is perhaps due to insufficient memory on X
234 server. Let's just ignore it. */
6c4aeab6
KH
235 x_clear_errors (display);
236 num_fonts = 0;
237 break;
c2f5bfd6 238 }
6c4aeab6
KH
239 if (num_fonts < limit)
240 break;
241 XFreeFontNames (names);
242 }
243
f0c55750 244 if (num_fonts > 0)
6c4aeab6 245 {
f0c55750 246 char **indices = alloca (sizeof (char *) * num_fonts);
6c4aeab6 247
f0c55750
KH
248 for (i = 0; i < num_fonts; i++)
249 indices[i] = names[i];
250 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 251
f0c55750 252 for (i = 0; i < num_fonts; i++)
c2f5bfd6 253 {
f0c55750
KH
254 Lisp_Object entity;
255 int result;
6c4aeab6 256
05131107 257 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 258 continue;
6c4aeab6 259
f0c55750
KH
260 entity = font_make_entity ();
261 ASET (entity, FONT_TYPE_INDEX, Qx);
6c4aeab6 262
f0c55750
KH
263 result = font_parse_xlfd (indices[i], entity);
264 if (result < 0)
c2f5bfd6 265 {
f0c55750
KH
266 /* This may be an alias name. Try to get the full XLFD name
267 from XA_FONT property of the font. */
268 XFontStruct *font = XLoadQueryFont (display, indices[i]);
269 unsigned long value;
270
271 if (! font)
6c4aeab6 272 continue;
f0c55750
KH
273 if (XGetFontProperty (font, XA_FONT, &value))
274 {
275 char *name = (char *) XGetAtomName (display, (Atom) value);
276 int len = strlen (name);
277
278 /* If DXPC (a Differential X Protocol Compressor)
279 Ver.3.7 is running, XGetAtomName will return null
280 string. We must avoid such a name. */
281 if (len > 0)
282 result = font_parse_xlfd (name, entity);
283 XFree (name);
284 }
285 XFreeFont (display, font);
c2f5bfd6 286 }
f0c55750
KH
287
288 if (result == 0
289 /* Avoid auto-scaled fonts. */
290 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
291 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
292 list = Fcons (entity, list);
c2f5bfd6 293 }
019e13ef 294 XFreeFontNames (names);
c2f5bfd6
KH
295 }
296
297 x_uncatch_errors ();
298 UNBLOCK_INPUT;
299
960d80b9 300 font_add_log ("xfont-list", build_string (pattern), list);
6c4aeab6
KH
301 return list;
302}
c2f5bfd6 303
6c4aeab6
KH
304static Lisp_Object
305xfont_list (frame, spec)
306 Lisp_Object frame, spec;
307{
308 FRAME_PTR f = XFRAME (frame);
309 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
960d80b9 310 Lisp_Object registry, list, val, extra;
6c4aeab6
KH
311 int len;
312 char name[256];
313
314 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 315 if (CONSP (extra))
c2f5bfd6 316 {
6c4aeab6
KH
317 val = assq_no_quit (QCotf, extra);
318 if (! NILP (val))
f0c55750 319 return Qnil;
6c4aeab6
KH
320 val = assq_no_quit (QCscript, extra);
321 if (! NILP (val))
f0c55750
KH
322 return Qnil;
323 val = assq_no_quit (QClang, extra);
6c4aeab6 324 if (! NILP (val))
f0c55750 325 return Qnil;
c2f5bfd6 326 }
6c4aeab6 327
f0c55750 328 registry = AREF (spec, FONT_REGISTRY_INDEX);
f0c55750
KH
329 len = font_unparse_xlfd (spec, 0, name, 256);
330 ASET (spec, FONT_REGISTRY_INDEX, registry);
331 if (len < 0)
332 return Qnil;
333 list = xfont_list_pattern (frame, display, name);
334 if (NILP (list) && NILP (registry))
c2f5bfd6 335 {
f0c55750
KH
336 /* Try iso10646-1 */
337 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
338
339 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 340 {
f0c55750
KH
341 strcpy (r, "iso10646-1");
342 list = xfont_list_pattern (frame, display, name);
343 }
344 }
345 if (NILP (list) && ! NILP (registry))
346 {
37470f4d 347 /* Try alternate registries. */
f0c55750 348 Lisp_Object alter;
6c4aeab6 349
f0c55750
KH
350 if ((alter = Fassoc (SYMBOL_NAME (registry),
351 Vface_alternative_font_registry_alist),
352 CONSP (alter)))
353 {
354 /* Pointer to REGISTRY-ENCODING field. */
355 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
356
357 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
358 if (STRINGP (XCAR (alter))
359 && ((r - name) + SBYTES (XCAR (alter))) < 256)
360 {
361 strcpy (r, (char *) SDATA (XCAR (alter)));
362 list = xfont_list_pattern (frame, display, name);
363 if (! NILP (list))
364 break;
365 }
6c4aeab6 366 }
c2f5bfd6 367 }
37470f4d
KH
368 if (NILP (list))
369 {
370 /* Try alias. */
371 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
372 if (CONSP (val) && STRINGP (XCDR (val)))
7740d2c7 373 list = xfont_list_pattern (frame, display, (char *) SDATA (XCDR (val)));
37470f4d 374 }
c2f5bfd6 375
f0c55750 376 return list;
c2f5bfd6
KH
377}
378
6e34c9c1
KH
379static Lisp_Object
380xfont_match (frame, spec)
381 Lisp_Object frame, spec;
382{
383 FRAME_PTR f = XFRAME (frame);
384 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
385 Lisp_Object extra, val, entity;
f0c55750 386 char buf[256], *name;
6e34c9c1
KH
387 XFontStruct *xfont;
388 unsigned long value;
389
390 extra = AREF (spec, FONT_EXTRA_INDEX);
391 val = assq_no_quit (QCname, extra);
392 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750
KH
393 {
394 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
395 return Qnil;
396 name = buf;
397 }
398 else
399 name = (char *) SDATA (XCDR (val));
6e34c9c1 400
9c6d1df5 401 BLOCK_INPUT;
6e34c9c1 402 entity = Qnil;
6e34c9c1
KH
403 xfont = XLoadQueryFont (display, name);
404 if (xfont)
405 {
406 if (XGetFontProperty (xfont, XA_FONT, &value))
407 {
408 int len;
409
410 name = (char *) XGetAtomName (display, (Atom) value);
411 len = strlen (name);
412
413 /* If DXPC (a Differential X Protocol Compressor)
414 Ver.3.7 is running, XGetAtomName will return null
415 string. We must avoid such a name. */
416 if (len > 0)
417 {
f0c55750 418 entity = font_make_entity ();
6e34c9c1 419 ASET (entity, FONT_TYPE_INDEX, Qx);
6e34c9c1
KH
420 if (font_parse_xlfd (name, entity) < 0)
421 entity = Qnil;
422 }
423 XFree (name);
424 }
425 XFreeFont (display, xfont);
426 }
9c6d1df5 427 UNBLOCK_INPUT;
6e34c9c1 428
960d80b9 429 font_add_log ("xfont-match", spec, entity);
6e34c9c1
KH
430 return entity;
431}
432
c2f5bfd6
KH
433static Lisp_Object
434xfont_list_family (frame)
9df50a31 435 Lisp_Object frame;
c2f5bfd6
KH
436{
437 FRAME_PTR f = XFRAME (frame);
438 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
439 char **names;
440 int num_fonts, i;
441 Lisp_Object list;
442 char *last_family;
443 int last_len;
444
445 BLOCK_INPUT;
446 x_catch_errors (dpyinfo->display);
447 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
448 0x8000, &num_fonts);
449 if (x_had_errors_p (dpyinfo->display))
450 {
451 /* This error is perhaps due to insufficient memory on X server.
452 Let's just ignore it. */
453 x_clear_errors (dpyinfo->display);
454 num_fonts = 0;
455 }
456
457 list = Qnil;
458 for (i = 0, last_len = 0; i < num_fonts; i++)
459 {
460 char *p0 = names[i], *p1;
461 Lisp_Object family;
462
463 p0++; /* skip the leading '-' */
464 while (*p0 && *p0 != '-') p0++; /* skip foundry */
465 if (! *p0)
466 continue;
467 p1 = ++p0;
468 while (*p1 && *p1 != '-') p1++; /* find the end of family */
469 if (! *p1 || p1 == p0)
470 continue;
471 if (last_len == p1 - p0
472 && bcmp (last_family, p0, last_len) == 0)
473 continue;
474 last_len = p1 - p0;
475 last_family = p0;
29428bb8
KH
476 family = font_intern_prop (p0, last_len, 1);
477 if (NILP (assq_no_quit (family, list)))
c2f5bfd6
KH
478 list = Fcons (family, list);
479 }
480
481 XFreeFontNames (names);
482 x_uncatch_errors ();
483 UNBLOCK_INPUT;
484
485 return list;
486}
487
f0c55750
KH
488extern Lisp_Object QCavgwidth;
489
490static Lisp_Object
c2f5bfd6
KH
491xfont_open (f, entity, pixel_size)
492 FRAME_PTR f;
493 Lisp_Object entity;
494 int pixel_size;
495{
496 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
497 Display *display = dpyinfo->display;
498 char name[256];
499 int len;
500 unsigned long value;
501 Lisp_Object registry;
502 struct charset *encoding, *repertory;
f0c55750 503 Lisp_Object font_object, fullname;
c2f5bfd6
KH
504 struct font *font;
505 XFontStruct *xfont;
f0c55750 506 int i;
c2f5bfd6
KH
507
508 /* At first, check if we know how to encode characters for this
509 font. */
510 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 511 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
c8e0e16d
KH
512 {
513 font_add_log (" x:unknown registry", registry, Qnil);
514 return Qnil;
515 }
c2f5bfd6
KH
516
517 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
518 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
519 else if (pixel_size == 0)
520 {
521 if (FRAME_FONT (f))
522 pixel_size = FRAME_FONT (f)->pixel_size;
523 else
524 pixel_size = 14;
525 }
c2f5bfd6
KH
526 len = font_unparse_xlfd (entity, pixel_size, name, 256);
527 if (len <= 0)
c8e0e16d
KH
528 {
529 font_add_log (" x:unparse failed", entity, Qnil);
530 return Qnil;
531 }
c2f5bfd6
KH
532
533 BLOCK_INPUT;
534 x_catch_errors (display);
535 xfont = XLoadQueryFont (display, name);
536 if (x_had_errors_p (display))
537 {
538 /* This error is perhaps due to insufficient memory on X server.
539 Let's just ignore it. */
540 x_clear_errors (display);
541 xfont = NULL;
542 }
2f73901f
KH
543 else if (! xfont)
544 {
545 /* Some version of X lists:
546 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
547 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
548 but can open only:
549 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
550 and
551 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
552 So, we try again with wildcards in RESX and RESY. */
553 Lisp_Object temp;
554
555 temp = Fcopy_font_spec (entity);
556 ASET (temp, FONT_DPI_INDEX, Qnil);
557 len = font_unparse_xlfd (temp, pixel_size, name, 256);
558 if (len <= 0)
559 {
560 font_add_log (" x:unparse failed", temp, Qnil);
561 return Qnil;
562 }
563 xfont = XLoadQueryFont (display, name);
564 if (x_had_errors_p (display))
565 {
566 /* This error is perhaps due to insufficient memory on X server.
567 Let's just ignore it. */
568 x_clear_errors (display);
569 xfont = NULL;
570 }
571 }
f0c55750
KH
572 fullname = Qnil;
573 /* Try to get the full name of FONT. */
574 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
575 {
576 char *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 {
587 if (*p == '-')
588 dashes++;
589 p++;
590 }
591
592 if (dashes >= 13)
593 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
594 XFree (p0);
595 }
c2f5bfd6
KH
596 x_uncatch_errors ();
597 UNBLOCK_INPUT;
598
599 if (! xfont)
c8e0e16d
KH
600 {
601 font_add_log (" x:open failed", build_string (name), Qnil);
602 return Qnil;
603 }
f0c55750 604
947eecfb
KH
605 font_object = font_make_object (VECSIZE (struct xfont_info),
606 entity, pixel_size);
f0c55750
KH
607 ASET (font_object, FONT_TYPE_INDEX, Qx);
608 if (STRINGP (fullname))
960d80b9 609 font_parse_xlfd ((char *) SDATA (fullname), font_object);
f0c55750
KH
610 if (STRINGP (fullname))
611 ASET (font_object, FONT_NAME_INDEX, fullname);
612 else
613 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
614 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
615 ASET (font_object, FONT_FILE_INDEX, Qnil);
616 ASET (font_object, FONT_FORMAT_INDEX, Qx);
617 font = XFONT_OBJECT (font_object);
618 ((struct xfont_info *) font)->xfont = xfont;
619 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
620 font->pixel_size = pixel_size;
621 font->driver = &xfont_driver;
c2f5bfd6 622 font->encoding_charset = encoding->id;
1886668d 623 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
624 font->ascent = xfont->ascent;
625 font->descent = xfont->descent;
f0c55750
KH
626 font->height = font->ascent + font->descent;
627 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
628 if (xfont->min_bounds.width == xfont->max_bounds.width)
629 {
630 /* Fixed width font. */
f0c55750 631 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
632 }
633 else
634 {
c2f5bfd6 635 XCharStruct *pcm;
f0c55750
KH
636 XChar2b char2b;
637 Lisp_Object val;
c2f5bfd6
KH
638
639 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
640 pcm = xfont_get_pcm (xfont, &char2b);
641 if (pcm)
f0c55750 642 font->space_width = pcm->width;
c2f5bfd6 643 else
f0c55750
KH
644 font->space_width = 0;
645
646 val = Ffont_get (font_object, QCavgwidth);
647 if (INTEGERP (val))
648 font->average_width = XINT (val);
649 if (font->average_width < 0)
650 font->average_width = - font->average_width;
651 if (font->average_width == 0
652 && encoding->ascii_compatible_p)
c2f5bfd6 653 {
f0c55750 654 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 655
f0c55750
KH
656 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
657 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
658 width += pcm->width, n++;
4f64a164
KH
659 if (n > 0)
660 font->average_width = width / n;
c2f5bfd6 661 }
4f64a164
KH
662 if (font->average_width == 0)
663 /* No easy way other than this to get a reasonable
664 average_width. */
665 font->average_width
666 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
c2f5bfd6 667 }
c2f5bfd6 668
f0c55750
KH
669 BLOCK_INPUT;
670 font->underline_thickness
671 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
672 ? (long) value : 0);
673 font->underline_position
674 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
675 ? (long) value : -1);
676 font->baseline_offset
c2f5bfd6
KH
677 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
678 ? (long) value : 0);
f0c55750 679 font->relative_compose
c2f5bfd6
KH
680 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
681 ? (long) value : 0);
f0c55750 682 font->default_ascent
c2f5bfd6
KH
683 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
684 ? (long) value : 0);
c2f5bfd6
KH
685 UNBLOCK_INPUT;
686
f0c55750
KH
687 if (NILP (fullname))
688 fullname = AREF (font_object, FONT_NAME_INDEX);
634c4da0
KH
689 font->vertical_centering
690 = (STRINGP (Vvertical_centering_font_regexp)
691 && (fast_string_match_ignore_case
692 (Vvertical_centering_font_regexp, fullname) >= 0));
c2f5bfd6 693
f0c55750 694 return font_object;
c2f5bfd6
KH
695}
696
697static void
698xfont_close (f, font)
699 FRAME_PTR f;
700 struct font *font;
701{
702 BLOCK_INPUT;
f0c55750 703 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 704 UNBLOCK_INPUT;
c2f5bfd6
KH
705}
706
707static int
708xfont_prepare_face (f, face)
709 FRAME_PTR f;
710 struct face *face;
711{
712 BLOCK_INPUT;
f0c55750
KH
713 XSetFont (FRAME_X_DISPLAY (f), face->gc,
714 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
715 UNBLOCK_INPUT;
716
717 return 0;
718}
719
c2f5bfd6
KH
720static int
721xfont_has_char (entity, c)
722 Lisp_Object entity;
723 int c;
724{
725 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
726 struct charset *repertory;
727
a9822ae8 728 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
729 return -1;
730 if (! repertory)
731 return -1;
732 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
733}
734
735static unsigned
736xfont_encode_char (font, c)
737 struct font *font;
738 int c;
739{
f0c55750 740 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
741 struct charset *charset;
742 unsigned code;
743 XChar2b char2b;
744
745 charset = CHARSET_FROM_ID (font->encoding_charset);
746 code = ENCODE_CHAR (charset, c);
747 if (code == CHARSET_INVALID_CODE (charset))
21138cff 748 return FONT_INVALID_CODE;
1886668d 749 if (font->repertory_charset >= 0)
c2f5bfd6 750 {
1886668d 751 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 752 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 753 ? code : FONT_INVALID_CODE);
c2f5bfd6 754 }
88649c62
KH
755 char2b.byte1 = code >> 8;
756 char2b.byte2 = code & 0xFF;
f0c55750 757 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
758}
759
760static int
761xfont_text_extents (font, code, nglyphs, metrics)
762 struct font *font;
763 unsigned *code;
764 int nglyphs;
765 struct font_metrics *metrics;
766{
f0c55750 767 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6 768 int width = 0;
41fa3e2c 769 int i, first, x;
c2f5bfd6
KH
770
771 if (metrics)
772 bzero (metrics, sizeof (struct font_metrics));
41fa3e2c 773 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
c2f5bfd6
KH
774 {
775 XChar2b char2b;
776 static XCharStruct *pcm;
777
778 if (code[i] >= 0x10000)
779 continue;
780 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 781 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
782 if (! pcm)
783 continue;
41fa3e2c
KH
784 if (first)
785 {
786 if (metrics)
787 {
788 metrics->lbearing = pcm->lbearing;
789 metrics->rbearing = pcm->rbearing;
790 metrics->ascent = pcm->ascent;
791 metrics->descent = pcm->descent;
792 }
793 first = 0;
794 }
795 else
796 {
797 if (metrics)
798 {
799 if (metrics->lbearing > width + pcm->lbearing)
800 metrics->lbearing = width + pcm->lbearing;
801 if (metrics->rbearing < width + pcm->rbearing)
802 metrics->rbearing = width + pcm->rbearing;
803 if (metrics->ascent < pcm->ascent)
804 metrics->ascent = pcm->ascent;
805 if (metrics->descent < pcm->descent)
806 metrics->descent = pcm->descent;
807 }
808 }
c2f5bfd6
KH
809 width += pcm->width;
810 }
811 if (metrics)
812 metrics->width = width;
813 return width;
814}
815
816static int
817xfont_draw (s, from, to, x, y, with_background)
818 struct glyph_string *s;
819 int from, to, x, y, with_background;
820{
f0c55750 821 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 822 int len = to - from;
6e34c9c1 823 GC gc = s->gc;
298fd5b1 824 int i;
6e34c9c1 825
f0c55750 826 if (s->gc != s->face->gc)
6e34c9c1 827 {
d45fefc7 828 BLOCK_INPUT;
f0c55750 829 XSetFont (s->display, gc, xfont->fid);
d45fefc7 830 UNBLOCK_INPUT;
6e34c9c1 831 }
c2f5bfd6
KH
832
833 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
834 {
835 char *str;
c2f5bfd6
KH
836 USE_SAFE_ALLOCA;
837
838 SAFE_ALLOCA (str, char *, len);
839 for (i = 0; i < len ; i++)
840 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 841 BLOCK_INPUT;
c2f5bfd6 842 if (with_background > 0)
298fd5b1
KH
843 {
844 if (s->padding_p)
845 for (i = 0; i < len; i++)
846 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
847 gc, x + i, y, str + i, 1);
848 else
849 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
850 gc, x, y, str, len);
851 }
c2f5bfd6 852 else
298fd5b1
KH
853 {
854 if (s->padding_p)
855 for (i = 0; i < len; i++)
856 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
857 gc, x + i, y, str + i, 1);
858 else
859 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
860 gc, x, y, str, len);
861 }
d45fefc7 862 UNBLOCK_INPUT;
c2f5bfd6
KH
863 SAFE_FREE ();
864 return s->nchars;
865 }
866
d45fefc7 867 BLOCK_INPUT;
c2f5bfd6 868 if (with_background > 0)
298fd5b1
KH
869 {
870 if (s->padding_p)
871 for (i = 0; i < len; i++)
872 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
873 gc, x + i, y, s->char2b + from + i, 1);
874 else
875 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
876 gc, x, y, s->char2b + from, len);
877 }
c2f5bfd6 878 else
298fd5b1
KH
879 {
880 if (s->padding_p)
881 for (i = 0; i < len; i++)
882 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
883 gc, x + i, y, s->char2b + from + i, 1);
884 else
885 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
886 gc, x, y, s->char2b + from, len);
887 }
d45fefc7 888 UNBLOCK_INPUT;
c2f5bfd6
KH
889
890 return len;
891}
892
f0c55750
KH
893static int
894xfont_check (f, font)
895 FRAME_PTR f;
896 struct font *font;
897{
898 struct xfont_info *xfont = (struct xfont_info *) font;
899
900 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
901}
902
c2f5bfd6
KH
903\f
904void
905syms_of_xfont ()
906{
c2f5bfd6
KH
907 xfont_driver.type = Qx;
908 register_font_driver (&xfont_driver, NULL);
909}
885b7d09
MB
910
911/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
912 (do not change this comment) */