]> code.delx.au - gnu-emacs/blob - src/xftfont.c
* src/macfont.m (mac_font_shape): Make sure that total_advance is increasing.
[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 /* The following workaround is unnecessary on most systems, and
399 causes annoying differences in glyph height between regular and
400 bold fonts (see bug#22383). However, with some fonts, such as
401 monaco, removing the workaround results in overlapping vertical
402 space of a line, see bug#23360. As long as the way to reconcile
403 these opposites is not known, we provide a user option to work
404 around the problem. */
405 if (pixel_size >= 5
406 && xft_font_ascent_descent_override)
407 {
408 /* The above condition is a dirty workaround because
409 XftTextExtents8 behaves strangely for some fonts
410 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
411 if (font->ascent < extents.y)
412 font->ascent = extents.y;
413 if (font->descent < extents.height - extents.y)
414 font->descent = extents.height - extents.y;
415 }
416 font->height = font->ascent + font->descent;
417
418 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
419 {
420 int upEM = ft_face->units_per_EM;
421
422 font->underline_position = -ft_face->underline_position * size / upEM;
423 font->underline_thickness = ft_face->underline_thickness * size / upEM;
424 if (font->underline_thickness > 2)
425 font->underline_position -= font->underline_thickness / 2;
426 }
427 else
428 {
429 font->underline_position = -1;
430 font->underline_thickness = 0;
431 }
432 #ifdef HAVE_LIBOTF
433 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
434 xftfont_info->otf = NULL;
435 #endif /* HAVE_LIBOTF */
436 xftfont_info->ft_size = ft_face->size;
437
438 font->baseline_offset = 0;
439 font->relative_compose = 0;
440 font->default_ascent = 0;
441 font->vertical_centering = false;
442 #ifdef FT_BDF_H
443 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
444 {
445 BDF_PropertyRec rec;
446
447 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
448 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
449 font->baseline_offset = rec.u.integer;
450 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
451 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
452 font->relative_compose = rec.u.integer;
453 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
454 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
455 font->default_ascent = rec.u.integer;
456 }
457 #endif
458
459 return font_object;
460 }
461
462 static void
463 xftfont_close (struct font *font)
464 {
465 struct x_display_info *xdi;
466 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
467
468 #ifdef HAVE_LIBOTF
469 if (xftfont_info->otf)
470 {
471 OTF_close (xftfont_info->otf);
472 xftfont_info->otf = NULL;
473 }
474 #endif
475
476 /* See comment in xfont_close. */
477 if (xftfont_info->xftfont
478 && ((xdi = x_display_info_for_display (xftfont_info->display))
479 && xftfont_info->x_display_id == xdi->x_id))
480 {
481 block_input ();
482 XftUnlockFace (xftfont_info->xftfont);
483 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
484 unblock_input ();
485 xftfont_info->xftfont = NULL;
486 }
487 }
488
489 static void
490 xftfont_prepare_face (struct frame *f, struct face *face)
491 {
492 struct xftface_info *xftface_info;
493
494 #if false
495 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
496 if (face != face->ascii_face)
497 {
498 face->extra = face->ascii_face->extra;
499 return;
500 }
501 #endif
502
503 xftface_info = xmalloc (sizeof *xftface_info);
504 xftfont_get_colors (f, face, face->gc, NULL,
505 &xftface_info->xft_fg, &xftface_info->xft_bg);
506 face->extra = xftface_info;
507 }
508
509 static void
510 xftfont_done_face (struct frame *f, struct face *face)
511 {
512 struct xftface_info *xftface_info;
513
514 #if false
515 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
516 if (face != face->ascii_face
517 || ! face->extra)
518 return;
519 #endif
520
521 xftface_info = (struct xftface_info *) face->extra;
522 if (xftface_info)
523 {
524 xfree (xftface_info);
525 face->extra = NULL;
526 }
527 }
528
529 static int
530 xftfont_has_char (Lisp_Object font, int c)
531 {
532 struct xftfont_info *xftfont_info;
533 struct charset *cs = NULL;
534
535 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
536 && charset_jisx0208 >= 0)
537 cs = CHARSET_FROM_ID (charset_jisx0208);
538 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
539 && charset_ksc5601 >= 0)
540 cs = CHARSET_FROM_ID (charset_ksc5601);
541 if (cs)
542 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
543
544 if (FONT_ENTITY_P (font))
545 return ftfont_driver.has_char (font, c);
546 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
547 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
548 (FcChar32) c) == FcTrue);
549 }
550
551 static unsigned
552 xftfont_encode_char (struct font *font, int c)
553 {
554 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
555 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
556 (FcChar32) c);
557
558 return (code ? code : FONT_INVALID_CODE);
559 }
560
561 static void
562 xftfont_text_extents (struct font *font, unsigned int *code,
563 int nglyphs, struct font_metrics *metrics)
564 {
565 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
566 XGlyphInfo extents;
567
568 block_input ();
569 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
570 &extents);
571 unblock_input ();
572
573 metrics->lbearing = - extents.x;
574 metrics->rbearing = - extents.x + extents.width;
575 metrics->width = extents.xOff;
576 metrics->ascent = extents.y;
577 metrics->descent = extents.height - extents.y;
578 }
579
580 static XftDraw *
581 xftfont_get_xft_draw (struct frame *f)
582 {
583 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
584
585 if (! xft_draw)
586 {
587 block_input ();
588 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
589 FRAME_X_WINDOW (f),
590 FRAME_X_VISUAL (f),
591 FRAME_X_COLORMAP (f));
592 unblock_input ();
593 eassert (xft_draw != NULL);
594 font_put_frame_data (f, Qxft, xft_draw);
595 }
596 return xft_draw;
597 }
598
599 static int
600 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
601 bool with_background)
602 {
603 struct frame *f = s->f;
604 struct face *face = s->face;
605 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
606 struct xftface_info *xftface_info = NULL;
607 XftDraw *xft_draw = xftfont_get_xft_draw (f);
608 FT_UInt *code;
609 XftColor fg, bg;
610 int len = to - from;
611 int i;
612
613 if (s->font == face->font)
614 xftface_info = (struct xftface_info *) face->extra;
615 xftfont_get_colors (f, face, s->gc, xftface_info,
616 &fg, with_background ? &bg : NULL);
617 block_input ();
618 if (s->num_clips > 0)
619 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
620 else
621 XftDrawSetClip (xft_draw, NULL);
622
623 if (with_background)
624 {
625 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
626
627 /* Font's global height and ascent values might be
628 preposterously large for some fonts. We fix here the case
629 when those fonts are used for display of glyphless
630 characters, because drawing background with font dimensions
631 in those cases makes the display illegible. There's only one
632 more call to the draw method with with_background set to
633 true, and that's in x_draw_glyph_string_foreground, when
634 drawing the cursor, where we have no such heuristics
635 available. FIXME. */
636 if (s->first_glyph->type == GLYPHLESS_GLYPH
637 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
638 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
639 height = ascent =
640 s->first_glyph->slice.glyphless.lower_yoff
641 - s->first_glyph->slice.glyphless.upper_yoff;
642 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
643 }
644 code = alloca (sizeof (FT_UInt) * len);
645 for (i = 0; i < len; i++)
646 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
647 | XCHAR2B_BYTE2 (s->char2b + from + i));
648
649 if (s->padding_p)
650 for (i = 0; i < len; i++)
651 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
652 x + i, y, code + i, 1);
653 else
654 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
655 x, y, code, len);
656 unblock_input ();
657
658 return len;
659 }
660
661 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
662 static Lisp_Object
663 xftfont_shape (Lisp_Object lgstring)
664 {
665 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
666 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
667 FT_Face ft_face;
668 Lisp_Object val;
669
670 ft_face = XftLockFace (xftfont_info->xftfont);
671 xftfont_info->ft_size = ft_face->size;
672 val = ftfont_driver.shape (lgstring);
673 XftUnlockFace (xftfont_info->xftfont);
674 return val;
675 }
676 #endif
677
678 static int
679 xftfont_end_for_frame (struct frame *f)
680 {
681 XftDraw *xft_draw;
682
683 /* Don't do anything if display is dead */
684 if (FRAME_X_DISPLAY (f) == NULL) return 0;
685
686 xft_draw = font_get_frame_data (f, Qxft);
687
688 if (xft_draw)
689 {
690 block_input ();
691 XftDrawDestroy (xft_draw);
692 unblock_input ();
693 font_put_frame_data (f, Qxft, NULL);
694 }
695 return 0;
696 }
697
698 static bool
699 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
700 Lisp_Object entity)
701 {
702 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
703 FcPattern *oldpat = info->xftfont->pattern;
704 Display *display = FRAME_X_DISPLAY (f);
705 FcPattern *pat = FcPatternCreate ();
706 FcBool b1, b2;
707 bool ok = false;
708 int i1, i2, r1, r2;
709
710 xftfont_add_rendering_parameters (pat, entity);
711 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
712
713 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
714 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
715 if (r1 != r2 || b1 != b2) goto out;
716 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
717 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
718 if (r1 != r2 || b1 != b2) goto out;
719 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
720 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
721 if (r1 != r2 || b1 != b2) goto out;
722 #ifdef FC_EMBOLDEN
723 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
724 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
725 if (r1 != r2 || b1 != b2) goto out;
726 #endif
727 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
728 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
729 if (r1 != r2 || i1 != i2) goto out;
730 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
731 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
732 if (r1 != r2 || i1 != i2) goto out;
733 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
734 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
735 if (r1 != r2 || i1 != i2) goto out;
736
737 ok = true;
738 out:
739 FcPatternDestroy (pat);
740 return ok;
741 }
742
743 void
744 syms_of_xftfont (void)
745 {
746 DEFSYM (Qxft, "xft");
747 DEFSYM (QChinting, ":hinting");
748 DEFSYM (QCautohint, ":autohint");
749 DEFSYM (QChintstyle, ":hintstyle");
750 DEFSYM (QCrgba, ":rgba");
751 DEFSYM (QCembolden, ":embolden");
752 DEFSYM (QClcdfilter, ":lcdfilter");
753
754 DEFVAR_BOOL ("xft-font-ascent-descent-override",
755 xft_font_ascent_descent_override,
756 doc: /* Non-nil means override the ascent and descent values for Xft font driver.
757 This is needed with some fonts to correct vertical overlap of glyphs. */);
758 xft_font_ascent_descent_override = 0;
759
760 ascii_printable[0] = 0;
761
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
780
781 register_font_driver (&xftfont_driver, NULL);
782 }