lisp/gnus/nnimap.el (nnimap-get-groups): Fix XEmacs compilation
[emacs.git] / src / xftfont.c
blob0e8b876f1d33bd1cb3e90c522532254360a95ba6
1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2015 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 <X11/Xlib.h>
25 #include <X11/Xft/Xft.h>
27 #include "lisp.h"
28 #include "dispextern.h"
29 #include "xterm.h"
30 #include "frame.h"
31 #include "blockinput.h"
32 #include "character.h"
33 #include "charset.h"
34 #include "composite.h"
35 #include "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
39 /* Xft font driver. */
42 /* The actual structure for Xft font that can be cast to struct
43 font. */
45 struct xftfont_info
47 struct font font;
48 /* The following five members must be here in this order to be
49 compatible with struct ftfont_info (in ftfont.c). */
50 #ifdef HAVE_LIBOTF
51 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
52 OTF *otf;
53 #endif /* HAVE_LIBOTF */
54 FT_Size ft_size;
55 int index;
56 FT_Matrix matrix;
57 Display *display;
58 XftFont *xftfont;
59 unsigned x_display_id;
62 /* Structure pointed by (struct face *)->extra */
64 struct xftface_info
66 XftColor xft_fg; /* color for face->foreground */
67 XftColor xft_bg; /* color for face->background */
70 /* Setup foreground and background colors of GC into FG and BG. If
71 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
72 may be NULL. */
74 static void
75 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
76 struct xftface_info *xftface_info,
77 XftColor *fg, XftColor *bg)
79 if (xftface_info && face->gc == gc)
81 *fg = xftface_info->xft_fg;
82 if (bg)
83 *bg = xftface_info->xft_bg;
85 else
87 XGCValues xgcv;
88 bool fg_done = false, bg_done = false;
90 block_input ();
91 XGetGCValues (FRAME_X_DISPLAY (f), gc,
92 GCForeground | GCBackground, &xgcv);
93 if (xftface_info)
95 if (xgcv.foreground == face->foreground)
96 *fg = xftface_info->xft_fg, fg_done = true;
97 else if (xgcv.foreground == face->background)
98 *fg = xftface_info->xft_bg, fg_done = true;
99 if (! bg)
100 bg_done = true;
101 else if (xgcv.background == face->background)
102 *bg = xftface_info->xft_bg, bg_done = true;
103 else if (xgcv.background == face->foreground)
104 *bg = xftface_info->xft_fg, bg_done = true;
107 if (! (fg_done & bg_done))
109 XColor colors[2];
111 colors[0].pixel = fg->pixel = xgcv.foreground;
112 if (bg)
113 colors[1].pixel = bg->pixel = xgcv.background;
114 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
115 bg ? 2 : 1);
116 fg->color.alpha = 0xFFFF;
117 fg->color.red = colors[0].red;
118 fg->color.green = colors[0].green;
119 fg->color.blue = colors[0].blue;
120 if (bg)
122 bg->color.alpha = 0xFFFF;
123 bg->color.red = colors[1].red;
124 bg->color.green = colors[1].green;
125 bg->color.blue = colors[1].blue;
128 unblock_input ();
133 struct font_driver xftfont_driver;
135 static Lisp_Object
136 xftfont_list (struct frame *f, Lisp_Object spec)
138 Lisp_Object list = ftfont_driver.list (f, spec), tail;
140 for (tail = list; CONSP (tail); tail = XCDR (tail))
141 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
142 return list;
145 static Lisp_Object
146 xftfont_match (struct frame *f, Lisp_Object spec)
148 Lisp_Object entity = ftfont_driver.match (f, spec);
150 if (! NILP (entity))
151 ASET (entity, FONT_TYPE_INDEX, Qxft);
152 return entity;
155 static FcChar8 ascii_printable[95];
157 static void
158 xftfont_fix_match (FcPattern *pat, FcPattern *match)
160 /* These values are not used for matching (except antialias), but for
161 rendering, so make sure they are carried over to the match.
162 We also put antialias here because most fonts are antialiased, so
163 the match will have antialias true. */
165 FcBool b = FcTrue;
166 int i;
167 double dpi;
169 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
170 if (! b)
172 FcPatternDel (match, FC_ANTIALIAS);
173 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
175 FcPatternGetBool (pat, FC_HINTING, 0, &b);
176 if (! b)
178 FcPatternDel (match, FC_HINTING);
179 FcPatternAddBool (match, FC_HINTING, FcFalse);
181 #ifndef FC_HINT_STYLE
182 # define FC_HINT_STYLE "hintstyle"
183 #endif
184 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
186 FcPatternDel (match, FC_HINT_STYLE);
187 FcPatternAddInteger (match, FC_HINT_STYLE, i);
189 #ifndef FC_LCD_FILTER
190 /* Older fontconfig versions don't have FC_LCD_FILTER. */
191 #define FC_LCD_FILTER "lcdfilter"
192 #endif
193 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
195 FcPatternDel (match, FC_LCD_FILTER);
196 FcPatternAddInteger (match, FC_LCD_FILTER, i);
198 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
200 FcPatternDel (match, FC_RGBA);
201 FcPatternAddInteger (match, FC_RGBA, i);
203 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
205 FcPatternDel (match, FC_DPI);
206 FcPatternAddDouble (match, FC_DPI, dpi);
210 static void
211 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
213 Lisp_Object tail;
214 int ival;
216 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
218 Lisp_Object key = XCAR (XCAR (tail));
219 Lisp_Object val = XCDR (XCAR (tail));
221 if (EQ (key, QCantialias))
222 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
223 else if (EQ (key, QChinting))
224 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
225 else if (EQ (key, QCautohint))
226 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
227 else if (EQ (key, QChintstyle))
229 if (INTEGERP (val))
230 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
231 else if (SYMBOLP (val)
232 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
233 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
235 else if (EQ (key, QCrgba))
237 if (INTEGERP (val))
238 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
239 else if (SYMBOLP (val)
240 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
241 FcPatternAddInteger (pat, FC_RGBA, ival);
243 else if (EQ (key, QClcdfilter))
245 if (INTEGERP (val))
246 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
247 else if (SYMBOLP (val)
248 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
249 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
251 #ifdef FC_EMBOLDEN
252 else if (EQ (key, QCembolden))
253 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
254 #endif
258 static Lisp_Object
259 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
261 FcResult result;
262 Display *display = FRAME_X_DISPLAY (f);
263 Lisp_Object val, filename, idx, font_object;
264 FcPattern *pat = NULL, *match;
265 struct xftfont_info *xftfont_info = NULL;
266 struct font *font;
267 double size = 0;
268 XftFont *xftfont = NULL;
269 int spacing;
270 int i;
271 XGlyphInfo extents;
272 FT_Face ft_face;
273 FcMatrix *matrix;
275 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
276 if (! CONSP (val))
277 return Qnil;
278 val = XCDR (val);
279 filename = XCAR (val);
280 idx = XCDR (val);
281 size = XINT (AREF (entity, FONT_SIZE_INDEX));
282 if (size == 0)
283 size = pixel_size;
284 pat = FcPatternCreate ();
285 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
286 i = FONT_SLANT_NUMERIC (entity) - 100;
287 if (i < 0) i = 0;
288 FcPatternAddInteger (pat, FC_SLANT, i);
289 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
290 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
291 val = AREF (entity, FONT_FAMILY_INDEX);
292 if (! NILP (val))
293 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
294 val = AREF (entity, FONT_FOUNDRY_INDEX);
295 if (! NILP (val))
296 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
297 val = AREF (entity, FONT_SPACING_INDEX);
298 if (! NILP (val))
299 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
300 val = AREF (entity, FONT_DPI_INDEX);
301 if (! NILP (val))
303 double dbl = XINT (val);
305 FcPatternAddDouble (pat, FC_DPI, dbl);
307 val = AREF (entity, FONT_AVGWIDTH_INDEX);
308 if (INTEGERP (val) && XINT (val) == 0)
309 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
310 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
311 over 10x20-ISO8859-1.pcf.gz). */
312 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
314 xftfont_add_rendering_parameters (pat, entity);
316 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
317 FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
320 block_input ();
322 /* Substitute in values from X resources and XftDefaultSet. */
323 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
324 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
325 xftfont_fix_match (pat, match);
327 FcPatternDestroy (pat);
328 xftfont = XftFontOpenPattern (display, match);
329 if (!xftfont)
331 unblock_input ();
332 XftPatternDestroy (match);
333 return Qnil;
335 ft_face = XftLockFace (xftfont);
336 unblock_input ();
338 /* We should not destroy PAT here because it is kept in XFTFONT and
339 destroyed automatically when XFTFONT is closed. */
340 font_object = font_build_object (VECSIZE (struct xftfont_info),
341 Qxft, entity, size);
342 ASET (font_object, FONT_FILE_INDEX, filename);
343 font = XFONT_OBJECT (font_object);
344 font->pixel_size = size;
345 font->driver = &xftfont_driver;
346 font->encoding_charset = font->repertory_charset = -1;
348 xftfont_info = (struct xftfont_info *) font;
349 xftfont_info->display = display;
350 xftfont_info->xftfont = xftfont;
351 xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
352 /* This means that there's no need of transformation. */
353 xftfont_info->matrix.xx = 0;
354 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
355 == FcResultMatch)
357 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
358 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
359 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
360 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
362 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
363 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
364 else
365 spacing = FC_PROPORTIONAL;
366 if (! ascii_printable[0])
368 int ch;
369 for (ch = 0; ch < 95; ch++)
370 ascii_printable[ch] = ' ' + ch;
372 block_input ();
374 /* Unfortunately Xft doesn't provide a way to get minimum char
375 width. So, we set min_width to space_width. */
377 if (spacing != FC_PROPORTIONAL
378 #ifdef FC_DUAL
379 && spacing != FC_DUAL
380 #endif /* FC_DUAL */
383 font->min_width = font->max_width = font->average_width
384 = font->space_width = xftfont->max_advance_width;
385 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
387 else
389 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
390 font->min_width = font->max_width = font->space_width
391 = extents.xOff;
392 if (font->space_width <= 0)
393 /* dirty workaround */
394 font->space_width = pixel_size;
395 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
396 font->average_width = (font->space_width + extents.xOff) / 95;
398 unblock_input ();
400 font->ascent = xftfont->ascent;
401 font->descent = xftfont->descent;
402 if (pixel_size >= 5)
404 /* The above condition is a dirty workaround because
405 XftTextExtents8 behaves strangely for some fonts
406 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
407 if (font->ascent < extents.y)
408 font->ascent = extents.y;
409 if (font->descent < extents.height - extents.y)
410 font->descent = extents.height - extents.y;
412 font->height = font->ascent + font->descent;
414 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
416 int upEM = ft_face->units_per_EM;
418 font->underline_position = -ft_face->underline_position * size / upEM;
419 font->underline_thickness = ft_face->underline_thickness * size / upEM;
420 if (font->underline_thickness > 2)
421 font->underline_position -= font->underline_thickness / 2;
423 else
425 font->underline_position = -1;
426 font->underline_thickness = 0;
428 #ifdef HAVE_LIBOTF
429 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
430 xftfont_info->otf = NULL;
431 #endif /* HAVE_LIBOTF */
432 xftfont_info->ft_size = ft_face->size;
434 font->baseline_offset = 0;
435 font->relative_compose = 0;
436 font->default_ascent = 0;
437 font->vertical_centering = false;
438 #ifdef FT_BDF_H
439 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
441 BDF_PropertyRec rec;
443 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
444 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
445 font->baseline_offset = rec.u.integer;
446 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
447 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
448 font->relative_compose = rec.u.integer;
449 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
450 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
451 font->default_ascent = rec.u.integer;
453 #endif
455 return font_object;
458 static void
459 xftfont_close (struct font *font)
461 struct x_display_info *xdi;
462 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
464 #ifdef HAVE_LIBOTF
465 if (xftfont_info->otf)
467 OTF_close (xftfont_info->otf);
468 xftfont_info->otf = NULL;
470 #endif
472 /* See comment in xfont_close. */
473 if (xftfont_info->xftfont
474 && ((xdi = x_display_info_for_display (xftfont_info->display))
475 && xftfont_info->x_display_id == xdi->x_id))
477 block_input ();
478 XftUnlockFace (xftfont_info->xftfont);
479 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
480 unblock_input ();
481 xftfont_info->xftfont = NULL;
485 static void
486 xftfont_prepare_face (struct frame *f, struct face *face)
488 struct xftface_info *xftface_info;
490 #if false
491 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
492 if (face != face->ascii_face)
494 face->extra = face->ascii_face->extra;
495 return;
497 #endif
499 xftface_info = xmalloc (sizeof *xftface_info);
500 xftfont_get_colors (f, face, face->gc, NULL,
501 &xftface_info->xft_fg, &xftface_info->xft_bg);
502 face->extra = xftface_info;
505 static void
506 xftfont_done_face (struct frame *f, struct face *face)
508 struct xftface_info *xftface_info;
510 #if false
511 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
512 if (face != face->ascii_face
513 || ! face->extra)
514 return;
515 #endif
517 xftface_info = (struct xftface_info *) face->extra;
518 if (xftface_info)
520 xfree (xftface_info);
521 face->extra = NULL;
525 static int
526 xftfont_has_char (Lisp_Object font, int c)
528 struct xftfont_info *xftfont_info;
529 struct charset *cs = NULL;
531 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
532 && charset_jisx0208 >= 0)
533 cs = CHARSET_FROM_ID (charset_jisx0208);
534 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
535 && charset_ksc5601 >= 0)
536 cs = CHARSET_FROM_ID (charset_ksc5601);
537 if (cs)
538 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
540 if (FONT_ENTITY_P (font))
541 return ftfont_driver.has_char (font, c);
542 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
543 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
544 (FcChar32) c) == FcTrue);
547 static unsigned
548 xftfont_encode_char (struct font *font, int c)
550 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
551 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
552 (FcChar32) c);
554 return (code ? code : FONT_INVALID_CODE);
557 static void
558 xftfont_text_extents (struct font *font, unsigned int *code,
559 int nglyphs, struct font_metrics *metrics)
561 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
562 XGlyphInfo extents;
564 block_input ();
565 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
566 &extents);
567 unblock_input ();
569 metrics->lbearing = - extents.x;
570 metrics->rbearing = - extents.x + extents.width;
571 metrics->width = extents.xOff;
572 metrics->ascent = extents.y;
573 metrics->descent = extents.height - extents.y;
576 static XftDraw *
577 xftfont_get_xft_draw (struct frame *f)
579 XftDraw *xft_draw = font_get_frame_data (f, Qxft);
581 if (! xft_draw)
583 block_input ();
584 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
585 FRAME_X_WINDOW (f),
586 FRAME_X_VISUAL (f),
587 FRAME_X_COLORMAP (f));
588 unblock_input ();
589 eassert (xft_draw != NULL);
590 font_put_frame_data (f, Qxft, xft_draw);
592 return xft_draw;
595 static int
596 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
597 bool with_background)
599 struct frame *f = s->f;
600 struct face *face = s->face;
601 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
602 struct xftface_info *xftface_info = NULL;
603 XftDraw *xft_draw = xftfont_get_xft_draw (f);
604 FT_UInt *code;
605 XftColor fg, bg;
606 int len = to - from;
607 int i;
609 if (s->font == face->font)
610 xftface_info = (struct xftface_info *) face->extra;
611 xftfont_get_colors (f, face, s->gc, xftface_info,
612 &fg, with_background ? &bg : NULL);
613 block_input ();
614 if (s->num_clips > 0)
615 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
616 else
617 XftDrawSetClip (xft_draw, NULL);
619 if (with_background)
620 XftDrawRect (xft_draw, &bg,
621 x, y - s->font->ascent, s->width, s->font->height);
622 code = alloca (sizeof (FT_UInt) * len);
623 for (i = 0; i < len; i++)
624 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
625 | XCHAR2B_BYTE2 (s->char2b + from + i));
627 if (s->padding_p)
628 for (i = 0; i < len; i++)
629 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
630 x + i, y, code + i, 1);
631 else
632 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
633 x, y, code, len);
634 unblock_input ();
636 return len;
639 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
640 static Lisp_Object
641 xftfont_shape (Lisp_Object lgstring)
643 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
644 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
645 FT_Face ft_face;
646 Lisp_Object val;
648 ft_face = XftLockFace (xftfont_info->xftfont);
649 xftfont_info->ft_size = ft_face->size;
650 val = ftfont_driver.shape (lgstring);
651 XftUnlockFace (xftfont_info->xftfont);
652 return val;
654 #endif
656 static int
657 xftfont_end_for_frame (struct frame *f)
659 XftDraw *xft_draw;
661 /* Don't do anything if display is dead */
662 if (FRAME_X_DISPLAY (f) == NULL) return 0;
664 xft_draw = font_get_frame_data (f, Qxft);
666 if (xft_draw)
668 block_input ();
669 XftDrawDestroy (xft_draw);
670 unblock_input ();
671 font_put_frame_data (f, Qxft, NULL);
673 return 0;
676 static bool
677 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
678 Lisp_Object entity)
680 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
681 FcPattern *oldpat = info->xftfont->pattern;
682 Display *display = FRAME_X_DISPLAY (f);
683 FcPattern *pat = FcPatternCreate ();
684 FcBool b1, b2;
685 bool ok = false;
686 int i1, i2, r1, r2;
688 xftfont_add_rendering_parameters (pat, entity);
689 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
691 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
692 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
693 if (r1 != r2 || b1 != b2) goto out;
694 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
695 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
696 if (r1 != r2 || b1 != b2) goto out;
697 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
698 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
699 if (r1 != r2 || b1 != b2) goto out;
700 #ifdef FC_EMBOLDEN
701 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
702 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
703 if (r1 != r2 || b1 != b2) goto out;
704 #endif
705 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
706 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
707 if (r1 != r2 || i1 != i2) goto out;
708 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
709 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
710 if (r1 != r2 || i1 != i2) goto out;
711 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
712 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
713 if (r1 != r2 || i1 != i2) goto out;
715 ok = true;
716 out:
717 FcPatternDestroy (pat);
718 return ok;
721 void
722 syms_of_xftfont (void)
724 DEFSYM (Qxft, "xft");
725 DEFSYM (QChinting, ":hinting");
726 DEFSYM (QCautohint, ":autohint");
727 DEFSYM (QChintstyle, ":hintstyle");
728 DEFSYM (QCrgba, ":rgba");
729 DEFSYM (QCembolden, ":embolden");
730 DEFSYM (QClcdfilter, ":lcdfilter");
732 ascii_printable[0] = 0;
734 xftfont_driver = ftfont_driver;
735 xftfont_driver.type = Qxft;
736 xftfont_driver.get_cache = xfont_driver.get_cache;
737 xftfont_driver.list = xftfont_list;
738 xftfont_driver.match = xftfont_match;
739 xftfont_driver.open = xftfont_open;
740 xftfont_driver.close = xftfont_close;
741 xftfont_driver.prepare_face = xftfont_prepare_face;
742 xftfont_driver.done_face = xftfont_done_face;
743 xftfont_driver.has_char = xftfont_has_char;
744 xftfont_driver.encode_char = xftfont_encode_char;
745 xftfont_driver.text_extents = xftfont_text_extents;
746 xftfont_driver.draw = xftfont_draw;
747 xftfont_driver.end_for_frame = xftfont_end_for_frame;
748 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
749 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
750 xftfont_driver.shape = xftfont_shape;
751 #endif
753 register_font_driver (&xftfont_driver, NULL);