(ftxfont_match): New function.
[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
KH
241static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
242static Lisp_Object xfont_list_family P_ ((Lisp_Object));
243static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
244static void xfont_close P_ ((FRAME_PTR, struct font *));
245static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
246#if 0
247static void xfont_done_face P_ ((FRAME_PTR, struct face *));
248#endif
249static int xfont_has_char P_ ((Lisp_Object, int));
250static unsigned xfont_encode_char P_ ((struct font *, int));
251static int xfont_text_extents P_ ((struct font *, unsigned *, int,
252 struct font_metrics *));
253static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
254
255struct font_driver xfont_driver =
256 {
257 (Lisp_Object) NULL, /* Qx */
258 xfont_get_cache,
c2f5bfd6
KH
259 xfont_list,
260 xfont_list_family,
261 NULL,
262 xfont_open,
263 xfont_close,
264 xfont_prepare_face,
265 NULL /*xfont_done_face*/,
266 xfont_has_char,
267 xfont_encode_char,
268 xfont_text_extents,
269 xfont_draw,
270 };
271
272extern Lisp_Object QCname;
273
274static Lisp_Object
275xfont_get_cache (frame)
276 Lisp_Object frame;
277{
278 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame));
279
280 return (dpyinfo->name_list_element);
281}
282
c2f5bfd6
KH
283extern Lisp_Object Vface_alternative_font_registry_alist;
284
285static Lisp_Object
6c4aeab6
KH
286xfont_list_pattern (frame, display, pattern)
287 Lisp_Object frame;
288 Display *display;
289 char *pattern;
c2f5bfd6 290{
6c4aeab6
KH
291 Lisp_Object list = Qnil;
292 int i, limit, num_fonts;
293 char **names;
c2f5bfd6
KH
294
295 BLOCK_INPUT;
6c4aeab6 296 x_catch_errors (display);
c2f5bfd6 297
6c4aeab6 298 for (limit = 512; ; limit *= 2)
c2f5bfd6 299 {
6c4aeab6
KH
300 names = XListFonts (display, pattern, limit, &num_fonts);
301 if (x_had_errors_p (display))
c2f5bfd6
KH
302 {
303 /* This error is perhaps due to insufficient memory on X
304 server. Let's just ignore it. */
6c4aeab6
KH
305 x_clear_errors (display);
306 num_fonts = 0;
307 break;
c2f5bfd6 308 }
6c4aeab6
KH
309 if (num_fonts < limit)
310 break;
311 XFreeFontNames (names);
312 }
313
314 for (i = 0; i < num_fonts; i++)
315 {
316 Lisp_Object entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
317 int result;
318
319 ASET (entity, FONT_TYPE_INDEX, Qx);
320 ASET (entity, FONT_FRAME_INDEX, frame);
321
322 result = font_parse_xlfd (names[i], entity);
323 if (result < 0)
c2f5bfd6 324 {
6c4aeab6
KH
325 /* This may be an alias name. Try to get the full XLFD name
326 from XA_FONT property of the font. */
327 XFontStruct *font = XLoadQueryFont (display, names[i]);
328 unsigned long value;
329
330 if (! font)
331 continue;
c2f5bfd6
KH
332 if (XGetFontProperty (font, XA_FONT, &value))
333 {
6c4aeab6
KH
334 char *name = (char *) XGetAtomName (display, (Atom) value);
335 int len = strlen (name);
c2f5bfd6
KH
336
337 /* If DXPC (a Differential X Protocol Compressor)
338 Ver.3.7 is running, XGetAtomName will return null
339 string. We must avoid such a name. */
340 if (len > 0)
6c4aeab6
KH
341 result = font_parse_xlfd (name, entity);
342 XFree (name);
c2f5bfd6 343 }
6c4aeab6 344 XFreeFont (display, font);
c2f5bfd6 345 }
6c4aeab6
KH
346
347 if (result == 0)
c2f5bfd6 348 {
6c4aeab6
KH
349 Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX);
350 char *p = (char *) SDATA (SYMBOL_NAME (val));
351
352 /* P == "RESX-RESY-SPACING-AVGWIDTH. We rejust this font if
353 it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0). */
354 if (atoi (p) > 0)
c2f5bfd6 355 {
6c4aeab6
KH
356 p += SBYTES (SYMBOL_NAME (val));
357 while (p[-1] != '-') p--;
358 if (atoi (p) == 0)
359 continue;
c2f5bfd6 360 }
6c4aeab6 361 list = Fcons (entity, list);
c2f5bfd6
KH
362 }
363 }
364
365 x_uncatch_errors ();
366 UNBLOCK_INPUT;
367
6c4aeab6
KH
368 return list;
369}
c2f5bfd6 370
6c4aeab6
KH
371static Lisp_Object
372xfont_list (frame, spec)
373 Lisp_Object frame, spec;
374{
375 FRAME_PTR f = XFRAME (frame);
376 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
377 Lisp_Object list, val, extra, font_name;
378 int len;
379 char name[256];
380
381 extra = AREF (spec, FONT_EXTRA_INDEX);
382 font_name = Qnil;
383 if (CONSP (extra))
c2f5bfd6 384 {
6c4aeab6
KH
385 val = assq_no_quit (QCotf, extra);
386 if (! NILP (val))
387 return null_vector;
388 val = assq_no_quit (QCscript, extra);
389 if (! NILP (val))
390 return null_vector;
391 val = assq_no_quit (QClanguage, extra);
392 if (! NILP (val))
393 return null_vector;
394 val = assq_no_quit (QCname, extra);
395 if (CONSP (val))
396 font_name = XCDR (val);
c2f5bfd6 397 }
6c4aeab6 398
1f221e7a
KH
399 if (STRINGP (font_name)
400 && ! strchr ((char *) SDATA (font_name), ':'))
6c4aeab6
KH
401 list = xfont_list_pattern (frame, display, (char *) SDATA (font_name));
402 else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0)
403 return null_vector;
404 else
c2f5bfd6 405 {
6c4aeab6
KH
406 list = xfont_list_pattern (frame, display, name);
407 if (NILP (list))
408 {
409 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
410 Lisp_Object alter;
411
412 if (! NILP (registry)
413 && (alter = Fassoc (SYMBOL_NAME (registry),
414 Vface_alternative_font_registry_alist))
415 && CONSP (alter))
416 {
417 /* Pointer to REGISTRY-ENCODING field. */
418 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
419
420 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
421 if (STRINGP (XCAR (alter))
422 && ((r - name) + SBYTES (XCAR (alter))) < 255)
423 {
424 strcpy (r, (char *) SDATA (XCAR (alter)));
425 list = xfont_list_pattern (frame, display, name);
426 if (! NILP (list))
427 break;
428 }
429 }
430 }
c2f5bfd6 431 }
c2f5bfd6 432
6c4aeab6 433 return (NILP (list) ? null_vector : Fvconcat (1, &list));
c2f5bfd6
KH
434}
435
436static int
437memq_no_quit (elt, list)
438 Lisp_Object elt, list;
439{
440 while (CONSP (list) && ! EQ (XCAR (list), elt))
441 list = XCDR (list);
442 return (CONSP (list));
443}
444
445static Lisp_Object
446xfont_list_family (frame)
9df50a31 447 Lisp_Object frame;
c2f5bfd6
KH
448{
449 FRAME_PTR f = XFRAME (frame);
450 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
451 char **names;
452 int num_fonts, i;
453 Lisp_Object list;
454 char *last_family;
455 int last_len;
456
457 BLOCK_INPUT;
458 x_catch_errors (dpyinfo->display);
459 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
460 0x8000, &num_fonts);
461 if (x_had_errors_p (dpyinfo->display))
462 {
463 /* This error is perhaps due to insufficient memory on X server.
464 Let's just ignore it. */
465 x_clear_errors (dpyinfo->display);
466 num_fonts = 0;
467 }
468
469 list = Qnil;
470 for (i = 0, last_len = 0; i < num_fonts; i++)
471 {
472 char *p0 = names[i], *p1;
473 Lisp_Object family;
474
475 p0++; /* skip the leading '-' */
476 while (*p0 && *p0 != '-') p0++; /* skip foundry */
477 if (! *p0)
478 continue;
479 p1 = ++p0;
480 while (*p1 && *p1 != '-') p1++; /* find the end of family */
481 if (! *p1 || p1 == p0)
482 continue;
483 if (last_len == p1 - p0
484 && bcmp (last_family, p0, last_len) == 0)
485 continue;
486 last_len = p1 - p0;
487 last_family = p0;
488 family = intern_downcase (p0, last_len);
489 if (! memq_no_quit (family, list))
490 list = Fcons (family, list);
491 }
492
493 XFreeFontNames (names);
494 x_uncatch_errors ();
495 UNBLOCK_INPUT;
496
497 return list;
498}
499
500static struct font *
501xfont_open (f, entity, pixel_size)
502 FRAME_PTR f;
503 Lisp_Object entity;
504 int pixel_size;
505{
506 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
507 Display *display = dpyinfo->display;
508 char name[256];
509 int len;
510 unsigned long value;
511 Lisp_Object registry;
512 struct charset *encoding, *repertory;
513 struct font *font;
514 XFontStruct *xfont;
515
516 /* At first, check if we know how to encode characters for this
517 font. */
518 registry = AREF (entity, FONT_REGISTRY_INDEX);
519 if (xfont_registry_charsets (registry, &encoding, &repertory) < 0)
520 return NULL;
521
522 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
523 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
524 len = font_unparse_xlfd (entity, pixel_size, name, 256);
525 if (len <= 0)
526 return NULL;
527
528 BLOCK_INPUT;
529 x_catch_errors (display);
530 xfont = XLoadQueryFont (display, name);
531 if (x_had_errors_p (display))
532 {
533 /* This error is perhaps due to insufficient memory on X server.
534 Let's just ignore it. */
535 x_clear_errors (display);
536 xfont = NULL;
537 }
538 x_uncatch_errors ();
539 UNBLOCK_INPUT;
540
541 if (! xfont)
542 return NULL;
543 font = malloc (sizeof (struct font));
544 font->font.font = xfont;
545 font->entity = entity;
546 font->pixel_size = pixel_size;
547 font->driver = &xfont_driver;
548 font->font.name = malloc (len + 1);
549 if (! font->font.name)
550 {
551 XFreeFont (display, xfont);
552 free (font);
553 return NULL;
554 }
555 bcopy (name, font->font.name, len + 1);
556 font->font.charset = encoding->id;
557 font->encoding_charset = encoding->id;
1886668d 558 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
559 font->ascent = xfont->ascent;
560 font->descent = xfont->descent;
561
562 if (xfont->min_bounds.width == xfont->max_bounds.width)
563 {
564 /* Fixed width font. */
565 font->font.average_width = font->font.space_width
566 = xfont->min_bounds.width;
567 }
568 else
569 {
570 XChar2b char2b;
571 XCharStruct *pcm;
572
573 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
574 pcm = xfont_get_pcm (xfont, &char2b);
575 if (pcm)
576 font->font.space_width = pcm->width;
577 else
578 font->font.space_width = xfont->max_bounds.width;
579
580 font->font.average_width
581 = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
582 ? (long) value / 10 : 0);
583 if (font->font.average_width < 0)
584 font->font.average_width = - font->font.average_width;
585 if (font->font.average_width == 0)
586 {
587 if (pcm)
588 {
589 int width = pcm->width;
590 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
591 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
592 width += pcm->width;
593 font->font.average_width = width / 95;
594 }
595 else
596 font->font.average_width = xfont->max_bounds.width;
597 }
598 }
599 font->min_width = xfont->min_bounds.width;
600 if (font->min_width <= 0)
601 font->min_width = font->font.space_width;
602
603 BLOCK_INPUT;
604 /* Try to get the full name of FONT. Put it in FULL_NAME. */
605 if (XGetFontProperty (xfont, XA_FONT, &value))
606 {
607 char *full_name = NULL, *p0, *p;
608 int dashes = 0;
609
610 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
611 /* Count the number of dashes in the "full name".
612 If it is too few, this isn't really the font's full name,
613 so don't use it.
614 In X11R4, the fonts did not come with their canonical names
615 stored in them. */
616 while (*p)
617 {
618 if (*p == '-')
619 dashes++;
620 p++;
621 }
622
623 if (dashes >= 13)
624 {
625 full_name = (char *) malloc (p - p0 + 1);
626 if (full_name)
627 bcopy (p0, full_name, p - p0 + 1);
628 }
629 XFree (p0);
630
631 if (full_name)
632 font->font.full_name = full_name;
633 else
634 font->font.full_name = font->font.name;
635 }
636 font->file_name = NULL;
637
638 font->font.size = xfont->max_bounds.width;
639 font->font.height = xfont->ascent + xfont->descent;
640 font->font.baseline_offset
641 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
642 ? (long) value : 0);
643 font->font.relative_compose
644 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
645 ? (long) value : 0);
646 font->font.default_ascent
647 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
648 ? (long) value : 0);
649 font->font.vertical_centering
650 = (STRINGP (Vvertical_centering_font_regexp)
651 && (fast_c_string_match_ignore_case
652 (Vvertical_centering_font_regexp, font->font.full_name) >= 0));
653
654 UNBLOCK_INPUT;
655
656 dpyinfo->n_fonts++;
657
658 /* Set global flag fonts_changed_p to non-zero if the font loaded
659 has a character with a smaller width than any other character
660 before, or if the font loaded has a smaller height than any other
661 font loaded before. If this happens, it will make a glyph matrix
662 reallocation necessary. */
663 if (dpyinfo->n_fonts == 1)
664 {
665 dpyinfo->smallest_font_height = font->font.height;
666 dpyinfo->smallest_char_width = font->min_width;
667 fonts_changed_p = 1;
668 }
669 else
670 {
671 if (dpyinfo->smallest_font_height > font->font.height)
672 dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1;
673 if (dpyinfo->smallest_char_width > font->min_width)
674 dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1;
675 }
676
677 return font;
678}
679
680static void
681xfont_close (f, font)
682 FRAME_PTR f;
683 struct font *font;
684{
685 BLOCK_INPUT;
686 XFreeFont (FRAME_X_DISPLAY (f), font->font.font);
687 UNBLOCK_INPUT;
688
689 if (font->font.name != font->font.full_name)
690 free (font->font.full_name);
691 free (font->font.name);
692 free (font);
693 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
694}
695
696static int
697xfont_prepare_face (f, face)
698 FRAME_PTR f;
699 struct face *face;
700{
701 BLOCK_INPUT;
702 XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid);
703 UNBLOCK_INPUT;
704
705 return 0;
706}
707
708#if 0
709static void
710xfont_done_face (f, face)
711 FRAME_PTR f;
712 struct face *face;
713{
714 if (face->extra)
715 {
716 BLOCK_INPUT;
717 XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra);
718 UNBLOCK_INPUT;
719 face->extra = NULL;
720 }
721}
722#endif /* 0 */
723
724static int
725xfont_has_char (entity, c)
726 Lisp_Object entity;
727 int c;
728{
729 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
730 struct charset *repertory;
731
732 if (xfont_registry_charsets (registry, NULL, &repertory) < 0)
733 return -1;
734 if (! repertory)
735 return -1;
736 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
737}
738
739static unsigned
740xfont_encode_char (font, c)
741 struct font *font;
742 int c;
743{
744 struct charset *charset;
745 unsigned code;
746 XChar2b char2b;
747
748 charset = CHARSET_FROM_ID (font->encoding_charset);
749 code = ENCODE_CHAR (charset, c);
750 if (code == CHARSET_INVALID_CODE (charset))
751 return 0xFFFFFFFF;
1886668d 752 if (font->repertory_charset >= 0)
c2f5bfd6 753 {
1886668d 754 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6
KH
755 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
756 ? code : 0xFFFFFFFF);
757 }
88649c62
KH
758 char2b.byte1 = code >> 8;
759 char2b.byte2 = code & 0xFF;
c2f5bfd6
KH
760 return (xfont_get_pcm (font->font.font, &char2b) ? code : 0xFFFFFFFF);
761}
762
763static int
764xfont_text_extents (font, code, nglyphs, metrics)
765 struct font *font;
766 unsigned *code;
767 int nglyphs;
768 struct font_metrics *metrics;
769{
770 int width = 0;
771 int i, x;
772
773 if (metrics)
774 bzero (metrics, sizeof (struct font_metrics));
775 for (i = 0, x = 0; i < nglyphs; i++)
776 {
777 XChar2b char2b;
778 static XCharStruct *pcm;
779
780 if (code[i] >= 0x10000)
781 continue;
782 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
783 pcm = xfont_get_pcm (font->font.font, &char2b);
784 if (! pcm)
785 continue;
786 if (metrics->lbearing > width + pcm->lbearing)
787 metrics->lbearing = width + pcm->lbearing;
788 if (metrics->rbearing < width + pcm->rbearing)
789 metrics->rbearing = width + pcm->rbearing;
790 if (metrics->ascent < pcm->ascent)
791 metrics->ascent = pcm->ascent;
792 if (metrics->descent < pcm->descent)
793 metrics->descent = pcm->descent;
794 width += pcm->width;
795 }
796 if (metrics)
797 metrics->width = width;
798 return width;
799}
800
801static int
802xfont_draw (s, from, to, x, y, with_background)
803 struct glyph_string *s;
804 int from, to, x, y, with_background;
805{
806 XFontStruct *xfont = s->face->font;
807 int len = to - from;
808
809 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
810 {
811 char *str;
812 int i;
813 USE_SAFE_ALLOCA;
814
815 SAFE_ALLOCA (str, char *, len);
816 for (i = 0; i < len ; i++)
817 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
818 if (with_background > 0)
819 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
820 s->gc, x, y, str, len);
821 else
822 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
823 s->gc, x, y, str, len);
824 SAFE_FREE ();
825 return s->nchars;
826 }
827
828 if (with_background > 0)
829 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
830 s->gc, x, y, s->char2b + from, len);
831 else
832 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
833 s->gc, x, y, s->char2b + from, len);
834
835 return len;
836}
837
838
839\f
840void
841syms_of_xfont ()
842{
843 staticpro (&x_font_charset_alist);
844 x_font_charset_alist = Qnil;
845
846 DEFSYM (Qx, "x");
847 xfont_driver.type = Qx;
848 register_font_driver (&xfont_driver, NULL);
849}
885b7d09
MB
850
851/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
852 (do not change this comment) */