(msdos_stdcolor_idx): Use xstricmp.
[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
53
54/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
55 is not contained in the font. */
56
57static XCharStruct *
58xfont_get_pcm (xfont, char2b)
59 XFontStruct *xfont;
60 XChar2b *char2b;
61{
62 /* The result metric information. */
63 XCharStruct *pcm = NULL;
64
960d80b9 65 font_assert (xfont && char2b);
c2f5bfd6
KH
66
67 if (xfont->per_char != NULL)
68 {
69 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
70 {
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;
81 }
82 else
83 {
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:
88
89 byte1 = N/D + min_byte1
90 byte2 = N\D + min_char_or_byte2
91
92 where:
93
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));
105 }
106 }
107 else
108 {
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;
115 }
116
117 return ((pcm == NULL
118 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
119 ? NULL : pcm);
120}
121
f0c55750
KH
122/* Find a CCL program for a font specified by FONTP, and set the member
123 `encoder' of the structure. */
124
125static void
126xfont_find_ccl_program (font)
127 struct font *font;
128{
129 Lisp_Object list, elt;
130
131 elt = Qnil;
132 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
133 {
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;
144 }
145
146 if (! NILP (list))
147 {
148 struct ccl_program *ccl
149 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
150
151 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
152 xfree (ccl);
153 else
154 font->font_encoder = ccl;
155 }
156}
157
feb2737b 158static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
c2f5bfd6 159static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
6e34c9c1 160static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6 161static Lisp_Object xfont_list_family P_ ((Lisp_Object));
f0c55750 162static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
c2f5bfd6
KH
163static void xfont_close P_ ((FRAME_PTR, struct font *));
164static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
c2f5bfd6
KH
165static int xfont_has_char P_ ((Lisp_Object, int));
166static unsigned xfont_encode_char P_ ((struct font *, int));
167static int xfont_text_extents P_ ((struct font *, unsigned *, int,
168 struct font_metrics *));
169static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
f0c55750 170static int xfont_check P_ ((FRAME_PTR, struct font *));
c2f5bfd6
KH
171
172struct font_driver xfont_driver =
173 {
575abfb7 174 0, /* Qx */
f0c55750 175 0, /* case insensitive */
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,
f0c55750 184 NULL,
c2f5bfd6
KH
185 xfont_has_char,
186 xfont_encode_char,
187 xfont_text_extents,
f0c55750
KH
188 xfont_draw,
189 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
190 xfont_check
c2f5bfd6
KH
191 };
192
193extern Lisp_Object QCname;
194
195static Lisp_Object
feb2737b
KH
196xfont_get_cache (f)
197 FRAME_PTR f;
c2f5bfd6 198{
feb2737b 199 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
200
201 return (dpyinfo->name_list_element);
202}
203
c2f5bfd6
KH
204extern Lisp_Object Vface_alternative_font_registry_alist;
205
f0c55750
KH
206static int
207compare_font_names (const void *name1, const void *name2)
208{
61a540f5 209 return xstricmp (*(const char **) name1, *(const char **) name2);
f0c55750
KH
210}
211
212static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
213
c2f5bfd6 214static Lisp_Object
6c4aeab6
KH
215xfont_list_pattern (frame, display, pattern)
216 Lisp_Object frame;
217 Display *display;
218 char *pattern;
c2f5bfd6 219{
6c4aeab6
KH
220 Lisp_Object list = Qnil;
221 int i, limit, num_fonts;
222 char **names;
c2f5bfd6
KH
223
224 BLOCK_INPUT;
6c4aeab6 225 x_catch_errors (display);
c2f5bfd6 226
6c4aeab6 227 for (limit = 512; ; limit *= 2)
c2f5bfd6 228 {
6c4aeab6
KH
229 names = XListFonts (display, pattern, limit, &num_fonts);
230 if (x_had_errors_p (display))
c2f5bfd6
KH
231 {
232 /* This error is perhaps due to insufficient memory on X
233 server. Let's just ignore it. */
6c4aeab6
KH
234 x_clear_errors (display);
235 num_fonts = 0;
236 break;
c2f5bfd6 237 }
6c4aeab6
KH
238 if (num_fonts < limit)
239 break;
240 XFreeFontNames (names);
241 }
242
f0c55750 243 if (num_fonts > 0)
6c4aeab6 244 {
f0c55750 245 char **indices = alloca (sizeof (char *) * num_fonts);
6c4aeab6 246
f0c55750
KH
247 for (i = 0; i < num_fonts; i++)
248 indices[i] = names[i];
249 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 250
f0c55750 251 for (i = 0; i < num_fonts; i++)
c2f5bfd6 252 {
f0c55750
KH
253 Lisp_Object entity;
254 int result;
6c4aeab6 255
61a540f5 256 if (i > 0 && xstricmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 257 continue;
6c4aeab6 258
f0c55750
KH
259 entity = font_make_entity ();
260 ASET (entity, FONT_TYPE_INDEX, Qx);
6c4aeab6 261
f0c55750
KH
262 result = font_parse_xlfd (indices[i], entity);
263 if (result < 0)
c2f5bfd6 264 {
f0c55750
KH
265 /* This may be an alias name. Try to get the full XLFD name
266 from XA_FONT property of the font. */
267 XFontStruct *font = XLoadQueryFont (display, indices[i]);
268 unsigned long value;
269
270 if (! font)
6c4aeab6 271 continue;
f0c55750
KH
272 if (XGetFontProperty (font, XA_FONT, &value))
273 {
274 char *name = (char *) XGetAtomName (display, (Atom) value);
275 int len = strlen (name);
276
277 /* If DXPC (a Differential X Protocol Compressor)
278 Ver.3.7 is running, XGetAtomName will return null
279 string. We must avoid such a name. */
280 if (len > 0)
281 result = font_parse_xlfd (name, entity);
282 XFree (name);
283 }
284 XFreeFont (display, font);
c2f5bfd6 285 }
f0c55750
KH
286
287 if (result == 0
288 /* Avoid auto-scaled fonts. */
289 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
290 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
291 list = Fcons (entity, list);
c2f5bfd6
KH
292 }
293 }
294
295 x_uncatch_errors ();
296 UNBLOCK_INPUT;
297
960d80b9 298 font_add_log ("xfont-list", build_string (pattern), list);
6c4aeab6
KH
299 return list;
300}
c2f5bfd6 301
6c4aeab6
KH
302static Lisp_Object
303xfont_list (frame, spec)
304 Lisp_Object frame, spec;
305{
306 FRAME_PTR f = XFRAME (frame);
307 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
960d80b9 308 Lisp_Object registry, list, val, extra;
6c4aeab6
KH
309 int len;
310 char name[256];
311
312 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 313 if (CONSP (extra))
c2f5bfd6 314 {
6c4aeab6
KH
315 val = assq_no_quit (QCotf, extra);
316 if (! NILP (val))
f0c55750 317 return Qnil;
6c4aeab6
KH
318 val = assq_no_quit (QCscript, extra);
319 if (! NILP (val))
f0c55750
KH
320 return Qnil;
321 val = assq_no_quit (QClang, extra);
6c4aeab6 322 if (! NILP (val))
f0c55750 323 return Qnil;
c2f5bfd6 324 }
6c4aeab6 325
f0c55750
KH
326 registry = AREF (spec, FONT_REGISTRY_INDEX);
327 if (NILP (registry))
328 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
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))
c2f5bfd6 335 {
f0c55750
KH
336 /* Try iso10646-1 */
337 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
338
339 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 340 {
f0c55750
KH
341 strcpy (r, "iso10646-1");
342 list = xfont_list_pattern (frame, display, name);
343 }
344 }
345 if (NILP (list) && ! NILP (registry))
346 {
347 Lisp_Object alter;
6c4aeab6 348
f0c55750
KH
349 if ((alter = Fassoc (SYMBOL_NAME (registry),
350 Vface_alternative_font_registry_alist),
351 CONSP (alter)))
352 {
353 /* Pointer to REGISTRY-ENCODING field. */
354 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
355
356 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
357 if (STRINGP (XCAR (alter))
358 && ((r - name) + SBYTES (XCAR (alter))) < 256)
359 {
360 strcpy (r, (char *) SDATA (XCAR (alter)));
361 list = xfont_list_pattern (frame, display, name);
362 if (! NILP (list))
363 break;
364 }
6c4aeab6 365 }
c2f5bfd6 366 }
c2f5bfd6 367
f0c55750 368 return list;
c2f5bfd6
KH
369}
370
6e34c9c1
KH
371static Lisp_Object
372xfont_match (frame, spec)
373 Lisp_Object frame, spec;
374{
375 FRAME_PTR f = XFRAME (frame);
376 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
377 Lisp_Object extra, val, entity;
f0c55750 378 char buf[256], *name;
6e34c9c1
KH
379 XFontStruct *xfont;
380 unsigned long value;
381
382 extra = AREF (spec, FONT_EXTRA_INDEX);
383 val = assq_no_quit (QCname, extra);
384 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750
KH
385 {
386 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
387 return Qnil;
388 name = buf;
389 }
390 else
391 name = (char *) SDATA (XCDR (val));
6e34c9c1 392
9c6d1df5 393 BLOCK_INPUT;
6e34c9c1 394 entity = Qnil;
6e34c9c1
KH
395 xfont = XLoadQueryFont (display, name);
396 if (xfont)
397 {
398 if (XGetFontProperty (xfont, XA_FONT, &value))
399 {
400 int len;
401
402 name = (char *) XGetAtomName (display, (Atom) value);
403 len = strlen (name);
404
405 /* If DXPC (a Differential X Protocol Compressor)
406 Ver.3.7 is running, XGetAtomName will return null
407 string. We must avoid such a name. */
408 if (len > 0)
409 {
f0c55750 410 entity = font_make_entity ();
6e34c9c1 411 ASET (entity, FONT_TYPE_INDEX, Qx);
6e34c9c1
KH
412 if (font_parse_xlfd (name, entity) < 0)
413 entity = Qnil;
414 }
415 XFree (name);
416 }
417 XFreeFont (display, xfont);
418 }
9c6d1df5 419 UNBLOCK_INPUT;
6e34c9c1 420
960d80b9 421 font_add_log ("xfont-match", spec, entity);
6e34c9c1
KH
422 return entity;
423}
424
c2f5bfd6
KH
425static Lisp_Object
426xfont_list_family (frame)
9df50a31 427 Lisp_Object frame;
c2f5bfd6
KH
428{
429 FRAME_PTR f = XFRAME (frame);
430 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
431 char **names;
432 int num_fonts, i;
433 Lisp_Object list;
434 char *last_family;
435 int last_len;
436
437 BLOCK_INPUT;
438 x_catch_errors (dpyinfo->display);
439 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
440 0x8000, &num_fonts);
441 if (x_had_errors_p (dpyinfo->display))
442 {
443 /* This error is perhaps due to insufficient memory on X server.
444 Let's just ignore it. */
445 x_clear_errors (dpyinfo->display);
446 num_fonts = 0;
447 }
448
449 list = Qnil;
450 for (i = 0, last_len = 0; i < num_fonts; i++)
451 {
452 char *p0 = names[i], *p1;
453 Lisp_Object family;
454
455 p0++; /* skip the leading '-' */
456 while (*p0 && *p0 != '-') p0++; /* skip foundry */
457 if (! *p0)
458 continue;
459 p1 = ++p0;
460 while (*p1 && *p1 != '-') p1++; /* find the end of family */
461 if (! *p1 || p1 == p0)
462 continue;
463 if (last_len == p1 - p0
464 && bcmp (last_family, p0, last_len) == 0)
465 continue;
466 last_len = p1 - p0;
467 last_family = p0;
f0c55750
KH
468 family = make_unibyte_string (p0, last_len);
469 if (NILP (Fassoc_string (family, list, Qt)))
c2f5bfd6
KH
470 list = Fcons (family, list);
471 }
472
473 XFreeFontNames (names);
474 x_uncatch_errors ();
475 UNBLOCK_INPUT;
476
477 return list;
478}
479
f0c55750
KH
480extern Lisp_Object QCavgwidth;
481
482static Lisp_Object
c2f5bfd6
KH
483xfont_open (f, entity, pixel_size)
484 FRAME_PTR f;
485 Lisp_Object entity;
486 int pixel_size;
487{
488 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
489 Display *display = dpyinfo->display;
490 char name[256];
491 int len;
492 unsigned long value;
493 Lisp_Object registry;
494 struct charset *encoding, *repertory;
f0c55750 495 Lisp_Object font_object, fullname;
c2f5bfd6
KH
496 struct font *font;
497 XFontStruct *xfont;
f0c55750 498 int i;
c2f5bfd6
KH
499
500 /* At first, check if we know how to encode characters for this
501 font. */
502 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 503 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
f0c55750 504 return Qnil;
c2f5bfd6
KH
505
506 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
507 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
508 else if (pixel_size == 0)
509 {
510 if (FRAME_FONT (f))
511 pixel_size = FRAME_FONT (f)->pixel_size;
512 else
513 pixel_size = 14;
514 }
c2f5bfd6
KH
515 len = font_unparse_xlfd (entity, pixel_size, name, 256);
516 if (len <= 0)
f0c55750 517 return Qnil;
c2f5bfd6
KH
518
519 BLOCK_INPUT;
520 x_catch_errors (display);
521 xfont = XLoadQueryFont (display, name);
522 if (x_had_errors_p (display))
523 {
524 /* This error is perhaps due to insufficient memory on X server.
525 Let's just ignore it. */
526 x_clear_errors (display);
527 xfont = NULL;
528 }
f0c55750
KH
529 fullname = Qnil;
530 /* Try to get the full name of FONT. */
531 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
532 {
533 char *p0, *p;
534 int dashes = 0;
535
536 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
537 /* Count the number of dashes in the "full name".
538 If it is too few, this isn't really the font's full name,
539 so don't use it.
540 In X11R4, the fonts did not come with their canonical names
541 stored in them. */
542 while (*p)
543 {
544 if (*p == '-')
545 dashes++;
546 p++;
547 }
548
549 if (dashes >= 13)
550 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
551 XFree (p0);
552 }
c2f5bfd6
KH
553 x_uncatch_errors ();
554 UNBLOCK_INPUT;
555
556 if (! xfont)
f0c55750
KH
557 return Qnil;
558
559 font_object = font_make_object (VECSIZE (struct xfont_info));
560 ASET (font_object, FONT_TYPE_INDEX, Qx);
561 if (STRINGP (fullname))
960d80b9 562 font_parse_xlfd ((char *) SDATA (fullname), font_object);
f0c55750
KH
563 for (i = 1; i < FONT_ENTITY_MAX; i++)
564 ASET (font_object, i, AREF (entity, i));
565 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
566 if (STRINGP (fullname))
567 ASET (font_object, FONT_NAME_INDEX, fullname);
568 else
569 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
570 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
571 ASET (font_object, FONT_FILE_INDEX, Qnil);
572 ASET (font_object, FONT_FORMAT_INDEX, Qx);
573 font = XFONT_OBJECT (font_object);
574 ((struct xfont_info *) font)->xfont = xfont;
575 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
576 font->pixel_size = pixel_size;
577 font->driver = &xfont_driver;
c2f5bfd6 578 font->encoding_charset = encoding->id;
1886668d 579 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
580 font->ascent = xfont->ascent;
581 font->descent = xfont->descent;
f0c55750
KH
582 font->height = font->ascent + font->descent;
583 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
584 if (xfont->min_bounds.width == xfont->max_bounds.width)
585 {
586 /* Fixed width font. */
f0c55750 587 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
588 }
589 else
590 {
c2f5bfd6 591 XCharStruct *pcm;
f0c55750
KH
592 XChar2b char2b;
593 Lisp_Object val;
c2f5bfd6
KH
594
595 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
596 pcm = xfont_get_pcm (xfont, &char2b);
597 if (pcm)
f0c55750 598 font->space_width = pcm->width;
c2f5bfd6 599 else
f0c55750
KH
600 font->space_width = 0;
601
602 val = Ffont_get (font_object, QCavgwidth);
603 if (INTEGERP (val))
604 font->average_width = XINT (val);
605 if (font->average_width < 0)
606 font->average_width = - font->average_width;
607 if (font->average_width == 0
608 && encoding->ascii_compatible_p)
c2f5bfd6 609 {
f0c55750 610 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 611
f0c55750
KH
612 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
613 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
614 width += pcm->width, n++;
615 font->average_width = width / n;
c2f5bfd6 616 }
c2f5bfd6 617 }
c2f5bfd6 618
f0c55750
KH
619 BLOCK_INPUT;
620 font->underline_thickness
621 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
622 ? (long) value : 0);
623 font->underline_position
624 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
625 ? (long) value : -1);
626 font->baseline_offset
c2f5bfd6
KH
627 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
628 ? (long) value : 0);
f0c55750 629 font->relative_compose
c2f5bfd6
KH
630 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
631 ? (long) value : 0);
f0c55750 632 font->default_ascent
c2f5bfd6
KH
633 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
634 ? (long) value : 0);
c2f5bfd6
KH
635 UNBLOCK_INPUT;
636
f0c55750
KH
637 if (NILP (fullname))
638 fullname = AREF (font_object, FONT_NAME_INDEX);
639 font->vertical_centering
640 = (STRINGP (Vvertical_centering_font_regexp)
641 && (fast_string_match_ignore_case
642 (Vvertical_centering_font_regexp, fullname) >= 0));
c2f5bfd6 643
f0c55750 644 return font_object;
c2f5bfd6
KH
645}
646
647static void
648xfont_close (f, font)
649 FRAME_PTR f;
650 struct font *font;
651{
652 BLOCK_INPUT;
f0c55750 653 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 654 UNBLOCK_INPUT;
c2f5bfd6
KH
655}
656
657static int
658xfont_prepare_face (f, face)
659 FRAME_PTR f;
660 struct face *face;
661{
662 BLOCK_INPUT;
f0c55750
KH
663 XSetFont (FRAME_X_DISPLAY (f), face->gc,
664 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
665 UNBLOCK_INPUT;
666
667 return 0;
668}
669
c2f5bfd6
KH
670static int
671xfont_has_char (entity, c)
672 Lisp_Object entity;
673 int c;
674{
675 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
676 struct charset *repertory;
677
a9822ae8 678 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
679 return -1;
680 if (! repertory)
681 return -1;
682 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
683}
684
685static unsigned
686xfont_encode_char (font, c)
687 struct font *font;
688 int c;
689{
f0c55750 690 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
691 struct charset *charset;
692 unsigned code;
693 XChar2b char2b;
694
695 charset = CHARSET_FROM_ID (font->encoding_charset);
696 code = ENCODE_CHAR (charset, c);
697 if (code == CHARSET_INVALID_CODE (charset))
21138cff 698 return FONT_INVALID_CODE;
1886668d 699 if (font->repertory_charset >= 0)
c2f5bfd6 700 {
1886668d 701 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 702 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 703 ? code : FONT_INVALID_CODE);
c2f5bfd6 704 }
88649c62
KH
705 char2b.byte1 = code >> 8;
706 char2b.byte2 = code & 0xFF;
f0c55750 707 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
708}
709
710static int
711xfont_text_extents (font, code, nglyphs, metrics)
712 struct font *font;
713 unsigned *code;
714 int nglyphs;
715 struct font_metrics *metrics;
716{
f0c55750 717 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
718 int width = 0;
719 int i, x;
720
721 if (metrics)
722 bzero (metrics, sizeof (struct font_metrics));
723 for (i = 0, x = 0; i < nglyphs; i++)
724 {
725 XChar2b char2b;
726 static XCharStruct *pcm;
727
728 if (code[i] >= 0x10000)
729 continue;
730 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 731 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
732 if (! pcm)
733 continue;
734 if (metrics->lbearing > width + pcm->lbearing)
735 metrics->lbearing = width + pcm->lbearing;
736 if (metrics->rbearing < width + pcm->rbearing)
737 metrics->rbearing = width + pcm->rbearing;
738 if (metrics->ascent < pcm->ascent)
739 metrics->ascent = pcm->ascent;
740 if (metrics->descent < pcm->descent)
741 metrics->descent = pcm->descent;
742 width += pcm->width;
743 }
744 if (metrics)
745 metrics->width = width;
746 return width;
747}
748
749static int
750xfont_draw (s, from, to, x, y, with_background)
751 struct glyph_string *s;
752 int from, to, x, y, with_background;
753{
f0c55750 754 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 755 int len = to - from;
6e34c9c1 756 GC gc = s->gc;
298fd5b1 757 int i;
6e34c9c1 758
f0c55750 759 if (s->gc != s->face->gc)
6e34c9c1 760 {
d45fefc7 761 BLOCK_INPUT;
f0c55750 762 XSetFont (s->display, gc, xfont->fid);
d45fefc7 763 UNBLOCK_INPUT;
6e34c9c1 764 }
c2f5bfd6
KH
765
766 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
767 {
768 char *str;
c2f5bfd6
KH
769 USE_SAFE_ALLOCA;
770
771 SAFE_ALLOCA (str, char *, len);
772 for (i = 0; i < len ; i++)
773 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 774 BLOCK_INPUT;
c2f5bfd6 775 if (with_background > 0)
298fd5b1
KH
776 {
777 if (s->padding_p)
778 for (i = 0; i < len; i++)
779 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
780 gc, x + i, y, str + i, 1);
781 else
782 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
783 gc, x, y, str, len);
784 }
c2f5bfd6 785 else
298fd5b1
KH
786 {
787 if (s->padding_p)
788 for (i = 0; i < len; i++)
789 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
790 gc, x + i, y, str + i, 1);
791 else
792 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
793 gc, x, y, str, len);
794 }
d45fefc7 795 UNBLOCK_INPUT;
c2f5bfd6
KH
796 SAFE_FREE ();
797 return s->nchars;
798 }
799
d45fefc7 800 BLOCK_INPUT;
c2f5bfd6 801 if (with_background > 0)
298fd5b1
KH
802 {
803 if (s->padding_p)
804 for (i = 0; i < len; i++)
805 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
806 gc, x + i, y, s->char2b + from + i, 1);
807 else
808 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
809 gc, x, y, s->char2b + from, len);
810 }
c2f5bfd6 811 else
298fd5b1
KH
812 {
813 if (s->padding_p)
814 for (i = 0; i < len; i++)
815 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
816 gc, x + i, y, s->char2b + from + i, 1);
817 else
818 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
819 gc, x, y, s->char2b + from, len);
820 }
d45fefc7 821 UNBLOCK_INPUT;
c2f5bfd6
KH
822
823 return len;
824}
825
f0c55750
KH
826static int
827xfont_check (f, font)
828 FRAME_PTR f;
829 struct font *font;
830{
831 struct xfont_info *xfont = (struct xfont_info *) font;
832
833 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
834}
835
c2f5bfd6
KH
836\f
837void
838syms_of_xfont ()
839{
c2f5bfd6
KH
840 xfont_driver.type = Qx;
841 register_font_driver (&xfont_driver, NULL);
842}
885b7d09
MB
843
844/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
845 (do not change this comment) */