; ChangeLog.2: Fix author of last Tramp commit
[emacs.git] / src / xftfont.c
bloba1846e8d4619ac572d2d07b806f05dbfc5e43133
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 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
115 bg ? 2 : 1);
116 fg->color.alpha = 0xFFFF;
117 fg->color.red = colors[0].red;
118 fg->color.green = colors[0].green;
119 fg->color.blue = colors[0].blue;
120 if (bg)
122 bg->color.alpha = 0xFFFF;
123 bg->color.red = colors[1].red;
124 bg->color.green = colors[1].green;
125 bg->color.blue = colors[1].blue;
128 unblock_input ();
133 struct font_driver xftfont_driver;
135 static Lisp_Object
136 xftfont_list (struct frame *f, Lisp_Object spec)
138 Lisp_Object list = ftfont_driver.list (f, spec), tail;
140 for (tail = list; CONSP (tail); tail = XCDR (tail))
141 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
142 return list;
145 static Lisp_Object
146 xftfont_match (struct frame *f, Lisp_Object spec)
148 Lisp_Object entity = ftfont_driver.match (f, spec);
150 if (! NILP (entity))
151 ASET (entity, FONT_TYPE_INDEX, Qxft);
152 return entity;
155 static FcChar8 ascii_printable[95];
157 static void
158 xftfont_fix_match (FcPattern *pat, FcPattern *match)
160 /* These values are not used for matching (except antialias), but for
161 rendering, so make sure they are carried over to the match.
162 We also put antialias here because most fonts are antialiased, so
163 the match will have antialias true. */
165 FcBool b = FcTrue;
166 int i;
167 double dpi;
169 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
170 if (! b)
172 FcPatternDel (match, FC_ANTIALIAS);
173 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
175 FcPatternGetBool (pat, FC_HINTING, 0, &b);
176 if (! b)
178 FcPatternDel (match, FC_HINTING);
179 FcPatternAddBool (match, FC_HINTING, FcFalse);
181 #ifndef FC_HINT_STYLE
182 # define FC_HINT_STYLE "hintstyle"
183 #endif
184 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
186 FcPatternDel (match, FC_HINT_STYLE);
187 FcPatternAddInteger (match, FC_HINT_STYLE, i);
189 #ifndef FC_LCD_FILTER
190 /* Older fontconfig versions don't have FC_LCD_FILTER. */
191 #define FC_LCD_FILTER "lcdfilter"
192 #endif
193 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
195 FcPatternDel (match, FC_LCD_FILTER);
196 FcPatternAddInteger (match, FC_LCD_FILTER, i);
198 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
200 FcPatternDel (match, FC_RGBA);
201 FcPatternAddInteger (match, FC_RGBA, i);
203 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
205 FcPatternDel (match, FC_DPI);
206 FcPatternAddDouble (match, FC_DPI, dpi);
210 static void
211 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
213 Lisp_Object tail;
214 int ival;
216 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
218 Lisp_Object key = XCAR (XCAR (tail));
219 Lisp_Object val = XCDR (XCAR (tail));
221 if (EQ (key, QCantialias))
222 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
223 else if (EQ (key, QChinting))
224 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
225 else if (EQ (key, QCautohint))
226 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
227 else if (EQ (key, QChintstyle))
229 if (INTEGERP (val))
230 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
231 else if (SYMBOLP (val)
232 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
233 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
235 else if (EQ (key, QCrgba))
237 if (INTEGERP (val))
238 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
239 else if (SYMBOLP (val)
240 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
241 FcPatternAddInteger (pat, FC_RGBA, ival);
243 else if (EQ (key, QClcdfilter))
245 if (INTEGERP (val))
246 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
247 else if (SYMBOLP (val)
248 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
249 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
251 #ifdef FC_EMBOLDEN
252 else if (EQ (key, QCembolden))
253 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
254 #endif
258 static Lisp_Object
259 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
261 FcResult result;
262 Display *display = FRAME_X_DISPLAY (f);
263 Lisp_Object val, filename, idx, font_object;
264 FcPattern *pat = NULL, *match;
265 struct xftfont_info *xftfont_info = NULL;
266 struct font *font;
267 double size = 0;
268 XftFont *xftfont = NULL;
269 int spacing;
270 int i;
271 XGlyphInfo extents;
272 FT_Face ft_face;
273 FcMatrix *matrix;
275 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
276 if (! CONSP (val))
277 return Qnil;
278 val = XCDR (val);
279 filename = XCAR (val);
280 idx = XCDR (val);
281 size = XINT (AREF (entity, FONT_SIZE_INDEX));
282 if (size == 0)
283 size = pixel_size;
284 pat = FcPatternCreate ();
285 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
286 i = FONT_SLANT_NUMERIC (entity) - 100;
287 if (i < 0) i = 0;
288 FcPatternAddInteger (pat, FC_SLANT, i);
289 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
290 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
291 val = AREF (entity, FONT_FAMILY_INDEX);
292 if (! NILP (val))
293 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
294 val = AREF (entity, FONT_FOUNDRY_INDEX);
295 if (! NILP (val))
296 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
297 val = AREF (entity, FONT_SPACING_INDEX);
298 if (! NILP (val))
299 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
300 val = AREF (entity, FONT_DPI_INDEX);
301 if (! NILP (val))
303 double dbl = XINT (val);
305 FcPatternAddDouble (pat, FC_DPI, dbl);
307 val = AREF (entity, FONT_AVGWIDTH_INDEX);
308 if (INTEGERP (val) && XINT (val) == 0)
309 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
310 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
311 over 10x20-ISO8859-1.pcf.gz). */
312 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
314 xftfont_add_rendering_parameters (pat, entity);
316 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
317 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
320 block_input ();
322 /* Substitute in values from X resources and XftDefaultSet. */
323 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
324 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
325 xftfont_fix_match (pat, match);
327 FcPatternDestroy (pat);
328 xftfont = XftFontOpenPattern (display, match);
329 if (!xftfont)
331 unblock_input ();
332 XftPatternDestroy (match);
333 return Qnil;
335 ft_face = XftLockFace (xftfont);
336 unblock_input ();
338 /* We should not destroy PAT here because it is kept in XFTFONT and
339 destroyed automatically when XFTFONT is closed. */
340 font_object = font_build_object (VECSIZE (struct xftfont_info),
341 Qxft, entity, size);
342 ASET (font_object, FONT_FILE_INDEX, filename);
343 font = XFONT_OBJECT (font_object);
344 font->pixel_size = size;
345 font->driver = &xftfont_driver;
346 font->encoding_charset = font->repertory_charset = -1;
348 xftfont_info = (struct xftfont_info *) font;
349 xftfont_info->display = display;
350 xftfont_info->xftfont = xftfont;
351 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
352 /* This means that there's no need of transformation. */
353 xftfont_info->matrix.xx = 0;
354 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
355 == FcResultMatch)
357 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
358 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
359 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
360 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
362 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
363 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
364 else
365 spacing = FC_PROPORTIONAL;
366 if (! ascii_printable[0])
368 int ch;
369 for (ch = 0; ch < 95; ch++)
370 ascii_printable[ch] = ' ' + ch;
372 block_input ();
374 /* Unfortunately Xft doesn't provide a way to get minimum char
375 width. So, we set min_width to space_width. */
377 if (spacing != FC_PROPORTIONAL
378 #ifdef FC_DUAL
379 && spacing != FC_DUAL
380 #endif /* FC_DUAL */
383 font->min_width = font->max_width = font->average_width
384 = font->space_width = xftfont->max_advance_width;
385 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
387 else
389 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
390 font->min_width = font->max_width = font->space_width
391 = extents.xOff;
392 if (font->space_width <= 0)
393 /* dirty workaround */
394 font->space_width = pixel_size;
395 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
396 font->average_width = (font->space_width + extents.xOff) / 95;
398 unblock_input ();
400 font->ascent = xftfont->ascent;
401 font->descent = xftfont->descent;
402 if (pixel_size >= 5)
404 /* The above condition is a dirty workaround because
405 XftTextExtents8 behaves strangely for some fonts
406 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
407 if (font->ascent < extents.y)
408 font->ascent = extents.y;
409 if (font->descent < extents.height - extents.y)
410 font->descent = extents.height - extents.y;
412 font->height = font->ascent + font->descent;
414 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
416 int upEM = ft_face->units_per_EM;
418 font->underline_position = -ft_face->underline_position * size / upEM;
419 font->underline_thickness = ft_face->underline_thickness * size / upEM;
420 if (font->underline_thickness > 2)
421 font->underline_position -= font->underline_thickness / 2;
423 else
425 font->underline_position = -1;
426 font->underline_thickness = 0;
428 #ifdef HAVE_LIBOTF
429 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
430 xftfont_info->otf = NULL;
431 #endif /* HAVE_LIBOTF */
432 xftfont_info->ft_size = ft_face->size;
434 font->baseline_offset = 0;
435 font->relative_compose = 0;
436 font->default_ascent = 0;
437 font->vertical_centering = false;
438 #ifdef FT_BDF_H
439 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
441 BDF_PropertyRec rec;
443 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
444 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
445 font->baseline_offset = rec.u.integer;
446 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
447 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
448 font->relative_compose = rec.u.integer;
449 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
450 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
451 font->default_ascent = rec.u.integer;
453 #endif
455 return font_object;
458 static void
459 xftfont_close (struct font *font)
461 struct x_display_info *xdi;
462 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
464 #ifdef HAVE_LIBOTF
465 if (xftfont_info->otf)
467 OTF_close (xftfont_info->otf);
468 xftfont_info->otf = NULL;
470 #endif
472 /* See comment in xfont_close. */
473 if (xftfont_info->xftfont
474 && ((xdi = x_display_info_for_display (xftfont_info->display))
475 && xftfont_info->x_display_id == xdi->x_id))
477 block_input ();
478 XftUnlockFace (xftfont_info->xftfont);
479 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
480 unblock_input ();
481 xftfont_info->xftfont = NULL;
485 static void
486 xftfont_prepare_face (struct frame *f, struct face *face)
488 struct xftface_info *xftface_info;
490 #if false
491 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
492 if (face != face->ascii_face)
494 face->extra = face->ascii_face->extra;
495 return;
497 #endif
499 xftface_info = xmalloc (sizeof *xftface_info);
500 xftfont_get_colors (f, face, face->gc, NULL,
501 &xftface_info->xft_fg, &xftface_info->xft_bg);
502 face->extra = xftface_info;
505 static void
506 xftfont_done_face (struct frame *f, struct face *face)
508 struct xftface_info *xftface_info;
510 #if false
511 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
512 if (face != face->ascii_face
513 || ! face->extra)
514 return;
515 #endif
517 xftface_info = (struct xftface_info *) face->extra;
518 if (xftface_info)
520 xfree (xftface_info);
521 face->extra = NULL;
525 static int
526 xftfont_has_char (Lisp_Object font, int c)
528 struct xftfont_info *xftfont_info;
529 struct charset *cs = NULL;
531 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
532 && charset_jisx0208 >= 0)
533 cs = CHARSET_FROM_ID (charset_jisx0208);
534 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
535 && charset_ksc5601 >= 0)
536 cs = CHARSET_FROM_ID (charset_ksc5601);
537 if (cs)
538 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
540 if (FONT_ENTITY_P (font))
541 return ftfont_driver.has_char (font, c);
542 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
543 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
544 (FcChar32) c) == FcTrue);
547 static unsigned
548 xftfont_encode_char (struct font *font, int c)
550 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
551 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
552 (FcChar32) c);
554 return (code ? code : FONT_INVALID_CODE);
557 static void
558 xftfont_text_extents (struct font *font, unsigned int *code,
559 int nglyphs, struct font_metrics *metrics)
561 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
562 XGlyphInfo extents;
564 block_input ();
565 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
566 &extents);
567 unblock_input ();
569 metrics->lbearing = - extents.x;
570 metrics->rbearing = - extents.x + extents.width;
571 metrics->width = extents.xOff;
572 metrics->ascent = extents.y;
573 metrics->descent = extents.height - extents.y;
576 static XftDraw *
577 xftfont_get_xft_draw (struct frame *f)
579 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
581 if (! xft_draw)
583 block_input ();
584 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
585 FRAME_X_WINDOW (f),
586 FRAME_X_VISUAL (f),
587 FRAME_X_COLORMAP (f));
588 unblock_input ();
589 eassert (xft_draw != NULL);
590 font_put_frame_data (f, Qxft, xft_draw);
592 return xft_draw;
595 static int
596 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
597 bool with_background)
599 struct frame *f = s->f;
600 struct face *face = s->face;
601 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
602 struct xftface_info *xftface_info = NULL;
603 XftDraw *xft_draw = xftfont_get_xft_draw (f);
604 FT_UInt *code;
605 XftColor fg, bg;
606 int len = to - from;
607 int i;
609 if (s->font == face->font)
610 xftface_info = (struct xftface_info *) face->extra;
611 xftfont_get_colors (f, face, s->gc, xftface_info,
612 &fg, with_background ? &bg : NULL);
613 block_input ();
614 if (s->num_clips > 0)
615 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
616 else
617 XftDrawSetClip (xft_draw, NULL);
619 if (with_background)
621 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
623 /* Font's global height and ascent values might be
624 preposterously large for some fonts. We fix here the case
625 when those fonts are used for display of glyphless
626 characters, because drawing background with font dimensions
627 in those cases makes the display illegible. There's only one
628 more call to the draw method with with_background set to
629 true, and that's in x_draw_glyph_string_foreground, when
630 drawing the cursor, where we have no such heuristics
631 available. FIXME. */
632 if (s->first_glyph->type == GLYPHLESS_GLYPH
633 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
634 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
635 height = ascent =
636 s->first_glyph->slice.glyphless.lower_yoff
637 - s->first_glyph->slice.glyphless.upper_yoff;
638 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
640 code = alloca (sizeof (FT_UInt) * len);
641 for (i = 0; i < len; i++)
642 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
643 | XCHAR2B_BYTE2 (s->char2b + from + i));
645 if (s->padding_p)
646 for (i = 0; i < len; i++)
647 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
648 x + i, y, code + i, 1);
649 else
650 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
651 x, y, code, len);
652 unblock_input ();
654 return len;
657 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
658 static Lisp_Object
659 xftfont_shape (Lisp_Object lgstring)
661 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
662 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
663 FT_Face ft_face;
664 Lisp_Object val;
666 ft_face = XftLockFace (xftfont_info->xftfont);
667 xftfont_info->ft_size = ft_face->size;
668 val = ftfont_driver.shape (lgstring);
669 XftUnlockFace (xftfont_info->xftfont);
670 return val;
672 #endif
674 static int
675 xftfont_end_for_frame (struct frame *f)
677 XftDraw *xft_draw;
679 /* Don't do anything if display is dead */
680 if (FRAME_X_DISPLAY (f) == NULL) return 0;
682 xft_draw = font_get_frame_data (f, Qxft);
684 if (xft_draw)
686 block_input ();
687 XftDrawDestroy (xft_draw);
688 unblock_input ();
689 font_put_frame_data (f, Qxft, NULL);
691 return 0;
694 static bool
695 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
696 Lisp_Object entity)
698 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
699 FcPattern *oldpat = info->xftfont->pattern;
700 Display *display = FRAME_X_DISPLAY (f);
701 FcPattern *pat = FcPatternCreate ();
702 FcBool b1, b2;
703 bool ok = false;
704 int i1, i2, r1, r2;
706 xftfont_add_rendering_parameters (pat, entity);
707 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
709 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
710 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
711 if (r1 != r2 || b1 != b2) goto out;
712 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
713 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
714 if (r1 != r2 || b1 != b2) goto out;
715 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
716 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
717 if (r1 != r2 || b1 != b2) goto out;
718 #ifdef FC_EMBOLDEN
719 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
720 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
721 if (r1 != r2 || b1 != b2) goto out;
722 #endif
723 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
724 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
725 if (r1 != r2 || i1 != i2) goto out;
726 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
727 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
728 if (r1 != r2 || i1 != i2) goto out;
729 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
730 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
731 if (r1 != r2 || i1 != i2) goto out;
733 ok = true;
734 out:
735 FcPatternDestroy (pat);
736 return ok;
739 void
740 syms_of_xftfont (void)
742 DEFSYM (Qxft, "xft");
743 DEFSYM (QChinting, ":hinting");
744 DEFSYM (QCautohint, ":autohint");
745 DEFSYM (QChintstyle, ":hintstyle");
746 DEFSYM (QCrgba, ":rgba");
747 DEFSYM (QCembolden, ":embolden");
748 DEFSYM (QClcdfilter, ":lcdfilter");
750 ascii_printable[0] = 0;
752 xftfont_driver = ftfont_driver;
753 xftfont_driver.type = Qxft;
754 xftfont_driver.get_cache = xfont_driver.get_cache;
755 xftfont_driver.list = xftfont_list;
756 xftfont_driver.match = xftfont_match;
757 xftfont_driver.open = xftfont_open;
758 xftfont_driver.close = xftfont_close;
759 xftfont_driver.prepare_face = xftfont_prepare_face;
760 xftfont_driver.done_face = xftfont_done_face;
761 xftfont_driver.has_char = xftfont_has_char;
762 xftfont_driver.encode_char = xftfont_encode_char;
763 xftfont_driver.text_extents = xftfont_text_extents;
764 xftfont_driver.draw = xftfont_draw;
765 xftfont_driver.end_for_frame = xftfont_end_for_frame;
766 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
767 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
768 xftfont_driver.shape = xftfont_shape;
769 #endif
771 register_font_driver (&xftfont_driver, NULL);