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