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