Enlarge DUMPED_HEAP_SIZE
[emacs.git] / src / xftfont.c
blob861ad80da5c00b422ca2e2bb69958002b54e7a41
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2016 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 <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 "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 ();
129 struct font_driver xftfont_driver;
131 static Lisp_Object
132 xftfont_list (struct frame *f, Lisp_Object spec)
134 Lisp_Object list = ftfont_driver.list (f, spec), tail;
136 for (tail = list; CONSP (tail); tail = XCDR (tail))
137 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
138 return list;
141 static Lisp_Object
142 xftfont_match (struct frame *f, Lisp_Object spec)
144 Lisp_Object entity = ftfont_driver.match (f, spec);
146 if (! NILP (entity))
147 ASET (entity, FONT_TYPE_INDEX, Qxft);
148 return entity;
151 static FcChar8 ascii_printable[95];
153 static void
154 xftfont_fix_match (FcPattern *pat, FcPattern *match)
156 /* These values are not used for matching (except antialias), but for
157 rendering, so make sure they are carried over to the match.
158 We also put antialias here because most fonts are antialiased, so
159 the match will have antialias true. */
161 FcBool b = FcTrue;
162 int i;
163 double dpi;
165 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
166 if (! b)
168 FcPatternDel (match, FC_ANTIALIAS);
169 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
171 FcPatternGetBool (pat, FC_HINTING, 0, &b);
172 if (! b)
174 FcPatternDel (match, FC_HINTING);
175 FcPatternAddBool (match, FC_HINTING, FcFalse);
177 #ifndef FC_HINT_STYLE
178 # define FC_HINT_STYLE "hintstyle"
179 #endif
180 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
182 FcPatternDel (match, FC_HINT_STYLE);
183 FcPatternAddInteger (match, FC_HINT_STYLE, i);
185 #ifndef FC_LCD_FILTER
186 /* Older fontconfig versions don't have FC_LCD_FILTER. */
187 #define FC_LCD_FILTER "lcdfilter"
188 #endif
189 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
191 FcPatternDel (match, FC_LCD_FILTER);
192 FcPatternAddInteger (match, FC_LCD_FILTER, i);
194 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
196 FcPatternDel (match, FC_RGBA);
197 FcPatternAddInteger (match, FC_RGBA, i);
199 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
201 FcPatternDel (match, FC_DPI);
202 FcPatternAddDouble (match, FC_DPI, dpi);
206 static void
207 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
209 Lisp_Object tail;
210 int ival;
212 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
214 Lisp_Object key = XCAR (XCAR (tail));
215 Lisp_Object val = XCDR (XCAR (tail));
217 if (EQ (key, QCantialias))
218 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
219 else if (EQ (key, QChinting))
220 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
221 else if (EQ (key, QCautohint))
222 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
223 else if (EQ (key, QChintstyle))
225 if (INTEGERP (val))
226 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
227 else if (SYMBOLP (val)
228 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
229 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
231 else if (EQ (key, QCrgba))
233 if (INTEGERP (val))
234 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
235 else if (SYMBOLP (val)
236 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
237 FcPatternAddInteger (pat, FC_RGBA, ival);
239 else if (EQ (key, QClcdfilter))
241 if (INTEGERP (val))
242 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
243 else if (SYMBOLP (val)
244 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
245 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
247 #ifdef FC_EMBOLDEN
248 else if (EQ (key, QCembolden))
249 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
250 #endif
254 static Lisp_Object
255 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
257 FcResult result;
258 Display *display = FRAME_X_DISPLAY (f);
259 Lisp_Object val, filename, idx, font_object;
260 FcPattern *pat = NULL, *match;
261 struct xftfont_info *xftfont_info = NULL;
262 struct font *font;
263 double size = 0;
264 XftFont *xftfont = NULL;
265 int spacing;
266 int i;
267 XGlyphInfo extents;
268 FT_Face ft_face;
269 FcMatrix *matrix;
271 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
272 if (! CONSP (val))
273 return Qnil;
274 val = XCDR (val);
275 filename = XCAR (val);
276 idx = XCDR (val);
277 size = XINT (AREF (entity, FONT_SIZE_INDEX));
278 if (size == 0)
279 size = pixel_size;
280 pat = FcPatternCreate ();
281 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
282 i = FONT_SLANT_NUMERIC (entity) - 100;
283 if (i < 0) i = 0;
284 FcPatternAddInteger (pat, FC_SLANT, i);
285 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
286 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
287 val = AREF (entity, FONT_FAMILY_INDEX);
288 if (! NILP (val))
289 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
290 val = AREF (entity, FONT_FOUNDRY_INDEX);
291 if (! NILP (val))
292 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
293 val = AREF (entity, FONT_SPACING_INDEX);
294 if (! NILP (val))
295 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
296 val = AREF (entity, FONT_DPI_INDEX);
297 if (! NILP (val))
299 double dbl = XINT (val);
301 FcPatternAddDouble (pat, FC_DPI, dbl);
303 val = AREF (entity, FONT_AVGWIDTH_INDEX);
304 if (INTEGERP (val) && XINT (val) == 0)
305 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
306 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
307 over 10x20-ISO8859-1.pcf.gz). */
308 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
310 xftfont_add_rendering_parameters (pat, entity);
312 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
313 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
316 block_input ();
318 /* Substitute in values from X resources and XftDefaultSet. */
319 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
320 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
321 xftfont_fix_match (pat, match);
323 FcPatternDestroy (pat);
324 xftfont = XftFontOpenPattern (display, match);
325 if (!xftfont)
327 unblock_input ();
328 XftPatternDestroy (match);
329 return Qnil;
331 ft_face = XftLockFace (xftfont);
332 unblock_input ();
334 /* We should not destroy PAT here because it is kept in XFTFONT and
335 destroyed automatically when XFTFONT is closed. */
336 font_object = font_build_object (VECSIZE (struct xftfont_info),
337 Qxft, entity, size);
338 ASET (font_object, FONT_FILE_INDEX, filename);
339 font = XFONT_OBJECT (font_object);
340 font->pixel_size = size;
341 font->driver = &xftfont_driver;
342 font->encoding_charset = font->repertory_charset = -1;
344 xftfont_info = (struct xftfont_info *) font;
345 xftfont_info->display = display;
346 xftfont_info->xftfont = xftfont;
347 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
348 /* This means that there's no need of transformation. */
349 xftfont_info->matrix.xx = 0;
350 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
351 == FcResultMatch)
353 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
354 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
355 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
356 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
358 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
359 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
360 else
361 spacing = FC_PROPORTIONAL;
362 if (! ascii_printable[0])
364 int ch;
365 for (ch = 0; ch < 95; ch++)
366 ascii_printable[ch] = ' ' + ch;
368 block_input ();
370 /* Unfortunately Xft doesn't provide a way to get minimum char
371 width. So, we set min_width to space_width. */
373 if (spacing != FC_PROPORTIONAL
374 #ifdef FC_DUAL
375 && spacing != FC_DUAL
376 #endif /* FC_DUAL */
379 font->min_width = font->max_width = font->average_width
380 = font->space_width = xftfont->max_advance_width;
381 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
383 else
385 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
386 font->min_width = font->max_width = font->space_width
387 = extents.xOff;
388 if (font->space_width <= 0)
389 /* dirty workaround */
390 font->space_width = pixel_size;
391 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
392 font->average_width = (font->space_width + extents.xOff) / 95;
394 unblock_input ();
396 font->ascent = xftfont->ascent;
397 font->descent = xftfont->descent;
398 /* The following workaround is unnecessary on most systems, and
399 causes annoying differences in glyph height between regular and
400 bold fonts (see bug#22383). However, with some fonts, such as
401 monaco, removing the workaround results in overlapping vertical
402 space of a line, see bug#23360. As long as the way to reconcile
403 these opposites is not known, we provide a user option to work
404 around the problem. */
405 if (pixel_size >= 5
406 && xft_font_ascent_descent_override)
408 /* The above condition is a dirty workaround because
409 XftTextExtents8 behaves strangely for some fonts
410 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
411 if (font->ascent < extents.y)
412 font->ascent = extents.y;
413 if (font->descent < extents.height - extents.y)
414 font->descent = extents.height - extents.y;
416 font->height = font->ascent + font->descent;
418 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
420 int upEM = ft_face->units_per_EM;
422 font->underline_position = -ft_face->underline_position * size / upEM;
423 font->underline_thickness = ft_face->underline_thickness * size / upEM;
424 if (font->underline_thickness > 2)
425 font->underline_position -= font->underline_thickness / 2;
427 else
429 font->underline_position = -1;
430 font->underline_thickness = 0;
432 #ifdef HAVE_LIBOTF
433 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
434 xftfont_info->otf = NULL;
435 #endif /* HAVE_LIBOTF */
436 xftfont_info->ft_size = ft_face->size;
438 font->baseline_offset = 0;
439 font->relative_compose = 0;
440 font->default_ascent = 0;
441 font->vertical_centering = false;
442 #ifdef FT_BDF_H
443 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
445 BDF_PropertyRec rec;
447 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
448 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
449 font->baseline_offset = rec.u.integer;
450 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
451 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
452 font->relative_compose = rec.u.integer;
453 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
454 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
455 font->default_ascent = rec.u.integer;
457 #endif
459 return font_object;
462 static void
463 xftfont_close (struct font *font)
465 struct x_display_info *xdi;
466 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
468 #ifdef HAVE_LIBOTF
469 if (xftfont_info->otf)
471 OTF_close (xftfont_info->otf);
472 xftfont_info->otf = NULL;
474 #endif
476 /* See comment in xfont_close. */
477 if (xftfont_info->xftfont
478 && ((xdi = x_display_info_for_display (xftfont_info->display))
479 && xftfont_info->x_display_id == xdi->x_id))
481 block_input ();
482 XftUnlockFace (xftfont_info->xftfont);
483 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
484 unblock_input ();
485 xftfont_info->xftfont = NULL;
489 static void
490 xftfont_prepare_face (struct frame *f, struct face *face)
492 struct xftface_info *xftface_info;
494 #if false
495 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
496 if (face != face->ascii_face)
498 face->extra = face->ascii_face->extra;
499 return;
501 #endif
503 xftface_info = xmalloc (sizeof *xftface_info);
504 xftfont_get_colors (f, face, face->gc, NULL,
505 &xftface_info->xft_fg, &xftface_info->xft_bg);
506 face->extra = xftface_info;
509 static void
510 xftfont_done_face (struct frame *f, struct face *face)
512 struct xftface_info *xftface_info;
514 #if false
515 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
516 if (face != face->ascii_face
517 || ! face->extra)
518 return;
519 #endif
521 xftface_info = (struct xftface_info *) face->extra;
522 if (xftface_info)
524 xfree (xftface_info);
525 face->extra = NULL;
529 static int
530 xftfont_has_char (Lisp_Object font, int c)
532 struct xftfont_info *xftfont_info;
533 struct charset *cs = NULL;
535 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
536 && charset_jisx0208 >= 0)
537 cs = CHARSET_FROM_ID (charset_jisx0208);
538 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
539 && charset_ksc5601 >= 0)
540 cs = CHARSET_FROM_ID (charset_ksc5601);
541 if (cs)
542 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
544 if (FONT_ENTITY_P (font))
545 return ftfont_driver.has_char (font, c);
546 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
547 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
548 (FcChar32) c) == FcTrue);
551 static unsigned
552 xftfont_encode_char (struct font *font, int c)
554 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
555 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
556 (FcChar32) c);
558 return (code ? code : FONT_INVALID_CODE);
561 static void
562 xftfont_text_extents (struct font *font, unsigned int *code,
563 int nglyphs, struct font_metrics *metrics)
565 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
566 XGlyphInfo extents;
568 block_input ();
569 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
570 &extents);
571 unblock_input ();
573 metrics->lbearing = - extents.x;
574 metrics->rbearing = - extents.x + extents.width;
575 metrics->width = extents.xOff;
576 metrics->ascent = extents.y;
577 metrics->descent = extents.height - extents.y;
580 static XftDraw *
581 xftfont_get_xft_draw (struct frame *f)
583 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
585 if (! xft_draw)
587 block_input ();
588 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
589 FRAME_X_DRAWABLE (f),
590 FRAME_X_VISUAL (f),
591 FRAME_X_COLORMAP (f));
592 unblock_input ();
593 eassert (xft_draw != NULL);
594 font_put_frame_data (f, Qxft, xft_draw);
596 return xft_draw;
599 static int
600 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
601 bool with_background)
603 block_input ();
605 struct frame *f = s->f;
606 struct face *face = s->face;
607 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
608 struct xftface_info *xftface_info = NULL;
609 XftDraw *xft_draw = xftfont_get_xft_draw (f);
610 FT_UInt *code;
611 XftColor fg, bg;
612 int len = to - from;
613 int i;
615 if (s->font == face->font)
616 xftface_info = (struct xftface_info *) face->extra;
617 xftfont_get_colors (f, face, s->gc, xftface_info,
618 &fg, with_background ? &bg : NULL);
619 if (s->num_clips > 0)
620 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
621 else
622 XftDrawSetClip (xft_draw, NULL);
624 if (with_background)
626 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
628 /* Font's global height and ascent values might be
629 preposterously large for some fonts. We fix here the case
630 when those fonts are used for display of glyphless
631 characters, because drawing background with font dimensions
632 in those cases makes the display illegible. There's only one
633 more call to the draw method with with_background set to
634 true, and that's in x_draw_glyph_string_foreground, when
635 drawing the cursor, where we have no such heuristics
636 available. FIXME. */
637 if (s->first_glyph->type == GLYPHLESS_GLYPH
638 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
639 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
640 height = ascent =
641 s->first_glyph->slice.glyphless.lower_yoff
642 - s->first_glyph->slice.glyphless.upper_yoff;
643 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
645 code = alloca (sizeof (FT_UInt) * len);
646 for (i = 0; i < len; i++)
647 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
648 | XCHAR2B_BYTE2 (s->char2b + from + i));
650 if (s->padding_p)
651 for (i = 0; i < len; i++)
652 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
653 x + i, y, code + i, 1);
654 else
655 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
656 x, y, code, len);
657 /* Need to explicitly mark the frame dirty because we didn't call
658 FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
659 XftDraw structure. */
660 x_mark_frame_dirty (f);
661 unblock_input ();
662 return len;
665 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
666 static Lisp_Object
667 xftfont_shape (Lisp_Object lgstring)
669 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
670 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
671 FT_Face ft_face;
672 Lisp_Object val;
674 ft_face = XftLockFace (xftfont_info->xftfont);
675 xftfont_info->ft_size = ft_face->size;
676 val = ftfont_driver.shape (lgstring);
677 XftUnlockFace (xftfont_info->xftfont);
678 return val;
680 #endif
682 static int
683 xftfont_end_for_frame (struct frame *f)
685 block_input ();
686 XftDraw *xft_draw;
688 xft_draw = font_get_frame_data (f, Qxft);
689 if (xft_draw)
691 block_input ();
692 XftDrawDestroy (xft_draw);
693 unblock_input ();
694 font_put_frame_data (f, Qxft, NULL);
696 unblock_input ();
697 return 0;
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 void
755 syms_of_xftfont (void)
757 DEFSYM (Qxft, "xft");
758 DEFSYM (QChinting, ":hinting");
759 DEFSYM (QCautohint, ":autohint");
760 DEFSYM (QChintstyle, ":hintstyle");
761 DEFSYM (QCrgba, ":rgba");
762 DEFSYM (QCembolden, ":embolden");
763 DEFSYM (QClcdfilter, ":lcdfilter");
765 DEFVAR_BOOL ("xft-font-ascent-descent-override",
766 xft_font_ascent_descent_override,
767 doc: /* Non-nil means override the ascent and descent values for Xft font driver.
768 This is needed with some fonts to correct vertical overlap of glyphs. */);
769 xft_font_ascent_descent_override = 0;
771 ascii_printable[0] = 0;
773 xftfont_driver = ftfont_driver;
774 xftfont_driver.type = Qxft;
775 xftfont_driver.get_cache = xfont_driver.get_cache;
776 xftfont_driver.list = xftfont_list;
777 xftfont_driver.match = xftfont_match;
778 xftfont_driver.open = xftfont_open;
779 xftfont_driver.close = xftfont_close;
780 xftfont_driver.prepare_face = xftfont_prepare_face;
781 xftfont_driver.done_face = xftfont_done_face;
782 xftfont_driver.has_char = xftfont_has_char;
783 xftfont_driver.encode_char = xftfont_encode_char;
784 xftfont_driver.text_extents = xftfont_text_extents;
785 xftfont_driver.draw = xftfont_draw;
786 xftfont_driver.end_for_frame = xftfont_end_for_frame;
787 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
788 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
789 xftfont_driver.shape = xftfont_shape;
790 #endif
791 /* When using X double buffering, the XftDraw structure we build
792 seems to be useless once a frame is resized, so recreate it on
793 ConfigureNotify and in some other cases. */
794 xftfont_driver.drop_xrender_surfaces = xftfont_drop_xrender_surfaces;
796 register_font_driver (&xftfont_driver, NULL);