90400
|
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
|
|
7 This file is part of GNU Emacs.
|
|
8
|
|
9 GNU Emacs is free software; you can redistribute it and/or modify
|
|
10 it under the terms of the GNU General Public License as published by
|
|
11 the Free Software Foundation; either version 2, or (at your option)
|
|
12 any later version.
|
|
13
|
|
14 GNU Emacs is distributed in the hope that it will be useful,
|
|
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17 GNU General Public License for more details.
|
|
18
|
|
19 You should have received a copy of the GNU General Public License
|
|
20 along with GNU Emacs; see the file COPYING. If not, write to
|
|
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
22 Boston, 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
|
|
39 /* X core font driver. */
|
|
40
|
|
41 Lisp_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. */
|
|
59 static Lisp_Object x_font_charset_alist;
|
|
60
|
|
61 /* Prototypes of support functions. */
|
|
62 extern void x_clear_errors P_ ((Display *));
|
|
63
|
|
64 static char *xfont_query_font P_ ((Display *, char *, Lisp_Object));
|
|
65 static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
|
|
66 static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **,
|
|
67 struct charset **));
|
|
68
|
|
69 static char *
|
|
70 xfont_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
|
|
95 if (font_parse_xlfd (n, spec, 0) >= 0)
|
|
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
|
|
112 static XCharStruct *
|
|
113 xfont_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
|
|
177 extern 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
|
|
183 static int
|
|
184 xfont_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
|
|
240 static Lisp_Object xfont_get_cache P_ ((Lisp_Object));
|
|
241 static int xfont_parse_name P_ ((FRAME_PTR, char *, Lisp_Object));
|
|
242 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
|
|
243 static Lisp_Object xfont_list_family P_ ((Lisp_Object));
|
|
244 static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
|
|
245 static void xfont_close P_ ((FRAME_PTR, struct font *));
|
|
246 static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
|
|
247 #if 0
|
|
248 static void xfont_done_face P_ ((FRAME_PTR, struct face *));
|
|
249 #endif
|
|
250 static int xfont_has_char P_ ((Lisp_Object, int));
|
|
251 static unsigned xfont_encode_char P_ ((struct font *, int));
|
|
252 static int xfont_text_extents P_ ((struct font *, unsigned *, int,
|
|
253 struct font_metrics *));
|
|
254 static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
|
|
255
|
|
256 struct font_driver xfont_driver =
|
|
257 {
|
|
258 (Lisp_Object) NULL, /* Qx */
|
|
259 xfont_get_cache,
|
|
260 xfont_parse_name,
|
|
261 xfont_list,
|
|
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
|
|
274 extern Lisp_Object QCname;
|
|
275
|
|
276 static Lisp_Object
|
|
277 xfont_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
|
|
285 static int
|
|
286 xfont_parse_name (f, name, spec)
|
|
287 FRAME_PTR f;
|
|
288 char *name;
|
|
289 Lisp_Object spec;
|
|
290 {
|
|
291 if (font_parse_xlfd (name, spec, 0) >= 0)
|
|
292 return 0;
|
|
293 name = xfont_query_font (FRAME_X_DISPLAY (f), name, spec);
|
|
294 if (name)
|
|
295 {
|
|
296 XFree (name);
|
|
297 return 0;
|
|
298 }
|
|
299 return -1;
|
|
300 }
|
|
301
|
|
302 extern Lisp_Object Vface_alternative_font_registry_alist;
|
|
303
|
|
304 static Lisp_Object
|
|
305 xfont_list (frame, spec)
|
|
306 Lisp_Object frame, spec;
|
|
307 {
|
|
308 FRAME_PTR f = XFRAME (frame);
|
|
309 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
|
|
310 Lisp_Object *vec, val, extra, font_name, entity;
|
|
311 char name[256], **names;
|
|
312 int i, idx, limit, num_fonts;
|
|
313 int error_occurred = 0;
|
|
314 USE_SAFE_ALLOCA;
|
|
315
|
|
316 extra = AREF (spec, FONT_EXTRA_INDEX);
|
|
317 font_name = Qnil;
|
|
318 if (CONSP (extra))
|
|
319 {
|
|
320 val = Fassq (QCotf, extra);
|
|
321 if (! NILP (val))
|
|
322 return null_vector;
|
|
323 val = Fassq (QCname, extra);
|
|
324 if (CONSP (val))
|
|
325 font_name = XCDR (val);
|
|
326 }
|
|
327
|
|
328 if (! STRINGP (font_name)
|
|
329 && font_unparse_xlfd (spec, 0, name, 256) < 0)
|
|
330 return null_vector;
|
|
331
|
|
332 BLOCK_INPUT;
|
|
333 x_catch_errors (dpyinfo->display);
|
|
334
|
|
335 if (STRINGP (font_name))
|
|
336 {
|
|
337 XFontStruct *font = XLoadQueryFont (dpyinfo->display,
|
|
338 (char *) SDATA (font_name));
|
|
339 unsigned long value;
|
|
340
|
|
341 num_fonts = 0;
|
|
342 if (x_had_errors_p (dpyinfo->display))
|
|
343 {
|
|
344 /* This error is perhaps due to insufficient memory on X
|
|
345 server. Let's just ignore it. */
|
|
346 font = NULL;
|
|
347 error_occurred = 1;
|
|
348 x_clear_errors (dpyinfo->display);
|
|
349 }
|
|
350 if (font)
|
|
351 {
|
|
352 if (XGetFontProperty (font, XA_FONT, &value))
|
|
353 {
|
|
354 char *n = (char *) XGetAtomName (dpyinfo->display, (Atom) value);
|
|
355 int len = strlen (n);
|
|
356 char *tmp;
|
|
357
|
|
358 /* If DXPC (a Differential X Protocol Compressor)
|
|
359 Ver.3.7 is running, XGetAtomName will return null
|
|
360 string. We must avoid such a name. */
|
|
361 if (len > 0)
|
|
362 {
|
|
363 num_fonts = 1;
|
|
364 names = (char **) alloca (sizeof (char *));
|
|
365 /* Some systems only allow alloca assigned to a
|
|
366 simple var. */
|
|
367 tmp = (char *) alloca (len + 1); names[0] = tmp;
|
|
368 bcopy (n, names[0], len + 1);
|
|
369 }
|
|
370 XFree (n);
|
|
371 }
|
|
372 XFreeFont (dpyinfo->display, font);
|
|
373 }
|
|
374 }
|
|
375 else
|
|
376 {
|
|
377 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
|
|
378 Lisp_Object alter = Qnil;
|
|
379 char *r = NULL;
|
|
380
|
|
381 if (! NILP (registry))
|
|
382 alter = Fassoc_string (SYMBOL_NAME (registry),
|
|
383 Vface_alternative_font_registry_alist);
|
|
384 while (1)
|
|
385 {
|
|
386 for (limit = 512, num_fonts = 0; ; limit *= 2)
|
|
387 {
|
|
388 names = XListFonts (dpyinfo->display, name, limit, &num_fonts);
|
|
389 if (x_had_errors_p (dpyinfo->display))
|
|
390 {
|
|
391 /* This error is perhaps due to insufficient memory
|
|
392 on X server. Let's just ignore it. */
|
|
393 x_clear_errors (dpyinfo->display);
|
|
394 error_occurred = 1;
|
|
395 num_fonts = 0;
|
|
396 break;
|
|
397 }
|
|
398 if (num_fonts < limit)
|
|
399 break;
|
|
400 XFreeFontNames (names);
|
|
401 }
|
|
402 if (num_fonts > 0
|
|
403 || NILP (alter))
|
|
404 break;
|
|
405
|
|
406 /* Setup for trying alternatives. */
|
|
407 if (! r
|
|
408 && ! (r = strstr (name, (char *) SDATA (SYMBOL_NAME (registry)))))
|
|
409 abort ();
|
|
410 while (1)
|
|
411 {
|
|
412 registry = Qnil;
|
|
413 alter = XCDR (alter);
|
|
414 if (NILP (alter))
|
|
415 break;
|
|
416 registry = XCAR (alter);
|
|
417 if ((r - name) + SBYTES (registry) < 255)
|
|
418 break;
|
|
419 }
|
|
420 if (NILP (registry))
|
|
421 break;
|
|
422 bcopy (SDATA (registry), r, SBYTES (registry));
|
|
423 }
|
|
424 }
|
|
425
|
|
426 x_uncatch_errors ();
|
|
427 UNBLOCK_INPUT;
|
|
428
|
|
429 if (error_occurred)
|
|
430 return Qnil;
|
|
431 if (num_fonts == 0)
|
|
432 return null_vector;
|
|
433
|
|
434 entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
|
|
435 ASET (entity, FONT_TYPE_INDEX, Qx);
|
|
436 ASET (entity, FONT_FRAME_INDEX, frame);
|
|
437
|
|
438 SAFE_ALLOCA_LISP (vec, num_fonts);
|
|
439 for (i = idx = 0; i < num_fonts; i++)
|
|
440 {
|
|
441 if (font_parse_xlfd (names[i], entity, 0) > 0)
|
|
442 vec[idx++] = Fcopy_sequence (entity);
|
|
443 }
|
|
444 if (! STRINGP (font_name))
|
|
445 {
|
|
446 BLOCK_INPUT;
|
|
447 XFreeFontNames (names);
|
|
448 UNBLOCK_INPUT;
|
|
449 }
|
|
450 val = Fvector (idx, vec);
|
|
451 SAFE_FREE ();
|
|
452
|
|
453 return val;
|
|
454 }
|
|
455
|
|
456 static int
|
|
457 memq_no_quit (elt, list)
|
|
458 Lisp_Object elt, list;
|
|
459 {
|
|
460 while (CONSP (list) && ! EQ (XCAR (list), elt))
|
|
461 list = XCDR (list);
|
|
462 return (CONSP (list));
|
|
463 }
|
|
464
|
|
465 static Lisp_Object
|
|
466 xfont_list_family (frame)
|
|
467 {
|
|
468 FRAME_PTR f = XFRAME (frame);
|
|
469 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
|
|
470 char **names;
|
|
471 int num_fonts, i;
|
|
472 Lisp_Object list;
|
|
473 char *last_family;
|
|
474 int last_len;
|
|
475
|
|
476 BLOCK_INPUT;
|
|
477 x_catch_errors (dpyinfo->display);
|
|
478 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
|
|
479 0x8000, &num_fonts);
|
|
480 if (x_had_errors_p (dpyinfo->display))
|
|
481 {
|
|
482 /* This error is perhaps due to insufficient memory on X server.
|
|
483 Let's just ignore it. */
|
|
484 x_clear_errors (dpyinfo->display);
|
|
485 num_fonts = 0;
|
|
486 }
|
|
487
|
|
488 list = Qnil;
|
|
489 for (i = 0, last_len = 0; i < num_fonts; i++)
|
|
490 {
|
|
491 char *p0 = names[i], *p1;
|
|
492 Lisp_Object family;
|
|
493
|
|
494 p0++; /* skip the leading '-' */
|
|
495 while (*p0 && *p0 != '-') p0++; /* skip foundry */
|
|
496 if (! *p0)
|
|
497 continue;
|
|
498 p1 = ++p0;
|
|
499 while (*p1 && *p1 != '-') p1++; /* find the end of family */
|
|
500 if (! *p1 || p1 == p0)
|
|
501 continue;
|
|
502 if (last_len == p1 - p0
|
|
503 && bcmp (last_family, p0, last_len) == 0)
|
|
504 continue;
|
|
505 last_len = p1 - p0;
|
|
506 last_family = p0;
|
|
507 family = intern_downcase (p0, last_len);
|
|
508 if (! memq_no_quit (family, list))
|
|
509 list = Fcons (family, list);
|
|
510 }
|
|
511
|
|
512 XFreeFontNames (names);
|
|
513 x_uncatch_errors ();
|
|
514 UNBLOCK_INPUT;
|
|
515
|
|
516 return list;
|
|
517 }
|
|
518
|
|
519 static struct font *
|
|
520 xfont_open (f, entity, pixel_size)
|
|
521 FRAME_PTR f;
|
|
522 Lisp_Object entity;
|
|
523 int pixel_size;
|
|
524 {
|
|
525 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
|
|
526 Display *display = dpyinfo->display;
|
|
527 char name[256];
|
|
528 int len;
|
|
529 unsigned long value;
|
|
530 Lisp_Object registry;
|
|
531 struct charset *encoding, *repertory;
|
|
532 struct font *font;
|
|
533 XFontStruct *xfont;
|
|
534
|
|
535 /* At first, check if we know how to encode characters for this
|
|
536 font. */
|
|
537 registry = AREF (entity, FONT_REGISTRY_INDEX);
|
|
538 if (xfont_registry_charsets (registry, &encoding, &repertory) < 0)
|
|
539 return NULL;
|
|
540
|
|
541 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
|
|
542 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
|
|
543 len = font_unparse_xlfd (entity, pixel_size, name, 256);
|
|
544 if (len <= 0)
|
|
545 return NULL;
|
|
546
|
|
547 BLOCK_INPUT;
|
|
548 x_catch_errors (display);
|
|
549 xfont = XLoadQueryFont (display, name);
|
|
550 if (x_had_errors_p (display))
|
|
551 {
|
|
552 /* This error is perhaps due to insufficient memory on X server.
|
|
553 Let's just ignore it. */
|
|
554 x_clear_errors (display);
|
|
555 xfont = NULL;
|
|
556 }
|
|
557 x_uncatch_errors ();
|
|
558 UNBLOCK_INPUT;
|
|
559
|
|
560 if (! xfont)
|
|
561 return NULL;
|
|
562 font = malloc (sizeof (struct font));
|
|
563 font->font.font = xfont;
|
|
564 font->entity = entity;
|
|
565 font->pixel_size = pixel_size;
|
|
566 font->driver = &xfont_driver;
|
|
567 font->font.name = malloc (len + 1);
|
|
568 if (! font->font.name)
|
|
569 {
|
|
570 XFreeFont (display, xfont);
|
|
571 free (font);
|
|
572 return NULL;
|
|
573 }
|
|
574 bcopy (name, font->font.name, len + 1);
|
|
575 font->font.charset = encoding->id;
|
|
576 font->encoding_charset = encoding->id;
|
|
577 font->repertory_charet = repertory ? repertory->id : -1;
|
|
578 font->ascent = xfont->ascent;
|
|
579 font->descent = xfont->descent;
|
|
580
|
|
581 if (xfont->min_bounds.width == xfont->max_bounds.width)
|
|
582 {
|
|
583 /* Fixed width font. */
|
|
584 font->font.average_width = font->font.space_width
|
|
585 = xfont->min_bounds.width;
|
|
586 }
|
|
587 else
|
|
588 {
|
|
589 XChar2b char2b;
|
|
590 XCharStruct *pcm;
|
|
591
|
|
592 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
|
|
593 pcm = xfont_get_pcm (xfont, &char2b);
|
|
594 if (pcm)
|
|
595 font->font.space_width = pcm->width;
|
|
596 else
|
|
597 font->font.space_width = xfont->max_bounds.width;
|
|
598
|
|
599 font->font.average_width
|
|
600 = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
|
|
601 ? (long) value / 10 : 0);
|
|
602 if (font->font.average_width < 0)
|
|
603 font->font.average_width = - font->font.average_width;
|
|
604 if (font->font.average_width == 0)
|
|
605 {
|
|
606 if (pcm)
|
|
607 {
|
|
608 int width = pcm->width;
|
|
609 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
|
|
610 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
|
|
611 width += pcm->width;
|
|
612 font->font.average_width = width / 95;
|
|
613 }
|
|
614 else
|
|
615 font->font.average_width = xfont->max_bounds.width;
|
|
616 }
|
|
617 }
|
|
618 font->min_width = xfont->min_bounds.width;
|
|
619 if (font->min_width <= 0)
|
|
620 font->min_width = font->font.space_width;
|
|
621
|
|
622 BLOCK_INPUT;
|
|
623 /* Try to get the full name of FONT. Put it in FULL_NAME. */
|
|
624 if (XGetFontProperty (xfont, XA_FONT, &value))
|
|
625 {
|
|
626 char *full_name = NULL, *p0, *p;
|
|
627 int dashes = 0;
|
|
628
|
|
629 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
|
|
630 /* Count the number of dashes in the "full name".
|
|
631 If it is too few, this isn't really the font's full name,
|
|
632 so don't use it.
|
|
633 In X11R4, the fonts did not come with their canonical names
|
|
634 stored in them. */
|
|
635 while (*p)
|
|
636 {
|
|
637 if (*p == '-')
|
|
638 dashes++;
|
|
639 p++;
|
|
640 }
|
|
641
|
|
642 if (dashes >= 13)
|
|
643 {
|
|
644 full_name = (char *) malloc (p - p0 + 1);
|
|
645 if (full_name)
|
|
646 bcopy (p0, full_name, p - p0 + 1);
|
|
647 }
|
|
648 XFree (p0);
|
|
649
|
|
650 if (full_name)
|
|
651 font->font.full_name = full_name;
|
|
652 else
|
|
653 font->font.full_name = font->font.name;
|
|
654 }
|
|
655 font->file_name = NULL;
|
|
656
|
|
657 font->font.size = xfont->max_bounds.width;
|
|
658 font->font.height = xfont->ascent + xfont->descent;
|
|
659 font->font.baseline_offset
|
|
660 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
|
|
661 ? (long) value : 0);
|
|
662 font->font.relative_compose
|
|
663 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
|
|
664 ? (long) value : 0);
|
|
665 font->font.default_ascent
|
|
666 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
|
|
667 ? (long) value : 0);
|
|
668 font->font.vertical_centering
|
|
669 = (STRINGP (Vvertical_centering_font_regexp)
|
|
670 && (fast_c_string_match_ignore_case
|
|
671 (Vvertical_centering_font_regexp, font->font.full_name) >= 0));
|
|
672
|
|
673 UNBLOCK_INPUT;
|
|
674
|
|
675 dpyinfo->n_fonts++;
|
|
676
|
|
677 /* Set global flag fonts_changed_p to non-zero if the font loaded
|
|
678 has a character with a smaller width than any other character
|
|
679 before, or if the font loaded has a smaller height than any other
|
|
680 font loaded before. If this happens, it will make a glyph matrix
|
|
681 reallocation necessary. */
|
|
682 if (dpyinfo->n_fonts == 1)
|
|
683 {
|
|
684 dpyinfo->smallest_font_height = font->font.height;
|
|
685 dpyinfo->smallest_char_width = font->min_width;
|
|
686 fonts_changed_p = 1;
|
|
687 }
|
|
688 else
|
|
689 {
|
|
690 if (dpyinfo->smallest_font_height > font->font.height)
|
|
691 dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1;
|
|
692 if (dpyinfo->smallest_char_width > font->min_width)
|
|
693 dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1;
|
|
694 }
|
|
695
|
|
696 return font;
|
|
697 }
|
|
698
|
|
699 static void
|
|
700 xfont_close (f, font)
|
|
701 FRAME_PTR f;
|
|
702 struct font *font;
|
|
703 {
|
|
704 BLOCK_INPUT;
|
|
705 XFreeFont (FRAME_X_DISPLAY (f), font->font.font);
|
|
706 UNBLOCK_INPUT;
|
|
707
|
|
708 if (font->font.name != font->font.full_name)
|
|
709 free (font->font.full_name);
|
|
710 free (font->font.name);
|
|
711 free (font);
|
|
712 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
|
|
713 }
|
|
714
|
|
715 static int
|
|
716 xfont_prepare_face (f, face)
|
|
717 FRAME_PTR f;
|
|
718 struct face *face;
|
|
719 {
|
|
720 BLOCK_INPUT;
|
|
721 XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid);
|
|
722 UNBLOCK_INPUT;
|
|
723
|
|
724 return 0;
|
|
725 }
|
|
726
|
|
727 #if 0
|
|
728 static void
|
|
729 xfont_done_face (f, face)
|
|
730 FRAME_PTR f;
|
|
731 struct face *face;
|
|
732 {
|
|
733 if (face->extra)
|
|
734 {
|
|
735 BLOCK_INPUT;
|
|
736 XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra);
|
|
737 UNBLOCK_INPUT;
|
|
738 face->extra = NULL;
|
|
739 }
|
|
740 }
|
|
741 #endif /* 0 */
|
|
742
|
|
743 static int
|
|
744 xfont_has_char (entity, c)
|
|
745 Lisp_Object entity;
|
|
746 int c;
|
|
747 {
|
|
748 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
|
|
749 struct charset *repertory;
|
|
750
|
|
751 if (xfont_registry_charsets (registry, NULL, &repertory) < 0)
|
|
752 return -1;
|
|
753 if (! repertory)
|
|
754 return -1;
|
|
755 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
|
|
756 }
|
|
757
|
|
758 static unsigned
|
|
759 xfont_encode_char (font, c)
|
|
760 struct font *font;
|
|
761 int c;
|
|
762 {
|
|
763 struct charset *charset;
|
|
764 unsigned code;
|
|
765 XChar2b char2b;
|
|
766
|
|
767 charset = CHARSET_FROM_ID (font->encoding_charset);
|
|
768 code = ENCODE_CHAR (charset, c);
|
|
769 if (code == CHARSET_INVALID_CODE (charset))
|
|
770 return 0xFFFFFFFF;
|
|
771 if (font->repertory_charet >= 0)
|
|
772 {
|
|
773 charset = CHARSET_FROM_ID (font->repertory_charet);
|
|
774 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
|
|
775 ? code : 0xFFFFFFFF);
|
|
776 }
|
|
777 char2b.byte1 = code >> 16;
|
|
778 char2b.byte2 = code & 0xFFFF;
|
|
779 return (xfont_get_pcm (font->font.font, &char2b) ? code : 0xFFFFFFFF);
|
|
780 }
|
|
781
|
|
782 static int
|
|
783 xfont_text_extents (font, code, nglyphs, metrics)
|
|
784 struct font *font;
|
|
785 unsigned *code;
|
|
786 int nglyphs;
|
|
787 struct font_metrics *metrics;
|
|
788 {
|
|
789 int width = 0;
|
|
790 int i, x;
|
|
791
|
|
792 if (metrics)
|
|
793 bzero (metrics, sizeof (struct font_metrics));
|
|
794 for (i = 0, x = 0; i < nglyphs; i++)
|
|
795 {
|
|
796 XChar2b char2b;
|
|
797 static XCharStruct *pcm;
|
|
798
|
|
799 if (code[i] >= 0x10000)
|
|
800 continue;
|
|
801 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
|
|
802 pcm = xfont_get_pcm (font->font.font, &char2b);
|
|
803 if (! pcm)
|
|
804 continue;
|
|
805 if (metrics->lbearing > width + pcm->lbearing)
|
|
806 metrics->lbearing = width + pcm->lbearing;
|
|
807 if (metrics->rbearing < width + pcm->rbearing)
|
|
808 metrics->rbearing = width + pcm->rbearing;
|
|
809 if (metrics->ascent < pcm->ascent)
|
|
810 metrics->ascent = pcm->ascent;
|
|
811 if (metrics->descent < pcm->descent)
|
|
812 metrics->descent = pcm->descent;
|
|
813 width += pcm->width;
|
|
814 }
|
|
815 if (metrics)
|
|
816 metrics->width = width;
|
|
817 return width;
|
|
818 }
|
|
819
|
|
820 static int
|
|
821 xfont_draw (s, from, to, x, y, with_background)
|
|
822 struct glyph_string *s;
|
|
823 int from, to, x, y, with_background;
|
|
824 {
|
|
825 XFontStruct *xfont = s->face->font;
|
|
826 int len = to - from;
|
|
827
|
|
828 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
|
|
829 {
|
|
830 char *str;
|
|
831 int i;
|
|
832 USE_SAFE_ALLOCA;
|
|
833
|
|
834 SAFE_ALLOCA (str, char *, len);
|
|
835 for (i = 0; i < len ; i++)
|
|
836 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
|
|
837 if (with_background > 0)
|
|
838 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
|
839 s->gc, x, y, str, len);
|
|
840 else
|
|
841 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
|
842 s->gc, x, y, str, len);
|
|
843 SAFE_FREE ();
|
|
844 return s->nchars;
|
|
845 }
|
|
846
|
|
847 if (with_background > 0)
|
|
848 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
|
849 s->gc, x, y, s->char2b + from, len);
|
|
850 else
|
|
851 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
|
|
852 s->gc, x, y, s->char2b + from, len);
|
|
853
|
|
854 return len;
|
|
855 }
|
|
856
|
|
857
|
|
858
|
|
859 void
|
|
860 syms_of_xfont ()
|
|
861 {
|
|
862 staticpro (&x_font_charset_alist);
|
|
863 x_font_charset_alist = Qnil;
|
|
864
|
|
865 DEFSYM (Qx, "x");
|
|
866 xfont_driver.type = Qx;
|
|
867 register_font_driver (&xfont_driver, NULL);
|
|
868 }
|