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