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