; * lisp/ldefs-boot.el: Update.
[emacs.git] / src / xftfont.c
blob805ea0ede9cee2bcdfaa1622af327ec9a0f02e86
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2019 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 members up to and including 'matrix' must be here
46 in this order to be compatible with struct ftfont_info (in
47 ftfont.c). */
48 #ifdef HAVE_LIBOTF
49 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
50 OTF *otf;
51 #endif /* HAVE_LIBOTF */
52 FT_Size ft_size;
53 int index;
54 FT_Matrix matrix;
56 Display *display;
57 XftFont *xftfont;
58 unsigned x_display_id;
61 /* Structure pointed by (struct face *)->extra */
63 struct xftface_info
65 XftColor xft_fg; /* color for face->foreground */
66 XftColor xft_bg; /* color for face->background */
69 /* Setup foreground and background colors of GC into FG and BG. If
70 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
71 may be NULL. */
73 static void
74 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
75 struct xftface_info *xftface_info,
76 XftColor *fg, XftColor *bg)
78 if (xftface_info && face->gc == gc)
80 *fg = xftface_info->xft_fg;
81 if (bg)
82 *bg = xftface_info->xft_bg;
84 else
86 XGCValues xgcv;
87 bool fg_done = false, bg_done = false;
89 block_input ();
90 XGetGCValues (FRAME_X_DISPLAY (f), gc,
91 GCForeground | GCBackground, &xgcv);
92 if (xftface_info)
94 if (xgcv.foreground == face->foreground)
95 *fg = xftface_info->xft_fg, fg_done = true;
96 else if (xgcv.foreground == face->background)
97 *fg = xftface_info->xft_bg, fg_done = true;
98 if (! bg)
99 bg_done = true;
100 else if (xgcv.background == face->background)
101 *bg = xftface_info->xft_bg, bg_done = true;
102 else if (xgcv.background == face->foreground)
103 *bg = xftface_info->xft_fg, bg_done = true;
106 if (! (fg_done & bg_done))
108 XColor colors[2];
110 colors[0].pixel = fg->pixel = xgcv.foreground;
111 if (bg)
112 colors[1].pixel = bg->pixel = xgcv.background;
113 x_query_colors (f, colors, bg ? 2 : 1);
114 fg->color.alpha = 0xFFFF;
115 fg->color.red = colors[0].red;
116 fg->color.green = colors[0].green;
117 fg->color.blue = colors[0].blue;
118 if (bg)
120 bg->color.alpha = 0xFFFF;
121 bg->color.red = colors[1].red;
122 bg->color.green = colors[1].green;
123 bg->color.blue = colors[1].blue;
126 unblock_input ();
130 static Lisp_Object
131 xftfont_list (struct frame *f, Lisp_Object spec)
133 Lisp_Object list = ftfont_list (f, spec);
135 for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
136 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
137 return list;
140 static Lisp_Object
141 xftfont_match (struct frame *f, Lisp_Object spec)
143 Lisp_Object entity = ftfont_match (f, spec);
145 if (! NILP (entity))
146 ASET (entity, FONT_TYPE_INDEX, Qxft);
147 return entity;
150 static FcChar8 ascii_printable[95];
152 static void
153 xftfont_fix_match (FcPattern *pat, FcPattern *match)
155 /* These values are not used for matching (except antialias), but for
156 rendering, so make sure they are carried over to the match.
157 We also put antialias here because most fonts are antialiased, so
158 the match will have antialias true. */
160 FcBool b = FcTrue;
161 int i;
162 double dpi;
164 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
165 if (! b)
167 FcPatternDel (match, FC_ANTIALIAS);
168 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
170 FcPatternGetBool (pat, FC_HINTING, 0, &b);
171 if (! b)
173 FcPatternDel (match, FC_HINTING);
174 FcPatternAddBool (match, FC_HINTING, FcFalse);
176 #ifndef FC_HINT_STYLE
177 # define FC_HINT_STYLE "hintstyle"
178 #endif
179 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
181 FcPatternDel (match, FC_HINT_STYLE);
182 FcPatternAddInteger (match, FC_HINT_STYLE, i);
184 #ifndef FC_LCD_FILTER
185 /* Older fontconfig versions don't have FC_LCD_FILTER. */
186 #define FC_LCD_FILTER "lcdfilter"
187 #endif
188 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
190 FcPatternDel (match, FC_LCD_FILTER);
191 FcPatternAddInteger (match, FC_LCD_FILTER, i);
193 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
195 FcPatternDel (match, FC_RGBA);
196 FcPatternAddInteger (match, FC_RGBA, i);
198 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
200 FcPatternDel (match, FC_DPI);
201 FcPatternAddDouble (match, FC_DPI, dpi);
205 static void
206 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
208 Lisp_Object tail;
209 int ival;
211 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
213 Lisp_Object key = XCAR (XCAR (tail));
214 Lisp_Object val = XCDR (XCAR (tail));
216 if (EQ (key, QCantialias))
217 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
218 else if (EQ (key, QChinting))
219 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
220 else if (EQ (key, QCautohint))
221 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
222 else if (EQ (key, QChintstyle))
224 if (INTEGERP (val))
225 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
226 else if (SYMBOLP (val)
227 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
228 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
230 else if (EQ (key, QCrgba))
232 if (INTEGERP (val))
233 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
234 else if (SYMBOLP (val)
235 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
236 FcPatternAddInteger (pat, FC_RGBA, ival);
238 else if (EQ (key, QClcdfilter))
240 if (INTEGERP (val))
241 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
242 else if (SYMBOLP (val)
243 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
244 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
246 #ifdef FC_EMBOLDEN
247 else if (EQ (key, QCembolden))
248 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
249 #endif
253 static Lisp_Object
254 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
256 FcResult result;
257 Display *display = FRAME_X_DISPLAY (f);
258 Lisp_Object val, filename, idx, font_object;
259 FcPattern *pat = NULL, *match;
260 struct xftfont_info *xftfont_info = NULL;
261 struct font *font;
262 double size = 0;
263 XftFont *xftfont = NULL;
264 int spacing;
265 int i;
266 XGlyphInfo extents;
267 FT_Face ft_face;
268 FcMatrix *matrix;
270 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
271 if (! CONSP (val))
272 return Qnil;
273 val = XCDR (val);
274 filename = XCAR (val);
275 idx = XCDR (val);
276 size = XINT (AREF (entity, FONT_SIZE_INDEX));
277 if (size == 0)
278 size = pixel_size;
279 pat = FcPatternCreate ();
280 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
281 i = FONT_SLANT_NUMERIC (entity) - 100;
282 if (i < 0) i = 0;
283 FcPatternAddInteger (pat, FC_SLANT, i);
284 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
285 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
286 val = AREF (entity, FONT_FAMILY_INDEX);
287 if (! NILP (val))
288 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
289 val = AREF (entity, FONT_FOUNDRY_INDEX);
290 if (! NILP (val))
291 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
292 val = AREF (entity, FONT_SPACING_INDEX);
293 if (! NILP (val))
294 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
295 val = AREF (entity, FONT_DPI_INDEX);
296 if (! NILP (val))
298 double dbl = XINT (val);
300 FcPatternAddDouble (pat, FC_DPI, dbl);
302 val = AREF (entity, FONT_AVGWIDTH_INDEX);
303 if (INTEGERP (val) && XINT (val) == 0)
304 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
305 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
306 over 10x20-ISO8859-1.pcf.gz). */
307 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
309 xftfont_add_rendering_parameters (pat, entity);
311 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
312 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
315 block_input ();
317 /* Substitute in values from X resources and XftDefaultSet. */
318 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
319 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
320 xftfont_fix_match (pat, match);
322 FcPatternDestroy (pat);
323 xftfont = XftFontOpenPattern (display, match);
324 if (!xftfont)
326 unblock_input ();
327 XftPatternDestroy (match);
328 return Qnil;
330 ft_face = XftLockFace (xftfont);
331 unblock_input ();
333 /* We should not destroy PAT here because it is kept in XFTFONT and
334 destroyed automatically when XFTFONT is closed. */
335 font_object = font_build_object (VECSIZE (struct xftfont_info),
336 Qxft, entity, size);
337 ASET (font_object, FONT_FILE_INDEX, filename);
338 font = XFONT_OBJECT (font_object);
339 font->pixel_size = size;
340 font->driver = &xftfont_driver;
341 font->encoding_charset = font->repertory_charset = -1;
343 xftfont_info = (struct xftfont_info *) font;
344 xftfont_info->display = display;
345 xftfont_info->xftfont = xftfont;
346 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
347 /* This means that there's no need of transformation. */
348 xftfont_info->matrix.xx = 0;
349 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
350 == FcResultMatch)
352 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
353 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
354 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
355 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
357 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
358 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
359 else
360 spacing = FC_PROPORTIONAL;
361 if (! ascii_printable[0])
363 int ch;
364 for (ch = 0; ch < 95; ch++)
365 ascii_printable[ch] = ' ' + ch;
367 block_input ();
369 /* Unfortunately Xft doesn't provide a way to get minimum char
370 width. So, we set min_width to space_width. */
372 if (spacing != FC_PROPORTIONAL
373 #ifdef FC_DUAL
374 && spacing != FC_DUAL
375 #endif /* FC_DUAL */
378 font->min_width = font->max_width = font->average_width
379 = font->space_width = xftfont->max_advance_width;
380 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
382 else
384 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
385 font->min_width = font->max_width = font->space_width
386 = extents.xOff;
387 if (font->space_width <= 0)
388 /* dirty workaround */
389 font->space_width = pixel_size;
390 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
391 font->average_width = (font->space_width + extents.xOff) / 95;
393 unblock_input ();
395 font->ascent = xftfont->ascent;
396 font->descent = xftfont->descent;
397 /* The following workaround is unnecessary on most systems, and
398 causes annoying differences in glyph height between regular and
399 bold fonts (see bug#22383). However, with some fonts, such as
400 monaco, removing the workaround results in overlapping vertical
401 space of a line, see bug#23360. As long as the way to reconcile
402 these opposites is not known, we provide a user option to work
403 around the problem. */
404 if (pixel_size >= 5
405 && xft_font_ascent_descent_override)
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 = false;
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 false
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 false
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_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 void
561 xftfont_text_extents (struct font *font, unsigned int *code,
562 int nglyphs, struct font_metrics *metrics)
564 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
565 XGlyphInfo extents;
567 block_input ();
568 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
569 &extents);
570 unblock_input ();
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;
579 static XftDraw *
580 xftfont_get_xft_draw (struct frame *f)
582 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
584 if (! xft_draw)
586 block_input ();
587 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
588 FRAME_X_DRAWABLE (f),
589 FRAME_X_VISUAL (f),
590 FRAME_X_COLORMAP (f));
591 unblock_input ();
592 eassert (xft_draw != NULL);
593 font_put_frame_data (f, Qxft, xft_draw);
595 return xft_draw;
598 static int
599 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
600 bool with_background)
602 block_input ();
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 if (s->num_clips > 0)
619 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
620 else
621 XftDrawSetClip (xft_draw, NULL);
623 if (with_background)
625 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
627 /* Font's global height and ascent values might be
628 preposterously large for some fonts. We fix here the case
629 when those fonts are used for display of glyphless
630 characters, because drawing background with font dimensions
631 in those cases makes the display illegible. There's only one
632 more call to the draw method with with_background set to
633 true, and that's in x_draw_glyph_string_foreground, when
634 drawing the cursor, where we have no such heuristics
635 available. FIXME. */
636 if (s->first_glyph->type == GLYPHLESS_GLYPH
637 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
638 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
639 height = ascent =
640 s->first_glyph->slice.glyphless.lower_yoff
641 - s->first_glyph->slice.glyphless.upper_yoff;
642 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
644 code = alloca (sizeof (FT_UInt) * len);
645 for (i = 0; i < len; i++)
646 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
647 | XCHAR2B_BYTE2 (s->char2b + from + i));
649 if (s->padding_p)
650 for (i = 0; i < len; i++)
651 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
652 x + i, y, code + i, 1);
653 else
654 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
655 x, y, code, len);
656 /* Need to explicitly mark the frame dirty because we didn't call
657 FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
658 XftDraw structure. */
659 x_mark_frame_dirty (f);
660 unblock_input ();
661 return len;
664 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
665 static Lisp_Object
666 xftfont_shape (Lisp_Object lgstring)
668 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
669 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
670 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
671 xftfont_info->ft_size = ft_face->size;
672 Lisp_Object val = ftfont_shape (lgstring);
673 XftUnlockFace (xftfont_info->xftfont);
674 return val;
676 #endif
678 static int
679 xftfont_end_for_frame (struct frame *f)
681 block_input ();
682 XftDraw *xft_draw;
684 xft_draw = font_get_frame_data (f, Qxft);
685 if (xft_draw)
687 block_input ();
688 XftDrawDestroy (xft_draw);
689 unblock_input ();
690 font_put_frame_data (f, Qxft, NULL);
692 unblock_input ();
693 return 0;
696 /* When using X double buffering, the XftDraw structure we build
697 seems to be useless once a frame is resized, so recreate it on
698 ConfigureNotify and in some other cases. */
700 static void
701 xftfont_drop_xrender_surfaces (struct frame *f)
703 block_input ();
704 if (FRAME_X_DOUBLE_BUFFERED_P (f))
705 xftfont_end_for_frame (f);
706 unblock_input ();
709 static bool
710 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
711 Lisp_Object entity)
713 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
714 FcPattern *oldpat = info->xftfont->pattern;
715 Display *display = FRAME_X_DISPLAY (f);
716 FcPattern *pat = FcPatternCreate ();
717 FcBool b1, b2;
718 bool ok = false;
719 int i1, i2, r1, r2;
721 xftfont_add_rendering_parameters (pat, entity);
722 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
724 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
725 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
726 if (r1 != r2 || b1 != b2) goto out;
727 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
728 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
729 if (r1 != r2 || b1 != b2) goto out;
730 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
731 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
732 if (r1 != r2 || b1 != b2) goto out;
733 #ifdef FC_EMBOLDEN
734 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
735 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
736 if (r1 != r2 || b1 != b2) goto out;
737 #endif
738 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
739 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
740 if (r1 != r2 || i1 != i2) goto out;
741 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
742 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
743 if (r1 != r2 || i1 != i2) goto out;
744 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
745 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
746 if (r1 != r2 || i1 != i2) goto out;
748 ok = true;
749 out:
750 FcPatternDestroy (pat);
751 return ok;
754 struct font_driver const xftfont_driver =
756 /* We can't draw a text without device dependent functions. */
757 .type = LISPSYM_INITIALLY (Qxft),
758 .get_cache = xfont_get_cache,
759 .list = xftfont_list,
760 .match = xftfont_match,
761 .list_family = ftfont_list_family,
762 .open = xftfont_open,
763 .close = xftfont_close,
764 .prepare_face = xftfont_prepare_face,
765 .done_face = xftfont_done_face,
766 .has_char = xftfont_has_char,
767 .encode_char = xftfont_encode_char,
768 .text_extents = xftfont_text_extents,
769 .draw = xftfont_draw,
770 .get_bitmap = ftfont_get_bitmap,
771 .anchor_point = ftfont_anchor_point,
772 #ifdef HAVE_LIBOTF
773 .otf_capability = ftfont_otf_capability,
774 #endif
775 .end_for_frame = xftfont_end_for_frame,
776 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
777 .shape = xftfont_shape,
778 #endif
779 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
780 .get_variation_glyphs = ftfont_variation_glyphs,
781 #endif
782 .filter_properties = ftfont_filter_properties,
783 .cached_font_ok = xftfont_cached_font_ok,
784 .combining_capability = ftfont_combining_capability,
785 .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
788 void
789 syms_of_xftfont (void)
791 DEFSYM (Qxft, "xft");
792 DEFSYM (QChinting, ":hinting");
793 DEFSYM (QCautohint, ":autohint");
794 DEFSYM (QChintstyle, ":hintstyle");
795 DEFSYM (QCrgba, ":rgba");
796 DEFSYM (QCembolden, ":embolden");
797 DEFSYM (QClcdfilter, ":lcdfilter");
799 DEFVAR_BOOL ("xft-font-ascent-descent-override",
800 xft_font_ascent_descent_override,
801 doc: /* Non-nil means override the ascent and descent values for Xft font driver.
802 This is needed with some fonts to correct vertical overlap of glyphs. */);
803 xft_font_ascent_descent_override = 0;
805 ascii_printable[0] = 0;
807 register_font_driver (&xftfont_driver, NULL);