* process.h (PSET): Remove.
[emacs.git] / src / xftfont.c
blob5e60ab0c4d30bd2cfd2cfe1db2d68336ce962473
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 <setjmp.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xft/Xft.h>
28 #include "lisp.h"
29 #include "dispextern.h"
30 #include "xterm.h"
31 #include "frame.h"
32 #include "blockinput.h"
33 #include "character.h"
34 #include "charset.h"
35 #include "composite.h"
36 #include "fontset.h"
37 #include "font.h"
38 #include "ftfont.h"
40 /* Xft font driver. */
42 Lisp_Object Qxft;
43 static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
44 QClcdfilter;
46 /* The actual structure for Xft font that can be casted to struct
47 font. */
49 struct xftfont_info
51 struct font font;
52 /* The following five members must be here in this order to be
53 compatible with struct ftfont_info (in ftfont.c). */
54 #ifdef HAVE_LIBOTF
55 int maybe_otf; /* Flag to tell if this may be OTF or not. */
56 OTF *otf;
57 #endif /* HAVE_LIBOTF */
58 FT_Size ft_size;
59 int index;
60 FT_Matrix matrix;
61 Display *display;
62 int screen;
63 XftFont *xftfont;
66 /* Structure pointed by (struct face *)->extra */
68 struct xftface_info
70 XftColor xft_fg; /* color for face->foreground */
71 XftColor xft_bg; /* color for face->background */
74 static void xftfont_get_colors (FRAME_PTR, struct face *, GC gc,
75 struct xftface_info *,
76 XftColor *fg, XftColor *bg);
79 /* Setup foreground and background colors of GC into FG and BG. If
80 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
81 may be NULL. */
83 static void
84 xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *xftface_info, XftColor *fg, XftColor *bg)
86 if (xftface_info && face->gc == gc)
88 *fg = xftface_info->xft_fg;
89 if (bg)
90 *bg = xftface_info->xft_bg;
92 else
94 XGCValues xgcv;
95 int fg_done = 0, bg_done = 0;
97 BLOCK_INPUT;
98 XGetGCValues (FRAME_X_DISPLAY (f), gc,
99 GCForeground | GCBackground, &xgcv);
100 if (xftface_info)
102 if (xgcv.foreground == face->foreground)
103 *fg = xftface_info->xft_fg, fg_done = 1;
104 else if (xgcv.foreground == face->background)
105 *fg = xftface_info->xft_bg, fg_done = 1;
106 if (! bg)
107 bg_done = 1;
108 else if (xgcv.background == face->background)
109 *bg = xftface_info->xft_bg, bg_done = 1;
110 else if (xgcv.background == face->foreground)
111 *bg = xftface_info->xft_fg, bg_done = 1;
114 if (fg_done + bg_done < 2)
116 XColor colors[2];
118 colors[0].pixel = fg->pixel = xgcv.foreground;
119 if (bg)
120 colors[1].pixel = bg->pixel = xgcv.background;
121 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
122 bg ? 2 : 1);
123 fg->color.alpha = 0xFFFF;
124 fg->color.red = colors[0].red;
125 fg->color.green = colors[0].green;
126 fg->color.blue = colors[0].blue;
127 if (bg)
129 bg->color.alpha = 0xFFFF;
130 bg->color.red = colors[1].red;
131 bg->color.green = colors[1].green;
132 bg->color.blue = colors[1].blue;
135 UNBLOCK_INPUT;
140 static Lisp_Object xftfont_list (Lisp_Object, Lisp_Object);
141 static Lisp_Object xftfont_match (Lisp_Object, Lisp_Object);
142 static Lisp_Object xftfont_open (FRAME_PTR, Lisp_Object, int);
143 static void xftfont_close (FRAME_PTR, struct font *);
144 static int xftfont_prepare_face (FRAME_PTR, struct face *);
145 static void xftfont_done_face (FRAME_PTR, struct face *);
146 static int xftfont_has_char (Lisp_Object, int);
147 static unsigned xftfont_encode_char (struct font *, int);
148 static int xftfont_text_extents (struct font *, unsigned *, int,
149 struct font_metrics *);
150 static int xftfont_draw (struct glyph_string *, int, int, int, int, int);
151 static int xftfont_end_for_frame (FRAME_PTR f);
153 struct font_driver xftfont_driver;
155 static Lisp_Object
156 xftfont_list (Lisp_Object frame, Lisp_Object spec)
158 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
160 for (tail = list; CONSP (tail); tail = XCDR (tail))
161 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
162 return list;
165 static Lisp_Object
166 xftfont_match (Lisp_Object frame, Lisp_Object spec)
168 Lisp_Object entity = ftfont_driver.match (frame, spec);
170 if (! NILP (entity))
171 ASET (entity, FONT_TYPE_INDEX, Qxft);
172 return entity;
175 static FcChar8 ascii_printable[95];
177 static void
178 xftfont_fix_match (FcPattern *pat, FcPattern *match)
180 /* These values are not used for matching (except antialias), but for
181 rendering, so make sure they are carried over to the match.
182 We also put antialias here because most fonts are antialiased, so
183 the match will have antialias true. */
185 FcBool b = FcTrue;
186 int i;
187 double dpi;
189 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
190 if (! b)
192 FcPatternDel (match, FC_ANTIALIAS);
193 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
195 FcPatternGetBool (pat, FC_HINTING, 0, &b);
196 if (! b)
198 FcPatternDel (match, FC_HINTING);
199 FcPatternAddBool (match, FC_HINTING, FcFalse);
201 #ifndef FC_HINT_STYLE
202 # define FC_HINT_STYLE "hintstyle"
203 #endif
204 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
206 FcPatternDel (match, FC_HINT_STYLE);
207 FcPatternAddInteger (match, FC_HINT_STYLE, i);
209 #ifndef FC_LCD_FILTER
210 /* Older fontconfig versions don't have FC_LCD_FILTER. */
211 #define FC_LCD_FILTER "lcdfilter"
212 #endif
213 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
215 FcPatternDel (match, FC_LCD_FILTER);
216 FcPatternAddInteger (match, FC_LCD_FILTER, i);
218 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
220 FcPatternDel (match, FC_RGBA);
221 FcPatternAddInteger (match, FC_RGBA, i);
223 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
225 FcPatternDel (match, FC_DPI);
226 FcPatternAddDouble (match, FC_DPI, dpi);
230 static void
231 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
233 Lisp_Object tail;
234 int ival;
236 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
238 Lisp_Object key = XCAR (XCAR (tail));
239 Lisp_Object val = XCDR (XCAR (tail));
241 if (EQ (key, QCantialias))
242 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
243 else if (EQ (key, QChinting))
244 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
245 else if (EQ (key, QCautohint))
246 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
247 else if (EQ (key, QChintstyle))
249 if (INTEGERP (val))
250 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
251 else if (SYMBOLP (val)
252 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
253 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
255 else if (EQ (key, QCrgba))
257 if (INTEGERP (val))
258 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
259 else if (SYMBOLP (val)
260 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
261 FcPatternAddInteger (pat, FC_RGBA, ival);
263 else if (EQ (key, QClcdfilter))
265 if (INTEGERP (val))
266 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
267 else if (SYMBOLP (val)
268 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
269 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
271 #ifdef FC_EMBOLDEN
272 else if (EQ (key, QCembolden))
273 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
274 #endif
278 static Lisp_Object
279 xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
281 FcResult result;
282 Display *display = FRAME_X_DISPLAY (f);
283 Lisp_Object val, filename, idx, font_object;
284 FcPattern *pat = NULL, *match;
285 struct xftfont_info *xftfont_info = NULL;
286 struct font *font;
287 double size = 0;
288 XftFont *xftfont = NULL;
289 int spacing;
290 char name[256];
291 int len, i;
292 XGlyphInfo extents;
293 FT_Face ft_face;
294 FcMatrix *matrix;
296 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
297 if (! CONSP (val))
298 return Qnil;
299 val = XCDR (val);
300 filename = XCAR (val);
301 idx = XCDR (val);
302 size = XINT (AREF (entity, FONT_SIZE_INDEX));
303 if (size == 0)
304 size = pixel_size;
305 pat = FcPatternCreate ();
306 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
307 i = FONT_SLANT_NUMERIC (entity) - 100;
308 if (i < 0) i = 0;
309 FcPatternAddInteger (pat, FC_SLANT, i);
310 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
311 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
312 val = AREF (entity, FONT_FAMILY_INDEX);
313 if (! NILP (val))
314 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
315 val = AREF (entity, FONT_FOUNDRY_INDEX);
316 if (! NILP (val))
317 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
318 val = AREF (entity, FONT_SPACING_INDEX);
319 if (! NILP (val))
320 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
321 val = AREF (entity, FONT_DPI_INDEX);
322 if (! NILP (val))
324 double dbl = XINT (val);
326 FcPatternAddDouble (pat, FC_DPI, dbl);
328 val = AREF (entity, FONT_AVGWIDTH_INDEX);
329 if (INTEGERP (val) && XINT (val) == 0)
330 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
331 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
332 over 10x20-ISO8859-1.pcf.gz). */
333 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
335 xftfont_add_rendering_parameters (pat, entity);
337 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
338 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
341 BLOCK_INPUT;
342 /* Make sure that the Xrender extension is added before the Xft one.
343 Otherwise, the close-display hook set by Xft is called after the
344 one for Xrender, and the former tries to re-add the latter. This
345 results in inconsistency of internal states and leads to X
346 protocol error when one reconnects to the same X server.
347 (Bug#1696) */
349 int event_base, error_base;
350 XRenderQueryExtension (display, &event_base, &error_base);
353 /* Substitute in values from X resources and XftDefaultSet. */
354 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
355 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
356 xftfont_fix_match (pat, match);
358 FcPatternDestroy (pat);
359 xftfont = XftFontOpenPattern (display, match);
360 if (!xftfont)
362 UNBLOCK_INPUT;
363 XftPatternDestroy (match);
364 return Qnil;
366 ft_face = XftLockFace (xftfont);
367 UNBLOCK_INPUT;
369 /* We should not destroy PAT here because it is kept in XFTFONT and
370 destroyed automatically when XFTFONT is closed. */
371 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
372 ASET (font_object, FONT_TYPE_INDEX, Qxft);
373 len = font_unparse_xlfd (entity, size, name, 256);
374 if (len > 0)
375 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
376 len = font_unparse_fcname (entity, size, name, 256);
377 if (len > 0)
378 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
379 else
380 ASET (font_object, FONT_FULLNAME_INDEX,
381 AREF (font_object, FONT_NAME_INDEX));
382 ASET (font_object, FONT_FILE_INDEX, filename);
383 ASET (font_object, FONT_FORMAT_INDEX,
384 ftfont_font_format (xftfont->pattern, filename));
385 font = XFONT_OBJECT (font_object);
386 font->pixel_size = pixel_size;
387 font->driver = &xftfont_driver;
388 font->encoding_charset = font->repertory_charset = -1;
390 xftfont_info = (struct xftfont_info *) font;
391 xftfont_info->display = display;
392 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
393 xftfont_info->xftfont = xftfont;
394 /* This means that there's no need of transformation. */
395 xftfont_info->matrix.xx = 0;
396 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
397 == FcResultMatch)
399 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
400 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
401 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
402 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
404 font->pixel_size = size;
405 font->driver = &xftfont_driver;
406 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
407 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
408 else
409 spacing = FC_PROPORTIONAL;
410 if (! ascii_printable[0])
412 int ch;
413 for (ch = 0; ch < 95; ch++)
414 ascii_printable[ch] = ' ' + ch;
416 BLOCK_INPUT;
418 /* Unfortunately Xft doesn't provide a way to get minimum char
419 width. So, we set min_width to space_width. */
421 if (spacing != FC_PROPORTIONAL
422 #ifdef FC_DUAL
423 && spacing != FC_DUAL
424 #endif /* FC_DUAL */
427 font->min_width = font->max_width = font->average_width
428 = font->space_width = xftfont->max_advance_width;
429 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
431 else
433 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
434 font->min_width = font->max_width = font->space_width
435 = extents.xOff;
436 if (font->space_width <= 0)
437 /* dirty workaround */
438 font->space_width = pixel_size;
439 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
440 font->average_width = (font->space_width + extents.xOff) / 95;
442 UNBLOCK_INPUT;
444 font->ascent = xftfont->ascent;
445 font->descent = xftfont->descent;
446 if (pixel_size >= 5)
448 /* The above condition is a dirty workaround because
449 XftTextExtents8 behaves strangely for some fonts
450 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
451 if (font->ascent < extents.y)
452 font->ascent = extents.y;
453 if (font->descent < extents.height - extents.y)
454 font->descent = extents.height - extents.y;
456 font->height = font->ascent + font->descent;
458 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
460 int upEM = ft_face->units_per_EM;
462 font->underline_position = -ft_face->underline_position * size / upEM;
463 font->underline_thickness = ft_face->underline_thickness * size / upEM;
464 if (font->underline_thickness > 2)
465 font->underline_position -= font->underline_thickness / 2;
467 else
469 font->underline_position = -1;
470 font->underline_thickness = 0;
472 #ifdef HAVE_LIBOTF
473 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
474 xftfont_info->otf = NULL;
475 #endif /* HAVE_LIBOTF */
476 xftfont_info->ft_size = ft_face->size;
478 font->baseline_offset = 0;
479 font->relative_compose = 0;
480 font->default_ascent = 0;
481 font->vertical_centering = 0;
482 #ifdef FT_BDF_H
483 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
485 BDF_PropertyRec rec;
487 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
488 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
489 font->baseline_offset = rec.u.integer;
490 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
491 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
492 font->relative_compose = rec.u.integer;
493 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
494 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
495 font->default_ascent = rec.u.integer;
497 #endif
499 return font_object;
502 static void
503 xftfont_close (FRAME_PTR f, struct font *font)
505 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
507 #ifdef HAVE_LIBOTF
508 if (xftfont_info->otf)
509 OTF_close (xftfont_info->otf);
510 #endif
511 BLOCK_INPUT;
512 XftUnlockFace (xftfont_info->xftfont);
513 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
514 UNBLOCK_INPUT;
517 static int
518 xftfont_prepare_face (FRAME_PTR f, struct face *face)
520 struct xftface_info *xftface_info;
522 #if 0
523 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
524 if (face != face->ascii_face)
526 face->extra = face->ascii_face->extra;
527 return 0;
529 #endif
531 xftface_info = malloc (sizeof *xftface_info);
532 if (! xftface_info)
533 return -1;
534 xftfont_get_colors (f, face, face->gc, NULL,
535 &xftface_info->xft_fg, &xftface_info->xft_bg);
536 face->extra = xftface_info;
537 return 0;
540 static void
541 xftfont_done_face (FRAME_PTR f, struct face *face)
543 struct xftface_info *xftface_info;
545 #if 0
546 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
547 if (face != face->ascii_face
548 || ! face->extra)
549 return;
550 #endif
552 xftface_info = (struct xftface_info *) face->extra;
553 if (xftface_info)
555 free (xftface_info);
556 face->extra = NULL;
560 static int
561 xftfont_has_char (Lisp_Object font, int c)
563 struct xftfont_info *xftfont_info;
564 struct charset *cs = NULL;
566 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
567 && charset_jisx0208 >= 0)
568 cs = CHARSET_FROM_ID (charset_jisx0208);
569 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
570 && charset_ksc5601 >= 0)
571 cs = CHARSET_FROM_ID (charset_ksc5601);
572 if (cs)
573 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
575 if (FONT_ENTITY_P (font))
576 return ftfont_driver.has_char (font, c);
577 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
578 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
579 (FcChar32) c) == FcTrue);
582 static unsigned
583 xftfont_encode_char (struct font *font, int c)
585 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
586 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
587 (FcChar32) c);
589 return (code ? code : FONT_INVALID_CODE);
592 static int
593 xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
595 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
596 XGlyphInfo extents;
598 BLOCK_INPUT;
599 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
600 &extents);
601 UNBLOCK_INPUT;
602 if (metrics)
604 metrics->lbearing = - extents.x;
605 metrics->rbearing = - extents.x + extents.width;
606 metrics->width = extents.xOff;
607 metrics->ascent = extents.y;
608 metrics->descent = extents.height - extents.y;
610 return extents.xOff;
613 static XftDraw *
614 xftfont_get_xft_draw (FRAME_PTR f)
616 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
618 if (! xft_draw)
620 BLOCK_INPUT;
621 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
622 FRAME_X_WINDOW (f),
623 FRAME_X_VISUAL (f),
624 FRAME_X_COLORMAP (f));
625 UNBLOCK_INPUT;
626 eassert (xft_draw != NULL);
627 font_put_frame_data (f, &xftfont_driver, xft_draw);
629 return xft_draw;
632 static int
633 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_background)
635 FRAME_PTR f = s->f;
636 struct face *face = s->face;
637 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
638 struct xftface_info *xftface_info = NULL;
639 XftDraw *xft_draw = xftfont_get_xft_draw (f);
640 FT_UInt *code;
641 XftColor fg, bg;
642 int len = to - from;
643 int i;
645 if (s->font == face->font)
646 xftface_info = (struct xftface_info *) face->extra;
647 xftfont_get_colors (f, face, s->gc, xftface_info,
648 &fg, with_background ? &bg : NULL);
649 BLOCK_INPUT;
650 if (s->num_clips > 0)
651 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
652 else
653 XftDrawSetClip (xft_draw, NULL);
655 if (with_background)
656 XftDrawRect (xft_draw, &bg,
657 x, y - s->font->ascent, s->width, s->font->height);
658 code = alloca (sizeof (FT_UInt) * len);
659 for (i = 0; i < len; i++)
660 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
661 | XCHAR2B_BYTE2 (s->char2b + from + i));
663 if (s->padding_p)
664 for (i = 0; i < len; i++)
665 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
666 x + i, y, code + i, 1);
667 else
668 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
669 x, y, code, len);
670 UNBLOCK_INPUT;
672 return len;
675 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
676 static Lisp_Object
677 xftfont_shape (Lisp_Object lgstring)
679 struct font *font;
680 struct xftfont_info *xftfont_info;
681 FT_Face ft_face;
682 Lisp_Object val;
684 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
685 xftfont_info = (struct xftfont_info *) font;
686 ft_face = XftLockFace (xftfont_info->xftfont);
687 xftfont_info->ft_size = ft_face->size;
688 val = ftfont_driver.shape (lgstring);
689 XftUnlockFace (xftfont_info->xftfont);
690 return val;
692 #endif
694 static int
695 xftfont_end_for_frame (FRAME_PTR f)
697 XftDraw *xft_draw;
699 /* Don't do anything if display is dead */
700 if (FRAME_X_DISPLAY (f) == NULL) return 0;
702 xft_draw = font_get_frame_data (f, &xftfont_driver);
704 if (xft_draw)
706 BLOCK_INPUT;
707 XftDrawDestroy (xft_draw);
708 UNBLOCK_INPUT;
709 font_put_frame_data (f, &xftfont_driver, NULL);
711 return 0;
714 static int
715 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, Lisp_Object entity)
717 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
718 FcPattern *oldpat = info->xftfont->pattern;
719 Display *display = FRAME_X_DISPLAY (f);
720 FcPattern *pat = FcPatternCreate ();
721 FcBool b1, b2;
722 int ok = 0, i1, i2, r1, r2;
724 xftfont_add_rendering_parameters (pat, entity);
725 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
727 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
728 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
729 if (r1 != r2 || b1 != b2) goto out;
730 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
731 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
732 if (r1 != r2 || b1 != b2) goto out;
733 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
734 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
735 if (r1 != r2 || b1 != b2) goto out;
736 #ifdef FC_EMBOLDEN
737 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
738 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
739 if (r1 != r2 || b1 != b2) goto out;
740 #endif
741 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
742 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
743 if (r1 != r2 || i1 != i2) goto out;
744 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
745 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
746 if (r1 != r2 || i1 != i2) goto out;
747 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
748 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
749 if (r1 != r2 || i1 != i2) goto out;
751 ok = 1;
752 out:
753 FcPatternDestroy (pat);
754 return ok;
757 void
758 syms_of_xftfont (void)
760 DEFSYM (Qxft, "xft");
761 DEFSYM (QChinting, ":hinting");
762 DEFSYM (QCautohint, ":autohint");
763 DEFSYM (QChintstyle, ":hintstyle");
764 DEFSYM (QCrgba, ":rgba");
765 DEFSYM (QCembolden, ":embolden");
766 DEFSYM (QClcdfilter, ":lcdfilter");
768 ascii_printable[0] = 0;
770 xftfont_driver = ftfont_driver;
771 xftfont_driver.type = Qxft;
772 xftfont_driver.get_cache = xfont_driver.get_cache;
773 xftfont_driver.list = xftfont_list;
774 xftfont_driver.match = xftfont_match;
775 xftfont_driver.open = xftfont_open;
776 xftfont_driver.close = xftfont_close;
777 xftfont_driver.prepare_face = xftfont_prepare_face;
778 xftfont_driver.done_face = xftfont_done_face;
779 xftfont_driver.has_char = xftfont_has_char;
780 xftfont_driver.encode_char = xftfont_encode_char;
781 xftfont_driver.text_extents = xftfont_text_extents;
782 xftfont_driver.draw = xftfont_draw;
783 xftfont_driver.end_for_frame = xftfont_end_for_frame;
784 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
785 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
786 xftfont_driver.shape = xftfont_shape;
787 #endif
789 register_font_driver (&xftfont_driver, NULL);