(fontset_from_font, Ffontset_info): Add the 2nd arg in
[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
9ec0b715 9GNU Emacs is free software: you can redistribute it and/or modify
c2f5bfd6 10it under the terms of the GNU General Public License as published by
9ec0b715
GM
11the Free Software Foundation, either version 3 of the License, or
12(at your option) any later version.
c2f5bfd6
KH
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
9ec0b715 20along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
c2f5bfd6
KH
21
22#include <config.h>
23#include <stdio.h>
f0c55750 24#include <stdlib.h>
c2f5bfd6
KH
25#include <X11/Xlib.h>
26
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"
f0c55750 36#include "ccl.h"
c2f5bfd6
KH
37
38\f
39/* X core font driver. */
40
f0c55750
KH
41struct xfont_info
42{
43 struct font font;
44 Display *display;
45 XFontStruct *xfont;
46};
47
c2f5bfd6
KH
48/* Prototypes of support functions. */
49extern void x_clear_errors P_ ((Display *));
50
c2f5bfd6 51static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
f0c55750 52static void xfont_find_ccl_program P_ ((struct font *));
c2f5bfd6
KH
53static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **,
54 struct charset **));
55
c2f5bfd6
KH
56
57/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
58 is not contained in the font. */
59
60static XCharStruct *
61xfont_get_pcm (xfont, char2b)
62 XFontStruct *xfont;
63 XChar2b *char2b;
64{
65 /* The result metric information. */
66 XCharStruct *pcm = NULL;
67
68 xassert (xfont && char2b);
69
70 if (xfont->per_char != NULL)
71 {
72 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
73 {
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;
84 }
85 else
86 {
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:
91
92 byte1 = N/D + min_byte1
93 byte2 = N\D + min_char_or_byte2
94
95 where:
96
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));
108 }
109 }
110 else
111 {
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;
118 }
119
120 return ((pcm == NULL
121 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
122 ? NULL : pcm);
123}
124
f0c55750
KH
125/* Find a CCL program for a font specified by FONTP, and set the member
126 `encoder' of the structure. */
127
128static void
129xfont_find_ccl_program (font)
130 struct font *font;
131{
132 Lisp_Object list, elt;
133
134 elt = Qnil;
135 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
136 {
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;
147 }
148
149 if (! NILP (list))
150 {
151 struct ccl_program *ccl
152 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
153
154 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
155 xfree (ccl);
156 else
157 font->font_encoder = ccl;
158 }
159}
160
feb2737b 161static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
c2f5bfd6 162static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
6e34c9c1 163static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6 164static Lisp_Object xfont_list_family P_ ((Lisp_Object));
f0c55750 165static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
c2f5bfd6
KH
166static void xfont_close P_ ((FRAME_PTR, struct font *));
167static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
c2f5bfd6
KH
168static int xfont_has_char P_ ((Lisp_Object, int));
169static unsigned xfont_encode_char P_ ((struct font *, int));
170static int xfont_text_extents P_ ((struct font *, unsigned *, int,
171 struct font_metrics *));
172static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
f0c55750 173static int xfont_check P_ ((FRAME_PTR, struct font *));
c2f5bfd6
KH
174
175struct font_driver xfont_driver =
176 {
575abfb7 177 0, /* Qx */
f0c55750 178 0, /* case insensitive */
c2f5bfd6 179 xfont_get_cache,
c2f5bfd6 180 xfont_list,
6e34c9c1 181 xfont_match,
c2f5bfd6
KH
182 xfont_list_family,
183 NULL,
184 xfont_open,
185 xfont_close,
186 xfont_prepare_face,
f0c55750 187 NULL,
c2f5bfd6
KH
188 xfont_has_char,
189 xfont_encode_char,
190 xfont_text_extents,
f0c55750
KH
191 xfont_draw,
192 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
193 xfont_check
c2f5bfd6
KH
194 };
195
196extern Lisp_Object QCname;
197
198static Lisp_Object
feb2737b
KH
199xfont_get_cache (f)
200 FRAME_PTR f;
c2f5bfd6 201{
feb2737b 202 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
203
204 return (dpyinfo->name_list_element);
205}
206
c2f5bfd6
KH
207extern Lisp_Object Vface_alternative_font_registry_alist;
208
f0c55750
KH
209static int
210compare_font_names (const void *name1, const void *name2)
211{
212 return strcasecmp (*(const char **) name1, *(const char **) name2);
213}
214
215static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
216
c2f5bfd6 217static Lisp_Object
6c4aeab6
KH
218xfont_list_pattern (frame, display, pattern)
219 Lisp_Object frame;
220 Display *display;
221 char *pattern;
c2f5bfd6 222{
6c4aeab6
KH
223 Lisp_Object list = Qnil;
224 int i, limit, num_fonts;
225 char **names;
c2f5bfd6
KH
226
227 BLOCK_INPUT;
6c4aeab6 228 x_catch_errors (display);
c2f5bfd6 229
6c4aeab6 230 for (limit = 512; ; limit *= 2)
c2f5bfd6 231 {
6c4aeab6
KH
232 names = XListFonts (display, pattern, limit, &num_fonts);
233 if (x_had_errors_p (display))
c2f5bfd6
KH
234 {
235 /* This error is perhaps due to insufficient memory on X
236 server. Let's just ignore it. */
6c4aeab6
KH
237 x_clear_errors (display);
238 num_fonts = 0;
239 break;
c2f5bfd6 240 }
6c4aeab6
KH
241 if (num_fonts < limit)
242 break;
243 XFreeFontNames (names);
244 }
245
f0c55750 246 if (num_fonts > 0)
6c4aeab6 247 {
f0c55750 248 char **indices = alloca (sizeof (char *) * num_fonts);
6c4aeab6 249
f0c55750
KH
250 for (i = 0; i < num_fonts; i++)
251 indices[i] = names[i];
252 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 253
f0c55750 254 for (i = 0; i < num_fonts; i++)
c2f5bfd6 255 {
f0c55750
KH
256 Lisp_Object entity;
257 int result;
6c4aeab6 258
f0c55750 259 if (i > 0 && strcasecmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 260 continue;
6c4aeab6 261
f0c55750
KH
262 entity = font_make_entity ();
263 ASET (entity, FONT_TYPE_INDEX, Qx);
6c4aeab6 264
f0c55750
KH
265 result = font_parse_xlfd (indices[i], entity);
266 if (result < 0)
c2f5bfd6 267 {
f0c55750
KH
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;
272
273 if (! font)
6c4aeab6 274 continue;
f0c55750
KH
275 if (XGetFontProperty (font, XA_FONT, &value))
276 {
277 char *name = (char *) XGetAtomName (display, (Atom) value);
278 int len = strlen (name);
279
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);
286 }
287 XFreeFont (display, font);
c2f5bfd6 288 }
f0c55750
KH
289
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);
c2f5bfd6
KH
295 }
296 }
297
298 x_uncatch_errors ();
299 UNBLOCK_INPUT;
300
6c4aeab6
KH
301 return list;
302}
c2f5bfd6 303
6c4aeab6
KH
304static Lisp_Object
305xfont_list (frame, spec)
306 Lisp_Object frame, spec;
307{
308 FRAME_PTR f = XFRAME (frame);
309 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
f0c55750
KH
310 Lisp_Object registry, list, val, extra, font_name;
311 Lisp_Object dpi, avgwidth;
6c4aeab6
KH
312 int len;
313 char name[256];
314
315 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 316 if (CONSP (extra))
c2f5bfd6 317 {
6c4aeab6
KH
318 val = assq_no_quit (QCotf, extra);
319 if (! NILP (val))
f0c55750 320 return Qnil;
6c4aeab6
KH
321 val = assq_no_quit (QCscript, extra);
322 if (! NILP (val))
f0c55750
KH
323 return Qnil;
324 val = assq_no_quit (QClang, extra);
6c4aeab6 325 if (! NILP (val))
f0c55750 326 return Qnil;
c2f5bfd6 327 }
6c4aeab6 328
f0c55750
KH
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))
c2f5bfd6 338 {
f0c55750
KH
339 /* Try iso10646-1 */
340 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
341
342 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 343 {
f0c55750
KH
344 strcpy (r, "iso10646-1");
345 list = xfont_list_pattern (frame, display, name);
346 }
347 }
348 if (NILP (list) && ! NILP (registry))
349 {
350 Lisp_Object alter;
6c4aeab6 351
f0c55750
KH
352 if ((alter = Fassoc (SYMBOL_NAME (registry),
353 Vface_alternative_font_registry_alist),
354 CONSP (alter)))
355 {
356 /* Pointer to REGISTRY-ENCODING field. */
357 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
358
359 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
360 if (STRINGP (XCAR (alter))
361 && ((r - name) + SBYTES (XCAR (alter))) < 256)
362 {
363 strcpy (r, (char *) SDATA (XCAR (alter)));
364 list = xfont_list_pattern (frame, display, name);
365 if (! NILP (list))
366 break;
367 }
6c4aeab6 368 }
c2f5bfd6 369 }
c2f5bfd6 370
f0c55750 371 return list;
c2f5bfd6
KH
372}
373
6e34c9c1
KH
374static Lisp_Object
375xfont_match (frame, spec)
376 Lisp_Object frame, spec;
377{
378 FRAME_PTR f = XFRAME (frame);
379 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
380 Lisp_Object extra, val, entity;
f0c55750 381 char buf[256], *name;
6e34c9c1
KH
382 XFontStruct *xfont;
383 unsigned long value;
384
385 extra = AREF (spec, FONT_EXTRA_INDEX);
386 val = assq_no_quit (QCname, extra);
387 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750
KH
388 {
389 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
390 return Qnil;
391 name = buf;
392 }
393 else
394 name = (char *) SDATA (XCDR (val));
6e34c9c1 395
9c6d1df5 396 BLOCK_INPUT;
6e34c9c1 397 entity = Qnil;
6e34c9c1
KH
398 xfont = XLoadQueryFont (display, name);
399 if (xfont)
400 {
401 if (XGetFontProperty (xfont, XA_FONT, &value))
402 {
403 int len;
404
405 name = (char *) XGetAtomName (display, (Atom) value);
406 len = strlen (name);
407
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)
412 {
f0c55750 413 entity = font_make_entity ();
6e34c9c1 414 ASET (entity, FONT_TYPE_INDEX, Qx);
6e34c9c1
KH
415 if (font_parse_xlfd (name, entity) < 0)
416 entity = Qnil;
417 }
418 XFree (name);
419 }
420 XFreeFont (display, xfont);
421 }
9c6d1df5 422 UNBLOCK_INPUT;
6e34c9c1
KH
423
424 return entity;
425}
426
c2f5bfd6
KH
427static int
428memq_no_quit (elt, list)
429 Lisp_Object elt, list;
430{
431 while (CONSP (list) && ! EQ (XCAR (list), elt))
432 list = XCDR (list);
433 return (CONSP (list));
434}
435
436static Lisp_Object
437xfont_list_family (frame)
9df50a31 438 Lisp_Object frame;
c2f5bfd6
KH
439{
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;
447
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))
453 {
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;
458 }
459
460 list = Qnil;
461 for (i = 0, last_len = 0; i < num_fonts; i++)
462 {
463 char *p0 = names[i], *p1;
464 Lisp_Object family;
465
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;
f0c55750
KH
479 family = make_unibyte_string (p0, last_len);
480 if (NILP (Fassoc_string (family, list, Qt)))
c2f5bfd6
KH
481 list = Fcons (family, list);
482 }
483
484 XFreeFontNames (names);
485 x_uncatch_errors ();
486 UNBLOCK_INPUT;
487
488 return list;
489}
490
f0c55750
KH
491extern Lisp_Object QCavgwidth;
492
493static Lisp_Object
c2f5bfd6
KH
494xfont_open (f, entity, pixel_size)
495 FRAME_PTR f;
496 Lisp_Object entity;
497 int pixel_size;
498{
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;
f0c55750 506 Lisp_Object font_object, fullname;
c2f5bfd6
KH
507 struct font *font;
508 XFontStruct *xfont;
f0c55750 509 int i;
c2f5bfd6
KH
510
511 /* At first, check if we know how to encode characters for this
512 font. */
513 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 514 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
f0c55750 515 return Qnil;
c2f5bfd6
KH
516
517 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
518 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
519 else if (pixel_size == 0)
520 {
521 if (FRAME_FONT (f))
522 pixel_size = FRAME_FONT (f)->pixel_size;
523 else
524 pixel_size = 14;
525 }
c2f5bfd6
KH
526 len = font_unparse_xlfd (entity, pixel_size, name, 256);
527 if (len <= 0)
f0c55750 528 return Qnil;
c2f5bfd6
KH
529
530 BLOCK_INPUT;
531 x_catch_errors (display);
532 xfont = XLoadQueryFont (display, name);
533 if (x_had_errors_p (display))
534 {
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;
539 }
f0c55750
KH
540 fullname = Qnil;
541 /* Try to get the full name of FONT. */
542 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
543 {
544 char *p0, *p;
545 int dashes = 0;
546
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)
554 {
555 if (*p == '-')
556 dashes++;
557 p++;
558 }
559
560 if (dashes >= 13)
561 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
562 XFree (p0);
563 }
c2f5bfd6
KH
564 x_uncatch_errors ();
565 UNBLOCK_INPUT;
566
567 if (! xfont)
f0c55750
KH
568 return Qnil;
569
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);
c2f5bfd6
KH
587 font->pixel_size = pixel_size;
588 font->driver = &xfont_driver;
c2f5bfd6 589 font->encoding_charset = encoding->id;
1886668d 590 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
591 font->ascent = xfont->ascent;
592 font->descent = xfont->descent;
f0c55750
KH
593 font->height = font->ascent + font->descent;
594 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
595 if (xfont->min_bounds.width == xfont->max_bounds.width)
596 {
597 /* Fixed width font. */
f0c55750 598 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
599 }
600 else
601 {
c2f5bfd6 602 XCharStruct *pcm;
f0c55750
KH
603 XChar2b char2b;
604 Lisp_Object val;
c2f5bfd6
KH
605
606 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
607 pcm = xfont_get_pcm (xfont, &char2b);
608 if (pcm)
f0c55750 609 font->space_width = pcm->width;
c2f5bfd6 610 else
f0c55750
KH
611 font->space_width = 0;
612
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)
c2f5bfd6 620 {
f0c55750 621 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 622
f0c55750
KH
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;
c2f5bfd6 627 }
c2f5bfd6 628 }
c2f5bfd6 629
f0c55750
KH
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
c2f5bfd6
KH
638 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
639 ? (long) value : 0);
f0c55750 640 font->relative_compose
c2f5bfd6
KH
641 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
642 ? (long) value : 0);
f0c55750 643 font->default_ascent
c2f5bfd6
KH
644 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
645 ? (long) value : 0);
c2f5bfd6
KH
646 UNBLOCK_INPUT;
647
f0c55750
KH
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));
c2f5bfd6 654
f0c55750 655 return font_object;
c2f5bfd6
KH
656}
657
658static void
659xfont_close (f, font)
660 FRAME_PTR f;
661 struct font *font;
662{
663 BLOCK_INPUT;
f0c55750 664 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 665 UNBLOCK_INPUT;
c2f5bfd6
KH
666}
667
668static int
669xfont_prepare_face (f, face)
670 FRAME_PTR f;
671 struct face *face;
672{
673 BLOCK_INPUT;
f0c55750
KH
674 XSetFont (FRAME_X_DISPLAY (f), face->gc,
675 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
676 UNBLOCK_INPUT;
677
678 return 0;
679}
680
c2f5bfd6
KH
681static int
682xfont_has_char (entity, c)
683 Lisp_Object entity;
684 int c;
685{
686 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
687 struct charset *repertory;
688
a9822ae8 689 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
690 return -1;
691 if (! repertory)
692 return -1;
693 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
694}
695
696static unsigned
697xfont_encode_char (font, c)
698 struct font *font;
699 int c;
700{
f0c55750 701 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
702 struct charset *charset;
703 unsigned code;
704 XChar2b char2b;
705
706 charset = CHARSET_FROM_ID (font->encoding_charset);
707 code = ENCODE_CHAR (charset, c);
708 if (code == CHARSET_INVALID_CODE (charset))
21138cff 709 return FONT_INVALID_CODE;
1886668d 710 if (font->repertory_charset >= 0)
c2f5bfd6 711 {
1886668d 712 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 713 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 714 ? code : FONT_INVALID_CODE);
c2f5bfd6 715 }
88649c62
KH
716 char2b.byte1 = code >> 8;
717 char2b.byte2 = code & 0xFF;
f0c55750 718 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
719}
720
721static int
722xfont_text_extents (font, code, nglyphs, metrics)
723 struct font *font;
724 unsigned *code;
725 int nglyphs;
726 struct font_metrics *metrics;
727{
f0c55750 728 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
729 int width = 0;
730 int i, x;
731
732 if (metrics)
733 bzero (metrics, sizeof (struct font_metrics));
734 for (i = 0, x = 0; i < nglyphs; i++)
735 {
736 XChar2b char2b;
737 static XCharStruct *pcm;
738
739 if (code[i] >= 0x10000)
740 continue;
741 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 742 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
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;
754 }
755 if (metrics)
756 metrics->width = width;
757 return width;
758}
759
760static int
761xfont_draw (s, from, to, x, y, with_background)
762 struct glyph_string *s;
763 int from, to, x, y, with_background;
764{
f0c55750 765 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 766 int len = to - from;
6e34c9c1 767 GC gc = s->gc;
298fd5b1 768 int i;
6e34c9c1 769
f0c55750 770 if (s->gc != s->face->gc)
6e34c9c1 771 {
d45fefc7 772 BLOCK_INPUT;
f0c55750 773 XSetFont (s->display, gc, xfont->fid);
d45fefc7 774 UNBLOCK_INPUT;
6e34c9c1 775 }
c2f5bfd6
KH
776
777 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
778 {
779 char *str;
c2f5bfd6
KH
780 USE_SAFE_ALLOCA;
781
782 SAFE_ALLOCA (str, char *, len);
783 for (i = 0; i < len ; i++)
784 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 785 BLOCK_INPUT;
c2f5bfd6 786 if (with_background > 0)
298fd5b1
KH
787 {
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);
795 }
c2f5bfd6 796 else
298fd5b1
KH
797 {
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);
805 }
d45fefc7 806 UNBLOCK_INPUT;
c2f5bfd6
KH
807 SAFE_FREE ();
808 return s->nchars;
809 }
810
d45fefc7 811 BLOCK_INPUT;
c2f5bfd6 812 if (with_background > 0)
298fd5b1
KH
813 {
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);
821 }
c2f5bfd6 822 else
298fd5b1
KH
823 {
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);
831 }
d45fefc7 832 UNBLOCK_INPUT;
c2f5bfd6
KH
833
834 return len;
835}
836
f0c55750
KH
837static int
838xfont_check (f, font)
839 FRAME_PTR f;
840 struct font *font;
841{
842 struct xfont_info *xfont = (struct xfont_info *) font;
843
844 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
845}
846
c2f5bfd6
KH
847\f
848void
849syms_of_xfont ()
850{
c2f5bfd6
KH
851 xfont_driver.type = Qx;
852 register_font_driver (&xfont_driver, NULL);
853}
885b7d09
MB
854
855/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
856 (do not change this comment) */