1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2012 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/>. */
26 #include <X11/Xft/Xft.h>
29 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
35 #include "composite.h"
40 /* Xft font driver. */
43 static Lisp_Object QChinting
, QCautohint
, QChintstyle
, QCrgba
, QCembolden
,
46 /* The actual structure for Xft font that can be casted to struct
52 /* The following five members must be here in this order to be
53 compatible with struct ftfont_info (in ftfont.c). */
55 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
57 #endif /* HAVE_LIBOTF */
66 /* Structure pointed by (struct face *)->extra */
70 XftColor xft_fg
; /* color for face->foreground */
71 XftColor xft_bg
; /* color for face->background */
74 static void xftfont_get_colors (FRAME_PTR
, struct face
*, GC gc
,
75 struct xftface_info
*,
76 XftColor
*fg
, XftColor
*bg
);
79 /* Setup foreground and background colors of GC into FG and BG. If
80 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
84 xftfont_get_colors (FRAME_PTR f
, struct face
*face
, GC gc
, struct xftface_info
*xftface_info
, XftColor
*fg
, XftColor
*bg
)
86 if (xftface_info
&& face
->gc
== gc
)
88 *fg
= xftface_info
->xft_fg
;
90 *bg
= xftface_info
->xft_bg
;
95 bool fg_done
= 0, bg_done
= 0;
98 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
99 GCForeground
| GCBackground
, &xgcv
);
102 if (xgcv
.foreground
== face
->foreground
)
103 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
104 else if (xgcv
.foreground
== face
->background
)
105 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
108 else if (xgcv
.background
== face
->background
)
109 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
110 else if (xgcv
.background
== face
->foreground
)
111 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
114 if (! (fg_done
& bg_done
))
118 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
120 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
121 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
123 fg
->color
.alpha
= 0xFFFF;
124 fg
->color
.red
= colors
[0].red
;
125 fg
->color
.green
= colors
[0].green
;
126 fg
->color
.blue
= colors
[0].blue
;
129 bg
->color
.alpha
= 0xFFFF;
130 bg
->color
.red
= colors
[1].red
;
131 bg
->color
.green
= colors
[1].green
;
132 bg
->color
.blue
= colors
[1].blue
;
140 struct font_driver xftfont_driver
;
143 xftfont_list (Lisp_Object frame
, Lisp_Object spec
)
145 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
147 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
148 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
153 xftfont_match (Lisp_Object frame
, Lisp_Object spec
)
155 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
158 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
162 static FcChar8 ascii_printable
[95];
165 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
167 /* These values are not used for matching (except antialias), but for
168 rendering, so make sure they are carried over to the match.
169 We also put antialias here because most fonts are antialiased, so
170 the match will have antialias true. */
176 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
179 FcPatternDel (match
, FC_ANTIALIAS
);
180 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
182 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
185 FcPatternDel (match
, FC_HINTING
);
186 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
188 #ifndef FC_HINT_STYLE
189 # define FC_HINT_STYLE "hintstyle"
191 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
193 FcPatternDel (match
, FC_HINT_STYLE
);
194 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
196 #ifndef FC_LCD_FILTER
197 /* Older fontconfig versions don't have FC_LCD_FILTER. */
198 #define FC_LCD_FILTER "lcdfilter"
200 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
202 FcPatternDel (match
, FC_LCD_FILTER
);
203 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
205 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
207 FcPatternDel (match
, FC_RGBA
);
208 FcPatternAddInteger (match
, FC_RGBA
, i
);
210 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
212 FcPatternDel (match
, FC_DPI
);
213 FcPatternAddDouble (match
, FC_DPI
, dpi
);
218 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
223 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
225 Lisp_Object key
= XCAR (XCAR (tail
));
226 Lisp_Object val
= XCDR (XCAR (tail
));
228 if (EQ (key
, QCantialias
))
229 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
230 else if (EQ (key
, QChinting
))
231 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
232 else if (EQ (key
, QCautohint
))
233 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
234 else if (EQ (key
, QChintstyle
))
237 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
238 else if (SYMBOLP (val
)
239 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
240 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
242 else if (EQ (key
, QCrgba
))
245 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
246 else if (SYMBOLP (val
)
247 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
248 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
250 else if (EQ (key
, QClcdfilter
))
253 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
254 else if (SYMBOLP (val
)
255 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
256 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
259 else if (EQ (key
, QCembolden
))
260 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
266 xftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
269 Display
*display
= FRAME_X_DISPLAY (f
);
270 Lisp_Object val
, filename
, idx
, font_object
;
271 FcPattern
*pat
= NULL
, *match
;
272 struct xftfont_info
*xftfont_info
= NULL
;
275 XftFont
*xftfont
= NULL
;
283 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
287 filename
= XCAR (val
);
289 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
292 pat
= FcPatternCreate ();
293 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
294 i
= FONT_SLANT_NUMERIC (entity
) - 100;
296 FcPatternAddInteger (pat
, FC_SLANT
, i
);
297 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
298 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
299 val
= AREF (entity
, FONT_FAMILY_INDEX
);
301 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
302 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
304 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
305 val
= AREF (entity
, FONT_SPACING_INDEX
);
307 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
308 val
= AREF (entity
, FONT_DPI_INDEX
);
311 double dbl
= XINT (val
);
313 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
315 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
316 if (INTEGERP (val
) && XINT (val
) == 0)
317 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
318 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
319 over 10x20-ISO8859-1.pcf.gz). */
320 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
322 xftfont_add_rendering_parameters (pat
, entity
);
324 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
325 FcPatternAddInteger (pat
, FC_INDEX
, XINT (idx
));
329 /* Make sure that the Xrender extension is added before the Xft one.
330 Otherwise, the close-display hook set by Xft is called after the
331 one for Xrender, and the former tries to re-add the latter. This
332 results in inconsistency of internal states and leads to X
333 protocol error when one reconnects to the same X server.
336 int event_base
, error_base
;
337 XRenderQueryExtension (display
, &event_base
, &error_base
);
340 /* Substitute in values from X resources and XftDefaultSet. */
341 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
342 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
343 xftfont_fix_match (pat
, match
);
345 FcPatternDestroy (pat
);
346 xftfont
= XftFontOpenPattern (display
, match
);
350 XftPatternDestroy (match
);
353 ft_face
= XftLockFace (xftfont
);
356 /* We should not destroy PAT here because it is kept in XFTFONT and
357 destroyed automatically when XFTFONT is closed. */
358 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
359 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
360 len
= font_unparse_xlfd (entity
, size
, name
, 256);
362 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
363 len
= font_unparse_fcname (entity
, size
, name
, 256);
365 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
367 ASET (font_object
, FONT_FULLNAME_INDEX
,
368 AREF (font_object
, FONT_NAME_INDEX
));
369 ASET (font_object
, FONT_FILE_INDEX
, filename
);
370 ASET (font_object
, FONT_FORMAT_INDEX
,
371 ftfont_font_format (xftfont
->pattern
, filename
));
372 font
= XFONT_OBJECT (font_object
);
373 font
->pixel_size
= pixel_size
;
374 font
->driver
= &xftfont_driver
;
375 font
->encoding_charset
= font
->repertory_charset
= -1;
377 xftfont_info
= (struct xftfont_info
*) font
;
378 xftfont_info
->display
= display
;
379 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
380 xftfont_info
->xftfont
= xftfont
;
381 /* This means that there's no need of transformation. */
382 xftfont_info
->matrix
.xx
= 0;
383 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
386 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
387 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
388 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
389 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
391 font
->pixel_size
= size
;
392 font
->driver
= &xftfont_driver
;
393 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
394 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
396 spacing
= FC_PROPORTIONAL
;
397 if (! ascii_printable
[0])
400 for (ch
= 0; ch
< 95; ch
++)
401 ascii_printable
[ch
] = ' ' + ch
;
405 /* Unfortunately Xft doesn't provide a way to get minimum char
406 width. So, we set min_width to space_width. */
408 if (spacing
!= FC_PROPORTIONAL
410 && spacing
!= FC_DUAL
414 font
->min_width
= font
->max_width
= font
->average_width
415 = font
->space_width
= xftfont
->max_advance_width
;
416 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
420 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
421 font
->min_width
= font
->max_width
= font
->space_width
423 if (font
->space_width
<= 0)
424 /* dirty workaround */
425 font
->space_width
= pixel_size
;
426 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
427 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
431 font
->ascent
= xftfont
->ascent
;
432 font
->descent
= xftfont
->descent
;
435 /* The above condition is a dirty workaround because
436 XftTextExtents8 behaves strangely for some fonts
437 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
438 if (font
->ascent
< extents
.y
)
439 font
->ascent
= extents
.y
;
440 if (font
->descent
< extents
.height
- extents
.y
)
441 font
->descent
= extents
.height
- extents
.y
;
443 font
->height
= font
->ascent
+ font
->descent
;
445 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
447 int upEM
= ft_face
->units_per_EM
;
449 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
450 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
451 if (font
->underline_thickness
> 2)
452 font
->underline_position
-= font
->underline_thickness
/ 2;
456 font
->underline_position
= -1;
457 font
->underline_thickness
= 0;
460 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
461 xftfont_info
->otf
= NULL
;
462 #endif /* HAVE_LIBOTF */
463 xftfont_info
->ft_size
= ft_face
->size
;
465 font
->baseline_offset
= 0;
466 font
->relative_compose
= 0;
467 font
->default_ascent
= 0;
468 font
->vertical_centering
= 0;
470 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
474 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
475 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
476 font
->baseline_offset
= rec
.u
.integer
;
477 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
478 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
479 font
->relative_compose
= rec
.u
.integer
;
480 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
481 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
482 font
->default_ascent
= rec
.u
.integer
;
490 xftfont_close (FRAME_PTR f
, struct font
*font
)
492 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
495 if (xftfont_info
->otf
)
496 OTF_close (xftfont_info
->otf
);
499 XftUnlockFace (xftfont_info
->xftfont
);
500 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
505 xftfont_prepare_face (FRAME_PTR 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 (FRAME_PTR 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 (FRAME_PTR 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
)
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 (FRAME_PTR 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
);