remove Lisp_Free struct type
[bpt/emacs.git] / src / xftfont.c
CommitLineData
c2f5bfd6 1/* xftfont.c -- XFT font driver.
ba318903 2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
5df4f04c 3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
c2f5bfd6
KH
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7This file is part of GNU Emacs.
8
9ec0b715 9GNU Emacs is free software: you can redistribute it and/or modify
c2f5bfd6 10it under the terms of the GNU General Public License as published by
9ec0b715
GM
11the Free Software Foundation, either version 3 of the License, or
12(at your option) any later version.
c2f5bfd6
KH
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
9ec0b715 20along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
c2f5bfd6
KH
21
22#include <config.h>
23#include <stdio.h>
24#include <X11/Xlib.h>
25#include <X11/Xft/Xft.h>
26
27#include "lisp.h"
28#include "dispextern.h"
29#include "xterm.h"
30#include "frame.h"
31#include "blockinput.h"
32#include "character.h"
33#include "charset.h"
31daa5e1 34#include "composite.h"
c2f5bfd6
KH
35#include "fontset.h"
36#include "font.h"
4613015e 37#include "ftfont.h"
c2f5bfd6
KH
38
39/* Xft font driver. */
40
a2d19368 41Lisp_Object Qxft;
223e5fc6
JD
42static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
43 QClcdfilter;
c2f5bfd6 44
d5081c1e 45/* The actual structure for Xft font that can be cast to struct
c2f5bfd6
KH
46 font. */
47
48struct xftfont_info
49{
50 struct font font;
91ce2415 51 /* The following five members must be here in this order to be
0fce2b40 52 compatible with struct ftfont_info (in ftfont.c). */
4613015e 53#ifdef HAVE_LIBOTF
a864ef14 54 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
4613015e 55 OTF *otf;
794eba0f 56#endif /* HAVE_LIBOTF */
0fce2b40 57 FT_Size ft_size;
b0c25608 58 int index;
91ce2415 59 FT_Matrix matrix;
0fce2b40 60 Display *display;
0fce2b40 61 XftFont *xftfont;
19dae293 62 unsigned x_display_id;
c2f5bfd6
KH
63};
64
65/* Structure pointed by (struct face *)->extra */
10aca0f7 66
c2f5bfd6
KH
67struct xftface_info
68{
10aca0f7
KH
69 XftColor xft_fg; /* color for face->foreground */
70 XftColor xft_bg; /* color for face->background */
c2f5bfd6
KH
71};
72
10aca0f7
KH
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
c2f5bfd6 77static void
a10c8269
DA
78xftfont_get_colors (struct frame *f, struct face *face, GC gc,
79 struct xftface_info *xftface_info,
80 XftColor *fg, XftColor *bg)
c2f5bfd6
KH
81{
82 if (xftface_info && face->gc == gc)
83 {
84 *fg = xftface_info->xft_fg;
85 if (bg)
86 *bg = xftface_info->xft_bg;
87 }
88 else
89 {
90 XGCValues xgcv;
a864ef14 91 bool fg_done = 0, bg_done = 0;
c2f5bfd6 92
4d7e6e51 93 block_input ();
c2f5bfd6
KH
94 XGetGCValues (FRAME_X_DISPLAY (f), gc,
95 GCForeground | GCBackground, &xgcv);
96 if (xftface_info)
97 {
98 if (xgcv.foreground == face->foreground)
99 *fg = xftface_info->xft_fg, fg_done = 1;
100 else if (xgcv.foreground == face->background)
101 *fg = xftface_info->xft_bg, fg_done = 1;
102 if (! bg)
103 bg_done = 1;
104 else if (xgcv.background == face->background)
105 *bg = xftface_info->xft_bg, bg_done = 1;
106 else if (xgcv.background == face->foreground)
107 *bg = xftface_info->xft_fg, bg_done = 1;
108 }
109
a864ef14 110 if (! (fg_done & bg_done))
c2f5bfd6
KH
111 {
112 XColor colors[2];
113
114 colors[0].pixel = fg->pixel = xgcv.foreground;
115 if (bg)
116 colors[1].pixel = bg->pixel = xgcv.background;
117 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
118 bg ? 2 : 1);
119 fg->color.alpha = 0xFFFF;
120 fg->color.red = colors[0].red;
121 fg->color.green = colors[0].green;
122 fg->color.blue = colors[0].blue;
123 if (bg)
124 {
125 bg->color.alpha = 0xFFFF;
126 bg->color.red = colors[1].red;
127 bg->color.green = colors[1].green;
128 bg->color.blue = colors[1].blue;
129 }
130 }
4d7e6e51 131 unblock_input ();
c2f5bfd6
KH
132 }
133}
134
c2f5bfd6 135
c2f5bfd6
KH
136struct font_driver xftfont_driver;
137
138static Lisp_Object
fdb396e2 139xftfont_list (struct frame *f, Lisp_Object spec)
c2f5bfd6 140{
fdb396e2 141 Lisp_Object list = ftfont_driver.list (f, spec), tail;
8510724d 142
3528e709
KH
143 for (tail = list; CONSP (tail); tail = XCDR (tail))
144 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
145 return list;
c2f5bfd6
KH
146}
147
10aca0f7 148static Lisp_Object
fdb396e2 149xftfont_match (struct frame *f, Lisp_Object spec)
10aca0f7 150{
fdb396e2 151 Lisp_Object entity = ftfont_driver.match (f, spec);
10aca0f7 152
3528e709 153 if (! NILP (entity))
10aca0f7
KH
154 ASET (entity, FONT_TYPE_INDEX, Qxft);
155 return entity;
156}
157
c2f5bfd6
KH
158static FcChar8 ascii_printable[95];
159
637fa988 160static void
971de7fb 161xftfont_fix_match (FcPattern *pat, FcPattern *match)
637fa988
JD
162{
163 /* These values are not used for matching (except antialias), but for
164 rendering, so make sure they are carried over to the match.
165 We also put antialias here because most fonts are antialiased, so
166 the match will have antialias true. */
167
168 FcBool b = FcTrue;
169 int i;
170 double dpi;
171
172 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
af59aa6e 173 if (! b)
637fa988
JD
174 {
175 FcPatternDel (match, FC_ANTIALIAS);
176 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
177 }
178 FcPatternGetBool (pat, FC_HINTING, 0, &b);
af59aa6e 179 if (! b)
637fa988
JD
180 {
181 FcPatternDel (match, FC_HINTING);
182 FcPatternAddBool (match, FC_HINTING, FcFalse);
183 }
af59aa6e
PE
184#ifndef FC_HINT_STYLE
185# define FC_HINT_STYLE "hintstyle"
186#endif
637fa988
JD
187 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
188 {
189 FcPatternDel (match, FC_HINT_STYLE);
190 FcPatternAddInteger (match, FC_HINT_STYLE, i);
191 }
21050de1 192#ifndef FC_LCD_FILTER
a6eb20d8 193 /* Older fontconfig versions don't have FC_LCD_FILTER. */
21050de1
JD
194#define FC_LCD_FILTER "lcdfilter"
195#endif
637fa988
JD
196 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
197 {
198 FcPatternDel (match, FC_LCD_FILTER);
199 FcPatternAddInteger (match, FC_LCD_FILTER, i);
200 }
201 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
202 {
203 FcPatternDel (match, FC_RGBA);
204 FcPatternAddInteger (match, FC_RGBA, i);
205 }
206 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
207 {
208 FcPatternDel (match, FC_DPI);
209 FcPatternAddDouble (match, FC_DPI, dpi);
210 }
211}
212
d0cf45b7 213static void
971de7fb 214xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
d0cf45b7
JD
215{
216 Lisp_Object tail;
217 int ival;
218
219 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
220 {
221 Lisp_Object key = XCAR (XCAR (tail));
222 Lisp_Object val = XCDR (XCAR (tail));
223
224 if (EQ (key, QCantialias))
225 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
226 else if (EQ (key, QChinting))
227 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
228 else if (EQ (key, QCautohint))
229 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
230 else if (EQ (key, QChintstyle))
231 {
232 if (INTEGERP (val))
233 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
234 else if (SYMBOLP (val)
235 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
236 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
237 }
238 else if (EQ (key, QCrgba))
239 {
240 if (INTEGERP (val))
241 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
242 else if (SYMBOLP (val)
243 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
244 FcPatternAddInteger (pat, FC_RGBA, ival);
245 }
246 else if (EQ (key, QClcdfilter))
247 {
248 if (INTEGERP (val))
249 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
250 else if (SYMBOLP (val)
251 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
252 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
253 }
254#ifdef FC_EMBOLDEN
255 else if (EQ (key, QCembolden))
256 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
257#endif
258 }
259}
260
3528e709 261static Lisp_Object
a10c8269 262xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
c2f5bfd6 263{
81094fab 264 FcResult result;
c2f5bfd6 265 Display *display = FRAME_X_DISPLAY (f);
001a7ab4 266 Lisp_Object val, filename, idx, font_object;
81094fab 267 FcPattern *pat = NULL, *match;
2d93c6bd 268 struct xftfont_info *xftfont_info = NULL;
c2f5bfd6
KH
269 struct font *font;
270 double size = 0;
2d93c6bd 271 XftFont *xftfont = NULL;
c2f5bfd6 272 int spacing;
3528e709 273 char name[256];
d0cf45b7 274 int len, i;
91c5bb27 275 XGlyphInfo extents;
365131ac 276 FT_Face ft_face;
91ce2415 277 FcMatrix *matrix;
c2f5bfd6 278
3528e709 279 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
686ee703 280 if (! CONSP (val))
3528e709 281 return Qnil;
686ee703
KH
282 val = XCDR (val);
283 filename = XCAR (val);
001a7ab4 284 idx = XCDR (val);
c2f5bfd6
KH
285 size = XINT (AREF (entity, FONT_SIZE_INDEX));
286 if (size == 0)
287 size = pixel_size;
288 pat = FcPatternCreate ();
81094fab
KH
289 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
290 i = FONT_SLANT_NUMERIC (entity) - 100;
291 if (i < 0) i = 0;
292 FcPatternAddInteger (pat, FC_SLANT, i);
293 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
c2f5bfd6 294 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
3cc2aca0
KH
295 val = AREF (entity, FONT_FAMILY_INDEX);
296 if (! NILP (val))
297 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
dc2226d0
KH
298 val = AREF (entity, FONT_FOUNDRY_INDEX);
299 if (! NILP (val))
300 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
301 val = AREF (entity, FONT_SPACING_INDEX);
302 if (! NILP (val))
303 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
304 val = AREF (entity, FONT_DPI_INDEX);
305 if (! NILP (val))
306 {
307 double dbl = XINT (val);
308
309 FcPatternAddDouble (pat, FC_DPI, dbl);
310 }
311 val = AREF (entity, FONT_AVGWIDTH_INDEX);
312 if (INTEGERP (val) && XINT (val) == 0)
313 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
0fce2b40
KH
314 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
315 over 10x20-ISO8859-1.pcf.gz). */
316 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
dc2226d0 317
d0cf45b7 318 xftfont_add_rendering_parameters (pat, entity);
dcce3c58 319
0fce2b40 320 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
001a7ab4 321 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
8510724d 322
0fce2b40 323
4d7e6e51 324 block_input ();
637fa988
JD
325
326 /* Substitute in values from X resources and XftDefaultSet. */
327 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
81094fab 328 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
637fa988 329 xftfont_fix_match (pat, match);
223e5fc6 330
81094fab
KH
331 FcPatternDestroy (pat);
332 xftfont = XftFontOpenPattern (display, match);
99061dfc 333 if (!xftfont)
5c629bf6 334 {
4d7e6e51 335 unblock_input ();
5c629bf6
CY
336 XftPatternDestroy (match);
337 return Qnil;
338 }
99061dfc 339 ft_face = XftLockFace (xftfont);
4d7e6e51 340 unblock_input ();
99061dfc 341
c2f5bfd6
KH
342 /* We should not destroy PAT here because it is kept in XFTFONT and
343 destroyed automatically when XFTFONT is closed. */
0fce2b40 344 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
3528e709 345 ASET (font_object, FONT_TYPE_INDEX, Qxft);
3528e709
KH
346 len = font_unparse_xlfd (entity, size, name, 256);
347 if (len > 0)
2781b4e0 348 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
3528e709
KH
349 len = font_unparse_fcname (entity, size, name, 256);
350 if (len > 0)
2781b4e0 351 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
3528e709
KH
352 else
353 ASET (font_object, FONT_FULLNAME_INDEX,
354 AREF (font_object, FONT_NAME_INDEX));
686ee703
KH
355 ASET (font_object, FONT_FILE_INDEX, filename);
356 ASET (font_object, FONT_FORMAT_INDEX,
1cf6763f 357 ftfont_font_format (xftfont->pattern, filename));
3528e709 358 font = XFONT_OBJECT (font_object);
12645ae6 359 font->pixel_size = size;
3528e709
KH
360 font->driver = &xftfont_driver;
361 font->encoding_charset = font->repertory_charset = -1;
362
363 xftfont_info = (struct xftfont_info *) font;
c2f5bfd6 364 xftfont_info->display = display;
c2f5bfd6 365 xftfont_info->xftfont = xftfont;
19dae293 366 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
91ce2415
KH
367 /* This means that there's no need of transformation. */
368 xftfont_info->matrix.xx = 0;
369 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
370 == FcResultMatch)
371 {
372 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
373 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
374 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
375 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
376 }
686ee703
KH
377 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
378 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
379 else
c2f5bfd6 380 spacing = FC_PROPORTIONAL;
91c5bb27
KH
381 if (! ascii_printable[0])
382 {
001a7ab4
PE
383 int ch;
384 for (ch = 0; ch < 95; ch++)
385 ascii_printable[ch] = ' ' + ch;
91c5bb27 386 }
4d7e6e51 387 block_input ();
032a42c8
CY
388
389 /* Unfortunately Xft doesn't provide a way to get minimum char
390 width. So, we set min_width to space_width. */
391
ea2460a0
KH
392 if (spacing != FC_PROPORTIONAL
393#ifdef FC_DUAL
394 && spacing != FC_DUAL
395#endif /* FC_DUAL */
396 )
91c5bb27 397 {
032a42c8
CY
398 font->min_width = font->max_width = font->average_width
399 = font->space_width = xftfont->max_advance_width;
91c5bb27
KH
400 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
401 }
c2f5bfd6
KH
402 else
403 {
c2f5bfd6 404 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
032a42c8
CY
405 font->min_width = font->max_width = font->space_width
406 = extents.xOff;
3528e709 407 if (font->space_width <= 0)
c2f5bfd6 408 /* dirty workaround */
8510724d 409 font->space_width = pixel_size;
c2f5bfd6 410 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
3528e709 411 font->average_width = (font->space_width + extents.xOff) / 95;
c2f5bfd6 412 }
4d7e6e51 413 unblock_input ();
c2f5bfd6 414
91c5bb27 415 font->ascent = xftfont->ascent;
91c5bb27 416 font->descent = xftfont->descent;
81094fab
KH
417 if (pixel_size >= 5)
418 {
419 /* The above condition is a dirty workaround because
420 XftTextExtents8 behaves strangely for some fonts
421 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
422 if (font->ascent < extents.y)
423 font->ascent = extents.y;
424 if (font->descent < extents.height - extents.y)
425 font->descent = extents.height - extents.y;
426 }
3528e709 427 font->height = font->ascent + font->descent;
91c5bb27 428
3528e709 429 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
c2f5bfd6 430 {
3528e709
KH
431 int upEM = ft_face->units_per_EM;
432
433 font->underline_position = -ft_face->underline_position * size / upEM;
bc981e4e 434 font->underline_thickness = ft_face->underline_thickness * size / upEM;
951b8112
KH
435 if (font->underline_thickness > 2)
436 font->underline_position -= font->underline_thickness / 2;
c2f5bfd6
KH
437 }
438 else
439 {
3528e709
KH
440 font->underline_position = -1;
441 font->underline_thickness = 0;
c2f5bfd6 442 }
3528e709 443#ifdef HAVE_LIBOTF
a864ef14 444 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
3528e709
KH
445 xftfont_info->otf = NULL;
446#endif /* HAVE_LIBOTF */
0fce2b40 447 xftfont_info->ft_size = ft_face->size;
c2f5bfd6 448
3528e709
KH
449 font->baseline_offset = 0;
450 font->relative_compose = 0;
451 font->default_ascent = 0;
452 font->vertical_centering = 0;
0fce2b40
KH
453#ifdef FT_BDF_H
454 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
455 {
456 BDF_PropertyRec rec;
457
458 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
459 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
460 font->baseline_offset = rec.u.integer;
461 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
462 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
463 font->relative_compose = rec.u.integer;
464 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
465 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
466 font->default_ascent = rec.u.integer;
467 }
468#endif
3528e709
KH
469
470 return font_object;
c2f5bfd6
KH
471}
472
473static void
78e0b35c 474xftfont_close (struct font *font)
c2f5bfd6 475{
19dae293 476 struct x_display_info *xdi;
c2f5bfd6
KH
477 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
478
4613015e
KH
479#ifdef HAVE_LIBOTF
480 if (xftfont_info->otf)
78e0b35c
DA
481 {
482 OTF_close (xftfont_info->otf);
483 xftfont_info->otf = NULL;
484 }
4613015e 485#endif
78e0b35c 486
5ae356d9
DA
487 /* See comment in xfont_close. */
488 if (xftfont_info->xftfont
19dae293
DA
489 && ((xdi = x_display_info_for_display (xftfont_info->display))
490 && xftfont_info->x_display_id == xdi->x_id))
78e0b35c
DA
491 {
492 block_input ();
493 XftUnlockFace (xftfont_info->xftfont);
494 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
495 unblock_input ();
496 xftfont_info->xftfont = NULL;
497 }
c2f5bfd6
KH
498}
499
24ce6a02 500static void
a10c8269 501xftfont_prepare_face (struct frame *f, struct face *face)
c2f5bfd6 502{
e2d0c925 503 struct xftface_info *xftface_info;
c2f5bfd6 504
a703d27d
KH
505#if 0
506 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
e2d0c925
KH
507 if (face != face->ascii_face)
508 {
509 face->extra = face->ascii_face->extra;
24ce6a02 510 return;
e2d0c925 511 }
a703d27d 512#endif
e2d0c925 513
24ce6a02 514 xftface_info = xmalloc (sizeof *xftface_info);
c2f5bfd6
KH
515 xftfont_get_colors (f, face, face->gc, NULL,
516 &xftface_info->xft_fg, &xftface_info->xft_bg);
c2f5bfd6 517 face->extra = xftface_info;
c2f5bfd6
KH
518}
519
520static void
a10c8269 521xftfont_done_face (struct frame *f, struct face *face)
c2f5bfd6 522{
e2d0c925 523 struct xftface_info *xftface_info;
8510724d 524
a703d27d
KH
525#if 0
526 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
e2d0c925
KH
527 if (face != face->ascii_face
528 || ! face->extra)
529 return;
a703d27d 530#endif
c2f5bfd6 531
e2d0c925 532 xftface_info = (struct xftface_info *) face->extra;
773039e8
JD
533 if (xftface_info)
534 {
24ce6a02 535 xfree (xftface_info);
a92ee6bf 536 face->extra = NULL;
773039e8 537 }
c2f5bfd6
KH
538}
539
6570a1c4 540static int
971de7fb 541xftfont_has_char (Lisp_Object font, int c)
6570a1c4
KH
542{
543 struct xftfont_info *xftfont_info;
b840b299 544 struct charset *cs = NULL;
6570a1c4 545
b840b299
KH
546 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
547 && charset_jisx0208 >= 0)
548 cs = CHARSET_FROM_ID (charset_jisx0208);
549 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
550 && charset_ksc5601 >= 0)
551 cs = CHARSET_FROM_ID (charset_ksc5601);
552 if (cs)
553 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
554
ea12eb81
KH
555 if (FONT_ENTITY_P (font))
556 return ftfont_driver.has_char (font, c);
6570a1c4
KH
557 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
558 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
559 (FcChar32) c) == FcTrue);
560}
561
c2f5bfd6 562static unsigned
971de7fb 563xftfont_encode_char (struct font *font, int c)
c2f5bfd6
KH
564{
565 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
566 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
567 (FcChar32) c);
8510724d 568
b5b2545a 569 return (code ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
570}
571
572static int
971de7fb 573xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
c2f5bfd6
KH
574{
575 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
576 XGlyphInfo extents;
577
4d7e6e51 578 block_input ();
c2f5bfd6
KH
579 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
580 &extents);
4d7e6e51 581 unblock_input ();
c2f5bfd6
KH
582 if (metrics)
583 {
584 metrics->lbearing = - extents.x;
585 metrics->rbearing = - extents.x + extents.width;
586 metrics->width = extents.xOff;
587 metrics->ascent = extents.y;
4b848612 588 metrics->descent = extents.height - extents.y;
c2f5bfd6
KH
589 }
590 return extents.xOff;
591}
592
a92ee6bf 593static XftDraw *
a10c8269 594xftfont_get_xft_draw (struct frame *f)
a92ee6bf 595{
8510724d 596 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
a92ee6bf
KH
597
598 if (! xft_draw)
599 {
4d7e6e51 600 block_input ();
a92ee6bf
KH
601 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
602 FRAME_X_WINDOW (f),
603 FRAME_X_VISUAL (f),
604 FRAME_X_COLORMAP (f));
4d7e6e51 605 unblock_input ();
4e6a86c6 606 eassert (xft_draw != NULL);
a92ee6bf
KH
607 font_put_frame_data (f, &xftfont_driver, xft_draw);
608 }
609 return xft_draw;
610}
611
c2f5bfd6 612static int
a864ef14
PE
613xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
614 bool with_background)
c2f5bfd6 615{
a10c8269 616 struct frame *f = s->f;
c2f5bfd6 617 struct face *face = s->face;
3528e709 618 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
c78c1659 619 struct xftface_info *xftface_info = NULL;
a92ee6bf 620 XftDraw *xft_draw = xftfont_get_xft_draw (f);
c2f5bfd6
KH
621 FT_UInt *code;
622 XftColor fg, bg;
c2f5bfd6
KH
623 int len = to - from;
624 int i;
625
3528e709 626 if (s->font == face->font)
a92ee6bf 627 xftface_info = (struct xftface_info *) face->extra;
c2f5bfd6 628 xftfont_get_colors (f, face, s->gc, xftface_info,
322f8671 629 &fg, with_background ? &bg : NULL);
4d7e6e51 630 block_input ();
03d198e8
KH
631 if (s->num_clips > 0)
632 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
633 else
634 XftDrawSetClip (xft_draw, NULL);
635
c2f5bfd6 636 if (with_background)
3528e709 637 XftDrawRect (xft_draw, &bg,
100d5755 638 x, y - s->font->ascent, s->width, s->font->height);
c2f5bfd6
KH
639 code = alloca (sizeof (FT_UInt) * len);
640 for (i = 0; i < len; i++)
641 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
642 | XCHAR2B_BYTE2 (s->char2b + from + i));
643
785543da
KH
644 if (s->padding_p)
645 for (i = 0; i < len; i++)
646 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
647 x + i, y, code + i, 1);
648 else
649 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
650 x, y, code, len);
4d7e6e51 651 unblock_input ();
c2f5bfd6
KH
652
653 return len;
654}
655
0248044d
PE
656#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
657static Lisp_Object
31daa5e1
KH
658xftfont_shape (Lisp_Object lgstring)
659{
660 struct font *font;
661 struct xftfont_info *xftfont_info;
662 FT_Face ft_face;
663 Lisp_Object val;
664
665 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
666 xftfont_info = (struct xftfont_info *) font;
667 ft_face = XftLockFace (xftfont_info->xftfont);
668 xftfont_info->ft_size = ft_face->size;
669 val = ftfont_driver.shape (lgstring);
670 XftUnlockFace (xftfont_info->xftfont);
671 return val;
672}
0248044d 673#endif
31daa5e1 674
a92ee6bf 675static int
a10c8269 676xftfont_end_for_frame (struct frame *f)
a92ee6bf 677{
ece2d4ed
JD
678 XftDraw *xft_draw;
679
680 /* Don't do anything if display is dead */
681 if (FRAME_X_DISPLAY (f) == NULL) return 0;
682
683 xft_draw = font_get_frame_data (f, &xftfont_driver);
a92ee6bf
KH
684
685 if (xft_draw)
686 {
4d7e6e51 687 block_input ();
a92ee6bf 688 XftDrawDestroy (xft_draw);
4d7e6e51 689 unblock_input ();
a92ee6bf
KH
690 font_put_frame_data (f, &xftfont_driver, NULL);
691 }
692 return 0;
693}
c2f5bfd6 694
a864ef14
PE
695static bool
696xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
697 Lisp_Object entity)
d0cf45b7
JD
698{
699 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
700 FcPattern *oldpat = info->xftfont->pattern;
701 Display *display = FRAME_X_DISPLAY (f);
702 FcPattern *pat = FcPatternCreate ();
703 FcBool b1, b2;
a864ef14
PE
704 bool ok = 0;
705 int i1, i2, r1, r2;
d0cf45b7
JD
706
707 xftfont_add_rendering_parameters (pat, entity);
708 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
709
710 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
711 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
712 if (r1 != r2 || b1 != b2) goto out;
713 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
714 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
715 if (r1 != r2 || b1 != b2) goto out;
716 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
717 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
718 if (r1 != r2 || b1 != b2) goto out;
719#ifdef FC_EMBOLDEN
720 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
721 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
722 if (r1 != r2 || b1 != b2) goto out;
723#endif
724 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
725 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
726 if (r1 != r2 || i1 != i2) goto out;
727 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
728 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
729 if (r1 != r2 || i1 != i2) goto out;
730 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
731 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
732 if (r1 != r2 || i1 != i2) goto out;
733
734 ok = 1;
735 out:
736 FcPatternDestroy (pat);
737 return ok;
738}
739
c2f5bfd6 740void
971de7fb 741syms_of_xftfont (void)
c2f5bfd6
KH
742{
743 DEFSYM (Qxft, "xft");
81094fab 744 DEFSYM (QChinting, ":hinting");
9743ac48 745 DEFSYM (QCautohint, ":autohint");
81094fab
KH
746 DEFSYM (QChintstyle, ":hintstyle");
747 DEFSYM (QCrgba, ":rgba");
748 DEFSYM (QCembolden, ":embolden");
223e5fc6 749 DEFSYM (QClcdfilter, ":lcdfilter");
c2f5bfd6 750
032a42c8
CY
751 ascii_printable[0] = 0;
752
c2f5bfd6
KH
753 xftfont_driver = ftfont_driver;
754 xftfont_driver.type = Qxft;
755 xftfont_driver.get_cache = xfont_driver.get_cache;
756 xftfont_driver.list = xftfont_list;
10aca0f7 757 xftfont_driver.match = xftfont_match;
c2f5bfd6
KH
758 xftfont_driver.open = xftfont_open;
759 xftfont_driver.close = xftfont_close;
760 xftfont_driver.prepare_face = xftfont_prepare_face;
761 xftfont_driver.done_face = xftfont_done_face;
6570a1c4 762 xftfont_driver.has_char = xftfont_has_char;
c2f5bfd6
KH
763 xftfont_driver.encode_char = xftfont_encode_char;
764 xftfont_driver.text_extents = xftfont_text_extents;
765 xftfont_driver.draw = xftfont_draw;
a92ee6bf 766 xftfont_driver.end_for_frame = xftfont_end_for_frame;
d0cf45b7 767 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
31daa5e1
KH
768#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
769 xftfont_driver.shape = xftfont_shape;
770#endif
c2f5bfd6
KH
771
772 register_font_driver (&xftfont_driver, NULL);
773}