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/>. */
25 #include <X11/Xft/Xft.h>
28 #include "dispextern.h"
31 #include "blockinput.h"
32 #include "character.h"
34 #include "composite.h"
39 /* Xft font driver. */
42 /* The actual structure for Xft font that can be cast to struct
48 /* The following five members must be here in this order to be
49 compatible with struct ftfont_info (in ftfont.c). */
51 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
53 #endif /* HAVE_LIBOTF */
59 unsigned x_display_id
;
62 /* Structure pointed by (struct face *)->extra */
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
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
;
83 *bg
= xftface_info
->xft_bg
;
88 bool fg_done
= false, bg_done
= false;
91 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
92 GCForeground
| GCBackground
, &xgcv
);
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;
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
))
111 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
113 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
114 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
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
;
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
;
133 struct font_driver xftfont_driver
;
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
);
146 xftfont_match (struct frame
*f
, Lisp_Object spec
)
148 Lisp_Object entity
= ftfont_driver
.match (f
, spec
);
151 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
155 static FcChar8 ascii_printable
[95];
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. */
169 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
172 FcPatternDel (match
, FC_ANTIALIAS
);
173 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
175 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
178 FcPatternDel (match
, FC_HINTING
);
179 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
181 #ifndef FC_HINT_STYLE
182 # define FC_HINT_STYLE "hintstyle"
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"
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
);
211 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
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
))
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
))
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
))
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
);
252 else if (EQ (key
, QCembolden
))
253 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
259 xftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
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
;
268 XftFont
*xftfont
= NULL
;
275 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
279 filename
= XCAR (val
);
281 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
284 pat
= FcPatternCreate ();
285 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
286 i
= FONT_SLANT_NUMERIC (entity
) - 100;
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
);
293 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
294 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
296 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
297 val
= AREF (entity
, FONT_SPACING_INDEX
);
299 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
300 val
= AREF (entity
, FONT_DPI_INDEX
);
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
));
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
);
332 XftPatternDestroy (match
);
335 ft_face
= XftLockFace (xftfont
);
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
),
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
)
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
));
365 spacing
= FC_PROPORTIONAL
;
366 if (! ascii_printable
[0])
369 for (ch
= 0; ch
< 95; ch
++)
370 ascii_printable
[ch
] = ' ' + ch
;
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
379 && spacing
!= 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
);
389 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
390 font
->min_width
= font
->max_width
= font
->space_width
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;
400 font
->ascent
= xftfont
->ascent
;
401 font
->descent
= xftfont
->descent
;
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;
425 font
->underline_position
= -1;
426 font
->underline_thickness
= 0;
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;
439 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
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
;
459 xftfont_close (struct font
*font
)
461 struct x_display_info
*xdi
;
462 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
465 if (xftfont_info
->otf
)
467 OTF_close (xftfont_info
->otf
);
468 xftfont_info
->otf
= NULL
;
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
))
478 XftUnlockFace (xftfont_info
->xftfont
);
479 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
481 xftfont_info
->xftfont
= NULL
;
486 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
488 struct xftface_info
*xftface_info
;
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
;
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
;
506 xftfont_done_face (struct frame
*f
, struct face
*face
)
508 struct xftface_info
*xftface_info
;
511 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
512 if (face
!= face
->ascii_face
517 xftface_info
= (struct xftface_info
*) face
->extra
;
520 xfree (xftface_info
);
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
);
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
);
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
,
554 return (code
? code
: FONT_INVALID_CODE
);
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
;
565 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
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
;
577 xftfont_get_xft_draw (struct frame
*f
)
579 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
584 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
587 FRAME_X_COLORMAP (f
));
589 eassert (xft_draw
!= NULL
);
590 font_put_frame_data (f
, Qxft
, xft_draw
);
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
);
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
);
614 if (s
->num_clips
> 0)
615 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
617 XftDrawSetClip (xft_draw
, NULL
);
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
));
628 for (i
= 0; i
< len
; i
++)
629 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
630 x
+ i
, y
, code
+ i
, 1);
632 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
639 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
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
;
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
);
657 xftfont_end_for_frame (struct frame
*f
)
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
);
669 XftDrawDestroy (xft_draw
);
671 font_put_frame_data (f
, Qxft
, NULL
);
677 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
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 ();
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
;
701 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
702 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
703 if (r1
!= r2
|| b1
!= b2
) goto out
;
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
;
717 FcPatternDestroy (pat
);
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
;
753 register_font_driver (&xftfont_driver
, NULL
);