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