Fix problems caught with --enable-gcc-warnings
[emacs.git] / src / xftfont.c
blob851edb69fa04661def775a57b31b49266a44c30b
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2015 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. */
42 /* The actual structure for Xft font that can be cast to struct
43 font. */
45 struct xftfont_info
47 struct font font;
48 /* The following five members must be here in this order to be
49 compatible with struct ftfont_info (in ftfont.c). */
50 #ifdef HAVE_LIBOTF
51 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
52 OTF *otf;
53 #endif /* HAVE_LIBOTF */
54 FT_Size ft_size;
55 int index;
56 FT_Matrix matrix;
57 Display *display;
58 XftFont *xftfont;
59 unsigned x_display_id;
62 /* Structure pointed by (struct face *)->extra */
64 struct xftface_info
66 XftColor xft_fg; /* color for face->foreground */
67 XftColor xft_bg; /* color for face->background */
70 /* Setup foreground and background colors of GC into FG and BG. If
71 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
72 may be NULL. */
74 static void
75 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
76 struct xftface_info *xftface_info,
77 XftColor *fg, XftColor *bg)
79 if (xftface_info && face->gc == gc)
81 *fg = xftface_info->xft_fg;
82 if (bg)
83 *bg = xftface_info->xft_bg;
85 else
87 XGCValues xgcv;
88 bool fg_done = false, bg_done = false;
90 block_input ();
91 XGetGCValues (FRAME_X_DISPLAY (f), gc,
92 GCForeground | GCBackground, &xgcv);
93 if (xftface_info)
95 if (xgcv.foreground == face->foreground)
96 *fg = xftface_info->xft_fg, fg_done = true;
97 else if (xgcv.foreground == face->background)
98 *fg = xftface_info->xft_bg, fg_done = true;
99 if (! bg)
100 bg_done = true;
101 else if (xgcv.background == face->background)
102 *bg = xftface_info->xft_bg, bg_done = true;
103 else if (xgcv.background == face->foreground)
104 *bg = xftface_info->xft_fg, bg_done = true;
107 if (! (fg_done & bg_done))
109 XColor colors[2];
111 colors[0].pixel = fg->pixel = xgcv.foreground;
112 if (bg)
113 colors[1].pixel = bg->pixel = xgcv.background;
114 x_query_colors (f, colors, bg ? 2 : 1);
115 fg->color.alpha = 0xFFFF;
116 fg->color.red = colors[0].red;
117 fg->color.green = colors[0].green;
118 fg->color.blue = colors[0].blue;
119 if (bg)
121 bg->color.alpha = 0xFFFF;
122 bg->color.red = colors[1].red;
123 bg->color.green = colors[1].green;
124 bg->color.blue = colors[1].blue;
127 unblock_input ();
132 struct font_driver xftfont_driver;
134 static Lisp_Object
135 xftfont_list (struct frame *f, Lisp_Object spec)
137 Lisp_Object list = ftfont_driver.list (f, spec), tail;
139 for (tail = list; CONSP (tail); tail = XCDR (tail))
140 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
141 return list;
144 static Lisp_Object
145 xftfont_match (struct frame *f, Lisp_Object spec)
147 Lisp_Object entity = ftfont_driver.match (f, spec);
149 if (! NILP (entity))
150 ASET (entity, FONT_TYPE_INDEX, Qxft);
151 return entity;
154 static FcChar8 ascii_printable[95];
156 static void
157 xftfont_fix_match (FcPattern *pat, FcPattern *match)
159 /* These values are not used for matching (except antialias), but for
160 rendering, so make sure they are carried over to the match.
161 We also put antialias here because most fonts are antialiased, so
162 the match will have antialias true. */
164 FcBool b = FcTrue;
165 int i;
166 double dpi;
168 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
169 if (! b)
171 FcPatternDel (match, FC_ANTIALIAS);
172 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
174 FcPatternGetBool (pat, FC_HINTING, 0, &b);
175 if (! b)
177 FcPatternDel (match, FC_HINTING);
178 FcPatternAddBool (match, FC_HINTING, FcFalse);
180 #ifndef FC_HINT_STYLE
181 # define FC_HINT_STYLE "hintstyle"
182 #endif
183 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
185 FcPatternDel (match, FC_HINT_STYLE);
186 FcPatternAddInteger (match, FC_HINT_STYLE, i);
188 #ifndef FC_LCD_FILTER
189 /* Older fontconfig versions don't have FC_LCD_FILTER. */
190 #define FC_LCD_FILTER "lcdfilter"
191 #endif
192 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
194 FcPatternDel (match, FC_LCD_FILTER);
195 FcPatternAddInteger (match, FC_LCD_FILTER, i);
197 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
199 FcPatternDel (match, FC_RGBA);
200 FcPatternAddInteger (match, FC_RGBA, i);
202 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
204 FcPatternDel (match, FC_DPI);
205 FcPatternAddDouble (match, FC_DPI, dpi);
209 static void
210 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
212 Lisp_Object tail;
213 int ival;
215 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
217 Lisp_Object key = XCAR (XCAR (tail));
218 Lisp_Object val = XCDR (XCAR (tail));
220 if (EQ (key, QCantialias))
221 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
222 else if (EQ (key, QChinting))
223 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
224 else if (EQ (key, QCautohint))
225 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
226 else if (EQ (key, QChintstyle))
228 if (INTEGERP (val))
229 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
230 else if (SYMBOLP (val)
231 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
232 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
234 else if (EQ (key, QCrgba))
236 if (INTEGERP (val))
237 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
238 else if (SYMBOLP (val)
239 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
240 FcPatternAddInteger (pat, FC_RGBA, ival);
242 else if (EQ (key, QClcdfilter))
244 if (INTEGERP (val))
245 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
246 else if (SYMBOLP (val)
247 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
248 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
250 #ifdef FC_EMBOLDEN
251 else if (EQ (key, QCembolden))
252 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
253 #endif
257 static Lisp_Object
258 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
260 FcResult result;
261 Display *display = FRAME_X_DISPLAY (f);
262 Lisp_Object val, filename, idx, font_object;
263 FcPattern *pat = NULL, *match;
264 struct xftfont_info *xftfont_info = NULL;
265 struct font *font;
266 double size = 0;
267 XftFont *xftfont = NULL;
268 int spacing;
269 int i;
270 XGlyphInfo extents;
271 FT_Face ft_face;
272 FcMatrix *matrix;
274 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
275 if (! CONSP (val))
276 return Qnil;
277 val = XCDR (val);
278 filename = XCAR (val);
279 idx = XCDR (val);
280 size = XINT (AREF (entity, FONT_SIZE_INDEX));
281 if (size == 0)
282 size = pixel_size;
283 pat = FcPatternCreate ();
284 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
285 i = FONT_SLANT_NUMERIC (entity) - 100;
286 if (i < 0) i = 0;
287 FcPatternAddInteger (pat, FC_SLANT, i);
288 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
289 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
290 val = AREF (entity, FONT_FAMILY_INDEX);
291 if (! NILP (val))
292 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
293 val = AREF (entity, FONT_FOUNDRY_INDEX);
294 if (! NILP (val))
295 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
296 val = AREF (entity, FONT_SPACING_INDEX);
297 if (! NILP (val))
298 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
299 val = AREF (entity, FONT_DPI_INDEX);
300 if (! NILP (val))
302 double dbl = XINT (val);
304 FcPatternAddDouble (pat, FC_DPI, dbl);
306 val = AREF (entity, FONT_AVGWIDTH_INDEX);
307 if (INTEGERP (val) && XINT (val) == 0)
308 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
309 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
310 over 10x20-ISO8859-1.pcf.gz). */
311 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
313 xftfont_add_rendering_parameters (pat, entity);
315 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
316 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
319 block_input ();
321 /* Substitute in values from X resources and XftDefaultSet. */
322 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
323 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
324 xftfont_fix_match (pat, match);
326 FcPatternDestroy (pat);
327 xftfont = XftFontOpenPattern (display, match);
328 if (!xftfont)
330 unblock_input ();
331 XftPatternDestroy (match);
332 return Qnil;
334 ft_face = XftLockFace (xftfont);
335 unblock_input ();
337 /* We should not destroy PAT here because it is kept in XFTFONT and
338 destroyed automatically when XFTFONT is closed. */
339 font_object = font_build_object (VECSIZE (struct xftfont_info),
340 Qxft, entity, size);
341 ASET (font_object, FONT_FILE_INDEX, filename);
342 font = XFONT_OBJECT (font_object);
343 font->pixel_size = size;
344 font->driver = &xftfont_driver;
345 font->encoding_charset = font->repertory_charset = -1;
347 xftfont_info = (struct xftfont_info *) font;
348 xftfont_info->display = display;
349 xftfont_info->xftfont = xftfont;
350 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
351 /* This means that there's no need of transformation. */
352 xftfont_info->matrix.xx = 0;
353 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
354 == FcResultMatch)
356 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
357 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
358 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
359 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
361 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
362 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
363 else
364 spacing = FC_PROPORTIONAL;
365 if (! ascii_printable[0])
367 int ch;
368 for (ch = 0; ch < 95; ch++)
369 ascii_printable[ch] = ' ' + ch;
371 block_input ();
373 /* Unfortunately Xft doesn't provide a way to get minimum char
374 width. So, we set min_width to space_width. */
376 if (spacing != FC_PROPORTIONAL
377 #ifdef FC_DUAL
378 && spacing != FC_DUAL
379 #endif /* FC_DUAL */
382 font->min_width = font->max_width = font->average_width
383 = font->space_width = xftfont->max_advance_width;
384 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
386 else
388 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
389 font->min_width = font->max_width = font->space_width
390 = extents.xOff;
391 if (font->space_width <= 0)
392 /* dirty workaround */
393 font->space_width = pixel_size;
394 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
395 font->average_width = (font->space_width + extents.xOff) / 95;
397 unblock_input ();
399 font->ascent = xftfont->ascent;
400 font->descent = xftfont->descent;
401 if (pixel_size >= 5)
403 /* The above condition is a dirty workaround because
404 XftTextExtents8 behaves strangely for some fonts
405 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
406 if (font->ascent < extents.y)
407 font->ascent = extents.y;
408 if (font->descent < extents.height - extents.y)
409 font->descent = extents.height - extents.y;
411 font->height = font->ascent + font->descent;
413 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
415 int upEM = ft_face->units_per_EM;
417 font->underline_position = -ft_face->underline_position * size / upEM;
418 font->underline_thickness = ft_face->underline_thickness * size / upEM;
419 if (font->underline_thickness > 2)
420 font->underline_position -= font->underline_thickness / 2;
422 else
424 font->underline_position = -1;
425 font->underline_thickness = 0;
427 #ifdef HAVE_LIBOTF
428 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
429 xftfont_info->otf = NULL;
430 #endif /* HAVE_LIBOTF */
431 xftfont_info->ft_size = ft_face->size;
433 font->baseline_offset = 0;
434 font->relative_compose = 0;
435 font->default_ascent = 0;
436 font->vertical_centering = false;
437 #ifdef FT_BDF_H
438 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
440 BDF_PropertyRec rec;
442 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
443 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
444 font->baseline_offset = rec.u.integer;
445 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
446 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
447 font->relative_compose = rec.u.integer;
448 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
449 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
450 font->default_ascent = rec.u.integer;
452 #endif
454 return font_object;
457 static void
458 xftfont_close (struct font *font)
460 struct x_display_info *xdi;
461 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
463 #ifdef HAVE_LIBOTF
464 if (xftfont_info->otf)
466 OTF_close (xftfont_info->otf);
467 xftfont_info->otf = NULL;
469 #endif
471 /* See comment in xfont_close. */
472 if (xftfont_info->xftfont
473 && ((xdi = x_display_info_for_display (xftfont_info->display))
474 && xftfont_info->x_display_id == xdi->x_id))
476 block_input ();
477 XftUnlockFace (xftfont_info->xftfont);
478 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
479 unblock_input ();
480 xftfont_info->xftfont = NULL;
484 static void
485 xftfont_prepare_face (struct frame *f, struct face *face)
487 struct xftface_info *xftface_info;
489 #if false
490 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
491 if (face != face->ascii_face)
493 face->extra = face->ascii_face->extra;
494 return;
496 #endif
498 xftface_info = xmalloc (sizeof *xftface_info);
499 xftfont_get_colors (f, face, face->gc, NULL,
500 &xftface_info->xft_fg, &xftface_info->xft_bg);
501 face->extra = xftface_info;
504 static void
505 xftfont_done_face (struct frame *f, struct face *face)
507 struct xftface_info *xftface_info;
509 #if false
510 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
511 if (face != face->ascii_face
512 || ! face->extra)
513 return;
514 #endif
516 xftface_info = (struct xftface_info *) face->extra;
517 if (xftface_info)
519 xfree (xftface_info);
520 face->extra = NULL;
524 static int
525 xftfont_has_char (Lisp_Object font, int c)
527 struct xftfont_info *xftfont_info;
528 struct charset *cs = NULL;
530 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
531 && charset_jisx0208 >= 0)
532 cs = CHARSET_FROM_ID (charset_jisx0208);
533 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
534 && charset_ksc5601 >= 0)
535 cs = CHARSET_FROM_ID (charset_ksc5601);
536 if (cs)
537 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
539 if (FONT_ENTITY_P (font))
540 return ftfont_driver.has_char (font, c);
541 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
542 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
543 (FcChar32) c) == FcTrue);
546 static unsigned
547 xftfont_encode_char (struct font *font, int c)
549 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
550 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
551 (FcChar32) c);
553 return (code ? code : FONT_INVALID_CODE);
556 static void
557 xftfont_text_extents (struct font *font, unsigned int *code,
558 int nglyphs, struct font_metrics *metrics)
560 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
561 XGlyphInfo extents;
563 block_input ();
564 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
565 &extents);
566 unblock_input ();
568 metrics->lbearing = - extents.x;
569 metrics->rbearing = - extents.x + extents.width;
570 metrics->width = extents.xOff;
571 metrics->ascent = extents.y;
572 metrics->descent = extents.height - extents.y;
575 static XftDraw *
576 xftfont_get_xft_draw (struct frame *f)
578 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
580 if (! xft_draw)
582 block_input ();
583 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
584 FRAME_X_WINDOW (f),
585 FRAME_X_VISUAL (f),
586 FRAME_X_COLORMAP (f));
587 unblock_input ();
588 eassert (xft_draw != NULL);
589 font_put_frame_data (f, Qxft, xft_draw);
591 return xft_draw;
594 static int
595 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
596 bool with_background)
598 struct frame *f = s->f;
599 struct face *face = s->face;
600 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
601 struct xftface_info *xftface_info = NULL;
602 XftDraw *xft_draw = xftfont_get_xft_draw (f);
603 FT_UInt *code;
604 XftColor fg, bg;
605 int len = to - from;
606 int i;
608 if (s->font == face->font)
609 xftface_info = (struct xftface_info *) face->extra;
610 xftfont_get_colors (f, face, s->gc, xftface_info,
611 &fg, with_background ? &bg : NULL);
612 block_input ();
613 if (s->num_clips > 0)
614 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
615 else
616 XftDrawSetClip (xft_draw, NULL);
618 if (with_background)
620 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
622 /* Font's global height and ascent values might be
623 preposterously large for some fonts. We fix here the case
624 when those fonts are used for display of glyphless
625 characters, because drawing background with font dimensions
626 in those cases makes the display illegible. There's only one
627 more call to the draw method with with_background set to
628 true, and that's in x_draw_glyph_string_foreground, when
629 drawing the cursor, where we have no such heuristics
630 available. FIXME. */
631 if (s->first_glyph->type == GLYPHLESS_GLYPH
632 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
633 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
634 height = ascent =
635 s->first_glyph->slice.glyphless.lower_yoff
636 - s->first_glyph->slice.glyphless.upper_yoff;
637 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
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));
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);
651 unblock_input ();
653 return len;
656 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
657 static Lisp_Object
658 xftfont_shape (Lisp_Object lgstring)
660 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
661 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
662 FT_Face ft_face;
663 Lisp_Object val;
665 ft_face = XftLockFace (xftfont_info->xftfont);
666 xftfont_info->ft_size = ft_face->size;
667 val = ftfont_driver.shape (lgstring);
668 XftUnlockFace (xftfont_info->xftfont);
669 return val;
671 #endif
673 static int
674 xftfont_end_for_frame (struct frame *f)
676 XftDraw *xft_draw;
678 /* Don't do anything if display is dead */
679 if (FRAME_X_DISPLAY (f) == NULL) return 0;
681 xft_draw = font_get_frame_data (f, Qxft);
683 if (xft_draw)
685 block_input ();
686 XftDrawDestroy (xft_draw);
687 unblock_input ();
688 font_put_frame_data (f, Qxft, NULL);
690 return 0;
693 static bool
694 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
695 Lisp_Object entity)
697 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
698 FcPattern *oldpat = info->xftfont->pattern;
699 Display *display = FRAME_X_DISPLAY (f);
700 FcPattern *pat = FcPatternCreate ();
701 FcBool b1, b2;
702 bool ok = false;
703 int i1, i2, r1, r2;
705 xftfont_add_rendering_parameters (pat, entity);
706 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
708 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
709 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
710 if (r1 != r2 || b1 != b2) goto out;
711 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
712 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
713 if (r1 != r2 || b1 != b2) goto out;
714 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
715 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
716 if (r1 != r2 || b1 != b2) goto out;
717 #ifdef FC_EMBOLDEN
718 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
719 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
720 if (r1 != r2 || b1 != b2) goto out;
721 #endif
722 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
723 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
724 if (r1 != r2 || i1 != i2) goto out;
725 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
726 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
727 if (r1 != r2 || i1 != i2) goto out;
728 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
729 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
730 if (r1 != r2 || i1 != i2) goto out;
732 ok = true;
733 out:
734 FcPatternDestroy (pat);
735 return ok;
738 void
739 syms_of_xftfont (void)
741 DEFSYM (Qxft, "xft");
742 DEFSYM (QChinting, ":hinting");
743 DEFSYM (QCautohint, ":autohint");
744 DEFSYM (QChintstyle, ":hintstyle");
745 DEFSYM (QCrgba, ":rgba");
746 DEFSYM (QCembolden, ":embolden");
747 DEFSYM (QClcdfilter, ":lcdfilter");
749 ascii_printable[0] = 0;
751 xftfont_driver = ftfont_driver;
752 xftfont_driver.type = Qxft;
753 xftfont_driver.get_cache = xfont_driver.get_cache;
754 xftfont_driver.list = xftfont_list;
755 xftfont_driver.match = xftfont_match;
756 xftfont_driver.open = xftfont_open;
757 xftfont_driver.close = xftfont_close;
758 xftfont_driver.prepare_face = xftfont_prepare_face;
759 xftfont_driver.done_face = xftfont_done_face;
760 xftfont_driver.has_char = xftfont_has_char;
761 xftfont_driver.encode_char = xftfont_encode_char;
762 xftfont_driver.text_extents = xftfont_text_extents;
763 xftfont_driver.draw = xftfont_draw;
764 xftfont_driver.end_for_frame = xftfont_end_for_frame;
765 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
766 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
767 xftfont_driver.shape = xftfont_shape;
768 #endif
770 register_font_driver (&xftfont_driver, NULL);