(top-level): Don't require cl when compiling.
[emacs.git] / src / xfont.c
blob3a49d7246d3441a89ab29d82c03dcc7f998cca98
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 *));
53 static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **,
54 struct charset **));
57 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
58 is not contained in the font. */
60 static XCharStruct *
61 xfont_get_pcm (xfont, char2b)
62 XFontStruct *xfont;
63 XChar2b *char2b;
65 /* The result metric information. */
66 XCharStruct *pcm = NULL;
68 xassert (xfont && char2b);
70 if (xfont->per_char != NULL)
72 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
74 /* min_char_or_byte2 specifies the linear character index
75 corresponding to the first element of the per_char array,
76 max_char_or_byte2 is the index of the last character. A
77 character with non-zero CHAR2B->byte1 is not in the font.
78 A character with byte2 less than min_char_or_byte2 or
79 greater max_char_or_byte2 is not in the font. */
80 if (char2b->byte1 == 0
81 && char2b->byte2 >= xfont->min_char_or_byte2
82 && char2b->byte2 <= xfont->max_char_or_byte2)
83 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
85 else
87 /* If either min_byte1 or max_byte1 are nonzero, both
88 min_char_or_byte2 and max_char_or_byte2 are less than
89 256, and the 2-byte character index values corresponding
90 to the per_char array element N (counting from 0) are:
92 byte1 = N/D + min_byte1
93 byte2 = N\D + min_char_or_byte2
95 where:
97 D = max_char_or_byte2 - min_char_or_byte2 + 1
98 / = integer division
99 \ = integer modulus */
100 if (char2b->byte1 >= xfont->min_byte1
101 && char2b->byte1 <= xfont->max_byte1
102 && char2b->byte2 >= xfont->min_char_or_byte2
103 && char2b->byte2 <= xfont->max_char_or_byte2)
104 pcm = (xfont->per_char
105 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
106 * (char2b->byte1 - xfont->min_byte1))
107 + (char2b->byte2 - xfont->min_char_or_byte2));
110 else
112 /* If the per_char pointer is null, all glyphs between the first
113 and last character indexes inclusive have the same
114 information, as given by both min_bounds and max_bounds. */
115 if (char2b->byte2 >= xfont->min_char_or_byte2
116 && char2b->byte2 <= xfont->max_char_or_byte2)
117 pcm = &xfont->max_bounds;
120 return ((pcm == NULL
121 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
122 ? NULL : pcm);
125 /* Find a CCL program for a font specified by FONTP, and set the member
126 `encoder' of the structure. */
128 static void
129 xfont_find_ccl_program (font)
130 struct font *font;
132 Lisp_Object list, elt;
134 elt = Qnil;
135 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
137 elt = XCAR (list);
138 if (CONSP (elt)
139 && STRINGP (XCAR (elt))
140 && ((fast_string_match_ignore_case (XCAR (elt),
141 font->props[FONT_NAME_INDEX])
142 >= 0)
143 || (fast_string_match_ignore_case (XCAR (elt),
144 font->props[FONT_FULLNAME_INDEX])
145 >= 0)))
146 break;
149 if (! NILP (list))
151 struct ccl_program *ccl
152 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
154 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
155 xfree (ccl);
156 else
157 font->font_encoder = ccl;
161 static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
162 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
163 static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
164 static Lisp_Object xfont_list_family P_ ((Lisp_Object));
165 static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
166 static void xfont_close P_ ((FRAME_PTR, struct font *));
167 static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
168 static int xfont_has_char P_ ((Lisp_Object, int));
169 static unsigned xfont_encode_char P_ ((struct font *, int));
170 static int xfont_text_extents P_ ((struct font *, unsigned *, int,
171 struct font_metrics *));
172 static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
173 static int xfont_check P_ ((FRAME_PTR, struct font *));
175 struct font_driver xfont_driver =
177 0, /* Qx */
178 0, /* case insensitive */
179 xfont_get_cache,
180 xfont_list,
181 xfont_match,
182 xfont_list_family,
183 NULL,
184 xfont_open,
185 xfont_close,
186 xfont_prepare_face,
187 NULL,
188 xfont_has_char,
189 xfont_encode_char,
190 xfont_text_extents,
191 xfont_draw,
192 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
193 xfont_check
196 extern Lisp_Object QCname;
198 static Lisp_Object
199 xfont_get_cache (f)
200 FRAME_PTR f;
202 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
204 return (dpyinfo->name_list_element);
207 extern Lisp_Object Vface_alternative_font_registry_alist;
209 static int
210 compare_font_names (const void *name1, const void *name2)
212 return strcasecmp (*(const char **) name1, *(const char **) name2);
215 static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
217 static Lisp_Object
218 xfont_list_pattern (frame, display, pattern)
219 Lisp_Object frame;
220 Display *display;
221 char *pattern;
223 Lisp_Object list = Qnil;
224 int i, limit, num_fonts;
225 char **names;
227 BLOCK_INPUT;
228 x_catch_errors (display);
230 for (limit = 512; ; limit *= 2)
232 names = XListFonts (display, pattern, limit, &num_fonts);
233 if (x_had_errors_p (display))
235 /* This error is perhaps due to insufficient memory on X
236 server. Let's just ignore it. */
237 x_clear_errors (display);
238 num_fonts = 0;
239 break;
241 if (num_fonts < limit)
242 break;
243 XFreeFontNames (names);
246 if (num_fonts > 0)
248 char **indices = alloca (sizeof (char *) * num_fonts);
250 for (i = 0; i < num_fonts; i++)
251 indices[i] = names[i];
252 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
254 for (i = 0; i < num_fonts; i++)
256 Lisp_Object entity;
257 int result;
259 if (i > 0 && strcasecmp (indices[i - 1], indices[i]) == 0)
260 continue;
262 entity = font_make_entity ();
263 ASET (entity, FONT_TYPE_INDEX, Qx);
265 result = font_parse_xlfd (indices[i], entity);
266 if (result < 0)
268 /* This may be an alias name. Try to get the full XLFD name
269 from XA_FONT property of the font. */
270 XFontStruct *font = XLoadQueryFont (display, indices[i]);
271 unsigned long value;
273 if (! font)
274 continue;
275 if (XGetFontProperty (font, XA_FONT, &value))
277 char *name = (char *) XGetAtomName (display, (Atom) value);
278 int len = strlen (name);
280 /* If DXPC (a Differential X Protocol Compressor)
281 Ver.3.7 is running, XGetAtomName will return null
282 string. We must avoid such a name. */
283 if (len > 0)
284 result = font_parse_xlfd (name, entity);
285 XFree (name);
287 XFreeFont (display, font);
290 if (result == 0
291 /* Avoid auto-scaled fonts. */
292 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
293 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
294 list = Fcons (entity, list);
298 x_uncatch_errors ();
299 UNBLOCK_INPUT;
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, font_name;
311 Lisp_Object dpi, avgwidth;
312 int len;
313 char name[256];
315 extra = AREF (spec, FONT_EXTRA_INDEX);
316 if (CONSP (extra))
318 val = assq_no_quit (QCotf, extra);
319 if (! NILP (val))
320 return Qnil;
321 val = assq_no_quit (QCscript, extra);
322 if (! NILP (val))
323 return Qnil;
324 val = assq_no_quit (QClang, extra);
325 if (! NILP (val))
326 return Qnil;
329 registry = AREF (spec, FONT_REGISTRY_INDEX);
330 if (NILP (registry))
331 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
332 len = font_unparse_xlfd (spec, 0, name, 256);
333 ASET (spec, FONT_REGISTRY_INDEX, registry);
334 if (len < 0)
335 return Qnil;
336 list = xfont_list_pattern (frame, display, name);
337 if (NILP (list) && NILP (registry))
339 /* Try iso10646-1 */
340 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
342 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
344 strcpy (r, "iso10646-1");
345 list = xfont_list_pattern (frame, display, name);
348 if (NILP (list) && ! NILP (registry))
350 Lisp_Object alter;
352 if ((alter = Fassoc (SYMBOL_NAME (registry),
353 Vface_alternative_font_registry_alist),
354 CONSP (alter)))
356 /* Pointer to REGISTRY-ENCODING field. */
357 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
359 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
360 if (STRINGP (XCAR (alter))
361 && ((r - name) + SBYTES (XCAR (alter))) < 256)
363 strcpy (r, (char *) SDATA (XCAR (alter)));
364 list = xfont_list_pattern (frame, display, name);
365 if (! NILP (list))
366 break;
371 return list;
374 static Lisp_Object
375 xfont_match (frame, spec)
376 Lisp_Object frame, spec;
378 FRAME_PTR f = XFRAME (frame);
379 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
380 Lisp_Object extra, val, entity;
381 char buf[256], *name;
382 XFontStruct *xfont;
383 unsigned long value;
385 extra = AREF (spec, FONT_EXTRA_INDEX);
386 val = assq_no_quit (QCname, extra);
387 if (! CONSP (val) || ! STRINGP (XCDR (val)))
389 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
390 return Qnil;
391 name = buf;
393 else
394 name = (char *) SDATA (XCDR (val));
396 BLOCK_INPUT;
397 entity = Qnil;
398 xfont = XLoadQueryFont (display, name);
399 if (xfont)
401 if (XGetFontProperty (xfont, XA_FONT, &value))
403 int len;
405 name = (char *) XGetAtomName (display, (Atom) value);
406 len = strlen (name);
408 /* If DXPC (a Differential X Protocol Compressor)
409 Ver.3.7 is running, XGetAtomName will return null
410 string. We must avoid such a name. */
411 if (len > 0)
413 entity = font_make_entity ();
414 ASET (entity, FONT_TYPE_INDEX, Qx);
415 if (font_parse_xlfd (name, entity) < 0)
416 entity = Qnil;
418 XFree (name);
420 XFreeFont (display, xfont);
422 UNBLOCK_INPUT;
424 return entity;
427 static int
428 memq_no_quit (elt, list)
429 Lisp_Object elt, list;
431 while (CONSP (list) && ! EQ (XCAR (list), elt))
432 list = XCDR (list);
433 return (CONSP (list));
436 static Lisp_Object
437 xfont_list_family (frame)
438 Lisp_Object frame;
440 FRAME_PTR f = XFRAME (frame);
441 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
442 char **names;
443 int num_fonts, i;
444 Lisp_Object list;
445 char *last_family;
446 int last_len;
448 BLOCK_INPUT;
449 x_catch_errors (dpyinfo->display);
450 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
451 0x8000, &num_fonts);
452 if (x_had_errors_p (dpyinfo->display))
454 /* This error is perhaps due to insufficient memory on X server.
455 Let's just ignore it. */
456 x_clear_errors (dpyinfo->display);
457 num_fonts = 0;
460 list = Qnil;
461 for (i = 0, last_len = 0; i < num_fonts; i++)
463 char *p0 = names[i], *p1;
464 Lisp_Object family;
466 p0++; /* skip the leading '-' */
467 while (*p0 && *p0 != '-') p0++; /* skip foundry */
468 if (! *p0)
469 continue;
470 p1 = ++p0;
471 while (*p1 && *p1 != '-') p1++; /* find the end of family */
472 if (! *p1 || p1 == p0)
473 continue;
474 if (last_len == p1 - p0
475 && bcmp (last_family, p0, last_len) == 0)
476 continue;
477 last_len = p1 - p0;
478 last_family = p0;
479 family = make_unibyte_string (p0, last_len);
480 if (NILP (Fassoc_string (family, list, Qt)))
481 list = Fcons (family, list);
484 XFreeFontNames (names);
485 x_uncatch_errors ();
486 UNBLOCK_INPUT;
488 return list;
491 extern Lisp_Object QCavgwidth;
493 static Lisp_Object
494 xfont_open (f, entity, pixel_size)
495 FRAME_PTR f;
496 Lisp_Object entity;
497 int pixel_size;
499 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
500 Display *display = dpyinfo->display;
501 char name[256];
502 int len;
503 unsigned long value;
504 Lisp_Object registry;
505 struct charset *encoding, *repertory;
506 Lisp_Object font_object, fullname;
507 struct font *font;
508 XFontStruct *xfont;
509 int i;
511 /* At first, check if we know how to encode characters for this
512 font. */
513 registry = AREF (entity, FONT_REGISTRY_INDEX);
514 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
515 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)
528 return Qnil;
530 BLOCK_INPUT;
531 x_catch_errors (display);
532 xfont = XLoadQueryFont (display, name);
533 if (x_had_errors_p (display))
535 /* This error is perhaps due to insufficient memory on X server.
536 Let's just ignore it. */
537 x_clear_errors (display);
538 xfont = NULL;
540 fullname = Qnil;
541 /* Try to get the full name of FONT. */
542 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
544 char *p0, *p;
545 int dashes = 0;
547 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
548 /* Count the number of dashes in the "full name".
549 If it is too few, this isn't really the font's full name,
550 so don't use it.
551 In X11R4, the fonts did not come with their canonical names
552 stored in them. */
553 while (*p)
555 if (*p == '-')
556 dashes++;
557 p++;
560 if (dashes >= 13)
561 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
562 XFree (p0);
564 x_uncatch_errors ();
565 UNBLOCK_INPUT;
567 if (! xfont)
568 return Qnil;
570 font_object = font_make_object (VECSIZE (struct xfont_info));
571 ASET (font_object, FONT_TYPE_INDEX, Qx);
572 if (STRINGP (fullname))
573 font_parse_xlfd (SDATA (fullname), font_object);
574 for (i = 1; i < FONT_ENTITY_MAX; i++)
575 ASET (font_object, i, AREF (entity, i));
576 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
577 if (STRINGP (fullname))
578 ASET (font_object, FONT_NAME_INDEX, fullname);
579 else
580 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
581 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
582 ASET (font_object, FONT_FILE_INDEX, Qnil);
583 ASET (font_object, FONT_FORMAT_INDEX, Qx);
584 font = XFONT_OBJECT (font_object);
585 ((struct xfont_info *) font)->xfont = xfont;
586 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
587 font->pixel_size = pixel_size;
588 font->driver = &xfont_driver;
589 font->encoding_charset = encoding->id;
590 font->repertory_charset = repertory ? repertory->id : -1;
591 font->ascent = xfont->ascent;
592 font->descent = xfont->descent;
593 font->height = font->ascent + font->descent;
594 font->min_width = xfont->min_bounds.width;
595 if (xfont->min_bounds.width == xfont->max_bounds.width)
597 /* Fixed width font. */
598 font->average_width = font->space_width = xfont->min_bounds.width;
600 else
602 XCharStruct *pcm;
603 XChar2b char2b;
604 Lisp_Object val;
606 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
607 pcm = xfont_get_pcm (xfont, &char2b);
608 if (pcm)
609 font->space_width = pcm->width;
610 else
611 font->space_width = 0;
613 val = Ffont_get (font_object, QCavgwidth);
614 if (INTEGERP (val))
615 font->average_width = XINT (val);
616 if (font->average_width < 0)
617 font->average_width = - font->average_width;
618 if (font->average_width == 0
619 && encoding->ascii_compatible_p)
621 int width = font->space_width, n = pcm != NULL;
623 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
624 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
625 width += pcm->width, n++;
626 font->average_width = width / n;
630 BLOCK_INPUT;
631 font->underline_thickness
632 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
633 ? (long) value : 0);
634 font->underline_position
635 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
636 ? (long) value : -1);
637 font->baseline_offset
638 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
639 ? (long) value : 0);
640 font->relative_compose
641 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
642 ? (long) value : 0);
643 font->default_ascent
644 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
645 ? (long) value : 0);
646 UNBLOCK_INPUT;
648 if (NILP (fullname))
649 fullname = AREF (font_object, FONT_NAME_INDEX);
650 font->vertical_centering
651 = (STRINGP (Vvertical_centering_font_regexp)
652 && (fast_string_match_ignore_case
653 (Vvertical_centering_font_regexp, fullname) >= 0));
655 return font_object;
658 static void
659 xfont_close (f, font)
660 FRAME_PTR f;
661 struct font *font;
663 BLOCK_INPUT;
664 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
665 UNBLOCK_INPUT;
668 static int
669 xfont_prepare_face (f, face)
670 FRAME_PTR f;
671 struct face *face;
673 BLOCK_INPUT;
674 XSetFont (FRAME_X_DISPLAY (f), face->gc,
675 ((struct xfont_info *) face->font)->xfont->fid);
676 UNBLOCK_INPUT;
678 return 0;
681 static int
682 xfont_has_char (entity, c)
683 Lisp_Object entity;
684 int c;
686 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
687 struct charset *repertory;
689 if (font_registry_charsets (registry, NULL, &repertory) < 0)
690 return -1;
691 if (! repertory)
692 return -1;
693 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
696 static unsigned
697 xfont_encode_char (font, c)
698 struct font *font;
699 int c;
701 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
702 struct charset *charset;
703 unsigned code;
704 XChar2b char2b;
706 charset = CHARSET_FROM_ID (font->encoding_charset);
707 code = ENCODE_CHAR (charset, c);
708 if (code == CHARSET_INVALID_CODE (charset))
709 return FONT_INVALID_CODE;
710 if (font->repertory_charset >= 0)
712 charset = CHARSET_FROM_ID (font->repertory_charset);
713 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
714 ? code : FONT_INVALID_CODE);
716 char2b.byte1 = code >> 8;
717 char2b.byte2 = code & 0xFF;
718 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
721 static int
722 xfont_text_extents (font, code, nglyphs, metrics)
723 struct font *font;
724 unsigned *code;
725 int nglyphs;
726 struct font_metrics *metrics;
728 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
729 int width = 0;
730 int i, x;
732 if (metrics)
733 bzero (metrics, sizeof (struct font_metrics));
734 for (i = 0, x = 0; i < nglyphs; i++)
736 XChar2b char2b;
737 static XCharStruct *pcm;
739 if (code[i] >= 0x10000)
740 continue;
741 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
742 pcm = xfont_get_pcm (xfont, &char2b);
743 if (! pcm)
744 continue;
745 if (metrics->lbearing > width + pcm->lbearing)
746 metrics->lbearing = width + pcm->lbearing;
747 if (metrics->rbearing < width + pcm->rbearing)
748 metrics->rbearing = width + pcm->rbearing;
749 if (metrics->ascent < pcm->ascent)
750 metrics->ascent = pcm->ascent;
751 if (metrics->descent < pcm->descent)
752 metrics->descent = pcm->descent;
753 width += pcm->width;
755 if (metrics)
756 metrics->width = width;
757 return width;
760 static int
761 xfont_draw (s, from, to, x, y, with_background)
762 struct glyph_string *s;
763 int from, to, x, y, with_background;
765 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
766 int len = to - from;
767 GC gc = s->gc;
768 int i;
770 if (s->gc != s->face->gc)
772 BLOCK_INPUT;
773 XSetFont (s->display, gc, xfont->fid);
774 UNBLOCK_INPUT;
777 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
779 char *str;
780 USE_SAFE_ALLOCA;
782 SAFE_ALLOCA (str, char *, len);
783 for (i = 0; i < len ; i++)
784 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
785 BLOCK_INPUT;
786 if (with_background > 0)
788 if (s->padding_p)
789 for (i = 0; i < len; i++)
790 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
791 gc, x + i, y, str + i, 1);
792 else
793 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
794 gc, x, y, str, len);
796 else
798 if (s->padding_p)
799 for (i = 0; i < len; i++)
800 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
801 gc, x + i, y, str + i, 1);
802 else
803 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
804 gc, x, y, str, len);
806 UNBLOCK_INPUT;
807 SAFE_FREE ();
808 return s->nchars;
811 BLOCK_INPUT;
812 if (with_background > 0)
814 if (s->padding_p)
815 for (i = 0; i < len; i++)
816 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
817 gc, x + i, y, s->char2b + from + i, 1);
818 else
819 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
820 gc, x, y, s->char2b + from, len);
822 else
824 if (s->padding_p)
825 for (i = 0; i < len; i++)
826 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
827 gc, x + i, y, s->char2b + from + i, 1);
828 else
829 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
830 gc, x, y, s->char2b + from, len);
832 UNBLOCK_INPUT;
834 return len;
837 static int
838 xfont_check (f, font)
839 FRAME_PTR f;
840 struct font *font;
842 struct xfont_info *xfont = (struct xfont_info *) font;
844 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
848 void
849 syms_of_xfont ()
851 xfont_driver.type = Qx;
852 register_font_driver (&xfont_driver, NULL);
855 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
856 (do not change this comment) */