1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2014 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 cast 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 */
62 unsigned x_display_id
;
65 /* Structure pointed by (struct face *)->extra */
69 XftColor xft_fg
; /* color for face->foreground */
70 XftColor xft_bg
; /* color for face->background */
73 /* Setup foreground and background colors of GC into FG and BG. If
74 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
78 xftfont_get_colors (struct frame
*f
, struct face
*face
, GC gc
,
79 struct xftface_info
*xftface_info
,
80 XftColor
*fg
, XftColor
*bg
)
82 if (xftface_info
&& face
->gc
== gc
)
84 *fg
= xftface_info
->xft_fg
;
86 *bg
= xftface_info
->xft_bg
;
91 bool fg_done
= 0, bg_done
= 0;
94 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
95 GCForeground
| GCBackground
, &xgcv
);
98 if (xgcv
.foreground
== face
->foreground
)
99 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
100 else if (xgcv
.foreground
== face
->background
)
101 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
104 else if (xgcv
.background
== face
->background
)
105 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
106 else if (xgcv
.background
== face
->foreground
)
107 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
110 if (! (fg_done
& bg_done
))
114 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
116 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
117 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
119 fg
->color
.alpha
= 0xFFFF;
120 fg
->color
.red
= colors
[0].red
;
121 fg
->color
.green
= colors
[0].green
;
122 fg
->color
.blue
= colors
[0].blue
;
125 bg
->color
.alpha
= 0xFFFF;
126 bg
->color
.red
= colors
[1].red
;
127 bg
->color
.green
= colors
[1].green
;
128 bg
->color
.blue
= colors
[1].blue
;
136 struct font_driver xftfont_driver
;
139 xftfont_list (struct frame
*f
, Lisp_Object spec
)
141 Lisp_Object list
= ftfont_driver
.list (f
, spec
), tail
;
143 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
144 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
149 xftfont_match (struct frame
*f
, Lisp_Object spec
)
151 Lisp_Object entity
= ftfont_driver
.match (f
, spec
);
154 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
158 static FcChar8 ascii_printable
[95];
161 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
163 /* These values are not used for matching (except antialias), but for
164 rendering, so make sure they are carried over to the match.
165 We also put antialias here because most fonts are antialiased, so
166 the match will have antialias true. */
172 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
175 FcPatternDel (match
, FC_ANTIALIAS
);
176 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
178 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
181 FcPatternDel (match
, FC_HINTING
);
182 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
184 #ifndef FC_HINT_STYLE
185 # define FC_HINT_STYLE "hintstyle"
187 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
189 FcPatternDel (match
, FC_HINT_STYLE
);
190 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
192 #ifndef FC_LCD_FILTER
193 /* Older fontconfig versions don't have FC_LCD_FILTER. */
194 #define FC_LCD_FILTER "lcdfilter"
196 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
198 FcPatternDel (match
, FC_LCD_FILTER
);
199 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
201 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
203 FcPatternDel (match
, FC_RGBA
);
204 FcPatternAddInteger (match
, FC_RGBA
, i
);
206 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
208 FcPatternDel (match
, FC_DPI
);
209 FcPatternAddDouble (match
, FC_DPI
, dpi
);
214 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
219 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
221 Lisp_Object key
= XCAR (XCAR (tail
));
222 Lisp_Object val
= XCDR (XCAR (tail
));
224 if (EQ (key
, QCantialias
))
225 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
226 else if (EQ (key
, QChinting
))
227 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
228 else if (EQ (key
, QCautohint
))
229 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
230 else if (EQ (key
, QChintstyle
))
233 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
234 else if (SYMBOLP (val
)
235 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
236 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
238 else if (EQ (key
, QCrgba
))
241 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
242 else if (SYMBOLP (val
)
243 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
244 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
246 else if (EQ (key
, QClcdfilter
))
249 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
250 else if (SYMBOLP (val
)
251 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
252 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
255 else if (EQ (key
, QCembolden
))
256 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
262 xftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
265 Display
*display
= FRAME_X_DISPLAY (f
);
266 Lisp_Object val
, filename
, idx
, font_object
;
267 FcPattern
*pat
= NULL
, *match
;
268 struct xftfont_info
*xftfont_info
= NULL
;
271 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
));
325 /* Substitute in values from X resources and XftDefaultSet. */
326 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
327 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
328 xftfont_fix_match (pat
, match
);
330 FcPatternDestroy (pat
);
331 xftfont
= XftFontOpenPattern (display
, match
);
335 XftPatternDestroy (match
);
338 ft_face
= XftLockFace (xftfont
);
341 /* We should not destroy PAT here because it is kept in XFTFONT and
342 destroyed automatically when XFTFONT is closed. */
343 font_object
= font_build_object (VECSIZE (struct xftfont_info
),
345 ASET (font_object
, FONT_FILE_INDEX
, filename
);
346 font
= XFONT_OBJECT (font_object
);
347 font
->pixel_size
= size
;
348 font
->driver
= &xftfont_driver
;
349 font
->encoding_charset
= font
->repertory_charset
= -1;
351 xftfont_info
= (struct xftfont_info
*) font
;
352 xftfont_info
->display
= display
;
353 xftfont_info
->xftfont
= xftfont
;
354 xftfont_info
->x_display_id
= FRAME_DISPLAY_INFO (f
)->x_id
;
355 /* This means that there's no need of transformation. */
356 xftfont_info
->matrix
.xx
= 0;
357 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
360 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
361 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
362 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
363 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
365 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
366 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
368 spacing
= FC_PROPORTIONAL
;
369 if (! ascii_printable
[0])
372 for (ch
= 0; ch
< 95; ch
++)
373 ascii_printable
[ch
] = ' ' + ch
;
377 /* Unfortunately Xft doesn't provide a way to get minimum char
378 width. So, we set min_width to space_width. */
380 if (spacing
!= FC_PROPORTIONAL
382 && spacing
!= FC_DUAL
386 font
->min_width
= font
->max_width
= font
->average_width
387 = font
->space_width
= xftfont
->max_advance_width
;
388 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
392 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
393 font
->min_width
= font
->max_width
= font
->space_width
395 if (font
->space_width
<= 0)
396 /* dirty workaround */
397 font
->space_width
= pixel_size
;
398 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
399 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
403 font
->ascent
= xftfont
->ascent
;
404 font
->descent
= xftfont
->descent
;
407 /* The above condition is a dirty workaround because
408 XftTextExtents8 behaves strangely for some fonts
409 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
410 if (font
->ascent
< extents
.y
)
411 font
->ascent
= extents
.y
;
412 if (font
->descent
< extents
.height
- extents
.y
)
413 font
->descent
= extents
.height
- extents
.y
;
415 font
->height
= font
->ascent
+ font
->descent
;
417 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
419 int upEM
= ft_face
->units_per_EM
;
421 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
422 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
423 if (font
->underline_thickness
> 2)
424 font
->underline_position
-= font
->underline_thickness
/ 2;
428 font
->underline_position
= -1;
429 font
->underline_thickness
= 0;
432 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
433 xftfont_info
->otf
= NULL
;
434 #endif /* HAVE_LIBOTF */
435 xftfont_info
->ft_size
= ft_face
->size
;
437 font
->baseline_offset
= 0;
438 font
->relative_compose
= 0;
439 font
->default_ascent
= 0;
440 font
->vertical_centering
= 0;
442 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
446 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
447 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
448 font
->baseline_offset
= rec
.u
.integer
;
449 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
450 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
451 font
->relative_compose
= rec
.u
.integer
;
452 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
453 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
454 font
->default_ascent
= rec
.u
.integer
;
462 xftfont_close (struct font
*font
)
464 struct x_display_info
*xdi
;
465 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
468 if (xftfont_info
->otf
)
470 OTF_close (xftfont_info
->otf
);
471 xftfont_info
->otf
= NULL
;
475 /* See comment in xfont_close. */
476 if (xftfont_info
->xftfont
477 && ((xdi
= x_display_info_for_display (xftfont_info
->display
))
478 && xftfont_info
->x_display_id
== xdi
->x_id
))
481 XftUnlockFace (xftfont_info
->xftfont
);
482 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
484 xftfont_info
->xftfont
= NULL
;
489 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
491 struct xftface_info
*xftface_info
;
494 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
495 if (face
!= face
->ascii_face
)
497 face
->extra
= face
->ascii_face
->extra
;
502 xftface_info
= xmalloc (sizeof *xftface_info
);
503 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
504 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
505 face
->extra
= xftface_info
;
509 xftfont_done_face (struct frame
*f
, struct face
*face
)
511 struct xftface_info
*xftface_info
;
514 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
515 if (face
!= face
->ascii_face
520 xftface_info
= (struct xftface_info
*) face
->extra
;
523 xfree (xftface_info
);
529 xftfont_has_char (Lisp_Object font
, int c
)
531 struct xftfont_info
*xftfont_info
;
532 struct charset
*cs
= NULL
;
534 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
535 && charset_jisx0208
>= 0)
536 cs
= CHARSET_FROM_ID (charset_jisx0208
);
537 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
538 && charset_ksc5601
>= 0)
539 cs
= CHARSET_FROM_ID (charset_ksc5601
);
541 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
543 if (FONT_ENTITY_P (font
))
544 return ftfont_driver
.has_char (font
, c
);
545 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
546 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
547 (FcChar32
) c
) == FcTrue
);
551 xftfont_encode_char (struct font
*font
, int c
)
553 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
554 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
557 return (code
? code
: FONT_INVALID_CODE
);
561 xftfont_text_extents (struct font
*font
, unsigned int *code
,
562 int nglyphs
, struct font_metrics
*metrics
)
564 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
568 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
572 metrics
->lbearing
= - extents
.x
;
573 metrics
->rbearing
= - extents
.x
+ extents
.width
;
574 metrics
->width
= extents
.xOff
;
575 metrics
->ascent
= extents
.y
;
576 metrics
->descent
= extents
.height
- extents
.y
;
580 xftfont_get_xft_draw (struct frame
*f
)
582 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
587 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
590 FRAME_X_COLORMAP (f
));
592 eassert (xft_draw
!= NULL
);
593 font_put_frame_data (f
, Qxft
, xft_draw
);
599 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
600 bool with_background
)
602 struct frame
*f
= s
->f
;
603 struct face
*face
= s
->face
;
604 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
605 struct xftface_info
*xftface_info
= NULL
;
606 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
612 if (s
->font
== face
->font
)
613 xftface_info
= (struct xftface_info
*) face
->extra
;
614 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
615 &fg
, with_background
? &bg
: NULL
);
617 if (s
->num_clips
> 0)
618 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
620 XftDrawSetClip (xft_draw
, NULL
);
623 XftDrawRect (xft_draw
, &bg
,
624 x
, y
- s
->font
->ascent
, s
->width
, s
->font
->height
);
625 code
= alloca (sizeof (FT_UInt
) * len
);
626 for (i
= 0; i
< len
; i
++)
627 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
628 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
631 for (i
= 0; i
< len
; i
++)
632 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
633 x
+ i
, y
, code
+ i
, 1);
635 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
642 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
644 xftfont_shape (Lisp_Object lgstring
)
647 struct xftfont_info
*xftfont_info
;
651 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
652 xftfont_info
= (struct xftfont_info
*) font
;
653 ft_face
= XftLockFace (xftfont_info
->xftfont
);
654 xftfont_info
->ft_size
= ft_face
->size
;
655 val
= ftfont_driver
.shape (lgstring
);
656 XftUnlockFace (xftfont_info
->xftfont
);
662 xftfont_end_for_frame (struct frame
*f
)
666 /* Don't do anything if display is dead */
667 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
669 xft_draw
= font_get_frame_data (f
, Qxft
);
674 XftDrawDestroy (xft_draw
);
676 font_put_frame_data (f
, Qxft
, NULL
);
682 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
685 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
686 FcPattern
*oldpat
= info
->xftfont
->pattern
;
687 Display
*display
= FRAME_X_DISPLAY (f
);
688 FcPattern
*pat
= FcPatternCreate ();
693 xftfont_add_rendering_parameters (pat
, entity
);
694 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
696 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
697 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
698 if (r1
!= r2
|| b1
!= b2
) goto out
;
699 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
700 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
701 if (r1
!= r2
|| b1
!= b2
) goto out
;
702 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
703 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
704 if (r1
!= r2
|| b1
!= b2
) goto out
;
706 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
707 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
708 if (r1
!= r2
|| b1
!= b2
) goto out
;
710 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
711 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
712 if (r1
!= r2
|| i1
!= i2
) goto out
;
713 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
714 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
715 if (r1
!= r2
|| i1
!= i2
) goto out
;
716 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
717 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
718 if (r1
!= r2
|| i1
!= i2
) goto out
;
722 FcPatternDestroy (pat
);
727 syms_of_xftfont (void)
729 DEFSYM (Qxft
, "xft");
730 DEFSYM (QChinting
, ":hinting");
731 DEFSYM (QCautohint
, ":autohint");
732 DEFSYM (QChintstyle
, ":hintstyle");
733 DEFSYM (QCrgba
, ":rgba");
734 DEFSYM (QCembolden
, ":embolden");
735 DEFSYM (QClcdfilter
, ":lcdfilter");
737 ascii_printable
[0] = 0;
739 xftfont_driver
= ftfont_driver
;
740 xftfont_driver
.type
= Qxft
;
741 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
742 xftfont_driver
.list
= xftfont_list
;
743 xftfont_driver
.match
= xftfont_match
;
744 xftfont_driver
.open
= xftfont_open
;
745 xftfont_driver
.close
= xftfont_close
;
746 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
747 xftfont_driver
.done_face
= xftfont_done_face
;
748 xftfont_driver
.has_char
= xftfont_has_char
;
749 xftfont_driver
.encode_char
= xftfont_encode_char
;
750 xftfont_driver
.text_extents
= xftfont_text_extents
;
751 xftfont_driver
.draw
= xftfont_draw
;
752 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
753 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
754 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
755 xftfont_driver
.shape
= xftfont_shape
;
758 register_font_driver (&xftfont_driver
, NULL
);