Consider Vother_window_scroll_buffer valid iff it's a live buffer.
[emacs.git] / src / xftfont.c
blob32816b97f23ba8c659c88cf2467ddae693952f05
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xft/Xft.h>
27 #include "lisp.h"
28 #include "dispextern.h"
29 #include "xterm.h"
30 #include "frame.h"
31 #include "blockinput.h"
32 #include "character.h"
33 #include "charset.h"
34 #include "composite.h"
35 #include "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
39 /* Xft font driver. */
41 Lisp_Object Qxft;
42 static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
43 QClcdfilter;
45 /* The actual structure for Xft font that can be cast to struct
46 font. */
48 struct xftfont_info
50 struct font font;
51 /* The following five members must be here in this order to be
52 compatible with struct ftfont_info (in ftfont.c). */
53 #ifdef HAVE_LIBOTF
54 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
55 OTF *otf;
56 #endif /* HAVE_LIBOTF */
57 FT_Size ft_size;
58 int index;
59 FT_Matrix matrix;
60 Display *display;
61 XftFont *xftfont;
64 /* Structure pointed by (struct face *)->extra */
66 struct xftface_info
68 XftColor xft_fg; /* color for face->foreground */
69 XftColor xft_bg; /* color for face->background */
72 /* Setup foreground and background colors of GC into FG and BG. If
73 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
74 may be NULL. */
76 static void
77 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
78 struct xftface_info *xftface_info,
79 XftColor *fg, XftColor *bg)
81 if (xftface_info && face->gc == gc)
83 *fg = xftface_info->xft_fg;
84 if (bg)
85 *bg = xftface_info->xft_bg;
87 else
89 XGCValues xgcv;
90 bool fg_done = 0, bg_done = 0;
92 block_input ();
93 XGetGCValues (FRAME_X_DISPLAY (f), gc,
94 GCForeground | GCBackground, &xgcv);
95 if (xftface_info)
97 if (xgcv.foreground == face->foreground)
98 *fg = xftface_info->xft_fg, fg_done = 1;
99 else if (xgcv.foreground == face->background)
100 *fg = xftface_info->xft_bg, fg_done = 1;
101 if (! bg)
102 bg_done = 1;
103 else if (xgcv.background == face->background)
104 *bg = xftface_info->xft_bg, bg_done = 1;
105 else if (xgcv.background == face->foreground)
106 *bg = xftface_info->xft_fg, bg_done = 1;
109 if (! (fg_done & bg_done))
111 XColor colors[2];
113 colors[0].pixel = fg->pixel = xgcv.foreground;
114 if (bg)
115 colors[1].pixel = bg->pixel = xgcv.background;
116 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
117 bg ? 2 : 1);
118 fg->color.alpha = 0xFFFF;
119 fg->color.red = colors[0].red;
120 fg->color.green = colors[0].green;
121 fg->color.blue = colors[0].blue;
122 if (bg)
124 bg->color.alpha = 0xFFFF;
125 bg->color.red = colors[1].red;
126 bg->color.green = colors[1].green;
127 bg->color.blue = colors[1].blue;
130 unblock_input ();
135 struct font_driver xftfont_driver;
137 static Lisp_Object
138 xftfont_list (struct frame *f, Lisp_Object spec)
140 Lisp_Object list = ftfont_driver.list (f, spec), tail;
142 for (tail = list; CONSP (tail); tail = XCDR (tail))
143 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
144 return list;
147 static Lisp_Object
148 xftfont_match (struct frame *f, Lisp_Object spec)
150 Lisp_Object entity = ftfont_driver.match (f, spec);
152 if (! NILP (entity))
153 ASET (entity, FONT_TYPE_INDEX, Qxft);
154 return entity;
157 static FcChar8 ascii_printable[95];
159 static void
160 xftfont_fix_match (FcPattern *pat, FcPattern *match)
162 /* These values are not used for matching (except antialias), but for
163 rendering, so make sure they are carried over to the match.
164 We also put antialias here because most fonts are antialiased, so
165 the match will have antialias true. */
167 FcBool b = FcTrue;
168 int i;
169 double dpi;
171 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
172 if (! b)
174 FcPatternDel (match, FC_ANTIALIAS);
175 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
177 FcPatternGetBool (pat, FC_HINTING, 0, &b);
178 if (! b)
180 FcPatternDel (match, FC_HINTING);
181 FcPatternAddBool (match, FC_HINTING, FcFalse);
183 #ifndef FC_HINT_STYLE
184 # define FC_HINT_STYLE "hintstyle"
185 #endif
186 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
188 FcPatternDel (match, FC_HINT_STYLE);
189 FcPatternAddInteger (match, FC_HINT_STYLE, i);
191 #ifndef FC_LCD_FILTER
192 /* Older fontconfig versions don't have FC_LCD_FILTER. */
193 #define FC_LCD_FILTER "lcdfilter"
194 #endif
195 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
197 FcPatternDel (match, FC_LCD_FILTER);
198 FcPatternAddInteger (match, FC_LCD_FILTER, i);
200 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
202 FcPatternDel (match, FC_RGBA);
203 FcPatternAddInteger (match, FC_RGBA, i);
205 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
207 FcPatternDel (match, FC_DPI);
208 FcPatternAddDouble (match, FC_DPI, dpi);
212 static void
213 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
215 Lisp_Object tail;
216 int ival;
218 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
220 Lisp_Object key = XCAR (XCAR (tail));
221 Lisp_Object val = XCDR (XCAR (tail));
223 if (EQ (key, QCantialias))
224 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
225 else if (EQ (key, QChinting))
226 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
227 else if (EQ (key, QCautohint))
228 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
229 else if (EQ (key, QChintstyle))
231 if (INTEGERP (val))
232 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
233 else if (SYMBOLP (val)
234 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
235 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
237 else if (EQ (key, QCrgba))
239 if (INTEGERP (val))
240 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
241 else if (SYMBOLP (val)
242 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
243 FcPatternAddInteger (pat, FC_RGBA, ival);
245 else if (EQ (key, QClcdfilter))
247 if (INTEGERP (val))
248 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
249 else if (SYMBOLP (val)
250 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
251 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
253 #ifdef FC_EMBOLDEN
254 else if (EQ (key, QCembolden))
255 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
256 #endif
260 static Lisp_Object
261 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
263 FcResult result;
264 Display *display = FRAME_X_DISPLAY (f);
265 Lisp_Object val, filename, idx, font_object;
266 FcPattern *pat = NULL, *match;
267 struct xftfont_info *xftfont_info = NULL;
268 struct font *font;
269 double size = 0;
270 XftFont *xftfont = NULL;
271 int spacing;
272 char name[256];
273 int len, i;
274 XGlyphInfo extents;
275 FT_Face ft_face;
276 FcMatrix *matrix;
278 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
279 if (! CONSP (val))
280 return Qnil;
281 val = XCDR (val);
282 filename = XCAR (val);
283 idx = XCDR (val);
284 size = XINT (AREF (entity, FONT_SIZE_INDEX));
285 if (size == 0)
286 size = pixel_size;
287 pat = FcPatternCreate ();
288 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
289 i = FONT_SLANT_NUMERIC (entity) - 100;
290 if (i < 0) i = 0;
291 FcPatternAddInteger (pat, FC_SLANT, i);
292 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
293 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
294 val = AREF (entity, FONT_FAMILY_INDEX);
295 if (! NILP (val))
296 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
297 val = AREF (entity, FONT_FOUNDRY_INDEX);
298 if (! NILP (val))
299 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
300 val = AREF (entity, FONT_SPACING_INDEX);
301 if (! NILP (val))
302 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
303 val = AREF (entity, FONT_DPI_INDEX);
304 if (! NILP (val))
306 double dbl = XINT (val);
308 FcPatternAddDouble (pat, FC_DPI, dbl);
310 val = AREF (entity, FONT_AVGWIDTH_INDEX);
311 if (INTEGERP (val) && XINT (val) == 0)
312 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
313 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
314 over 10x20-ISO8859-1.pcf.gz). */
315 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
317 xftfont_add_rendering_parameters (pat, entity);
319 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
320 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
323 block_input ();
324 /* Make sure that the Xrender extension is added before the Xft one.
325 Otherwise, the close-display hook set by Xft is called after the
326 one for Xrender, and the former tries to re-add the latter. This
327 results in inconsistency of internal states and leads to X
328 protocol error when one reconnects to the same X server.
329 (Bug#1696) */
331 int event_base, error_base;
332 XRenderQueryExtension (display, &event_base, &error_base);
335 /* Substitute in values from X resources and XftDefaultSet. */
336 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
337 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
338 xftfont_fix_match (pat, match);
340 FcPatternDestroy (pat);
341 xftfont = XftFontOpenPattern (display, match);
342 if (!xftfont)
344 unblock_input ();
345 XftPatternDestroy (match);
346 return Qnil;
348 ft_face = XftLockFace (xftfont);
349 unblock_input ();
351 /* We should not destroy PAT here because it is kept in XFTFONT and
352 destroyed automatically when XFTFONT is closed. */
353 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
354 ASET (font_object, FONT_TYPE_INDEX, Qxft);
355 len = font_unparse_xlfd (entity, size, name, 256);
356 if (len > 0)
357 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
358 len = font_unparse_fcname (entity, size, name, 256);
359 if (len > 0)
360 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
361 else
362 ASET (font_object, FONT_FULLNAME_INDEX,
363 AREF (font_object, FONT_NAME_INDEX));
364 ASET (font_object, FONT_FILE_INDEX, filename);
365 ASET (font_object, FONT_FORMAT_INDEX,
366 ftfont_font_format (xftfont->pattern, filename));
367 font = XFONT_OBJECT (font_object);
368 font->pixel_size = size;
369 font->driver = &xftfont_driver;
370 font->encoding_charset = font->repertory_charset = -1;
372 xftfont_info = (struct xftfont_info *) font;
373 xftfont_info->display = display;
374 xftfont_info->xftfont = xftfont;
375 /* This means that there's no need of transformation. */
376 xftfont_info->matrix.xx = 0;
377 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
378 == FcResultMatch)
380 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
381 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
382 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
383 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
385 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
386 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
387 else
388 spacing = FC_PROPORTIONAL;
389 if (! ascii_printable[0])
391 int ch;
392 for (ch = 0; ch < 95; ch++)
393 ascii_printable[ch] = ' ' + ch;
395 block_input ();
397 /* Unfortunately Xft doesn't provide a way to get minimum char
398 width. So, we set min_width to space_width. */
400 if (spacing != FC_PROPORTIONAL
401 #ifdef FC_DUAL
402 && spacing != FC_DUAL
403 #endif /* FC_DUAL */
406 font->min_width = font->max_width = font->average_width
407 = font->space_width = xftfont->max_advance_width;
408 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
410 else
412 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
413 font->min_width = font->max_width = font->space_width
414 = extents.xOff;
415 if (font->space_width <= 0)
416 /* dirty workaround */
417 font->space_width = pixel_size;
418 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
419 font->average_width = (font->space_width + extents.xOff) / 95;
421 unblock_input ();
423 font->ascent = xftfont->ascent;
424 font->descent = xftfont->descent;
425 if (pixel_size >= 5)
427 /* The above condition is a dirty workaround because
428 XftTextExtents8 behaves strangely for some fonts
429 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
430 if (font->ascent < extents.y)
431 font->ascent = extents.y;
432 if (font->descent < extents.height - extents.y)
433 font->descent = extents.height - extents.y;
435 font->height = font->ascent + font->descent;
437 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
439 int upEM = ft_face->units_per_EM;
441 font->underline_position = -ft_face->underline_position * size / upEM;
442 font->underline_thickness = ft_face->underline_thickness * size / upEM;
443 if (font->underline_thickness > 2)
444 font->underline_position -= font->underline_thickness / 2;
446 else
448 font->underline_position = -1;
449 font->underline_thickness = 0;
451 #ifdef HAVE_LIBOTF
452 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
453 xftfont_info->otf = NULL;
454 #endif /* HAVE_LIBOTF */
455 xftfont_info->ft_size = ft_face->size;
457 font->baseline_offset = 0;
458 font->relative_compose = 0;
459 font->default_ascent = 0;
460 font->vertical_centering = 0;
461 #ifdef FT_BDF_H
462 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
464 BDF_PropertyRec rec;
466 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
467 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
468 font->baseline_offset = rec.u.integer;
469 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
470 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
471 font->relative_compose = rec.u.integer;
472 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
473 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
474 font->default_ascent = rec.u.integer;
476 #endif
478 return font_object;
481 static void
482 xftfont_close (struct font *font)
484 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
486 #ifdef HAVE_LIBOTF
487 if (xftfont_info->otf)
489 OTF_close (xftfont_info->otf);
490 xftfont_info->otf = NULL;
492 #endif
494 /* See comment in xfont_close. */
495 if (xftfont_info->xftfont
496 && x_display_info_for_display (xftfont_info->display))
498 block_input ();
499 XftUnlockFace (xftfont_info->xftfont);
500 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
501 unblock_input ();
502 xftfont_info->xftfont = NULL;
506 static int
507 xftfont_prepare_face (struct frame *f, struct face *face)
509 struct xftface_info *xftface_info;
511 #if 0
512 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
513 if (face != face->ascii_face)
515 face->extra = face->ascii_face->extra;
516 return 0;
518 #endif
520 xftface_info = malloc (sizeof *xftface_info);
521 if (! xftface_info)
522 return -1;
523 xftfont_get_colors (f, face, face->gc, NULL,
524 &xftface_info->xft_fg, &xftface_info->xft_bg);
525 face->extra = xftface_info;
526 return 0;
529 static void
530 xftfont_done_face (struct frame *f, struct face *face)
532 struct xftface_info *xftface_info;
534 #if 0
535 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
536 if (face != face->ascii_face
537 || ! face->extra)
538 return;
539 #endif
541 xftface_info = (struct xftface_info *) face->extra;
542 if (xftface_info)
544 free (xftface_info);
545 face->extra = NULL;
549 static int
550 xftfont_has_char (Lisp_Object font, int c)
552 struct xftfont_info *xftfont_info;
553 struct charset *cs = NULL;
555 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
556 && charset_jisx0208 >= 0)
557 cs = CHARSET_FROM_ID (charset_jisx0208);
558 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
559 && charset_ksc5601 >= 0)
560 cs = CHARSET_FROM_ID (charset_ksc5601);
561 if (cs)
562 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
564 if (FONT_ENTITY_P (font))
565 return ftfont_driver.has_char (font, c);
566 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
567 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
568 (FcChar32) c) == FcTrue);
571 static unsigned
572 xftfont_encode_char (struct font *font, int c)
574 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
575 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
576 (FcChar32) c);
578 return (code ? code : FONT_INVALID_CODE);
581 static int
582 xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
584 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
585 XGlyphInfo extents;
587 block_input ();
588 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
589 &extents);
590 unblock_input ();
591 if (metrics)
593 metrics->lbearing = - extents.x;
594 metrics->rbearing = - extents.x + extents.width;
595 metrics->width = extents.xOff;
596 metrics->ascent = extents.y;
597 metrics->descent = extents.height - extents.y;
599 return extents.xOff;
602 static XftDraw *
603 xftfont_get_xft_draw (struct frame *f)
605 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
607 if (! xft_draw)
609 block_input ();
610 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
611 FRAME_X_WINDOW (f),
612 FRAME_X_VISUAL (f),
613 FRAME_X_COLORMAP (f));
614 unblock_input ();
615 eassert (xft_draw != NULL);
616 font_put_frame_data (f, &xftfont_driver, xft_draw);
618 return xft_draw;
621 static int
622 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
623 bool with_background)
625 struct frame *f = s->f;
626 struct face *face = s->face;
627 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
628 struct xftface_info *xftface_info = NULL;
629 XftDraw *xft_draw = xftfont_get_xft_draw (f);
630 FT_UInt *code;
631 XftColor fg, bg;
632 int len = to - from;
633 int i;
635 if (s->font == face->font)
636 xftface_info = (struct xftface_info *) face->extra;
637 xftfont_get_colors (f, face, s->gc, xftface_info,
638 &fg, with_background ? &bg : NULL);
639 block_input ();
640 if (s->num_clips > 0)
641 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
642 else
643 XftDrawSetClip (xft_draw, NULL);
645 if (with_background)
646 XftDrawRect (xft_draw, &bg,
647 x, y - s->font->ascent, s->width, s->font->height);
648 code = alloca (sizeof (FT_UInt) * len);
649 for (i = 0; i < len; i++)
650 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
651 | XCHAR2B_BYTE2 (s->char2b + from + i));
653 if (s->padding_p)
654 for (i = 0; i < len; i++)
655 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
656 x + i, y, code + i, 1);
657 else
658 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
659 x, y, code, len);
660 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;
670 struct xftfont_info *xftfont_info;
671 FT_Face ft_face;
672 Lisp_Object val;
674 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
675 xftfont_info = (struct xftfont_info *) font;
676 ft_face = XftLockFace (xftfont_info->xftfont);
677 xftfont_info->ft_size = ft_face->size;
678 val = ftfont_driver.shape (lgstring);
679 XftUnlockFace (xftfont_info->xftfont);
680 return val;
682 #endif
684 static int
685 xftfont_end_for_frame (struct frame *f)
687 XftDraw *xft_draw;
689 /* Don't do anything if display is dead */
690 if (FRAME_X_DISPLAY (f) == NULL) return 0;
692 xft_draw = font_get_frame_data (f, &xftfont_driver);
694 if (xft_draw)
696 block_input ();
697 XftDrawDestroy (xft_draw);
698 unblock_input ();
699 font_put_frame_data (f, &xftfont_driver, NULL);
701 return 0;
704 static bool
705 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
706 Lisp_Object entity)
708 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
709 FcPattern *oldpat = info->xftfont->pattern;
710 Display *display = FRAME_X_DISPLAY (f);
711 FcPattern *pat = FcPatternCreate ();
712 FcBool b1, b2;
713 bool ok = 0;
714 int i1, i2, r1, r2;
716 xftfont_add_rendering_parameters (pat, entity);
717 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
719 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
720 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
721 if (r1 != r2 || b1 != b2) goto out;
722 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
723 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
724 if (r1 != r2 || b1 != b2) goto out;
725 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
726 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
727 if (r1 != r2 || b1 != b2) goto out;
728 #ifdef FC_EMBOLDEN
729 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
730 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
731 if (r1 != r2 || b1 != b2) goto out;
732 #endif
733 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
734 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
735 if (r1 != r2 || i1 != i2) goto out;
736 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
737 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
738 if (r1 != r2 || i1 != i2) goto out;
739 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
740 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
741 if (r1 != r2 || i1 != i2) goto out;
743 ok = 1;
744 out:
745 FcPatternDestroy (pat);
746 return ok;
749 void
750 syms_of_xftfont (void)
752 DEFSYM (Qxft, "xft");
753 DEFSYM (QChinting, ":hinting");
754 DEFSYM (QCautohint, ":autohint");
755 DEFSYM (QChintstyle, ":hintstyle");
756 DEFSYM (QCrgba, ":rgba");
757 DEFSYM (QCembolden, ":embolden");
758 DEFSYM (QClcdfilter, ":lcdfilter");
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);