Fix wrong font metrics for mouse highlight (backport 2011-12-15T02:12:08Z!handa@m17n...
[emacs.git] / src / xftfont.c
blobaa31fd9d868683482d791f23021f77e4adf5dac1
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 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
7 This file is part of GNU Emacs.
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.
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.
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/>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <setjmp.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xft/Xft.h>
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"
40 /* Xft font driver. */
42 static Lisp_Object Qxft;
43 static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
44 QClcdfilter;
46 /* The actual structure for Xft font that can be casted to struct
47 font. */
49 struct xftfont_info
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;
66 /* Structure pointed by (struct face *)->extra */
68 struct xftface_info
70 XftColor xft_fg; /* color for face->foreground */
71 XftColor xft_bg; /* color for face->background */
74 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
75 struct xftface_info *,
76 XftColor *fg, XftColor *bg));
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. */
83 static void
84 xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
85 FRAME_PTR f;
86 struct face *face;
87 GC gc;
88 struct xftface_info *xftface_info;
89 XftColor *fg, *bg;
91 if (xftface_info && face->gc == gc)
93 *fg = xftface_info->xft_fg;
94 if (bg)
95 *bg = xftface_info->xft_bg;
97 else
99 XGCValues xgcv;
100 int fg_done = 0, bg_done = 0;
102 BLOCK_INPUT;
103 XGetGCValues (FRAME_X_DISPLAY (f), gc,
104 GCForeground | GCBackground, &xgcv);
105 if (xftface_info)
107 if (xgcv.foreground == face->foreground)
108 *fg = xftface_info->xft_fg, fg_done = 1;
109 else if (xgcv.foreground == face->background)
110 *fg = xftface_info->xft_bg, fg_done = 1;
111 if (! bg)
112 bg_done = 1;
113 else if (xgcv.background == face->background)
114 *bg = xftface_info->xft_bg, bg_done = 1;
115 else if (xgcv.background == face->foreground)
116 *bg = xftface_info->xft_fg, bg_done = 1;
119 if (fg_done + bg_done < 2)
121 XColor colors[2];
123 colors[0].pixel = fg->pixel = xgcv.foreground;
124 if (bg)
125 colors[1].pixel = bg->pixel = xgcv.background;
126 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
127 bg ? 2 : 1);
128 fg->color.alpha = 0xFFFF;
129 fg->color.red = colors[0].red;
130 fg->color.green = colors[0].green;
131 fg->color.blue = colors[0].blue;
132 if (bg)
134 bg->color.alpha = 0xFFFF;
135 bg->color.red = colors[1].red;
136 bg->color.green = colors[1].green;
137 bg->color.blue = colors[1].blue;
140 UNBLOCK_INPUT;
145 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
146 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
147 static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
148 static void xftfont_close P_ ((FRAME_PTR, struct font *));
149 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
150 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
151 static int xftfont_has_char P_ ((Lisp_Object, int));
152 static unsigned xftfont_encode_char P_ ((struct font *, int));
153 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
154 struct font_metrics *));
155 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
156 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
158 struct font_driver xftfont_driver;
160 static Lisp_Object
161 xftfont_list (frame, spec)
162 Lisp_Object frame;
163 Lisp_Object spec;
165 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
167 for (tail = list; CONSP (tail); tail = XCDR (tail))
168 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
169 return list;
172 static Lisp_Object
173 xftfont_match (frame, spec)
174 Lisp_Object frame;
175 Lisp_Object spec;
177 Lisp_Object entity = ftfont_driver.match (frame, spec);
179 if (! NILP (entity))
180 ASET (entity, FONT_TYPE_INDEX, Qxft);
181 return entity;
184 extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
185 extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
186 extern Lisp_Object QCantialias;
188 static FcChar8 ascii_printable[95];
190 static void
191 xftfont_fix_match (pat, match)
192 FcPattern *pat, *match;
194 /* These values are not used for matching (except antialias), but for
195 rendering, so make sure they are carried over to the match.
196 We also put antialias here because most fonts are antialiased, so
197 the match will have antialias true. */
199 FcBool b = FcTrue;
200 int i;
201 double dpi;
203 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
204 if (! b)
206 FcPatternDel (match, FC_ANTIALIAS);
207 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
209 FcPatternGetBool (pat, FC_HINTING, 0, &b);
210 if (! b)
212 FcPatternDel (match, FC_HINTING);
213 FcPatternAddBool (match, FC_HINTING, FcFalse);
215 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
217 FcPatternDel (match, FC_HINT_STYLE);
218 FcPatternAddInteger (match, FC_HINT_STYLE, i);
220 #ifndef FC_LCD_FILTER
221 /* Older fontconfig versions don't have FC_LCD_FILTER. */
222 #define FC_LCD_FILTER "lcdfilter"
223 #endif
224 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
226 FcPatternDel (match, FC_LCD_FILTER);
227 FcPatternAddInteger (match, FC_LCD_FILTER, i);
229 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
231 FcPatternDel (match, FC_RGBA);
232 FcPatternAddInteger (match, FC_RGBA, i);
234 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
236 FcPatternDel (match, FC_DPI);
237 FcPatternAddDouble (match, FC_DPI, dpi);
241 static void
242 xftfont_add_rendering_parameters (pat, entity)
243 FcPattern *pat;
244 Lisp_Object entity;
246 Lisp_Object tail;
247 int ival;
249 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
251 Lisp_Object key = XCAR (XCAR (tail));
252 Lisp_Object val = XCDR (XCAR (tail));
254 if (EQ (key, QCantialias))
255 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
256 else if (EQ (key, QChinting))
257 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
258 else if (EQ (key, QCautohint))
259 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
260 else if (EQ (key, QChintstyle))
262 if (INTEGERP (val))
263 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
264 else if (SYMBOLP (val)
265 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
266 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
268 else if (EQ (key, QCrgba))
270 if (INTEGERP (val))
271 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
272 else if (SYMBOLP (val)
273 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
274 FcPatternAddInteger (pat, FC_RGBA, ival);
276 else if (EQ (key, QClcdfilter))
278 if (INTEGERP (val))
279 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
280 else if (SYMBOLP (val)
281 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
282 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
284 #ifdef FC_EMBOLDEN
285 else if (EQ (key, QCembolden))
286 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
287 #endif
291 static Lisp_Object
292 xftfont_open (f, entity, pixel_size)
293 FRAME_PTR f;
294 Lisp_Object entity;
295 int pixel_size;
297 FcResult result;
298 Display *display = FRAME_X_DISPLAY (f);
299 Lisp_Object val, filename, index, font_object;
300 FcPattern *pat = NULL, *match;
301 struct xftfont_info *xftfont_info = NULL;
302 struct font *font;
303 double size = 0;
304 XftFont *xftfont = NULL;
305 int spacing;
306 char name[256];
307 int len, i;
308 XGlyphInfo extents;
309 FT_Face ft_face;
310 FcMatrix *matrix;
312 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
313 if (! CONSP (val))
314 return Qnil;
315 val = XCDR (val);
316 filename = XCAR (val);
317 index = XCDR (val);
318 size = XINT (AREF (entity, FONT_SIZE_INDEX));
319 if (size == 0)
320 size = pixel_size;
321 pat = FcPatternCreate ();
322 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
323 i = FONT_SLANT_NUMERIC (entity) - 100;
324 if (i < 0) i = 0;
325 FcPatternAddInteger (pat, FC_SLANT, i);
326 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
327 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
328 val = AREF (entity, FONT_FAMILY_INDEX);
329 if (! NILP (val))
330 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
331 val = AREF (entity, FONT_FOUNDRY_INDEX);
332 if (! NILP (val))
333 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
334 val = AREF (entity, FONT_SPACING_INDEX);
335 if (! NILP (val))
336 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
337 val = AREF (entity, FONT_DPI_INDEX);
338 if (! NILP (val))
340 double dbl = XINT (val);
342 FcPatternAddDouble (pat, FC_DPI, dbl);
344 val = AREF (entity, FONT_AVGWIDTH_INDEX);
345 if (INTEGERP (val) && XINT (val) == 0)
346 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
347 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
348 over 10x20-ISO8859-1.pcf.gz). */
349 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
351 xftfont_add_rendering_parameters (pat, entity);
353 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
354 FcPatternAddInteger (pat, FC_INDEX, XINT (index));
357 BLOCK_INPUT;
358 /* Make sure that the Xrender extension is added before the Xft one.
359 Otherwise, the close-display hook set by Xft is called after the
360 one for Xrender, and the former tries to re-add the latter. This
361 results in inconsistency of internal states and leads to X
362 protocol error when one reconnects to the same X server.
363 (Bug#1696) */
365 int event_base, error_base;
366 XRenderQueryExtension (display, &event_base, &error_base);
369 /* Substitute in values from X resources and XftDefaultSet. */
370 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
371 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
372 xftfont_fix_match (pat, match);
374 FcPatternDestroy (pat);
375 xftfont = XftFontOpenPattern (display, match);
376 if (!xftfont)
378 UNBLOCK_INPUT;
379 XftPatternDestroy (match);
380 return Qnil;
382 ft_face = XftLockFace (xftfont);
383 UNBLOCK_INPUT;
385 /* We should not destroy PAT here because it is kept in XFTFONT and
386 destroyed automatically when XFTFONT is closed. */
387 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
388 ASET (font_object, FONT_TYPE_INDEX, Qxft);
389 len = font_unparse_xlfd (entity, size, name, 256);
390 if (len > 0)
391 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
392 len = font_unparse_fcname (entity, size, name, 256);
393 if (len > 0)
394 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
395 else
396 ASET (font_object, FONT_FULLNAME_INDEX,
397 AREF (font_object, FONT_NAME_INDEX));
398 ASET (font_object, FONT_FILE_INDEX, filename);
399 ASET (font_object, FONT_FORMAT_INDEX,
400 ftfont_font_format (xftfont->pattern, filename));
401 font = XFONT_OBJECT (font_object);
402 font->pixel_size = pixel_size;
403 font->driver = &xftfont_driver;
404 font->encoding_charset = font->repertory_charset = -1;
406 xftfont_info = (struct xftfont_info *) font;
407 xftfont_info->display = display;
408 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
409 xftfont_info->xftfont = xftfont;
410 /* This means that there's no need of transformation. */
411 xftfont_info->matrix.xx = 0;
412 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
413 == FcResultMatch)
415 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
416 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
417 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
418 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
420 font->pixel_size = size;
421 font->driver = &xftfont_driver;
422 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
423 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
424 else
425 spacing = FC_PROPORTIONAL;
426 if (! ascii_printable[0])
428 int i;
429 for (i = 0; i < 95; i++)
430 ascii_printable[i] = ' ' + i;
432 BLOCK_INPUT;
433 if (spacing != FC_PROPORTIONAL
434 #ifdef FC_DUAL
435 && spacing != FC_DUAL
436 #endif /* FC_DUAL */
439 font->min_width = font->average_width = font->space_width
440 = xftfont->max_advance_width;
441 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
443 else
445 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
446 font->space_width = extents.xOff;
447 if (font->space_width <= 0)
448 /* dirty workaround */
449 font->space_width = pixel_size;
450 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
451 font->average_width = (font->space_width + extents.xOff) / 95;
453 UNBLOCK_INPUT;
455 font->ascent = xftfont->ascent;
456 font->descent = xftfont->descent;
457 if (pixel_size >= 5)
459 /* The above condition is a dirty workaround because
460 XftTextExtents8 behaves strangely for some fonts
461 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
462 if (font->ascent < extents.y)
463 font->ascent = extents.y;
464 if (font->descent < extents.height - extents.y)
465 font->descent = extents.height - extents.y;
467 font->height = font->ascent + font->descent;
469 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
471 int upEM = ft_face->units_per_EM;
473 font->underline_position = -ft_face->underline_position * size / upEM;
474 font->underline_thickness = ft_face->underline_thickness * size / upEM;
475 if (font->underline_thickness > 2)
476 font->underline_position -= font->underline_thickness / 2;
478 else
480 font->underline_position = -1;
481 font->underline_thickness = 0;
483 #ifdef HAVE_LIBOTF
484 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
485 xftfont_info->otf = NULL;
486 #endif /* HAVE_LIBOTF */
487 xftfont_info->ft_size = ft_face->size;
489 /* Unfortunately Xft doesn't provide a way to get minimum char
490 width. So, we use space_width instead. */
491 font->min_width = font->space_width;
493 font->baseline_offset = 0;
494 font->relative_compose = 0;
495 font->default_ascent = 0;
496 font->vertical_centering = 0;
497 #ifdef FT_BDF_H
498 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
500 BDF_PropertyRec rec;
502 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
503 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
504 font->baseline_offset = rec.u.integer;
505 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
506 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
507 font->relative_compose = rec.u.integer;
508 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
509 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
510 font->default_ascent = rec.u.integer;
512 #endif
514 return font_object;
517 static void
518 xftfont_close (f, font)
519 FRAME_PTR f;
520 struct font *font;
522 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
524 #ifdef HAVE_LIBOTF
525 if (xftfont_info->otf)
526 OTF_close (xftfont_info->otf);
527 #endif
528 BLOCK_INPUT;
529 XftUnlockFace (xftfont_info->xftfont);
530 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
531 UNBLOCK_INPUT;
534 static int
535 xftfont_prepare_face (f, face)
536 FRAME_PTR f;
537 struct face *face;
539 struct xftface_info *xftface_info;
541 #if 0
542 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
543 if (face != face->ascii_face)
545 face->extra = face->ascii_face->extra;
546 return 0;
548 #endif
550 xftface_info = malloc (sizeof (struct xftface_info));
551 if (! xftface_info)
552 return -1;
553 xftfont_get_colors (f, face, face->gc, NULL,
554 &xftface_info->xft_fg, &xftface_info->xft_bg);
555 face->extra = xftface_info;
556 return 0;
559 static void
560 xftfont_done_face (f, face)
561 FRAME_PTR f;
562 struct face *face;
564 struct xftface_info *xftface_info;
566 #if 0
567 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
568 if (face != face->ascii_face
569 || ! face->extra)
570 return;
571 #endif
573 xftface_info = (struct xftface_info *) face->extra;
574 if (xftface_info)
576 free (xftface_info);
577 face->extra = NULL;
581 extern Lisp_Object Qja, Qko;
583 static int
584 xftfont_has_char (font, c)
585 Lisp_Object font;
586 int c;
588 struct xftfont_info *xftfont_info;
589 struct charset *cs = NULL;
591 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
592 && charset_jisx0208 >= 0)
593 cs = CHARSET_FROM_ID (charset_jisx0208);
594 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
595 && charset_ksc5601 >= 0)
596 cs = CHARSET_FROM_ID (charset_ksc5601);
597 if (cs)
598 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
600 if (FONT_ENTITY_P (font))
601 return ftfont_driver.has_char (font, c);
602 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
603 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
604 (FcChar32) c) == FcTrue);
607 static unsigned
608 xftfont_encode_char (font, c)
609 struct font *font;
610 int c;
612 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
613 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
614 (FcChar32) c);
616 return (code ? code : FONT_INVALID_CODE);
619 static int
620 xftfont_text_extents (font, code, nglyphs, metrics)
621 struct font *font;
622 unsigned *code;
623 int nglyphs;
624 struct font_metrics *metrics;
626 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
627 XGlyphInfo extents;
629 BLOCK_INPUT;
630 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
631 &extents);
632 UNBLOCK_INPUT;
633 if (metrics)
635 metrics->lbearing = - extents.x;
636 metrics->rbearing = - extents.x + extents.width;
637 metrics->width = extents.xOff;
638 metrics->ascent = extents.y;
639 metrics->descent = extents.height - extents.y;
641 return extents.xOff;
644 static XftDraw *
645 xftfont_get_xft_draw (f)
646 FRAME_PTR f;
648 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
650 if (! xft_draw)
652 BLOCK_INPUT;
653 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
654 FRAME_X_WINDOW (f),
655 FRAME_X_VISUAL (f),
656 FRAME_X_COLORMAP (f));
657 UNBLOCK_INPUT;
658 if (! xft_draw)
659 abort ();
660 font_put_frame_data (f, &xftfont_driver, xft_draw);
662 return xft_draw;
665 static int
666 xftfont_draw (s, from, to, x, y, with_background)
667 struct glyph_string *s;
668 int from, to, x, y, with_background;
670 FRAME_PTR f = s->f;
671 struct face *face = s->face;
672 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
673 struct xftface_info *xftface_info = NULL;
674 XftDraw *xft_draw = xftfont_get_xft_draw (f);
675 FT_UInt *code;
676 XftColor fg, bg;
677 int len = to - from;
678 int i;
680 if (s->font == face->font)
681 xftface_info = (struct xftface_info *) face->extra;
682 xftfont_get_colors (f, face, s->gc, xftface_info,
683 &fg, with_background ? &bg : NULL);
684 BLOCK_INPUT;
685 if (s->num_clips > 0)
686 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
687 else
688 XftDrawSetClip (xft_draw, NULL);
690 if (with_background)
691 XftDrawRect (xft_draw, &bg,
692 x, y - s->font->ascent, s->width, s->font->height);
693 code = alloca (sizeof (FT_UInt) * len);
694 for (i = 0; i < len; i++)
695 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
696 | XCHAR2B_BYTE2 (s->char2b + from + i));
698 if (s->padding_p)
699 for (i = 0; i < len; i++)
700 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
701 x + i, y, code + i, 1);
702 else
703 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
704 x, y, code, len);
705 UNBLOCK_INPUT;
707 return len;
710 Lisp_Object
711 xftfont_shape (Lisp_Object lgstring)
713 struct font *font;
714 struct xftfont_info *xftfont_info;
715 FT_Face ft_face;
716 Lisp_Object val;
718 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
719 xftfont_info = (struct xftfont_info *) font;
720 ft_face = XftLockFace (xftfont_info->xftfont);
721 xftfont_info->ft_size = ft_face->size;
722 val = ftfont_driver.shape (lgstring);
723 XftUnlockFace (xftfont_info->xftfont);
724 return val;
727 static int
728 xftfont_end_for_frame (f)
729 FRAME_PTR f;
731 XftDraw *xft_draw;
733 /* Don't do anything if display is dead */
734 if (FRAME_X_DISPLAY (f) == NULL) return 0;
736 xft_draw = font_get_frame_data (f, &xftfont_driver);
738 if (xft_draw)
740 BLOCK_INPUT;
741 XftDrawDestroy (xft_draw);
742 UNBLOCK_INPUT;
743 font_put_frame_data (f, &xftfont_driver, NULL);
745 return 0;
748 static int
749 xftfont_cached_font_ok (f, font_object, entity)
750 struct frame *f;
751 Lisp_Object font_object;
752 Lisp_Object entity;
755 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
756 FcPattern *oldpat = info->xftfont->pattern;
757 Display *display = FRAME_X_DISPLAY (f);
758 FcPattern *pat = FcPatternCreate ();
759 FcBool b1, b2;
760 int ok = 0, i1, i2, r1, r2;
762 xftfont_add_rendering_parameters (pat, entity);
763 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
765 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
766 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
767 if (r1 != r2 || b1 != b2) goto out;
768 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
769 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
770 if (r1 != r2 || b1 != b2) goto out;
771 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
772 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
773 if (r1 != r2 || b1 != b2) goto out;
774 #ifdef FC_EMBOLDEN
775 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
776 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
777 if (r1 != r2 || b1 != b2) goto out;
778 #endif
779 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
780 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
781 if (r1 != r2 || i1 != i2) goto out;
782 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
783 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
784 if (r1 != r2 || i1 != i2) goto out;
785 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
786 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
787 if (r1 != r2 || i1 != i2) goto out;
789 ok = 1;
790 out:
791 FcPatternDestroy (pat);
792 return ok;
795 void
796 syms_of_xftfont ()
798 DEFSYM (Qxft, "xft");
799 DEFSYM (QChinting, ":hinting");
800 DEFSYM (QCautohint, ":autohint");
801 DEFSYM (QChintstyle, ":hintstyle");
802 DEFSYM (QCrgba, ":rgba");
803 DEFSYM (QCembolden, ":embolden");
804 DEFSYM (QClcdfilter, ":lcdfilter");
806 xftfont_driver = ftfont_driver;
807 xftfont_driver.type = Qxft;
808 xftfont_driver.get_cache = xfont_driver.get_cache;
809 xftfont_driver.list = xftfont_list;
810 xftfont_driver.match = xftfont_match;
811 xftfont_driver.open = xftfont_open;
812 xftfont_driver.close = xftfont_close;
813 xftfont_driver.prepare_face = xftfont_prepare_face;
814 xftfont_driver.done_face = xftfont_done_face;
815 xftfont_driver.has_char = xftfont_has_char;
816 xftfont_driver.encode_char = xftfont_encode_char;
817 xftfont_driver.text_extents = xftfont_text_extents;
818 xftfont_driver.draw = xftfont_draw;
819 xftfont_driver.end_for_frame = xftfont_end_for_frame;
820 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
821 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
822 xftfont_driver.shape = xftfont_shape;
823 #endif
825 register_font_driver (&xftfont_driver, NULL);
828 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
829 (do not change this comment) */