Bump version to 23.1.90.
[emacs.git] / src / xftfont.c
blobe2819863f07407809b0d94ee4adb31c193d420d5
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 #ifndef FC_LCD_FILTER
218 /* Older fontconfig versions don't have FC_LCD_FILTER. */
219 #define FC_LCD_FILTER "lcdfilter"
220 #endif
221 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
223 FcPatternDel (match, FC_LCD_FILTER);
224 FcPatternAddInteger (match, FC_LCD_FILTER, i);
226 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
228 FcPatternDel (match, FC_RGBA);
229 FcPatternAddInteger (match, FC_RGBA, i);
231 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
233 FcPatternDel (match, FC_DPI);
234 FcPatternAddDouble (match, FC_DPI, dpi);
238 static Lisp_Object
239 xftfont_open (f, entity, pixel_size)
240 FRAME_PTR f;
241 Lisp_Object entity;
242 int pixel_size;
244 FcResult result;
245 Display *display = FRAME_X_DISPLAY (f);
246 Lisp_Object val, filename, index, tail, font_object;
247 FcPattern *pat = NULL, *match;
248 struct xftfont_info *xftfont_info = NULL;
249 struct font *font;
250 double size = 0;
251 XftFont *xftfont = NULL;
252 int spacing;
253 char name[256];
254 int len, i;
255 XGlyphInfo extents;
256 FT_Face ft_face;
258 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
259 if (! CONSP (val))
260 return Qnil;
261 val = XCDR (val);
262 filename = XCAR (val);
263 index = XCDR (val);
264 size = XINT (AREF (entity, FONT_SIZE_INDEX));
265 if (size == 0)
266 size = pixel_size;
267 pat = FcPatternCreate ();
268 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
269 i = FONT_SLANT_NUMERIC (entity) - 100;
270 if (i < 0) i = 0;
271 FcPatternAddInteger (pat, FC_SLANT, i);
272 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
273 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
274 val = AREF (entity, FONT_FAMILY_INDEX);
275 if (! NILP (val))
276 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
277 val = AREF (entity, FONT_FOUNDRY_INDEX);
278 if (! NILP (val))
279 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
280 val = AREF (entity, FONT_SPACING_INDEX);
281 if (! NILP (val))
282 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
283 val = AREF (entity, FONT_DPI_INDEX);
284 if (! NILP (val))
286 double dbl = XINT (val);
288 FcPatternAddDouble (pat, FC_DPI, dbl);
290 val = AREF (entity, FONT_AVGWIDTH_INDEX);
291 if (INTEGERP (val) && XINT (val) == 0)
292 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
293 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
294 over 10x20-ISO8859-1.pcf.gz). */
295 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
297 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
299 Lisp_Object key, val;
301 key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
302 if (EQ (key, QCantialias))
303 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
304 else if (EQ (key, QChinting))
305 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
306 else if (EQ (key, QCautohint))
307 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
308 else if (EQ (key, QChintstyle))
310 if (INTEGERP (val))
311 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
313 else if (EQ (key, QCrgba))
315 if (INTEGERP (val))
316 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
318 #ifdef FC_EMBOLDEN
319 else if (EQ (key, QCembolden))
320 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
321 #endif
324 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
325 FcPatternAddInteger (pat, FC_INDEX, XINT (index));
328 BLOCK_INPUT;
329 /* Make sure that the Xrender extension is added before the Xft one.
330 Otherwise, the close-display hook set by Xft is called after the
331 one for Xrender, and the former tries to re-add the latter. This
332 results in inconsistency of internal states and leads to X
333 protocol error when one reconnects to the same X server.
334 (Bug#1696) */
336 int event_base, error_base;
337 XRenderQueryExtension (display, &event_base, &error_base);
340 /* Substitute in values from X resources and XftDefaultSet. */
341 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
342 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
343 xftfont_fix_match (pat, match);
345 FcPatternDestroy (pat);
346 xftfont = XftFontOpenPattern (display, match);
347 if (!xftfont)
349 UNBLOCK_INPUT;
350 XftPatternDestroy (match);
351 return Qnil;
353 ft_face = XftLockFace (xftfont);
354 UNBLOCK_INPUT;
356 /* We should not destroy PAT here because it is kept in XFTFONT and
357 destroyed automatically when XFTFONT is closed. */
358 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
359 ASET (font_object, FONT_TYPE_INDEX, Qxft);
360 len = font_unparse_xlfd (entity, size, name, 256);
361 if (len > 0)
362 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
363 len = font_unparse_fcname (entity, size, name, 256);
364 if (len > 0)
365 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
366 else
367 ASET (font_object, FONT_FULLNAME_INDEX,
368 AREF (font_object, FONT_NAME_INDEX));
369 ASET (font_object, FONT_FILE_INDEX, filename);
370 ASET (font_object, FONT_FORMAT_INDEX,
371 ftfont_font_format (xftfont->pattern, filename));
372 font = XFONT_OBJECT (font_object);
373 font->pixel_size = pixel_size;
374 font->driver = &xftfont_driver;
375 font->encoding_charset = font->repertory_charset = -1;
377 xftfont_info = (struct xftfont_info *) font;
378 xftfont_info->display = display;
379 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
380 xftfont_info->xftfont = xftfont;
381 font->pixel_size = size;
382 font->driver = &xftfont_driver;
383 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
384 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
385 else
386 spacing = FC_PROPORTIONAL;
387 if (! ascii_printable[0])
389 int i;
390 for (i = 0; i < 95; i++)
391 ascii_printable[i] = ' ' + i;
393 BLOCK_INPUT;
394 if (spacing != FC_PROPORTIONAL)
396 font->min_width = font->average_width = font->space_width
397 = xftfont->max_advance_width;
398 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
400 else
402 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
403 font->space_width = extents.xOff;
404 if (font->space_width <= 0)
405 /* dirty workaround */
406 font->space_width = pixel_size;
407 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
408 font->average_width = (font->space_width + extents.xOff) / 95;
410 UNBLOCK_INPUT;
412 font->ascent = xftfont->ascent;
413 font->descent = xftfont->descent;
414 if (pixel_size >= 5)
416 /* The above condition is a dirty workaround because
417 XftTextExtents8 behaves strangely for some fonts
418 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
419 if (font->ascent < extents.y)
420 font->ascent = extents.y;
421 if (font->descent < extents.height - extents.y)
422 font->descent = extents.height - extents.y;
424 font->height = font->ascent + font->descent;
426 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
428 int upEM = ft_face->units_per_EM;
430 font->underline_position = -ft_face->underline_position * size / upEM;
431 font->underline_thickness = ft_face->underline_thickness * size / upEM;
432 if (font->underline_thickness > 2)
433 font->underline_position -= font->underline_thickness / 2;
435 else
437 font->underline_position = -1;
438 font->underline_thickness = 0;
440 #ifdef HAVE_LIBOTF
441 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
442 xftfont_info->otf = NULL;
443 #endif /* HAVE_LIBOTF */
444 xftfont_info->ft_size = ft_face->size;
446 /* Unfortunately Xft doesn't provide a way to get minimum char
447 width. So, we use space_width instead. */
448 font->min_width = font->space_width;
450 font->baseline_offset = 0;
451 font->relative_compose = 0;
452 font->default_ascent = 0;
453 font->vertical_centering = 0;
454 #ifdef FT_BDF_H
455 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
457 BDF_PropertyRec rec;
459 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
460 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
461 font->baseline_offset = rec.u.integer;
462 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
463 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
464 font->relative_compose = rec.u.integer;
465 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
466 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
467 font->default_ascent = rec.u.integer;
469 #endif
471 return font_object;
474 static void
475 xftfont_close (f, font)
476 FRAME_PTR f;
477 struct font *font;
479 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
481 #ifdef HAVE_LIBOTF
482 if (xftfont_info->otf)
483 OTF_close (xftfont_info->otf);
484 #endif
485 BLOCK_INPUT;
486 XftUnlockFace (xftfont_info->xftfont);
487 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
488 UNBLOCK_INPUT;
491 static int
492 xftfont_prepare_face (f, face)
493 FRAME_PTR f;
494 struct face *face;
496 struct xftface_info *xftface_info;
498 #if 0
499 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
500 if (face != face->ascii_face)
502 face->extra = face->ascii_face->extra;
503 return 0;
505 #endif
507 xftface_info = malloc (sizeof (struct xftface_info));
508 if (! xftface_info)
509 return -1;
510 xftfont_get_colors (f, face, face->gc, NULL,
511 &xftface_info->xft_fg, &xftface_info->xft_bg);
512 face->extra = xftface_info;
513 return 0;
516 static void
517 xftfont_done_face (f, face)
518 FRAME_PTR f;
519 struct face *face;
521 struct xftface_info *xftface_info;
523 #if 0
524 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
525 if (face != face->ascii_face
526 || ! face->extra)
527 return;
528 #endif
530 xftface_info = (struct xftface_info *) face->extra;
531 if (xftface_info)
533 free (xftface_info);
534 face->extra = NULL;
538 extern Lisp_Object Qja, Qko;
540 static int
541 xftfont_has_char (font, c)
542 Lisp_Object font;
543 int c;
545 struct xftfont_info *xftfont_info;
546 struct charset *cs = NULL;
548 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
549 && charset_jisx0208 >= 0)
550 cs = CHARSET_FROM_ID (charset_jisx0208);
551 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
552 && charset_ksc5601 >= 0)
553 cs = CHARSET_FROM_ID (charset_ksc5601);
554 if (cs)
555 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
557 if (FONT_ENTITY_P (font))
558 return ftfont_driver.has_char (font, c);
559 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
560 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
561 (FcChar32) c) == FcTrue);
564 static unsigned
565 xftfont_encode_char (font, c)
566 struct font *font;
567 int c;
569 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
570 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
571 (FcChar32) c);
573 return (code ? code : FONT_INVALID_CODE);
576 static int
577 xftfont_text_extents (font, code, nglyphs, metrics)
578 struct font *font;
579 unsigned *code;
580 int nglyphs;
581 struct font_metrics *metrics;
583 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
584 XGlyphInfo extents;
586 BLOCK_INPUT;
587 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
588 &extents);
589 UNBLOCK_INPUT;
590 if (metrics)
592 metrics->lbearing = - extents.x;
593 metrics->rbearing = - extents.x + extents.width;
594 metrics->width = extents.xOff;
595 metrics->ascent = extents.y;
596 metrics->descent = extents.height - extents.y;
598 return extents.xOff;
601 static XftDraw *
602 xftfont_get_xft_draw (f)
603 FRAME_PTR f;
605 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
607 if (! xft_draw)
609 BLOCK_INPUT;
610 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
611 FRAME_X_WINDOW (f),
612 FRAME_X_VISUAL (f),
613 FRAME_X_COLORMAP (f));
614 UNBLOCK_INPUT;
615 if (! xft_draw)
616 abort ();
617 font_put_frame_data (f, &xftfont_driver, xft_draw);
619 return xft_draw;
622 static int
623 xftfont_draw (s, from, to, x, y, with_background)
624 struct glyph_string *s;
625 int from, to, x, y, with_background;
627 FRAME_PTR f = s->f;
628 struct face *face = s->face;
629 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
630 struct xftface_info *xftface_info = NULL;
631 XftDraw *xft_draw = xftfont_get_xft_draw (f);
632 FT_UInt *code;
633 XftColor fg, bg;
634 int len = to - from;
635 int i;
637 if (s->font == face->font)
638 xftface_info = (struct xftface_info *) face->extra;
639 xftfont_get_colors (f, face, s->gc, xftface_info,
640 &fg, with_background ? &bg : NULL);
641 BLOCK_INPUT;
642 if (s->num_clips > 0)
643 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
644 else
645 XftDrawSetClip (xft_draw, NULL);
647 if (with_background)
648 XftDrawRect (xft_draw, &bg,
649 x, y - face->font->ascent, s->width, face->font->height);
650 code = alloca (sizeof (FT_UInt) * len);
651 for (i = 0; i < len; i++)
652 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
653 | XCHAR2B_BYTE2 (s->char2b + from + i));
655 if (s->padding_p)
656 for (i = 0; i < len; i++)
657 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
658 x + i, y, code + i, 1);
659 else
660 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
661 x, y, code, len);
662 UNBLOCK_INPUT;
664 return len;
667 static int
668 xftfont_end_for_frame (f)
669 FRAME_PTR f;
671 XftDraw *xft_draw;
673 /* Don't do anything if display is dead */
674 if (FRAME_X_DISPLAY (f) == NULL) return 0;
676 xft_draw = font_get_frame_data (f, &xftfont_driver);
678 if (xft_draw)
680 BLOCK_INPUT;
681 XftDrawDestroy (xft_draw);
682 UNBLOCK_INPUT;
683 font_put_frame_data (f, &xftfont_driver, NULL);
685 return 0;
688 void
689 syms_of_xftfont ()
691 DEFSYM (Qxft, "xft");
692 DEFSYM (QChinting, ":hinting");
693 DEFSYM (QCautohint, ":autohint");
694 DEFSYM (QChintstyle, ":hintstyle");
695 DEFSYM (QCrgba, ":rgba");
696 DEFSYM (QCembolden, ":embolden");
698 xftfont_driver = ftfont_driver;
699 xftfont_driver.type = Qxft;
700 xftfont_driver.get_cache = xfont_driver.get_cache;
701 xftfont_driver.list = xftfont_list;
702 xftfont_driver.match = xftfont_match;
703 xftfont_driver.open = xftfont_open;
704 xftfont_driver.close = xftfont_close;
705 xftfont_driver.prepare_face = xftfont_prepare_face;
706 xftfont_driver.done_face = xftfont_done_face;
707 xftfont_driver.has_char = xftfont_has_char;
708 xftfont_driver.encode_char = xftfont_encode_char;
709 xftfont_driver.text_extents = xftfont_text_extents;
710 xftfont_driver.draw = xftfont_draw;
711 xftfont_driver.end_for_frame = xftfont_end_for_frame;
713 register_font_driver (&xftfont_driver, NULL);
716 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
717 (do not change this comment) */