Minor cleanups.
[emacs.git] / src / xftfont.c
blob5d4581be4e94b37ae6f74762186fcc92a724a611
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
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 "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
39 /* Xft font driver. */
41 static Lisp_Object Qxft;
42 static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
43 QClcdfilter;
45 /* The actual structure for Xft font that can be casted to struct
46 font. */
48 struct xftfont_info
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 int 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 int screen;
62 XftFont *xftfont;
65 /* Structure pointed by (struct face *)->extra */
67 struct xftface_info
69 XftColor xft_fg; /* color for face->foreground */
70 XftColor xft_bg; /* color for face->background */
73 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
74 struct xftface_info *,
75 XftColor *fg, XftColor *bg));
78 /* Setup foreground and background colors of GC into FG and BG. If
79 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
80 may be NULL. */
82 static void
83 xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
84 FRAME_PTR f;
85 struct face *face;
86 GC gc;
87 struct xftface_info *xftface_info;
88 XftColor *fg, *bg;
90 if (xftface_info && face->gc == gc)
92 *fg = xftface_info->xft_fg;
93 if (bg)
94 *bg = xftface_info->xft_bg;
96 else
98 XGCValues xgcv;
99 int fg_done = 0, bg_done = 0;
101 BLOCK_INPUT;
102 XGetGCValues (FRAME_X_DISPLAY (f), gc,
103 GCForeground | GCBackground, &xgcv);
104 if (xftface_info)
106 if (xgcv.foreground == face->foreground)
107 *fg = xftface_info->xft_fg, fg_done = 1;
108 else if (xgcv.foreground == face->background)
109 *fg = xftface_info->xft_bg, fg_done = 1;
110 if (! bg)
111 bg_done = 1;
112 else if (xgcv.background == face->background)
113 *bg = xftface_info->xft_bg, bg_done = 1;
114 else if (xgcv.background == face->foreground)
115 *bg = xftface_info->xft_fg, bg_done = 1;
118 if (fg_done + bg_done < 2)
120 XColor colors[2];
122 colors[0].pixel = fg->pixel = xgcv.foreground;
123 if (bg)
124 colors[1].pixel = bg->pixel = xgcv.background;
125 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
126 bg ? 2 : 1);
127 fg->color.alpha = 0xFFFF;
128 fg->color.red = colors[0].red;
129 fg->color.green = colors[0].green;
130 fg->color.blue = colors[0].blue;
131 if (bg)
133 bg->color.alpha = 0xFFFF;
134 bg->color.red = colors[1].red;
135 bg->color.green = colors[1].green;
136 bg->color.blue = colors[1].blue;
139 UNBLOCK_INPUT;
144 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
145 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
146 static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
147 static void xftfont_close P_ ((FRAME_PTR, struct font *));
148 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
149 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
150 static int xftfont_has_char P_ ((Lisp_Object, int));
151 static unsigned xftfont_encode_char P_ ((struct font *, int));
152 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
153 struct font_metrics *));
154 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
155 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
157 struct font_driver xftfont_driver;
159 static Lisp_Object
160 xftfont_list (frame, spec)
161 Lisp_Object frame;
162 Lisp_Object spec;
164 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
166 for (tail = list; CONSP (tail); tail = XCDR (tail))
167 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
168 return list;
171 static Lisp_Object
172 xftfont_match (frame, spec)
173 Lisp_Object frame;
174 Lisp_Object spec;
176 Lisp_Object entity = ftfont_driver.match (frame, spec);
178 if (! NILP (entity))
179 ASET (entity, FONT_TYPE_INDEX, Qxft);
180 return entity;
183 extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
184 extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
185 extern Lisp_Object QCantialias;
187 static FcChar8 ascii_printable[95];
189 static void
190 xftfont_fix_match (pat, match)
191 FcPattern *pat, *match;
193 /* These values are not used for matching (except antialias), but for
194 rendering, so make sure they are carried over to the match.
195 We also put antialias here because most fonts are antialiased, so
196 the match will have antialias true. */
198 FcBool b = FcTrue;
199 int i;
200 double dpi;
202 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
203 if (! b)
205 FcPatternDel (match, FC_ANTIALIAS);
206 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
208 FcPatternGetBool (pat, FC_HINTING, 0, &b);
209 if (! b)
211 FcPatternDel (match, FC_HINTING);
212 FcPatternAddBool (match, FC_HINTING, FcFalse);
214 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
216 FcPatternDel (match, FC_HINT_STYLE);
217 FcPatternAddInteger (match, FC_HINT_STYLE, i);
219 #ifndef FC_LCD_FILTER
220 /* Older fontconfig versions don't have FC_LCD_FILTER. */
221 #define FC_LCD_FILTER "lcdfilter"
222 #endif
223 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
225 FcPatternDel (match, FC_LCD_FILTER);
226 FcPatternAddInteger (match, FC_LCD_FILTER, i);
228 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
230 FcPatternDel (match, FC_RGBA);
231 FcPatternAddInteger (match, FC_RGBA, i);
233 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
235 FcPatternDel (match, FC_DPI);
236 FcPatternAddDouble (match, FC_DPI, dpi);
240 static void
241 xftfont_add_rendering_parameters (pat, entity)
242 FcPattern *pat;
243 Lisp_Object entity;
245 Lisp_Object tail;
246 int ival;
248 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
250 Lisp_Object key = XCAR (XCAR (tail));
251 Lisp_Object val = XCDR (XCAR (tail));
253 if (EQ (key, QCantialias))
254 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
255 else if (EQ (key, QChinting))
256 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
257 else if (EQ (key, QCautohint))
258 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
259 else if (EQ (key, QChintstyle))
261 if (INTEGERP (val))
262 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
263 else if (SYMBOLP (val)
264 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
265 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
267 else if (EQ (key, QCrgba))
269 if (INTEGERP (val))
270 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
271 else if (SYMBOLP (val)
272 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
273 FcPatternAddInteger (pat, FC_RGBA, ival);
275 else if (EQ (key, QClcdfilter))
277 if (INTEGERP (val))
278 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
279 else if (SYMBOLP (val)
280 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
281 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
283 #ifdef FC_EMBOLDEN
284 else if (EQ (key, QCembolden))
285 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
286 #endif
290 static Lisp_Object
291 xftfont_open (f, entity, pixel_size)
292 FRAME_PTR f;
293 Lisp_Object entity;
294 int pixel_size;
296 FcResult result;
297 Display *display = FRAME_X_DISPLAY (f);
298 Lisp_Object val, filename, index, font_object;
299 FcPattern *pat = NULL, *match;
300 struct xftfont_info *xftfont_info = NULL;
301 struct font *font;
302 double size = 0;
303 XftFont *xftfont = NULL;
304 int spacing;
305 char name[256];
306 int len, i;
307 XGlyphInfo extents;
308 FT_Face ft_face;
309 FcMatrix *matrix;
311 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
312 if (! CONSP (val))
313 return Qnil;
314 val = XCDR (val);
315 filename = XCAR (val);
316 index = XCDR (val);
317 size = XINT (AREF (entity, FONT_SIZE_INDEX));
318 if (size == 0)
319 size = pixel_size;
320 pat = FcPatternCreate ();
321 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
322 i = FONT_SLANT_NUMERIC (entity) - 100;
323 if (i < 0) i = 0;
324 FcPatternAddInteger (pat, FC_SLANT, i);
325 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
326 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
327 val = AREF (entity, FONT_FAMILY_INDEX);
328 if (! NILP (val))
329 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
330 val = AREF (entity, FONT_FOUNDRY_INDEX);
331 if (! NILP (val))
332 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
333 val = AREF (entity, FONT_SPACING_INDEX);
334 if (! NILP (val))
335 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
336 val = AREF (entity, FONT_DPI_INDEX);
337 if (! NILP (val))
339 double dbl = XINT (val);
341 FcPatternAddDouble (pat, FC_DPI, dbl);
343 val = AREF (entity, FONT_AVGWIDTH_INDEX);
344 if (INTEGERP (val) && XINT (val) == 0)
345 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
346 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
347 over 10x20-ISO8859-1.pcf.gz). */
348 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
350 xftfont_add_rendering_parameters (pat, entity);
352 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
353 FcPatternAddInteger (pat, FC_INDEX, XINT (index));
356 BLOCK_INPUT;
357 /* Make sure that the Xrender extension is added before the Xft one.
358 Otherwise, the close-display hook set by Xft is called after the
359 one for Xrender, and the former tries to re-add the latter. This
360 results in inconsistency of internal states and leads to X
361 protocol error when one reconnects to the same X server.
362 (Bug#1696) */
364 int event_base, error_base;
365 XRenderQueryExtension (display, &event_base, &error_base);
368 /* Substitute in values from X resources and XftDefaultSet. */
369 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
370 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
371 xftfont_fix_match (pat, match);
373 FcPatternDestroy (pat);
374 xftfont = XftFontOpenPattern (display, match);
375 if (!xftfont)
377 UNBLOCK_INPUT;
378 XftPatternDestroy (match);
379 return Qnil;
381 ft_face = XftLockFace (xftfont);
382 UNBLOCK_INPUT;
384 /* We should not destroy PAT here because it is kept in XFTFONT and
385 destroyed automatically when XFTFONT is closed. */
386 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
387 ASET (font_object, FONT_TYPE_INDEX, Qxft);
388 len = font_unparse_xlfd (entity, size, name, 256);
389 if (len > 0)
390 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
391 len = font_unparse_fcname (entity, size, name, 256);
392 if (len > 0)
393 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
394 else
395 ASET (font_object, FONT_FULLNAME_INDEX,
396 AREF (font_object, FONT_NAME_INDEX));
397 ASET (font_object, FONT_FILE_INDEX, filename);
398 ASET (font_object, FONT_FORMAT_INDEX,
399 ftfont_font_format (xftfont->pattern, filename));
400 font = XFONT_OBJECT (font_object);
401 font->pixel_size = pixel_size;
402 font->driver = &xftfont_driver;
403 font->encoding_charset = font->repertory_charset = -1;
405 xftfont_info = (struct xftfont_info *) font;
406 xftfont_info->display = display;
407 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
408 xftfont_info->xftfont = xftfont;
409 /* This means that there's no need of transformation. */
410 xftfont_info->matrix.xx = 0;
411 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
412 == FcResultMatch)
414 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
415 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
416 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
417 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
419 font->pixel_size = size;
420 font->driver = &xftfont_driver;
421 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
422 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
423 else
424 spacing = FC_PROPORTIONAL;
425 if (! ascii_printable[0])
427 int i;
428 for (i = 0; i < 95; i++)
429 ascii_printable[i] = ' ' + i;
431 BLOCK_INPUT;
432 if (spacing != FC_PROPORTIONAL)
434 font->min_width = font->average_width = font->space_width
435 = xftfont->max_advance_width;
436 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
438 else
440 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
441 font->space_width = extents.xOff;
442 if (font->space_width <= 0)
443 /* dirty workaround */
444 font->space_width = pixel_size;
445 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
446 font->average_width = (font->space_width + extents.xOff) / 95;
448 UNBLOCK_INPUT;
450 font->ascent = xftfont->ascent;
451 font->descent = xftfont->descent;
452 if (pixel_size >= 5)
454 /* The above condition is a dirty workaround because
455 XftTextExtents8 behaves strangely for some fonts
456 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
457 if (font->ascent < extents.y)
458 font->ascent = extents.y;
459 if (font->descent < extents.height - extents.y)
460 font->descent = extents.height - extents.y;
462 font->height = font->ascent + font->descent;
464 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
466 int upEM = ft_face->units_per_EM;
468 font->underline_position = -ft_face->underline_position * size / upEM;
469 font->underline_thickness = ft_face->underline_thickness * size / upEM;
470 if (font->underline_thickness > 2)
471 font->underline_position -= font->underline_thickness / 2;
473 else
475 font->underline_position = -1;
476 font->underline_thickness = 0;
478 #ifdef HAVE_LIBOTF
479 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
480 xftfont_info->otf = NULL;
481 #endif /* HAVE_LIBOTF */
482 xftfont_info->ft_size = ft_face->size;
484 /* Unfortunately Xft doesn't provide a way to get minimum char
485 width. So, we use space_width instead. */
486 font->min_width = font->space_width;
488 font->baseline_offset = 0;
489 font->relative_compose = 0;
490 font->default_ascent = 0;
491 font->vertical_centering = 0;
492 #ifdef FT_BDF_H
493 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
495 BDF_PropertyRec rec;
497 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
498 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
499 font->baseline_offset = rec.u.integer;
500 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
501 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
502 font->relative_compose = rec.u.integer;
503 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
504 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
505 font->default_ascent = rec.u.integer;
507 #endif
509 return font_object;
512 static void
513 xftfont_close (f, font)
514 FRAME_PTR f;
515 struct font *font;
517 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
519 #ifdef HAVE_LIBOTF
520 if (xftfont_info->otf)
521 OTF_close (xftfont_info->otf);
522 #endif
523 BLOCK_INPUT;
524 XftUnlockFace (xftfont_info->xftfont);
525 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
526 UNBLOCK_INPUT;
529 static int
530 xftfont_prepare_face (f, face)
531 FRAME_PTR f;
532 struct face *face;
534 struct xftface_info *xftface_info;
536 #if 0
537 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
538 if (face != face->ascii_face)
540 face->extra = face->ascii_face->extra;
541 return 0;
543 #endif
545 xftface_info = malloc (sizeof (struct xftface_info));
546 if (! xftface_info)
547 return -1;
548 xftfont_get_colors (f, face, face->gc, NULL,
549 &xftface_info->xft_fg, &xftface_info->xft_bg);
550 face->extra = xftface_info;
551 return 0;
554 static void
555 xftfont_done_face (f, face)
556 FRAME_PTR f;
557 struct face *face;
559 struct xftface_info *xftface_info;
561 #if 0
562 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
563 if (face != face->ascii_face
564 || ! face->extra)
565 return;
566 #endif
568 xftface_info = (struct xftface_info *) face->extra;
569 if (xftface_info)
571 free (xftface_info);
572 face->extra = NULL;
576 extern Lisp_Object Qja, Qko;
578 static int
579 xftfont_has_char (font, c)
580 Lisp_Object font;
581 int c;
583 struct xftfont_info *xftfont_info;
584 struct charset *cs = NULL;
586 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
587 && charset_jisx0208 >= 0)
588 cs = CHARSET_FROM_ID (charset_jisx0208);
589 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
590 && charset_ksc5601 >= 0)
591 cs = CHARSET_FROM_ID (charset_ksc5601);
592 if (cs)
593 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
595 if (FONT_ENTITY_P (font))
596 return ftfont_driver.has_char (font, c);
597 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
598 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
599 (FcChar32) c) == FcTrue);
602 static unsigned
603 xftfont_encode_char (font, c)
604 struct font *font;
605 int c;
607 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
608 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
609 (FcChar32) c);
611 return (code ? code : FONT_INVALID_CODE);
614 static int
615 xftfont_text_extents (font, code, nglyphs, metrics)
616 struct font *font;
617 unsigned *code;
618 int nglyphs;
619 struct font_metrics *metrics;
621 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
622 XGlyphInfo extents;
624 BLOCK_INPUT;
625 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
626 &extents);
627 UNBLOCK_INPUT;
628 if (metrics)
630 metrics->lbearing = - extents.x;
631 metrics->rbearing = - extents.x + extents.width;
632 metrics->width = extents.xOff;
633 metrics->ascent = extents.y;
634 metrics->descent = extents.height - extents.y;
636 return extents.xOff;
639 static XftDraw *
640 xftfont_get_xft_draw (f)
641 FRAME_PTR f;
643 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
645 if (! xft_draw)
647 BLOCK_INPUT;
648 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
649 FRAME_X_WINDOW (f),
650 FRAME_X_VISUAL (f),
651 FRAME_X_COLORMAP (f));
652 UNBLOCK_INPUT;
653 if (! xft_draw)
654 abort ();
655 font_put_frame_data (f, &xftfont_driver, xft_draw);
657 return xft_draw;
660 static int
661 xftfont_draw (s, from, to, x, y, with_background)
662 struct glyph_string *s;
663 int from, to, x, y, with_background;
665 FRAME_PTR f = s->f;
666 struct face *face = s->face;
667 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
668 struct xftface_info *xftface_info = NULL;
669 XftDraw *xft_draw = xftfont_get_xft_draw (f);
670 FT_UInt *code;
671 XftColor fg, bg;
672 int len = to - from;
673 int i;
675 if (s->font == face->font)
676 xftface_info = (struct xftface_info *) face->extra;
677 xftfont_get_colors (f, face, s->gc, xftface_info,
678 &fg, with_background ? &bg : NULL);
679 BLOCK_INPUT;
680 if (s->num_clips > 0)
681 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
682 else
683 XftDrawSetClip (xft_draw, NULL);
685 if (with_background)
686 XftDrawRect (xft_draw, &bg,
687 x, y - face->font->ascent, s->width, face->font->height);
688 code = alloca (sizeof (FT_UInt) * len);
689 for (i = 0; i < len; i++)
690 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
691 | XCHAR2B_BYTE2 (s->char2b + from + i));
693 if (s->padding_p)
694 for (i = 0; i < len; i++)
695 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
696 x + i, y, code + i, 1);
697 else
698 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
699 x, y, code, len);
700 UNBLOCK_INPUT;
702 return len;
705 static int
706 xftfont_end_for_frame (f)
707 FRAME_PTR f;
709 XftDraw *xft_draw;
711 /* Don't do anything if display is dead */
712 if (FRAME_X_DISPLAY (f) == NULL) return 0;
714 xft_draw = font_get_frame_data (f, &xftfont_driver);
716 if (xft_draw)
718 BLOCK_INPUT;
719 XftDrawDestroy (xft_draw);
720 UNBLOCK_INPUT;
721 font_put_frame_data (f, &xftfont_driver, NULL);
723 return 0;
726 static int
727 xftfont_cached_font_ok (f, font_object, entity)
728 struct frame *f;
729 Lisp_Object font_object;
730 Lisp_Object entity;
733 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
734 FcPattern *oldpat = info->xftfont->pattern;
735 Display *display = FRAME_X_DISPLAY (f);
736 FcPattern *pat = FcPatternCreate ();
737 FcBool b1, b2;
738 int ok = 0, i1, i2, r1, r2;
740 xftfont_add_rendering_parameters (pat, entity);
741 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
743 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
744 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
745 if (r1 != r2 || b1 != b2) goto out;
746 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
747 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
748 if (r1 != r2 || b1 != b2) goto out;
749 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
750 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
751 if (r1 != r2 || b1 != b2) goto out;
752 #ifdef FC_EMBOLDEN
753 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
754 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
755 if (r1 != r2 || b1 != b2) goto out;
756 #endif
757 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
758 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
759 if (r1 != r2 || i1 != i2) goto out;
760 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
761 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
762 if (r1 != r2 || i1 != i2) goto out;
763 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
764 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
765 if (r1 != r2 || i1 != i2) goto out;
767 ok = 1;
768 out:
769 FcPatternDestroy (pat);
770 return ok;
773 void
774 syms_of_xftfont ()
776 DEFSYM (Qxft, "xft");
777 DEFSYM (QChinting, ":hinting");
778 DEFSYM (QCautohint, ":autohint");
779 DEFSYM (QChintstyle, ":hintstyle");
780 DEFSYM (QCrgba, ":rgba");
781 DEFSYM (QCembolden, ":embolden");
782 DEFSYM (QClcdfilter, ":lcdfilter");
784 xftfont_driver = ftfont_driver;
785 xftfont_driver.type = Qxft;
786 xftfont_driver.get_cache = xfont_driver.get_cache;
787 xftfont_driver.list = xftfont_list;
788 xftfont_driver.match = xftfont_match;
789 xftfont_driver.open = xftfont_open;
790 xftfont_driver.close = xftfont_close;
791 xftfont_driver.prepare_face = xftfont_prepare_face;
792 xftfont_driver.done_face = xftfont_done_face;
793 xftfont_driver.has_char = xftfont_has_char;
794 xftfont_driver.encode_char = xftfont_encode_char;
795 xftfont_driver.text_extents = xftfont_text_extents;
796 xftfont_driver.draw = xftfont_draw;
797 xftfont_driver.end_for_frame = xftfont_end_for_frame;
798 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
800 register_font_driver (&xftfont_driver, NULL);
803 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
804 (do not change this comment) */