Merge from emacs-24; up to 2014-06-22T05:00:14Z!dmantipov@yandex.ru
[emacs.git] / src / xftfont.c
blob9726a3b991199317bfba7c148756ecfb4b3471ea
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
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 <X11/Xlib.h>
25 #include <X11/Xft/Xft.h>
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"
34 #include "composite.h"
35 #include "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
39 /* Xft font driver. */
41 Lisp_Object Qxft;
42 static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
43 QClcdfilter;
45 /* The actual structure for Xft font that can be cast to struct
46 font. */
48 struct xftfont_info
50 struct font font;
51 /* The following five members must be here in this order to be
52 compatible with struct ftfont_info (in ftfont.c). */
53 #ifdef HAVE_LIBOTF
54 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
55 OTF *otf;
56 #endif /* HAVE_LIBOTF */
57 FT_Size ft_size;
58 int index;
59 FT_Matrix matrix;
60 Display *display;
61 XftFont *xftfont;
62 unsigned x_display_id;
65 /* Structure pointed by (struct face *)->extra */
67 struct xftface_info
69 XftColor xft_fg; /* color for face->foreground */
70 XftColor xft_bg; /* color for face->background */
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. */
77 static void
78 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
79 struct xftface_info *xftface_info,
80 XftColor *fg, XftColor *bg)
82 if (xftface_info && face->gc == gc)
84 *fg = xftface_info->xft_fg;
85 if (bg)
86 *bg = xftface_info->xft_bg;
88 else
90 XGCValues xgcv;
91 bool fg_done = 0, bg_done = 0;
93 block_input ();
94 XGetGCValues (FRAME_X_DISPLAY (f), gc,
95 GCForeground | GCBackground, &xgcv);
96 if (xftface_info)
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;
110 if (! (fg_done & bg_done))
112 XColor colors[2];
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)
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;
131 unblock_input ();
136 struct font_driver xftfont_driver;
138 static Lisp_Object
139 xftfont_list (struct frame *f, Lisp_Object spec)
141 Lisp_Object list = ftfont_driver.list (f, spec), tail;
143 for (tail = list; CONSP (tail); tail = XCDR (tail))
144 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
145 return list;
148 static Lisp_Object
149 xftfont_match (struct frame *f, Lisp_Object spec)
151 Lisp_Object entity = ftfont_driver.match (f, spec);
153 if (! NILP (entity))
154 ASET (entity, FONT_TYPE_INDEX, Qxft);
155 return entity;
158 static FcChar8 ascii_printable[95];
160 static void
161 xftfont_fix_match (FcPattern *pat, FcPattern *match)
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. */
168 FcBool b = FcTrue;
169 int i;
170 double dpi;
172 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
173 if (! b)
175 FcPatternDel (match, FC_ANTIALIAS);
176 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
178 FcPatternGetBool (pat, FC_HINTING, 0, &b);
179 if (! b)
181 FcPatternDel (match, FC_HINTING);
182 FcPatternAddBool (match, FC_HINTING, FcFalse);
184 #ifndef FC_HINT_STYLE
185 # define FC_HINT_STYLE "hintstyle"
186 #endif
187 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
189 FcPatternDel (match, FC_HINT_STYLE);
190 FcPatternAddInteger (match, FC_HINT_STYLE, i);
192 #ifndef FC_LCD_FILTER
193 /* Older fontconfig versions don't have FC_LCD_FILTER. */
194 #define FC_LCD_FILTER "lcdfilter"
195 #endif
196 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
198 FcPatternDel (match, FC_LCD_FILTER);
199 FcPatternAddInteger (match, FC_LCD_FILTER, i);
201 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
203 FcPatternDel (match, FC_RGBA);
204 FcPatternAddInteger (match, FC_RGBA, i);
206 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
208 FcPatternDel (match, FC_DPI);
209 FcPatternAddDouble (match, FC_DPI, dpi);
213 static void
214 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
216 Lisp_Object tail;
217 int ival;
219 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
221 Lisp_Object key = XCAR (XCAR (tail));
222 Lisp_Object val = XCDR (XCAR (tail));
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))
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);
238 else if (EQ (key, QCrgba))
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);
246 else if (EQ (key, QClcdfilter))
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);
254 #ifdef FC_EMBOLDEN
255 else if (EQ (key, QCembolden))
256 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
257 #endif
261 static Lisp_Object
262 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
264 FcResult result;
265 Display *display = FRAME_X_DISPLAY (f);
266 Lisp_Object val, filename, idx, font_object;
267 FcPattern *pat = NULL, *match;
268 struct xftfont_info *xftfont_info = NULL;
269 struct font *font;
270 double size = 0;
271 XftFont *xftfont = NULL;
272 int spacing;
273 int i;
274 XGlyphInfo extents;
275 FT_Face ft_face;
276 FcMatrix *matrix;
278 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
279 if (! CONSP (val))
280 return Qnil;
281 val = XCDR (val);
282 filename = XCAR (val);
283 idx = XCDR (val);
284 size = XINT (AREF (entity, FONT_SIZE_INDEX));
285 if (size == 0)
286 size = pixel_size;
287 pat = FcPatternCreate ();
288 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
289 i = FONT_SLANT_NUMERIC (entity) - 100;
290 if (i < 0) i = 0;
291 FcPatternAddInteger (pat, FC_SLANT, i);
292 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
293 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
294 val = AREF (entity, FONT_FAMILY_INDEX);
295 if (! NILP (val))
296 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
297 val = AREF (entity, FONT_FOUNDRY_INDEX);
298 if (! NILP (val))
299 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
300 val = AREF (entity, FONT_SPACING_INDEX);
301 if (! NILP (val))
302 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
303 val = AREF (entity, FONT_DPI_INDEX);
304 if (! NILP (val))
306 double dbl = XINT (val);
308 FcPatternAddDouble (pat, FC_DPI, dbl);
310 val = AREF (entity, FONT_AVGWIDTH_INDEX);
311 if (INTEGERP (val) && XINT (val) == 0)
312 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
313 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
314 over 10x20-ISO8859-1.pcf.gz). */
315 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
317 xftfont_add_rendering_parameters (pat, entity);
319 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
320 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
323 block_input ();
325 /* Substitute in values from X resources and XftDefaultSet. */
326 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
327 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
328 xftfont_fix_match (pat, match);
330 FcPatternDestroy (pat);
331 xftfont = XftFontOpenPattern (display, match);
332 if (!xftfont)
334 unblock_input ();
335 XftPatternDestroy (match);
336 return Qnil;
338 ft_face = XftLockFace (xftfont);
339 unblock_input ();
341 /* We should not destroy PAT here because it is kept in XFTFONT and
342 destroyed automatically when XFTFONT is closed. */
343 font_object = font_build_object (VECSIZE (struct xftfont_info),
344 Qxft, entity, size);
345 ASET (font_object, FONT_FILE_INDEX, filename);
346 font = XFONT_OBJECT (font_object);
347 font->pixel_size = size;
348 font->driver = &xftfont_driver;
349 font->encoding_charset = font->repertory_charset = -1;
351 xftfont_info = (struct xftfont_info *) font;
352 xftfont_info->display = display;
353 xftfont_info->xftfont = xftfont;
354 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
355 /* This means that there's no need of transformation. */
356 xftfont_info->matrix.xx = 0;
357 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
358 == FcResultMatch)
360 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
361 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
362 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
363 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
365 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
366 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
367 else
368 spacing = FC_PROPORTIONAL;
369 if (! ascii_printable[0])
371 int ch;
372 for (ch = 0; ch < 95; ch++)
373 ascii_printable[ch] = ' ' + ch;
375 block_input ();
377 /* Unfortunately Xft doesn't provide a way to get minimum char
378 width. So, we set min_width to space_width. */
380 if (spacing != FC_PROPORTIONAL
381 #ifdef FC_DUAL
382 && spacing != FC_DUAL
383 #endif /* FC_DUAL */
386 font->min_width = font->max_width = font->average_width
387 = font->space_width = xftfont->max_advance_width;
388 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
390 else
392 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
393 font->min_width = font->max_width = font->space_width
394 = extents.xOff;
395 if (font->space_width <= 0)
396 /* dirty workaround */
397 font->space_width = pixel_size;
398 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
399 font->average_width = (font->space_width + extents.xOff) / 95;
401 unblock_input ();
403 font->ascent = xftfont->ascent;
404 font->descent = xftfont->descent;
405 if (pixel_size >= 5)
407 /* The above condition is a dirty workaround because
408 XftTextExtents8 behaves strangely for some fonts
409 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
410 if (font->ascent < extents.y)
411 font->ascent = extents.y;
412 if (font->descent < extents.height - extents.y)
413 font->descent = extents.height - extents.y;
415 font->height = font->ascent + font->descent;
417 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
419 int upEM = ft_face->units_per_EM;
421 font->underline_position = -ft_face->underline_position * size / upEM;
422 font->underline_thickness = ft_face->underline_thickness * size / upEM;
423 if (font->underline_thickness > 2)
424 font->underline_position -= font->underline_thickness / 2;
426 else
428 font->underline_position = -1;
429 font->underline_thickness = 0;
431 #ifdef HAVE_LIBOTF
432 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
433 xftfont_info->otf = NULL;
434 #endif /* HAVE_LIBOTF */
435 xftfont_info->ft_size = ft_face->size;
437 font->baseline_offset = 0;
438 font->relative_compose = 0;
439 font->default_ascent = 0;
440 font->vertical_centering = 0;
441 #ifdef FT_BDF_H
442 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
444 BDF_PropertyRec rec;
446 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
447 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
448 font->baseline_offset = rec.u.integer;
449 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
450 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
451 font->relative_compose = rec.u.integer;
452 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
453 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
454 font->default_ascent = rec.u.integer;
456 #endif
458 return font_object;
461 static void
462 xftfont_close (struct font *font)
464 struct x_display_info *xdi;
465 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
467 #ifdef HAVE_LIBOTF
468 if (xftfont_info->otf)
470 OTF_close (xftfont_info->otf);
471 xftfont_info->otf = NULL;
473 #endif
475 /* See comment in xfont_close. */
476 if (xftfont_info->xftfont
477 && ((xdi = x_display_info_for_display (xftfont_info->display))
478 && xftfont_info->x_display_id == xdi->x_id))
480 block_input ();
481 XftUnlockFace (xftfont_info->xftfont);
482 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
483 unblock_input ();
484 xftfont_info->xftfont = NULL;
488 static void
489 xftfont_prepare_face (struct frame *f, struct face *face)
491 struct xftface_info *xftface_info;
493 #if 0
494 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
495 if (face != face->ascii_face)
497 face->extra = face->ascii_face->extra;
498 return;
500 #endif
502 xftface_info = xmalloc (sizeof *xftface_info);
503 xftfont_get_colors (f, face, face->gc, NULL,
504 &xftface_info->xft_fg, &xftface_info->xft_bg);
505 face->extra = xftface_info;
508 static void
509 xftfont_done_face (struct frame *f, struct face *face)
511 struct xftface_info *xftface_info;
513 #if 0
514 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
515 if (face != face->ascii_face
516 || ! face->extra)
517 return;
518 #endif
520 xftface_info = (struct xftface_info *) face->extra;
521 if (xftface_info)
523 xfree (xftface_info);
524 face->extra = NULL;
528 static int
529 xftfont_has_char (Lisp_Object font, int c)
531 struct xftfont_info *xftfont_info;
532 struct charset *cs = NULL;
534 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
535 && charset_jisx0208 >= 0)
536 cs = CHARSET_FROM_ID (charset_jisx0208);
537 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
538 && charset_ksc5601 >= 0)
539 cs = CHARSET_FROM_ID (charset_ksc5601);
540 if (cs)
541 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
543 if (FONT_ENTITY_P (font))
544 return ftfont_driver.has_char (font, c);
545 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
546 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
547 (FcChar32) c) == FcTrue);
550 static unsigned
551 xftfont_encode_char (struct font *font, int c)
553 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
554 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
555 (FcChar32) c);
557 return (code ? code : FONT_INVALID_CODE);
560 static int
561 xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
563 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
564 XGlyphInfo extents;
566 block_input ();
567 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
568 &extents);
569 unblock_input ();
570 if (metrics)
572 metrics->lbearing = - extents.x;
573 metrics->rbearing = - extents.x + extents.width;
574 metrics->width = extents.xOff;
575 metrics->ascent = extents.y;
576 metrics->descent = extents.height - extents.y;
578 return extents.xOff;
581 static XftDraw *
582 xftfont_get_xft_draw (struct frame *f)
584 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
586 if (! xft_draw)
588 block_input ();
589 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
590 FRAME_X_WINDOW (f),
591 FRAME_X_VISUAL (f),
592 FRAME_X_COLORMAP (f));
593 unblock_input ();
594 eassert (xft_draw != NULL);
595 font_put_frame_data (f, Qxft, xft_draw);
597 return xft_draw;
600 static int
601 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
602 bool with_background)
604 struct frame *f = s->f;
605 struct face *face = s->face;
606 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
607 struct xftface_info *xftface_info = NULL;
608 XftDraw *xft_draw = xftfont_get_xft_draw (f);
609 FT_UInt *code;
610 XftColor fg, bg;
611 int len = to - from;
612 int i;
614 if (s->font == face->font)
615 xftface_info = (struct xftface_info *) face->extra;
616 xftfont_get_colors (f, face, s->gc, xftface_info,
617 &fg, with_background ? &bg : NULL);
618 block_input ();
619 if (s->num_clips > 0)
620 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
621 else
622 XftDrawSetClip (xft_draw, NULL);
624 if (with_background)
625 XftDrawRect (xft_draw, &bg,
626 x, y - s->font->ascent, s->width, s->font->height);
627 code = alloca (sizeof (FT_UInt) * len);
628 for (i = 0; i < len; i++)
629 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
630 | XCHAR2B_BYTE2 (s->char2b + from + i));
632 if (s->padding_p)
633 for (i = 0; i < len; i++)
634 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
635 x + i, y, code + i, 1);
636 else
637 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
638 x, y, code, len);
639 unblock_input ();
641 return len;
644 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
645 static Lisp_Object
646 xftfont_shape (Lisp_Object lgstring)
648 struct font *font;
649 struct xftfont_info *xftfont_info;
650 FT_Face ft_face;
651 Lisp_Object val;
653 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
654 xftfont_info = (struct xftfont_info *) font;
655 ft_face = XftLockFace (xftfont_info->xftfont);
656 xftfont_info->ft_size = ft_face->size;
657 val = ftfont_driver.shape (lgstring);
658 XftUnlockFace (xftfont_info->xftfont);
659 return val;
661 #endif
663 static int
664 xftfont_end_for_frame (struct frame *f)
666 XftDraw *xft_draw;
668 /* Don't do anything if display is dead */
669 if (FRAME_X_DISPLAY (f) == NULL) return 0;
671 xft_draw = font_get_frame_data (f, Qxft);
673 if (xft_draw)
675 block_input ();
676 XftDrawDestroy (xft_draw);
677 unblock_input ();
678 font_put_frame_data (f, Qxft, NULL);
680 return 0;
683 static bool
684 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
685 Lisp_Object entity)
687 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
688 FcPattern *oldpat = info->xftfont->pattern;
689 Display *display = FRAME_X_DISPLAY (f);
690 FcPattern *pat = FcPatternCreate ();
691 FcBool b1, b2;
692 bool ok = 0;
693 int i1, i2, r1, r2;
695 xftfont_add_rendering_parameters (pat, entity);
696 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
698 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
699 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
700 if (r1 != r2 || b1 != b2) goto out;
701 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
702 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
703 if (r1 != r2 || b1 != b2) goto out;
704 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
705 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
706 if (r1 != r2 || b1 != b2) goto out;
707 #ifdef FC_EMBOLDEN
708 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
709 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
710 if (r1 != r2 || b1 != b2) goto out;
711 #endif
712 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
713 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
714 if (r1 != r2 || i1 != i2) goto out;
715 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
716 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
717 if (r1 != r2 || i1 != i2) goto out;
718 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
719 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
720 if (r1 != r2 || i1 != i2) goto out;
722 ok = 1;
723 out:
724 FcPatternDestroy (pat);
725 return ok;
728 void
729 syms_of_xftfont (void)
731 DEFSYM (Qxft, "xft");
732 DEFSYM (QChinting, ":hinting");
733 DEFSYM (QCautohint, ":autohint");
734 DEFSYM (QChintstyle, ":hintstyle");
735 DEFSYM (QCrgba, ":rgba");
736 DEFSYM (QCembolden, ":embolden");
737 DEFSYM (QClcdfilter, ":lcdfilter");
739 ascii_printable[0] = 0;
741 xftfont_driver = ftfont_driver;
742 xftfont_driver.type = Qxft;
743 xftfont_driver.get_cache = xfont_driver.get_cache;
744 xftfont_driver.list = xftfont_list;
745 xftfont_driver.match = xftfont_match;
746 xftfont_driver.open = xftfont_open;
747 xftfont_driver.close = xftfont_close;
748 xftfont_driver.prepare_face = xftfont_prepare_face;
749 xftfont_driver.done_face = xftfont_done_face;
750 xftfont_driver.has_char = xftfont_has_char;
751 xftfont_driver.encode_char = xftfont_encode_char;
752 xftfont_driver.text_extents = xftfont_text_extents;
753 xftfont_driver.draw = xftfont_draw;
754 xftfont_driver.end_for_frame = xftfont_end_for_frame;
755 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
756 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
757 xftfont_driver.shape = xftfont_shape;
758 #endif
760 register_font_driver (&xftfont_driver, NULL);