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
;
279 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
283 filename
= XCAR (val
);
285 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
288 pat
= FcPatternCreate ();
289 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
290 i
= FONT_SLANT_NUMERIC (entity
) - 100;
292 FcPatternAddInteger (pat
, FC_SLANT
, i
);
293 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
294 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
295 val
= AREF (entity
, FONT_FAMILY_INDEX
);
297 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
298 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
300 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
301 val
= AREF (entity
, FONT_SPACING_INDEX
);
303 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
304 val
= AREF (entity
, FONT_DPI_INDEX
);
307 double dbl
= XINT (val
);
309 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
311 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
312 if (INTEGERP (val
) && XINT (val
) == 0)
313 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
314 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
315 over 10x20-ISO8859-1.pcf.gz). */
316 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
318 xftfont_add_rendering_parameters (pat
, entity
);
320 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
321 FcPatternAddInteger (pat
, FC_INDEX
, XINT (idx
));
325 /* Make sure that the Xrender extension is added before the Xft one.
326 Otherwise, the close-display hook set by Xft is called after the
327 one for Xrender, and the former tries to re-add the latter. This
328 results in inconsistency of internal states and leads to X
329 protocol error when one reconnects to the same X server.
332 int event_base
, error_base
;
333 XRenderQueryExtension (display
, &event_base
, &error_base
);
336 /* Substitute in values from X resources and XftDefaultSet. */
337 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
338 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
339 xftfont_fix_match (pat
, match
);
341 FcPatternDestroy (pat
);
342 xftfont
= XftFontOpenPattern (display
, match
);
346 XftPatternDestroy (match
);
349 ft_face
= XftLockFace (xftfont
);
352 /* We should not destroy PAT here because it is kept in XFTFONT and
353 destroyed automatically when XFTFONT is closed. */
354 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
355 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
356 len
= font_unparse_xlfd (entity
, size
, name
, 256);
358 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
359 len
= font_unparse_fcname (entity
, size
, name
, 256);
361 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
363 ASET (font_object
, FONT_FULLNAME_INDEX
,
364 AREF (font_object
, FONT_NAME_INDEX
));
365 ASET (font_object
, FONT_FILE_INDEX
, filename
);
366 ASET (font_object
, FONT_FORMAT_INDEX
,
367 ftfont_font_format (xftfont
->pattern
, filename
));
368 font
= XFONT_OBJECT (font_object
);
369 font
->pixel_size
= size
;
370 font
->driver
= &xftfont_driver
;
371 font
->encoding_charset
= font
->repertory_charset
= -1;
373 xftfont_info
= (struct xftfont_info
*) font
;
374 xftfont_info
->display
= display
;
375 xftfont_info
->xftfont
= xftfont
;
376 xftfont_info
->x_display_id
= FRAME_DISPLAY_INFO (f
)->x_id
;
377 /* This means that there's no need of transformation. */
378 xftfont_info
->matrix
.xx
= 0;
379 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
382 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
383 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
384 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
385 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
387 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
388 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
390 spacing
= FC_PROPORTIONAL
;
391 if (! ascii_printable
[0])
394 for (ch
= 0; ch
< 95; ch
++)
395 ascii_printable
[ch
] = ' ' + ch
;
399 /* Unfortunately Xft doesn't provide a way to get minimum char
400 width. So, we set min_width to space_width. */
402 if (spacing
!= FC_PROPORTIONAL
404 && spacing
!= FC_DUAL
408 font
->min_width
= font
->max_width
= font
->average_width
409 = font
->space_width
= xftfont
->max_advance_width
;
410 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
414 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
415 font
->min_width
= font
->max_width
= font
->space_width
417 if (font
->space_width
<= 0)
418 /* dirty workaround */
419 font
->space_width
= pixel_size
;
420 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
421 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
425 font
->ascent
= xftfont
->ascent
;
426 font
->descent
= xftfont
->descent
;
429 /* The above condition is a dirty workaround because
430 XftTextExtents8 behaves strangely for some fonts
431 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
432 if (font
->ascent
< extents
.y
)
433 font
->ascent
= extents
.y
;
434 if (font
->descent
< extents
.height
- extents
.y
)
435 font
->descent
= extents
.height
- extents
.y
;
437 font
->height
= font
->ascent
+ font
->descent
;
439 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
441 int upEM
= ft_face
->units_per_EM
;
443 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
444 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
445 if (font
->underline_thickness
> 2)
446 font
->underline_position
-= font
->underline_thickness
/ 2;
450 font
->underline_position
= -1;
451 font
->underline_thickness
= 0;
454 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
455 xftfont_info
->otf
= NULL
;
456 #endif /* HAVE_LIBOTF */
457 xftfont_info
->ft_size
= ft_face
->size
;
459 font
->baseline_offset
= 0;
460 font
->relative_compose
= 0;
461 font
->default_ascent
= 0;
462 font
->vertical_centering
= 0;
464 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
468 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
469 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
470 font
->baseline_offset
= rec
.u
.integer
;
471 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
472 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
473 font
->relative_compose
= rec
.u
.integer
;
474 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
475 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
476 font
->default_ascent
= rec
.u
.integer
;
484 xftfont_close (struct font
*font
)
486 struct x_display_info
*xdi
;
487 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
490 if (xftfont_info
->otf
)
492 OTF_close (xftfont_info
->otf
);
493 xftfont_info
->otf
= NULL
;
497 /* See comment in xfont_close. */
498 if (xftfont_info
->xftfont
499 && ((xdi
= x_display_info_for_display (xftfont_info
->display
))
500 && xftfont_info
->x_display_id
== xdi
->x_id
))
503 XftUnlockFace (xftfont_info
->xftfont
);
504 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
506 xftfont_info
->xftfont
= NULL
;
511 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
513 struct xftface_info
*xftface_info
;
516 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
517 if (face
!= face
->ascii_face
)
519 face
->extra
= face
->ascii_face
->extra
;
524 xftface_info
= xmalloc (sizeof *xftface_info
);
525 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
526 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
527 face
->extra
= xftface_info
;
531 xftfont_done_face (struct frame
*f
, struct face
*face
)
533 struct xftface_info
*xftface_info
;
536 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
537 if (face
!= face
->ascii_face
542 xftface_info
= (struct xftface_info
*) face
->extra
;
545 xfree (xftface_info
);
551 xftfont_has_char (Lisp_Object font
, int c
)
553 struct xftfont_info
*xftfont_info
;
554 struct charset
*cs
= NULL
;
556 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
557 && charset_jisx0208
>= 0)
558 cs
= CHARSET_FROM_ID (charset_jisx0208
);
559 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
560 && charset_ksc5601
>= 0)
561 cs
= CHARSET_FROM_ID (charset_ksc5601
);
563 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
565 if (FONT_ENTITY_P (font
))
566 return ftfont_driver
.has_char (font
, c
);
567 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
568 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
569 (FcChar32
) c
) == FcTrue
);
573 xftfont_encode_char (struct font
*font
, int c
)
575 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
576 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
579 return (code
? code
: FONT_INVALID_CODE
);
583 xftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
585 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
589 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
594 metrics
->lbearing
= - extents
.x
;
595 metrics
->rbearing
= - extents
.x
+ extents
.width
;
596 metrics
->width
= extents
.xOff
;
597 metrics
->ascent
= extents
.y
;
598 metrics
->descent
= extents
.height
- extents
.y
;
604 xftfont_get_xft_draw (struct frame
*f
)
606 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
611 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
614 FRAME_X_COLORMAP (f
));
616 eassert (xft_draw
!= NULL
);
617 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
623 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
624 bool with_background
)
626 struct frame
*f
= s
->f
;
627 struct face
*face
= s
->face
;
628 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
629 struct xftface_info
*xftface_info
= NULL
;
630 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
636 if (s
->font
== face
->font
)
637 xftface_info
= (struct xftface_info
*) face
->extra
;
638 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
639 &fg
, with_background
? &bg
: NULL
);
641 if (s
->num_clips
> 0)
642 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
644 XftDrawSetClip (xft_draw
, NULL
);
647 XftDrawRect (xft_draw
, &bg
,
648 x
, y
- s
->font
->ascent
, s
->width
, s
->font
->height
);
649 code
= alloca (sizeof (FT_UInt
) * len
);
650 for (i
= 0; i
< len
; i
++)
651 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
652 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
655 for (i
= 0; i
< len
; i
++)
656 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
657 x
+ i
, y
, code
+ i
, 1);
659 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
666 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
668 xftfont_shape (Lisp_Object lgstring
)
671 struct xftfont_info
*xftfont_info
;
675 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
676 xftfont_info
= (struct xftfont_info
*) font
;
677 ft_face
= XftLockFace (xftfont_info
->xftfont
);
678 xftfont_info
->ft_size
= ft_face
->size
;
679 val
= ftfont_driver
.shape (lgstring
);
680 XftUnlockFace (xftfont_info
->xftfont
);
686 xftfont_end_for_frame (struct frame
*f
)
690 /* Don't do anything if display is dead */
691 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
693 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
698 XftDrawDestroy (xft_draw
);
700 font_put_frame_data (f
, &xftfont_driver
, NULL
);
706 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
709 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
710 FcPattern
*oldpat
= info
->xftfont
->pattern
;
711 Display
*display
= FRAME_X_DISPLAY (f
);
712 FcPattern
*pat
= FcPatternCreate ();
717 xftfont_add_rendering_parameters (pat
, entity
);
718 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
720 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
721 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
722 if (r1
!= r2
|| b1
!= b2
) goto out
;
723 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
724 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
725 if (r1
!= r2
|| b1
!= b2
) goto out
;
726 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
727 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
728 if (r1
!= r2
|| b1
!= b2
) goto out
;
730 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
731 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
732 if (r1
!= r2
|| b1
!= b2
) goto out
;
734 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
735 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
736 if (r1
!= r2
|| i1
!= i2
) goto out
;
737 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
738 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
739 if (r1
!= r2
|| i1
!= i2
) goto out
;
740 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
741 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
742 if (r1
!= r2
|| i1
!= i2
) goto out
;
746 FcPatternDestroy (pat
);
751 syms_of_xftfont (void)
753 DEFSYM (Qxft
, "xft");
754 DEFSYM (QChinting
, ":hinting");
755 DEFSYM (QCautohint
, ":autohint");
756 DEFSYM (QChintstyle
, ":hintstyle");
757 DEFSYM (QCrgba
, ":rgba");
758 DEFSYM (QCembolden
, ":embolden");
759 DEFSYM (QClcdfilter
, ":lcdfilter");
761 ascii_printable
[0] = 0;
763 xftfont_driver
= ftfont_driver
;
764 xftfont_driver
.type
= Qxft
;
765 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
766 xftfont_driver
.list
= xftfont_list
;
767 xftfont_driver
.match
= xftfont_match
;
768 xftfont_driver
.open
= xftfont_open
;
769 xftfont_driver
.close
= xftfont_close
;
770 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
771 xftfont_driver
.done_face
= xftfont_done_face
;
772 xftfont_driver
.has_char
= xftfont_has_char
;
773 xftfont_driver
.encode_char
= xftfont_encode_char
;
774 xftfont_driver
.text_extents
= xftfont_text_extents
;
775 xftfont_driver
.draw
= xftfont_draw
;
776 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
777 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
778 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
779 xftfont_driver
.shape
= xftfont_shape
;
782 register_font_driver (&xftfont_driver
, NULL
);