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