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