1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2011 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/>. */
26 #include <X11/Xft/Xft.h>
29 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
35 #include "composite.h"
40 /* Xft font driver. */
42 static Lisp_Object Qxft
;
43 static Lisp_Object QChinting
, QCautohint
, QChintstyle
, QCrgba
, QCembolden
,
46 /* The actual structure for Xft font that can be casted to struct
52 /* The following five members must be here in this order to be
53 compatible with struct ftfont_info (in ftfont.c). */
55 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
57 #endif /* HAVE_LIBOTF */
66 /* Structure pointed by (struct face *)->extra */
70 XftColor xft_fg
; /* color for face->foreground */
71 XftColor xft_bg
; /* color for face->background */
74 static void xftfont_get_colors (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
84 xftfont_get_colors (FRAME_PTR f
, struct face
*face
, GC gc
, struct xftface_info
*xftface_info
, XftColor
*fg
, XftColor
*bg
)
86 if (xftface_info
&& face
->gc
== gc
)
88 *fg
= xftface_info
->xft_fg
;
90 *bg
= xftface_info
->xft_bg
;
95 int fg_done
= 0, bg_done
= 0;
98 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
99 GCForeground
| GCBackground
, &xgcv
);
102 if (xgcv
.foreground
== face
->foreground
)
103 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
104 else if (xgcv
.foreground
== face
->background
)
105 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
108 else if (xgcv
.background
== face
->background
)
109 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
110 else if (xgcv
.background
== face
->foreground
)
111 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
114 if (fg_done
+ bg_done
< 2)
118 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
120 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
121 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
123 fg
->color
.alpha
= 0xFFFF;
124 fg
->color
.red
= colors
[0].red
;
125 fg
->color
.green
= colors
[0].green
;
126 fg
->color
.blue
= colors
[0].blue
;
129 bg
->color
.alpha
= 0xFFFF;
130 bg
->color
.red
= colors
[1].red
;
131 bg
->color
.green
= colors
[1].green
;
132 bg
->color
.blue
= colors
[1].blue
;
140 static Lisp_Object
xftfont_list (Lisp_Object
, Lisp_Object
);
141 static Lisp_Object
xftfont_match (Lisp_Object
, Lisp_Object
);
142 static Lisp_Object
xftfont_open (FRAME_PTR
, Lisp_Object
, int);
143 static void xftfont_close (FRAME_PTR
, struct font
*);
144 static int xftfont_prepare_face (FRAME_PTR
, struct face
*);
145 static void xftfont_done_face (FRAME_PTR
, struct face
*);
146 static int xftfont_has_char (Lisp_Object
, int);
147 static unsigned xftfont_encode_char (struct font
*, int);
148 static int xftfont_text_extents (struct font
*, unsigned *, int,
149 struct font_metrics
*);
150 static int xftfont_draw (struct glyph_string
*, int, int, int, int, int);
151 static int xftfont_end_for_frame (FRAME_PTR f
);
153 struct font_driver xftfont_driver
;
156 xftfont_list (Lisp_Object frame
, Lisp_Object spec
)
158 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
160 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
161 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
166 xftfont_match (Lisp_Object frame
, Lisp_Object spec
)
168 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
171 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
175 static FcChar8 ascii_printable
[95];
178 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
180 /* These values are not used for matching (except antialias), but for
181 rendering, so make sure they are carried over to the match.
182 We also put antialias here because most fonts are antialiased, so
183 the match will have antialias true. */
189 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
192 FcPatternDel (match
, FC_ANTIALIAS
);
193 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
195 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
198 FcPatternDel (match
, FC_HINTING
);
199 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
201 #ifndef FC_HINT_STYLE
202 # define FC_HINT_STYLE "hintstyle"
204 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
206 FcPatternDel (match
, FC_HINT_STYLE
);
207 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
209 #ifndef FC_LCD_FILTER
210 /* Older fontconfig versions don't have FC_LCD_FILTER. */
211 #define FC_LCD_FILTER "lcdfilter"
213 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
215 FcPatternDel (match
, FC_LCD_FILTER
);
216 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
218 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
220 FcPatternDel (match
, FC_RGBA
);
221 FcPatternAddInteger (match
, FC_RGBA
, i
);
223 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
225 FcPatternDel (match
, FC_DPI
);
226 FcPatternAddDouble (match
, FC_DPI
, dpi
);
231 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
236 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
238 Lisp_Object key
= XCAR (XCAR (tail
));
239 Lisp_Object val
= XCDR (XCAR (tail
));
241 if (EQ (key
, QCantialias
))
242 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
243 else if (EQ (key
, QChinting
))
244 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
245 else if (EQ (key
, QCautohint
))
246 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
247 else if (EQ (key
, QChintstyle
))
250 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
251 else if (SYMBOLP (val
)
252 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
253 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
255 else if (EQ (key
, QCrgba
))
258 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
259 else if (SYMBOLP (val
)
260 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
261 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
263 else if (EQ (key
, QClcdfilter
))
266 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
267 else if (SYMBOLP (val
)
268 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
269 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
272 else if (EQ (key
, QCembolden
))
273 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
279 xftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
282 Display
*display
= FRAME_X_DISPLAY (f
);
283 Lisp_Object val
, filename
, index
, font_object
;
284 FcPattern
*pat
= NULL
, *match
;
285 struct xftfont_info
*xftfont_info
= NULL
;
288 XftFont
*xftfont
= NULL
;
296 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
300 filename
= XCAR (val
);
302 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
305 pat
= FcPatternCreate ();
306 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
307 i
= FONT_SLANT_NUMERIC (entity
) - 100;
309 FcPatternAddInteger (pat
, FC_SLANT
, i
);
310 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
311 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
312 val
= AREF (entity
, FONT_FAMILY_INDEX
);
314 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
315 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
317 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
318 val
= AREF (entity
, FONT_SPACING_INDEX
);
320 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
321 val
= AREF (entity
, FONT_DPI_INDEX
);
324 double dbl
= XINT (val
);
326 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
328 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
329 if (INTEGERP (val
) && XINT (val
) == 0)
330 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
331 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
332 over 10x20-ISO8859-1.pcf.gz). */
333 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
335 xftfont_add_rendering_parameters (pat
, entity
);
337 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
338 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
342 /* Make sure that the Xrender extension is added before the Xft one.
343 Otherwise, the close-display hook set by Xft is called after the
344 one for Xrender, and the former tries to re-add the latter. This
345 results in inconsistency of internal states and leads to X
346 protocol error when one reconnects to the same X server.
349 int event_base
, error_base
;
350 XRenderQueryExtension (display
, &event_base
, &error_base
);
353 /* Substitute in values from X resources and XftDefaultSet. */
354 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
355 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
356 xftfont_fix_match (pat
, match
);
358 FcPatternDestroy (pat
);
359 xftfont
= XftFontOpenPattern (display
, match
);
363 XftPatternDestroy (match
);
366 ft_face
= XftLockFace (xftfont
);
369 /* We should not destroy PAT here because it is kept in XFTFONT and
370 destroyed automatically when XFTFONT is closed. */
371 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
372 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
373 len
= font_unparse_xlfd (entity
, size
, name
, 256);
375 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
376 len
= font_unparse_fcname (entity
, size
, name
, 256);
378 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
380 ASET (font_object
, FONT_FULLNAME_INDEX
,
381 AREF (font_object
, FONT_NAME_INDEX
));
382 ASET (font_object
, FONT_FILE_INDEX
, filename
);
383 ASET (font_object
, FONT_FORMAT_INDEX
,
384 ftfont_font_format (xftfont
->pattern
, filename
));
385 font
= XFONT_OBJECT (font_object
);
386 font
->pixel_size
= pixel_size
;
387 font
->driver
= &xftfont_driver
;
388 font
->encoding_charset
= font
->repertory_charset
= -1;
390 xftfont_info
= (struct xftfont_info
*) font
;
391 xftfont_info
->display
= display
;
392 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
393 xftfont_info
->xftfont
= xftfont
;
394 /* This means that there's no need of transformation. */
395 xftfont_info
->matrix
.xx
= 0;
396 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
399 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
400 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
401 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
402 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
404 font
->pixel_size
= size
;
405 font
->driver
= &xftfont_driver
;
406 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
407 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
409 spacing
= FC_PROPORTIONAL
;
410 if (! ascii_printable
[0])
413 for (i
= 0; i
< 95; i
++)
414 ascii_printable
[i
] = ' ' + i
;
417 if (spacing
!= FC_PROPORTIONAL
419 && spacing
!= FC_DUAL
423 font
->min_width
= font
->average_width
= font
->space_width
424 = xftfont
->max_advance_width
;
425 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
429 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
430 font
->space_width
= extents
.xOff
;
431 if (font
->space_width
<= 0)
432 /* dirty workaround */
433 font
->space_width
= pixel_size
;
434 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
435 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
439 font
->ascent
= xftfont
->ascent
;
440 font
->descent
= xftfont
->descent
;
443 /* The above condition is a dirty workaround because
444 XftTextExtents8 behaves strangely for some fonts
445 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
446 if (font
->ascent
< extents
.y
)
447 font
->ascent
= extents
.y
;
448 if (font
->descent
< extents
.height
- extents
.y
)
449 font
->descent
= extents
.height
- extents
.y
;
451 font
->height
= font
->ascent
+ font
->descent
;
453 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
455 int upEM
= ft_face
->units_per_EM
;
457 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
458 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
459 if (font
->underline_thickness
> 2)
460 font
->underline_position
-= font
->underline_thickness
/ 2;
464 font
->underline_position
= -1;
465 font
->underline_thickness
= 0;
468 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
469 xftfont_info
->otf
= NULL
;
470 #endif /* HAVE_LIBOTF */
471 xftfont_info
->ft_size
= ft_face
->size
;
473 /* Unfortunately Xft doesn't provide a way to get minimum char
474 width. So, we use space_width instead. */
475 font
->min_width
= font
->space_width
;
477 font
->baseline_offset
= 0;
478 font
->relative_compose
= 0;
479 font
->default_ascent
= 0;
480 font
->vertical_centering
= 0;
482 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
486 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
487 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
488 font
->baseline_offset
= rec
.u
.integer
;
489 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
490 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
491 font
->relative_compose
= rec
.u
.integer
;
492 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
493 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
494 font
->default_ascent
= rec
.u
.integer
;
502 xftfont_close (FRAME_PTR f
, struct font
*font
)
504 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
507 if (xftfont_info
->otf
)
508 OTF_close (xftfont_info
->otf
);
511 XftUnlockFace (xftfont_info
->xftfont
);
512 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
517 xftfont_prepare_face (FRAME_PTR f
, struct face
*face
)
519 struct xftface_info
*xftface_info
;
522 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
523 if (face
!= face
->ascii_face
)
525 face
->extra
= face
->ascii_face
->extra
;
530 xftface_info
= malloc (sizeof (struct xftface_info
));
533 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
534 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
535 face
->extra
= xftface_info
;
540 xftfont_done_face (FRAME_PTR f
, struct face
*face
)
542 struct xftface_info
*xftface_info
;
545 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
546 if (face
!= face
->ascii_face
551 xftface_info
= (struct xftface_info
*) face
->extra
;
560 xftfont_has_char (Lisp_Object font
, int c
)
562 struct xftfont_info
*xftfont_info
;
563 struct charset
*cs
= NULL
;
565 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
566 && charset_jisx0208
>= 0)
567 cs
= CHARSET_FROM_ID (charset_jisx0208
);
568 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
569 && charset_ksc5601
>= 0)
570 cs
= CHARSET_FROM_ID (charset_ksc5601
);
572 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
574 if (FONT_ENTITY_P (font
))
575 return ftfont_driver
.has_char (font
, c
);
576 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
577 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
578 (FcChar32
) c
) == FcTrue
);
582 xftfont_encode_char (struct font
*font
, int c
)
584 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
585 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
588 return (code
? code
: FONT_INVALID_CODE
);
592 xftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
594 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
598 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
603 metrics
->lbearing
= - extents
.x
;
604 metrics
->rbearing
= - extents
.x
+ extents
.width
;
605 metrics
->width
= extents
.xOff
;
606 metrics
->ascent
= extents
.y
;
607 metrics
->descent
= extents
.height
- extents
.y
;
613 xftfont_get_xft_draw (FRAME_PTR f
)
615 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
620 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
623 FRAME_X_COLORMAP (f
));
627 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
633 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
, int with_background
)
636 struct face
*face
= s
->face
;
637 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
638 struct xftface_info
*xftface_info
= NULL
;
639 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
645 if (s
->font
== face
->font
)
646 xftface_info
= (struct xftface_info
*) face
->extra
;
647 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
648 &fg
, with_background
? &bg
: NULL
);
650 if (s
->num_clips
> 0)
651 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
653 XftDrawSetClip (xft_draw
, NULL
);
656 XftDrawRect (xft_draw
, &bg
,
657 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
658 code
= alloca (sizeof (FT_UInt
) * len
);
659 for (i
= 0; i
< len
; i
++)
660 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
661 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
664 for (i
= 0; i
< len
; i
++)
665 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
666 x
+ i
, y
, code
+ i
, 1);
668 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
676 xftfont_shape (Lisp_Object lgstring
)
679 struct xftfont_info
*xftfont_info
;
683 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
684 xftfont_info
= (struct xftfont_info
*) font
;
685 ft_face
= XftLockFace (xftfont_info
->xftfont
);
686 xftfont_info
->ft_size
= ft_face
->size
;
687 val
= ftfont_driver
.shape (lgstring
);
688 XftUnlockFace (xftfont_info
->xftfont
);
693 xftfont_end_for_frame (FRAME_PTR f
)
697 /* Don't do anything if display is dead */
698 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
700 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
705 XftDrawDestroy (xft_draw
);
707 font_put_frame_data (f
, &xftfont_driver
, NULL
);
713 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
, Lisp_Object entity
)
715 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
716 FcPattern
*oldpat
= info
->xftfont
->pattern
;
717 Display
*display
= FRAME_X_DISPLAY (f
);
718 FcPattern
*pat
= FcPatternCreate ();
720 int ok
= 0, i1
, i2
, r1
, r2
;
722 xftfont_add_rendering_parameters (pat
, entity
);
723 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
725 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
726 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
727 if (r1
!= r2
|| b1
!= b2
) goto out
;
728 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
729 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
730 if (r1
!= r2
|| b1
!= b2
) goto out
;
731 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
732 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
733 if (r1
!= r2
|| b1
!= b2
) goto out
;
735 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
736 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
737 if (r1
!= r2
|| b1
!= b2
) goto out
;
739 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
740 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
741 if (r1
!= r2
|| i1
!= i2
) goto out
;
742 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
743 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
744 if (r1
!= r2
|| i1
!= i2
) goto out
;
745 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
746 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
747 if (r1
!= r2
|| i1
!= i2
) goto out
;
751 FcPatternDestroy (pat
);
756 syms_of_xftfont (void)
758 DEFSYM (Qxft
, "xft");
759 DEFSYM (QChinting
, ":hinting");
760 DEFSYM (QCautohint
, ":autohint");
761 DEFSYM (QChintstyle
, ":hintstyle");
762 DEFSYM (QCrgba
, ":rgba");
763 DEFSYM (QCembolden
, ":embolden");
764 DEFSYM (QClcdfilter
, ":lcdfilter");
766 xftfont_driver
= ftfont_driver
;
767 xftfont_driver
.type
= Qxft
;
768 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
769 xftfont_driver
.list
= xftfont_list
;
770 xftfont_driver
.match
= xftfont_match
;
771 xftfont_driver
.open
= xftfont_open
;
772 xftfont_driver
.close
= xftfont_close
;
773 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
774 xftfont_driver
.done_face
= xftfont_done_face
;
775 xftfont_driver
.has_char
= xftfont_has_char
;
776 xftfont_driver
.encode_char
= xftfont_encode_char
;
777 xftfont_driver
.text_extents
= xftfont_text_extents
;
778 xftfont_driver
.draw
= xftfont_draw
;
779 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
780 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
781 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
782 xftfont_driver
.shape
= xftfont_shape
;
785 register_font_driver (&xftfont_driver
, NULL
);