]> code.delx.au - gnu-emacs/blob - src/xftfont.c
*** empty log message ***
[gnu-emacs] / src / xftfont.c
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007
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 #include <X11/Xft/Xft.h>
28
29 #include "lisp.h"
30 #include "dispextern.h"
31 #include "xterm.h"
32 #include "frame.h"
33 #include "blockinput.h"
34 #include "character.h"
35 #include "charset.h"
36 #include "fontset.h"
37 #include "font.h"
38 #include "ftfont.h"
39
40 /* Xft font driver. */
41
42 static Lisp_Object Qxft;
43
44 /* The actual structure for Xft font that can be casted to struct
45 font. */
46
47 struct xftfont_info
48 {
49 struct font font;
50 Display *display;
51 int screen;
52 XftFont *xftfont;
53 FT_Face ft_face; /* Set to the value of XftLockFace (xftfont). */
54 #ifdef HAVE_LIBOTF
55 int maybe_otf; /* Flag to tell if this may be OTF or not. */
56 OTF *otf;
57 #endif /* HAVE_LIBOTF */
58 };
59
60 /* Structure pointed by (struct face *)->extra */
61
62 struct xftface_info
63 {
64 XftColor xft_fg; /* color for face->foreground */
65 XftColor xft_bg; /* color for face->background */
66 };
67
68 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
69 struct xftface_info *,
70 XftColor *fg, XftColor *bg));
71 static Font xftfont_default_fid P_ ((FRAME_PTR));
72
73
74 /* Setup foreground and background colors of GC into FG and BG. If
75 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
76 may be NULL. */
77
78 static void
79 xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
80 FRAME_PTR f;
81 struct face *face;
82 GC gc;
83 struct xftface_info *xftface_info;
84 XftColor *fg, *bg;
85 {
86 if (xftface_info && face->gc == gc)
87 {
88 *fg = xftface_info->xft_fg;
89 if (bg)
90 *bg = xftface_info->xft_bg;
91 }
92 else
93 {
94 XGCValues xgcv;
95 int fg_done = 0, bg_done = 0;
96
97 BLOCK_INPUT;
98 XGetGCValues (FRAME_X_DISPLAY (f), gc,
99 GCForeground | GCBackground, &xgcv);
100 if (xftface_info)
101 {
102 if (xgcv.foreground == face->foreground)
103 *fg = xftface_info->xft_fg, fg_done = 1;
104 else if (xgcv.foreground == face->background)
105 *fg = xftface_info->xft_bg, fg_done = 1;
106 if (! bg)
107 bg_done = 1;
108 else if (xgcv.background == face->background)
109 *bg = xftface_info->xft_bg, bg_done = 1;
110 else if (xgcv.background == face->foreground)
111 *bg = xftface_info->xft_fg, bg_done = 1;
112 }
113
114 if (fg_done + bg_done < 2)
115 {
116 XColor colors[2];
117
118 colors[0].pixel = fg->pixel = xgcv.foreground;
119 if (bg)
120 colors[1].pixel = bg->pixel = xgcv.background;
121 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
122 bg ? 2 : 1);
123 fg->color.alpha = 0xFFFF;
124 fg->color.red = colors[0].red;
125 fg->color.green = colors[0].green;
126 fg->color.blue = colors[0].blue;
127 if (bg)
128 {
129 bg->color.alpha = 0xFFFF;
130 bg->color.red = colors[1].red;
131 bg->color.green = colors[1].green;
132 bg->color.blue = colors[1].blue;
133 }
134 }
135 UNBLOCK_INPUT;
136 }
137 }
138
139 /* Return the default Font ID on frame F. The Returned Font ID is
140 stored in the GC of the frame F, but the font is never used. So,
141 any ID is ok as long as it is valid. */
142
143 static Font
144 xftfont_default_fid (f)
145 FRAME_PTR f;
146 {
147 static int fid_known;
148 static Font fid;
149
150 if (! fid_known)
151 {
152 fid = XLoadFont (FRAME_X_DISPLAY (f), "fixed");
153 if (! fid)
154 {
155 fid = XLoadFont (FRAME_X_DISPLAY (f), "*");
156 if (! fid)
157 abort ();
158 }
159 fid_known = 1;
160 }
161 return fid;
162 }
163
164
165 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
166 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
167 static struct font *xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
168 static void xftfont_close P_ ((FRAME_PTR, struct font *));
169 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
170 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
171 static unsigned xftfont_encode_char P_ ((struct font *, int));
172 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
173 struct font_metrics *));
174 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
175
176 static int xftfont_anchor_point P_ ((struct font *, unsigned, int,
177 int *, int *));
178 static int xftfont_start_for_frame P_ ((FRAME_PTR f));
179 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
180
181 struct font_driver xftfont_driver;
182
183 static Lisp_Object
184 xftfont_list (frame, spec)
185 Lisp_Object frame;
186 Lisp_Object spec;
187 {
188 Lisp_Object val = ftfont_driver.list (frame, spec);
189 int i;
190
191 if (! NILP (val))
192 for (i = 0; i < ASIZE (val); i++)
193 ASET (AREF (val, i), FONT_TYPE_INDEX, Qxft);
194 return val;
195 }
196
197 static Lisp_Object
198 xftfont_match (frame, spec)
199 Lisp_Object frame;
200 Lisp_Object spec;
201 {
202 Lisp_Object entity = ftfont_driver.match (frame, spec);
203
204 if (VECTORP (entity))
205 ASET (entity, FONT_TYPE_INDEX, Qxft);
206 return entity;
207 }
208
209 extern Lisp_Object ftfont_font_format P_ ((FcPattern *));
210
211 static FcChar8 ascii_printable[95];
212
213 static struct font *
214 xftfont_open (f, entity, pixel_size)
215 FRAME_PTR f;
216 Lisp_Object entity;
217 int pixel_size;
218 {
219 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
220 Display *display = FRAME_X_DISPLAY (f);
221 Lisp_Object val;
222 FcPattern *pattern, *pat = NULL;
223 FcChar8 *file;
224 struct xftfont_info *xftfont_info = NULL;
225 XFontStruct *xfont = NULL;
226 struct font *font;
227 double size = 0;
228 XftFont *xftfont = NULL;
229 int spacing;
230 char *name;
231 int len;
232 XGlyphInfo extents;
233
234 val = AREF (entity, FONT_EXTRA_INDEX);
235 if (XTYPE (val) != Lisp_Misc
236 || XMISCTYPE (val) != Lisp_Misc_Save_Value)
237 return NULL;
238 pattern = XSAVE_VALUE (val)->pointer;
239 if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch)
240 return NULL;
241
242 size = XINT (AREF (entity, FONT_SIZE_INDEX));
243 if (size == 0)
244 size = pixel_size;
245
246 pat = FcPatternCreate ();
247 FcPatternAddString (pat, FC_FILE, file);
248 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
249 /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/
250 val = AREF (entity, FONT_FAMILY_INDEX);
251 if (! NILP (val))
252 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
253 FcConfigSubstitute (NULL, pat, FcMatchPattern);
254
255 BLOCK_INPUT;
256 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
257 xftfont = XftFontOpenPattern (display, pat);
258 /* We should not destroy PAT here because it is kept in XFTFONT and
259 destroyed automatically when XFTFONT is closed. */
260 if (! xftfont)
261 goto err;
262
263 xftfont_info = malloc (sizeof (struct xftfont_info));
264 if (! xftfont_info)
265 goto err;
266 xfont = malloc (sizeof (XFontStruct));
267 if (! xfont)
268 goto err;
269 xftfont_info->display = display;
270 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
271 xftfont_info->xftfont = xftfont;
272 xftfont_info->ft_face = XftLockFace (xftfont);
273 #ifdef HAVE_LIBOTF
274 xftfont_info->maybe_otf = xftfont_info->ft_face->face_flags & FT_FACE_FLAG_SFNT;
275 xftfont_info->otf = NULL;
276 #endif /* HAVE_LIBOTF */
277
278 font = (struct font *) xftfont_info;
279 font->format = ftfont_font_format (xftfont->pattern);
280 font->entity = entity;
281 font->pixel_size = size;
282 font->driver = &xftfont_driver;
283 len = 96;
284 name = malloc (len);
285 while (name && font_unparse_fcname (entity, pixel_size, name, len) < 0)
286 {
287 char *new = realloc (name, len += 32);
288
289 if (! new)
290 free (name);
291 name = new;
292 }
293 if (! name)
294 goto err;
295 font->font.full_name = font->font.name = name;
296 font->file_name = (char *) file;
297 font->font.size = xftfont->max_advance_width;
298 font->font.charset = font->encoding_charset = font->repertory_charset = -1;
299
300 if (FcPatternGetInteger (xftfont->pattern, FC_SPACING, 0, &spacing)
301 != FcResultMatch)
302 spacing = FC_PROPORTIONAL;
303 if (! ascii_printable[0])
304 {
305 int i;
306 for (i = 0; i < 95; i++)
307 ascii_printable[i] = ' ' + i;
308 }
309 if (spacing != FC_PROPORTIONAL)
310 {
311 font->font.average_width = font->font.space_width
312 = xftfont->max_advance_width;
313 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
314 }
315 else
316 {
317 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
318 font->font.space_width = extents.xOff;
319 if (font->font.space_width <= 0)
320 /* dirty workaround */
321 font->font.space_width = pixel_size;
322 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
323 font->font.average_width = (font->font.space_width + extents.xOff) / 95;
324 }
325 UNBLOCK_INPUT;
326
327 font->ascent = xftfont->ascent;
328 if (font->ascent < extents.y)
329 font->ascent = extents.y;
330 font->descent = xftfont->descent;
331 if (font->descent < extents.height - extents.y)
332 font->descent = extents.height - extents.y;
333 font->font.height = font->ascent + font->descent;
334
335 /* Unfortunately Xft doesn't provide a way to get minimum char
336 width. So, we use space_width instead. */
337 font->min_width = font->font.space_width;
338
339 font->font.baseline_offset = 0;
340 font->font.relative_compose = 0;
341 font->font.default_ascent = 0;
342 font->font.vertical_centering = 0;
343
344 /* Setup pseudo XFontStruct */
345 xfont->fid = xftfont_default_fid (f);
346 xfont->ascent = font->ascent;
347 xfont->descent = font->descent;
348 xfont->max_bounds.descent = font->descent;
349 xfont->max_bounds.width = xftfont->max_advance_width;
350 xfont->min_bounds.width = font->font.space_width;
351 font->font.font = xfont;
352
353 dpyinfo->n_fonts++;
354
355 /* Set global flag fonts_changed_p to non-zero if the font loaded
356 has a character with a smaller width than any other character
357 before, or if the font loaded has a smaller height than any other
358 font loaded before. If this happens, it will make a glyph matrix
359 reallocation necessary. */
360 if (dpyinfo->n_fonts == 1)
361 {
362 dpyinfo->smallest_font_height = font->font.height;
363 dpyinfo->smallest_char_width = font->min_width;
364 fonts_changed_p = 1;
365 }
366 else
367 {
368 if (dpyinfo->smallest_font_height > font->font.height)
369 dpyinfo->smallest_font_height = font->font.height,
370 fonts_changed_p |= 1;
371 if (dpyinfo->smallest_char_width > font->min_width)
372 dpyinfo->smallest_char_width = font->min_width,
373 fonts_changed_p |= 1;
374 }
375
376 return font;
377
378 err:
379 if (xftfont) XftFontClose (display, xftfont);
380 UNBLOCK_INPUT;
381 if (xftfont_info) free (xftfont_info);
382 if (xfont) free (xfont);
383 return NULL;
384 }
385
386 static void
387 xftfont_close (f, font)
388 FRAME_PTR f;
389 struct font *font;
390 {
391 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
392
393 #ifdef HAVE_LIBOTF
394 if (xftfont_info->otf)
395 OTF_close (xftfont_info->otf);
396 #endif
397 XftUnlockFace (xftfont_info->xftfont);
398 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
399 if (font->font.name)
400 free (font->font.name);
401 free (font);
402 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
403 }
404
405 static int
406 xftfont_prepare_face (f, face)
407 FRAME_PTR f;
408 struct face *face;
409 {
410 struct xftface_info *xftface_info;
411
412 #if 0
413 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
414 if (face != face->ascii_face)
415 {
416 face->extra = face->ascii_face->extra;
417 return 0;
418 }
419 #endif
420
421 xftface_info = malloc (sizeof (struct xftface_info));
422 if (! xftface_info)
423 return -1;
424
425 BLOCK_INPUT;
426 xftfont_get_colors (f, face, face->gc, NULL,
427 &xftface_info->xft_fg, &xftface_info->xft_bg);
428 UNBLOCK_INPUT;
429
430 face->extra = xftface_info;
431 return 0;
432 }
433
434 static void
435 xftfont_done_face (f, face)
436 FRAME_PTR f;
437 struct face *face;
438 {
439 struct xftface_info *xftface_info;
440
441 #if 0
442 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
443 if (face != face->ascii_face
444 || ! face->extra)
445 return;
446 #endif
447
448 xftface_info = (struct xftface_info *) face->extra;
449 if (xftface_info)
450 {
451 free (xftface_info);
452 face->extra = NULL;
453 }
454 }
455
456 static unsigned
457 xftfont_encode_char (font, c)
458 struct font *font;
459 int c;
460 {
461 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
462 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
463 (FcChar32) c);
464
465 return (code ? code : 0xFFFFFFFF);
466 }
467
468 static int
469 xftfont_text_extents (font, code, nglyphs, metrics)
470 struct font *font;
471 unsigned *code;
472 int nglyphs;
473 struct font_metrics *metrics;
474 {
475 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
476 XGlyphInfo extents;
477
478 BLOCK_INPUT;
479 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
480 &extents);
481 UNBLOCK_INPUT;
482 if (metrics)
483 {
484 metrics->lbearing = - extents.x;
485 metrics->rbearing = - extents.x + extents.width;
486 metrics->width = extents.xOff;
487 metrics->ascent = extents.y;
488 metrics->descent = extents.height - extents.y;
489 }
490 return extents.xOff;
491 }
492
493 static XftDraw *
494 xftfont_get_xft_draw (f)
495 FRAME_PTR f;
496 {
497 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);;
498
499 if (! xft_draw)
500 {
501 BLOCK_INPUT;
502 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
503 FRAME_X_WINDOW (f),
504 FRAME_X_VISUAL (f),
505 FRAME_X_COLORMAP (f));
506 UNBLOCK_INPUT;
507 if (! xft_draw)
508 abort ();
509 font_put_frame_data (f, &xftfont_driver, xft_draw);
510 }
511 return xft_draw;
512 }
513
514 static int
515 xftfont_draw (s, from, to, x, y, with_background)
516 struct glyph_string *s;
517 int from, to, x, y, with_background;
518 {
519 FRAME_PTR f = s->f;
520 struct face *face = s->face;
521 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font_info;
522 struct xftface_info *xftface_info = NULL;
523 XftDraw *xft_draw = xftfont_get_xft_draw (f);
524 FT_UInt *code;
525 XftColor fg, bg;
526 XRectangle r;
527 int len = to - from;
528 int i;
529
530 if (s->font_info == face->font_info)
531 xftface_info = (struct xftface_info *) face->extra;
532 xftfont_get_colors (f, face, s->gc, xftface_info,
533 &fg, with_background ? &bg : NULL);
534 BLOCK_INPUT;
535 if (s->num_clips > 0)
536 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
537 else
538 XftDrawSetClip (xft_draw, NULL);
539
540 if (with_background)
541 {
542 struct font *font = (struct font *) face->font_info;
543
544 XftDrawRect (xft_draw, &bg,
545 x, y - face->font->ascent, s->width, font->font.height);
546 }
547 code = alloca (sizeof (FT_UInt) * len);
548 for (i = 0; i < len; i++)
549 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
550 | XCHAR2B_BYTE2 (s->char2b + from + i));
551
552 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
553 x, y, code, len);
554 UNBLOCK_INPUT;
555
556 return len;
557 }
558
559 static int
560 xftfont_anchor_point (font, code, index, x, y)
561 struct font *font;
562 unsigned code;
563 int index;
564 int *x, *y;
565 {
566 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
567 FT_Face ft_face = xftfont_info->ft_face;
568
569 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
570 return -1;
571 if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
572 return -1;
573 if (index >= ft_face->glyph->outline.n_points)
574 return -1;
575 *x = ft_face->glyph->outline.points[index].x;
576 *y = ft_face->glyph->outline.points[index].y;
577 return 0;
578 }
579
580 static int
581 xftfont_end_for_frame (f)
582 FRAME_PTR f;
583 {
584 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
585
586 if (xft_draw)
587 {
588 BLOCK_INPUT;
589 XftDrawDestroy (xft_draw);
590 UNBLOCK_INPUT;
591 font_put_frame_data (f, &xftfont_driver, NULL);
592 }
593 return 0;
594 }
595
596 #ifdef HAVE_LIBOTF
597 #ifdef HAVE_M17N_FLT
598 static Lisp_Object
599 xftfont_shape (lgstring)
600 Lisp_Object lgstring;
601 {
602 struct font *font;
603 struct xftfont_info *xftfont_info;
604
605 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
606 xftfont_info = (struct xftfont_info *) font;
607 if (! xftfont_info->maybe_otf)
608 return Qnil;
609 if (! xftfont_info->otf)
610 {
611 OTF *otf = OTF_open_ft_face (xftfont_info->ft_face);
612
613 if (! otf || OTF_get_table (otf, "head") < 0)
614 {
615 if (otf)
616 OTF_close (otf);
617 xftfont_info->maybe_otf = 0;
618 return 0;
619 }
620 xftfont_info->otf = otf;
621 }
622
623 return ftfont_shape_by_flt (lgstring, font, xftfont_info->ft_face,
624 xftfont_info->otf);
625 }
626 #endif /* HAVE_M17N_FLT */
627 #endif /* HAVE_LIBOTF */
628
629 void
630 syms_of_xftfont ()
631 {
632 DEFSYM (Qxft, "xft");
633
634 xftfont_driver = ftfont_driver;
635 xftfont_driver.type = Qxft;
636 xftfont_driver.get_cache = xfont_driver.get_cache;
637 xftfont_driver.list = xftfont_list;
638 xftfont_driver.match = xftfont_match;
639 xftfont_driver.open = xftfont_open;
640 xftfont_driver.close = xftfont_close;
641 xftfont_driver.prepare_face = xftfont_prepare_face;
642 xftfont_driver.done_face = xftfont_done_face;
643 xftfont_driver.encode_char = xftfont_encode_char;
644 xftfont_driver.text_extents = xftfont_text_extents;
645 xftfont_driver.draw = xftfont_draw;
646 xftfont_driver.anchor_point = xftfont_anchor_point;
647 xftfont_driver.end_for_frame = xftfont_end_for_frame;
648 #ifdef HAVE_LIBOTF
649 #ifdef HAVE_M17N_FLT
650 xftfont_driver.shape = xftfont_shape;
651 #endif /* HAVE_M17N_FLT */
652 #endif /* HAVE_LIBOTF */
653
654 register_font_driver (&xftfont_driver, NULL);
655 }
656
657 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
658 (do not change this comment) */