1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2013 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 static Lisp_Object QChinting
, QCautohint
, QChintstyle
, QCrgba
, QCembolden
,
45 /* The actual structure for Xft font that can be casted to struct
51 /* The following five members must be here in this order to be
52 compatible with struct ftfont_info (in ftfont.c). */
54 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
56 #endif /* HAVE_LIBOTF */
64 /* Structure pointed by (struct face *)->extra */
68 XftColor xft_fg
; /* color for face->foreground */
69 XftColor xft_bg
; /* color for face->background */
72 /* Setup foreground and background colors of GC into FG and BG. If
73 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
77 xftfont_get_colors (struct frame
*f
, struct face
*face
, GC gc
,
78 struct xftface_info
*xftface_info
,
79 XftColor
*fg
, XftColor
*bg
)
81 if (xftface_info
&& face
->gc
== gc
)
83 *fg
= xftface_info
->xft_fg
;
85 *bg
= xftface_info
->xft_bg
;
90 bool fg_done
= 0, bg_done
= 0;
93 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
94 GCForeground
| GCBackground
, &xgcv
);
97 if (xgcv
.foreground
== face
->foreground
)
98 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
99 else if (xgcv
.foreground
== face
->background
)
100 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
103 else if (xgcv
.background
== face
->background
)
104 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
105 else if (xgcv
.background
== face
->foreground
)
106 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
109 if (! (fg_done
& bg_done
))
113 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
115 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
116 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
118 fg
->color
.alpha
= 0xFFFF;
119 fg
->color
.red
= colors
[0].red
;
120 fg
->color
.green
= colors
[0].green
;
121 fg
->color
.blue
= colors
[0].blue
;
124 bg
->color
.alpha
= 0xFFFF;
125 bg
->color
.red
= colors
[1].red
;
126 bg
->color
.green
= colors
[1].green
;
127 bg
->color
.blue
= colors
[1].blue
;
135 struct font_driver xftfont_driver
;
138 xftfont_list (struct frame
*f
, Lisp_Object spec
)
140 Lisp_Object list
= ftfont_driver
.list (f
, spec
), tail
;
142 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
143 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
148 xftfont_match (struct frame
*f
, Lisp_Object spec
)
150 Lisp_Object entity
= ftfont_driver
.match (f
, spec
);
153 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
157 static FcChar8 ascii_printable
[95];
160 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
162 /* These values are not used for matching (except antialias), but for
163 rendering, so make sure they are carried over to the match.
164 We also put antialias here because most fonts are antialiased, so
165 the match will have antialias true. */
171 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
174 FcPatternDel (match
, FC_ANTIALIAS
);
175 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
177 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
180 FcPatternDel (match
, FC_HINTING
);
181 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
183 #ifndef FC_HINT_STYLE
184 # define FC_HINT_STYLE "hintstyle"
186 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
188 FcPatternDel (match
, FC_HINT_STYLE
);
189 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
191 #ifndef FC_LCD_FILTER
192 /* Older fontconfig versions don't have FC_LCD_FILTER. */
193 #define FC_LCD_FILTER "lcdfilter"
195 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
197 FcPatternDel (match
, FC_LCD_FILTER
);
198 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
200 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
202 FcPatternDel (match
, FC_RGBA
);
203 FcPatternAddInteger (match
, FC_RGBA
, i
);
205 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
207 FcPatternDel (match
, FC_DPI
);
208 FcPatternAddDouble (match
, FC_DPI
, dpi
);
213 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
218 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
220 Lisp_Object key
= XCAR (XCAR (tail
));
221 Lisp_Object val
= XCDR (XCAR (tail
));
223 if (EQ (key
, QCantialias
))
224 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
225 else if (EQ (key
, QChinting
))
226 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
227 else if (EQ (key
, QCautohint
))
228 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
229 else if (EQ (key
, QChintstyle
))
232 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
233 else if (SYMBOLP (val
)
234 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
235 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
237 else if (EQ (key
, QCrgba
))
240 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
241 else if (SYMBOLP (val
)
242 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
243 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
245 else if (EQ (key
, QClcdfilter
))
248 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
249 else if (SYMBOLP (val
)
250 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
251 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
254 else if (EQ (key
, QCembolden
))
255 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
261 xftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
264 Display
*display
= FRAME_X_DISPLAY (f
);
265 Lisp_Object val
, filename
, idx
, font_object
;
266 FcPattern
*pat
= NULL
, *match
;
267 struct xftfont_info
*xftfont_info
= NULL
;
270 XftFont
*xftfont
= NULL
;
278 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
282 filename
= XCAR (val
);
284 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
287 pat
= FcPatternCreate ();
288 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
289 i
= FONT_SLANT_NUMERIC (entity
) - 100;
291 FcPatternAddInteger (pat
, FC_SLANT
, i
);
292 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
293 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
294 val
= AREF (entity
, FONT_FAMILY_INDEX
);
296 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
297 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
299 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
300 val
= AREF (entity
, FONT_SPACING_INDEX
);
302 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
303 val
= AREF (entity
, FONT_DPI_INDEX
);
306 double dbl
= XINT (val
);
308 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
310 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
311 if (INTEGERP (val
) && XINT (val
) == 0)
312 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
313 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
314 over 10x20-ISO8859-1.pcf.gz). */
315 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
317 xftfont_add_rendering_parameters (pat
, entity
);
319 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
320 FcPatternAddInteger (pat
, FC_INDEX
, XINT (idx
));
324 /* Make sure that the Xrender extension is added before the Xft one.
325 Otherwise, the close-display hook set by Xft is called after the
326 one for Xrender, and the former tries to re-add the latter. This
327 results in inconsistency of internal states and leads to X
328 protocol error when one reconnects to the same X server.
331 int event_base
, error_base
;
332 XRenderQueryExtension (display
, &event_base
, &error_base
);
335 /* Substitute in values from X resources and XftDefaultSet. */
336 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
337 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
338 xftfont_fix_match (pat
, match
);
340 FcPatternDestroy (pat
);
341 xftfont
= XftFontOpenPattern (display
, match
);
345 XftPatternDestroy (match
);
348 ft_face
= XftLockFace (xftfont
);
351 /* We should not destroy PAT here because it is kept in XFTFONT and
352 destroyed automatically when XFTFONT is closed. */
353 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
354 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
355 len
= font_unparse_xlfd (entity
, size
, name
, 256);
357 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
358 len
= font_unparse_fcname (entity
, size
, name
, 256);
360 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
362 ASET (font_object
, FONT_FULLNAME_INDEX
,
363 AREF (font_object
, FONT_NAME_INDEX
));
364 ASET (font_object
, FONT_FILE_INDEX
, filename
);
365 ASET (font_object
, FONT_FORMAT_INDEX
,
366 ftfont_font_format (xftfont
->pattern
, filename
));
367 font
= XFONT_OBJECT (font_object
);
368 font
->pixel_size
= size
;
369 font
->driver
= &xftfont_driver
;
370 font
->encoding_charset
= font
->repertory_charset
= -1;
372 xftfont_info
= (struct xftfont_info
*) font
;
373 xftfont_info
->display
= display
;
374 xftfont_info
->xftfont
= xftfont
;
375 /* This means that there's no need of transformation. */
376 xftfont_info
->matrix
.xx
= 0;
377 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
380 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
381 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
382 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
383 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
385 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
386 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
388 spacing
= FC_PROPORTIONAL
;
389 if (! ascii_printable
[0])
392 for (ch
= 0; ch
< 95; ch
++)
393 ascii_printable
[ch
] = ' ' + ch
;
397 /* Unfortunately Xft doesn't provide a way to get minimum char
398 width. So, we set min_width to space_width. */
400 if (spacing
!= FC_PROPORTIONAL
402 && spacing
!= FC_DUAL
406 font
->min_width
= font
->max_width
= font
->average_width
407 = font
->space_width
= xftfont
->max_advance_width
;
408 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
412 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
413 font
->min_width
= font
->max_width
= font
->space_width
415 if (font
->space_width
<= 0)
416 /* dirty workaround */
417 font
->space_width
= pixel_size
;
418 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
419 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
423 font
->ascent
= xftfont
->ascent
;
424 font
->descent
= xftfont
->descent
;
427 /* The above condition is a dirty workaround because
428 XftTextExtents8 behaves strangely for some fonts
429 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
430 if (font
->ascent
< extents
.y
)
431 font
->ascent
= extents
.y
;
432 if (font
->descent
< extents
.height
- extents
.y
)
433 font
->descent
= extents
.height
- extents
.y
;
435 font
->height
= font
->ascent
+ font
->descent
;
437 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
439 int upEM
= ft_face
->units_per_EM
;
441 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
442 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
443 if (font
->underline_thickness
> 2)
444 font
->underline_position
-= font
->underline_thickness
/ 2;
448 font
->underline_position
= -1;
449 font
->underline_thickness
= 0;
452 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
453 xftfont_info
->otf
= NULL
;
454 #endif /* HAVE_LIBOTF */
455 xftfont_info
->ft_size
= ft_face
->size
;
457 font
->baseline_offset
= 0;
458 font
->relative_compose
= 0;
459 font
->default_ascent
= 0;
460 font
->vertical_centering
= 0;
462 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
466 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
467 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
468 font
->baseline_offset
= rec
.u
.integer
;
469 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
470 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
471 font
->relative_compose
= rec
.u
.integer
;
472 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
473 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
474 font
->default_ascent
= rec
.u
.integer
;
482 xftfont_close (struct font
*font
)
484 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
487 if (xftfont_info
->otf
)
489 OTF_close (xftfont_info
->otf
);
490 xftfont_info
->otf
= NULL
;
494 if (xftfont_info
->xftfont
)
497 XftUnlockFace (xftfont_info
->xftfont
);
498 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
500 xftfont_info
->xftfont
= NULL
;
505 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
507 struct xftface_info
*xftface_info
;
510 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
511 if (face
!= face
->ascii_face
)
513 face
->extra
= face
->ascii_face
->extra
;
518 xftface_info
= malloc (sizeof *xftface_info
);
521 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
522 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
523 face
->extra
= xftface_info
;
528 xftfont_done_face (struct frame
*f
, struct face
*face
)
530 struct xftface_info
*xftface_info
;
533 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
534 if (face
!= face
->ascii_face
539 xftface_info
= (struct xftface_info
*) face
->extra
;
548 xftfont_has_char (Lisp_Object font
, int c
)
550 struct xftfont_info
*xftfont_info
;
551 struct charset
*cs
= NULL
;
553 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
554 && charset_jisx0208
>= 0)
555 cs
= CHARSET_FROM_ID (charset_jisx0208
);
556 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
557 && charset_ksc5601
>= 0)
558 cs
= CHARSET_FROM_ID (charset_ksc5601
);
560 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
562 if (FONT_ENTITY_P (font
))
563 return ftfont_driver
.has_char (font
, c
);
564 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
565 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
566 (FcChar32
) c
) == FcTrue
);
570 xftfont_encode_char (struct font
*font
, int c
)
572 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
573 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
576 return (code
? code
: FONT_INVALID_CODE
);
580 xftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
582 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
586 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
591 metrics
->lbearing
= - extents
.x
;
592 metrics
->rbearing
= - extents
.x
+ extents
.width
;
593 metrics
->width
= extents
.xOff
;
594 metrics
->ascent
= extents
.y
;
595 metrics
->descent
= extents
.height
- extents
.y
;
601 xftfont_get_xft_draw (struct frame
*f
)
603 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
608 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
611 FRAME_X_COLORMAP (f
));
613 eassert (xft_draw
!= NULL
);
614 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
620 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
621 bool with_background
)
623 struct frame
*f
= s
->f
;
624 struct face
*face
= s
->face
;
625 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
626 struct xftface_info
*xftface_info
= NULL
;
627 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
633 if (s
->font
== face
->font
)
634 xftface_info
= (struct xftface_info
*) face
->extra
;
635 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
636 &fg
, with_background
? &bg
: NULL
);
638 if (s
->num_clips
> 0)
639 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
641 XftDrawSetClip (xft_draw
, NULL
);
644 XftDrawRect (xft_draw
, &bg
,
645 x
, y
- s
->font
->ascent
, s
->width
, s
->font
->height
);
646 code
= alloca (sizeof (FT_UInt
) * len
);
647 for (i
= 0; i
< len
; i
++)
648 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
649 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
652 for (i
= 0; i
< len
; i
++)
653 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
654 x
+ i
, y
, code
+ i
, 1);
656 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
663 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
665 xftfont_shape (Lisp_Object lgstring
)
668 struct xftfont_info
*xftfont_info
;
672 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
673 xftfont_info
= (struct xftfont_info
*) font
;
674 ft_face
= XftLockFace (xftfont_info
->xftfont
);
675 xftfont_info
->ft_size
= ft_face
->size
;
676 val
= ftfont_driver
.shape (lgstring
);
677 XftUnlockFace (xftfont_info
->xftfont
);
683 xftfont_end_for_frame (struct frame
*f
)
687 /* Don't do anything if display is dead */
688 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
690 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
695 XftDrawDestroy (xft_draw
);
697 font_put_frame_data (f
, &xftfont_driver
, NULL
);
703 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
706 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
707 FcPattern
*oldpat
= info
->xftfont
->pattern
;
708 Display
*display
= FRAME_X_DISPLAY (f
);
709 FcPattern
*pat
= FcPatternCreate ();
714 xftfont_add_rendering_parameters (pat
, entity
);
715 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
717 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
718 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
719 if (r1
!= r2
|| b1
!= b2
) goto out
;
720 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
721 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
722 if (r1
!= r2
|| b1
!= b2
) goto out
;
723 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
724 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
725 if (r1
!= r2
|| b1
!= b2
) goto out
;
727 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
728 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
729 if (r1
!= r2
|| b1
!= b2
) goto out
;
731 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
732 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
733 if (r1
!= r2
|| i1
!= i2
) goto out
;
734 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
735 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
736 if (r1
!= r2
|| i1
!= i2
) goto out
;
737 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
738 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
739 if (r1
!= r2
|| i1
!= i2
) goto out
;
743 FcPatternDestroy (pat
);
748 syms_of_xftfont (void)
750 DEFSYM (Qxft
, "xft");
751 DEFSYM (QChinting
, ":hinting");
752 DEFSYM (QCautohint
, ":autohint");
753 DEFSYM (QChintstyle
, ":hintstyle");
754 DEFSYM (QCrgba
, ":rgba");
755 DEFSYM (QCembolden
, ":embolden");
756 DEFSYM (QClcdfilter
, ":lcdfilter");
758 ascii_printable
[0] = 0;
760 xftfont_driver
= ftfont_driver
;
761 xftfont_driver
.type
= Qxft
;
762 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
763 xftfont_driver
.list
= xftfont_list
;
764 xftfont_driver
.match
= xftfont_match
;
765 xftfont_driver
.open
= xftfont_open
;
766 xftfont_driver
.close
= xftfont_close
;
767 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
768 xftfont_driver
.done_face
= xftfont_done_face
;
769 xftfont_driver
.has_char
= xftfont_has_char
;
770 xftfont_driver
.encode_char
= xftfont_encode_char
;
771 xftfont_driver
.text_extents
= xftfont_text_extents
;
772 xftfont_driver
.draw
= xftfont_draw
;
773 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
774 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
775 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
776 xftfont_driver
.shape
= xftfont_shape
;
779 register_font_driver (&xftfont_driver
, NULL
);