avoid recursive `require' when loading semantic
[bpt/emacs.git] / src / xftfont.c
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2014 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
326 /* Substitute in values from X resources and XftDefaultSet. */
327 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
328 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
329 xftfont_fix_match (pat, match);
330
331 FcPatternDestroy (pat);
332 xftfont = XftFontOpenPattern (display, match);
333 if (!xftfont)
334 {
335 unblock_input ();
336 XftPatternDestroy (match);
337 return Qnil;
338 }
339 ft_face = XftLockFace (xftfont);
340 unblock_input ();
341
342 /* We should not destroy PAT here because it is kept in XFTFONT and
343 destroyed automatically when XFTFONT is closed. */
344 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
345 ASET (font_object, FONT_TYPE_INDEX, Qxft);
346 len = font_unparse_xlfd (entity, size, name, 256);
347 if (len > 0)
348 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
349 len = font_unparse_fcname (entity, size, name, 256);
350 if (len > 0)
351 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
352 else
353 ASET (font_object, FONT_FULLNAME_INDEX,
354 AREF (font_object, FONT_NAME_INDEX));
355 ASET (font_object, FONT_FILE_INDEX, filename);
356 ASET (font_object, FONT_FORMAT_INDEX,
357 ftfont_font_format (xftfont->pattern, filename));
358 font = XFONT_OBJECT (font_object);
359 font->pixel_size = size;
360 font->driver = &xftfont_driver;
361 font->encoding_charset = font->repertory_charset = -1;
362
363 xftfont_info = (struct xftfont_info *) font;
364 xftfont_info->display = display;
365 xftfont_info->xftfont = xftfont;
366 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
367 /* This means that there's no need of transformation. */
368 xftfont_info->matrix.xx = 0;
369 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
370 == FcResultMatch)
371 {
372 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
373 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
374 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
375 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
376 }
377 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
378 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
379 else
380 spacing = FC_PROPORTIONAL;
381 if (! ascii_printable[0])
382 {
383 int ch;
384 for (ch = 0; ch < 95; ch++)
385 ascii_printable[ch] = ' ' + ch;
386 }
387 block_input ();
388
389 /* Unfortunately Xft doesn't provide a way to get minimum char
390 width. So, we set min_width to space_width. */
391
392 if (spacing != FC_PROPORTIONAL
393 #ifdef FC_DUAL
394 && spacing != FC_DUAL
395 #endif /* FC_DUAL */
396 )
397 {
398 font->min_width = font->max_width = font->average_width
399 = font->space_width = xftfont->max_advance_width;
400 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
401 }
402 else
403 {
404 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
405 font->min_width = font->max_width = font->space_width
406 = extents.xOff;
407 if (font->space_width <= 0)
408 /* dirty workaround */
409 font->space_width = pixel_size;
410 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
411 font->average_width = (font->space_width + extents.xOff) / 95;
412 }
413 unblock_input ();
414
415 font->ascent = xftfont->ascent;
416 font->descent = xftfont->descent;
417 if (pixel_size >= 5)
418 {
419 /* The above condition is a dirty workaround because
420 XftTextExtents8 behaves strangely for some fonts
421 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
422 if (font->ascent < extents.y)
423 font->ascent = extents.y;
424 if (font->descent < extents.height - extents.y)
425 font->descent = extents.height - extents.y;
426 }
427 font->height = font->ascent + font->descent;
428
429 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
430 {
431 int upEM = ft_face->units_per_EM;
432
433 font->underline_position = -ft_face->underline_position * size / upEM;
434 font->underline_thickness = ft_face->underline_thickness * size / upEM;
435 if (font->underline_thickness > 2)
436 font->underline_position -= font->underline_thickness / 2;
437 }
438 else
439 {
440 font->underline_position = -1;
441 font->underline_thickness = 0;
442 }
443 #ifdef HAVE_LIBOTF
444 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
445 xftfont_info->otf = NULL;
446 #endif /* HAVE_LIBOTF */
447 xftfont_info->ft_size = ft_face->size;
448
449 font->baseline_offset = 0;
450 font->relative_compose = 0;
451 font->default_ascent = 0;
452 font->vertical_centering = 0;
453 #ifdef FT_BDF_H
454 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
455 {
456 BDF_PropertyRec rec;
457
458 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
459 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
460 font->baseline_offset = rec.u.integer;
461 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
462 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
463 font->relative_compose = rec.u.integer;
464 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
465 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
466 font->default_ascent = rec.u.integer;
467 }
468 #endif
469
470 return font_object;
471 }
472
473 static void
474 xftfont_close (struct font *font)
475 {
476 struct x_display_info *xdi;
477 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
478
479 #ifdef HAVE_LIBOTF
480 if (xftfont_info->otf)
481 {
482 OTF_close (xftfont_info->otf);
483 xftfont_info->otf = NULL;
484 }
485 #endif
486
487 /* See comment in xfont_close. */
488 if (xftfont_info->xftfont
489 && ((xdi = x_display_info_for_display (xftfont_info->display))
490 && xftfont_info->x_display_id == xdi->x_id))
491 {
492 block_input ();
493 XftUnlockFace (xftfont_info->xftfont);
494 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
495 unblock_input ();
496 xftfont_info->xftfont = NULL;
497 }
498 }
499
500 static void
501 xftfont_prepare_face (struct frame *f, struct face *face)
502 {
503 struct xftface_info *xftface_info;
504
505 #if 0
506 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
507 if (face != face->ascii_face)
508 {
509 face->extra = face->ascii_face->extra;
510 return;
511 }
512 #endif
513
514 xftface_info = xmalloc (sizeof *xftface_info);
515 xftfont_get_colors (f, face, face->gc, NULL,
516 &xftface_info->xft_fg, &xftface_info->xft_bg);
517 face->extra = xftface_info;
518 }
519
520 static void
521 xftfont_done_face (struct frame *f, struct face *face)
522 {
523 struct xftface_info *xftface_info;
524
525 #if 0
526 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
527 if (face != face->ascii_face
528 || ! face->extra)
529 return;
530 #endif
531
532 xftface_info = (struct xftface_info *) face->extra;
533 if (xftface_info)
534 {
535 xfree (xftface_info);
536 face->extra = NULL;
537 }
538 }
539
540 static int
541 xftfont_has_char (Lisp_Object font, int c)
542 {
543 struct xftfont_info *xftfont_info;
544 struct charset *cs = NULL;
545
546 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
547 && charset_jisx0208 >= 0)
548 cs = CHARSET_FROM_ID (charset_jisx0208);
549 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
550 && charset_ksc5601 >= 0)
551 cs = CHARSET_FROM_ID (charset_ksc5601);
552 if (cs)
553 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
554
555 if (FONT_ENTITY_P (font))
556 return ftfont_driver.has_char (font, c);
557 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
558 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
559 (FcChar32) c) == FcTrue);
560 }
561
562 static unsigned
563 xftfont_encode_char (struct font *font, int c)
564 {
565 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
566 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
567 (FcChar32) c);
568
569 return (code ? code : FONT_INVALID_CODE);
570 }
571
572 static int
573 xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
574 {
575 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
576 XGlyphInfo extents;
577
578 block_input ();
579 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
580 &extents);
581 unblock_input ();
582 if (metrics)
583 {
584 metrics->lbearing = - extents.x;
585 metrics->rbearing = - extents.x + extents.width;
586 metrics->width = extents.xOff;
587 metrics->ascent = extents.y;
588 metrics->descent = extents.height - extents.y;
589 }
590 return extents.xOff;
591 }
592
593 static XftDraw *
594 xftfont_get_xft_draw (struct frame *f)
595 {
596 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
597
598 if (! xft_draw)
599 {
600 block_input ();
601 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
602 FRAME_X_WINDOW (f),
603 FRAME_X_VISUAL (f),
604 FRAME_X_COLORMAP (f));
605 unblock_input ();
606 eassert (xft_draw != NULL);
607 font_put_frame_data (f, &xftfont_driver, xft_draw);
608 }
609 return xft_draw;
610 }
611
612 static int
613 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
614 bool with_background)
615 {
616 struct frame *f = s->f;
617 struct face *face = s->face;
618 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
619 struct xftface_info *xftface_info = NULL;
620 XftDraw *xft_draw = xftfont_get_xft_draw (f);
621 FT_UInt *code;
622 XftColor fg, bg;
623 int len = to - from;
624 int i;
625
626 if (s->font == face->font)
627 xftface_info = (struct xftface_info *) face->extra;
628 xftfont_get_colors (f, face, s->gc, xftface_info,
629 &fg, with_background ? &bg : NULL);
630 block_input ();
631 if (s->num_clips > 0)
632 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
633 else
634 XftDrawSetClip (xft_draw, NULL);
635
636 if (with_background)
637 XftDrawRect (xft_draw, &bg,
638 x, y - s->font->ascent, s->width, s->font->height);
639 code = alloca (sizeof (FT_UInt) * len);
640 for (i = 0; i < len; i++)
641 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
642 | XCHAR2B_BYTE2 (s->char2b + from + i));
643
644 if (s->padding_p)
645 for (i = 0; i < len; i++)
646 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
647 x + i, y, code + i, 1);
648 else
649 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
650 x, y, code, len);
651 unblock_input ();
652
653 return len;
654 }
655
656 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
657 static Lisp_Object
658 xftfont_shape (Lisp_Object lgstring)
659 {
660 struct font *font;
661 struct xftfont_info *xftfont_info;
662 FT_Face ft_face;
663 Lisp_Object val;
664
665 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
666 xftfont_info = (struct xftfont_info *) font;
667 ft_face = XftLockFace (xftfont_info->xftfont);
668 xftfont_info->ft_size = ft_face->size;
669 val = ftfont_driver.shape (lgstring);
670 XftUnlockFace (xftfont_info->xftfont);
671 return val;
672 }
673 #endif
674
675 static int
676 xftfont_end_for_frame (struct frame *f)
677 {
678 XftDraw *xft_draw;
679
680 /* Don't do anything if display is dead */
681 if (FRAME_X_DISPLAY (f) == NULL) return 0;
682
683 xft_draw = font_get_frame_data (f, &xftfont_driver);
684
685 if (xft_draw)
686 {
687 block_input ();
688 XftDrawDestroy (xft_draw);
689 unblock_input ();
690 font_put_frame_data (f, &xftfont_driver, NULL);
691 }
692 return 0;
693 }
694
695 static bool
696 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
697 Lisp_Object entity)
698 {
699 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
700 FcPattern *oldpat = info->xftfont->pattern;
701 Display *display = FRAME_X_DISPLAY (f);
702 FcPattern *pat = FcPatternCreate ();
703 FcBool b1, b2;
704 bool ok = 0;
705 int i1, i2, r1, r2;
706
707 xftfont_add_rendering_parameters (pat, entity);
708 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
709
710 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
711 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
712 if (r1 != r2 || b1 != b2) goto out;
713 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
714 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
715 if (r1 != r2 || b1 != b2) goto out;
716 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
717 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
718 if (r1 != r2 || b1 != b2) goto out;
719 #ifdef FC_EMBOLDEN
720 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
721 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
722 if (r1 != r2 || b1 != b2) goto out;
723 #endif
724 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
725 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
726 if (r1 != r2 || i1 != i2) goto out;
727 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
728 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
729 if (r1 != r2 || i1 != i2) goto out;
730 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
731 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
732 if (r1 != r2 || i1 != i2) goto out;
733
734 ok = 1;
735 out:
736 FcPatternDestroy (pat);
737 return ok;
738 }
739
740 void
741 syms_of_xftfont (void)
742 {
743 DEFSYM (Qxft, "xft");
744 DEFSYM (QChinting, ":hinting");
745 DEFSYM (QCautohint, ":autohint");
746 DEFSYM (QChintstyle, ":hintstyle");
747 DEFSYM (QCrgba, ":rgba");
748 DEFSYM (QCembolden, ":embolden");
749 DEFSYM (QClcdfilter, ":lcdfilter");
750
751 ascii_printable[0] = 0;
752
753 xftfont_driver = ftfont_driver;
754 xftfont_driver.type = Qxft;
755 xftfont_driver.get_cache = xfont_driver.get_cache;
756 xftfont_driver.list = xftfont_list;
757 xftfont_driver.match = xftfont_match;
758 xftfont_driver.open = xftfont_open;
759 xftfont_driver.close = xftfont_close;
760 xftfont_driver.prepare_face = xftfont_prepare_face;
761 xftfont_driver.done_face = xftfont_done_face;
762 xftfont_driver.has_char = xftfont_has_char;
763 xftfont_driver.encode_char = xftfont_encode_char;
764 xftfont_driver.text_extents = xftfont_text_extents;
765 xftfont_driver.draw = xftfont_draw;
766 xftfont_driver.end_for_frame = xftfont_end_for_frame;
767 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
768 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
769 xftfont_driver.shape = xftfont_shape;
770 #endif
771
772 register_font_driver (&xftfont_driver, NULL);
773 }