menu-bar.el(menu-bar-options-save): Add font-use-system-font.
[bpt/emacs.git] / src / xftfont.c
CommitLineData
c2f5bfd6 1/* xftfont.c -- XFT font driver.
76b6f707
GM
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
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>
d7306fe6 24#include <setjmp.h>
c2f5bfd6
KH
25#include <X11/Xlib.h>
26#include <X11/Xft/Xft.h>
27
28#include "lisp.h"
29#include "dispextern.h"
30#include "xterm.h"
31#include "frame.h"
32#include "blockinput.h"
33#include "character.h"
34#include "charset.h"
35#include "fontset.h"
36#include "font.h"
4613015e 37#include "ftfont.h"
c2f5bfd6
KH
38
39/* Xft font driver. */
40
41static Lisp_Object Qxft;
81094fab 42static Lisp_Object QChinting , QCautohint, QChintstyle, QCrgba, QCembolden;
c2f5bfd6
KH
43
44/* The actual structure for Xft font that can be casted to struct
45 font. */
46
47struct xftfont_info
48{
49 struct font font;
b0c25608 50 /* The following four members must be here in this order to be
0fce2b40 51 compatible with struct ftfont_info (in ftfont.c). */
4613015e
KH
52#ifdef HAVE_LIBOTF
53 int maybe_otf; /* Flag to tell if this may be OTF or not. */
54 OTF *otf;
794eba0f 55#endif /* HAVE_LIBOTF */
0fce2b40 56 FT_Size ft_size;
b0c25608 57 int index;
0fce2b40
KH
58 Display *display;
59 int screen;
60 XftFont *xftfont;
c2f5bfd6
KH
61};
62
63/* Structure pointed by (struct face *)->extra */
10aca0f7 64
c2f5bfd6
KH
65struct xftface_info
66{
10aca0f7
KH
67 XftColor xft_fg; /* color for face->foreground */
68 XftColor xft_bg; /* color for face->background */
c2f5bfd6
KH
69};
70
71static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
72 struct xftface_info *,
73 XftColor *fg, XftColor *bg));
c2f5bfd6
KH
74
75
10aca0f7
KH
76/* Setup foreground and background colors of GC into FG and BG. If
77 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
78 may be NULL. */
79
c2f5bfd6
KH
80static void
81xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
82 FRAME_PTR f;
83 struct face *face;
84 GC gc;
85 struct xftface_info *xftface_info;
86 XftColor *fg, *bg;
87{
88 if (xftface_info && face->gc == gc)
89 {
90 *fg = xftface_info->xft_fg;
91 if (bg)
92 *bg = xftface_info->xft_bg;
93 }
94 else
95 {
96 XGCValues xgcv;
97 int fg_done = 0, bg_done = 0;
98
99 BLOCK_INPUT;
100 XGetGCValues (FRAME_X_DISPLAY (f), gc,
101 GCForeground | GCBackground, &xgcv);
102 if (xftface_info)
103 {
104 if (xgcv.foreground == face->foreground)
105 *fg = xftface_info->xft_fg, fg_done = 1;
106 else if (xgcv.foreground == face->background)
107 *fg = xftface_info->xft_bg, fg_done = 1;
108 if (! bg)
109 bg_done = 1;
110 else if (xgcv.background == face->background)
111 *bg = xftface_info->xft_bg, bg_done = 1;
112 else if (xgcv.background == face->foreground)
113 *bg = xftface_info->xft_fg, bg_done = 1;
114 }
115
116 if (fg_done + bg_done < 2)
117 {
118 XColor colors[2];
119
120 colors[0].pixel = fg->pixel = xgcv.foreground;
121 if (bg)
122 colors[1].pixel = bg->pixel = xgcv.background;
123 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
124 bg ? 2 : 1);
125 fg->color.alpha = 0xFFFF;
126 fg->color.red = colors[0].red;
127 fg->color.green = colors[0].green;
128 fg->color.blue = colors[0].blue;
129 if (bg)
130 {
131 bg->color.alpha = 0xFFFF;
132 bg->color.red = colors[1].red;
133 bg->color.green = colors[1].green;
134 bg->color.blue = colors[1].blue;
135 }
136 }
137 UNBLOCK_INPUT;
138 }
139}
140
c2f5bfd6
KH
141
142static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
10aca0f7 143static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
3528e709 144static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
c2f5bfd6
KH
145static void xftfont_close P_ ((FRAME_PTR, struct font *));
146static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
147static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
6570a1c4 148static int xftfont_has_char P_ ((Lisp_Object, int));
c2f5bfd6
KH
149static unsigned xftfont_encode_char P_ ((struct font *, int));
150static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
151 struct font_metrics *));
152static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
a92ee6bf 153static int xftfont_end_for_frame P_ ((FRAME_PTR f));
c2f5bfd6
KH
154
155struct font_driver xftfont_driver;
156
157static Lisp_Object
158xftfont_list (frame, spec)
159 Lisp_Object frame;
160 Lisp_Object spec;
161{
3528e709 162 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
8510724d 163
3528e709
KH
164 for (tail = list; CONSP (tail); tail = XCDR (tail))
165 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
166 return list;
c2f5bfd6
KH
167}
168
10aca0f7
KH
169static Lisp_Object
170xftfont_match (frame, spec)
171 Lisp_Object frame;
172 Lisp_Object spec;
173{
174 Lisp_Object entity = ftfont_driver.match (frame, spec);
175
3528e709 176 if (! NILP (entity))
10aca0f7
KH
177 ASET (entity, FONT_TYPE_INDEX, Qxft);
178 return entity;
179}
180
1cf6763f 181extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
0fce2b40 182extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
81094fab 183extern Lisp_Object QCantialias;
98d12656 184
c2f5bfd6
KH
185static FcChar8 ascii_printable[95];
186
637fa988
JD
187static void
188xftfont_fix_match (pat, match)
189 FcPattern *pat, *match;
190{
191 /* These values are not used for matching (except antialias), but for
192 rendering, so make sure they are carried over to the match.
193 We also put antialias here because most fonts are antialiased, so
194 the match will have antialias true. */
195
196 FcBool b = FcTrue;
197 int i;
198 double dpi;
199
200 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
201 if (! b)
202 {
203 FcPatternDel (match, FC_ANTIALIAS);
204 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
205 }
206 FcPatternGetBool (pat, FC_HINTING, 0, &b);
207 if (! b)
208 {
209 FcPatternDel (match, FC_HINTING);
210 FcPatternAddBool (match, FC_HINTING, FcFalse);
211 }
212 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
213 {
214 FcPatternDel (match, FC_HINT_STYLE);
215 FcPatternAddInteger (match, FC_HINT_STYLE, i);
216 }
217 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
218 {
219 FcPatternDel (match, FC_LCD_FILTER);
220 FcPatternAddInteger (match, FC_LCD_FILTER, i);
221 }
222 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
223 {
224 FcPatternDel (match, FC_RGBA);
225 FcPatternAddInteger (match, FC_RGBA, i);
226 }
227 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
228 {
229 FcPatternDel (match, FC_DPI);
230 FcPatternAddDouble (match, FC_DPI, dpi);
231 }
232}
233
3528e709 234static Lisp_Object
c2f5bfd6
KH
235xftfont_open (f, entity, pixel_size)
236 FRAME_PTR f;
237 Lisp_Object entity;
238 int pixel_size;
239{
81094fab 240 FcResult result;
c2f5bfd6 241 Display *display = FRAME_X_DISPLAY (f);
0fce2b40 242 Lisp_Object val, filename, index, tail, font_object;
81094fab 243 FcPattern *pat = NULL, *match;
2d93c6bd 244 struct xftfont_info *xftfont_info = NULL;
c2f5bfd6
KH
245 struct font *font;
246 double size = 0;
2d93c6bd 247 XftFont *xftfont = NULL;
c2f5bfd6 248 int spacing;
3528e709
KH
249 char name[256];
250 int len, i;
91c5bb27 251 XGlyphInfo extents;
365131ac 252 FT_Face ft_face;
c2f5bfd6 253
3528e709 254 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
686ee703 255 if (! CONSP (val))
3528e709 256 return Qnil;
686ee703
KH
257 val = XCDR (val);
258 filename = XCAR (val);
0fce2b40 259 index = XCDR (val);
c2f5bfd6
KH
260 size = XINT (AREF (entity, FONT_SIZE_INDEX));
261 if (size == 0)
262 size = pixel_size;
263 pat = FcPatternCreate ();
81094fab
KH
264 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
265 i = FONT_SLANT_NUMERIC (entity) - 100;
266 if (i < 0) i = 0;
267 FcPatternAddInteger (pat, FC_SLANT, i);
268 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
c2f5bfd6 269 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
3cc2aca0
KH
270 val = AREF (entity, FONT_FAMILY_INDEX);
271 if (! NILP (val))
272 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
dc2226d0
KH
273 val = AREF (entity, FONT_FOUNDRY_INDEX);
274 if (! NILP (val))
275 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
276 val = AREF (entity, FONT_SPACING_INDEX);
277 if (! NILP (val))
278 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
279 val = AREF (entity, FONT_DPI_INDEX);
280 if (! NILP (val))
281 {
282 double dbl = XINT (val);
283
284 FcPatternAddDouble (pat, FC_DPI, dbl);
285 }
286 val = AREF (entity, FONT_AVGWIDTH_INDEX);
287 if (INTEGERP (val) && XINT (val) == 0)
288 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
0fce2b40
KH
289 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
290 over 10x20-ISO8859-1.pcf.gz). */
291 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
dc2226d0 292
81094fab
KH
293 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
294 {
295 Lisp_Object key, val;
296
297 key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
298 if (EQ (key, QCantialias))
637fa988 299 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
81094fab
KH
300 else if (EQ (key, QChinting))
301 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
302 else if (EQ (key, QCautohint))
303 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
304 else if (EQ (key, QChintstyle))
305 {
306 if (INTEGERP (val))
ea12eb81 307 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
81094fab
KH
308 }
309 else if (EQ (key, QCrgba))
310 {
311 if (INTEGERP (val))
312 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
313 }
808dd567 314#ifdef FC_EMBOLDEN
81094fab
KH
315 else if (EQ (key, QCembolden))
316 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
808dd567 317#endif
81094fab 318 }
dcce3c58 319
0fce2b40
KH
320 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
321 FcPatternAddInteger (pat, FC_INDEX, XINT (index));
8510724d 322
0fce2b40 323
dcce3c58 324 BLOCK_INPUT;
9cb363db
YM
325 /* Make sure that the Xrender extension is added before the Xft one.
326 Otherwise, the close-display hook set by Xft is called after the
327 one for Xrender, and the former tries to re-add the latter. This
328 results in inconsistency of internal states and leads to X
329 protocol error when one reconnects to the same X server.
330 (Bug#1696) */
331 {
332 int event_base, error_base;
333 XRenderQueryExtension (display, &event_base, &error_base);
334 }
637fa988
JD
335
336 /* Substitute in values from X resources and XftDefaultSet. */
337 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
81094fab 338 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
637fa988
JD
339 xftfont_fix_match (pat, match);
340
81094fab
KH
341 FcPatternDestroy (pat);
342 xftfont = XftFontOpenPattern (display, match);
99061dfc 343 if (!xftfont)
5c629bf6 344 {
99061dfc 345 UNBLOCK_INPUT;
5c629bf6
CY
346 XftPatternDestroy (match);
347 return Qnil;
348 }
99061dfc
CY
349 ft_face = XftLockFace (xftfont);
350 UNBLOCK_INPUT;
351
c2f5bfd6
KH
352 /* We should not destroy PAT here because it is kept in XFTFONT and
353 destroyed automatically when XFTFONT is closed. */
0fce2b40 354 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
3528e709 355 ASET (font_object, FONT_TYPE_INDEX, Qxft);
3528e709
KH
356 len = font_unparse_xlfd (entity, size, name, 256);
357 if (len > 0)
2781b4e0 358 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
3528e709
KH
359 len = font_unparse_fcname (entity, size, name, 256);
360 if (len > 0)
2781b4e0 361 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
3528e709
KH
362 else
363 ASET (font_object, FONT_FULLNAME_INDEX,
364 AREF (font_object, FONT_NAME_INDEX));
686ee703
KH
365 ASET (font_object, FONT_FILE_INDEX, filename);
366 ASET (font_object, FONT_FORMAT_INDEX,
1cf6763f 367 ftfont_font_format (xftfont->pattern, filename));
3528e709
KH
368 font = XFONT_OBJECT (font_object);
369 font->pixel_size = pixel_size;
370 font->driver = &xftfont_driver;
371 font->encoding_charset = font->repertory_charset = -1;
372
373 xftfont_info = (struct xftfont_info *) font;
c2f5bfd6
KH
374 xftfont_info->display = display;
375 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
376 xftfont_info->xftfont = xftfont;
c2f5bfd6
KH
377 font->pixel_size = size;
378 font->driver = &xftfont_driver;
686ee703
KH
379 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
380 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
381 else
c2f5bfd6 382 spacing = FC_PROPORTIONAL;
91c5bb27
KH
383 if (! ascii_printable[0])
384 {
385 int i;
386 for (i = 0; i < 95; i++)
387 ascii_printable[i] = ' ' + i;
388 }
3528e709 389 BLOCK_INPUT;
c2f5bfd6 390 if (spacing != FC_PROPORTIONAL)
91c5bb27 391 {
3528e709 392 font->min_width = font->average_width = font->space_width
91c5bb27
KH
393 = xftfont->max_advance_width;
394 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
395 }
c2f5bfd6
KH
396 else
397 {
c2f5bfd6 398 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
3528e709
KH
399 font->space_width = extents.xOff;
400 if (font->space_width <= 0)
c2f5bfd6 401 /* dirty workaround */
8510724d 402 font->space_width = pixel_size;
c2f5bfd6 403 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
3528e709 404 font->average_width = (font->space_width + extents.xOff) / 95;
c2f5bfd6 405 }
dcce3c58 406 UNBLOCK_INPUT;
c2f5bfd6 407
91c5bb27 408 font->ascent = xftfont->ascent;
91c5bb27 409 font->descent = xftfont->descent;
81094fab
KH
410 if (pixel_size >= 5)
411 {
412 /* The above condition is a dirty workaround because
413 XftTextExtents8 behaves strangely for some fonts
414 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
415 if (font->ascent < extents.y)
416 font->ascent = extents.y;
417 if (font->descent < extents.height - extents.y)
418 font->descent = extents.height - extents.y;
419 }
3528e709 420 font->height = font->ascent + font->descent;
91c5bb27 421
3528e709 422 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
c2f5bfd6 423 {
3528e709
KH
424 int upEM = ft_face->units_per_EM;
425
426 font->underline_position = -ft_face->underline_position * size / upEM;
bc981e4e 427 font->underline_thickness = ft_face->underline_thickness * size / upEM;
951b8112
KH
428 if (font->underline_thickness > 2)
429 font->underline_position -= font->underline_thickness / 2;
c2f5bfd6
KH
430 }
431 else
432 {
3528e709
KH
433 font->underline_position = -1;
434 font->underline_thickness = 0;
c2f5bfd6 435 }
3528e709
KH
436#ifdef HAVE_LIBOTF
437 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
438 xftfont_info->otf = NULL;
439#endif /* HAVE_LIBOTF */
0fce2b40 440 xftfont_info->ft_size = ft_face->size;
c2f5bfd6 441
3528e709
KH
442 /* Unfortunately Xft doesn't provide a way to get minimum char
443 width. So, we use space_width instead. */
444 font->min_width = font->space_width;
2d93c6bd 445
3528e709
KH
446 font->baseline_offset = 0;
447 font->relative_compose = 0;
448 font->default_ascent = 0;
449 font->vertical_centering = 0;
0fce2b40
KH
450#ifdef FT_BDF_H
451 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
452 {
453 BDF_PropertyRec rec;
454
455 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
456 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
457 font->baseline_offset = rec.u.integer;
458 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
459 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
460 font->relative_compose = rec.u.integer;
461 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
462 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
463 font->default_ascent = rec.u.integer;
464 }
465#endif
3528e709
KH
466
467 return font_object;
c2f5bfd6
KH
468}
469
470static void
471xftfont_close (f, font)
472 FRAME_PTR f;
473 struct font *font;
474{
475 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
476
4613015e
KH
477#ifdef HAVE_LIBOTF
478 if (xftfont_info->otf)
479 OTF_close (xftfont_info->otf);
480#endif
3528e709 481 BLOCK_INPUT;
0fce2b40 482 XftUnlockFace (xftfont_info->xftfont);
c2f5bfd6 483 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
3528e709 484 UNBLOCK_INPUT;
c2f5bfd6
KH
485}
486
c2f5bfd6
KH
487static int
488xftfont_prepare_face (f, face)
489 FRAME_PTR f;
490 struct face *face;
491{
e2d0c925 492 struct xftface_info *xftface_info;
c2f5bfd6 493
a703d27d
KH
494#if 0
495 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
e2d0c925
KH
496 if (face != face->ascii_face)
497 {
498 face->extra = face->ascii_face->extra;
499 return 0;
500 }
a703d27d 501#endif
e2d0c925
KH
502
503 xftface_info = malloc (sizeof (struct xftface_info));
c2f5bfd6
KH
504 if (! xftface_info)
505 return -1;
c2f5bfd6
KH
506 xftfont_get_colors (f, face, face->gc, NULL,
507 &xftface_info->xft_fg, &xftface_info->xft_bg);
c2f5bfd6
KH
508 face->extra = xftface_info;
509 return 0;
510}
511
512static void
513xftfont_done_face (f, face)
514 FRAME_PTR f;
515 struct face *face;
516{
e2d0c925 517 struct xftface_info *xftface_info;
8510724d 518
a703d27d
KH
519#if 0
520 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
e2d0c925
KH
521 if (face != face->ascii_face
522 || ! face->extra)
523 return;
a703d27d 524#endif
c2f5bfd6 525
e2d0c925 526 xftface_info = (struct xftface_info *) face->extra;
773039e8
JD
527 if (xftface_info)
528 {
773039e8 529 free (xftface_info);
a92ee6bf 530 face->extra = NULL;
773039e8 531 }
c2f5bfd6
KH
532}
533
b840b299
KH
534extern Lisp_Object Qja, Qko;
535
6570a1c4
KH
536static int
537xftfont_has_char (font, c)
538 Lisp_Object font;
539 int c;
540{
541 struct xftfont_info *xftfont_info;
b840b299 542 struct charset *cs = NULL;
6570a1c4 543
b840b299
KH
544 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
545 && charset_jisx0208 >= 0)
546 cs = CHARSET_FROM_ID (charset_jisx0208);
547 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
548 && charset_ksc5601 >= 0)
549 cs = CHARSET_FROM_ID (charset_ksc5601);
550 if (cs)
551 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
552
ea12eb81
KH
553 if (FONT_ENTITY_P (font))
554 return ftfont_driver.has_char (font, c);
6570a1c4
KH
555 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
556 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
557 (FcChar32) c) == FcTrue);
558}
559
c2f5bfd6
KH
560static unsigned
561xftfont_encode_char (font, c)
562 struct font *font;
563 int c;
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
573xftfont_text_extents (font, code, nglyphs, metrics)
574 struct font *font;
575 unsigned *code;
576 int nglyphs;
577 struct font_metrics *metrics;
578{
579 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
580 XGlyphInfo extents;
581
582 BLOCK_INPUT;
583 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
584 &extents);
585 UNBLOCK_INPUT;
586 if (metrics)
587 {
588 metrics->lbearing = - extents.x;
589 metrics->rbearing = - extents.x + extents.width;
590 metrics->width = extents.xOff;
591 metrics->ascent = extents.y;
4b848612 592 metrics->descent = extents.height - extents.y;
c2f5bfd6
KH
593 }
594 return extents.xOff;
595}
596
a92ee6bf
KH
597static XftDraw *
598xftfont_get_xft_draw (f)
599 FRAME_PTR f;
600{
8510724d 601 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
a92ee6bf
KH
602
603 if (! xft_draw)
604 {
605 BLOCK_INPUT;
606 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
607 FRAME_X_WINDOW (f),
608 FRAME_X_VISUAL (f),
609 FRAME_X_COLORMAP (f));
610 UNBLOCK_INPUT;
611 if (! xft_draw)
612 abort ();
613 font_put_frame_data (f, &xftfont_driver, xft_draw);
614 }
615 return xft_draw;
616}
617
c2f5bfd6
KH
618static int
619xftfont_draw (s, from, to, x, y, with_background)
620 struct glyph_string *s;
621 int from, to, x, y, with_background;
622{
623 FRAME_PTR f = s->f;
624 struct face *face = s->face;
3528e709 625 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
c78c1659 626 struct xftface_info *xftface_info = NULL;
a92ee6bf 627 XftDraw *xft_draw = xftfont_get_xft_draw (f);
c2f5bfd6
KH
628 FT_UInt *code;
629 XftColor fg, bg;
c2f5bfd6
KH
630 int len = to - from;
631 int i;
632
3528e709 633 if (s->font == face->font)
a92ee6bf 634 xftface_info = (struct xftface_info *) face->extra;
c2f5bfd6 635 xftfont_get_colors (f, face, s->gc, xftface_info,
322f8671 636 &fg, with_background ? &bg : NULL);
c2f5bfd6 637 BLOCK_INPUT;
03d198e8
KH
638 if (s->num_clips > 0)
639 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
640 else
641 XftDrawSetClip (xft_draw, NULL);
642
c2f5bfd6 643 if (with_background)
3528e709
KH
644 XftDrawRect (xft_draw, &bg,
645 x, y - face->font->ascent, s->width, face->font->height);
c2f5bfd6
KH
646 code = alloca (sizeof (FT_UInt) * len);
647 for (i = 0; i < len; i++)
648 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
649 | XCHAR2B_BYTE2 (s->char2b + from + i));
650
785543da
KH
651 if (s->padding_p)
652 for (i = 0; i < len; i++)
653 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
654 x + i, y, code + i, 1);
655 else
656 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
657 x, y, code, len);
c2f5bfd6
KH
658 UNBLOCK_INPUT;
659
660 return len;
661}
662
a92ee6bf
KH
663static int
664xftfont_end_for_frame (f)
665 FRAME_PTR f;
666{
667 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
668
669 if (xft_draw)
670 {
671 BLOCK_INPUT;
672 XftDrawDestroy (xft_draw);
673 UNBLOCK_INPUT;
674 font_put_frame_data (f, &xftfont_driver, NULL);
675 }
676 return 0;
677}
c2f5bfd6
KH
678
679void
680syms_of_xftfont ()
681{
682 DEFSYM (Qxft, "xft");
81094fab 683 DEFSYM (QChinting, ":hinting");
9743ac48 684 DEFSYM (QCautohint, ":autohint");
81094fab
KH
685 DEFSYM (QChintstyle, ":hintstyle");
686 DEFSYM (QCrgba, ":rgba");
687 DEFSYM (QCembolden, ":embolden");
c2f5bfd6
KH
688
689 xftfont_driver = ftfont_driver;
690 xftfont_driver.type = Qxft;
691 xftfont_driver.get_cache = xfont_driver.get_cache;
692 xftfont_driver.list = xftfont_list;
10aca0f7 693 xftfont_driver.match = xftfont_match;
c2f5bfd6
KH
694 xftfont_driver.open = xftfont_open;
695 xftfont_driver.close = xftfont_close;
696 xftfont_driver.prepare_face = xftfont_prepare_face;
697 xftfont_driver.done_face = xftfont_done_face;
6570a1c4 698 xftfont_driver.has_char = xftfont_has_char;
c2f5bfd6
KH
699 xftfont_driver.encode_char = xftfont_encode_char;
700 xftfont_driver.text_extents = xftfont_text_extents;
701 xftfont_driver.draw = xftfont_draw;
a92ee6bf 702 xftfont_driver.end_for_frame = xftfont_end_for_frame;
c2f5bfd6
KH
703
704 register_font_driver (&xftfont_driver, NULL);
705}
885b7d09
MB
706
707/* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
708 (do not change this comment) */