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>
30 #include "blockinput.h"
32 #include "composite.h"
36 /* Xft font driver. */
39 /* The actual structure for Xft font that can be cast to struct
45 /* The following five members must be here in this order to be
46 compatible with struct ftfont_info (in ftfont.c). */
48 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
50 #endif /* HAVE_LIBOTF */
56 unsigned x_display_id
;
59 /* Structure pointed by (struct face *)->extra */
63 XftColor xft_fg
; /* color for face->foreground */
64 XftColor xft_bg
; /* color for face->background */
67 /* Setup foreground and background colors of GC into FG and BG. If
68 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
72 xftfont_get_colors (struct frame
*f
, struct face
*face
, GC gc
,
73 struct xftface_info
*xftface_info
,
74 XftColor
*fg
, XftColor
*bg
)
76 if (xftface_info
&& face
->gc
== gc
)
78 *fg
= xftface_info
->xft_fg
;
80 *bg
= xftface_info
->xft_bg
;
85 bool fg_done
= false, bg_done
= false;
88 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
89 GCForeground
| GCBackground
, &xgcv
);
92 if (xgcv
.foreground
== face
->foreground
)
93 *fg
= xftface_info
->xft_fg
, fg_done
= true;
94 else if (xgcv
.foreground
== face
->background
)
95 *fg
= xftface_info
->xft_bg
, fg_done
= true;
98 else if (xgcv
.background
== face
->background
)
99 *bg
= xftface_info
->xft_bg
, bg_done
= true;
100 else if (xgcv
.background
== face
->foreground
)
101 *bg
= xftface_info
->xft_fg
, bg_done
= true;
104 if (! (fg_done
& bg_done
))
108 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
110 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
111 x_query_colors (f
, colors
, bg
? 2 : 1);
112 fg
->color
.alpha
= 0xFFFF;
113 fg
->color
.red
= colors
[0].red
;
114 fg
->color
.green
= colors
[0].green
;
115 fg
->color
.blue
= colors
[0].blue
;
118 bg
->color
.alpha
= 0xFFFF;
119 bg
->color
.red
= colors
[1].red
;
120 bg
->color
.green
= colors
[1].green
;
121 bg
->color
.blue
= colors
[1].blue
;
129 struct font_driver xftfont_driver
;
132 xftfont_list (struct frame
*f
, Lisp_Object spec
)
134 Lisp_Object list
= ftfont_driver
.list (f
, spec
), tail
;
136 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
137 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
142 xftfont_match (struct frame
*f
, Lisp_Object spec
)
144 Lisp_Object entity
= ftfont_driver
.match (f
, spec
);
147 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
151 static FcChar8 ascii_printable
[95];
154 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
156 /* These values are not used for matching (except antialias), but for
157 rendering, so make sure they are carried over to the match.
158 We also put antialias here because most fonts are antialiased, so
159 the match will have antialias true. */
165 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
168 FcPatternDel (match
, FC_ANTIALIAS
);
169 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
171 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
174 FcPatternDel (match
, FC_HINTING
);
175 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
177 #ifndef FC_HINT_STYLE
178 # define FC_HINT_STYLE "hintstyle"
180 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
182 FcPatternDel (match
, FC_HINT_STYLE
);
183 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
185 #ifndef FC_LCD_FILTER
186 /* Older fontconfig versions don't have FC_LCD_FILTER. */
187 #define FC_LCD_FILTER "lcdfilter"
189 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
191 FcPatternDel (match
, FC_LCD_FILTER
);
192 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
194 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
196 FcPatternDel (match
, FC_RGBA
);
197 FcPatternAddInteger (match
, FC_RGBA
, i
);
199 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
201 FcPatternDel (match
, FC_DPI
);
202 FcPatternAddDouble (match
, FC_DPI
, dpi
);
207 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
212 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
214 Lisp_Object key
= XCAR (XCAR (tail
));
215 Lisp_Object val
= XCDR (XCAR (tail
));
217 if (EQ (key
, QCantialias
))
218 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
219 else if (EQ (key
, QChinting
))
220 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
221 else if (EQ (key
, QCautohint
))
222 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
223 else if (EQ (key
, QChintstyle
))
226 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
227 else if (SYMBOLP (val
)
228 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
229 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
231 else if (EQ (key
, QCrgba
))
234 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
235 else if (SYMBOLP (val
)
236 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
237 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
239 else if (EQ (key
, QClcdfilter
))
242 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
243 else if (SYMBOLP (val
)
244 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
245 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
248 else if (EQ (key
, QCembolden
))
249 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
255 xftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
258 Display
*display
= FRAME_X_DISPLAY (f
);
259 Lisp_Object val
, filename
, idx
, font_object
;
260 FcPattern
*pat
= NULL
, *match
;
261 struct xftfont_info
*xftfont_info
= NULL
;
264 XftFont
*xftfont
= NULL
;
271 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
275 filename
= XCAR (val
);
277 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
280 pat
= FcPatternCreate ();
281 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
282 i
= FONT_SLANT_NUMERIC (entity
) - 100;
284 FcPatternAddInteger (pat
, FC_SLANT
, i
);
285 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
286 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
287 val
= AREF (entity
, FONT_FAMILY_INDEX
);
289 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
290 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
292 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
293 val
= AREF (entity
, FONT_SPACING_INDEX
);
295 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
296 val
= AREF (entity
, FONT_DPI_INDEX
);
299 double dbl
= XINT (val
);
301 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
303 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
304 if (INTEGERP (val
) && XINT (val
) == 0)
305 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
306 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
307 over 10x20-ISO8859-1.pcf.gz). */
308 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
310 xftfont_add_rendering_parameters (pat
, entity
);
312 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
313 FcPatternAddInteger (pat
, FC_INDEX
, XINT (idx
));
318 /* Substitute in values from X resources and XftDefaultSet. */
319 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
320 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
321 xftfont_fix_match (pat
, match
);
323 FcPatternDestroy (pat
);
324 xftfont
= XftFontOpenPattern (display
, match
);
328 XftPatternDestroy (match
);
331 ft_face
= XftLockFace (xftfont
);
334 /* We should not destroy PAT here because it is kept in XFTFONT and
335 destroyed automatically when XFTFONT is closed. */
336 font_object
= font_build_object (VECSIZE (struct xftfont_info
),
338 ASET (font_object
, FONT_FILE_INDEX
, filename
);
339 font
= XFONT_OBJECT (font_object
);
340 font
->pixel_size
= size
;
341 font
->driver
= &xftfont_driver
;
342 font
->encoding_charset
= font
->repertory_charset
= -1;
344 xftfont_info
= (struct xftfont_info
*) font
;
345 xftfont_info
->display
= display
;
346 xftfont_info
->xftfont
= xftfont
;
347 xftfont_info
->x_display_id
= FRAME_DISPLAY_INFO (f
)->x_id
;
348 /* This means that there's no need of transformation. */
349 xftfont_info
->matrix
.xx
= 0;
350 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
353 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
354 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
355 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
356 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
358 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
359 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
361 spacing
= FC_PROPORTIONAL
;
362 if (! ascii_printable
[0])
365 for (ch
= 0; ch
< 95; ch
++)
366 ascii_printable
[ch
] = ' ' + ch
;
370 /* Unfortunately Xft doesn't provide a way to get minimum char
371 width. So, we set min_width to space_width. */
373 if (spacing
!= FC_PROPORTIONAL
375 && spacing
!= FC_DUAL
379 font
->min_width
= font
->max_width
= font
->average_width
380 = font
->space_width
= xftfont
->max_advance_width
;
381 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
385 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
386 font
->min_width
= font
->max_width
= font
->space_width
388 if (font
->space_width
<= 0)
389 /* dirty workaround */
390 font
->space_width
= pixel_size
;
391 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
392 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
396 font
->ascent
= xftfont
->ascent
;
397 font
->descent
= xftfont
->descent
;
400 /* The above condition is a dirty workaround because
401 XftTextExtents8 behaves strangely for some fonts
402 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
403 if (font
->ascent
< extents
.y
)
404 font
->ascent
= extents
.y
;
405 if (font
->descent
< extents
.height
- extents
.y
)
406 font
->descent
= extents
.height
- extents
.y
;
408 font
->height
= font
->ascent
+ font
->descent
;
410 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
412 int upEM
= ft_face
->units_per_EM
;
414 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
415 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
416 if (font
->underline_thickness
> 2)
417 font
->underline_position
-= font
->underline_thickness
/ 2;
421 font
->underline_position
= -1;
422 font
->underline_thickness
= 0;
425 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
426 xftfont_info
->otf
= NULL
;
427 #endif /* HAVE_LIBOTF */
428 xftfont_info
->ft_size
= ft_face
->size
;
430 font
->baseline_offset
= 0;
431 font
->relative_compose
= 0;
432 font
->default_ascent
= 0;
433 font
->vertical_centering
= false;
435 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
439 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
440 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
441 font
->baseline_offset
= rec
.u
.integer
;
442 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
443 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
444 font
->relative_compose
= rec
.u
.integer
;
445 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
446 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
447 font
->default_ascent
= rec
.u
.integer
;
455 xftfont_close (struct font
*font
)
457 struct x_display_info
*xdi
;
458 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
461 if (xftfont_info
->otf
)
463 OTF_close (xftfont_info
->otf
);
464 xftfont_info
->otf
= NULL
;
468 /* See comment in xfont_close. */
469 if (xftfont_info
->xftfont
470 && ((xdi
= x_display_info_for_display (xftfont_info
->display
))
471 && xftfont_info
->x_display_id
== xdi
->x_id
))
474 XftUnlockFace (xftfont_info
->xftfont
);
475 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
477 xftfont_info
->xftfont
= NULL
;
482 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
484 struct xftface_info
*xftface_info
;
487 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
488 if (face
!= face
->ascii_face
)
490 face
->extra
= face
->ascii_face
->extra
;
495 xftface_info
= xmalloc (sizeof *xftface_info
);
496 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
497 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
498 face
->extra
= xftface_info
;
502 xftfont_done_face (struct frame
*f
, struct face
*face
)
504 struct xftface_info
*xftface_info
;
507 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
508 if (face
!= face
->ascii_face
513 xftface_info
= (struct xftface_info
*) face
->extra
;
516 xfree (xftface_info
);
522 xftfont_has_char (Lisp_Object font
, int c
)
524 struct xftfont_info
*xftfont_info
;
525 struct charset
*cs
= NULL
;
527 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
528 && charset_jisx0208
>= 0)
529 cs
= CHARSET_FROM_ID (charset_jisx0208
);
530 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
531 && charset_ksc5601
>= 0)
532 cs
= CHARSET_FROM_ID (charset_ksc5601
);
534 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
536 if (FONT_ENTITY_P (font
))
537 return ftfont_driver
.has_char (font
, c
);
538 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
539 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
540 (FcChar32
) c
) == FcTrue
);
544 xftfont_encode_char (struct font
*font
, int c
)
546 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
547 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
550 return (code
? code
: FONT_INVALID_CODE
);
554 xftfont_text_extents (struct font
*font
, unsigned int *code
,
555 int nglyphs
, struct font_metrics
*metrics
)
557 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
561 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
565 metrics
->lbearing
= - extents
.x
;
566 metrics
->rbearing
= - extents
.x
+ extents
.width
;
567 metrics
->width
= extents
.xOff
;
568 metrics
->ascent
= extents
.y
;
569 metrics
->descent
= extents
.height
- extents
.y
;
573 xftfont_get_xft_draw (struct frame
*f
)
575 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
580 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
583 FRAME_X_COLORMAP (f
));
585 eassert (xft_draw
!= NULL
);
586 font_put_frame_data (f
, Qxft
, xft_draw
);
592 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
593 bool with_background
)
595 struct frame
*f
= s
->f
;
596 struct face
*face
= s
->face
;
597 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
598 struct xftface_info
*xftface_info
= NULL
;
599 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
605 if (s
->font
== face
->font
)
606 xftface_info
= (struct xftface_info
*) face
->extra
;
607 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
608 &fg
, with_background
? &bg
: NULL
);
610 if (s
->num_clips
> 0)
611 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
613 XftDrawSetClip (xft_draw
, NULL
);
617 int height
= FONT_HEIGHT (s
->font
), ascent
= FONT_BASE (s
->font
);
619 /* Font's global height and ascent values might be
620 preposterously large for some fonts. We fix here the case
621 when those fonts are used for display of glyphless
622 characters, because drawing background with font dimensions
623 in those cases makes the display illegible. There's only one
624 more call to the draw method with with_background set to
625 true, and that's in x_draw_glyph_string_foreground, when
626 drawing the cursor, where we have no such heuristics
628 if (s
->first_glyph
->type
== GLYPHLESS_GLYPH
629 && (s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
630 || s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
))
632 s
->first_glyph
->slice
.glyphless
.lower_yoff
633 - s
->first_glyph
->slice
.glyphless
.upper_yoff
;
634 XftDrawRect (xft_draw
, &bg
, x
, y
- ascent
, s
->width
, height
);
636 code
= alloca (sizeof (FT_UInt
) * len
);
637 for (i
= 0; i
< len
; i
++)
638 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
639 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
642 for (i
= 0; i
< len
; i
++)
643 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
644 x
+ i
, y
, code
+ i
, 1);
646 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
653 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
655 xftfont_shape (Lisp_Object lgstring
)
657 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
658 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
662 ft_face
= XftLockFace (xftfont_info
->xftfont
);
663 xftfont_info
->ft_size
= ft_face
->size
;
664 val
= ftfont_driver
.shape (lgstring
);
665 XftUnlockFace (xftfont_info
->xftfont
);
671 xftfont_end_for_frame (struct frame
*f
)
675 /* Don't do anything if display is dead */
676 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
678 xft_draw
= font_get_frame_data (f
, Qxft
);
683 XftDrawDestroy (xft_draw
);
685 font_put_frame_data (f
, Qxft
, NULL
);
691 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
694 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
695 FcPattern
*oldpat
= info
->xftfont
->pattern
;
696 Display
*display
= FRAME_X_DISPLAY (f
);
697 FcPattern
*pat
= FcPatternCreate ();
702 xftfont_add_rendering_parameters (pat
, entity
);
703 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
705 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
706 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
707 if (r1
!= r2
|| b1
!= b2
) goto out
;
708 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
709 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
710 if (r1
!= r2
|| b1
!= b2
) goto out
;
711 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
712 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
713 if (r1
!= r2
|| b1
!= b2
) goto out
;
715 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
716 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
717 if (r1
!= r2
|| b1
!= b2
) goto out
;
719 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
720 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
721 if (r1
!= r2
|| i1
!= i2
) goto out
;
722 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
723 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
724 if (r1
!= r2
|| i1
!= i2
) goto out
;
725 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
726 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
727 if (r1
!= r2
|| i1
!= i2
) goto out
;
731 FcPatternDestroy (pat
);
736 syms_of_xftfont (void)
738 DEFSYM (Qxft
, "xft");
739 DEFSYM (QChinting
, ":hinting");
740 DEFSYM (QCautohint
, ":autohint");
741 DEFSYM (QChintstyle
, ":hintstyle");
742 DEFSYM (QCrgba
, ":rgba");
743 DEFSYM (QCembolden
, ":embolden");
744 DEFSYM (QClcdfilter
, ":lcdfilter");
746 ascii_printable
[0] = 0;
748 xftfont_driver
= ftfont_driver
;
749 xftfont_driver
.type
= Qxft
;
750 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
751 xftfont_driver
.list
= xftfont_list
;
752 xftfont_driver
.match
= xftfont_match
;
753 xftfont_driver
.open
= xftfont_open
;
754 xftfont_driver
.close
= xftfont_close
;
755 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
756 xftfont_driver
.done_face
= xftfont_done_face
;
757 xftfont_driver
.has_char
= xftfont_has_char
;
758 xftfont_driver
.encode_char
= xftfont_encode_char
;
759 xftfont_driver
.text_extents
= xftfont_text_extents
;
760 xftfont_driver
.draw
= xftfont_draw
;
761 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
762 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
763 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
764 xftfont_driver
.shape
= xftfont_shape
;
767 register_font_driver (&xftfont_driver
, NULL
);