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 x_query_colors (f
, colors
, bg
? 2 : 1);
115 fg
->color
.alpha
= 0xFFFF;
116 fg
->color
.red
= colors
[0].red
;
117 fg
->color
.green
= colors
[0].green
;
118 fg
->color
.blue
= colors
[0].blue
;
121 bg
->color
.alpha
= 0xFFFF;
122 bg
->color
.red
= colors
[1].red
;
123 bg
->color
.green
= colors
[1].green
;
124 bg
->color
.blue
= colors
[1].blue
;
132 struct font_driver xftfont_driver
;
135 xftfont_list (struct frame
*f
, Lisp_Object spec
)
137 Lisp_Object list
= ftfont_driver
.list (f
, spec
), tail
;
139 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
140 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
145 xftfont_match (struct frame
*f
, Lisp_Object spec
)
147 Lisp_Object entity
= ftfont_driver
.match (f
, spec
);
150 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
154 static FcChar8 ascii_printable
[95];
157 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
159 /* These values are not used for matching (except antialias), but for
160 rendering, so make sure they are carried over to the match.
161 We also put antialias here because most fonts are antialiased, so
162 the match will have antialias true. */
168 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
171 FcPatternDel (match
, FC_ANTIALIAS
);
172 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
174 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
177 FcPatternDel (match
, FC_HINTING
);
178 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
180 #ifndef FC_HINT_STYLE
181 # define FC_HINT_STYLE "hintstyle"
183 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
185 FcPatternDel (match
, FC_HINT_STYLE
);
186 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
188 #ifndef FC_LCD_FILTER
189 /* Older fontconfig versions don't have FC_LCD_FILTER. */
190 #define FC_LCD_FILTER "lcdfilter"
192 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
194 FcPatternDel (match
, FC_LCD_FILTER
);
195 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
197 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
199 FcPatternDel (match
, FC_RGBA
);
200 FcPatternAddInteger (match
, FC_RGBA
, i
);
202 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
204 FcPatternDel (match
, FC_DPI
);
205 FcPatternAddDouble (match
, FC_DPI
, dpi
);
210 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
215 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
217 Lisp_Object key
= XCAR (XCAR (tail
));
218 Lisp_Object val
= XCDR (XCAR (tail
));
220 if (EQ (key
, QCantialias
))
221 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
222 else if (EQ (key
, QChinting
))
223 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
224 else if (EQ (key
, QCautohint
))
225 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
226 else if (EQ (key
, QChintstyle
))
229 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
230 else if (SYMBOLP (val
)
231 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
232 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
234 else if (EQ (key
, QCrgba
))
237 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
238 else if (SYMBOLP (val
)
239 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
240 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
242 else if (EQ (key
, QClcdfilter
))
245 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
246 else if (SYMBOLP (val
)
247 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
248 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
251 else if (EQ (key
, QCembolden
))
252 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
258 xftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
261 Display
*display
= FRAME_X_DISPLAY (f
);
262 Lisp_Object val
, filename
, idx
, font_object
;
263 FcPattern
*pat
= NULL
, *match
;
264 struct xftfont_info
*xftfont_info
= NULL
;
267 XftFont
*xftfont
= NULL
;
274 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
278 filename
= XCAR (val
);
280 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
283 pat
= FcPatternCreate ();
284 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
285 i
= FONT_SLANT_NUMERIC (entity
) - 100;
287 FcPatternAddInteger (pat
, FC_SLANT
, i
);
288 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
289 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
290 val
= AREF (entity
, FONT_FAMILY_INDEX
);
292 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
293 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
295 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
296 val
= AREF (entity
, FONT_SPACING_INDEX
);
298 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
299 val
= AREF (entity
, FONT_DPI_INDEX
);
302 double dbl
= XINT (val
);
304 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
306 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
307 if (INTEGERP (val
) && XINT (val
) == 0)
308 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
309 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
310 over 10x20-ISO8859-1.pcf.gz). */
311 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
313 xftfont_add_rendering_parameters (pat
, entity
);
315 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
316 FcPatternAddInteger (pat
, FC_INDEX
, XINT (idx
));
321 /* Substitute in values from X resources and XftDefaultSet. */
322 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
323 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
324 xftfont_fix_match (pat
, match
);
326 FcPatternDestroy (pat
);
327 xftfont
= XftFontOpenPattern (display
, match
);
331 XftPatternDestroy (match
);
334 ft_face
= XftLockFace (xftfont
);
337 /* We should not destroy PAT here because it is kept in XFTFONT and
338 destroyed automatically when XFTFONT is closed. */
339 font_object
= font_build_object (VECSIZE (struct xftfont_info
),
341 ASET (font_object
, FONT_FILE_INDEX
, filename
);
342 font
= XFONT_OBJECT (font_object
);
343 font
->pixel_size
= size
;
344 font
->driver
= &xftfont_driver
;
345 font
->encoding_charset
= font
->repertory_charset
= -1;
347 xftfont_info
= (struct xftfont_info
*) font
;
348 xftfont_info
->display
= display
;
349 xftfont_info
->xftfont
= xftfont
;
350 xftfont_info
->x_display_id
= FRAME_DISPLAY_INFO (f
)->x_id
;
351 /* This means that there's no need of transformation. */
352 xftfont_info
->matrix
.xx
= 0;
353 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
356 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
357 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
358 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
359 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
361 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
362 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
364 spacing
= FC_PROPORTIONAL
;
365 if (! ascii_printable
[0])
368 for (ch
= 0; ch
< 95; ch
++)
369 ascii_printable
[ch
] = ' ' + ch
;
373 /* Unfortunately Xft doesn't provide a way to get minimum char
374 width. So, we set min_width to space_width. */
376 if (spacing
!= FC_PROPORTIONAL
378 && spacing
!= FC_DUAL
382 font
->min_width
= font
->max_width
= font
->average_width
383 = font
->space_width
= xftfont
->max_advance_width
;
384 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
388 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
389 font
->min_width
= font
->max_width
= font
->space_width
391 if (font
->space_width
<= 0)
392 /* dirty workaround */
393 font
->space_width
= pixel_size
;
394 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
395 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
399 font
->ascent
= xftfont
->ascent
;
400 font
->descent
= xftfont
->descent
;
403 /* The above condition is a dirty workaround because
404 XftTextExtents8 behaves strangely for some fonts
405 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
406 if (font
->ascent
< extents
.y
)
407 font
->ascent
= extents
.y
;
408 if (font
->descent
< extents
.height
- extents
.y
)
409 font
->descent
= extents
.height
- extents
.y
;
411 font
->height
= font
->ascent
+ font
->descent
;
413 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
415 int upEM
= ft_face
->units_per_EM
;
417 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
418 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
419 if (font
->underline_thickness
> 2)
420 font
->underline_position
-= font
->underline_thickness
/ 2;
424 font
->underline_position
= -1;
425 font
->underline_thickness
= 0;
428 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
429 xftfont_info
->otf
= NULL
;
430 #endif /* HAVE_LIBOTF */
431 xftfont_info
->ft_size
= ft_face
->size
;
433 font
->baseline_offset
= 0;
434 font
->relative_compose
= 0;
435 font
->default_ascent
= 0;
436 font
->vertical_centering
= false;
438 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
442 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
443 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
444 font
->baseline_offset
= rec
.u
.integer
;
445 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
446 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
447 font
->relative_compose
= rec
.u
.integer
;
448 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
449 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
450 font
->default_ascent
= rec
.u
.integer
;
458 xftfont_close (struct font
*font
)
460 struct x_display_info
*xdi
;
461 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
464 if (xftfont_info
->otf
)
466 OTF_close (xftfont_info
->otf
);
467 xftfont_info
->otf
= NULL
;
471 /* See comment in xfont_close. */
472 if (xftfont_info
->xftfont
473 && ((xdi
= x_display_info_for_display (xftfont_info
->display
))
474 && xftfont_info
->x_display_id
== xdi
->x_id
))
477 XftUnlockFace (xftfont_info
->xftfont
);
478 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
480 xftfont_info
->xftfont
= NULL
;
485 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
487 struct xftface_info
*xftface_info
;
490 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
491 if (face
!= face
->ascii_face
)
493 face
->extra
= face
->ascii_face
->extra
;
498 xftface_info
= xmalloc (sizeof *xftface_info
);
499 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
500 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
501 face
->extra
= xftface_info
;
505 xftfont_done_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
516 xftface_info
= (struct xftface_info
*) face
->extra
;
519 xfree (xftface_info
);
525 xftfont_has_char (Lisp_Object font
, int c
)
527 struct xftfont_info
*xftfont_info
;
528 struct charset
*cs
= NULL
;
530 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
531 && charset_jisx0208
>= 0)
532 cs
= CHARSET_FROM_ID (charset_jisx0208
);
533 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
534 && charset_ksc5601
>= 0)
535 cs
= CHARSET_FROM_ID (charset_ksc5601
);
537 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
539 if (FONT_ENTITY_P (font
))
540 return ftfont_driver
.has_char (font
, c
);
541 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
542 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
543 (FcChar32
) c
) == FcTrue
);
547 xftfont_encode_char (struct font
*font
, int c
)
549 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
550 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
553 return (code
? code
: FONT_INVALID_CODE
);
557 xftfont_text_extents (struct font
*font
, unsigned int *code
,
558 int nglyphs
, struct font_metrics
*metrics
)
560 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
564 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
568 metrics
->lbearing
= - extents
.x
;
569 metrics
->rbearing
= - extents
.x
+ extents
.width
;
570 metrics
->width
= extents
.xOff
;
571 metrics
->ascent
= extents
.y
;
572 metrics
->descent
= extents
.height
- extents
.y
;
576 xftfont_get_xft_draw (struct frame
*f
)
578 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
583 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
586 FRAME_X_COLORMAP (f
));
588 eassert (xft_draw
!= NULL
);
589 font_put_frame_data (f
, Qxft
, xft_draw
);
595 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
596 bool with_background
)
598 struct frame
*f
= s
->f
;
599 struct face
*face
= s
->face
;
600 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
601 struct xftface_info
*xftface_info
= NULL
;
602 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
608 if (s
->font
== face
->font
)
609 xftface_info
= (struct xftface_info
*) face
->extra
;
610 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
611 &fg
, with_background
? &bg
: NULL
);
613 if (s
->num_clips
> 0)
614 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
616 XftDrawSetClip (xft_draw
, NULL
);
620 int height
= FONT_HEIGHT (s
->font
), ascent
= FONT_BASE (s
->font
);
622 /* Font's global height and ascent values might be
623 preposterously large for some fonts. We fix here the case
624 when those fonts are used for display of glyphless
625 characters, because drawing background with font dimensions
626 in those cases makes the display illegible. There's only one
627 more call to the draw method with with_background set to
628 true, and that's in x_draw_glyph_string_foreground, when
629 drawing the cursor, where we have no such heuristics
631 if (s
->first_glyph
->type
== GLYPHLESS_GLYPH
632 && (s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
633 || s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
))
635 s
->first_glyph
->slice
.glyphless
.lower_yoff
636 - s
->first_glyph
->slice
.glyphless
.upper_yoff
;
637 XftDrawRect (xft_draw
, &bg
, x
, y
- ascent
, s
->width
, height
);
639 code
= alloca (sizeof (FT_UInt
) * len
);
640 for (i
= 0; i
< len
; i
++)
641 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
642 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
645 for (i
= 0; i
< len
; i
++)
646 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
647 x
+ i
, y
, code
+ i
, 1);
649 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
656 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
658 xftfont_shape (Lisp_Object lgstring
)
660 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
661 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
665 ft_face
= XftLockFace (xftfont_info
->xftfont
);
666 xftfont_info
->ft_size
= ft_face
->size
;
667 val
= ftfont_driver
.shape (lgstring
);
668 XftUnlockFace (xftfont_info
->xftfont
);
674 xftfont_end_for_frame (struct frame
*f
)
678 /* Don't do anything if display is dead */
679 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
681 xft_draw
= font_get_frame_data (f
, Qxft
);
686 XftDrawDestroy (xft_draw
);
688 font_put_frame_data (f
, Qxft
, NULL
);
694 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
697 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
698 FcPattern
*oldpat
= info
->xftfont
->pattern
;
699 Display
*display
= FRAME_X_DISPLAY (f
);
700 FcPattern
*pat
= FcPatternCreate ();
705 xftfont_add_rendering_parameters (pat
, entity
);
706 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
708 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
709 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
710 if (r1
!= r2
|| b1
!= b2
) goto out
;
711 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
712 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
713 if (r1
!= r2
|| b1
!= b2
) goto out
;
714 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
715 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
716 if (r1
!= r2
|| b1
!= b2
) goto out
;
718 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
719 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
720 if (r1
!= r2
|| b1
!= b2
) goto out
;
722 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
723 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
724 if (r1
!= r2
|| i1
!= i2
) goto out
;
725 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
726 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
727 if (r1
!= r2
|| i1
!= i2
) goto out
;
728 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
729 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
730 if (r1
!= r2
|| i1
!= i2
) goto out
;
734 FcPatternDestroy (pat
);
739 syms_of_xftfont (void)
741 DEFSYM (Qxft
, "xft");
742 DEFSYM (QChinting
, ":hinting");
743 DEFSYM (QCautohint
, ":autohint");
744 DEFSYM (QChintstyle
, ":hintstyle");
745 DEFSYM (QCrgba
, ":rgba");
746 DEFSYM (QCembolden
, ":embolden");
747 DEFSYM (QClcdfilter
, ":lcdfilter");
749 ascii_printable
[0] = 0;
751 xftfont_driver
= ftfont_driver
;
752 xftfont_driver
.type
= Qxft
;
753 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
754 xftfont_driver
.list
= xftfont_list
;
755 xftfont_driver
.match
= xftfont_match
;
756 xftfont_driver
.open
= xftfont_open
;
757 xftfont_driver
.close
= xftfont_close
;
758 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
759 xftfont_driver
.done_face
= xftfont_done_face
;
760 xftfont_driver
.has_char
= xftfont_has_char
;
761 xftfont_driver
.encode_char
= xftfont_encode_char
;
762 xftfont_driver
.text_extents
= xftfont_text_extents
;
763 xftfont_driver
.draw
= xftfont_draw
;
764 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
765 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
766 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
767 xftfont_driver
.shape
= xftfont_shape
;
770 register_font_driver (&xftfont_driver
, NULL
);