Remove mention of obsolete president.
[emacs.git] / src / xfont.c
blobafafca89c2458b6ca2489f0b85697aff37981e3b
1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
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.
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.
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/>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <X11/Xlib.h>
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"
39 /* X core font driver. */
41 struct xfont_info
43 struct font font;
44 Display *display;
45 XFontStruct *xfont;
48 /* Prototypes of support functions. */
49 extern void x_clear_errors P_ ((Display *));
51 static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
52 static void xfont_find_ccl_program P_ ((struct font *));
54 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
55 is not contained in the font. */
57 static XCharStruct *
58 xfont_get_pcm (xfont, char2b)
59 XFontStruct *xfont;
60 XChar2b *char2b;
62 /* The result metric information. */
63 XCharStruct *pcm = NULL;
65 font_assert (xfont && char2b);
67 if (xfont->per_char != NULL)
69 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
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;
82 else
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:
89 byte1 = N/D + min_byte1
90 byte2 = N\D + min_char_or_byte2
92 where:
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));
107 else
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;
117 return ((pcm == NULL
118 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
119 ? NULL : pcm);
122 /* Find a CCL program for a font specified by FONTP, and set the member
123 `encoder' of the structure. */
125 static void
126 xfont_find_ccl_program (font)
127 struct font *font;
129 Lisp_Object list, elt;
131 elt = Qnil;
132 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
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;
146 if (! NILP (list))
148 struct ccl_program *ccl
149 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
151 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
152 xfree (ccl);
153 else
154 font->font_encoder = ccl;
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 *));
172 struct font_driver xfont_driver =
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
193 extern Lisp_Object QCname;
195 static Lisp_Object
196 xfont_get_cache (f)
197 FRAME_PTR f;
199 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
201 return (dpyinfo->name_list_element);
204 extern Lisp_Object Vface_alternative_font_registry_alist;
206 static int
207 compare_font_names (const void *name1, const void *name2)
209 return xstrcasecmp (*(const unsigned char **) name1,
210 *(const unsigned char **) name2);
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. */
218 static int
219 xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
221 char *p0 = xlfd, *p1 = output;
222 int c;
224 while (*p0)
226 c = *(unsigned char *) p0++;
227 p1 += CHAR_STRING (c, p1);
228 if (--len == 0)
229 break;
231 *p1 = 0;
232 return (p1 - output);
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. */
239 static int
240 xfont_encode_coding_xlfd (char *xlfd)
242 const unsigned char *p0 = (unsigned char *) xlfd;
243 unsigned char *p1 = (unsigned char *) xlfd;
244 int len = 0;
246 while (*p0)
248 int c = STRING_CHAR_ADVANCE (p0);
250 if (c >= 0x100)
251 return -1;
252 *p1++ = c;
253 len++;
255 *p1 = 0;
256 return len;
259 static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
261 static Lisp_Object
262 xfont_list_pattern (frame, display, pattern)
263 Lisp_Object frame;
264 Display *display;
265 char *pattern;
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];
273 BLOCK_INPUT;
274 x_catch_errors (display);
276 for (limit = 512; ; limit *= 2)
278 names = XListFonts (display, pattern, limit, &num_fonts);
279 if (x_had_errors_p (display))
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;
287 if (num_fonts < limit)
288 break;
289 XFreeFontNames (names);
292 if (num_fonts > 0)
294 char **indices = alloca (sizeof (char *) * num_fonts);
296 for (i = 0; i < num_fonts; i++)
297 indices[i] = names[i];
298 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
300 for (i = 0; i < num_fonts; i++)
302 Lisp_Object entity;
303 int result;
304 char *p;
306 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
307 continue;
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)
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;
320 if (! font)
321 continue;
322 if (XGetFontProperty (font, XA_FONT, &value))
324 char *name = (char *) XGetAtomName (display, (Atom) value);
325 int len = strlen (name);
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)
332 xfont_decode_coding_xlfd (indices[i], -1, buf);
333 result = font_parse_xlfd (buf, entity);
335 XFree (name);
337 XFreeFont (display, font);
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);
346 XFreeFontNames (names);
349 x_uncatch_errors ();
350 UNBLOCK_INPUT;
352 font_add_log ("xfont-list", build_string (pattern), list);
353 return list;
356 static Lisp_Object
357 xfont_list (frame, spec)
358 Lisp_Object frame, spec;
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];
367 extra = AREF (spec, FONT_EXTRA_INDEX);
368 if (CONSP (extra))
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;
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))
389 /* Try iso10646-1 */
390 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
392 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
394 strcpy (r, "iso10646-1");
395 list = xfont_list_pattern (frame, display, name);
398 if (NILP (list) && ! NILP (registry))
400 /* Try alternate registries. */
401 Lisp_Object alter;
403 if ((alter = Fassoc (SYMBOL_NAME (registry),
404 Vface_alternative_font_registry_alist),
405 CONSP (alter)))
407 /* Pointer to REGISTRY-ENCODING field. */
408 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
410 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
411 if (STRINGP (XCAR (alter))
412 && ((r - name) + SBYTES (XCAR (alter))) < 256)
414 strcpy (r, (char *) SDATA (XCAR (alter)));
415 list = xfont_list_pattern (frame, display, name);
416 if (! NILP (list))
417 break;
421 if (NILP (list))
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)
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);
434 return list;
437 static Lisp_Object
438 xfont_match (frame, spec)
439 Lisp_Object frame, spec;
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;
448 extra = AREF (spec, FONT_EXTRA_INDEX);
449 val = assq_no_quit (QCname, extra);
450 if (! CONSP (val) || ! STRINGP (XCDR (val)))
452 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
453 return Qnil;
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;
462 BLOCK_INPUT;
463 entity = Qnil;
464 xfont = XLoadQueryFont (display, name);
465 if (xfont)
467 if (XGetFontProperty (xfont, XA_FONT, &value))
469 int len;
470 char *s;
472 s = (char *) XGetAtomName (display, (Atom) value);
473 len = strlen (s);
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)
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;
486 XFree (s);
488 XFreeFont (display, xfont);
490 UNBLOCK_INPUT;
492 font_add_log ("xfont-match", spec, entity);
493 return entity;
496 static Lisp_Object
497 xfont_list_family (frame)
498 Lisp_Object frame;
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;
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))
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;
520 list = Qnil;
521 for (i = 0, last_len = 0; i < num_fonts; i++)
523 char *p0 = names[i], *p1, buf[512];
524 Lisp_Object family;
525 int decoded_len;
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;
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);
547 XFreeFontNames (names);
548 x_uncatch_errors ();
549 UNBLOCK_INPUT;
551 return list;
554 extern Lisp_Object QCavgwidth;
556 static Lisp_Object
557 xfont_open (f, entity, pixel_size)
558 FRAME_PTR f;
559 Lisp_Object entity;
560 int pixel_size;
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;
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)
579 font_add_log (" x:unknown registry", registry, Qnil);
580 return Qnil;
583 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
584 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
585 else if (pixel_size == 0)
587 if (FRAME_FONT (f))
588 pixel_size = FRAME_FONT (f)->pixel_size;
589 else
590 pixel_size = 14;
592 len = font_unparse_xlfd (entity, pixel_size, name, 512);
593 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
595 font_add_log (" x:unparse failed", entity, Qnil);
596 return Qnil;
599 BLOCK_INPUT;
600 x_catch_errors (display);
601 xfont = XLoadQueryFont (display, name);
602 if (x_had_errors_p (display))
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;
609 else if (! xfont)
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
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;
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)
626 font_add_log (" x:unparse failed", temp, Qnil);
627 return Qnil;
629 xfont = XLoadQueryFont (display, name);
630 if (x_had_errors_p (display))
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;
638 fullname = Qnil;
639 /* Try to get the full name of FONT. */
640 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
642 char *p0, *p;
643 int dashes = 0;
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)
653 if (*p == '-')
654 dashes++;
655 p++;
658 if (dashes >= 13)
660 len = xfont_decode_coding_xlfd (p0, -1, name);
661 fullname = Fdowncase (make_string (name, len));
663 XFree (p0);
665 x_uncatch_errors ();
666 UNBLOCK_INPUT;
668 if (! xfont)
670 font_add_log (" x:open failed", build_string (name), Qnil);
671 return Qnil;
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))
679 font_parse_xlfd ((char *) SDATA (fullname), font_object);
680 ASET (font_object, FONT_NAME_INDEX, fullname);
682 else
684 char buf[512];
686 len = xfont_decode_coding_xlfd (name, -1, buf);
687 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
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)
705 /* Fixed width font. */
706 font->average_width = font->space_width = xfont->min_bounds.width;
708 else
710 XCharStruct *pcm;
711 XChar2b char2b;
712 Lisp_Object val;
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;
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)
729 int width = font->space_width, n = pcm != NULL;
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;
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;
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;
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));
769 return font_object;
772 static void
773 xfont_close (f, font)
774 FRAME_PTR f;
775 struct font *font;
777 BLOCK_INPUT;
778 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
779 UNBLOCK_INPUT;
782 static int
783 xfont_prepare_face (f, face)
784 FRAME_PTR f;
785 struct face *face;
787 BLOCK_INPUT;
788 XSetFont (FRAME_X_DISPLAY (f), face->gc,
789 ((struct xfont_info *) face->font)->xfont->fid);
790 UNBLOCK_INPUT;
792 return 0;
795 static int
796 xfont_has_char (font, c)
797 Lisp_Object font;
798 int c;
800 Lisp_Object registry = AREF (font, FONT_REGISTRY_INDEX);
801 struct charset *encoding;
802 struct charset *repertory = NULL;
804 if (EQ (registry, Qiso10646_1))
806 /* We use a font of `ja' and `ko' adstyle only for a character
807 in JISX0208 and KSC5601 charsets respectively. */
808 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
809 && charset_jisx0208 >= 0)
810 encoding = repertory = CHARSET_FROM_ID (charset_jisx0208);
811 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
812 && charset_ksc5601 >= 0)
813 encoding = repertory = CHARSET_FROM_ID (charset_ksc5601);
814 else
815 encoding = CHARSET_FROM_ID (charset_unicode);
817 else if (font_registry_charsets (registry, &encoding, &repertory) < 0)
818 /* Unknown REGISTRY, not usable. */
819 return 0;
820 if (ASCII_CHAR_P (c) && encoding->ascii_compatible_p)
821 return 1;
822 if (! repertory)
823 return -1;
824 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
827 static unsigned
828 xfont_encode_char (font, c)
829 struct font *font;
830 int c;
832 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
833 struct charset *charset;
834 unsigned code;
835 XChar2b char2b;
837 charset = CHARSET_FROM_ID (font->encoding_charset);
838 code = ENCODE_CHAR (charset, c);
839 if (code == CHARSET_INVALID_CODE (charset))
840 return FONT_INVALID_CODE;
841 if (font->repertory_charset >= 0)
843 charset = CHARSET_FROM_ID (font->repertory_charset);
844 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
845 ? code : FONT_INVALID_CODE);
847 char2b.byte1 = code >> 8;
848 char2b.byte2 = code & 0xFF;
849 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
852 static int
853 xfont_text_extents (font, code, nglyphs, metrics)
854 struct font *font;
855 unsigned *code;
856 int nglyphs;
857 struct font_metrics *metrics;
859 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
860 int width = 0;
861 int i, first, x;
863 if (metrics)
864 bzero (metrics, sizeof (struct font_metrics));
865 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
867 XChar2b char2b;
868 static XCharStruct *pcm;
870 if (code[i] >= 0x10000)
871 continue;
872 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
873 pcm = xfont_get_pcm (xfont, &char2b);
874 if (! pcm)
875 continue;
876 if (first)
878 if (metrics)
880 metrics->lbearing = pcm->lbearing;
881 metrics->rbearing = pcm->rbearing;
882 metrics->ascent = pcm->ascent;
883 metrics->descent = pcm->descent;
885 first = 0;
887 else
889 if (metrics)
891 if (metrics->lbearing > width + pcm->lbearing)
892 metrics->lbearing = width + pcm->lbearing;
893 if (metrics->rbearing < width + pcm->rbearing)
894 metrics->rbearing = width + pcm->rbearing;
895 if (metrics->ascent < pcm->ascent)
896 metrics->ascent = pcm->ascent;
897 if (metrics->descent < pcm->descent)
898 metrics->descent = pcm->descent;
901 width += pcm->width;
903 if (metrics)
904 metrics->width = width;
905 return width;
908 static int
909 xfont_draw (s, from, to, x, y, with_background)
910 struct glyph_string *s;
911 int from, to, x, y, with_background;
913 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
914 int len = to - from;
915 GC gc = s->gc;
916 int i;
918 if (s->gc != s->face->gc)
920 BLOCK_INPUT;
921 XSetFont (s->display, gc, xfont->fid);
922 UNBLOCK_INPUT;
925 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
927 char *str;
928 USE_SAFE_ALLOCA;
930 SAFE_ALLOCA (str, char *, len);
931 for (i = 0; i < len ; i++)
932 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
933 BLOCK_INPUT;
934 if (with_background > 0)
936 if (s->padding_p)
937 for (i = 0; i < len; i++)
938 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
939 gc, x + i, y, str + i, 1);
940 else
941 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
942 gc, x, y, str, len);
944 else
946 if (s->padding_p)
947 for (i = 0; i < len; i++)
948 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
949 gc, x + i, y, str + i, 1);
950 else
951 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
952 gc, x, y, str, len);
954 UNBLOCK_INPUT;
955 SAFE_FREE ();
956 return s->nchars;
959 BLOCK_INPUT;
960 if (with_background > 0)
962 if (s->padding_p)
963 for (i = 0; i < len; i++)
964 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
965 gc, x + i, y, s->char2b + from + i, 1);
966 else
967 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
968 gc, x, y, s->char2b + from, len);
970 else
972 if (s->padding_p)
973 for (i = 0; i < len; i++)
974 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
975 gc, x + i, y, s->char2b + from + i, 1);
976 else
977 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
978 gc, x, y, s->char2b + from, len);
980 UNBLOCK_INPUT;
982 return len;
985 static int
986 xfont_check (f, font)
987 FRAME_PTR f;
988 struct font *font;
990 struct xfont_info *xfont = (struct xfont_info *) font;
992 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
996 void
997 syms_of_xfont ()
999 xfont_driver.type = Qx;
1000 register_font_driver (&xfont_driver, NULL);
1003 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
1004 (do not change this comment) */