#ifdef on FC_LCD_FILTER.
[emacs.git] / src / xftfont.c
blob130bd84c69b43558a41cae8e89d46fec51bb7d8b
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
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 3 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <setjmp.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xft/Xft.h>
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"
37 #include "ftfont.h"
39 /* Xft font driver. */
41 static Lisp_Object Qxft;
42 static Lisp_Object QChinting , QCautohint, QChintstyle, QCrgba, QCembolden;
44 /* The actual structure for Xft font that can be casted to struct
45 font. */
47 struct xftfont_info
49 struct font font;
50 /* The following four members must be here in this order to be
51 compatible with struct ftfont_info (in ftfont.c). */
52 #ifdef HAVE_LIBOTF
53 int maybe_otf; /* Flag to tell if this may be OTF or not. */
54 OTF *otf;
55 #endif /* HAVE_LIBOTF */
56 FT_Size ft_size;
57 int index;
58 Display *display;
59 int screen;
60 XftFont *xftfont;
63 /* Structure pointed by (struct face *)->extra */
65 struct xftface_info
67 XftColor xft_fg; /* color for face->foreground */
68 XftColor xft_bg; /* color for face->background */
71 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
72 struct xftface_info *,
73 XftColor *fg, XftColor *bg));
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. */
80 static void
81 xftfont_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;
88 if (xftface_info && face->gc == gc)
90 *fg = xftface_info->xft_fg;
91 if (bg)
92 *bg = xftface_info->xft_bg;
94 else
96 XGCValues xgcv;
97 int fg_done = 0, bg_done = 0;
99 BLOCK_INPUT;
100 XGetGCValues (FRAME_X_DISPLAY (f), gc,
101 GCForeground | GCBackground, &xgcv);
102 if (xftface_info)
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;
116 if (fg_done + bg_done < 2)
118 XColor colors[2];
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)
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;
137 UNBLOCK_INPUT;
142 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
143 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
144 static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
145 static void xftfont_close P_ ((FRAME_PTR, struct font *));
146 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
147 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
148 static int xftfont_has_char P_ ((Lisp_Object, int));
149 static unsigned xftfont_encode_char P_ ((struct font *, int));
150 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
151 struct font_metrics *));
152 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
153 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
155 struct font_driver xftfont_driver;
157 static Lisp_Object
158 xftfont_list (frame, spec)
159 Lisp_Object frame;
160 Lisp_Object spec;
162 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
164 for (tail = list; CONSP (tail); tail = XCDR (tail))
165 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
166 return list;
169 static Lisp_Object
170 xftfont_match (frame, spec)
171 Lisp_Object frame;
172 Lisp_Object spec;
174 Lisp_Object entity = ftfont_driver.match (frame, spec);
176 if (! NILP (entity))
177 ASET (entity, FONT_TYPE_INDEX, Qxft);
178 return entity;
181 extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
182 extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
183 extern Lisp_Object QCantialias;
185 static FcChar8 ascii_printable[95];
187 static void
188 xftfont_fix_match (pat, match)
189 FcPattern *pat, *match;
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. */
196 FcBool b = FcTrue;
197 int i;
198 double dpi;
200 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
201 if (! b)
203 FcPatternDel (match, FC_ANTIALIAS);
204 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
206 FcPatternGetBool (pat, FC_HINTING, 0, &b);
207 if (! b)
209 FcPatternDel (match, FC_HINTING);
210 FcPatternAddBool (match, FC_HINTING, FcFalse);
212 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
214 FcPatternDel (match, FC_HINT_STYLE);
215 FcPatternAddInteger (match, FC_HINT_STYLE, i);
217 #ifdef FC_LCD_FILTER
218 /* Older fontconfig versions don't have FC_LCD_FILTER. */
219 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
221 FcPatternDel (match, FC_LCD_FILTER);
222 FcPatternAddInteger (match, FC_LCD_FILTER, i);
224 #endif
225 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
227 FcPatternDel (match, FC_RGBA);
228 FcPatternAddInteger (match, FC_RGBA, i);
230 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
232 FcPatternDel (match, FC_DPI);
233 FcPatternAddDouble (match, FC_DPI, dpi);
237 static Lisp_Object
238 xftfont_open (f, entity, pixel_size)
239 FRAME_PTR f;
240 Lisp_Object entity;
241 int pixel_size;
243 FcResult result;
244 Display *display = FRAME_X_DISPLAY (f);
245 Lisp_Object val, filename, index, tail, font_object;
246 FcPattern *pat = NULL, *match;
247 struct xftfont_info *xftfont_info = NULL;
248 struct font *font;
249 double size = 0;
250 XftFont *xftfont = NULL;
251 int spacing;
252 char name[256];
253 int len, i;
254 XGlyphInfo extents;
255 FT_Face ft_face;
257 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
258 if (! CONSP (val))
259 return Qnil;
260 val = XCDR (val);
261 filename = XCAR (val);
262 index = XCDR (val);
263 size = XINT (AREF (entity, FONT_SIZE_INDEX));
264 if (size == 0)
265 size = pixel_size;
266 pat = FcPatternCreate ();
267 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
268 i = FONT_SLANT_NUMERIC (entity) - 100;
269 if (i < 0) i = 0;
270 FcPatternAddInteger (pat, FC_SLANT, i);
271 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
272 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
273 val = AREF (entity, FONT_FAMILY_INDEX);
274 if (! NILP (val))
275 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
276 val = AREF (entity, FONT_FOUNDRY_INDEX);
277 if (! NILP (val))
278 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
279 val = AREF (entity, FONT_SPACING_INDEX);
280 if (! NILP (val))
281 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
282 val = AREF (entity, FONT_DPI_INDEX);
283 if (! NILP (val))
285 double dbl = XINT (val);
287 FcPatternAddDouble (pat, FC_DPI, dbl);
289 val = AREF (entity, FONT_AVGWIDTH_INDEX);
290 if (INTEGERP (val) && XINT (val) == 0)
291 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
292 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
293 over 10x20-ISO8859-1.pcf.gz). */
294 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
296 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
298 Lisp_Object key, val;
300 key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
301 if (EQ (key, QCantialias))
302 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
303 else if (EQ (key, QChinting))
304 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
305 else if (EQ (key, QCautohint))
306 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
307 else if (EQ (key, QChintstyle))
309 if (INTEGERP (val))
310 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
312 else if (EQ (key, QCrgba))
314 if (INTEGERP (val))
315 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
317 #ifdef FC_EMBOLDEN
318 else if (EQ (key, QCembolden))
319 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
320 #endif
323 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
324 FcPatternAddInteger (pat, FC_INDEX, XINT (index));
327 BLOCK_INPUT;
328 /* Make sure that the Xrender extension is added before the Xft one.
329 Otherwise, the close-display hook set by Xft is called after the
330 one for Xrender, and the former tries to re-add the latter. This
331 results in inconsistency of internal states and leads to X
332 protocol error when one reconnects to the same X server.
333 (Bug#1696) */
335 int event_base, error_base;
336 XRenderQueryExtension (display, &event_base, &error_base);
339 /* Substitute in values from X resources and XftDefaultSet. */
340 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
341 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
342 xftfont_fix_match (pat, match);
344 FcPatternDestroy (pat);
345 xftfont = XftFontOpenPattern (display, match);
346 if (!xftfont)
348 UNBLOCK_INPUT;
349 XftPatternDestroy (match);
350 return Qnil;
352 ft_face = XftLockFace (xftfont);
353 UNBLOCK_INPUT;
355 /* We should not destroy PAT here because it is kept in XFTFONT and
356 destroyed automatically when XFTFONT is closed. */
357 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
358 ASET (font_object, FONT_TYPE_INDEX, Qxft);
359 len = font_unparse_xlfd (entity, size, name, 256);
360 if (len > 0)
361 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
362 len = font_unparse_fcname (entity, size, name, 256);
363 if (len > 0)
364 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
365 else
366 ASET (font_object, FONT_FULLNAME_INDEX,
367 AREF (font_object, FONT_NAME_INDEX));
368 ASET (font_object, FONT_FILE_INDEX, filename);
369 ASET (font_object, FONT_FORMAT_INDEX,
370 ftfont_font_format (xftfont->pattern, filename));
371 font = XFONT_OBJECT (font_object);
372 font->pixel_size = pixel_size;
373 font->driver = &xftfont_driver;
374 font->encoding_charset = font->repertory_charset = -1;
376 xftfont_info = (struct xftfont_info *) font;
377 xftfont_info->display = display;
378 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
379 xftfont_info->xftfont = xftfont;
380 font->pixel_size = size;
381 font->driver = &xftfont_driver;
382 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
383 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
384 else
385 spacing = FC_PROPORTIONAL;
386 if (! ascii_printable[0])
388 int i;
389 for (i = 0; i < 95; i++)
390 ascii_printable[i] = ' ' + i;
392 BLOCK_INPUT;
393 if (spacing != FC_PROPORTIONAL)
395 font->min_width = font->average_width = font->space_width
396 = xftfont->max_advance_width;
397 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
399 else
401 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
402 font->space_width = extents.xOff;
403 if (font->space_width <= 0)
404 /* dirty workaround */
405 font->space_width = pixel_size;
406 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
407 font->average_width = (font->space_width + extents.xOff) / 95;
409 UNBLOCK_INPUT;
411 font->ascent = xftfont->ascent;
412 font->descent = xftfont->descent;
413 if (pixel_size >= 5)
415 /* The above condition is a dirty workaround because
416 XftTextExtents8 behaves strangely for some fonts
417 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
418 if (font->ascent < extents.y)
419 font->ascent = extents.y;
420 if (font->descent < extents.height - extents.y)
421 font->descent = extents.height - extents.y;
423 font->height = font->ascent + font->descent;
425 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
427 int upEM = ft_face->units_per_EM;
429 font->underline_position = -ft_face->underline_position * size / upEM;
430 font->underline_thickness = ft_face->underline_thickness * size / upEM;
431 if (font->underline_thickness > 2)
432 font->underline_position -= font->underline_thickness / 2;
434 else
436 font->underline_position = -1;
437 font->underline_thickness = 0;
439 #ifdef HAVE_LIBOTF
440 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
441 xftfont_info->otf = NULL;
442 #endif /* HAVE_LIBOTF */
443 xftfont_info->ft_size = ft_face->size;
445 /* Unfortunately Xft doesn't provide a way to get minimum char
446 width. So, we use space_width instead. */
447 font->min_width = font->space_width;
449 font->baseline_offset = 0;
450 font->relative_compose = 0;
451 font->default_ascent = 0;
452 font->vertical_centering = 0;
453 #ifdef FT_BDF_H
454 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
456 BDF_PropertyRec rec;
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;
468 #endif
470 return font_object;
473 static void
474 xftfont_close (f, font)
475 FRAME_PTR f;
476 struct font *font;
478 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
480 #ifdef HAVE_LIBOTF
481 if (xftfont_info->otf)
482 OTF_close (xftfont_info->otf);
483 #endif
484 BLOCK_INPUT;
485 XftUnlockFace (xftfont_info->xftfont);
486 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
487 UNBLOCK_INPUT;
490 static int
491 xftfont_prepare_face (f, face)
492 FRAME_PTR f;
493 struct face *face;
495 struct xftface_info *xftface_info;
497 #if 0
498 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
499 if (face != face->ascii_face)
501 face->extra = face->ascii_face->extra;
502 return 0;
504 #endif
506 xftface_info = malloc (sizeof (struct xftface_info));
507 if (! xftface_info)
508 return -1;
509 xftfont_get_colors (f, face, face->gc, NULL,
510 &xftface_info->xft_fg, &xftface_info->xft_bg);
511 face->extra = xftface_info;
512 return 0;
515 static void
516 xftfont_done_face (f, face)
517 FRAME_PTR f;
518 struct face *face;
520 struct xftface_info *xftface_info;
522 #if 0
523 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
524 if (face != face->ascii_face
525 || ! face->extra)
526 return;
527 #endif
529 xftface_info = (struct xftface_info *) face->extra;
530 if (xftface_info)
532 free (xftface_info);
533 face->extra = NULL;
537 extern Lisp_Object Qja, Qko;
539 static int
540 xftfont_has_char (font, c)
541 Lisp_Object font;
542 int c;
544 struct xftfont_info *xftfont_info;
545 struct charset *cs = NULL;
547 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
548 && charset_jisx0208 >= 0)
549 cs = CHARSET_FROM_ID (charset_jisx0208);
550 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
551 && charset_ksc5601 >= 0)
552 cs = CHARSET_FROM_ID (charset_ksc5601);
553 if (cs)
554 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
556 if (FONT_ENTITY_P (font))
557 return ftfont_driver.has_char (font, c);
558 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
559 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
560 (FcChar32) c) == FcTrue);
563 static unsigned
564 xftfont_encode_char (font, c)
565 struct font *font;
566 int c;
568 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
569 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
570 (FcChar32) c);
572 return (code ? code : FONT_INVALID_CODE);
575 static int
576 xftfont_text_extents (font, code, nglyphs, metrics)
577 struct font *font;
578 unsigned *code;
579 int nglyphs;
580 struct font_metrics *metrics;
582 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
583 XGlyphInfo extents;
585 BLOCK_INPUT;
586 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
587 &extents);
588 UNBLOCK_INPUT;
589 if (metrics)
591 metrics->lbearing = - extents.x;
592 metrics->rbearing = - extents.x + extents.width;
593 metrics->width = extents.xOff;
594 metrics->ascent = extents.y;
595 metrics->descent = extents.height - extents.y;
597 return extents.xOff;
600 static XftDraw *
601 xftfont_get_xft_draw (f)
602 FRAME_PTR f;
604 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
606 if (! xft_draw)
608 BLOCK_INPUT;
609 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
610 FRAME_X_WINDOW (f),
611 FRAME_X_VISUAL (f),
612 FRAME_X_COLORMAP (f));
613 UNBLOCK_INPUT;
614 if (! xft_draw)
615 abort ();
616 font_put_frame_data (f, &xftfont_driver, xft_draw);
618 return xft_draw;
621 static int
622 xftfont_draw (s, from, to, x, y, with_background)
623 struct glyph_string *s;
624 int from, to, x, y, with_background;
626 FRAME_PTR f = s->f;
627 struct face *face = s->face;
628 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
629 struct xftface_info *xftface_info = NULL;
630 XftDraw *xft_draw = xftfont_get_xft_draw (f);
631 FT_UInt *code;
632 XftColor fg, bg;
633 int len = to - from;
634 int i;
636 if (s->font == face->font)
637 xftface_info = (struct xftface_info *) face->extra;
638 xftfont_get_colors (f, face, s->gc, xftface_info,
639 &fg, with_background ? &bg : NULL);
640 BLOCK_INPUT;
641 if (s->num_clips > 0)
642 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
643 else
644 XftDrawSetClip (xft_draw, NULL);
646 if (with_background)
647 XftDrawRect (xft_draw, &bg,
648 x, y - face->font->ascent, s->width, face->font->height);
649 code = alloca (sizeof (FT_UInt) * len);
650 for (i = 0; i < len; i++)
651 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
652 | XCHAR2B_BYTE2 (s->char2b + from + i));
654 if (s->padding_p)
655 for (i = 0; i < len; i++)
656 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
657 x + i, y, code + i, 1);
658 else
659 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
660 x, y, code, len);
661 UNBLOCK_INPUT;
663 return len;
666 static int
667 xftfont_end_for_frame (f)
668 FRAME_PTR f;
670 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
672 if (xft_draw)
674 BLOCK_INPUT;
675 XftDrawDestroy (xft_draw);
676 UNBLOCK_INPUT;
677 font_put_frame_data (f, &xftfont_driver, NULL);
679 return 0;
682 void
683 syms_of_xftfont ()
685 DEFSYM (Qxft, "xft");
686 DEFSYM (QChinting, ":hinting");
687 DEFSYM (QCautohint, ":autohint");
688 DEFSYM (QChintstyle, ":hintstyle");
689 DEFSYM (QCrgba, ":rgba");
690 DEFSYM (QCembolden, ":embolden");
692 xftfont_driver = ftfont_driver;
693 xftfont_driver.type = Qxft;
694 xftfont_driver.get_cache = xfont_driver.get_cache;
695 xftfont_driver.list = xftfont_list;
696 xftfont_driver.match = xftfont_match;
697 xftfont_driver.open = xftfont_open;
698 xftfont_driver.close = xftfont_close;
699 xftfont_driver.prepare_face = xftfont_prepare_face;
700 xftfont_driver.done_face = xftfont_done_face;
701 xftfont_driver.has_char = xftfont_has_char;
702 xftfont_driver.encode_char = xftfont_encode_char;
703 xftfont_driver.text_extents = xftfont_text_extents;
704 xftfont_driver.draw = xftfont_draw;
705 xftfont_driver.end_for_frame = xftfont_end_for_frame;
707 register_font_driver (&xftfont_driver, NULL);
710 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
711 (do not change this comment) */