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