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