Fix reStructuredText funky capitalization.
[emacs.git] / src / xfont.c
blob67cb6e506643e0059b2ec9718d4092368fbadac2
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
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 static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
215 static Lisp_Object
216 xfont_list_pattern (frame, display, pattern)
217 Lisp_Object frame;
218 Display *display;
219 char *pattern;
221 Lisp_Object list = Qnil;
222 int i, limit, num_fonts;
223 char **names;
225 BLOCK_INPUT;
226 x_catch_errors (display);
228 for (limit = 512; ; limit *= 2)
230 names = XListFonts (display, pattern, limit, &num_fonts);
231 if (x_had_errors_p (display))
233 /* This error is perhaps due to insufficient memory on X
234 server. Let's just ignore it. */
235 x_clear_errors (display);
236 num_fonts = 0;
237 break;
239 if (num_fonts < limit)
240 break;
241 XFreeFontNames (names);
244 if (num_fonts > 0)
246 char **indices = alloca (sizeof (char *) * num_fonts);
248 for (i = 0; i < num_fonts; i++)
249 indices[i] = names[i];
250 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
252 for (i = 0; i < num_fonts; i++)
254 Lisp_Object entity;
255 int result;
257 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
258 continue;
260 entity = font_make_entity ();
261 ASET (entity, FONT_TYPE_INDEX, Qx);
263 result = font_parse_xlfd (indices[i], entity);
264 if (result < 0)
266 /* This may be an alias name. Try to get the full XLFD name
267 from XA_FONT property of the font. */
268 XFontStruct *font = XLoadQueryFont (display, indices[i]);
269 unsigned long value;
271 if (! font)
272 continue;
273 if (XGetFontProperty (font, XA_FONT, &value))
275 char *name = (char *) XGetAtomName (display, (Atom) value);
276 int len = strlen (name);
278 /* If DXPC (a Differential X Protocol Compressor)
279 Ver.3.7 is running, XGetAtomName will return null
280 string. We must avoid such a name. */
281 if (len > 0)
282 result = font_parse_xlfd (name, entity);
283 XFree (name);
285 XFreeFont (display, font);
288 if (result == 0
289 /* Avoid auto-scaled fonts. */
290 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
291 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
292 list = Fcons (entity, list);
294 XFreeFontNames (names);
297 x_uncatch_errors ();
298 UNBLOCK_INPUT;
300 font_add_log ("xfont-list", build_string (pattern), list);
301 return list;
304 static Lisp_Object
305 xfont_list (frame, spec)
306 Lisp_Object frame, spec;
308 FRAME_PTR f = XFRAME (frame);
309 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
310 Lisp_Object registry, list, val, extra;
311 int len;
312 char name[256];
314 extra = AREF (spec, FONT_EXTRA_INDEX);
315 if (CONSP (extra))
317 val = assq_no_quit (QCotf, extra);
318 if (! NILP (val))
319 return Qnil;
320 val = assq_no_quit (QCscript, extra);
321 if (! NILP (val))
322 return Qnil;
323 val = assq_no_quit (QClang, extra);
324 if (! NILP (val))
325 return Qnil;
328 registry = AREF (spec, FONT_REGISTRY_INDEX);
329 len = font_unparse_xlfd (spec, 0, name, 256);
330 ASET (spec, FONT_REGISTRY_INDEX, registry);
331 if (len < 0)
332 return Qnil;
333 list = xfont_list_pattern (frame, display, name);
334 if (NILP (list) && NILP (registry))
336 /* Try iso10646-1 */
337 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
339 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
341 strcpy (r, "iso10646-1");
342 list = xfont_list_pattern (frame, display, name);
345 if (NILP (list) && ! NILP (registry))
347 /* Try alternate registries. */
348 Lisp_Object alter;
350 if ((alter = Fassoc (SYMBOL_NAME (registry),
351 Vface_alternative_font_registry_alist),
352 CONSP (alter)))
354 /* Pointer to REGISTRY-ENCODING field. */
355 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
357 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
358 if (STRINGP (XCAR (alter))
359 && ((r - name) + SBYTES (XCAR (alter))) < 256)
361 strcpy (r, (char *) SDATA (XCAR (alter)));
362 list = xfont_list_pattern (frame, display, name);
363 if (! NILP (list))
364 break;
368 if (NILP (list))
370 /* Try alias. */
371 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
372 if (CONSP (val) && STRINGP (XCDR (val)))
373 list = xfont_list_pattern (frame, display, (char *) SDATA (XCDR (val)));
376 return list;
379 static Lisp_Object
380 xfont_match (frame, spec)
381 Lisp_Object frame, spec;
383 FRAME_PTR f = XFRAME (frame);
384 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
385 Lisp_Object extra, val, entity;
386 char buf[256], *name;
387 XFontStruct *xfont;
388 unsigned long value;
390 extra = AREF (spec, FONT_EXTRA_INDEX);
391 val = assq_no_quit (QCname, extra);
392 if (! CONSP (val) || ! STRINGP (XCDR (val)))
394 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
395 return Qnil;
396 name = buf;
398 else
399 name = (char *) SDATA (XCDR (val));
401 BLOCK_INPUT;
402 entity = Qnil;
403 xfont = XLoadQueryFont (display, name);
404 if (xfont)
406 if (XGetFontProperty (xfont, XA_FONT, &value))
408 int len;
410 name = (char *) XGetAtomName (display, (Atom) value);
411 len = strlen (name);
413 /* If DXPC (a Differential X Protocol Compressor)
414 Ver.3.7 is running, XGetAtomName will return null
415 string. We must avoid such a name. */
416 if (len > 0)
418 entity = font_make_entity ();
419 ASET (entity, FONT_TYPE_INDEX, Qx);
420 if (font_parse_xlfd (name, entity) < 0)
421 entity = Qnil;
423 XFree (name);
425 XFreeFont (display, xfont);
427 UNBLOCK_INPUT;
429 font_add_log ("xfont-match", spec, entity);
430 return entity;
433 static Lisp_Object
434 xfont_list_family (frame)
435 Lisp_Object frame;
437 FRAME_PTR f = XFRAME (frame);
438 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
439 char **names;
440 int num_fonts, i;
441 Lisp_Object list;
442 char *last_family;
443 int last_len;
445 BLOCK_INPUT;
446 x_catch_errors (dpyinfo->display);
447 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
448 0x8000, &num_fonts);
449 if (x_had_errors_p (dpyinfo->display))
451 /* This error is perhaps due to insufficient memory on X server.
452 Let's just ignore it. */
453 x_clear_errors (dpyinfo->display);
454 num_fonts = 0;
457 list = Qnil;
458 for (i = 0, last_len = 0; i < num_fonts; i++)
460 char *p0 = names[i], *p1;
461 Lisp_Object family;
463 p0++; /* skip the leading '-' */
464 while (*p0 && *p0 != '-') p0++; /* skip foundry */
465 if (! *p0)
466 continue;
467 p1 = ++p0;
468 while (*p1 && *p1 != '-') p1++; /* find the end of family */
469 if (! *p1 || p1 == p0)
470 continue;
471 if (last_len == p1 - p0
472 && bcmp (last_family, p0, last_len) == 0)
473 continue;
474 last_len = p1 - p0;
475 last_family = p0;
476 family = font_intern_prop (p0, last_len, 1);
477 if (NILP (assq_no_quit (family, list)))
478 list = Fcons (family, list);
481 XFreeFontNames (names);
482 x_uncatch_errors ();
483 UNBLOCK_INPUT;
485 return list;
488 extern Lisp_Object QCavgwidth;
490 static Lisp_Object
491 xfont_open (f, entity, pixel_size)
492 FRAME_PTR f;
493 Lisp_Object entity;
494 int pixel_size;
496 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
497 Display *display = dpyinfo->display;
498 char name[256];
499 int len;
500 unsigned long value;
501 Lisp_Object registry;
502 struct charset *encoding, *repertory;
503 Lisp_Object font_object, fullname;
504 struct font *font;
505 XFontStruct *xfont;
506 int i;
508 /* At first, check if we know how to encode characters for this
509 font. */
510 registry = AREF (entity, FONT_REGISTRY_INDEX);
511 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
513 font_add_log (" x:unknown registry", registry, Qnil);
514 return Qnil;
517 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
518 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
519 else if (pixel_size == 0)
521 if (FRAME_FONT (f))
522 pixel_size = FRAME_FONT (f)->pixel_size;
523 else
524 pixel_size = 14;
526 len = font_unparse_xlfd (entity, pixel_size, name, 256);
527 if (len <= 0)
529 font_add_log (" x:unparse failed", entity, Qnil);
530 return Qnil;
533 BLOCK_INPUT;
534 x_catch_errors (display);
535 xfont = XLoadQueryFont (display, name);
536 if (x_had_errors_p (display))
538 /* This error is perhaps due to insufficient memory on X server.
539 Let's just ignore it. */
540 x_clear_errors (display);
541 xfont = NULL;
543 else if (! xfont)
545 /* Some version of X lists:
546 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
547 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
548 but can open only:
549 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
551 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
552 So, we try again with wildcards in RESX and RESY. */
553 Lisp_Object temp;
555 temp = Fcopy_font_spec (entity);
556 ASET (temp, FONT_DPI_INDEX, Qnil);
557 len = font_unparse_xlfd (temp, pixel_size, name, 256);
558 if (len <= 0)
560 font_add_log (" x:unparse failed", temp, Qnil);
561 return Qnil;
563 xfont = XLoadQueryFont (display, name);
564 if (x_had_errors_p (display))
566 /* This error is perhaps due to insufficient memory on X server.
567 Let's just ignore it. */
568 x_clear_errors (display);
569 xfont = NULL;
572 fullname = Qnil;
573 /* Try to get the full name of FONT. */
574 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
576 char *p0, *p;
577 int dashes = 0;
579 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
580 /* Count the number of dashes in the "full name".
581 If it is too few, this isn't really the font's full name,
582 so don't use it.
583 In X11R4, the fonts did not come with their canonical names
584 stored in them. */
585 while (*p)
587 if (*p == '-')
588 dashes++;
589 p++;
592 if (dashes >= 13)
593 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
594 XFree (p0);
596 x_uncatch_errors ();
597 UNBLOCK_INPUT;
599 if (! xfont)
601 font_add_log (" x:open failed", build_string (name), Qnil);
602 return Qnil;
605 font_object = font_make_object (VECSIZE (struct xfont_info),
606 entity, pixel_size);
607 ASET (font_object, FONT_TYPE_INDEX, Qx);
608 if (STRINGP (fullname))
609 font_parse_xlfd ((char *) SDATA (fullname), font_object);
610 if (STRINGP (fullname))
611 ASET (font_object, FONT_NAME_INDEX, fullname);
612 else
613 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
614 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
615 ASET (font_object, FONT_FILE_INDEX, Qnil);
616 ASET (font_object, FONT_FORMAT_INDEX, Qx);
617 font = XFONT_OBJECT (font_object);
618 ((struct xfont_info *) font)->xfont = xfont;
619 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
620 font->pixel_size = pixel_size;
621 font->driver = &xfont_driver;
622 font->encoding_charset = encoding->id;
623 font->repertory_charset = repertory ? repertory->id : -1;
624 font->ascent = xfont->ascent;
625 font->descent = xfont->descent;
626 font->height = font->ascent + font->descent;
627 font->min_width = xfont->min_bounds.width;
628 if (xfont->min_bounds.width == xfont->max_bounds.width)
630 /* Fixed width font. */
631 font->average_width = font->space_width = xfont->min_bounds.width;
633 else
635 XCharStruct *pcm;
636 XChar2b char2b;
637 Lisp_Object val;
639 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
640 pcm = xfont_get_pcm (xfont, &char2b);
641 if (pcm)
642 font->space_width = pcm->width;
643 else
644 font->space_width = 0;
646 val = Ffont_get (font_object, QCavgwidth);
647 if (INTEGERP (val))
648 font->average_width = XINT (val);
649 if (font->average_width < 0)
650 font->average_width = - font->average_width;
651 if (font->average_width == 0
652 && encoding->ascii_compatible_p)
654 int width = font->space_width, n = pcm != NULL;
656 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
657 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
658 width += pcm->width, n++;
659 if (n > 0)
660 font->average_width = width / n;
662 if (font->average_width == 0)
663 /* No easy way other than this to get a reasonable
664 average_width. */
665 font->average_width
666 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
669 BLOCK_INPUT;
670 font->underline_thickness
671 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
672 ? (long) value : 0);
673 font->underline_position
674 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
675 ? (long) value : -1);
676 font->baseline_offset
677 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
678 ? (long) value : 0);
679 font->relative_compose
680 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
681 ? (long) value : 0);
682 font->default_ascent
683 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
684 ? (long) value : 0);
685 UNBLOCK_INPUT;
687 if (NILP (fullname))
688 fullname = AREF (font_object, FONT_NAME_INDEX);
689 font->vertical_centering
690 = (STRINGP (Vvertical_centering_font_regexp)
691 && (fast_string_match_ignore_case
692 (Vvertical_centering_font_regexp, fullname) >= 0));
694 return font_object;
697 static void
698 xfont_close (f, font)
699 FRAME_PTR f;
700 struct font *font;
702 BLOCK_INPUT;
703 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
704 UNBLOCK_INPUT;
707 static int
708 xfont_prepare_face (f, face)
709 FRAME_PTR f;
710 struct face *face;
712 BLOCK_INPUT;
713 XSetFont (FRAME_X_DISPLAY (f), face->gc,
714 ((struct xfont_info *) face->font)->xfont->fid);
715 UNBLOCK_INPUT;
717 return 0;
720 static int
721 xfont_has_char (entity, c)
722 Lisp_Object entity;
723 int c;
725 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
726 struct charset *repertory;
728 if (font_registry_charsets (registry, NULL, &repertory) < 0)
729 return -1;
730 if (! repertory)
731 return -1;
732 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
735 static unsigned
736 xfont_encode_char (font, c)
737 struct font *font;
738 int c;
740 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
741 struct charset *charset;
742 unsigned code;
743 XChar2b char2b;
745 charset = CHARSET_FROM_ID (font->encoding_charset);
746 code = ENCODE_CHAR (charset, c);
747 if (code == CHARSET_INVALID_CODE (charset))
748 return FONT_INVALID_CODE;
749 if (font->repertory_charset >= 0)
751 charset = CHARSET_FROM_ID (font->repertory_charset);
752 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
753 ? code : FONT_INVALID_CODE);
755 char2b.byte1 = code >> 8;
756 char2b.byte2 = code & 0xFF;
757 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
760 static int
761 xfont_text_extents (font, code, nglyphs, metrics)
762 struct font *font;
763 unsigned *code;
764 int nglyphs;
765 struct font_metrics *metrics;
767 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
768 int width = 0;
769 int i, first, x;
771 if (metrics)
772 bzero (metrics, sizeof (struct font_metrics));
773 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
775 XChar2b char2b;
776 static XCharStruct *pcm;
778 if (code[i] >= 0x10000)
779 continue;
780 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
781 pcm = xfont_get_pcm (xfont, &char2b);
782 if (! pcm)
783 continue;
784 if (first)
786 if (metrics)
788 metrics->lbearing = pcm->lbearing;
789 metrics->rbearing = pcm->rbearing;
790 metrics->ascent = pcm->ascent;
791 metrics->descent = pcm->descent;
793 first = 0;
795 else
797 if (metrics)
799 if (metrics->lbearing > width + pcm->lbearing)
800 metrics->lbearing = width + pcm->lbearing;
801 if (metrics->rbearing < width + pcm->rbearing)
802 metrics->rbearing = width + pcm->rbearing;
803 if (metrics->ascent < pcm->ascent)
804 metrics->ascent = pcm->ascent;
805 if (metrics->descent < pcm->descent)
806 metrics->descent = pcm->descent;
809 width += pcm->width;
811 if (metrics)
812 metrics->width = width;
813 return width;
816 static int
817 xfont_draw (s, from, to, x, y, with_background)
818 struct glyph_string *s;
819 int from, to, x, y, with_background;
821 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
822 int len = to - from;
823 GC gc = s->gc;
824 int i;
826 if (s->gc != s->face->gc)
828 BLOCK_INPUT;
829 XSetFont (s->display, gc, xfont->fid);
830 UNBLOCK_INPUT;
833 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
835 char *str;
836 USE_SAFE_ALLOCA;
838 SAFE_ALLOCA (str, char *, len);
839 for (i = 0; i < len ; i++)
840 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
841 BLOCK_INPUT;
842 if (with_background > 0)
844 if (s->padding_p)
845 for (i = 0; i < len; i++)
846 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
847 gc, x + i, y, str + i, 1);
848 else
849 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
850 gc, x, y, str, len);
852 else
854 if (s->padding_p)
855 for (i = 0; i < len; i++)
856 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
857 gc, x + i, y, str + i, 1);
858 else
859 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
860 gc, x, y, str, len);
862 UNBLOCK_INPUT;
863 SAFE_FREE ();
864 return s->nchars;
867 BLOCK_INPUT;
868 if (with_background > 0)
870 if (s->padding_p)
871 for (i = 0; i < len; i++)
872 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
873 gc, x + i, y, s->char2b + from + i, 1);
874 else
875 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
876 gc, x, y, s->char2b + from, len);
878 else
880 if (s->padding_p)
881 for (i = 0; i < len; i++)
882 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
883 gc, x + i, y, s->char2b + from + i, 1);
884 else
885 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
886 gc, x, y, s->char2b + from, len);
888 UNBLOCK_INPUT;
890 return len;
893 static int
894 xfont_check (f, font)
895 FRAME_PTR f;
896 struct font *font;
898 struct xfont_info *xfont = (struct xfont_info *) font;
900 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
904 void
905 syms_of_xfont ()
907 xfont_driver.type = Qx;
908 register_font_driver (&xfont_driver, NULL);
911 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
912 (do not change this comment) */