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