Fix earlier NEWS change
[emacs.git] / src / xftfont.c
blob372ed87705fce6a81c343a09c588a5428c5ec24b
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2012 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 casted 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 int screen;
62 XftFont *xftfont;
65 /* Structure pointed by (struct face *)->extra */
67 struct xftface_info
69 XftColor xft_fg; /* color for face->foreground */
70 XftColor xft_bg; /* color for face->background */
73 static void xftfont_get_colors (FRAME_PTR, struct face *, GC gc,
74 struct xftface_info *,
75 XftColor *fg, XftColor *bg);
78 /* Setup foreground and background colors of GC into FG and BG. If
79 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
80 may be NULL. */
82 static void
83 xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *xftface_info, XftColor *fg, XftColor *bg)
85 if (xftface_info && face->gc == gc)
87 *fg = xftface_info->xft_fg;
88 if (bg)
89 *bg = xftface_info->xft_bg;
91 else
93 XGCValues xgcv;
94 bool fg_done = 0, bg_done = 0;
96 block_input ();
97 XGetGCValues (FRAME_X_DISPLAY (f), gc,
98 GCForeground | GCBackground, &xgcv);
99 if (xftface_info)
101 if (xgcv.foreground == face->foreground)
102 *fg = xftface_info->xft_fg, fg_done = 1;
103 else if (xgcv.foreground == face->background)
104 *fg = xftface_info->xft_bg, fg_done = 1;
105 if (! bg)
106 bg_done = 1;
107 else if (xgcv.background == face->background)
108 *bg = xftface_info->xft_bg, bg_done = 1;
109 else if (xgcv.background == face->foreground)
110 *bg = xftface_info->xft_fg, bg_done = 1;
113 if (! (fg_done & bg_done))
115 XColor colors[2];
117 colors[0].pixel = fg->pixel = xgcv.foreground;
118 if (bg)
119 colors[1].pixel = bg->pixel = xgcv.background;
120 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
121 bg ? 2 : 1);
122 fg->color.alpha = 0xFFFF;
123 fg->color.red = colors[0].red;
124 fg->color.green = colors[0].green;
125 fg->color.blue = colors[0].blue;
126 if (bg)
128 bg->color.alpha = 0xFFFF;
129 bg->color.red = colors[1].red;
130 bg->color.green = colors[1].green;
131 bg->color.blue = colors[1].blue;
134 unblock_input ();
139 struct font_driver xftfont_driver;
141 static Lisp_Object
142 xftfont_list (Lisp_Object frame, Lisp_Object spec)
144 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
146 for (tail = list; CONSP (tail); tail = XCDR (tail))
147 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
148 return list;
151 static Lisp_Object
152 xftfont_match (Lisp_Object frame, Lisp_Object spec)
154 Lisp_Object entity = ftfont_driver.match (frame, spec);
156 if (! NILP (entity))
157 ASET (entity, FONT_TYPE_INDEX, Qxft);
158 return entity;
161 static FcChar8 ascii_printable[95];
163 static void
164 xftfont_fix_match (FcPattern *pat, FcPattern *match)
166 /* These values are not used for matching (except antialias), but for
167 rendering, so make sure they are carried over to the match.
168 We also put antialias here because most fonts are antialiased, so
169 the match will have antialias true. */
171 FcBool b = FcTrue;
172 int i;
173 double dpi;
175 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
176 if (! b)
178 FcPatternDel (match, FC_ANTIALIAS);
179 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
181 FcPatternGetBool (pat, FC_HINTING, 0, &b);
182 if (! b)
184 FcPatternDel (match, FC_HINTING);
185 FcPatternAddBool (match, FC_HINTING, FcFalse);
187 #ifndef FC_HINT_STYLE
188 # define FC_HINT_STYLE "hintstyle"
189 #endif
190 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
192 FcPatternDel (match, FC_HINT_STYLE);
193 FcPatternAddInteger (match, FC_HINT_STYLE, i);
195 #ifndef FC_LCD_FILTER
196 /* Older fontconfig versions don't have FC_LCD_FILTER. */
197 #define FC_LCD_FILTER "lcdfilter"
198 #endif
199 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
201 FcPatternDel (match, FC_LCD_FILTER);
202 FcPatternAddInteger (match, FC_LCD_FILTER, i);
204 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
206 FcPatternDel (match, FC_RGBA);
207 FcPatternAddInteger (match, FC_RGBA, i);
209 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
211 FcPatternDel (match, FC_DPI);
212 FcPatternAddDouble (match, FC_DPI, dpi);
216 static void
217 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
219 Lisp_Object tail;
220 int ival;
222 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
224 Lisp_Object key = XCAR (XCAR (tail));
225 Lisp_Object val = XCDR (XCAR (tail));
227 if (EQ (key, QCantialias))
228 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
229 else if (EQ (key, QChinting))
230 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
231 else if (EQ (key, QCautohint))
232 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
233 else if (EQ (key, QChintstyle))
235 if (INTEGERP (val))
236 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
237 else if (SYMBOLP (val)
238 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
239 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
241 else if (EQ (key, QCrgba))
243 if (INTEGERP (val))
244 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
245 else if (SYMBOLP (val)
246 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
247 FcPatternAddInteger (pat, FC_RGBA, ival);
249 else if (EQ (key, QClcdfilter))
251 if (INTEGERP (val))
252 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
253 else if (SYMBOLP (val)
254 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
255 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
257 #ifdef FC_EMBOLDEN
258 else if (EQ (key, QCembolden))
259 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
260 #endif
264 static Lisp_Object
265 xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
267 FcResult result;
268 Display *display = FRAME_X_DISPLAY (f);
269 Lisp_Object val, filename, idx, font_object;
270 FcPattern *pat = NULL, *match;
271 struct xftfont_info *xftfont_info = NULL;
272 struct font *font;
273 double size = 0;
274 XftFont *xftfont = NULL;
275 int spacing;
276 char name[256];
277 int len, i;
278 XGlyphInfo extents;
279 FT_Face ft_face;
280 FcMatrix *matrix;
282 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
283 if (! CONSP (val))
284 return Qnil;
285 val = XCDR (val);
286 filename = XCAR (val);
287 idx = XCDR (val);
288 size = XINT (AREF (entity, FONT_SIZE_INDEX));
289 if (size == 0)
290 size = pixel_size;
291 pat = FcPatternCreate ();
292 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
293 i = FONT_SLANT_NUMERIC (entity) - 100;
294 if (i < 0) i = 0;
295 FcPatternAddInteger (pat, FC_SLANT, i);
296 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
297 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
298 val = AREF (entity, FONT_FAMILY_INDEX);
299 if (! NILP (val))
300 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
301 val = AREF (entity, FONT_FOUNDRY_INDEX);
302 if (! NILP (val))
303 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
304 val = AREF (entity, FONT_SPACING_INDEX);
305 if (! NILP (val))
306 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
307 val = AREF (entity, FONT_DPI_INDEX);
308 if (! NILP (val))
310 double dbl = XINT (val);
312 FcPatternAddDouble (pat, FC_DPI, dbl);
314 val = AREF (entity, FONT_AVGWIDTH_INDEX);
315 if (INTEGERP (val) && XINT (val) == 0)
316 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
317 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
318 over 10x20-ISO8859-1.pcf.gz). */
319 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
321 xftfont_add_rendering_parameters (pat, entity);
323 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
324 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
327 block_input ();
328 /* Make sure that the Xrender extension is added before the Xft one.
329 Otherwise, the close-display hook set by Xft is called after the
330 one for Xrender, and the former tries to re-add the latter. This
331 results in inconsistency of internal states and leads to X
332 protocol error when one reconnects to the same X server.
333 (Bug#1696) */
335 int event_base, error_base;
336 XRenderQueryExtension (display, &event_base, &error_base);
339 /* Substitute in values from X resources and XftDefaultSet. */
340 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
341 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
342 xftfont_fix_match (pat, match);
344 FcPatternDestroy (pat);
345 xftfont = XftFontOpenPattern (display, match);
346 if (!xftfont)
348 unblock_input ();
349 XftPatternDestroy (match);
350 return Qnil;
352 ft_face = XftLockFace (xftfont);
353 unblock_input ();
355 /* We should not destroy PAT here because it is kept in XFTFONT and
356 destroyed automatically when XFTFONT is closed. */
357 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
358 ASET (font_object, FONT_TYPE_INDEX, Qxft);
359 len = font_unparse_xlfd (entity, size, name, 256);
360 if (len > 0)
361 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
362 len = font_unparse_fcname (entity, size, name, 256);
363 if (len > 0)
364 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
365 else
366 ASET (font_object, FONT_FULLNAME_INDEX,
367 AREF (font_object, FONT_NAME_INDEX));
368 ASET (font_object, FONT_FILE_INDEX, filename);
369 ASET (font_object, FONT_FORMAT_INDEX,
370 ftfont_font_format (xftfont->pattern, filename));
371 font = XFONT_OBJECT (font_object);
372 font->pixel_size = pixel_size;
373 font->driver = &xftfont_driver;
374 font->encoding_charset = font->repertory_charset = -1;
376 xftfont_info = (struct xftfont_info *) font;
377 xftfont_info->display = display;
378 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
379 xftfont_info->xftfont = xftfont;
380 /* This means that there's no need of transformation. */
381 xftfont_info->matrix.xx = 0;
382 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
383 == FcResultMatch)
385 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
386 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
387 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
388 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
390 font->pixel_size = size;
391 font->driver = &xftfont_driver;
392 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
393 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
394 else
395 spacing = FC_PROPORTIONAL;
396 if (! ascii_printable[0])
398 int ch;
399 for (ch = 0; ch < 95; ch++)
400 ascii_printable[ch] = ' ' + ch;
402 block_input ();
404 /* Unfortunately Xft doesn't provide a way to get minimum char
405 width. So, we set min_width to space_width. */
407 if (spacing != FC_PROPORTIONAL
408 #ifdef FC_DUAL
409 && spacing != FC_DUAL
410 #endif /* FC_DUAL */
413 font->min_width = font->max_width = font->average_width
414 = font->space_width = xftfont->max_advance_width;
415 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
417 else
419 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
420 font->min_width = font->max_width = font->space_width
421 = extents.xOff;
422 if (font->space_width <= 0)
423 /* dirty workaround */
424 font->space_width = pixel_size;
425 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
426 font->average_width = (font->space_width + extents.xOff) / 95;
428 unblock_input ();
430 font->ascent = xftfont->ascent;
431 font->descent = xftfont->descent;
432 if (pixel_size >= 5)
434 /* The above condition is a dirty workaround because
435 XftTextExtents8 behaves strangely for some fonts
436 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
437 if (font->ascent < extents.y)
438 font->ascent = extents.y;
439 if (font->descent < extents.height - extents.y)
440 font->descent = extents.height - extents.y;
442 font->height = font->ascent + font->descent;
444 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
446 int upEM = ft_face->units_per_EM;
448 font->underline_position = -ft_face->underline_position * size / upEM;
449 font->underline_thickness = ft_face->underline_thickness * size / upEM;
450 if (font->underline_thickness > 2)
451 font->underline_position -= font->underline_thickness / 2;
453 else
455 font->underline_position = -1;
456 font->underline_thickness = 0;
458 #ifdef HAVE_LIBOTF
459 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
460 xftfont_info->otf = NULL;
461 #endif /* HAVE_LIBOTF */
462 xftfont_info->ft_size = ft_face->size;
464 font->baseline_offset = 0;
465 font->relative_compose = 0;
466 font->default_ascent = 0;
467 font->vertical_centering = 0;
468 #ifdef FT_BDF_H
469 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
471 BDF_PropertyRec rec;
473 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
474 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
475 font->baseline_offset = rec.u.integer;
476 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
477 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
478 font->relative_compose = rec.u.integer;
479 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
480 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
481 font->default_ascent = rec.u.integer;
483 #endif
485 return font_object;
488 static void
489 xftfont_close (FRAME_PTR f, struct font *font)
491 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
493 #ifdef HAVE_LIBOTF
494 if (xftfont_info->otf)
495 OTF_close (xftfont_info->otf);
496 #endif
497 block_input ();
498 XftUnlockFace (xftfont_info->xftfont);
499 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
500 unblock_input ();
503 static int
504 xftfont_prepare_face (FRAME_PTR f, struct face *face)
506 struct xftface_info *xftface_info;
508 #if 0
509 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
510 if (face != face->ascii_face)
512 face->extra = face->ascii_face->extra;
513 return 0;
515 #endif
517 xftface_info = malloc (sizeof *xftface_info);
518 if (! xftface_info)
519 return -1;
520 xftfont_get_colors (f, face, face->gc, NULL,
521 &xftface_info->xft_fg, &xftface_info->xft_bg);
522 face->extra = xftface_info;
523 return 0;
526 static void
527 xftfont_done_face (FRAME_PTR f, struct face *face)
529 struct xftface_info *xftface_info;
531 #if 0
532 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
533 if (face != face->ascii_face
534 || ! face->extra)
535 return;
536 #endif
538 xftface_info = (struct xftface_info *) face->extra;
539 if (xftface_info)
541 free (xftface_info);
542 face->extra = NULL;
546 static int
547 xftfont_has_char (Lisp_Object font, int c)
549 struct xftfont_info *xftfont_info;
550 struct charset *cs = NULL;
552 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
553 && charset_jisx0208 >= 0)
554 cs = CHARSET_FROM_ID (charset_jisx0208);
555 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
556 && charset_ksc5601 >= 0)
557 cs = CHARSET_FROM_ID (charset_ksc5601);
558 if (cs)
559 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
561 if (FONT_ENTITY_P (font))
562 return ftfont_driver.has_char (font, c);
563 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
564 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
565 (FcChar32) c) == FcTrue);
568 static unsigned
569 xftfont_encode_char (struct font *font, int c)
571 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
572 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
573 (FcChar32) c);
575 return (code ? code : FONT_INVALID_CODE);
578 static int
579 xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
581 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
582 XGlyphInfo extents;
584 block_input ();
585 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
586 &extents);
587 unblock_input ();
588 if (metrics)
590 metrics->lbearing = - extents.x;
591 metrics->rbearing = - extents.x + extents.width;
592 metrics->width = extents.xOff;
593 metrics->ascent = extents.y;
594 metrics->descent = extents.height - extents.y;
596 return extents.xOff;
599 static XftDraw *
600 xftfont_get_xft_draw (FRAME_PTR f)
602 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
604 if (! xft_draw)
606 block_input ();
607 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
608 FRAME_X_WINDOW (f),
609 FRAME_X_VISUAL (f),
610 FRAME_X_COLORMAP (f));
611 unblock_input ();
612 eassert (xft_draw != NULL);
613 font_put_frame_data (f, &xftfont_driver, xft_draw);
615 return xft_draw;
618 static int
619 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
620 bool with_background)
622 FRAME_PTR f = s->f;
623 struct face *face = s->face;
624 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
625 struct xftface_info *xftface_info = NULL;
626 XftDraw *xft_draw = xftfont_get_xft_draw (f);
627 FT_UInt *code;
628 XftColor fg, bg;
629 int len = to - from;
630 int i;
632 if (s->font == face->font)
633 xftface_info = (struct xftface_info *) face->extra;
634 xftfont_get_colors (f, face, s->gc, xftface_info,
635 &fg, with_background ? &bg : NULL);
636 block_input ();
637 if (s->num_clips > 0)
638 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
639 else
640 XftDrawSetClip (xft_draw, NULL);
642 if (with_background)
643 XftDrawRect (xft_draw, &bg,
644 x, y - s->font->ascent, s->width, s->font->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 unblock_input ();
659 return len;
662 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
663 static Lisp_Object
664 xftfont_shape (Lisp_Object lgstring)
666 struct font *font;
667 struct xftfont_info *xftfont_info;
668 FT_Face ft_face;
669 Lisp_Object val;
671 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
672 xftfont_info = (struct xftfont_info *) font;
673 ft_face = XftLockFace (xftfont_info->xftfont);
674 xftfont_info->ft_size = ft_face->size;
675 val = ftfont_driver.shape (lgstring);
676 XftUnlockFace (xftfont_info->xftfont);
677 return val;
679 #endif
681 static int
682 xftfont_end_for_frame (FRAME_PTR f)
684 XftDraw *xft_draw;
686 /* Don't do anything if display is dead */
687 if (FRAME_X_DISPLAY (f) == NULL) return 0;
689 xft_draw = font_get_frame_data (f, &xftfont_driver);
691 if (xft_draw)
693 block_input ();
694 XftDrawDestroy (xft_draw);
695 unblock_input ();
696 font_put_frame_data (f, &xftfont_driver, NULL);
698 return 0;
701 static bool
702 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
703 Lisp_Object entity)
705 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
706 FcPattern *oldpat = info->xftfont->pattern;
707 Display *display = FRAME_X_DISPLAY (f);
708 FcPattern *pat = FcPatternCreate ();
709 FcBool b1, b2;
710 bool ok = 0;
711 int i1, i2, r1, r2;
713 xftfont_add_rendering_parameters (pat, entity);
714 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
716 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
717 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
718 if (r1 != r2 || b1 != b2) goto out;
719 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
720 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
721 if (r1 != r2 || b1 != b2) goto out;
722 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
723 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
724 if (r1 != r2 || b1 != b2) goto out;
725 #ifdef FC_EMBOLDEN
726 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
727 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
728 if (r1 != r2 || b1 != b2) goto out;
729 #endif
730 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
731 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
732 if (r1 != r2 || i1 != i2) goto out;
733 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
734 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
735 if (r1 != r2 || i1 != i2) goto out;
736 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
737 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
738 if (r1 != r2 || i1 != i2) goto out;
740 ok = 1;
741 out:
742 FcPatternDestroy (pat);
743 return ok;
746 void
747 syms_of_xftfont (void)
749 DEFSYM (Qxft, "xft");
750 DEFSYM (QChinting, ":hinting");
751 DEFSYM (QCautohint, ":autohint");
752 DEFSYM (QChintstyle, ":hintstyle");
753 DEFSYM (QCrgba, ":rgba");
754 DEFSYM (QCembolden, ":embolden");
755 DEFSYM (QClcdfilter, ":lcdfilter");
757 ascii_printable[0] = 0;
759 xftfont_driver = ftfont_driver;
760 xftfont_driver.type = Qxft;
761 xftfont_driver.get_cache = xfont_driver.get_cache;
762 xftfont_driver.list = xftfont_list;
763 xftfont_driver.match = xftfont_match;
764 xftfont_driver.open = xftfont_open;
765 xftfont_driver.close = xftfont_close;
766 xftfont_driver.prepare_face = xftfont_prepare_face;
767 xftfont_driver.done_face = xftfont_done_face;
768 xftfont_driver.has_char = xftfont_has_char;
769 xftfont_driver.encode_char = xftfont_encode_char;
770 xftfont_driver.text_extents = xftfont_text_extents;
771 xftfont_driver.draw = xftfont_draw;
772 xftfont_driver.end_for_frame = xftfont_end_for_frame;
773 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
774 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
775 xftfont_driver.shape = xftfont_shape;
776 #endif
778 register_font_driver (&xftfont_driver, NULL);