Merge unicode branch
[bpt/emacs.git] / 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 #ifdef HAVE_LIBOTF
54 int maybe_otf; /* Flag to tell if this may be OTF or not. */
55 OTF *otf;
56 #endif /* HAVE_LIBOTF */
57 };
58
59 /* Structure pointed by (struct face *)->extra */
60
61 struct xftface_info
62 {
63 XftColor xft_fg; /* color for face->foreground */
64 XftColor xft_bg; /* color for face->background */
65 };
66
67 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
68 struct xftface_info *,
69 XftColor *fg, XftColor *bg));
70 static Font xftfont_default_fid P_ ((FRAME_PTR));
71
72
73 /* Setup foreground and background colors of GC into FG and BG. If
74 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
75 may be NULL. */
76
77 static void
78 xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
79 FRAME_PTR f;
80 struct face *face;
81 GC gc;
82 struct xftface_info *xftface_info;
83 XftColor *fg, *bg;
84 {
85 if (xftface_info && face->gc == gc)
86 {
87 *fg = xftface_info->xft_fg;
88 if (bg)
89 *bg = xftface_info->xft_bg;
90 }
91 else
92 {
93 XGCValues xgcv;
94 int fg_done = 0, bg_done = 0;
95
96 BLOCK_INPUT;
97 XGetGCValues (FRAME_X_DISPLAY (f), gc,
98 GCForeground | GCBackground, &xgcv);
99 if (xftface_info)
100 {
101 if (xgcv.foreground == face->foreground)
102 *fg = xftface_info->xft_fg, fg_done = 1;
103 else if (xgcv.foreground == face->background)
104 *fg = xftface_info->xft_bg, fg_done = 1;
105 if (! bg)
106 bg_done = 1;
107 else if (xgcv.background == face->background)
108 *bg = xftface_info->xft_bg, bg_done = 1;
109 else if (xgcv.background == face->foreground)
110 *bg = xftface_info->xft_fg, bg_done = 1;
111 }
112
113 if (fg_done + bg_done < 2)
114 {
115 XColor colors[2];
116
117 colors[0].pixel = fg->pixel = xgcv.foreground;
118 if (bg)
119 colors[1].pixel = bg->pixel = xgcv.background;
120 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
121 bg ? 2 : 1);
122 fg->color.alpha = 0xFFFF;
123 fg->color.red = colors[0].red;
124 fg->color.green = colors[0].green;
125 fg->color.blue = colors[0].blue;
126 if (bg)
127 {
128 bg->color.alpha = 0xFFFF;
129 bg->color.red = colors[1].red;
130 bg->color.green = colors[1].green;
131 bg->color.blue = colors[1].blue;
132 }
133 }
134 UNBLOCK_INPUT;
135 }
136 }
137
138 /* Return the default Font ID on frame F. The Returned Font ID is
139 stored in the GC of the frame F, but the font is never used. So,
140 any ID is ok as long as it is valid. */
141
142 static Font
143 xftfont_default_fid (f)
144 FRAME_PTR f;
145 {
146 static int fid_known;
147 static Font fid;
148
149 if (! fid_known)
150 {
151 fid = XLoadFont (FRAME_X_DISPLAY (f), "fixed");
152 if (! fid)
153 {
154 fid = XLoadFont (FRAME_X_DISPLAY (f), "*");
155 if (! fid)
156 abort ();
157 }
158 fid_known = 1;
159 }
160 return fid;
161 }
162
163
164 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
165 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
166 static struct font *xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
167 static void xftfont_close P_ ((FRAME_PTR, struct font *));
168 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
169 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
170 static unsigned xftfont_encode_char P_ ((struct font *, int));
171 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
172 struct font_metrics *));
173 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
174
175 static int xftfont_anchor_point P_ ((struct font *, unsigned, int,
176 int *, int *));
177 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
178
179 struct font_driver xftfont_driver;
180
181 static Lisp_Object
182 xftfont_list (frame, spec)
183 Lisp_Object frame;
184 Lisp_Object spec;
185 {
186 Lisp_Object val = ftfont_driver.list (frame, spec);
187 int i;
188
189 if (! NILP (val))
190 for (i = 0; i < ASIZE (val); i++)
191 ASET (AREF (val, i), FONT_TYPE_INDEX, Qxft);
192 return val;
193 }
194
195 static Lisp_Object
196 xftfont_match (frame, spec)
197 Lisp_Object frame;
198 Lisp_Object spec;
199 {
200 Lisp_Object entity = ftfont_driver.match (frame, spec);
201
202 if (VECTORP (entity))
203 ASET (entity, FONT_TYPE_INDEX, Qxft);
204 return entity;
205 }
206
207 extern Lisp_Object ftfont_font_format P_ ((FcPattern *));
208
209 static FcChar8 ascii_printable[95];
210
211 static struct font *
212 xftfont_open (f, entity, pixel_size)
213 FRAME_PTR f;
214 Lisp_Object entity;
215 int pixel_size;
216 {
217 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
218 Display *display = FRAME_X_DISPLAY (f);
219 Lisp_Object val;
220 FcPattern *pattern, *pat = NULL;
221 FcChar8 *file;
222 struct xftfont_info *xftfont_info = NULL;
223 XFontStruct *xfont = NULL;
224 struct font *font;
225 double size = 0;
226 XftFont *xftfont = NULL;
227 int spacing;
228 char *name;
229 int len;
230 XGlyphInfo extents;
231 FT_Face ft_face;
232
233 val = AREF (entity, FONT_EXTRA_INDEX);
234 if (XTYPE (val) != Lisp_Misc
235 || XMISCTYPE (val) != Lisp_Misc_Save_Value)
236 return NULL;
237 pattern = XSAVE_VALUE (val)->pointer;
238 if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch)
239 return NULL;
240
241 size = XINT (AREF (entity, FONT_SIZE_INDEX));
242 if (size == 0)
243 size = pixel_size;
244
245 pat = FcPatternCreate ();
246 FcPatternAddString (pat, FC_FILE, file);
247 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
248 /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/
249 val = AREF (entity, FONT_FAMILY_INDEX);
250 if (! NILP (val))
251 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
252 FcConfigSubstitute (NULL, pat, FcMatchPattern);
253
254 BLOCK_INPUT;
255 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
256 xftfont = XftFontOpenPattern (display, pat);
257 /* We should not destroy PAT here because it is kept in XFTFONT and
258 destroyed automatically when XFTFONT is closed. */
259 if (! xftfont)
260 goto err;
261
262 xftfont_info = malloc (sizeof (struct xftfont_info));
263 if (! xftfont_info)
264 goto err;
265 xfont = malloc (sizeof (XFontStruct));
266 if (! xfont)
267 goto err;
268 xftfont_info->display = display;
269 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
270 xftfont_info->xftfont = xftfont;
271 #ifdef HAVE_LIBOTF
272 ft_face = XftLockFace (xftfont);
273 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
274 XftUnlockFace (xftfont);
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 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
398 if (font->font.name)
399 free (font->font.name);
400 free (font);
401 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
402 }
403
404 static int
405 xftfont_prepare_face (f, face)
406 FRAME_PTR f;
407 struct face *face;
408 {
409 struct xftface_info *xftface_info;
410
411 #if 0
412 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
413 if (face != face->ascii_face)
414 {
415 face->extra = face->ascii_face->extra;
416 return 0;
417 }
418 #endif
419
420 xftface_info = malloc (sizeof (struct xftface_info));
421 if (! xftface_info)
422 return -1;
423
424 BLOCK_INPUT;
425 xftfont_get_colors (f, face, face->gc, NULL,
426 &xftface_info->xft_fg, &xftface_info->xft_bg);
427 UNBLOCK_INPUT;
428
429 face->extra = xftface_info;
430 return 0;
431 }
432
433 static void
434 xftfont_done_face (f, face)
435 FRAME_PTR f;
436 struct face *face;
437 {
438 struct xftface_info *xftface_info;
439
440 #if 0
441 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
442 if (face != face->ascii_face
443 || ! face->extra)
444 return;
445 #endif
446
447 xftface_info = (struct xftface_info *) face->extra;
448 if (xftface_info)
449 {
450 free (xftface_info);
451 face->extra = NULL;
452 }
453 }
454
455 static unsigned
456 xftfont_encode_char (font, c)
457 struct font *font;
458 int c;
459 {
460 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
461 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
462 (FcChar32) c);
463
464 return (code ? code : FONT_INVALID_CODE);
465 }
466
467 static int
468 xftfont_text_extents (font, code, nglyphs, metrics)
469 struct font *font;
470 unsigned *code;
471 int nglyphs;
472 struct font_metrics *metrics;
473 {
474 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
475 XGlyphInfo extents;
476
477 BLOCK_INPUT;
478 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
479 &extents);
480 UNBLOCK_INPUT;
481 if (metrics)
482 {
483 metrics->lbearing = - extents.x;
484 metrics->rbearing = - extents.x + extents.width;
485 metrics->width = extents.xOff;
486 metrics->ascent = extents.y;
487 metrics->descent = extents.height - extents.y;
488 }
489 return extents.xOff;
490 }
491
492 static XftDraw *
493 xftfont_get_xft_draw (f)
494 FRAME_PTR f;
495 {
496 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);;
497
498 if (! xft_draw)
499 {
500 BLOCK_INPUT;
501 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
502 FRAME_X_WINDOW (f),
503 FRAME_X_VISUAL (f),
504 FRAME_X_COLORMAP (f));
505 UNBLOCK_INPUT;
506 if (! xft_draw)
507 abort ();
508 font_put_frame_data (f, &xftfont_driver, xft_draw);
509 }
510 return xft_draw;
511 }
512
513 static int
514 xftfont_draw (s, from, to, x, y, with_background)
515 struct glyph_string *s;
516 int from, to, x, y, with_background;
517 {
518 FRAME_PTR f = s->f;
519 struct face *face = s->face;
520 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font_info;
521 struct xftface_info *xftface_info = NULL;
522 XftDraw *xft_draw = xftfont_get_xft_draw (f);
523 FT_UInt *code;
524 XftColor fg, bg;
525 XRectangle r;
526 int len = to - from;
527 int i;
528
529 if (s->font_info == face->font_info)
530 xftface_info = (struct xftface_info *) face->extra;
531 xftfont_get_colors (f, face, s->gc, xftface_info,
532 &fg, with_background ? &bg : NULL);
533 BLOCK_INPUT;
534 if (s->num_clips > 0)
535 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
536 else
537 XftDrawSetClip (xft_draw, NULL);
538
539 if (with_background)
540 {
541 struct font *font = (struct font *) face->font_info;
542
543 XftDrawRect (xft_draw, &bg,
544 x, y - face->font->ascent, s->width, font->font.height);
545 }
546 code = alloca (sizeof (FT_UInt) * len);
547 for (i = 0; i < len; i++)
548 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
549 | XCHAR2B_BYTE2 (s->char2b + from + i));
550
551 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
552 x, y, code, len);
553 UNBLOCK_INPUT;
554
555 return len;
556 }
557
558 static int
559 xftfont_anchor_point (font, code, index, x, y)
560 struct font *font;
561 unsigned code;
562 int index;
563 int *x, *y;
564 {
565 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
566 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
567 int result;
568
569 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
570 result = -1;
571 else if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
572 result = -1;
573 else if (index >= ft_face->glyph->outline.n_points)
574 result = -1;
575 else
576 {
577 *x = ft_face->glyph->outline.points[index].x;
578 *y = ft_face->glyph->outline.points[index].y;
579 }
580 XftUnlockFace (xftfont_info->xftfont);
581 return result;
582 }
583
584 static int
585 xftfont_end_for_frame (f)
586 FRAME_PTR f;
587 {
588 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
589
590 if (xft_draw)
591 {
592 BLOCK_INPUT;
593 XftDrawDestroy (xft_draw);
594 UNBLOCK_INPUT;
595 font_put_frame_data (f, &xftfont_driver, NULL);
596 }
597 return 0;
598 }
599
600 #ifdef HAVE_LIBOTF
601 #ifdef HAVE_M17N_FLT
602 static Lisp_Object
603 xftfont_shape (lgstring)
604 Lisp_Object lgstring;
605 {
606 struct font *font;
607 struct xftfont_info *xftfont_info;
608 int result;
609 FT_Face ft_face;
610
611 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
612 xftfont_info = (struct xftfont_info *) font;
613 if (! xftfont_info->maybe_otf)
614 return Qnil;
615 ft_face = XftLockFace (xftfont_info->xftfont);
616 if (! xftfont_info->otf)
617 {
618 OTF *otf = OTF_open_ft_face (ft_face);
619
620 if (! otf || OTF_get_table (otf, "head") < 0)
621 {
622 if (otf)
623 OTF_close (otf);
624 xftfont_info->maybe_otf = 0;
625 XftUnlockFace (xftfont_info->xftfont);
626 return 0;
627 }
628 xftfont_info->otf = otf;
629 }
630
631 result = ftfont_shape_by_flt (lgstring, font, ft_face, xftfont_info->otf);
632 XftUnlockFace (xftfont_info->xftfont);
633 return result;
634 }
635 #endif /* HAVE_M17N_FLT */
636 #endif /* HAVE_LIBOTF */
637
638 void
639 syms_of_xftfont ()
640 {
641 DEFSYM (Qxft, "xft");
642
643 xftfont_driver = ftfont_driver;
644 xftfont_driver.type = Qxft;
645 xftfont_driver.get_cache = xfont_driver.get_cache;
646 xftfont_driver.list = xftfont_list;
647 xftfont_driver.match = xftfont_match;
648 xftfont_driver.open = xftfont_open;
649 xftfont_driver.close = xftfont_close;
650 xftfont_driver.prepare_face = xftfont_prepare_face;
651 xftfont_driver.done_face = xftfont_done_face;
652 xftfont_driver.encode_char = xftfont_encode_char;
653 xftfont_driver.text_extents = xftfont_text_extents;
654 xftfont_driver.draw = xftfont_draw;
655 xftfont_driver.anchor_point = xftfont_anchor_point;
656 xftfont_driver.end_for_frame = xftfont_end_for_frame;
657 #ifdef HAVE_LIBOTF
658 #ifdef HAVE_M17N_FLT
659 xftfont_driver.shape = xftfont_shape;
660 #endif /* HAVE_M17N_FLT */
661 #endif /* HAVE_LIBOTF */
662
663 register_font_driver (&xftfont_driver, NULL);
664 }
665
666 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
667 (do not change this comment) */