Mercurial > emacs
comparison src/xfont.c @ 94940:061d44df20b7
Include <stdlib.h> and "ccl.h".
(struct xfont_info): New structure.
(xfont_query_font): Deleted.
(xfont_find_ccl_program): Renamed from x_find_ccl_program and
moved from xterm.c.
(xfont_driver): Adjusted for the change of struct font_driver.
(compare_font_names): New function.
(xfont_list_pattern): Sort font names case insensitively. Make
font_entity by calling font_make_entity. Avoid auto-scaled fonts.
(xfont_list): Return a list, not vector.
(xfont_match): If the font doesn't have QCname property, generate
a name from the other font properties.
(xfont_open): Return a font-ojbect. Adjusted for the change of
struct font. Get underline_thickness and underline_position from
font property. Don't update dpyinfo->smallest_font_height and
dpyinfo->smallest_char_width.
(xfont_close): Don't free struct font.
(xfont_prepare_face): Adjusted for the change of struct font.
(xfont_done_face): Deleted.
(xfont_has_char): Adjusted for the change of struct font.
(xfont_encode_char, xfont_draw): Likewise.
(xfont_check): New function.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Wed, 14 May 2008 01:42:33 +0000 |
parents | 1e28008a13e5 |
children | 8971ddf55736 |
comparison
equal
deleted
inserted
replaced
94939:da7871784939 | 94940:061d44df20b7 |
---|---|
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
22 Boston, MA 02110-1301, USA. */ | 22 Boston, MA 02110-1301, USA. */ |
23 | 23 |
24 #include <config.h> | 24 #include <config.h> |
25 #include <stdio.h> | 25 #include <stdio.h> |
26 #include <stdlib.h> | |
26 #include <X11/Xlib.h> | 27 #include <X11/Xlib.h> |
27 | 28 |
28 #include "lisp.h" | 29 #include "lisp.h" |
29 #include "dispextern.h" | 30 #include "dispextern.h" |
30 #include "xterm.h" | 31 #include "xterm.h" |
32 #include "blockinput.h" | 33 #include "blockinput.h" |
33 #include "character.h" | 34 #include "character.h" |
34 #include "charset.h" | 35 #include "charset.h" |
35 #include "fontset.h" | 36 #include "fontset.h" |
36 #include "font.h" | 37 #include "font.h" |
38 #include "ccl.h" | |
37 | 39 |
38 | 40 |
39 /* X core font driver. */ | 41 /* X core font driver. */ |
40 | 42 |
43 struct xfont_info | |
44 { | |
45 struct font font; | |
46 Display *display; | |
47 XFontStruct *xfont; | |
48 }; | |
49 | |
41 /* Prototypes of support functions. */ | 50 /* Prototypes of support functions. */ |
42 extern void x_clear_errors P_ ((Display *)); | 51 extern void x_clear_errors P_ ((Display *)); |
43 | 52 |
44 static char *xfont_query_font P_ ((Display *, char *, Lisp_Object)); | |
45 static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *)); | 53 static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *)); |
54 static void xfont_find_ccl_program P_ ((struct font *)); | |
46 static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **, | 55 static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **, |
47 struct charset **)); | 56 struct charset **)); |
48 | |
49 static char * | |
50 xfont_query_font (display, name, spec) | |
51 Display *display; | |
52 char *name; | |
53 Lisp_Object spec; | |
54 { | |
55 XFontStruct *font; | |
56 | |
57 BLOCK_INPUT; | |
58 x_catch_errors (display); | |
59 font = XLoadQueryFont (display, name); | |
60 name = NULL; | |
61 if (x_had_errors_p (display)) | |
62 { | |
63 /* This error is perhaps due to insufficient memory on X | |
64 server. Let's just ignore it. */ | |
65 x_clear_errors (display); | |
66 } | |
67 else if (font) | |
68 { | |
69 unsigned long value; | |
70 | |
71 if (XGetFontProperty (font, XA_FONT, &value)) | |
72 { | |
73 char *n = (char *) XGetAtomName (display, (Atom) value); | |
74 | |
75 if (font_parse_xlfd (n, spec) >= 0) | |
76 name = n; | |
77 else | |
78 XFree (n); | |
79 } | |
80 XFreeFont (display, font); | |
81 } | |
82 x_uncatch_errors (); | |
83 UNBLOCK_INPUT; | |
84 | |
85 return name; | |
86 } | |
87 | 57 |
88 | 58 |
89 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B | 59 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B |
90 is not contained in the font. */ | 60 is not contained in the font. */ |
91 | 61 |
152 return ((pcm == NULL | 122 return ((pcm == NULL |
153 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)) | 123 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)) |
154 ? NULL : pcm); | 124 ? NULL : pcm); |
155 } | 125 } |
156 | 126 |
127 /* Find a CCL program for a font specified by FONTP, and set the member | |
128 `encoder' of the structure. */ | |
129 | |
130 static void | |
131 xfont_find_ccl_program (font) | |
132 struct font *font; | |
133 { | |
134 Lisp_Object list, elt; | |
135 | |
136 elt = Qnil; | |
137 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list)) | |
138 { | |
139 elt = XCAR (list); | |
140 if (CONSP (elt) | |
141 && STRINGP (XCAR (elt)) | |
142 && ((fast_string_match_ignore_case (XCAR (elt), | |
143 font->props[FONT_NAME_INDEX]) | |
144 >= 0) | |
145 || (fast_string_match_ignore_case (XCAR (elt), | |
146 font->props[FONT_FULLNAME_INDEX]) | |
147 >= 0))) | |
148 break; | |
149 } | |
150 | |
151 if (! NILP (list)) | |
152 { | |
153 struct ccl_program *ccl | |
154 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program)); | |
155 | |
156 if (setup_ccl_program (ccl, XCDR (elt)) < 0) | |
157 xfree (ccl); | |
158 else | |
159 font->font_encoder = ccl; | |
160 } | |
161 } | |
162 | |
157 static Lisp_Object xfont_get_cache P_ ((FRAME_PTR)); | 163 static Lisp_Object xfont_get_cache P_ ((FRAME_PTR)); |
158 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object)); | 164 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object)); |
159 static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object)); | 165 static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object)); |
160 static Lisp_Object xfont_list_family P_ ((Lisp_Object)); | 166 static Lisp_Object xfont_list_family P_ ((Lisp_Object)); |
161 static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int)); | 167 static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int)); |
162 static void xfont_close P_ ((FRAME_PTR, struct font *)); | 168 static void xfont_close P_ ((FRAME_PTR, struct font *)); |
163 static int xfont_prepare_face P_ ((FRAME_PTR, struct face *)); | 169 static int xfont_prepare_face P_ ((FRAME_PTR, struct face *)); |
164 #if 0 | |
165 static void xfont_done_face P_ ((FRAME_PTR, struct face *)); | |
166 #endif | |
167 static int xfont_has_char P_ ((Lisp_Object, int)); | 170 static int xfont_has_char P_ ((Lisp_Object, int)); |
168 static unsigned xfont_encode_char P_ ((struct font *, int)); | 171 static unsigned xfont_encode_char P_ ((struct font *, int)); |
169 static int xfont_text_extents P_ ((struct font *, unsigned *, int, | 172 static int xfont_text_extents P_ ((struct font *, unsigned *, int, |
170 struct font_metrics *)); | 173 struct font_metrics *)); |
171 static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int)); | 174 static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int)); |
175 static int xfont_check P_ ((FRAME_PTR, struct font *)); | |
172 | 176 |
173 struct font_driver xfont_driver = | 177 struct font_driver xfont_driver = |
174 { | 178 { |
175 0, /* Qx */ | 179 0, /* Qx */ |
180 0, /* case insensitive */ | |
176 xfont_get_cache, | 181 xfont_get_cache, |
177 xfont_list, | 182 xfont_list, |
178 xfont_match, | 183 xfont_match, |
179 xfont_list_family, | 184 xfont_list_family, |
180 NULL, | 185 NULL, |
181 xfont_open, | 186 xfont_open, |
182 xfont_close, | 187 xfont_close, |
183 xfont_prepare_face, | 188 xfont_prepare_face, |
184 NULL /*xfont_done_face*/, | 189 NULL, |
185 xfont_has_char, | 190 xfont_has_char, |
186 xfont_encode_char, | 191 xfont_encode_char, |
187 xfont_text_extents, | 192 xfont_text_extents, |
188 xfont_draw | 193 xfont_draw, |
194 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
195 xfont_check | |
189 }; | 196 }; |
190 | 197 |
191 extern Lisp_Object QCname; | 198 extern Lisp_Object QCname; |
192 | 199 |
193 static Lisp_Object | 200 static Lisp_Object |
198 | 205 |
199 return (dpyinfo->name_list_element); | 206 return (dpyinfo->name_list_element); |
200 } | 207 } |
201 | 208 |
202 extern Lisp_Object Vface_alternative_font_registry_alist; | 209 extern Lisp_Object Vface_alternative_font_registry_alist; |
210 | |
211 static int | |
212 compare_font_names (const void *name1, const void *name2) | |
213 { | |
214 return strcasecmp (*(const char **) name1, *(const char **) name2); | |
215 } | |
216 | |
217 static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *)); | |
203 | 218 |
204 static Lisp_Object | 219 static Lisp_Object |
205 xfont_list_pattern (frame, display, pattern) | 220 xfont_list_pattern (frame, display, pattern) |
206 Lisp_Object frame; | 221 Lisp_Object frame; |
207 Display *display; | 222 Display *display; |
228 if (num_fonts < limit) | 243 if (num_fonts < limit) |
229 break; | 244 break; |
230 XFreeFontNames (names); | 245 XFreeFontNames (names); |
231 } | 246 } |
232 | 247 |
233 for (i = 0; i < num_fonts; i++) | 248 if (num_fonts > 0) |
234 { | 249 { |
235 Lisp_Object entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil); | 250 char **indices = alloca (sizeof (char *) * num_fonts); |
236 int result; | 251 |
237 | 252 for (i = 0; i < num_fonts; i++) |
238 ASET (entity, FONT_TYPE_INDEX, Qx); | 253 indices[i] = names[i]; |
239 ASET (entity, FONT_FRAME_INDEX, frame); | 254 qsort (indices, num_fonts, sizeof (char *), compare_font_names); |
240 | 255 |
241 result = font_parse_xlfd (names[i], entity); | 256 for (i = 0; i < num_fonts; i++) |
242 if (result < 0) | 257 { |
243 { | 258 Lisp_Object entity; |
244 /* This may be an alias name. Try to get the full XLFD name | 259 int result; |
245 from XA_FONT property of the font. */ | 260 |
246 XFontStruct *font = XLoadQueryFont (display, names[i]); | 261 if (i > 0 && strcasecmp (indices[i - 1], indices[i]) == 0) |
247 unsigned long value; | |
248 | |
249 if (! font) | |
250 continue; | 262 continue; |
251 if (XGetFontProperty (font, XA_FONT, &value)) | 263 |
264 entity = font_make_entity (); | |
265 ASET (entity, FONT_TYPE_INDEX, Qx); | |
266 | |
267 result = font_parse_xlfd (indices[i], entity); | |
268 if (result < 0) | |
252 { | 269 { |
253 char *name = (char *) XGetAtomName (display, (Atom) value); | 270 /* This may be an alias name. Try to get the full XLFD name |
254 int len = strlen (name); | 271 from XA_FONT property of the font. */ |
255 | 272 XFontStruct *font = XLoadQueryFont (display, indices[i]); |
256 /* If DXPC (a Differential X Protocol Compressor) | 273 unsigned long value; |
257 Ver.3.7 is running, XGetAtomName will return null | 274 |
258 string. We must avoid such a name. */ | 275 if (! font) |
259 if (len > 0) | 276 continue; |
260 result = font_parse_xlfd (name, entity); | 277 if (XGetFontProperty (font, XA_FONT, &value)) |
261 XFree (name); | 278 { |
279 char *name = (char *) XGetAtomName (display, (Atom) value); | |
280 int len = strlen (name); | |
281 | |
282 /* If DXPC (a Differential X Protocol Compressor) | |
283 Ver.3.7 is running, XGetAtomName will return null | |
284 string. We must avoid such a name. */ | |
285 if (len > 0) | |
286 result = font_parse_xlfd (name, entity); | |
287 XFree (name); | |
288 } | |
289 XFreeFont (display, font); | |
262 } | 290 } |
263 XFreeFont (display, font); | 291 |
264 } | 292 if (result == 0 |
265 | 293 /* Avoid auto-scaled fonts. */ |
266 if (result == 0) | 294 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0 |
267 { | 295 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0)) |
268 Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX); | 296 list = Fcons (entity, list); |
269 char *p = (char *) SDATA (SYMBOL_NAME (val)); | |
270 | |
271 /* P == "RESX-RESY-SPACING-AVGWIDTH. We rejust this font if | |
272 it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0). */ | |
273 if (atoi (p) > 0) | |
274 { | |
275 p += SBYTES (SYMBOL_NAME (val)); | |
276 while (p[-1] != '-') p--; | |
277 if (atoi (p) == 0) | |
278 continue; | |
279 } | |
280 list = Fcons (entity, list); | |
281 } | 297 } |
282 } | 298 } |
283 | 299 |
284 x_uncatch_errors (); | 300 x_uncatch_errors (); |
285 UNBLOCK_INPUT; | 301 UNBLOCK_INPUT; |
291 xfont_list (frame, spec) | 307 xfont_list (frame, spec) |
292 Lisp_Object frame, spec; | 308 Lisp_Object frame, spec; |
293 { | 309 { |
294 FRAME_PTR f = XFRAME (frame); | 310 FRAME_PTR f = XFRAME (frame); |
295 Display *display = FRAME_X_DISPLAY_INFO (f)->display; | 311 Display *display = FRAME_X_DISPLAY_INFO (f)->display; |
296 Lisp_Object list, val, extra, font_name; | 312 Lisp_Object registry, list, val, extra, font_name; |
313 Lisp_Object dpi, avgwidth; | |
297 int len; | 314 int len; |
298 char name[256]; | 315 char name[256]; |
299 | 316 |
300 extra = AREF (spec, FONT_EXTRA_INDEX); | 317 extra = AREF (spec, FONT_EXTRA_INDEX); |
301 font_name = Qnil; | |
302 if (CONSP (extra)) | 318 if (CONSP (extra)) |
303 { | 319 { |
304 val = assq_no_quit (QCotf, extra); | 320 val = assq_no_quit (QCotf, extra); |
305 if (! NILP (val)) | 321 if (! NILP (val)) |
306 return null_vector; | 322 return Qnil; |
307 val = assq_no_quit (QCscript, extra); | 323 val = assq_no_quit (QCscript, extra); |
308 if (! NILP (val)) | 324 if (! NILP (val)) |
309 return null_vector; | 325 return Qnil; |
310 val = assq_no_quit (QClanguage, extra); | 326 val = assq_no_quit (QClang, extra); |
311 if (! NILP (val)) | 327 if (! NILP (val)) |
312 return null_vector; | 328 return Qnil; |
313 val = assq_no_quit (QCname, extra); | 329 } |
314 if (CONSP (val)) | 330 |
315 font_name = XCDR (val); | 331 registry = AREF (spec, FONT_REGISTRY_INDEX); |
316 } | 332 if (NILP (registry)) |
317 | 333 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1); |
318 if (STRINGP (font_name) | 334 len = font_unparse_xlfd (spec, 0, name, 256); |
319 && ! strchr ((char *) SDATA (font_name), ':')) | 335 ASET (spec, FONT_REGISTRY_INDEX, registry); |
320 list = xfont_list_pattern (frame, display, (char *) SDATA (font_name)); | 336 if (len < 0) |
321 else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0) | 337 return Qnil; |
322 return null_vector; | 338 list = xfont_list_pattern (frame, display, name); |
323 else | 339 if (NILP (list) && NILP (registry)) |
324 { | 340 { |
325 list = xfont_list_pattern (frame, display, name); | 341 /* Try iso10646-1 */ |
326 if (NILP (list)) | 342 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */ |
327 { | 343 |
328 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX); | 344 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */ |
329 Lisp_Object alter; | 345 { |
330 | 346 strcpy (r, "iso10646-1"); |
331 if (! NILP (registry) | 347 list = xfont_list_pattern (frame, display, name); |
332 && (alter = Fassoc (SYMBOL_NAME (registry), | 348 } |
333 Vface_alternative_font_registry_alist), | 349 } |
334 CONSP (alter))) | 350 if (NILP (list) && ! NILP (registry)) |
335 { | 351 { |
336 /* Pointer to REGISTRY-ENCODING field. */ | 352 Lisp_Object alter; |
337 char *r = name + len - SBYTES (SYMBOL_NAME (registry)); | 353 |
338 | 354 if ((alter = Fassoc (SYMBOL_NAME (registry), |
339 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter)) | 355 Vface_alternative_font_registry_alist), |
340 if (STRINGP (XCAR (alter)) | 356 CONSP (alter))) |
341 && ((r - name) + SBYTES (XCAR (alter))) < 255) | 357 { |
342 { | 358 /* Pointer to REGISTRY-ENCODING field. */ |
343 strcpy (r, (char *) SDATA (XCAR (alter))); | 359 char *r = name + len - SBYTES (SYMBOL_NAME (registry)); |
344 list = xfont_list_pattern (frame, display, name); | 360 |
345 if (! NILP (list)) | 361 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter)) |
346 break; | 362 if (STRINGP (XCAR (alter)) |
347 } | 363 && ((r - name) + SBYTES (XCAR (alter))) < 256) |
348 } | 364 { |
349 } | 365 strcpy (r, (char *) SDATA (XCAR (alter))); |
350 } | 366 list = xfont_list_pattern (frame, display, name); |
351 | 367 if (! NILP (list)) |
352 return (NILP (list) ? null_vector : Fvconcat (1, &list)); | 368 break; |
369 } | |
370 } | |
371 } | |
372 | |
373 return list; | |
353 } | 374 } |
354 | 375 |
355 static Lisp_Object | 376 static Lisp_Object |
356 xfont_match (frame, spec) | 377 xfont_match (frame, spec) |
357 Lisp_Object frame, spec; | 378 Lisp_Object frame, spec; |
358 { | 379 { |
359 FRAME_PTR f = XFRAME (frame); | 380 FRAME_PTR f = XFRAME (frame); |
360 Display *display = FRAME_X_DISPLAY_INFO (f)->display; | 381 Display *display = FRAME_X_DISPLAY_INFO (f)->display; |
361 Lisp_Object extra, val, entity; | 382 Lisp_Object extra, val, entity; |
362 char *name; | 383 char buf[256], *name; |
363 XFontStruct *xfont; | 384 XFontStruct *xfont; |
364 unsigned long value; | 385 unsigned long value; |
365 | 386 |
366 extra = AREF (spec, FONT_EXTRA_INDEX); | 387 extra = AREF (spec, FONT_EXTRA_INDEX); |
367 val = assq_no_quit (QCname, extra); | 388 val = assq_no_quit (QCname, extra); |
368 if (! CONSP (val) || ! STRINGP (XCDR (val))) | 389 if (! CONSP (val) || ! STRINGP (XCDR (val))) |
369 return Qnil; | 390 { |
391 if (font_unparse_xlfd (spec, 0, buf, 256) < 0) | |
392 return Qnil; | |
393 name = buf; | |
394 } | |
395 else | |
396 name = (char *) SDATA (XCDR (val)); | |
370 | 397 |
371 BLOCK_INPUT; | 398 BLOCK_INPUT; |
372 entity = Qnil; | 399 entity = Qnil; |
373 name = (char *) SDATA (XCDR (val)); | |
374 xfont = XLoadQueryFont (display, name); | 400 xfont = XLoadQueryFont (display, name); |
375 if (xfont) | 401 if (xfont) |
376 { | 402 { |
377 if (XGetFontProperty (xfont, XA_FONT, &value)) | 403 if (XGetFontProperty (xfont, XA_FONT, &value)) |
378 { | 404 { |
384 /* If DXPC (a Differential X Protocol Compressor) | 410 /* If DXPC (a Differential X Protocol Compressor) |
385 Ver.3.7 is running, XGetAtomName will return null | 411 Ver.3.7 is running, XGetAtomName will return null |
386 string. We must avoid such a name. */ | 412 string. We must avoid such a name. */ |
387 if (len > 0) | 413 if (len > 0) |
388 { | 414 { |
389 entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil); | 415 entity = font_make_entity (); |
390 ASET (entity, FONT_TYPE_INDEX, Qx); | 416 ASET (entity, FONT_TYPE_INDEX, Qx); |
391 ASET (entity, FONT_FRAME_INDEX, frame); | |
392 if (font_parse_xlfd (name, entity) < 0) | 417 if (font_parse_xlfd (name, entity) < 0) |
393 entity = Qnil; | 418 entity = Qnil; |
394 } | 419 } |
395 XFree (name); | 420 XFree (name); |
396 } | 421 } |
451 if (last_len == p1 - p0 | 476 if (last_len == p1 - p0 |
452 && bcmp (last_family, p0, last_len) == 0) | 477 && bcmp (last_family, p0, last_len) == 0) |
453 continue; | 478 continue; |
454 last_len = p1 - p0; | 479 last_len = p1 - p0; |
455 last_family = p0; | 480 last_family = p0; |
456 family = intern_downcase (p0, last_len); | 481 family = make_unibyte_string (p0, last_len); |
457 if (! memq_no_quit (family, list)) | 482 if (NILP (Fassoc_string (family, list, Qt))) |
458 list = Fcons (family, list); | 483 list = Fcons (family, list); |
459 } | 484 } |
460 | 485 |
461 XFreeFontNames (names); | 486 XFreeFontNames (names); |
462 x_uncatch_errors (); | 487 x_uncatch_errors (); |
463 UNBLOCK_INPUT; | 488 UNBLOCK_INPUT; |
464 | 489 |
465 return list; | 490 return list; |
466 } | 491 } |
467 | 492 |
468 static struct font * | 493 extern Lisp_Object QCavgwidth; |
494 | |
495 static Lisp_Object | |
469 xfont_open (f, entity, pixel_size) | 496 xfont_open (f, entity, pixel_size) |
470 FRAME_PTR f; | 497 FRAME_PTR f; |
471 Lisp_Object entity; | 498 Lisp_Object entity; |
472 int pixel_size; | 499 int pixel_size; |
473 { | 500 { |
476 char name[256]; | 503 char name[256]; |
477 int len; | 504 int len; |
478 unsigned long value; | 505 unsigned long value; |
479 Lisp_Object registry; | 506 Lisp_Object registry; |
480 struct charset *encoding, *repertory; | 507 struct charset *encoding, *repertory; |
508 Lisp_Object font_object, fullname; | |
481 struct font *font; | 509 struct font *font; |
482 XFontStruct *xfont; | 510 XFontStruct *xfont; |
511 int i; | |
483 | 512 |
484 /* At first, check if we know how to encode characters for this | 513 /* At first, check if we know how to encode characters for this |
485 font. */ | 514 font. */ |
486 registry = AREF (entity, FONT_REGISTRY_INDEX); | 515 registry = AREF (entity, FONT_REGISTRY_INDEX); |
487 if (font_registry_charsets (registry, &encoding, &repertory) < 0) | 516 if (font_registry_charsets (registry, &encoding, &repertory) < 0) |
488 return NULL; | 517 return Qnil; |
489 | 518 |
490 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0) | 519 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0) |
491 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX)); | 520 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX)); |
521 else if (pixel_size == 0) | |
522 { | |
523 if (FRAME_FONT (f)) | |
524 pixel_size = FRAME_FONT (f)->pixel_size; | |
525 else | |
526 pixel_size = 14; | |
527 } | |
492 len = font_unparse_xlfd (entity, pixel_size, name, 256); | 528 len = font_unparse_xlfd (entity, pixel_size, name, 256); |
493 if (len <= 0) | 529 if (len <= 0) |
494 return NULL; | 530 return Qnil; |
495 | 531 |
496 BLOCK_INPUT; | 532 BLOCK_INPUT; |
497 x_catch_errors (display); | 533 x_catch_errors (display); |
498 xfont = XLoadQueryFont (display, name); | 534 xfont = XLoadQueryFont (display, name); |
499 if (x_had_errors_p (display)) | 535 if (x_had_errors_p (display)) |
501 /* This error is perhaps due to insufficient memory on X server. | 537 /* This error is perhaps due to insufficient memory on X server. |
502 Let's just ignore it. */ | 538 Let's just ignore it. */ |
503 x_clear_errors (display); | 539 x_clear_errors (display); |
504 xfont = NULL; | 540 xfont = NULL; |
505 } | 541 } |
506 x_uncatch_errors (); | 542 fullname = Qnil; |
507 UNBLOCK_INPUT; | 543 /* Try to get the full name of FONT. */ |
508 | 544 if (xfont && XGetFontProperty (xfont, XA_FONT, &value)) |
509 if (! xfont) | 545 { |
510 return NULL; | 546 char *p0, *p; |
511 font = malloc (sizeof (struct font)); | |
512 font->format = Qx; | |
513 font->font.font = xfont; | |
514 font->entity = entity; | |
515 font->pixel_size = pixel_size; | |
516 font->driver = &xfont_driver; | |
517 font->font.name = malloc (len + 1); | |
518 if (! font->font.name) | |
519 { | |
520 XFreeFont (display, xfont); | |
521 free (font); | |
522 return NULL; | |
523 } | |
524 bcopy (name, font->font.name, len + 1); | |
525 font->font.charset = encoding->id; | |
526 font->encoding_charset = encoding->id; | |
527 font->repertory_charset = repertory ? repertory->id : -1; | |
528 font->ascent = xfont->ascent; | |
529 font->descent = xfont->descent; | |
530 | |
531 if (xfont->min_bounds.width == xfont->max_bounds.width) | |
532 { | |
533 /* Fixed width font. */ | |
534 font->font.average_width = font->font.space_width | |
535 = xfont->min_bounds.width; | |
536 } | |
537 else | |
538 { | |
539 XChar2b char2b; | |
540 XCharStruct *pcm; | |
541 | |
542 char2b.byte1 = 0x00, char2b.byte2 = 0x20; | |
543 pcm = xfont_get_pcm (xfont, &char2b); | |
544 if (pcm) | |
545 font->font.space_width = pcm->width; | |
546 else | |
547 font->font.space_width = xfont->max_bounds.width; | |
548 | |
549 font->font.average_width | |
550 = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value) | |
551 ? (long) value / 10 : 0); | |
552 if (font->font.average_width < 0) | |
553 font->font.average_width = - font->font.average_width; | |
554 if (font->font.average_width == 0) | |
555 { | |
556 if (pcm) | |
557 { | |
558 int width = pcm->width; | |
559 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++) | |
560 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL) | |
561 width += pcm->width; | |
562 font->font.average_width = width / 95; | |
563 } | |
564 else | |
565 font->font.average_width = xfont->max_bounds.width; | |
566 } | |
567 } | |
568 font->min_width = xfont->min_bounds.width; | |
569 if (font->min_width <= 0) | |
570 font->min_width = font->font.space_width; | |
571 | |
572 BLOCK_INPUT; | |
573 /* Try to get the full name of FONT. Put it in FULL_NAME. */ | |
574 if (XGetFontProperty (xfont, XA_FONT, &value)) | |
575 { | |
576 char *full_name = NULL, *p0, *p; | |
577 int dashes = 0; | 547 int dashes = 0; |
578 | 548 |
579 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);; | 549 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);; |
580 /* Count the number of dashes in the "full name". | 550 /* Count the number of dashes in the "full name". |
581 If it is too few, this isn't really the font's full name, | 551 If it is too few, this isn't really the font's full name, |
588 dashes++; | 558 dashes++; |
589 p++; | 559 p++; |
590 } | 560 } |
591 | 561 |
592 if (dashes >= 13) | 562 if (dashes >= 13) |
593 { | 563 fullname = Fdowncase (make_unibyte_string (p0, p - p0)); |
594 full_name = (char *) malloc (p - p0 + 1); | |
595 if (full_name) | |
596 bcopy (p0, full_name, p - p0 + 1); | |
597 } | |
598 XFree (p0); | 564 XFree (p0); |
599 | 565 } |
600 if (full_name) | 566 x_uncatch_errors (); |
601 font->font.full_name = full_name; | 567 UNBLOCK_INPUT; |
568 | |
569 if (! xfont) | |
570 return Qnil; | |
571 | |
572 font_object = font_make_object (VECSIZE (struct xfont_info)); | |
573 ASET (font_object, FONT_TYPE_INDEX, Qx); | |
574 if (STRINGP (fullname)) | |
575 font_parse_xlfd (SDATA (fullname), font_object); | |
576 for (i = 1; i < FONT_ENTITY_MAX; i++) | |
577 ASET (font_object, i, AREF (entity, i)); | |
578 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size)); | |
579 if (STRINGP (fullname)) | |
580 ASET (font_object, FONT_NAME_INDEX, fullname); | |
581 else | |
582 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len)); | |
583 ASET (font_object, FONT_FULLNAME_INDEX, fullname); | |
584 ASET (font_object, FONT_FILE_INDEX, Qnil); | |
585 ASET (font_object, FONT_FORMAT_INDEX, Qx); | |
586 font = XFONT_OBJECT (font_object); | |
587 ((struct xfont_info *) font)->xfont = xfont; | |
588 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f); | |
589 font->pixel_size = pixel_size; | |
590 font->driver = &xfont_driver; | |
591 font->encoding_charset = encoding->id; | |
592 font->repertory_charset = repertory ? repertory->id : -1; | |
593 font->ascent = xfont->ascent; | |
594 font->descent = xfont->descent; | |
595 font->height = font->ascent + font->descent; | |
596 font->min_width = xfont->min_bounds.width; | |
597 if (xfont->min_bounds.width == xfont->max_bounds.width) | |
598 { | |
599 /* Fixed width font. */ | |
600 font->average_width = font->space_width = xfont->min_bounds.width; | |
601 } | |
602 else | |
603 { | |
604 XCharStruct *pcm; | |
605 XChar2b char2b; | |
606 Lisp_Object val; | |
607 | |
608 char2b.byte1 = 0x00, char2b.byte2 = 0x20; | |
609 pcm = xfont_get_pcm (xfont, &char2b); | |
610 if (pcm) | |
611 font->space_width = pcm->width; | |
602 else | 612 else |
603 font->font.full_name = font->font.name; | 613 font->space_width = 0; |
604 } | 614 |
605 font->file_name = NULL; | 615 val = Ffont_get (font_object, QCavgwidth); |
606 | 616 if (INTEGERP (val)) |
607 font->font.size = xfont->max_bounds.width; | 617 font->average_width = XINT (val); |
608 font->font.height = xfont->ascent + xfont->descent; | 618 if (font->average_width < 0) |
609 font->font.baseline_offset | 619 font->average_width = - font->average_width; |
620 if (font->average_width == 0 | |
621 && encoding->ascii_compatible_p) | |
622 { | |
623 int width = font->space_width, n = pcm != NULL; | |
624 | |
625 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++) | |
626 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL) | |
627 width += pcm->width, n++; | |
628 font->average_width = width / n; | |
629 } | |
630 } | |
631 | |
632 BLOCK_INPUT; | |
633 font->underline_thickness | |
634 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value) | |
635 ? (long) value : 0); | |
636 font->underline_position | |
637 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value) | |
638 ? (long) value : -1); | |
639 font->baseline_offset | |
610 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) | 640 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) |
611 ? (long) value : 0); | 641 ? (long) value : 0); |
612 font->font.relative_compose | 642 font->relative_compose |
613 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) | 643 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) |
614 ? (long) value : 0); | 644 ? (long) value : 0); |
615 font->font.default_ascent | 645 font->default_ascent |
616 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) | 646 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) |
617 ? (long) value : 0); | 647 ? (long) value : 0); |
618 font->font.vertical_centering | 648 UNBLOCK_INPUT; |
649 | |
650 if (NILP (fullname)) | |
651 fullname = AREF (font_object, FONT_NAME_INDEX); | |
652 font->vertical_centering | |
619 = (STRINGP (Vvertical_centering_font_regexp) | 653 = (STRINGP (Vvertical_centering_font_regexp) |
620 && (fast_c_string_match_ignore_case | 654 && (fast_string_match_ignore_case |
621 (Vvertical_centering_font_regexp, font->font.full_name) >= 0)); | 655 (Vvertical_centering_font_regexp, fullname) >= 0)); |
622 | 656 |
623 UNBLOCK_INPUT; | 657 return font_object; |
624 | |
625 dpyinfo->n_fonts++; | |
626 | |
627 /* Set global flag fonts_changed_p to non-zero if the font loaded | |
628 has a character with a smaller width than any other character | |
629 before, or if the font loaded has a smaller height than any other | |
630 font loaded before. If this happens, it will make a glyph matrix | |
631 reallocation necessary. */ | |
632 if (dpyinfo->n_fonts == 1) | |
633 { | |
634 dpyinfo->smallest_font_height = font->font.height; | |
635 dpyinfo->smallest_char_width = font->min_width; | |
636 fonts_changed_p = 1; | |
637 } | |
638 else | |
639 { | |
640 if (dpyinfo->smallest_font_height > font->font.height) | |
641 dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1; | |
642 if (dpyinfo->smallest_char_width > font->min_width) | |
643 dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1; | |
644 } | |
645 | |
646 return font; | |
647 } | 658 } |
648 | 659 |
649 static void | 660 static void |
650 xfont_close (f, font) | 661 xfont_close (f, font) |
651 FRAME_PTR f; | 662 FRAME_PTR f; |
652 struct font *font; | 663 struct font *font; |
653 { | 664 { |
654 BLOCK_INPUT; | 665 BLOCK_INPUT; |
655 XFreeFont (FRAME_X_DISPLAY (f), font->font.font); | 666 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont); |
656 UNBLOCK_INPUT; | 667 UNBLOCK_INPUT; |
657 | |
658 if (font->font.name != font->font.full_name) | |
659 free (font->font.full_name); | |
660 free (font->font.name); | |
661 free (font); | |
662 FRAME_X_DISPLAY_INFO (f)->n_fonts--; | |
663 } | 668 } |
664 | 669 |
665 static int | 670 static int |
666 xfont_prepare_face (f, face) | 671 xfont_prepare_face (f, face) |
667 FRAME_PTR f; | 672 FRAME_PTR f; |
668 struct face *face; | 673 struct face *face; |
669 { | 674 { |
670 BLOCK_INPUT; | 675 BLOCK_INPUT; |
671 XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid); | 676 XSetFont (FRAME_X_DISPLAY (f), face->gc, |
677 ((struct xfont_info *) face->font)->xfont->fid); | |
672 UNBLOCK_INPUT; | 678 UNBLOCK_INPUT; |
673 | 679 |
674 return 0; | 680 return 0; |
675 } | 681 } |
676 | |
677 #if 0 | |
678 static void | |
679 xfont_done_face (f, face) | |
680 FRAME_PTR f; | |
681 struct face *face; | |
682 { | |
683 if (face->extra) | |
684 { | |
685 BLOCK_INPUT; | |
686 XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra); | |
687 UNBLOCK_INPUT; | |
688 face->extra = NULL; | |
689 } | |
690 } | |
691 #endif /* 0 */ | |
692 | 682 |
693 static int | 683 static int |
694 xfont_has_char (entity, c) | 684 xfont_has_char (entity, c) |
695 Lisp_Object entity; | 685 Lisp_Object entity; |
696 int c; | 686 int c; |
708 static unsigned | 698 static unsigned |
709 xfont_encode_char (font, c) | 699 xfont_encode_char (font, c) |
710 struct font *font; | 700 struct font *font; |
711 int c; | 701 int c; |
712 { | 702 { |
703 XFontStruct *xfont = ((struct xfont_info *) font)->xfont; | |
713 struct charset *charset; | 704 struct charset *charset; |
714 unsigned code; | 705 unsigned code; |
715 XChar2b char2b; | 706 XChar2b char2b; |
716 | 707 |
717 charset = CHARSET_FROM_ID (font->encoding_charset); | 708 charset = CHARSET_FROM_ID (font->encoding_charset); |
724 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset) | 715 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset) |
725 ? code : FONT_INVALID_CODE); | 716 ? code : FONT_INVALID_CODE); |
726 } | 717 } |
727 char2b.byte1 = code >> 8; | 718 char2b.byte1 = code >> 8; |
728 char2b.byte2 = code & 0xFF; | 719 char2b.byte2 = code & 0xFF; |
729 return (xfont_get_pcm (font->font.font, &char2b) ? code : FONT_INVALID_CODE); | 720 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE); |
730 } | 721 } |
731 | 722 |
732 static int | 723 static int |
733 xfont_text_extents (font, code, nglyphs, metrics) | 724 xfont_text_extents (font, code, nglyphs, metrics) |
734 struct font *font; | 725 struct font *font; |
735 unsigned *code; | 726 unsigned *code; |
736 int nglyphs; | 727 int nglyphs; |
737 struct font_metrics *metrics; | 728 struct font_metrics *metrics; |
738 { | 729 { |
730 XFontStruct *xfont = ((struct xfont_info *) font)->xfont; | |
739 int width = 0; | 731 int width = 0; |
740 int i, x; | 732 int i, x; |
741 | 733 |
742 if (metrics) | 734 if (metrics) |
743 bzero (metrics, sizeof (struct font_metrics)); | 735 bzero (metrics, sizeof (struct font_metrics)); |
747 static XCharStruct *pcm; | 739 static XCharStruct *pcm; |
748 | 740 |
749 if (code[i] >= 0x10000) | 741 if (code[i] >= 0x10000) |
750 continue; | 742 continue; |
751 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF; | 743 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF; |
752 pcm = xfont_get_pcm (font->font.font, &char2b); | 744 pcm = xfont_get_pcm (xfont, &char2b); |
753 if (! pcm) | 745 if (! pcm) |
754 continue; | 746 continue; |
755 if (metrics->lbearing > width + pcm->lbearing) | 747 if (metrics->lbearing > width + pcm->lbearing) |
756 metrics->lbearing = width + pcm->lbearing; | 748 metrics->lbearing = width + pcm->lbearing; |
757 if (metrics->rbearing < width + pcm->rbearing) | 749 if (metrics->rbearing < width + pcm->rbearing) |
770 static int | 762 static int |
771 xfont_draw (s, from, to, x, y, with_background) | 763 xfont_draw (s, from, to, x, y, with_background) |
772 struct glyph_string *s; | 764 struct glyph_string *s; |
773 int from, to, x, y, with_background; | 765 int from, to, x, y, with_background; |
774 { | 766 { |
775 XFontStruct *xfont = s->face->font; | 767 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont; |
776 int len = to - from; | 768 int len = to - from; |
777 GC gc = s->gc; | 769 GC gc = s->gc; |
778 int i; | 770 int i; |
779 | 771 |
780 if (gc != s->face->gc) | 772 if (s->gc != s->face->gc) |
781 { | 773 { |
782 XGCValues xgcv; | |
783 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (s->f); | |
784 | |
785 BLOCK_INPUT; | 774 BLOCK_INPUT; |
786 XGetGCValues (s->display, gc, GCFont, &xgcv); | 775 XSetFont (s->display, gc, xfont->fid); |
787 if (xgcv.font != xfont->fid) | |
788 XSetFont (s->display, gc, xfont->fid); | |
789 UNBLOCK_INPUT; | 776 UNBLOCK_INPUT; |
790 } | 777 } |
791 | 778 |
792 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0) | 779 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0) |
793 { | 780 { |
847 UNBLOCK_INPUT; | 834 UNBLOCK_INPUT; |
848 | 835 |
849 return len; | 836 return len; |
850 } | 837 } |
851 | 838 |
839 static int | |
840 xfont_check (f, font) | |
841 FRAME_PTR f; | |
842 struct font *font; | |
843 { | |
844 struct xfont_info *xfont = (struct xfont_info *) font; | |
845 | |
846 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1); | |
847 } | |
848 | |
852 | 849 |
853 void | 850 void |
854 syms_of_xfont () | 851 syms_of_xfont () |
855 { | 852 { |
856 xfont_driver.type = Qx; | 853 xfont_driver.type = Qx; |