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