(lisp2): Add minibuffer.elc.
[emacs.git] / src / xfont.c
blobe6f0bde5114b83d1c1e69e4ae9b7a7dc2e93573f
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 char **) name1, *(const char **) name2);
212 static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
214 static Lisp_Object
215 xfont_list_pattern (frame, display, pattern)
216 Lisp_Object frame;
217 Display *display;
218 char *pattern;
220 Lisp_Object list = Qnil;
221 int i, limit, num_fonts;
222 char **names;
224 BLOCK_INPUT;
225 x_catch_errors (display);
227 for (limit = 512; ; limit *= 2)
229 names = XListFonts (display, pattern, limit, &num_fonts);
230 if (x_had_errors_p (display))
232 /* This error is perhaps due to insufficient memory on X
233 server. Let's just ignore it. */
234 x_clear_errors (display);
235 num_fonts = 0;
236 break;
238 if (num_fonts < limit)
239 break;
240 XFreeFontNames (names);
243 if (num_fonts > 0)
245 char **indices = alloca (sizeof (char *) * num_fonts);
247 for (i = 0; i < num_fonts; i++)
248 indices[i] = names[i];
249 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
251 for (i = 0; i < num_fonts; i++)
253 Lisp_Object entity;
254 int result;
256 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
257 continue;
259 entity = font_make_entity ();
260 ASET (entity, FONT_TYPE_INDEX, Qx);
262 result = font_parse_xlfd (indices[i], entity);
263 if (result < 0)
265 /* This may be an alias name. Try to get the full XLFD name
266 from XA_FONT property of the font. */
267 XFontStruct *font = XLoadQueryFont (display, indices[i]);
268 unsigned long value;
270 if (! font)
271 continue;
272 if (XGetFontProperty (font, XA_FONT, &value))
274 char *name = (char *) XGetAtomName (display, (Atom) value);
275 int len = strlen (name);
277 /* If DXPC (a Differential X Protocol Compressor)
278 Ver.3.7 is running, XGetAtomName will return null
279 string. We must avoid such a name. */
280 if (len > 0)
281 result = font_parse_xlfd (name, entity);
282 XFree (name);
284 XFreeFont (display, font);
287 if (result == 0
288 /* Avoid auto-scaled fonts. */
289 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
290 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
291 list = Fcons (entity, list);
293 XFreeFontNames (names);
296 x_uncatch_errors ();
297 UNBLOCK_INPUT;
299 font_add_log ("xfont-list", build_string (pattern), list);
300 return list;
303 static Lisp_Object
304 xfont_list (frame, spec)
305 Lisp_Object frame, spec;
307 FRAME_PTR f = XFRAME (frame);
308 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
309 Lisp_Object registry, list, val, extra;
310 int len;
311 char name[256];
313 extra = AREF (spec, FONT_EXTRA_INDEX);
314 if (CONSP (extra))
316 val = assq_no_quit (QCotf, extra);
317 if (! NILP (val))
318 return Qnil;
319 val = assq_no_quit (QCscript, extra);
320 if (! NILP (val))
321 return Qnil;
322 val = assq_no_quit (QClang, extra);
323 if (! NILP (val))
324 return Qnil;
327 registry = AREF (spec, FONT_REGISTRY_INDEX);
328 if (NILP (registry))
329 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
330 len = font_unparse_xlfd (spec, 0, name, 256);
331 ASET (spec, FONT_REGISTRY_INDEX, registry);
332 if (len < 0)
333 return Qnil;
334 list = xfont_list_pattern (frame, display, name);
335 if (NILP (list) && NILP (registry))
337 /* Try iso10646-1 */
338 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
340 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
342 strcpy (r, "iso10646-1");
343 list = xfont_list_pattern (frame, display, name);
346 if (NILP (list) && ! NILP (registry))
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;
369 return list;
372 static Lisp_Object
373 xfont_match (frame, spec)
374 Lisp_Object frame, spec;
376 FRAME_PTR f = XFRAME (frame);
377 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
378 Lisp_Object extra, val, entity;
379 char buf[256], *name;
380 XFontStruct *xfont;
381 unsigned long value;
383 extra = AREF (spec, FONT_EXTRA_INDEX);
384 val = assq_no_quit (QCname, extra);
385 if (! CONSP (val) || ! STRINGP (XCDR (val)))
387 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
388 return Qnil;
389 name = buf;
391 else
392 name = (char *) SDATA (XCDR (val));
394 BLOCK_INPUT;
395 entity = Qnil;
396 xfont = XLoadQueryFont (display, name);
397 if (xfont)
399 if (XGetFontProperty (xfont, XA_FONT, &value))
401 int len;
403 name = (char *) XGetAtomName (display, (Atom) value);
404 len = strlen (name);
406 /* If DXPC (a Differential X Protocol Compressor)
407 Ver.3.7 is running, XGetAtomName will return null
408 string. We must avoid such a name. */
409 if (len > 0)
411 entity = font_make_entity ();
412 ASET (entity, FONT_TYPE_INDEX, Qx);
413 if (font_parse_xlfd (name, entity) < 0)
414 entity = Qnil;
416 XFree (name);
418 XFreeFont (display, xfont);
420 UNBLOCK_INPUT;
422 font_add_log ("xfont-match", spec, entity);
423 return entity;
426 static Lisp_Object
427 xfont_list_family (frame)
428 Lisp_Object frame;
430 FRAME_PTR f = XFRAME (frame);
431 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
432 char **names;
433 int num_fonts, i;
434 Lisp_Object list;
435 char *last_family;
436 int last_len;
438 BLOCK_INPUT;
439 x_catch_errors (dpyinfo->display);
440 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
441 0x8000, &num_fonts);
442 if (x_had_errors_p (dpyinfo->display))
444 /* This error is perhaps due to insufficient memory on X server.
445 Let's just ignore it. */
446 x_clear_errors (dpyinfo->display);
447 num_fonts = 0;
450 list = Qnil;
451 for (i = 0, last_len = 0; i < num_fonts; i++)
453 char *p0 = names[i], *p1;
454 Lisp_Object family;
456 p0++; /* skip the leading '-' */
457 while (*p0 && *p0 != '-') p0++; /* skip foundry */
458 if (! *p0)
459 continue;
460 p1 = ++p0;
461 while (*p1 && *p1 != '-') p1++; /* find the end of family */
462 if (! *p1 || p1 == p0)
463 continue;
464 if (last_len == p1 - p0
465 && bcmp (last_family, p0, last_len) == 0)
466 continue;
467 last_len = p1 - p0;
468 last_family = p0;
469 family = make_unibyte_string (p0, last_len);
470 if (NILP (Fassoc_string (family, list, Qt)))
471 list = Fcons (family, list);
474 XFreeFontNames (names);
475 x_uncatch_errors ();
476 UNBLOCK_INPUT;
478 return list;
481 extern Lisp_Object QCavgwidth;
483 static Lisp_Object
484 xfont_open (f, entity, pixel_size)
485 FRAME_PTR f;
486 Lisp_Object entity;
487 int pixel_size;
489 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
490 Display *display = dpyinfo->display;
491 char name[256];
492 int len;
493 unsigned long value;
494 Lisp_Object registry;
495 struct charset *encoding, *repertory;
496 Lisp_Object font_object, fullname;
497 struct font *font;
498 XFontStruct *xfont;
499 int i;
501 /* At first, check if we know how to encode characters for this
502 font. */
503 registry = AREF (entity, FONT_REGISTRY_INDEX);
504 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
505 return Qnil;
507 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
508 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
509 else if (pixel_size == 0)
511 if (FRAME_FONT (f))
512 pixel_size = FRAME_FONT (f)->pixel_size;
513 else
514 pixel_size = 14;
516 len = font_unparse_xlfd (entity, pixel_size, name, 256);
517 if (len <= 0)
518 return Qnil;
520 BLOCK_INPUT;
521 x_catch_errors (display);
522 xfont = XLoadQueryFont (display, name);
523 if (x_had_errors_p (display))
525 /* This error is perhaps due to insufficient memory on X server.
526 Let's just ignore it. */
527 x_clear_errors (display);
528 xfont = NULL;
530 fullname = Qnil;
531 /* Try to get the full name of FONT. */
532 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
534 char *p0, *p;
535 int dashes = 0;
537 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
538 /* Count the number of dashes in the "full name".
539 If it is too few, this isn't really the font's full name,
540 so don't use it.
541 In X11R4, the fonts did not come with their canonical names
542 stored in them. */
543 while (*p)
545 if (*p == '-')
546 dashes++;
547 p++;
550 if (dashes >= 13)
551 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
552 XFree (p0);
554 x_uncatch_errors ();
555 UNBLOCK_INPUT;
557 if (! xfont)
558 return Qnil;
560 font_object = font_make_object (VECSIZE (struct xfont_info));
561 ASET (font_object, FONT_TYPE_INDEX, Qx);
562 if (STRINGP (fullname))
563 font_parse_xlfd ((char *) SDATA (fullname), font_object);
564 for (i = 1; i < FONT_ENTITY_MAX; i++)
565 ASET (font_object, i, AREF (entity, i));
566 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
567 if (STRINGP (fullname))
568 ASET (font_object, FONT_NAME_INDEX, fullname);
569 else
570 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
571 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
572 ASET (font_object, FONT_FILE_INDEX, Qnil);
573 ASET (font_object, FONT_FORMAT_INDEX, Qx);
574 font = XFONT_OBJECT (font_object);
575 ((struct xfont_info *) font)->xfont = xfont;
576 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
577 font->pixel_size = pixel_size;
578 font->driver = &xfont_driver;
579 font->encoding_charset = encoding->id;
580 font->repertory_charset = repertory ? repertory->id : -1;
581 font->ascent = xfont->ascent;
582 font->descent = xfont->descent;
583 font->height = font->ascent + font->descent;
584 font->min_width = xfont->min_bounds.width;
585 if (xfont->min_bounds.width == xfont->max_bounds.width)
587 /* Fixed width font. */
588 font->average_width = font->space_width = xfont->min_bounds.width;
590 else
592 XCharStruct *pcm;
593 XChar2b char2b;
594 Lisp_Object val;
596 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
597 pcm = xfont_get_pcm (xfont, &char2b);
598 if (pcm)
599 font->space_width = pcm->width;
600 else
601 font->space_width = 0;
603 val = Ffont_get (font_object, QCavgwidth);
604 if (INTEGERP (val))
605 font->average_width = XINT (val);
606 if (font->average_width < 0)
607 font->average_width = - font->average_width;
608 if (font->average_width == 0
609 && encoding->ascii_compatible_p)
611 int width = font->space_width, n = pcm != NULL;
613 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
614 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
615 width += pcm->width, n++;
616 if (n > 0)
617 font->average_width = width / n;
619 if (font->average_width == 0)
620 /* No easy way other than this to get a reasonable
621 average_width. */
622 font->average_width
623 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
626 BLOCK_INPUT;
627 font->underline_thickness
628 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
629 ? (long) value : 0);
630 font->underline_position
631 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
632 ? (long) value : -1);
633 font->baseline_offset
634 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
635 ? (long) value : 0);
636 font->relative_compose
637 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
638 ? (long) value : 0);
639 font->default_ascent
640 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
641 ? (long) value : 0);
642 UNBLOCK_INPUT;
644 if (NILP (fullname))
645 fullname = AREF (font_object, FONT_NAME_INDEX);
646 font->vertical_centering
647 = (STRINGP (Vvertical_centering_font_regexp)
648 && (fast_string_match_ignore_case
649 (Vvertical_centering_font_regexp, fullname) >= 0));
651 return font_object;
654 static void
655 xfont_close (f, font)
656 FRAME_PTR f;
657 struct font *font;
659 BLOCK_INPUT;
660 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
661 UNBLOCK_INPUT;
664 static int
665 xfont_prepare_face (f, face)
666 FRAME_PTR f;
667 struct face *face;
669 BLOCK_INPUT;
670 XSetFont (FRAME_X_DISPLAY (f), face->gc,
671 ((struct xfont_info *) face->font)->xfont->fid);
672 UNBLOCK_INPUT;
674 return 0;
677 static int
678 xfont_has_char (entity, c)
679 Lisp_Object entity;
680 int c;
682 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
683 struct charset *repertory;
685 if (font_registry_charsets (registry, NULL, &repertory) < 0)
686 return -1;
687 if (! repertory)
688 return -1;
689 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
692 static unsigned
693 xfont_encode_char (font, c)
694 struct font *font;
695 int c;
697 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
698 struct charset *charset;
699 unsigned code;
700 XChar2b char2b;
702 charset = CHARSET_FROM_ID (font->encoding_charset);
703 code = ENCODE_CHAR (charset, c);
704 if (code == CHARSET_INVALID_CODE (charset))
705 return FONT_INVALID_CODE;
706 if (font->repertory_charset >= 0)
708 charset = CHARSET_FROM_ID (font->repertory_charset);
709 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
710 ? code : FONT_INVALID_CODE);
712 char2b.byte1 = code >> 8;
713 char2b.byte2 = code & 0xFF;
714 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
717 static int
718 xfont_text_extents (font, code, nglyphs, metrics)
719 struct font *font;
720 unsigned *code;
721 int nglyphs;
722 struct font_metrics *metrics;
724 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
725 int width = 0;
726 int i, x;
728 if (metrics)
729 bzero (metrics, sizeof (struct font_metrics));
730 for (i = 0, x = 0; i < nglyphs; i++)
732 XChar2b char2b;
733 static XCharStruct *pcm;
735 if (code[i] >= 0x10000)
736 continue;
737 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
738 pcm = xfont_get_pcm (xfont, &char2b);
739 if (! pcm)
740 continue;
741 if (metrics->lbearing > width + pcm->lbearing)
742 metrics->lbearing = width + pcm->lbearing;
743 if (metrics->rbearing < width + pcm->rbearing)
744 metrics->rbearing = width + pcm->rbearing;
745 if (metrics->ascent < pcm->ascent)
746 metrics->ascent = pcm->ascent;
747 if (metrics->descent < pcm->descent)
748 metrics->descent = pcm->descent;
749 width += pcm->width;
751 if (metrics)
752 metrics->width = width;
753 return width;
756 static int
757 xfont_draw (s, from, to, x, y, with_background)
758 struct glyph_string *s;
759 int from, to, x, y, with_background;
761 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
762 int len = to - from;
763 GC gc = s->gc;
764 int i;
766 if (s->gc != s->face->gc)
768 BLOCK_INPUT;
769 XSetFont (s->display, gc, xfont->fid);
770 UNBLOCK_INPUT;
773 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
775 char *str;
776 USE_SAFE_ALLOCA;
778 SAFE_ALLOCA (str, char *, len);
779 for (i = 0; i < len ; i++)
780 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
781 BLOCK_INPUT;
782 if (with_background > 0)
784 if (s->padding_p)
785 for (i = 0; i < len; i++)
786 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
787 gc, x + i, y, str + i, 1);
788 else
789 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
790 gc, x, y, str, len);
792 else
794 if (s->padding_p)
795 for (i = 0; i < len; i++)
796 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
797 gc, x + i, y, str + i, 1);
798 else
799 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
800 gc, x, y, str, len);
802 UNBLOCK_INPUT;
803 SAFE_FREE ();
804 return s->nchars;
807 BLOCK_INPUT;
808 if (with_background > 0)
810 if (s->padding_p)
811 for (i = 0; i < len; i++)
812 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
813 gc, x + i, y, s->char2b + from + i, 1);
814 else
815 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
816 gc, x, y, s->char2b + from, len);
818 else
820 if (s->padding_p)
821 for (i = 0; i < len; i++)
822 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
823 gc, x + i, y, s->char2b + from + i, 1);
824 else
825 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
826 gc, x, y, s->char2b + from, len);
828 UNBLOCK_INPUT;
830 return len;
833 static int
834 xfont_check (f, font)
835 FRAME_PTR f;
836 struct font *font;
838 struct xfont_info *xfont = (struct xfont_info *) font;
840 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
844 void
845 syms_of_xfont ()
847 xfont_driver.type = Qx;
848 register_font_driver (&xfont_driver, NULL);
851 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
852 (do not change this comment) */