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