]> code.delx.au - gnu-emacs/blob - src/xfont.c
9e23b0abdfc84af81222fbc4ad84b8c7a285e191
[gnu-emacs] / src / xfont.c
1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
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 3 of the License, or
12 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <X11/Xlib.h>
26
27 #include "lisp.h"
28 #include "dispextern.h"
29 #include "xterm.h"
30 #include "frame.h"
31 #include "blockinput.h"
32 #include "character.h"
33 #include "charset.h"
34 #include "fontset.h"
35 #include "font.h"
36 #include "ccl.h"
37
38 \f
39 /* X core font driver. */
40
41 struct xfont_info
42 {
43 struct font font;
44 Display *display;
45 XFontStruct *xfont;
46 };
47
48 /* Prototypes of support functions. */
49 extern void x_clear_errors P_ ((Display *));
50
51 static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
52 static void xfont_find_ccl_program P_ ((struct font *));
53
54 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
55 is not contained in the font. */
56
57 static XCharStruct *
58 xfont_get_pcm (xfont, char2b)
59 XFontStruct *xfont;
60 XChar2b *char2b;
61 {
62 /* The result metric information. */
63 XCharStruct *pcm = NULL;
64
65 font_assert (xfont && char2b);
66
67 if (xfont->per_char != NULL)
68 {
69 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
70 {
71 /* min_char_or_byte2 specifies the linear character index
72 corresponding to the first element of the per_char array,
73 max_char_or_byte2 is the index of the last character. A
74 character with non-zero CHAR2B->byte1 is not in the font.
75 A character with byte2 less than min_char_or_byte2 or
76 greater max_char_or_byte2 is not in the font. */
77 if (char2b->byte1 == 0
78 && char2b->byte2 >= xfont->min_char_or_byte2
79 && char2b->byte2 <= xfont->max_char_or_byte2)
80 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
81 }
82 else
83 {
84 /* If either min_byte1 or max_byte1 are nonzero, both
85 min_char_or_byte2 and max_char_or_byte2 are less than
86 256, and the 2-byte character index values corresponding
87 to the per_char array element N (counting from 0) are:
88
89 byte1 = N/D + min_byte1
90 byte2 = N\D + min_char_or_byte2
91
92 where:
93
94 D = max_char_or_byte2 - min_char_or_byte2 + 1
95 / = integer division
96 \ = integer modulus */
97 if (char2b->byte1 >= xfont->min_byte1
98 && char2b->byte1 <= xfont->max_byte1
99 && char2b->byte2 >= xfont->min_char_or_byte2
100 && char2b->byte2 <= xfont->max_char_or_byte2)
101 pcm = (xfont->per_char
102 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
103 * (char2b->byte1 - xfont->min_byte1))
104 + (char2b->byte2 - xfont->min_char_or_byte2));
105 }
106 }
107 else
108 {
109 /* If the per_char pointer is null, all glyphs between the first
110 and last character indexes inclusive have the same
111 information, as given by both min_bounds and max_bounds. */
112 if (char2b->byte2 >= xfont->min_char_or_byte2
113 && char2b->byte2 <= xfont->max_char_or_byte2)
114 pcm = &xfont->max_bounds;
115 }
116
117 return ((pcm == NULL
118 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
119 ? NULL : pcm);
120 }
121
122 /* Find a CCL program for a font specified by FONTP, and set the member
123 `encoder' of the structure. */
124
125 static void
126 xfont_find_ccl_program (font)
127 struct font *font;
128 {
129 Lisp_Object list, elt;
130
131 elt = Qnil;
132 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
133 {
134 elt = XCAR (list);
135 if (CONSP (elt)
136 && STRINGP (XCAR (elt))
137 && ((fast_string_match_ignore_case (XCAR (elt),
138 font->props[FONT_NAME_INDEX])
139 >= 0)
140 || (fast_string_match_ignore_case (XCAR (elt),
141 font->props[FONT_FULLNAME_INDEX])
142 >= 0)))
143 break;
144 }
145
146 if (! NILP (list))
147 {
148 struct ccl_program *ccl
149 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
150
151 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
152 xfree (ccl);
153 else
154 font->font_encoder = ccl;
155 }
156 }
157
158 static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
159 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
160 static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
161 static Lisp_Object xfont_list_family P_ ((Lisp_Object));
162 static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
163 static void xfont_close P_ ((FRAME_PTR, struct font *));
164 static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
165 static int xfont_has_char P_ ((Lisp_Object, int));
166 static unsigned xfont_encode_char P_ ((struct font *, int));
167 static int xfont_text_extents P_ ((struct font *, unsigned *, int,
168 struct font_metrics *));
169 static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
170 static int xfont_check P_ ((FRAME_PTR, struct font *));
171
172 struct font_driver xfont_driver =
173 {
174 0, /* Qx */
175 0, /* case insensitive */
176 xfont_get_cache,
177 xfont_list,
178 xfont_match,
179 xfont_list_family,
180 NULL,
181 xfont_open,
182 xfont_close,
183 xfont_prepare_face,
184 NULL,
185 xfont_has_char,
186 xfont_encode_char,
187 xfont_text_extents,
188 xfont_draw,
189 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
190 xfont_check
191 };
192
193 extern Lisp_Object QCname;
194
195 static Lisp_Object
196 xfont_get_cache (f)
197 FRAME_PTR f;
198 {
199 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
200
201 return (dpyinfo->name_list_element);
202 }
203
204 extern Lisp_Object Vface_alternative_font_registry_alist;
205
206 static int
207 compare_font_names (const void *name1, const void *name2)
208 {
209 return xstrcasecmp (*(const unsigned char **) name1,
210 *(const unsigned char **) name2);
211 }
212
213 /* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
214 of the decoding result. LEN is the byte length of XLFD, or -1 if
215 XLFD is NULL terminated. The caller must assure that OUTPUT is at
216 least twice (plus 1) as large as XLFD. */
217
218 static int
219 xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
220 {
221 char *p0 = xlfd, *p1 = output;
222 int c;
223
224 while (*p0)
225 {
226 c = *(unsigned char *) p0++;
227 p1 += CHAR_STRING (c, p1);
228 if (--len == 0)
229 break;
230 }
231 *p1 = 0;
232 return (p1 - output);
233 }
234
235 /* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
236 resulting byte length. If XLFD contains unencodable character,
237 return -1. */
238
239 static int
240 xfont_encode_coding_xlfd (char *xlfd)
241 {
242 const unsigned char *p0 = (unsigned char *) xlfd;
243 unsigned char *p1 = (unsigned char *) xlfd;
244 int len = 0;
245
246 while (*p0)
247 {
248 int c = STRING_CHAR_ADVANCE (p0);
249
250 if (c >= 0x100)
251 return -1;
252 *p1++ = c;
253 len++;
254 }
255 *p1 = 0;
256 return len;
257 }
258
259 static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
260
261 static Lisp_Object
262 xfont_list_pattern (frame, display, pattern)
263 Lisp_Object frame;
264 Display *display;
265 char *pattern;
266 {
267 Lisp_Object list = Qnil;
268 int i, limit, num_fonts;
269 char **names;
270 /* Large enough to decode the longest XLFD (255 bytes). */
271 char buf[512];
272
273 BLOCK_INPUT;
274 x_catch_errors (display);
275
276 for (limit = 512; ; limit *= 2)
277 {
278 names = XListFonts (display, pattern, limit, &num_fonts);
279 if (x_had_errors_p (display))
280 {
281 /* This error is perhaps due to insufficient memory on X
282 server. Let's just ignore it. */
283 x_clear_errors (display);
284 num_fonts = 0;
285 break;
286 }
287 if (num_fonts < limit)
288 break;
289 XFreeFontNames (names);
290 }
291
292 if (num_fonts > 0)
293 {
294 char **indices = alloca (sizeof (char *) * num_fonts);
295
296 for (i = 0; i < num_fonts; i++)
297 indices[i] = names[i];
298 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
299
300 for (i = 0; i < num_fonts; i++)
301 {
302 Lisp_Object entity;
303 int result;
304 char *p;
305
306 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
307 continue;
308
309 entity = font_make_entity ();
310 ASET (entity, FONT_TYPE_INDEX, Qx);
311 xfont_decode_coding_xlfd (indices[i], -1, buf);
312 result = font_parse_xlfd (buf, entity);
313 if (result < 0)
314 {
315 /* This may be an alias name. Try to get the full XLFD name
316 from XA_FONT property of the font. */
317 XFontStruct *font = XLoadQueryFont (display, indices[i]);
318 unsigned long value;
319
320 if (! font)
321 continue;
322 if (XGetFontProperty (font, XA_FONT, &value))
323 {
324 char *name = (char *) XGetAtomName (display, (Atom) value);
325 int len = strlen (name);
326
327 /* If DXPC (a Differential X Protocol Compressor)
328 Ver.3.7 is running, XGetAtomName will return null
329 string. We must avoid such a name. */
330 if (len > 0)
331 {
332 xfont_decode_coding_xlfd (indices[i], -1, buf);
333 result = font_parse_xlfd (buf, entity);
334 }
335 XFree (name);
336 }
337 XFreeFont (display, font);
338 }
339
340 if (result == 0
341 /* Avoid auto-scaled fonts. */
342 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
343 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
344 list = Fcons (entity, list);
345 }
346 XFreeFontNames (names);
347 }
348
349 x_uncatch_errors ();
350 UNBLOCK_INPUT;
351
352 font_add_log ("xfont-list", build_string (pattern), list);
353 return list;
354 }
355
356 static Lisp_Object
357 xfont_list (frame, spec)
358 Lisp_Object frame, spec;
359 {
360 FRAME_PTR f = XFRAME (frame);
361 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
362 Lisp_Object registry, list, val, extra;
363 int len;
364 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
365 char name[512];
366
367 extra = AREF (spec, FONT_EXTRA_INDEX);
368 if (CONSP (extra))
369 {
370 val = assq_no_quit (QCotf, extra);
371 if (! NILP (val))
372 return Qnil;
373 val = assq_no_quit (QCscript, extra);
374 if (! NILP (val))
375 return Qnil;
376 val = assq_no_quit (QClang, extra);
377 if (! NILP (val))
378 return Qnil;
379 }
380
381 registry = AREF (spec, FONT_REGISTRY_INDEX);
382 len = font_unparse_xlfd (spec, 0, name, 512);
383 if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
384 return Qnil;
385 ASET (spec, FONT_REGISTRY_INDEX, registry);
386 list = xfont_list_pattern (frame, display, name);
387 if (NILP (list) && NILP (registry))
388 {
389 /* Try iso10646-1 */
390 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
391
392 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
393 {
394 strcpy (r, "iso10646-1");
395 list = xfont_list_pattern (frame, display, name);
396 }
397 }
398 if (NILP (list) && ! NILP (registry))
399 {
400 /* Try alternate registries. */
401 Lisp_Object alter;
402
403 if ((alter = Fassoc (SYMBOL_NAME (registry),
404 Vface_alternative_font_registry_alist),
405 CONSP (alter)))
406 {
407 /* Pointer to REGISTRY-ENCODING field. */
408 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
409
410 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
411 if (STRINGP (XCAR (alter))
412 && ((r - name) + SBYTES (XCAR (alter))) < 256)
413 {
414 strcpy (r, (char *) SDATA (XCAR (alter)));
415 list = xfont_list_pattern (frame, display, name);
416 if (! NILP (list))
417 break;
418 }
419 }
420 }
421 if (NILP (list))
422 {
423 /* Try alias. */
424 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
425 if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
426 {
427 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
428 if (xfont_encode_coding_xlfd (name) < 0)
429 return Qnil;
430 list = xfont_list_pattern (frame, display, name);
431 }
432 }
433
434 return list;
435 }
436
437 static Lisp_Object
438 xfont_match (frame, spec)
439 Lisp_Object frame, spec;
440 {
441 FRAME_PTR f = XFRAME (frame);
442 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
443 Lisp_Object extra, val, entity;
444 char name[512];
445 XFontStruct *xfont;
446 unsigned long value;
447
448 extra = AREF (spec, FONT_EXTRA_INDEX);
449 val = assq_no_quit (QCname, extra);
450 if (! CONSP (val) || ! STRINGP (XCDR (val)))
451 {
452 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
453 return Qnil;
454 }
455 else if (SBYTES (XCDR (val)) < 512)
456 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
457 else
458 return Qnil;
459 if (xfont_encode_coding_xlfd (name) < 0)
460 return Qnil;
461
462 BLOCK_INPUT;
463 entity = Qnil;
464 xfont = XLoadQueryFont (display, name);
465 if (xfont)
466 {
467 if (XGetFontProperty (xfont, XA_FONT, &value))
468 {
469 int len;
470 char *s;
471
472 s = (char *) XGetAtomName (display, (Atom) value);
473 len = strlen (s);
474
475 /* If DXPC (a Differential X Protocol Compressor)
476 Ver.3.7 is running, XGetAtomName will return null
477 string. We must avoid such a name. */
478 if (len > 0)
479 {
480 entity = font_make_entity ();
481 ASET (entity, FONT_TYPE_INDEX, Qx);
482 xfont_decode_coding_xlfd (s, -1, name);
483 if (font_parse_xlfd (name, entity) < 0)
484 entity = Qnil;
485 }
486 XFree (s);
487 }
488 XFreeFont (display, xfont);
489 }
490 UNBLOCK_INPUT;
491
492 font_add_log ("xfont-match", spec, entity);
493 return entity;
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, buf[512];
524 Lisp_Object family;
525 int decoded_len;
526
527 p0++; /* skip the leading '-' */
528 while (*p0 && *p0 != '-') p0++; /* skip foundry */
529 if (! *p0)
530 continue;
531 p1 = ++p0;
532 while (*p1 && *p1 != '-') p1++; /* find the end of family */
533 if (! *p1 || p1 == p0)
534 continue;
535 if (last_len == p1 - p0
536 && bcmp (last_family, p0, last_len) == 0)
537 continue;
538 last_len = p1 - p0;
539 last_family = p0;
540
541 decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
542 family = font_intern_prop (p0, decoded_len, 1);
543 if (NILP (assq_no_quit (family, list)))
544 list = Fcons (family, list);
545 }
546
547 XFreeFontNames (names);
548 x_uncatch_errors ();
549 UNBLOCK_INPUT;
550
551 return list;
552 }
553
554 extern Lisp_Object QCavgwidth;
555
556 static Lisp_Object
557 xfont_open (f, entity, pixel_size)
558 FRAME_PTR f;
559 Lisp_Object entity;
560 int pixel_size;
561 {
562 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
563 Display *display = dpyinfo->display;
564 char name[512];
565 int len;
566 unsigned long value;
567 Lisp_Object registry;
568 struct charset *encoding, *repertory;
569 Lisp_Object font_object, fullname;
570 struct font *font;
571 XFontStruct *xfont;
572 int i;
573
574 /* At first, check if we know how to encode characters for this
575 font. */
576 registry = AREF (entity, FONT_REGISTRY_INDEX);
577 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
578 {
579 font_add_log (" x:unknown registry", registry, Qnil);
580 return Qnil;
581 }
582
583 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
584 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
585 else if (pixel_size == 0)
586 {
587 if (FRAME_FONT (f))
588 pixel_size = FRAME_FONT (f)->pixel_size;
589 else
590 pixel_size = 14;
591 }
592 len = font_unparse_xlfd (entity, pixel_size, name, 512);
593 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
594 {
595 font_add_log (" x:unparse failed", entity, Qnil);
596 return Qnil;
597 }
598
599 BLOCK_INPUT;
600 x_catch_errors (display);
601 xfont = XLoadQueryFont (display, name);
602 if (x_had_errors_p (display))
603 {
604 /* This error is perhaps due to insufficient memory on X server.
605 Let's just ignore it. */
606 x_clear_errors (display);
607 xfont = NULL;
608 }
609 else if (! xfont)
610 {
611 /* Some version of X lists:
612 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
613 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
614 but can open only:
615 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
616 and
617 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
618 So, we try again with wildcards in RESX and RESY. */
619 Lisp_Object temp;
620
621 temp = Fcopy_font_spec (entity);
622 ASET (temp, FONT_DPI_INDEX, Qnil);
623 len = font_unparse_xlfd (temp, pixel_size, name, 512);
624 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
625 {
626 font_add_log (" x:unparse failed", temp, Qnil);
627 return Qnil;
628 }
629 xfont = XLoadQueryFont (display, name);
630 if (x_had_errors_p (display))
631 {
632 /* This error is perhaps due to insufficient memory on X server.
633 Let's just ignore it. */
634 x_clear_errors (display);
635 xfont = NULL;
636 }
637 }
638 fullname = Qnil;
639 /* Try to get the full name of FONT. */
640 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
641 {
642 char *p0, *p;
643 int dashes = 0;
644
645 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
646 /* Count the number of dashes in the "full name".
647 If it is too few, this isn't really the font's full name,
648 so don't use it.
649 In X11R4, the fonts did not come with their canonical names
650 stored in them. */
651 while (*p)
652 {
653 if (*p == '-')
654 dashes++;
655 p++;
656 }
657
658 if (dashes >= 13)
659 {
660 len = xfont_decode_coding_xlfd (p0, -1, name);
661 fullname = Fdowncase (make_string (name, len));
662 }
663 XFree (p0);
664 }
665 x_uncatch_errors ();
666 UNBLOCK_INPUT;
667
668 if (! xfont)
669 {
670 font_add_log (" x:open failed", build_string (name), Qnil);
671 return Qnil;
672 }
673
674 font_object = font_make_object (VECSIZE (struct xfont_info),
675 entity, pixel_size);
676 ASET (font_object, FONT_TYPE_INDEX, Qx);
677 if (STRINGP (fullname))
678 {
679 font_parse_xlfd ((char *) SDATA (fullname), font_object);
680 ASET (font_object, FONT_NAME_INDEX, fullname);
681 }
682 else
683 {
684 char buf[512];
685
686 len = xfont_decode_coding_xlfd (name, -1, buf);
687 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
688 }
689 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
690 ASET (font_object, FONT_FILE_INDEX, Qnil);
691 ASET (font_object, FONT_FORMAT_INDEX, Qx);
692 font = XFONT_OBJECT (font_object);
693 ((struct xfont_info *) font)->xfont = xfont;
694 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
695 font->pixel_size = pixel_size;
696 font->driver = &xfont_driver;
697 font->encoding_charset = encoding->id;
698 font->repertory_charset = repertory ? repertory->id : -1;
699 font->ascent = xfont->ascent;
700 font->descent = xfont->descent;
701 font->height = font->ascent + font->descent;
702 font->min_width = xfont->min_bounds.width;
703 if (xfont->min_bounds.width == xfont->max_bounds.width)
704 {
705 /* Fixed width font. */
706 font->average_width = font->space_width = xfont->min_bounds.width;
707 }
708 else
709 {
710 XCharStruct *pcm;
711 XChar2b char2b;
712 Lisp_Object val;
713
714 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
715 pcm = xfont_get_pcm (xfont, &char2b);
716 if (pcm)
717 font->space_width = pcm->width;
718 else
719 font->space_width = 0;
720
721 val = Ffont_get (font_object, QCavgwidth);
722 if (INTEGERP (val))
723 font->average_width = XINT (val);
724 if (font->average_width < 0)
725 font->average_width = - font->average_width;
726 if (font->average_width == 0
727 && encoding->ascii_compatible_p)
728 {
729 int width = font->space_width, n = pcm != NULL;
730
731 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
732 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
733 width += pcm->width, n++;
734 if (n > 0)
735 font->average_width = width / n;
736 }
737 if (font->average_width == 0)
738 /* No easy way other than this to get a reasonable
739 average_width. */
740 font->average_width
741 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
742 }
743
744 BLOCK_INPUT;
745 font->underline_thickness
746 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
747 ? (long) value : 0);
748 font->underline_position
749 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
750 ? (long) value : -1);
751 font->baseline_offset
752 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
753 ? (long) value : 0);
754 font->relative_compose
755 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
756 ? (long) value : 0);
757 font->default_ascent
758 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
759 ? (long) value : 0);
760 UNBLOCK_INPUT;
761
762 if (NILP (fullname))
763 fullname = AREF (font_object, FONT_NAME_INDEX);
764 font->vertical_centering
765 = (STRINGP (Vvertical_centering_font_regexp)
766 && (fast_string_match_ignore_case
767 (Vvertical_centering_font_regexp, fullname) >= 0));
768
769 return font_object;
770 }
771
772 static void
773 xfont_close (f, font)
774 FRAME_PTR f;
775 struct font *font;
776 {
777 BLOCK_INPUT;
778 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
779 UNBLOCK_INPUT;
780 }
781
782 static int
783 xfont_prepare_face (f, face)
784 FRAME_PTR f;
785 struct face *face;
786 {
787 BLOCK_INPUT;
788 XSetFont (FRAME_X_DISPLAY (f), face->gc,
789 ((struct xfont_info *) face->font)->xfont->fid);
790 UNBLOCK_INPUT;
791
792 return 0;
793 }
794
795 static int
796 xfont_has_char (entity, c)
797 Lisp_Object entity;
798 int c;
799 {
800 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
801 struct charset *repertory;
802
803 if (font_registry_charsets (registry, NULL, &repertory) < 0)
804 return -1;
805 if (! repertory)
806 return -1;
807 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
808 }
809
810 static unsigned
811 xfont_encode_char (font, c)
812 struct font *font;
813 int c;
814 {
815 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
816 struct charset *charset;
817 unsigned code;
818 XChar2b char2b;
819
820 charset = CHARSET_FROM_ID (font->encoding_charset);
821 code = ENCODE_CHAR (charset, c);
822 if (code == CHARSET_INVALID_CODE (charset))
823 return FONT_INVALID_CODE;
824 if (font->repertory_charset >= 0)
825 {
826 charset = CHARSET_FROM_ID (font->repertory_charset);
827 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
828 ? code : FONT_INVALID_CODE);
829 }
830 char2b.byte1 = code >> 8;
831 char2b.byte2 = code & 0xFF;
832 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
833 }
834
835 static int
836 xfont_text_extents (font, code, nglyphs, metrics)
837 struct font *font;
838 unsigned *code;
839 int nglyphs;
840 struct font_metrics *metrics;
841 {
842 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
843 int width = 0;
844 int i, first, x;
845
846 if (metrics)
847 bzero (metrics, sizeof (struct font_metrics));
848 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
849 {
850 XChar2b char2b;
851 static XCharStruct *pcm;
852
853 if (code[i] >= 0x10000)
854 continue;
855 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
856 pcm = xfont_get_pcm (xfont, &char2b);
857 if (! pcm)
858 continue;
859 if (first)
860 {
861 if (metrics)
862 {
863 metrics->lbearing = pcm->lbearing;
864 metrics->rbearing = pcm->rbearing;
865 metrics->ascent = pcm->ascent;
866 metrics->descent = pcm->descent;
867 }
868 first = 0;
869 }
870 else
871 {
872 if (metrics)
873 {
874 if (metrics->lbearing > width + pcm->lbearing)
875 metrics->lbearing = width + pcm->lbearing;
876 if (metrics->rbearing < width + pcm->rbearing)
877 metrics->rbearing = width + pcm->rbearing;
878 if (metrics->ascent < pcm->ascent)
879 metrics->ascent = pcm->ascent;
880 if (metrics->descent < pcm->descent)
881 metrics->descent = pcm->descent;
882 }
883 }
884 width += pcm->width;
885 }
886 if (metrics)
887 metrics->width = width;
888 return width;
889 }
890
891 static int
892 xfont_draw (s, from, to, x, y, with_background)
893 struct glyph_string *s;
894 int from, to, x, y, with_background;
895 {
896 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
897 int len = to - from;
898 GC gc = s->gc;
899 int i;
900
901 if (s->gc != s->face->gc)
902 {
903 BLOCK_INPUT;
904 XSetFont (s->display, gc, xfont->fid);
905 UNBLOCK_INPUT;
906 }
907
908 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
909 {
910 char *str;
911 USE_SAFE_ALLOCA;
912
913 SAFE_ALLOCA (str, char *, len);
914 for (i = 0; i < len ; i++)
915 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
916 BLOCK_INPUT;
917 if (with_background > 0)
918 {
919 if (s->padding_p)
920 for (i = 0; i < len; i++)
921 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
922 gc, x + i, y, str + i, 1);
923 else
924 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
925 gc, x, y, str, len);
926 }
927 else
928 {
929 if (s->padding_p)
930 for (i = 0; i < len; i++)
931 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
932 gc, x + i, y, str + i, 1);
933 else
934 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
935 gc, x, y, str, len);
936 }
937 UNBLOCK_INPUT;
938 SAFE_FREE ();
939 return s->nchars;
940 }
941
942 BLOCK_INPUT;
943 if (with_background > 0)
944 {
945 if (s->padding_p)
946 for (i = 0; i < len; i++)
947 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
948 gc, x + i, y, s->char2b + from + i, 1);
949 else
950 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
951 gc, x, y, s->char2b + from, len);
952 }
953 else
954 {
955 if (s->padding_p)
956 for (i = 0; i < len; i++)
957 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
958 gc, x + i, y, s->char2b + from + i, 1);
959 else
960 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
961 gc, x, y, s->char2b + from, len);
962 }
963 UNBLOCK_INPUT;
964
965 return len;
966 }
967
968 static int
969 xfont_check (f, font)
970 FRAME_PTR f;
971 struct font *font;
972 {
973 struct xfont_info *xfont = (struct xfont_info *) font;
974
975 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
976 }
977
978 \f
979 void
980 syms_of_xfont ()
981 {
982 xfont_driver.type = Qx;
983 register_font_driver (&xfont_driver, NULL);
984 }
985
986 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
987 (do not change this comment) */