(x_set_cursor_gc): Use display_info->font->fid for GCs.
[bpt/emacs.git] / src / xfont.c
CommitLineData
c2f5bfd6 1/* xfont.c -- X core font driver.
77ad4cfe
GM
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
c2f5bfd6
KH
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7This file is part of GNU Emacs.
8
9GNU Emacs is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
77ad4cfe 11the Free Software Foundation; either version 3, or (at your option)
c2f5bfd6
KH
12any later version.
13
14GNU Emacs is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU Emacs; see the file COPYING. If not, write to
21the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22Boston, MA 02110-1301, USA. */
23
24#include <config.h>
25#include <stdio.h>
26#include <X11/Xlib.h>
27
28#include "lisp.h"
29#include "dispextern.h"
30#include "xterm.h"
31#include "frame.h"
32#include "blockinput.h"
33#include "character.h"
34#include "charset.h"
35#include "fontset.h"
36#include "font.h"
37
38\f
39/* X core font driver. */
40
c2f5bfd6
KH
41/* Prototypes of support functions. */
42extern void x_clear_errors P_ ((Display *));
43
44static char *xfont_query_font P_ ((Display *, char *, Lisp_Object));
45static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
46static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **,
47 struct charset **));
48
49static char *
50xfont_query_font (display, name, spec)
51 Display *display;
52 char *name;
53 Lisp_Object spec;
54{
55 XFontStruct *font;
56
57 BLOCK_INPUT;
58 x_catch_errors (display);
59 font = XLoadQueryFont (display, name);
60 name = NULL;
61 if (x_had_errors_p (display))
62 {
63 /* This error is perhaps due to insufficient memory on X
64 server. Let's just ignore it. */
65 x_clear_errors (display);
66 }
67 else if (font)
68 {
69 unsigned long value;
70
71 if (XGetFontProperty (font, XA_FONT, &value))
72 {
73 char *n = (char *) XGetAtomName (display, (Atom) value);
74
6c4aeab6 75 if (font_parse_xlfd (n, spec) >= 0)
c2f5bfd6
KH
76 name = n;
77 else
78 XFree (n);
79 }
80 XFreeFont (display, font);
81 }
82 x_uncatch_errors ();
83 UNBLOCK_INPUT;
84
85 return name;
86}
87
88
89/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
90 is not contained in the font. */
91
92static XCharStruct *
93xfont_get_pcm (xfont, char2b)
94 XFontStruct *xfont;
95 XChar2b *char2b;
96{
97 /* The result metric information. */
98 XCharStruct *pcm = NULL;
99
100 xassert (xfont && char2b);
101
102 if (xfont->per_char != NULL)
103 {
104 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
105 {
106 /* min_char_or_byte2 specifies the linear character index
107 corresponding to the first element of the per_char array,
108 max_char_or_byte2 is the index of the last character. A
109 character with non-zero CHAR2B->byte1 is not in the font.
110 A character with byte2 less than min_char_or_byte2 or
111 greater max_char_or_byte2 is not in the font. */
112 if (char2b->byte1 == 0
113 && char2b->byte2 >= xfont->min_char_or_byte2
114 && char2b->byte2 <= xfont->max_char_or_byte2)
115 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
116 }
117 else
118 {
119 /* If either min_byte1 or max_byte1 are nonzero, both
120 min_char_or_byte2 and max_char_or_byte2 are less than
121 256, and the 2-byte character index values corresponding
122 to the per_char array element N (counting from 0) are:
123
124 byte1 = N/D + min_byte1
125 byte2 = N\D + min_char_or_byte2
126
127 where:
128
129 D = max_char_or_byte2 - min_char_or_byte2 + 1
130 / = integer division
131 \ = integer modulus */
132 if (char2b->byte1 >= xfont->min_byte1
133 && char2b->byte1 <= xfont->max_byte1
134 && char2b->byte2 >= xfont->min_char_or_byte2
135 && char2b->byte2 <= xfont->max_char_or_byte2)
136 pcm = (xfont->per_char
137 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
138 * (char2b->byte1 - xfont->min_byte1))
139 + (char2b->byte2 - xfont->min_char_or_byte2));
140 }
141 }
142 else
143 {
144 /* If the per_char pointer is null, all glyphs between the first
145 and last character indexes inclusive have the same
146 information, as given by both min_bounds and max_bounds. */
147 if (char2b->byte2 >= xfont->min_char_or_byte2
148 && char2b->byte2 <= xfont->max_char_or_byte2)
149 pcm = &xfont->max_bounds;
150 }
151
152 return ((pcm == NULL
153 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
154 ? NULL : pcm);
155}
156
feb2737b 157static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
c2f5bfd6 158static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
6e34c9c1 159static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6
KH
160static Lisp_Object xfont_list_family P_ ((Lisp_Object));
161static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
162static void xfont_close P_ ((FRAME_PTR, struct font *));
163static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
164#if 0
165static void xfont_done_face P_ ((FRAME_PTR, struct face *));
166#endif
167static int xfont_has_char P_ ((Lisp_Object, int));
168static unsigned xfont_encode_char P_ ((struct font *, int));
169static int xfont_text_extents P_ ((struct font *, unsigned *, int,
170 struct font_metrics *));
171static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
172
173struct font_driver xfont_driver =
174 {
575abfb7 175 0, /* Qx */
c2f5bfd6 176 xfont_get_cache,
c2f5bfd6 177 xfont_list,
6e34c9c1 178 xfont_match,
c2f5bfd6
KH
179 xfont_list_family,
180 NULL,
181 xfont_open,
182 xfont_close,
183 xfont_prepare_face,
184 NULL /*xfont_done_face*/,
185 xfont_has_char,
186 xfont_encode_char,
187 xfont_text_extents,
feb2737b 188 xfont_draw
c2f5bfd6
KH
189 };
190
191extern Lisp_Object QCname;
192
193static Lisp_Object
feb2737b
KH
194xfont_get_cache (f)
195 FRAME_PTR f;
c2f5bfd6 196{
feb2737b 197 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
198
199 return (dpyinfo->name_list_element);
200}
201
c2f5bfd6
KH
202extern Lisp_Object Vface_alternative_font_registry_alist;
203
204static Lisp_Object
6c4aeab6
KH
205xfont_list_pattern (frame, display, pattern)
206 Lisp_Object frame;
207 Display *display;
208 char *pattern;
c2f5bfd6 209{
6c4aeab6
KH
210 Lisp_Object list = Qnil;
211 int i, limit, num_fonts;
212 char **names;
c2f5bfd6
KH
213
214 BLOCK_INPUT;
6c4aeab6 215 x_catch_errors (display);
c2f5bfd6 216
6c4aeab6 217 for (limit = 512; ; limit *= 2)
c2f5bfd6 218 {
6c4aeab6
KH
219 names = XListFonts (display, pattern, limit, &num_fonts);
220 if (x_had_errors_p (display))
c2f5bfd6
KH
221 {
222 /* This error is perhaps due to insufficient memory on X
223 server. Let's just ignore it. */
6c4aeab6
KH
224 x_clear_errors (display);
225 num_fonts = 0;
226 break;
c2f5bfd6 227 }
6c4aeab6
KH
228 if (num_fonts < limit)
229 break;
230 XFreeFontNames (names);
231 }
232
233 for (i = 0; i < num_fonts; i++)
234 {
235 Lisp_Object entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
236 int result;
237
238 ASET (entity, FONT_TYPE_INDEX, Qx);
239 ASET (entity, FONT_FRAME_INDEX, frame);
240
241 result = font_parse_xlfd (names[i], entity);
242 if (result < 0)
c2f5bfd6 243 {
6c4aeab6
KH
244 /* This may be an alias name. Try to get the full XLFD name
245 from XA_FONT property of the font. */
246 XFontStruct *font = XLoadQueryFont (display, names[i]);
247 unsigned long value;
248
249 if (! font)
250 continue;
c2f5bfd6
KH
251 if (XGetFontProperty (font, XA_FONT, &value))
252 {
6c4aeab6
KH
253 char *name = (char *) XGetAtomName (display, (Atom) value);
254 int len = strlen (name);
c2f5bfd6
KH
255
256 /* If DXPC (a Differential X Protocol Compressor)
257 Ver.3.7 is running, XGetAtomName will return null
258 string. We must avoid such a name. */
259 if (len > 0)
6c4aeab6
KH
260 result = font_parse_xlfd (name, entity);
261 XFree (name);
c2f5bfd6 262 }
6c4aeab6 263 XFreeFont (display, font);
c2f5bfd6 264 }
6c4aeab6
KH
265
266 if (result == 0)
c2f5bfd6 267 {
6c4aeab6
KH
268 Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX);
269 char *p = (char *) SDATA (SYMBOL_NAME (val));
270
271 /* P == "RESX-RESY-SPACING-AVGWIDTH. We rejust this font if
272 it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0). */
273 if (atoi (p) > 0)
c2f5bfd6 274 {
6c4aeab6
KH
275 p += SBYTES (SYMBOL_NAME (val));
276 while (p[-1] != '-') p--;
277 if (atoi (p) == 0)
278 continue;
c2f5bfd6 279 }
6c4aeab6 280 list = Fcons (entity, list);
c2f5bfd6
KH
281 }
282 }
283
284 x_uncatch_errors ();
285 UNBLOCK_INPUT;
286
6c4aeab6
KH
287 return list;
288}
c2f5bfd6 289
6c4aeab6
KH
290static Lisp_Object
291xfont_list (frame, spec)
292 Lisp_Object frame, spec;
293{
294 FRAME_PTR f = XFRAME (frame);
295 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
296 Lisp_Object list, val, extra, font_name;
297 int len;
298 char name[256];
299
300 extra = AREF (spec, FONT_EXTRA_INDEX);
301 font_name = Qnil;
302 if (CONSP (extra))
c2f5bfd6 303 {
6c4aeab6
KH
304 val = assq_no_quit (QCotf, extra);
305 if (! NILP (val))
306 return null_vector;
307 val = assq_no_quit (QCscript, extra);
308 if (! NILP (val))
309 return null_vector;
310 val = assq_no_quit (QClanguage, extra);
311 if (! NILP (val))
312 return null_vector;
313 val = assq_no_quit (QCname, extra);
314 if (CONSP (val))
315 font_name = XCDR (val);
c2f5bfd6 316 }
6c4aeab6 317
1f221e7a
KH
318 if (STRINGP (font_name)
319 && ! strchr ((char *) SDATA (font_name), ':'))
6c4aeab6
KH
320 list = xfont_list_pattern (frame, display, (char *) SDATA (font_name));
321 else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0)
322 return null_vector;
323 else
c2f5bfd6 324 {
6c4aeab6
KH
325 list = xfont_list_pattern (frame, display, name);
326 if (NILP (list))
327 {
328 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
329 Lisp_Object alter;
330
331 if (! NILP (registry)
332 && (alter = Fassoc (SYMBOL_NAME (registry),
575abfb7
KH
333 Vface_alternative_font_registry_alist),
334 CONSP (alter)))
6c4aeab6
KH
335 {
336 /* Pointer to REGISTRY-ENCODING field. */
337 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
338
339 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
340 if (STRINGP (XCAR (alter))
341 && ((r - name) + SBYTES (XCAR (alter))) < 255)
342 {
343 strcpy (r, (char *) SDATA (XCAR (alter)));
344 list = xfont_list_pattern (frame, display, name);
345 if (! NILP (list))
346 break;
347 }
348 }
349 }
c2f5bfd6 350 }
c2f5bfd6 351
6c4aeab6 352 return (NILP (list) ? null_vector : Fvconcat (1, &list));
c2f5bfd6
KH
353}
354
6e34c9c1
KH
355static Lisp_Object
356xfont_match (frame, spec)
357 Lisp_Object frame, spec;
358{
359 FRAME_PTR f = XFRAME (frame);
360 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
361 Lisp_Object extra, val, entity;
362 char *name;
363 XFontStruct *xfont;
364 unsigned long value;
365
366 extra = AREF (spec, FONT_EXTRA_INDEX);
367 val = assq_no_quit (QCname, extra);
368 if (! CONSP (val) || ! STRINGP (XCDR (val)))
369 return Qnil;
370
9c6d1df5 371 BLOCK_INPUT;
6e34c9c1
KH
372 entity = Qnil;
373 name = (char *) SDATA (XCDR (val));
374 xfont = XLoadQueryFont (display, name);
375 if (xfont)
376 {
377 if (XGetFontProperty (xfont, XA_FONT, &value))
378 {
379 int len;
380
381 name = (char *) XGetAtomName (display, (Atom) value);
382 len = strlen (name);
383
384 /* If DXPC (a Differential X Protocol Compressor)
385 Ver.3.7 is running, XGetAtomName will return null
386 string. We must avoid such a name. */
387 if (len > 0)
388 {
389 entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
390 ASET (entity, FONT_TYPE_INDEX, Qx);
391 ASET (entity, FONT_FRAME_INDEX, frame);
392 if (font_parse_xlfd (name, entity) < 0)
393 entity = Qnil;
394 }
395 XFree (name);
396 }
397 XFreeFont (display, xfont);
398 }
9c6d1df5 399 UNBLOCK_INPUT;
6e34c9c1
KH
400
401 return entity;
402}
403
c2f5bfd6
KH
404static int
405memq_no_quit (elt, list)
406 Lisp_Object elt, list;
407{
408 while (CONSP (list) && ! EQ (XCAR (list), elt))
409 list = XCDR (list);
410 return (CONSP (list));
411}
412
413static Lisp_Object
414xfont_list_family (frame)
9df50a31 415 Lisp_Object frame;
c2f5bfd6
KH
416{
417 FRAME_PTR f = XFRAME (frame);
418 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
419 char **names;
420 int num_fonts, i;
421 Lisp_Object list;
422 char *last_family;
423 int last_len;
424
425 BLOCK_INPUT;
426 x_catch_errors (dpyinfo->display);
427 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
428 0x8000, &num_fonts);
429 if (x_had_errors_p (dpyinfo->display))
430 {
431 /* This error is perhaps due to insufficient memory on X server.
432 Let's just ignore it. */
433 x_clear_errors (dpyinfo->display);
434 num_fonts = 0;
435 }
436
437 list = Qnil;
438 for (i = 0, last_len = 0; i < num_fonts; i++)
439 {
440 char *p0 = names[i], *p1;
441 Lisp_Object family;
442
443 p0++; /* skip the leading '-' */
444 while (*p0 && *p0 != '-') p0++; /* skip foundry */
445 if (! *p0)
446 continue;
447 p1 = ++p0;
448 while (*p1 && *p1 != '-') p1++; /* find the end of family */
449 if (! *p1 || p1 == p0)
450 continue;
451 if (last_len == p1 - p0
452 && bcmp (last_family, p0, last_len) == 0)
453 continue;
454 last_len = p1 - p0;
455 last_family = p0;
456 family = intern_downcase (p0, last_len);
457 if (! memq_no_quit (family, list))
458 list = Fcons (family, list);
459 }
460
461 XFreeFontNames (names);
462 x_uncatch_errors ();
463 UNBLOCK_INPUT;
464
465 return list;
466}
467
468static struct font *
469xfont_open (f, entity, pixel_size)
470 FRAME_PTR f;
471 Lisp_Object entity;
472 int pixel_size;
473{
474 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
475 Display *display = dpyinfo->display;
476 char name[256];
477 int len;
478 unsigned long value;
479 Lisp_Object registry;
480 struct charset *encoding, *repertory;
481 struct font *font;
482 XFontStruct *xfont;
483
484 /* At first, check if we know how to encode characters for this
485 font. */
486 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 487 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
c2f5bfd6
KH
488 return NULL;
489
490 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
491 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
492 len = font_unparse_xlfd (entity, pixel_size, name, 256);
493 if (len <= 0)
494 return NULL;
495
496 BLOCK_INPUT;
497 x_catch_errors (display);
498 xfont = XLoadQueryFont (display, name);
499 if (x_had_errors_p (display))
500 {
501 /* This error is perhaps due to insufficient memory on X server.
502 Let's just ignore it. */
503 x_clear_errors (display);
504 xfont = NULL;
505 }
506 x_uncatch_errors ();
507 UNBLOCK_INPUT;
508
509 if (! xfont)
510 return NULL;
511 font = malloc (sizeof (struct font));
85c3e908 512 font->format = Qx;
c2f5bfd6
KH
513 font->font.font = xfont;
514 font->entity = entity;
515 font->pixel_size = pixel_size;
516 font->driver = &xfont_driver;
517 font->font.name = malloc (len + 1);
518 if (! font->font.name)
519 {
520 XFreeFont (display, xfont);
521 free (font);
522 return NULL;
523 }
524 bcopy (name, font->font.name, len + 1);
525 font->font.charset = encoding->id;
526 font->encoding_charset = encoding->id;
1886668d 527 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
528 font->ascent = xfont->ascent;
529 font->descent = xfont->descent;
530
531 if (xfont->min_bounds.width == xfont->max_bounds.width)
532 {
533 /* Fixed width font. */
534 font->font.average_width = font->font.space_width
535 = xfont->min_bounds.width;
536 }
537 else
538 {
539 XChar2b char2b;
540 XCharStruct *pcm;
541
542 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
543 pcm = xfont_get_pcm (xfont, &char2b);
544 if (pcm)
545 font->font.space_width = pcm->width;
546 else
547 font->font.space_width = xfont->max_bounds.width;
548
549 font->font.average_width
550 = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
551 ? (long) value / 10 : 0);
552 if (font->font.average_width < 0)
553 font->font.average_width = - font->font.average_width;
554 if (font->font.average_width == 0)
555 {
556 if (pcm)
557 {
558 int width = pcm->width;
559 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
560 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
561 width += pcm->width;
562 font->font.average_width = width / 95;
563 }
564 else
565 font->font.average_width = xfont->max_bounds.width;
566 }
567 }
568 font->min_width = xfont->min_bounds.width;
569 if (font->min_width <= 0)
570 font->min_width = font->font.space_width;
571
572 BLOCK_INPUT;
573 /* Try to get the full name of FONT. Put it in FULL_NAME. */
574 if (XGetFontProperty (xfont, XA_FONT, &value))
575 {
576 char *full_name = NULL, *p0, *p;
577 int dashes = 0;
578
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)
586 {
587 if (*p == '-')
588 dashes++;
589 p++;
590 }
591
592 if (dashes >= 13)
593 {
594 full_name = (char *) malloc (p - p0 + 1);
595 if (full_name)
596 bcopy (p0, full_name, p - p0 + 1);
597 }
598 XFree (p0);
599
600 if (full_name)
601 font->font.full_name = full_name;
602 else
603 font->font.full_name = font->font.name;
604 }
605 font->file_name = NULL;
606
607 font->font.size = xfont->max_bounds.width;
608 font->font.height = xfont->ascent + xfont->descent;
609 font->font.baseline_offset
610 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
611 ? (long) value : 0);
612 font->font.relative_compose
613 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
614 ? (long) value : 0);
615 font->font.default_ascent
616 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
617 ? (long) value : 0);
618 font->font.vertical_centering
619 = (STRINGP (Vvertical_centering_font_regexp)
620 && (fast_c_string_match_ignore_case
621 (Vvertical_centering_font_regexp, font->font.full_name) >= 0));
622
623 UNBLOCK_INPUT;
624
625 dpyinfo->n_fonts++;
626
627 /* Set global flag fonts_changed_p to non-zero if the font loaded
628 has a character with a smaller width than any other character
629 before, or if the font loaded has a smaller height than any other
630 font loaded before. If this happens, it will make a glyph matrix
631 reallocation necessary. */
632 if (dpyinfo->n_fonts == 1)
633 {
634 dpyinfo->smallest_font_height = font->font.height;
635 dpyinfo->smallest_char_width = font->min_width;
636 fonts_changed_p = 1;
637 }
638 else
639 {
640 if (dpyinfo->smallest_font_height > font->font.height)
641 dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1;
642 if (dpyinfo->smallest_char_width > font->min_width)
643 dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1;
644 }
645
646 return font;
647}
648
649static void
650xfont_close (f, font)
651 FRAME_PTR f;
652 struct font *font;
653{
654 BLOCK_INPUT;
655 XFreeFont (FRAME_X_DISPLAY (f), font->font.font);
656 UNBLOCK_INPUT;
657
658 if (font->font.name != font->font.full_name)
659 free (font->font.full_name);
660 free (font->font.name);
661 free (font);
662 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
663}
664
665static int
666xfont_prepare_face (f, face)
667 FRAME_PTR f;
668 struct face *face;
669{
670 BLOCK_INPUT;
671 XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid);
672 UNBLOCK_INPUT;
673
674 return 0;
675}
676
677#if 0
678static void
679xfont_done_face (f, face)
680 FRAME_PTR f;
681 struct face *face;
682{
683 if (face->extra)
684 {
685 BLOCK_INPUT;
686 XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra);
687 UNBLOCK_INPUT;
688 face->extra = NULL;
689 }
690}
691#endif /* 0 */
692
693static int
694xfont_has_char (entity, c)
695 Lisp_Object entity;
696 int c;
697{
698 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
699 struct charset *repertory;
700
a9822ae8 701 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
702 return -1;
703 if (! repertory)
704 return -1;
705 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
706}
707
708static unsigned
709xfont_encode_char (font, c)
710 struct font *font;
711 int c;
712{
713 struct charset *charset;
714 unsigned code;
715 XChar2b char2b;
716
717 charset = CHARSET_FROM_ID (font->encoding_charset);
718 code = ENCODE_CHAR (charset, c);
719 if (code == CHARSET_INVALID_CODE (charset))
21138cff 720 return FONT_INVALID_CODE;
1886668d 721 if (font->repertory_charset >= 0)
c2f5bfd6 722 {
1886668d 723 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 724 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 725 ? code : FONT_INVALID_CODE);
c2f5bfd6 726 }
88649c62
KH
727 char2b.byte1 = code >> 8;
728 char2b.byte2 = code & 0xFF;
21138cff 729 return (xfont_get_pcm (font->font.font, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
730}
731
732static int
733xfont_text_extents (font, code, nglyphs, metrics)
734 struct font *font;
735 unsigned *code;
736 int nglyphs;
737 struct font_metrics *metrics;
738{
739 int width = 0;
740 int i, x;
741
742 if (metrics)
743 bzero (metrics, sizeof (struct font_metrics));
744 for (i = 0, x = 0; i < nglyphs; i++)
745 {
746 XChar2b char2b;
747 static XCharStruct *pcm;
748
749 if (code[i] >= 0x10000)
750 continue;
751 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
752 pcm = xfont_get_pcm (font->font.font, &char2b);
753 if (! pcm)
754 continue;
755 if (metrics->lbearing > width + pcm->lbearing)
756 metrics->lbearing = width + pcm->lbearing;
757 if (metrics->rbearing < width + pcm->rbearing)
758 metrics->rbearing = width + pcm->rbearing;
759 if (metrics->ascent < pcm->ascent)
760 metrics->ascent = pcm->ascent;
761 if (metrics->descent < pcm->descent)
762 metrics->descent = pcm->descent;
763 width += pcm->width;
764 }
765 if (metrics)
766 metrics->width = width;
767 return width;
768}
769
770static int
771xfont_draw (s, from, to, x, y, with_background)
772 struct glyph_string *s;
773 int from, to, x, y, with_background;
774{
775 XFontStruct *xfont = s->face->font;
776 int len = to - from;
6e34c9c1
KH
777 GC gc = s->gc;
778
779 if (gc != s->face->gc)
780 {
781 XGCValues xgcv;
782 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (s->f);
783
784 XGetGCValues (s->display, gc, GCFont, &xgcv);
785 if (xgcv.font != xfont->fid)
786 XSetFont (s->display, gc, xfont->fid);
787 }
c2f5bfd6
KH
788
789 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
790 {
791 char *str;
792 int i;
793 USE_SAFE_ALLOCA;
794
795 SAFE_ALLOCA (str, char *, len);
796 for (i = 0; i < len ; i++)
797 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
798 if (with_background > 0)
799 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
6e34c9c1 800 gc, x, y, str, len);
c2f5bfd6
KH
801 else
802 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
6e34c9c1 803 gc, x, y, str, len);
c2f5bfd6
KH
804 SAFE_FREE ();
805 return s->nchars;
806 }
807
808 if (with_background > 0)
809 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
6e34c9c1 810 gc, x, y, s->char2b + from, len);
c2f5bfd6
KH
811 else
812 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
6e34c9c1 813 gc, x, y, s->char2b + from, len);
c2f5bfd6
KH
814
815 return len;
816}
817
c2f5bfd6
KH
818\f
819void
820syms_of_xfont ()
821{
c2f5bfd6
KH
822 xfont_driver.type = Qx;
823 register_font_driver (&xfont_driver, NULL);
824}
885b7d09
MB
825
826/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
827 (do not change this comment) */