]> code.delx.au - gnu-emacs/blob - src/xftfont.c
Fix documentation of dired-aux search/replace commands
[gnu-emacs] / src / xftfont.c
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
6
7 This file is part of GNU Emacs.
8
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.
13
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.
18
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/>. */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xft/Xft.h>
26
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"
35
36 /* Xft font driver. */
37
38
39 /* The actual structure for Xft font that can be cast to struct
40 font. */
41
42 struct xftfont_info
43 {
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;
57 };
58
59 /* Structure pointed by (struct face *)->extra */
60
61 struct xftface_info
62 {
63 XftColor xft_fg; /* color for face->foreground */
64 XftColor xft_bg; /* color for face->background */
65 };
66
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. */
70
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)
75 {
76 if (xftface_info && face->gc == gc)
77 {
78 *fg = xftface_info->xft_fg;
79 if (bg)
80 *bg = xftface_info->xft_bg;
81 }
82 else
83 {
84 XGCValues xgcv;
85 bool fg_done = false, bg_done = false;
86
87 block_input ();
88 XGetGCValues (FRAME_X_DISPLAY (f), gc,
89 GCForeground | GCBackground, &xgcv);
90 if (xftface_info)
91 {
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;
102 }
103
104 if (! (fg_done & bg_done))
105 {
106 XColor colors[2];
107
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)
117 {
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;
122 }
123 }
124 unblock_input ();
125 }
126 }
127
128
129 struct font_driver xftfont_driver;
130
131 static Lisp_Object
132 xftfont_list (struct frame *f, Lisp_Object spec)
133 {
134 Lisp_Object list = ftfont_driver.list (f, spec), tail;
135
136 for (tail = list; CONSP (tail); tail = XCDR (tail))
137 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
138 return list;
139 }
140
141 static Lisp_Object
142 xftfont_match (struct frame *f, Lisp_Object spec)
143 {
144 Lisp_Object entity = ftfont_driver.match (f, spec);
145
146 if (! NILP (entity))
147 ASET (entity, FONT_TYPE_INDEX, Qxft);
148 return entity;
149 }
150
151 static FcChar8 ascii_printable[95];
152
153 static void
154 xftfont_fix_match (FcPattern *pat, FcPattern *match)
155 {
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. */
160
161 FcBool b = FcTrue;
162 int i;
163 double dpi;
164
165 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
166 if (! b)
167 {
168 FcPatternDel (match, FC_ANTIALIAS);
169 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
170 }
171 FcPatternGetBool (pat, FC_HINTING, 0, &b);
172 if (! b)
173 {
174 FcPatternDel (match, FC_HINTING);
175 FcPatternAddBool (match, FC_HINTING, FcFalse);
176 }
177 #ifndef FC_HINT_STYLE
178 # define FC_HINT_STYLE "hintstyle"
179 #endif
180 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
181 {
182 FcPatternDel (match, FC_HINT_STYLE);
183 FcPatternAddInteger (match, FC_HINT_STYLE, i);
184 }
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))
190 {
191 FcPatternDel (match, FC_LCD_FILTER);
192 FcPatternAddInteger (match, FC_LCD_FILTER, i);
193 }
194 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
195 {
196 FcPatternDel (match, FC_RGBA);
197 FcPatternAddInteger (match, FC_RGBA, i);
198 }
199 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
200 {
201 FcPatternDel (match, FC_DPI);
202 FcPatternAddDouble (match, FC_DPI, dpi);
203 }
204 }
205
206 static void
207 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
208 {
209 Lisp_Object tail;
210 int ival;
211
212 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
213 {
214 Lisp_Object key = XCAR (XCAR (tail));
215 Lisp_Object val = XCDR (XCAR (tail));
216
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))
224 {
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);
230 }
231 else if (EQ (key, QCrgba))
232 {
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);
238 }
239 else if (EQ (key, QClcdfilter))
240 {
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);
246 }
247 #ifdef FC_EMBOLDEN
248 else if (EQ (key, QCembolden))
249 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
250 #endif
251 }
252 }
253
254 static Lisp_Object
255 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
256 {
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;
270
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))
298 {
299 double dbl = XINT (val);
300
301 FcPatternAddDouble (pat, FC_DPI, dbl);
302 }
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));
309
310 xftfont_add_rendering_parameters (pat, entity);
311
312 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
313 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
314
315
316 block_input ();
317
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);
322
323 FcPatternDestroy (pat);
324 xftfont = XftFontOpenPattern (display, match);
325 if (!xftfont)
326 {
327 unblock_input ();
328 XftPatternDestroy (match);
329 return Qnil;
330 }
331 ft_face = XftLockFace (xftfont);
332 unblock_input ();
333
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;
343
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)
352 {
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;
357 }
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])
363 {
364 int ch;
365 for (ch = 0; ch < 95; ch++)
366 ascii_printable[ch] = ' ' + ch;
367 }
368 block_input ();
369
370 /* Unfortunately Xft doesn't provide a way to get minimum char
371 width. So, we set min_width to space_width. */
372
373 if (spacing != FC_PROPORTIONAL
374 #ifdef FC_DUAL
375 && spacing != FC_DUAL
376 #endif /* FC_DUAL */
377 )
378 {
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);
382 }
383 else
384 {
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;
393 }
394 unblock_input ();
395
396 font->ascent = xftfont->ascent;
397 font->descent = xftfont->descent;
398 font->height = font->ascent + font->descent;
399
400 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
401 {
402 int upEM = ft_face->units_per_EM;
403
404 font->underline_position = -ft_face->underline_position * size / upEM;
405 font->underline_thickness = ft_face->underline_thickness * size / upEM;
406 if (font->underline_thickness > 2)
407 font->underline_position -= font->underline_thickness / 2;
408 }
409 else
410 {
411 font->underline_position = -1;
412 font->underline_thickness = 0;
413 }
414 #ifdef HAVE_LIBOTF
415 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
416 xftfont_info->otf = NULL;
417 #endif /* HAVE_LIBOTF */
418 xftfont_info->ft_size = ft_face->size;
419
420 font->baseline_offset = 0;
421 font->relative_compose = 0;
422 font->default_ascent = 0;
423 font->vertical_centering = false;
424 #ifdef FT_BDF_H
425 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
426 {
427 BDF_PropertyRec rec;
428
429 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
430 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
431 font->baseline_offset = rec.u.integer;
432 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
433 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
434 font->relative_compose = rec.u.integer;
435 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
436 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
437 font->default_ascent = rec.u.integer;
438 }
439 #endif
440
441 return font_object;
442 }
443
444 static void
445 xftfont_close (struct font *font)
446 {
447 struct x_display_info *xdi;
448 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
449
450 #ifdef HAVE_LIBOTF
451 if (xftfont_info->otf)
452 {
453 OTF_close (xftfont_info->otf);
454 xftfont_info->otf = NULL;
455 }
456 #endif
457
458 /* See comment in xfont_close. */
459 if (xftfont_info->xftfont
460 && ((xdi = x_display_info_for_display (xftfont_info->display))
461 && xftfont_info->x_display_id == xdi->x_id))
462 {
463 block_input ();
464 XftUnlockFace (xftfont_info->xftfont);
465 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
466 unblock_input ();
467 xftfont_info->xftfont = NULL;
468 }
469 }
470
471 static void
472 xftfont_prepare_face (struct frame *f, struct face *face)
473 {
474 struct xftface_info *xftface_info;
475
476 #if false
477 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
478 if (face != face->ascii_face)
479 {
480 face->extra = face->ascii_face->extra;
481 return;
482 }
483 #endif
484
485 xftface_info = xmalloc (sizeof *xftface_info);
486 xftfont_get_colors (f, face, face->gc, NULL,
487 &xftface_info->xft_fg, &xftface_info->xft_bg);
488 face->extra = xftface_info;
489 }
490
491 static void
492 xftfont_done_face (struct frame *f, struct face *face)
493 {
494 struct xftface_info *xftface_info;
495
496 #if false
497 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
498 if (face != face->ascii_face
499 || ! face->extra)
500 return;
501 #endif
502
503 xftface_info = (struct xftface_info *) face->extra;
504 if (xftface_info)
505 {
506 xfree (xftface_info);
507 face->extra = NULL;
508 }
509 }
510
511 static int
512 xftfont_has_char (Lisp_Object font, int c)
513 {
514 struct xftfont_info *xftfont_info;
515 struct charset *cs = NULL;
516
517 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
518 && charset_jisx0208 >= 0)
519 cs = CHARSET_FROM_ID (charset_jisx0208);
520 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
521 && charset_ksc5601 >= 0)
522 cs = CHARSET_FROM_ID (charset_ksc5601);
523 if (cs)
524 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
525
526 if (FONT_ENTITY_P (font))
527 return ftfont_driver.has_char (font, c);
528 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
529 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
530 (FcChar32) c) == FcTrue);
531 }
532
533 static unsigned
534 xftfont_encode_char (struct font *font, int c)
535 {
536 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
537 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
538 (FcChar32) c);
539
540 return (code ? code : FONT_INVALID_CODE);
541 }
542
543 static void
544 xftfont_text_extents (struct font *font, unsigned int *code,
545 int nglyphs, struct font_metrics *metrics)
546 {
547 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
548 XGlyphInfo extents;
549
550 block_input ();
551 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
552 &extents);
553 unblock_input ();
554
555 metrics->lbearing = - extents.x;
556 metrics->rbearing = - extents.x + extents.width;
557 metrics->width = extents.xOff;
558 metrics->ascent = extents.y;
559 metrics->descent = extents.height - extents.y;
560 }
561
562 static XftDraw *
563 xftfont_get_xft_draw (struct frame *f)
564 {
565 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
566
567 if (! xft_draw)
568 {
569 block_input ();
570 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
571 FRAME_X_WINDOW (f),
572 FRAME_X_VISUAL (f),
573 FRAME_X_COLORMAP (f));
574 unblock_input ();
575 eassert (xft_draw != NULL);
576 font_put_frame_data (f, Qxft, xft_draw);
577 }
578 return xft_draw;
579 }
580
581 static int
582 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
583 bool with_background)
584 {
585 struct frame *f = s->f;
586 struct face *face = s->face;
587 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
588 struct xftface_info *xftface_info = NULL;
589 XftDraw *xft_draw = xftfont_get_xft_draw (f);
590 FT_UInt *code;
591 XftColor fg, bg;
592 int len = to - from;
593 int i;
594
595 if (s->font == face->font)
596 xftface_info = (struct xftface_info *) face->extra;
597 xftfont_get_colors (f, face, s->gc, xftface_info,
598 &fg, with_background ? &bg : NULL);
599 block_input ();
600 if (s->num_clips > 0)
601 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
602 else
603 XftDrawSetClip (xft_draw, NULL);
604
605 if (with_background)
606 {
607 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
608
609 /* Font's global height and ascent values might be
610 preposterously large for some fonts. We fix here the case
611 when those fonts are used for display of glyphless
612 characters, because drawing background with font dimensions
613 in those cases makes the display illegible. There's only one
614 more call to the draw method with with_background set to
615 true, and that's in x_draw_glyph_string_foreground, when
616 drawing the cursor, where we have no such heuristics
617 available. FIXME. */
618 if (s->first_glyph->type == GLYPHLESS_GLYPH
619 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
620 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
621 height = ascent =
622 s->first_glyph->slice.glyphless.lower_yoff
623 - s->first_glyph->slice.glyphless.upper_yoff;
624 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
625 }
626 code = alloca (sizeof (FT_UInt) * len);
627 for (i = 0; i < len; i++)
628 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
629 | XCHAR2B_BYTE2 (s->char2b + from + i));
630
631 if (s->padding_p)
632 for (i = 0; i < len; i++)
633 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
634 x + i, y, code + i, 1);
635 else
636 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
637 x, y, code, len);
638 unblock_input ();
639
640 return len;
641 }
642
643 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
644 static Lisp_Object
645 xftfont_shape (Lisp_Object lgstring)
646 {
647 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
648 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
649 FT_Face ft_face;
650 Lisp_Object val;
651
652 ft_face = XftLockFace (xftfont_info->xftfont);
653 xftfont_info->ft_size = ft_face->size;
654 val = ftfont_driver.shape (lgstring);
655 XftUnlockFace (xftfont_info->xftfont);
656 return val;
657 }
658 #endif
659
660 static int
661 xftfont_end_for_frame (struct frame *f)
662 {
663 XftDraw *xft_draw;
664
665 /* Don't do anything if display is dead */
666 if (FRAME_X_DISPLAY (f) == NULL) return 0;
667
668 xft_draw = font_get_frame_data (f, Qxft);
669
670 if (xft_draw)
671 {
672 block_input ();
673 XftDrawDestroy (xft_draw);
674 unblock_input ();
675 font_put_frame_data (f, Qxft, NULL);
676 }
677 return 0;
678 }
679
680 static bool
681 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
682 Lisp_Object entity)
683 {
684 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
685 FcPattern *oldpat = info->xftfont->pattern;
686 Display *display = FRAME_X_DISPLAY (f);
687 FcPattern *pat = FcPatternCreate ();
688 FcBool b1, b2;
689 bool ok = false;
690 int i1, i2, r1, r2;
691
692 xftfont_add_rendering_parameters (pat, entity);
693 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
694
695 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
696 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
697 if (r1 != r2 || b1 != b2) goto out;
698 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
699 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
700 if (r1 != r2 || b1 != b2) goto out;
701 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
702 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
703 if (r1 != r2 || b1 != b2) goto out;
704 #ifdef FC_EMBOLDEN
705 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
706 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
707 if (r1 != r2 || b1 != b2) goto out;
708 #endif
709 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
710 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
711 if (r1 != r2 || i1 != i2) goto out;
712 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
713 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
714 if (r1 != r2 || i1 != i2) goto out;
715 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
716 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
717 if (r1 != r2 || i1 != i2) goto out;
718
719 ok = true;
720 out:
721 FcPatternDestroy (pat);
722 return ok;
723 }
724
725 void
726 syms_of_xftfont (void)
727 {
728 DEFSYM (Qxft, "xft");
729 DEFSYM (QChinting, ":hinting");
730 DEFSYM (QCautohint, ":autohint");
731 DEFSYM (QChintstyle, ":hintstyle");
732 DEFSYM (QCrgba, ":rgba");
733 DEFSYM (QCembolden, ":embolden");
734 DEFSYM (QClcdfilter, ":lcdfilter");
735
736 ascii_printable[0] = 0;
737
738 xftfont_driver = ftfont_driver;
739 xftfont_driver.type = Qxft;
740 xftfont_driver.get_cache = xfont_driver.get_cache;
741 xftfont_driver.list = xftfont_list;
742 xftfont_driver.match = xftfont_match;
743 xftfont_driver.open = xftfont_open;
744 xftfont_driver.close = xftfont_close;
745 xftfont_driver.prepare_face = xftfont_prepare_face;
746 xftfont_driver.done_face = xftfont_done_face;
747 xftfont_driver.has_char = xftfont_has_char;
748 xftfont_driver.encode_char = xftfont_encode_char;
749 xftfont_driver.text_extents = xftfont_text_extents;
750 xftfont_driver.draw = xftfont_draw;
751 xftfont_driver.end_for_frame = xftfont_end_for_frame;
752 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
753 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
754 xftfont_driver.shape = xftfont_shape;
755 #endif
756
757 register_font_driver (&xftfont_driver, NULL);
758 }