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
, int nglyphs
, struct font_metrics
*metrics
)
563 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
567 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
;
582 xftfont_get_xft_draw (struct frame
*f
)
584 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
589 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
592 FRAME_X_COLORMAP (f
));
594 eassert (xft_draw
!= NULL
);
595 font_put_frame_data (f
, Qxft
, xft_draw
);
601 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
602 bool with_background
)
604 struct frame
*f
= s
->f
;
605 struct face
*face
= s
->face
;
606 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
607 struct xftface_info
*xftface_info
= NULL
;
608 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
614 if (s
->font
== face
->font
)
615 xftface_info
= (struct xftface_info
*) face
->extra
;
616 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
617 &fg
, with_background
? &bg
: NULL
);
619 if (s
->num_clips
> 0)
620 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
622 XftDrawSetClip (xft_draw
, NULL
);
625 XftDrawRect (xft_draw
, &bg
,
626 x
, y
- s
->font
->ascent
, s
->width
, s
->font
->height
);
627 code
= alloca (sizeof (FT_UInt
) * len
);
628 for (i
= 0; i
< len
; i
++)
629 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
630 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
633 for (i
= 0; i
< len
; i
++)
634 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
635 x
+ i
, y
, code
+ i
, 1);
637 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
644 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
646 xftfont_shape (Lisp_Object lgstring
)
649 struct xftfont_info
*xftfont_info
;
653 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
654 xftfont_info
= (struct xftfont_info
*) font
;
655 ft_face
= XftLockFace (xftfont_info
->xftfont
);
656 xftfont_info
->ft_size
= ft_face
->size
;
657 val
= ftfont_driver
.shape (lgstring
);
658 XftUnlockFace (xftfont_info
->xftfont
);
664 xftfont_end_for_frame (struct frame
*f
)
668 /* Don't do anything if display is dead */
669 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
671 xft_draw
= font_get_frame_data (f
, Qxft
);
676 XftDrawDestroy (xft_draw
);
678 font_put_frame_data (f
, Qxft
, NULL
);
684 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
687 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
688 FcPattern
*oldpat
= info
->xftfont
->pattern
;
689 Display
*display
= FRAME_X_DISPLAY (f
);
690 FcPattern
*pat
= FcPatternCreate ();
695 xftfont_add_rendering_parameters (pat
, entity
);
696 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
698 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
699 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
700 if (r1
!= r2
|| b1
!= b2
) goto out
;
701 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
702 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
703 if (r1
!= r2
|| b1
!= b2
) goto out
;
704 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
705 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
706 if (r1
!= r2
|| b1
!= b2
) goto out
;
708 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
709 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
710 if (r1
!= r2
|| b1
!= b2
) goto out
;
712 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
713 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
714 if (r1
!= r2
|| i1
!= i2
) goto out
;
715 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
716 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
717 if (r1
!= r2
|| i1
!= i2
) goto out
;
718 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
719 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
720 if (r1
!= r2
|| i1
!= i2
) goto out
;
724 FcPatternDestroy (pat
);
729 syms_of_xftfont (void)
731 DEFSYM (Qxft
, "xft");
732 DEFSYM (QChinting
, ":hinting");
733 DEFSYM (QCautohint
, ":autohint");
734 DEFSYM (QChintstyle
, ":hintstyle");
735 DEFSYM (QCrgba
, ":rgba");
736 DEFSYM (QCembolden
, ":embolden");
737 DEFSYM (QClcdfilter
, ":lcdfilter");
739 ascii_printable
[0] = 0;
741 xftfont_driver
= ftfont_driver
;
742 xftfont_driver
.type
= Qxft
;
743 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
744 xftfont_driver
.list
= xftfont_list
;
745 xftfont_driver
.match
= xftfont_match
;
746 xftfont_driver
.open
= xftfont_open
;
747 xftfont_driver
.close
= xftfont_close
;
748 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
749 xftfont_driver
.done_face
= xftfont_done_face
;
750 xftfont_driver
.has_char
= xftfont_has_char
;
751 xftfont_driver
.encode_char
= xftfont_encode_char
;
752 xftfont_driver
.text_extents
= xftfont_text_extents
;
753 xftfont_driver
.draw
= xftfont_draw
;
754 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
755 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
756 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
757 xftfont_driver
.shape
= xftfont_shape
;
760 register_font_driver (&xftfont_driver
, NULL
);