; * ChangeLog.3: Update.
[emacs.git] / src / xftfont.c
blob5ef90a014eafad254f88ca0361fb10398842b6b3
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2018 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 (at
12 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 <https://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 "xterm.h"
29 #include "frame.h"
30 #include "blockinput.h"
31 #include "charset.h"
32 #include "composite.h"
33 #include "font.h"
34 #include "ftfont.h"
36 /* Xft font driver. */
39 /* The actual structure for Xft font that can be cast to struct
40 font. */
42 struct xftfont_info
44 struct font font;
45 /* The following five members must be here in this order to be
46 compatible with struct ftfont_info (in ftfont.c). */
47 #ifdef HAVE_LIBOTF
48 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
49 OTF *otf;
50 #endif /* HAVE_LIBOTF */
51 FT_Size ft_size;
52 int index;
53 FT_Matrix matrix;
54 Display *display;
55 XftFont *xftfont;
56 unsigned x_display_id;
59 /* Structure pointed by (struct face *)->extra */
61 struct xftface_info
63 XftColor xft_fg; /* color for face->foreground */
64 XftColor xft_bg; /* color for face->background */
67 /* Setup foreground and background colors of GC into FG and BG. If
68 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
69 may be NULL. */
71 static void
72 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
73 struct xftface_info *xftface_info,
74 XftColor *fg, XftColor *bg)
76 if (xftface_info && face->gc == gc)
78 *fg = xftface_info->xft_fg;
79 if (bg)
80 *bg = xftface_info->xft_bg;
82 else
84 XGCValues xgcv;
85 bool fg_done = false, bg_done = false;
87 block_input ();
88 XGetGCValues (FRAME_X_DISPLAY (f), gc,
89 GCForeground | GCBackground, &xgcv);
90 if (xftface_info)
92 if (xgcv.foreground == face->foreground)
93 *fg = xftface_info->xft_fg, fg_done = true;
94 else if (xgcv.foreground == face->background)
95 *fg = xftface_info->xft_bg, fg_done = true;
96 if (! bg)
97 bg_done = true;
98 else if (xgcv.background == face->background)
99 *bg = xftface_info->xft_bg, bg_done = true;
100 else if (xgcv.background == face->foreground)
101 *bg = xftface_info->xft_fg, bg_done = true;
104 if (! (fg_done & bg_done))
106 XColor colors[2];
108 colors[0].pixel = fg->pixel = xgcv.foreground;
109 if (bg)
110 colors[1].pixel = bg->pixel = xgcv.background;
111 x_query_colors (f, colors, bg ? 2 : 1);
112 fg->color.alpha = 0xFFFF;
113 fg->color.red = colors[0].red;
114 fg->color.green = colors[0].green;
115 fg->color.blue = colors[0].blue;
116 if (bg)
118 bg->color.alpha = 0xFFFF;
119 bg->color.red = colors[1].red;
120 bg->color.green = colors[1].green;
121 bg->color.blue = colors[1].blue;
124 unblock_input ();
128 static Lisp_Object
129 xftfont_list (struct frame *f, Lisp_Object spec)
131 Lisp_Object list = ftfont_list (f, spec);
133 for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
134 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
135 return list;
138 static Lisp_Object
139 xftfont_match (struct frame *f, Lisp_Object spec)
141 Lisp_Object entity = ftfont_match (f, spec);
143 if (! NILP (entity))
144 ASET (entity, FONT_TYPE_INDEX, Qxft);
145 return entity;
148 static FcChar8 ascii_printable[95];
150 static void
151 xftfont_fix_match (FcPattern *pat, FcPattern *match)
153 /* These values are not used for matching (except antialias), but for
154 rendering, so make sure they are carried over to the match.
155 We also put antialias here because most fonts are antialiased, so
156 the match will have antialias true. */
158 FcBool b = FcTrue;
159 int i;
160 double dpi;
162 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
163 if (! b)
165 FcPatternDel (match, FC_ANTIALIAS);
166 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
168 FcPatternGetBool (pat, FC_HINTING, 0, &b);
169 if (! b)
171 FcPatternDel (match, FC_HINTING);
172 FcPatternAddBool (match, FC_HINTING, FcFalse);
174 #ifndef FC_HINT_STYLE
175 # define FC_HINT_STYLE "hintstyle"
176 #endif
177 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
179 FcPatternDel (match, FC_HINT_STYLE);
180 FcPatternAddInteger (match, FC_HINT_STYLE, i);
182 #ifndef FC_LCD_FILTER
183 /* Older fontconfig versions don't have FC_LCD_FILTER. */
184 #define FC_LCD_FILTER "lcdfilter"
185 #endif
186 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
188 FcPatternDel (match, FC_LCD_FILTER);
189 FcPatternAddInteger (match, FC_LCD_FILTER, i);
191 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
193 FcPatternDel (match, FC_RGBA);
194 FcPatternAddInteger (match, FC_RGBA, i);
196 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
198 FcPatternDel (match, FC_DPI);
199 FcPatternAddDouble (match, FC_DPI, dpi);
203 static void
204 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
206 Lisp_Object tail;
207 int ival;
209 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
211 Lisp_Object key = XCAR (XCAR (tail));
212 Lisp_Object val = XCDR (XCAR (tail));
214 if (EQ (key, QCantialias))
215 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
216 else if (EQ (key, QChinting))
217 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
218 else if (EQ (key, QCautohint))
219 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
220 else if (EQ (key, QChintstyle))
222 if (INTEGERP (val))
223 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
224 else if (SYMBOLP (val)
225 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
226 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
228 else if (EQ (key, QCrgba))
230 if (INTEGERP (val))
231 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
232 else if (SYMBOLP (val)
233 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
234 FcPatternAddInteger (pat, FC_RGBA, ival);
236 else if (EQ (key, QClcdfilter))
238 if (INTEGERP (val))
239 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
240 else if (SYMBOLP (val)
241 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
242 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
244 #ifdef FC_EMBOLDEN
245 else if (EQ (key, QCembolden))
246 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
247 #endif
251 static Lisp_Object
252 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
254 FcResult result;
255 Display *display = FRAME_X_DISPLAY (f);
256 Lisp_Object val, filename, idx, font_object;
257 FcPattern *pat = NULL, *match;
258 struct xftfont_info *xftfont_info = NULL;
259 struct font *font;
260 double size = 0;
261 XftFont *xftfont = NULL;
262 int spacing;
263 int i;
264 XGlyphInfo extents;
265 FT_Face ft_face;
266 FcMatrix *matrix;
268 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
269 if (! CONSP (val))
270 return Qnil;
271 val = XCDR (val);
272 filename = XCAR (val);
273 idx = XCDR (val);
274 size = XINT (AREF (entity, FONT_SIZE_INDEX));
275 if (size == 0)
276 size = pixel_size;
277 pat = FcPatternCreate ();
278 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
279 i = FONT_SLANT_NUMERIC (entity) - 100;
280 if (i < 0) i = 0;
281 FcPatternAddInteger (pat, FC_SLANT, i);
282 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
283 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
284 val = AREF (entity, FONT_FAMILY_INDEX);
285 if (! NILP (val))
286 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
287 val = AREF (entity, FONT_FOUNDRY_INDEX);
288 if (! NILP (val))
289 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
290 val = AREF (entity, FONT_SPACING_INDEX);
291 if (! NILP (val))
292 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
293 val = AREF (entity, FONT_DPI_INDEX);
294 if (! NILP (val))
296 double dbl = XINT (val);
298 FcPatternAddDouble (pat, FC_DPI, dbl);
300 val = AREF (entity, FONT_AVGWIDTH_INDEX);
301 if (INTEGERP (val) && XINT (val) == 0)
302 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
303 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
304 over 10x20-ISO8859-1.pcf.gz). */
305 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
307 xftfont_add_rendering_parameters (pat, entity);
309 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
310 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
313 block_input ();
315 /* Substitute in values from X resources and XftDefaultSet. */
316 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
317 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
318 xftfont_fix_match (pat, match);
320 FcPatternDestroy (pat);
321 xftfont = XftFontOpenPattern (display, match);
322 if (!xftfont)
324 unblock_input ();
325 XftPatternDestroy (match);
326 return Qnil;
328 ft_face = XftLockFace (xftfont);
329 unblock_input ();
331 /* We should not destroy PAT here because it is kept in XFTFONT and
332 destroyed automatically when XFTFONT is closed. */
333 font_object = font_build_object (VECSIZE (struct xftfont_info),
334 Qxft, entity, size);
335 ASET (font_object, FONT_FILE_INDEX, filename);
336 font = XFONT_OBJECT (font_object);
337 font->pixel_size = size;
338 font->driver = &xftfont_driver;
339 font->encoding_charset = font->repertory_charset = -1;
341 xftfont_info = (struct xftfont_info *) font;
342 xftfont_info->display = display;
343 xftfont_info->xftfont = xftfont;
344 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
345 /* This means that there's no need of transformation. */
346 xftfont_info->matrix.xx = 0;
347 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
348 == FcResultMatch)
350 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
351 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
352 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
353 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
355 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
356 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
357 else
358 spacing = FC_PROPORTIONAL;
359 if (! ascii_printable[0])
361 int ch;
362 for (ch = 0; ch < 95; ch++)
363 ascii_printable[ch] = ' ' + ch;
365 block_input ();
367 /* Unfortunately Xft doesn't provide a way to get minimum char
368 width. So, we set min_width to space_width. */
370 if (spacing != FC_PROPORTIONAL
371 #ifdef FC_DUAL
372 && spacing != FC_DUAL
373 #endif /* FC_DUAL */
376 font->min_width = font->max_width = font->average_width
377 = font->space_width = xftfont->max_advance_width;
378 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
380 else
382 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
383 font->min_width = font->max_width = font->space_width
384 = extents.xOff;
385 if (font->space_width <= 0)
386 /* dirty workaround */
387 font->space_width = pixel_size;
388 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
389 font->average_width = (font->space_width + extents.xOff) / 95;
391 unblock_input ();
393 font->ascent = xftfont->ascent;
394 font->descent = xftfont->descent;
395 /* The following workaround is unnecessary on most systems, and
396 causes annoying differences in glyph height between regular and
397 bold fonts (see bug#22383). However, with some fonts, such as
398 monaco, removing the workaround results in overlapping vertical
399 space of a line, see bug#23360. As long as the way to reconcile
400 these opposites is not known, we provide a user option to work
401 around the problem. */
402 if (pixel_size >= 5
403 && xft_font_ascent_descent_override)
405 /* The above condition is a dirty workaround because
406 XftTextExtents8 behaves strangely for some fonts
407 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
408 if (font->ascent < extents.y)
409 font->ascent = extents.y;
410 if (font->descent < extents.height - extents.y)
411 font->descent = extents.height - extents.y;
413 font->height = font->ascent + font->descent;
415 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
417 int upEM = ft_face->units_per_EM;
419 font->underline_position = -ft_face->underline_position * size / upEM;
420 font->underline_thickness = ft_face->underline_thickness * size / upEM;
421 if (font->underline_thickness > 2)
422 font->underline_position -= font->underline_thickness / 2;
424 else
426 font->underline_position = -1;
427 font->underline_thickness = 0;
429 #ifdef HAVE_LIBOTF
430 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
431 xftfont_info->otf = NULL;
432 #endif /* HAVE_LIBOTF */
433 xftfont_info->ft_size = ft_face->size;
435 font->baseline_offset = 0;
436 font->relative_compose = 0;
437 font->default_ascent = 0;
438 font->vertical_centering = false;
439 #ifdef FT_BDF_H
440 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
442 BDF_PropertyRec rec;
444 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
445 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
446 font->baseline_offset = rec.u.integer;
447 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
448 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
449 font->relative_compose = rec.u.integer;
450 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
451 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
452 font->default_ascent = rec.u.integer;
454 #endif
456 return font_object;
459 static void
460 xftfont_close (struct font *font)
462 struct x_display_info *xdi;
463 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
465 #ifdef HAVE_LIBOTF
466 if (xftfont_info->otf)
468 OTF_close (xftfont_info->otf);
469 xftfont_info->otf = NULL;
471 #endif
473 /* See comment in xfont_close. */
474 if (xftfont_info->xftfont
475 && ((xdi = x_display_info_for_display (xftfont_info->display))
476 && xftfont_info->x_display_id == xdi->x_id))
478 block_input ();
479 XftUnlockFace (xftfont_info->xftfont);
480 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
481 unblock_input ();
482 xftfont_info->xftfont = NULL;
486 static void
487 xftfont_prepare_face (struct frame *f, struct face *face)
489 struct xftface_info *xftface_info;
491 #if false
492 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
493 if (face != face->ascii_face)
495 face->extra = face->ascii_face->extra;
496 return;
498 #endif
500 xftface_info = xmalloc (sizeof *xftface_info);
501 xftfont_get_colors (f, face, face->gc, NULL,
502 &xftface_info->xft_fg, &xftface_info->xft_bg);
503 face->extra = xftface_info;
506 static void
507 xftfont_done_face (struct frame *f, struct face *face)
509 struct xftface_info *xftface_info;
511 #if false
512 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
513 if (face != face->ascii_face
514 || ! face->extra)
515 return;
516 #endif
518 xftface_info = (struct xftface_info *) face->extra;
519 if (xftface_info)
521 xfree (xftface_info);
522 face->extra = NULL;
526 static int
527 xftfont_has_char (Lisp_Object font, int c)
529 struct xftfont_info *xftfont_info;
530 struct charset *cs = NULL;
532 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
533 && charset_jisx0208 >= 0)
534 cs = CHARSET_FROM_ID (charset_jisx0208);
535 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
536 && charset_ksc5601 >= 0)
537 cs = CHARSET_FROM_ID (charset_ksc5601);
538 if (cs)
539 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
541 if (FONT_ENTITY_P (font))
542 return ftfont_has_char (font, c);
543 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
544 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
545 (FcChar32) c) == FcTrue);
548 static unsigned
549 xftfont_encode_char (struct font *font, int c)
551 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
552 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
553 (FcChar32) c);
555 return (code ? code : FONT_INVALID_CODE);
558 static void
559 xftfont_text_extents (struct font *font, unsigned int *code,
560 int nglyphs, struct font_metrics *metrics)
562 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
563 XGlyphInfo extents;
565 block_input ();
566 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
567 &extents);
568 unblock_input ();
570 metrics->lbearing = - extents.x;
571 metrics->rbearing = - extents.x + extents.width;
572 metrics->width = extents.xOff;
573 metrics->ascent = extents.y;
574 metrics->descent = extents.height - extents.y;
577 static XftDraw *
578 xftfont_get_xft_draw (struct frame *f)
580 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
582 if (! xft_draw)
584 block_input ();
585 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
586 FRAME_X_DRAWABLE (f),
587 FRAME_X_VISUAL (f),
588 FRAME_X_COLORMAP (f));
589 unblock_input ();
590 eassert (xft_draw != NULL);
591 font_put_frame_data (f, Qxft, xft_draw);
593 return xft_draw;
596 static int
597 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
598 bool with_background)
600 block_input ();
602 struct frame *f = s->f;
603 struct face *face = s->face;
604 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
605 struct xftface_info *xftface_info = NULL;
606 XftDraw *xft_draw = xftfont_get_xft_draw (f);
607 FT_UInt *code;
608 XftColor fg, bg;
609 int len = to - from;
610 int i;
612 if (s->font == face->font)
613 xftface_info = (struct xftface_info *) face->extra;
614 xftfont_get_colors (f, face, s->gc, xftface_info,
615 &fg, with_background ? &bg : NULL);
616 if (s->num_clips > 0)
617 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
618 else
619 XftDrawSetClip (xft_draw, NULL);
621 if (with_background)
623 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
625 /* Font's global height and ascent values might be
626 preposterously large for some fonts. We fix here the case
627 when those fonts are used for display of glyphless
628 characters, because drawing background with font dimensions
629 in those cases makes the display illegible. There's only one
630 more call to the draw method with with_background set to
631 true, and that's in x_draw_glyph_string_foreground, when
632 drawing the cursor, where we have no such heuristics
633 available. FIXME. */
634 if (s->first_glyph->type == GLYPHLESS_GLYPH
635 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
636 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
637 height = ascent =
638 s->first_glyph->slice.glyphless.lower_yoff
639 - s->first_glyph->slice.glyphless.upper_yoff;
640 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
642 code = alloca (sizeof (FT_UInt) * len);
643 for (i = 0; i < len; i++)
644 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
645 | XCHAR2B_BYTE2 (s->char2b + from + i));
647 if (s->padding_p)
648 for (i = 0; i < len; i++)
649 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
650 x + i, y, code + i, 1);
651 else
652 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
653 x, y, code, len);
654 /* Need to explicitly mark the frame dirty because we didn't call
655 FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
656 XftDraw structure. */
657 x_mark_frame_dirty (f);
658 unblock_input ();
659 return len;
662 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
663 static Lisp_Object
664 xftfont_shape (Lisp_Object lgstring)
666 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
667 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
668 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
669 xftfont_info->ft_size = ft_face->size;
670 Lisp_Object val = ftfont_shape (lgstring);
671 XftUnlockFace (xftfont_info->xftfont);
672 return val;
674 #endif
676 static int
677 xftfont_end_for_frame (struct frame *f)
679 block_input ();
680 XftDraw *xft_draw;
682 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 unblock_input ();
691 return 0;
694 /* When using X double buffering, the XftDraw structure we build
695 seems to be useless once a frame is resized, so recreate it on
696 ConfigureNotify and in some other cases. */
698 static void
699 xftfont_drop_xrender_surfaces (struct frame *f)
701 block_input ();
702 if (FRAME_X_DOUBLE_BUFFERED_P (f))
703 xftfont_end_for_frame (f);
704 unblock_input ();
707 static bool
708 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
709 Lisp_Object entity)
711 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
712 FcPattern *oldpat = info->xftfont->pattern;
713 Display *display = FRAME_X_DISPLAY (f);
714 FcPattern *pat = FcPatternCreate ();
715 FcBool b1, b2;
716 bool ok = false;
717 int i1, i2, r1, r2;
719 xftfont_add_rendering_parameters (pat, entity);
720 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
722 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
723 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
724 if (r1 != r2 || b1 != b2) goto out;
725 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
726 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
727 if (r1 != r2 || b1 != b2) goto out;
728 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
729 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
730 if (r1 != r2 || b1 != b2) goto out;
731 #ifdef FC_EMBOLDEN
732 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
733 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
734 if (r1 != r2 || b1 != b2) goto out;
735 #endif
736 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
737 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
738 if (r1 != r2 || i1 != i2) goto out;
739 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
740 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
741 if (r1 != r2 || i1 != i2) goto out;
742 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
743 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
744 if (r1 != r2 || i1 != i2) goto out;
746 ok = true;
747 out:
748 FcPatternDestroy (pat);
749 return ok;
752 struct font_driver const xftfont_driver =
754 /* We can't draw a text without device dependent functions. */
755 .type = LISPSYM_INITIALLY (Qxft),
756 .get_cache = xfont_get_cache,
757 .list = xftfont_list,
758 .match = xftfont_match,
759 .list_family = ftfont_list_family,
760 .open = xftfont_open,
761 .close = xftfont_close,
762 .prepare_face = xftfont_prepare_face,
763 .done_face = xftfont_done_face,
764 .has_char = xftfont_has_char,
765 .encode_char = xftfont_encode_char,
766 .text_extents = xftfont_text_extents,
767 .draw = xftfont_draw,
768 .get_bitmap = ftfont_get_bitmap,
769 .anchor_point = ftfont_anchor_point,
770 #ifdef HAVE_LIBOTF
771 .otf_capability = ftfont_otf_capability,
772 #endif
773 .end_for_frame = xftfont_end_for_frame,
774 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
775 .shape = xftfont_shape,
776 #endif
777 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
778 .get_variation_glyphs = ftfont_variation_glyphs,
779 #endif
780 .filter_properties = ftfont_filter_properties,
781 .cached_font_ok = xftfont_cached_font_ok,
782 .combining_capability = ftfont_combining_capability,
783 .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
786 void
787 syms_of_xftfont (void)
789 DEFSYM (Qxft, "xft");
790 DEFSYM (QChinting, ":hinting");
791 DEFSYM (QCautohint, ":autohint");
792 DEFSYM (QChintstyle, ":hintstyle");
793 DEFSYM (QCrgba, ":rgba");
794 DEFSYM (QCembolden, ":embolden");
795 DEFSYM (QClcdfilter, ":lcdfilter");
797 DEFVAR_BOOL ("xft-font-ascent-descent-override",
798 xft_font_ascent_descent_override,
799 doc: /* Non-nil means override the ascent and descent values for Xft font driver.
800 This is needed with some fonts to correct vertical overlap of glyphs. */);
801 xft_font_ascent_descent_override = 0;
803 ascii_printable[0] = 0;
805 register_font_driver (&xftfont_driver, NULL);