*** empty log message ***
[emacs.git] / src / xfont.c
blob8e11d20408933940d65b76aaac53f366a49e1d06
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 = make_unibyte_string (p0, last_len);
477 if (NILP (Fassoc_string (family, list, Qt)))
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)
512 return Qnil;
514 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
515 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
516 else if (pixel_size == 0)
518 if (FRAME_FONT (f))
519 pixel_size = FRAME_FONT (f)->pixel_size;
520 else
521 pixel_size = 14;
523 len = font_unparse_xlfd (entity, pixel_size, name, 256);
524 if (len <= 0)
525 return Qnil;
527 BLOCK_INPUT;
528 x_catch_errors (display);
529 xfont = XLoadQueryFont (display, name);
530 if (x_had_errors_p (display))
532 /* This error is perhaps due to insufficient memory on X server.
533 Let's just ignore it. */
534 x_clear_errors (display);
535 xfont = NULL;
537 fullname = Qnil;
538 /* Try to get the full name of FONT. */
539 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
541 char *p0, *p;
542 int dashes = 0;
544 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
545 /* Count the number of dashes in the "full name".
546 If it is too few, this isn't really the font's full name,
547 so don't use it.
548 In X11R4, the fonts did not come with their canonical names
549 stored in them. */
550 while (*p)
552 if (*p == '-')
553 dashes++;
554 p++;
557 if (dashes >= 13)
558 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
559 XFree (p0);
561 x_uncatch_errors ();
562 UNBLOCK_INPUT;
564 if (! xfont)
565 return Qnil;
567 font_object = font_make_object (VECSIZE (struct xfont_info));
568 ASET (font_object, FONT_TYPE_INDEX, Qx);
569 if (STRINGP (fullname))
570 font_parse_xlfd ((char *) SDATA (fullname), font_object);
571 for (i = 1; i < FONT_ENTITY_MAX; i++)
572 ASET (font_object, i, AREF (entity, i));
573 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
574 if (STRINGP (fullname))
575 ASET (font_object, FONT_NAME_INDEX, fullname);
576 else
577 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
578 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
579 ASET (font_object, FONT_FILE_INDEX, Qnil);
580 ASET (font_object, FONT_FORMAT_INDEX, Qx);
581 font = XFONT_OBJECT (font_object);
582 ((struct xfont_info *) font)->xfont = xfont;
583 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
584 font->pixel_size = pixel_size;
585 font->driver = &xfont_driver;
586 font->encoding_charset = encoding->id;
587 font->repertory_charset = repertory ? repertory->id : -1;
588 font->ascent = xfont->ascent;
589 font->descent = xfont->descent;
590 font->height = font->ascent + font->descent;
591 font->min_width = xfont->min_bounds.width;
592 if (xfont->min_bounds.width == xfont->max_bounds.width)
594 /* Fixed width font. */
595 font->average_width = font->space_width = xfont->min_bounds.width;
597 else
599 XCharStruct *pcm;
600 XChar2b char2b;
601 Lisp_Object val;
603 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
604 pcm = xfont_get_pcm (xfont, &char2b);
605 if (pcm)
606 font->space_width = pcm->width;
607 else
608 font->space_width = 0;
610 val = Ffont_get (font_object, QCavgwidth);
611 if (INTEGERP (val))
612 font->average_width = XINT (val);
613 if (font->average_width < 0)
614 font->average_width = - font->average_width;
615 if (font->average_width == 0
616 && encoding->ascii_compatible_p)
618 int width = font->space_width, n = pcm != NULL;
620 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
621 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
622 width += pcm->width, n++;
623 if (n > 0)
624 font->average_width = width / n;
626 if (font->average_width == 0)
627 /* No easy way other than this to get a reasonable
628 average_width. */
629 font->average_width
630 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
633 BLOCK_INPUT;
634 font->underline_thickness
635 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
636 ? (long) value : 0);
637 font->underline_position
638 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
639 ? (long) value : -1);
640 font->baseline_offset
641 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
642 ? (long) value : 0);
643 font->relative_compose
644 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
645 ? (long) value : 0);
646 font->default_ascent
647 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
648 ? (long) value : 0);
649 UNBLOCK_INPUT;
651 if (NILP (fullname))
652 fullname = AREF (font_object, FONT_NAME_INDEX);
653 font->vertical_centering
654 = (STRINGP (Vvertical_centering_font_regexp)
655 && (fast_string_match_ignore_case
656 (Vvertical_centering_font_regexp, fullname) >= 0));
658 return font_object;
661 static void
662 xfont_close (f, font)
663 FRAME_PTR f;
664 struct font *font;
666 BLOCK_INPUT;
667 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
668 UNBLOCK_INPUT;
671 static int
672 xfont_prepare_face (f, face)
673 FRAME_PTR f;
674 struct face *face;
676 BLOCK_INPUT;
677 XSetFont (FRAME_X_DISPLAY (f), face->gc,
678 ((struct xfont_info *) face->font)->xfont->fid);
679 UNBLOCK_INPUT;
681 return 0;
684 static int
685 xfont_has_char (entity, c)
686 Lisp_Object entity;
687 int c;
689 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
690 struct charset *repertory;
692 if (font_registry_charsets (registry, NULL, &repertory) < 0)
693 return -1;
694 if (! repertory)
695 return -1;
696 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
699 static unsigned
700 xfont_encode_char (font, c)
701 struct font *font;
702 int c;
704 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
705 struct charset *charset;
706 unsigned code;
707 XChar2b char2b;
709 charset = CHARSET_FROM_ID (font->encoding_charset);
710 code = ENCODE_CHAR (charset, c);
711 if (code == CHARSET_INVALID_CODE (charset))
712 return FONT_INVALID_CODE;
713 if (font->repertory_charset >= 0)
715 charset = CHARSET_FROM_ID (font->repertory_charset);
716 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
717 ? code : FONT_INVALID_CODE);
719 char2b.byte1 = code >> 8;
720 char2b.byte2 = code & 0xFF;
721 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
724 static int
725 xfont_text_extents (font, code, nglyphs, metrics)
726 struct font *font;
727 unsigned *code;
728 int nglyphs;
729 struct font_metrics *metrics;
731 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
732 int width = 0;
733 int i, x;
735 if (metrics)
736 bzero (metrics, sizeof (struct font_metrics));
737 for (i = 0, x = 0; i < nglyphs; i++)
739 XChar2b char2b;
740 static XCharStruct *pcm;
742 if (code[i] >= 0x10000)
743 continue;
744 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
745 pcm = xfont_get_pcm (xfont, &char2b);
746 if (! pcm)
747 continue;
748 if (metrics->lbearing > width + pcm->lbearing)
749 metrics->lbearing = width + pcm->lbearing;
750 if (metrics->rbearing < width + pcm->rbearing)
751 metrics->rbearing = width + pcm->rbearing;
752 if (metrics->ascent < pcm->ascent)
753 metrics->ascent = pcm->ascent;
754 if (metrics->descent < pcm->descent)
755 metrics->descent = pcm->descent;
756 width += pcm->width;
758 if (metrics)
759 metrics->width = width;
760 return width;
763 static int
764 xfont_draw (s, from, to, x, y, with_background)
765 struct glyph_string *s;
766 int from, to, x, y, with_background;
768 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
769 int len = to - from;
770 GC gc = s->gc;
771 int i;
773 if (s->gc != s->face->gc)
775 BLOCK_INPUT;
776 XSetFont (s->display, gc, xfont->fid);
777 UNBLOCK_INPUT;
780 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
782 char *str;
783 USE_SAFE_ALLOCA;
785 SAFE_ALLOCA (str, char *, len);
786 for (i = 0; i < len ; i++)
787 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
788 BLOCK_INPUT;
789 if (with_background > 0)
791 if (s->padding_p)
792 for (i = 0; i < len; i++)
793 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
794 gc, x + i, y, str + i, 1);
795 else
796 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
797 gc, x, y, str, len);
799 else
801 if (s->padding_p)
802 for (i = 0; i < len; i++)
803 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
804 gc, x + i, y, str + i, 1);
805 else
806 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
807 gc, x, y, str, len);
809 UNBLOCK_INPUT;
810 SAFE_FREE ();
811 return s->nchars;
814 BLOCK_INPUT;
815 if (with_background > 0)
817 if (s->padding_p)
818 for (i = 0; i < len; i++)
819 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
820 gc, x + i, y, s->char2b + from + i, 1);
821 else
822 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
823 gc, x, y, s->char2b + from, len);
825 else
827 if (s->padding_p)
828 for (i = 0; i < len; i++)
829 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
830 gc, x + i, y, s->char2b + from + i, 1);
831 else
832 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
833 gc, x, y, s->char2b + from, len);
835 UNBLOCK_INPUT;
837 return len;
840 static int
841 xfont_check (f, font)
842 FRAME_PTR f;
843 struct font *font;
845 struct xfont_info *xfont = (struct xfont_info *) font;
847 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
851 void
852 syms_of_xfont ()
854 xfont_driver.type = Qx;
855 register_font_driver (&xfont_driver, NULL);
858 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
859 (do not change this comment) */