* src/casefiddle.c (casify_word): Return Qnil.
[emacs.git] / src / xftfont.c
blob34c6f7d3e42acbd0bd578c7b6dd6c9765723132f
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_WINDOW (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 struct frame *f = s->f;
604 struct face *face = s->face;
605 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
606 struct xftface_info *xftface_info = NULL;
607 XftDraw *xft_draw = xftfont_get_xft_draw (f);
608 FT_UInt *code;
609 XftColor fg, bg;
610 int len = to - from;
611 int i;
613 if (s->font == face->font)
614 xftface_info = (struct xftface_info *) face->extra;
615 xftfont_get_colors (f, face, s->gc, xftface_info,
616 &fg, with_background ? &bg : NULL);
617 block_input ();
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 unblock_input ();
658 return len;
661 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
662 static Lisp_Object
663 xftfont_shape (Lisp_Object lgstring)
665 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
666 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
667 FT_Face ft_face;
668 Lisp_Object val;
670 ft_face = XftLockFace (xftfont_info->xftfont);
671 xftfont_info->ft_size = ft_face->size;
672 val = ftfont_driver.shape (lgstring);
673 XftUnlockFace (xftfont_info->xftfont);
674 return val;
676 #endif
678 static int
679 xftfont_end_for_frame (struct frame *f)
681 XftDraw *xft_draw;
683 /* Don't do anything if display is dead */
684 if (FRAME_X_DISPLAY (f) == NULL) return 0;
686 xft_draw = font_get_frame_data (f, Qxft);
688 if (xft_draw)
690 block_input ();
691 XftDrawDestroy (xft_draw);
692 unblock_input ();
693 font_put_frame_data (f, Qxft, NULL);
695 return 0;
698 static bool
699 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
700 Lisp_Object entity)
702 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
703 FcPattern *oldpat = info->xftfont->pattern;
704 Display *display = FRAME_X_DISPLAY (f);
705 FcPattern *pat = FcPatternCreate ();
706 FcBool b1, b2;
707 bool ok = false;
708 int i1, i2, r1, r2;
710 xftfont_add_rendering_parameters (pat, entity);
711 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
713 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
714 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
715 if (r1 != r2 || b1 != b2) goto out;
716 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
717 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
718 if (r1 != r2 || b1 != b2) goto out;
719 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
720 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
721 if (r1 != r2 || b1 != b2) goto out;
722 #ifdef FC_EMBOLDEN
723 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
724 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
725 if (r1 != r2 || b1 != b2) goto out;
726 #endif
727 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
728 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
729 if (r1 != r2 || i1 != i2) goto out;
730 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
731 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
732 if (r1 != r2 || i1 != i2) goto out;
733 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
734 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
735 if (r1 != r2 || i1 != i2) goto out;
737 ok = true;
738 out:
739 FcPatternDestroy (pat);
740 return ok;
743 void
744 syms_of_xftfont (void)
746 DEFSYM (Qxft, "xft");
747 DEFSYM (QChinting, ":hinting");
748 DEFSYM (QCautohint, ":autohint");
749 DEFSYM (QChintstyle, ":hintstyle");
750 DEFSYM (QCrgba, ":rgba");
751 DEFSYM (QCembolden, ":embolden");
752 DEFSYM (QClcdfilter, ":lcdfilter");
754 DEFVAR_BOOL ("xft-font-ascent-descent-override",
755 xft_font_ascent_descent_override,
756 doc: /* Non-nil means override the ascent and descent values for Xft font driver.
757 This is needed with some fonts to correct vertical overlap of glyphs. */);
758 xft_font_ascent_descent_override = 0;
760 ascii_printable[0] = 0;
762 xftfont_driver = ftfont_driver;
763 xftfont_driver.type = Qxft;
764 xftfont_driver.get_cache = xfont_driver.get_cache;
765 xftfont_driver.list = xftfont_list;
766 xftfont_driver.match = xftfont_match;
767 xftfont_driver.open = xftfont_open;
768 xftfont_driver.close = xftfont_close;
769 xftfont_driver.prepare_face = xftfont_prepare_face;
770 xftfont_driver.done_face = xftfont_done_face;
771 xftfont_driver.has_char = xftfont_has_char;
772 xftfont_driver.encode_char = xftfont_encode_char;
773 xftfont_driver.text_extents = xftfont_text_extents;
774 xftfont_driver.draw = xftfont_draw;
775 xftfont_driver.end_for_frame = xftfont_end_for_frame;
776 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
777 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
778 xftfont_driver.shape = xftfont_shape;
779 #endif
781 register_font_driver (&xftfont_driver, NULL);