Handle system default font and changing font parameters.
[bpt/emacs.git] / src / xftfont.c
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
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 "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
38
39 /* Xft font driver. */
40
41 static Lisp_Object Qxft;
42 static Lisp_Object QChinting , QCautohint, QChintstyle, QCrgba, QCembolden;
43
44 /* The actual structure for Xft font that can be casted to struct
45 font. */
46
47 struct xftfont_info
48 {
49 struct font font;
50 /* The following four members must be here in this order to be
51 compatible with struct ftfont_info (in ftfont.c). */
52 #ifdef HAVE_LIBOTF
53 int maybe_otf; /* Flag to tell if this may be OTF or not. */
54 OTF *otf;
55 #endif /* HAVE_LIBOTF */
56 FT_Size ft_size;
57 int index;
58 Display *display;
59 int screen;
60 XftFont *xftfont;
61 };
62
63 /* Structure pointed by (struct face *)->extra */
64
65 struct xftface_info
66 {
67 XftColor xft_fg; /* color for face->foreground */
68 XftColor xft_bg; /* color for face->background */
69 };
70
71 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
72 struct xftface_info *,
73 XftColor *fg, XftColor *bg));
74
75
76 /* Setup foreground and background colors of GC into FG and BG. If
77 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
78 may be NULL. */
79
80 static void
81 xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
82 FRAME_PTR f;
83 struct face *face;
84 GC gc;
85 struct xftface_info *xftface_info;
86 XftColor *fg, *bg;
87 {
88 if (xftface_info && face->gc == gc)
89 {
90 *fg = xftface_info->xft_fg;
91 if (bg)
92 *bg = xftface_info->xft_bg;
93 }
94 else
95 {
96 XGCValues xgcv;
97 int fg_done = 0, bg_done = 0;
98
99 BLOCK_INPUT;
100 XGetGCValues (FRAME_X_DISPLAY (f), gc,
101 GCForeground | GCBackground, &xgcv);
102 if (xftface_info)
103 {
104 if (xgcv.foreground == face->foreground)
105 *fg = xftface_info->xft_fg, fg_done = 1;
106 else if (xgcv.foreground == face->background)
107 *fg = xftface_info->xft_bg, fg_done = 1;
108 if (! bg)
109 bg_done = 1;
110 else if (xgcv.background == face->background)
111 *bg = xftface_info->xft_bg, bg_done = 1;
112 else if (xgcv.background == face->foreground)
113 *bg = xftface_info->xft_fg, bg_done = 1;
114 }
115
116 if (fg_done + bg_done < 2)
117 {
118 XColor colors[2];
119
120 colors[0].pixel = fg->pixel = xgcv.foreground;
121 if (bg)
122 colors[1].pixel = bg->pixel = xgcv.background;
123 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
124 bg ? 2 : 1);
125 fg->color.alpha = 0xFFFF;
126 fg->color.red = colors[0].red;
127 fg->color.green = colors[0].green;
128 fg->color.blue = colors[0].blue;
129 if (bg)
130 {
131 bg->color.alpha = 0xFFFF;
132 bg->color.red = colors[1].red;
133 bg->color.green = colors[1].green;
134 bg->color.blue = colors[1].blue;
135 }
136 }
137 UNBLOCK_INPUT;
138 }
139 }
140
141
142 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
143 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
144 static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
145 static void xftfont_close P_ ((FRAME_PTR, struct font *));
146 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
147 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
148 static int xftfont_has_char P_ ((Lisp_Object, int));
149 static unsigned xftfont_encode_char P_ ((struct font *, int));
150 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
151 struct font_metrics *));
152 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
153 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
154
155 struct font_driver xftfont_driver;
156
157 static Lisp_Object
158 xftfont_list (frame, spec)
159 Lisp_Object frame;
160 Lisp_Object spec;
161 {
162 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
163
164 for (tail = list; CONSP (tail); tail = XCDR (tail))
165 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
166 return list;
167 }
168
169 static Lisp_Object
170 xftfont_match (frame, spec)
171 Lisp_Object frame;
172 Lisp_Object spec;
173 {
174 Lisp_Object entity = ftfont_driver.match (frame, spec);
175
176 if (! NILP (entity))
177 ASET (entity, FONT_TYPE_INDEX, Qxft);
178 return entity;
179 }
180
181 extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
182 extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
183 extern Lisp_Object QCantialias;
184
185 static FcChar8 ascii_printable[95];
186
187 static void
188 xftfont_fix_match (pat, match)
189 FcPattern *pat, *match;
190 {
191 /* These values are not used for matching (except antialias), but for
192 rendering, so make sure they are carried over to the match.
193 We also put antialias here because most fonts are antialiased, so
194 the match will have antialias true. */
195
196 FcBool b = FcTrue;
197 int i;
198 double dpi;
199
200 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
201 if (! b)
202 {
203 FcPatternDel (match, FC_ANTIALIAS);
204 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
205 }
206 FcPatternGetBool (pat, FC_HINTING, 0, &b);
207 if (! b)
208 {
209 FcPatternDel (match, FC_HINTING);
210 FcPatternAddBool (match, FC_HINTING, FcFalse);
211 }
212 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
213 {
214 FcPatternDel (match, FC_HINT_STYLE);
215 FcPatternAddInteger (match, FC_HINT_STYLE, i);
216 }
217 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
218 {
219 FcPatternDel (match, FC_LCD_FILTER);
220 FcPatternAddInteger (match, FC_LCD_FILTER, i);
221 }
222 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
223 {
224 FcPatternDel (match, FC_RGBA);
225 FcPatternAddInteger (match, FC_RGBA, i);
226 }
227 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
228 {
229 FcPatternDel (match, FC_DPI);
230 FcPatternAddDouble (match, FC_DPI, dpi);
231 }
232 }
233
234 static Lisp_Object
235 xftfont_open (f, entity, pixel_size)
236 FRAME_PTR f;
237 Lisp_Object entity;
238 int pixel_size;
239 {
240 FcResult result;
241 Display *display = FRAME_X_DISPLAY (f);
242 Lisp_Object val, filename, index, tail, font_object;
243 FcPattern *pat = NULL, *match;
244 struct xftfont_info *xftfont_info = NULL;
245 struct font *font;
246 double size = 0;
247 XftFont *xftfont = NULL;
248 int spacing;
249 char name[256];
250 int len, i;
251 XGlyphInfo extents;
252 FT_Face ft_face;
253
254 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
255 if (! CONSP (val))
256 return Qnil;
257 val = XCDR (val);
258 filename = XCAR (val);
259 index = XCDR (val);
260 size = XINT (AREF (entity, FONT_SIZE_INDEX));
261 if (size == 0)
262 size = pixel_size;
263 pat = FcPatternCreate ();
264 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
265 i = FONT_SLANT_NUMERIC (entity) - 100;
266 if (i < 0) i = 0;
267 FcPatternAddInteger (pat, FC_SLANT, i);
268 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
269 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
270 val = AREF (entity, FONT_FAMILY_INDEX);
271 if (! NILP (val))
272 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
273 val = AREF (entity, FONT_FOUNDRY_INDEX);
274 if (! NILP (val))
275 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
276 val = AREF (entity, FONT_SPACING_INDEX);
277 if (! NILP (val))
278 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
279 val = AREF (entity, FONT_DPI_INDEX);
280 if (! NILP (val))
281 {
282 double dbl = XINT (val);
283
284 FcPatternAddDouble (pat, FC_DPI, dbl);
285 }
286 val = AREF (entity, FONT_AVGWIDTH_INDEX);
287 if (INTEGERP (val) && XINT (val) == 0)
288 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
289 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
290 over 10x20-ISO8859-1.pcf.gz). */
291 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
292
293 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
294 {
295 Lisp_Object key, val;
296
297 key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
298 if (EQ (key, QCantialias))
299 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
300 else if (EQ (key, QChinting))
301 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
302 else if (EQ (key, QCautohint))
303 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
304 else if (EQ (key, QChintstyle))
305 {
306 if (INTEGERP (val))
307 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
308 }
309 else if (EQ (key, QCrgba))
310 {
311 if (INTEGERP (val))
312 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
313 }
314 #ifdef FC_EMBOLDEN
315 else if (EQ (key, QCembolden))
316 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
317 #endif
318 }
319
320 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
321 FcPatternAddInteger (pat, FC_INDEX, XINT (index));
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 = pixel_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->screen = FRAME_X_SCREEN_NUMBER (f);
376 xftfont_info->xftfont = xftfont;
377 font->pixel_size = size;
378 font->driver = &xftfont_driver;
379 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
380 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
381 else
382 spacing = FC_PROPORTIONAL;
383 if (! ascii_printable[0])
384 {
385 int i;
386 for (i = 0; i < 95; i++)
387 ascii_printable[i] = ' ' + i;
388 }
389 BLOCK_INPUT;
390 if (spacing != FC_PROPORTIONAL)
391 {
392 font->min_width = font->average_width = font->space_width
393 = xftfont->max_advance_width;
394 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
395 }
396 else
397 {
398 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
399 font->space_width = extents.xOff;
400 if (font->space_width <= 0)
401 /* dirty workaround */
402 font->space_width = pixel_size;
403 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
404 font->average_width = (font->space_width + extents.xOff) / 95;
405 }
406 UNBLOCK_INPUT;
407
408 font->ascent = xftfont->ascent;
409 font->descent = xftfont->descent;
410 if (pixel_size >= 5)
411 {
412 /* The above condition is a dirty workaround because
413 XftTextExtents8 behaves strangely for some fonts
414 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
415 if (font->ascent < extents.y)
416 font->ascent = extents.y;
417 if (font->descent < extents.height - extents.y)
418 font->descent = extents.height - extents.y;
419 }
420 font->height = font->ascent + font->descent;
421
422 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
423 {
424 int upEM = ft_face->units_per_EM;
425
426 font->underline_position = -ft_face->underline_position * size / upEM;
427 font->underline_thickness = ft_face->underline_thickness * size / upEM;
428 if (font->underline_thickness > 2)
429 font->underline_position -= font->underline_thickness / 2;
430 }
431 else
432 {
433 font->underline_position = -1;
434 font->underline_thickness = 0;
435 }
436 #ifdef HAVE_LIBOTF
437 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
438 xftfont_info->otf = NULL;
439 #endif /* HAVE_LIBOTF */
440 xftfont_info->ft_size = ft_face->size;
441
442 /* Unfortunately Xft doesn't provide a way to get minimum char
443 width. So, we use space_width instead. */
444 font->min_width = font->space_width;
445
446 font->baseline_offset = 0;
447 font->relative_compose = 0;
448 font->default_ascent = 0;
449 font->vertical_centering = 0;
450 #ifdef FT_BDF_H
451 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
452 {
453 BDF_PropertyRec rec;
454
455 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
456 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
457 font->baseline_offset = rec.u.integer;
458 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
459 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
460 font->relative_compose = rec.u.integer;
461 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
462 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
463 font->default_ascent = rec.u.integer;
464 }
465 #endif
466
467 return font_object;
468 }
469
470 static void
471 xftfont_close (f, font)
472 FRAME_PTR f;
473 struct font *font;
474 {
475 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
476
477 #ifdef HAVE_LIBOTF
478 if (xftfont_info->otf)
479 OTF_close (xftfont_info->otf);
480 #endif
481 BLOCK_INPUT;
482 XftUnlockFace (xftfont_info->xftfont);
483 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
484 UNBLOCK_INPUT;
485 }
486
487 static int
488 xftfont_prepare_face (f, face)
489 FRAME_PTR f;
490 struct face *face;
491 {
492 struct xftface_info *xftface_info;
493
494 #if 0
495 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
496 if (face != face->ascii_face)
497 {
498 face->extra = face->ascii_face->extra;
499 return 0;
500 }
501 #endif
502
503 xftface_info = malloc (sizeof (struct xftface_info));
504 if (! xftface_info)
505 return -1;
506 xftfont_get_colors (f, face, face->gc, NULL,
507 &xftface_info->xft_fg, &xftface_info->xft_bg);
508 face->extra = xftface_info;
509 return 0;
510 }
511
512 static void
513 xftfont_done_face (f, face)
514 FRAME_PTR f;
515 struct face *face;
516 {
517 struct xftface_info *xftface_info;
518
519 #if 0
520 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
521 if (face != face->ascii_face
522 || ! face->extra)
523 return;
524 #endif
525
526 xftface_info = (struct xftface_info *) face->extra;
527 if (xftface_info)
528 {
529 free (xftface_info);
530 face->extra = NULL;
531 }
532 }
533
534 extern Lisp_Object Qja, Qko;
535
536 static int
537 xftfont_has_char (font, c)
538 Lisp_Object font;
539 int c;
540 {
541 struct xftfont_info *xftfont_info;
542 struct charset *cs = NULL;
543
544 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
545 && charset_jisx0208 >= 0)
546 cs = CHARSET_FROM_ID (charset_jisx0208);
547 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
548 && charset_ksc5601 >= 0)
549 cs = CHARSET_FROM_ID (charset_ksc5601);
550 if (cs)
551 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
552
553 if (FONT_ENTITY_P (font))
554 return ftfont_driver.has_char (font, c);
555 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
556 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
557 (FcChar32) c) == FcTrue);
558 }
559
560 static unsigned
561 xftfont_encode_char (font, c)
562 struct font *font;
563 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 (font, code, nglyphs, metrics)
574 struct font *font;
575 unsigned *code;
576 int nglyphs;
577 struct font_metrics *metrics;
578 {
579 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
580 XGlyphInfo extents;
581
582 BLOCK_INPUT;
583 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
584 &extents);
585 UNBLOCK_INPUT;
586 if (metrics)
587 {
588 metrics->lbearing = - extents.x;
589 metrics->rbearing = - extents.x + extents.width;
590 metrics->width = extents.xOff;
591 metrics->ascent = extents.y;
592 metrics->descent = extents.height - extents.y;
593 }
594 return extents.xOff;
595 }
596
597 static XftDraw *
598 xftfont_get_xft_draw (f)
599 FRAME_PTR f;
600 {
601 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
602
603 if (! xft_draw)
604 {
605 BLOCK_INPUT;
606 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
607 FRAME_X_WINDOW (f),
608 FRAME_X_VISUAL (f),
609 FRAME_X_COLORMAP (f));
610 UNBLOCK_INPUT;
611 if (! xft_draw)
612 abort ();
613 font_put_frame_data (f, &xftfont_driver, xft_draw);
614 }
615 return xft_draw;
616 }
617
618 static int
619 xftfont_draw (s, from, to, x, y, with_background)
620 struct glyph_string *s;
621 int from, to, x, y, with_background;
622 {
623 FRAME_PTR f = s->f;
624 struct face *face = s->face;
625 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
626 struct xftface_info *xftface_info = NULL;
627 XftDraw *xft_draw = xftfont_get_xft_draw (f);
628 FT_UInt *code;
629 XftColor fg, bg;
630 int len = to - from;
631 int i;
632
633 if (s->font == face->font)
634 xftface_info = (struct xftface_info *) face->extra;
635 xftfont_get_colors (f, face, s->gc, xftface_info,
636 &fg, with_background ? &bg : NULL);
637 BLOCK_INPUT;
638 if (s->num_clips > 0)
639 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
640 else
641 XftDrawSetClip (xft_draw, NULL);
642
643 if (with_background)
644 XftDrawRect (xft_draw, &bg,
645 x, y - face->font->ascent, s->width, face->font->height);
646 code = alloca (sizeof (FT_UInt) * len);
647 for (i = 0; i < len; i++)
648 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
649 | XCHAR2B_BYTE2 (s->char2b + from + i));
650
651 if (s->padding_p)
652 for (i = 0; i < len; i++)
653 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
654 x + i, y, code + i, 1);
655 else
656 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
657 x, y, code, len);
658 UNBLOCK_INPUT;
659
660 return len;
661 }
662
663 static int
664 xftfont_end_for_frame (f)
665 FRAME_PTR f;
666 {
667 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
668
669 if (xft_draw)
670 {
671 BLOCK_INPUT;
672 XftDrawDestroy (xft_draw);
673 UNBLOCK_INPUT;
674 font_put_frame_data (f, &xftfont_driver, NULL);
675 }
676 return 0;
677 }
678
679 void
680 syms_of_xftfont ()
681 {
682 DEFSYM (Qxft, "xft");
683 DEFSYM (QChinting, ":hinting");
684 DEFSYM (QCautohint, ":autohint");
685 DEFSYM (QChintstyle, ":hintstyle");
686 DEFSYM (QCrgba, ":rgba");
687 DEFSYM (QCembolden, ":embolden");
688
689 xftfont_driver = ftfont_driver;
690 xftfont_driver.type = Qxft;
691 xftfont_driver.get_cache = xfont_driver.get_cache;
692 xftfont_driver.list = xftfont_list;
693 xftfont_driver.match = xftfont_match;
694 xftfont_driver.open = xftfont_open;
695 xftfont_driver.close = xftfont_close;
696 xftfont_driver.prepare_face = xftfont_prepare_face;
697 xftfont_driver.done_face = xftfont_done_face;
698 xftfont_driver.has_char = xftfont_has_char;
699 xftfont_driver.encode_char = xftfont_encode_char;
700 xftfont_driver.text_extents = xftfont_text_extents;
701 xftfont_driver.draw = xftfont_draw;
702 xftfont_driver.end_for_frame = xftfont_end_for_frame;
703
704 register_font_driver (&xftfont_driver, NULL);
705 }
706
707 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
708 (do not change this comment) */