1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
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"
39 /* Xft font driver. */
41 static Lisp_Object Qxft
;
42 static Lisp_Object QChinting
, QCautohint
, QChintstyle
, QCrgba
, QCembolden
,
45 /* The actual structure for Xft font that can be casted 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 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
56 #endif /* HAVE_LIBOTF */
65 /* Structure pointed by (struct face *)->extra */
69 XftColor xft_fg
; /* color for face->foreground */
70 XftColor xft_bg
; /* color for face->background */
73 static void xftfont_get_colors (FRAME_PTR
, struct face
*, GC gc
,
74 struct xftface_info
*,
75 XftColor
*fg
, XftColor
*bg
);
78 /* Setup foreground and background colors of GC into FG and BG. If
79 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
83 xftfont_get_colors (FRAME_PTR f
, struct face
*face
, GC gc
, struct xftface_info
*xftface_info
, XftColor
*fg
, XftColor
*bg
)
85 if (xftface_info
&& face
->gc
== gc
)
87 *fg
= xftface_info
->xft_fg
;
89 *bg
= xftface_info
->xft_bg
;
94 int fg_done
= 0, bg_done
= 0;
97 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
98 GCForeground
| GCBackground
, &xgcv
);
101 if (xgcv
.foreground
== face
->foreground
)
102 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
103 else if (xgcv
.foreground
== face
->background
)
104 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
107 else if (xgcv
.background
== face
->background
)
108 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
109 else if (xgcv
.background
== face
->foreground
)
110 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
113 if (fg_done
+ bg_done
< 2)
117 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
119 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
120 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
122 fg
->color
.alpha
= 0xFFFF;
123 fg
->color
.red
= colors
[0].red
;
124 fg
->color
.green
= colors
[0].green
;
125 fg
->color
.blue
= colors
[0].blue
;
128 bg
->color
.alpha
= 0xFFFF;
129 bg
->color
.red
= colors
[1].red
;
130 bg
->color
.green
= colors
[1].green
;
131 bg
->color
.blue
= colors
[1].blue
;
139 static Lisp_Object
xftfont_list (Lisp_Object
, Lisp_Object
);
140 static Lisp_Object
xftfont_match (Lisp_Object
, Lisp_Object
);
141 static Lisp_Object
xftfont_open (FRAME_PTR
, Lisp_Object
, int);
142 static void xftfont_close (FRAME_PTR
, struct font
*);
143 static int xftfont_prepare_face (FRAME_PTR
, struct face
*);
144 static void xftfont_done_face (FRAME_PTR
, struct face
*);
145 static int xftfont_has_char (Lisp_Object
, int);
146 static unsigned xftfont_encode_char (struct font
*, int);
147 static int xftfont_text_extents (struct font
*, unsigned *, int,
148 struct font_metrics
*);
149 static int xftfont_draw (struct glyph_string
*, int, int, int, int, int);
150 static int xftfont_end_for_frame (FRAME_PTR f
);
152 struct font_driver xftfont_driver
;
155 xftfont_list (Lisp_Object frame
, Lisp_Object spec
)
157 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
159 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
160 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
165 xftfont_match (Lisp_Object frame
, Lisp_Object spec
)
167 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
170 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
174 static FcChar8 ascii_printable
[95];
177 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
179 /* These values are not used for matching (except antialias), but for
180 rendering, so make sure they are carried over to the match.
181 We also put antialias here because most fonts are antialiased, so
182 the match will have antialias true. */
188 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
191 FcPatternDel (match
, FC_ANTIALIAS
);
192 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
194 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
197 FcPatternDel (match
, FC_HINTING
);
198 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
200 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
202 FcPatternDel (match
, FC_HINT_STYLE
);
203 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
205 #ifndef FC_LCD_FILTER
206 /* Older fontconfig versions don't have FC_LCD_FILTER. */
207 #define FC_LCD_FILTER "lcdfilter"
209 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
211 FcPatternDel (match
, FC_LCD_FILTER
);
212 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
214 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
216 FcPatternDel (match
, FC_RGBA
);
217 FcPatternAddInteger (match
, FC_RGBA
, i
);
219 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
221 FcPatternDel (match
, FC_DPI
);
222 FcPatternAddDouble (match
, FC_DPI
, dpi
);
227 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
232 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
234 Lisp_Object key
= XCAR (XCAR (tail
));
235 Lisp_Object val
= XCDR (XCAR (tail
));
237 if (EQ (key
, QCantialias
))
238 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
239 else if (EQ (key
, QChinting
))
240 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
241 else if (EQ (key
, QCautohint
))
242 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
243 else if (EQ (key
, QChintstyle
))
246 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
247 else if (SYMBOLP (val
)
248 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
249 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
251 else if (EQ (key
, QCrgba
))
254 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
255 else if (SYMBOLP (val
)
256 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
257 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
259 else if (EQ (key
, QClcdfilter
))
262 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
263 else if (SYMBOLP (val
)
264 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
265 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
268 else if (EQ (key
, QCembolden
))
269 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
275 xftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
278 Display
*display
= FRAME_X_DISPLAY (f
);
279 Lisp_Object val
, filename
, index
, font_object
;
280 FcPattern
*pat
= NULL
, *match
;
281 struct xftfont_info
*xftfont_info
= NULL
;
284 XftFont
*xftfont
= NULL
;
292 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
296 filename
= XCAR (val
);
298 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
301 pat
= FcPatternCreate ();
302 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
303 i
= FONT_SLANT_NUMERIC (entity
) - 100;
305 FcPatternAddInteger (pat
, FC_SLANT
, i
);
306 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
307 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
308 val
= AREF (entity
, FONT_FAMILY_INDEX
);
310 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
311 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
313 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
314 val
= AREF (entity
, FONT_SPACING_INDEX
);
316 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
317 val
= AREF (entity
, FONT_DPI_INDEX
);
320 double dbl
= XINT (val
);
322 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
324 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
325 if (INTEGERP (val
) && XINT (val
) == 0)
326 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
327 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
328 over 10x20-ISO8859-1.pcf.gz). */
329 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
331 xftfont_add_rendering_parameters (pat
, entity
);
333 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
334 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
338 /* Make sure that the Xrender extension is added before the Xft one.
339 Otherwise, the close-display hook set by Xft is called after the
340 one for Xrender, and the former tries to re-add the latter. This
341 results in inconsistency of internal states and leads to X
342 protocol error when one reconnects to the same X server.
345 int event_base
, error_base
;
346 XRenderQueryExtension (display
, &event_base
, &error_base
);
349 /* Substitute in values from X resources and XftDefaultSet. */
350 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
351 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
352 xftfont_fix_match (pat
, match
);
354 FcPatternDestroy (pat
);
355 xftfont
= XftFontOpenPattern (display
, match
);
359 XftPatternDestroy (match
);
362 ft_face
= XftLockFace (xftfont
);
365 /* We should not destroy PAT here because it is kept in XFTFONT and
366 destroyed automatically when XFTFONT is closed. */
367 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
368 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
369 len
= font_unparse_xlfd (entity
, size
, name
, 256);
371 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
372 len
= font_unparse_fcname (entity
, size
, name
, 256);
374 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
376 ASET (font_object
, FONT_FULLNAME_INDEX
,
377 AREF (font_object
, FONT_NAME_INDEX
));
378 ASET (font_object
, FONT_FILE_INDEX
, filename
);
379 ASET (font_object
, FONT_FORMAT_INDEX
,
380 ftfont_font_format (xftfont
->pattern
, filename
));
381 font
= XFONT_OBJECT (font_object
);
382 font
->pixel_size
= pixel_size
;
383 font
->driver
= &xftfont_driver
;
384 font
->encoding_charset
= font
->repertory_charset
= -1;
386 xftfont_info
= (struct xftfont_info
*) font
;
387 xftfont_info
->display
= display
;
388 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
389 xftfont_info
->xftfont
= xftfont
;
390 /* This means that there's no need of transformation. */
391 xftfont_info
->matrix
.xx
= 0;
392 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
395 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
396 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
397 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
398 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
400 font
->pixel_size
= size
;
401 font
->driver
= &xftfont_driver
;
402 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
403 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
405 spacing
= FC_PROPORTIONAL
;
406 if (! ascii_printable
[0])
409 for (i
= 0; i
< 95; i
++)
410 ascii_printable
[i
] = ' ' + i
;
413 if (spacing
!= FC_PROPORTIONAL
&& spacing
!= FC_DUAL
)
415 font
->min_width
= font
->average_width
= font
->space_width
416 = xftfont
->max_advance_width
;
417 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
421 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
422 font
->space_width
= extents
.xOff
;
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
;
461 xftfont_info
->otf
= NULL
;
462 #endif /* HAVE_LIBOTF */
463 xftfont_info
->ft_size
= ft_face
->size
;
465 /* Unfortunately Xft doesn't provide a way to get minimum char
466 width. So, we use space_width instead. */
467 font
->min_width
= font
->space_width
;
469 font
->baseline_offset
= 0;
470 font
->relative_compose
= 0;
471 font
->default_ascent
= 0;
472 font
->vertical_centering
= 0;
474 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
478 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
479 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
480 font
->baseline_offset
= rec
.u
.integer
;
481 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
482 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
483 font
->relative_compose
= rec
.u
.integer
;
484 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
485 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
486 font
->default_ascent
= rec
.u
.integer
;
494 xftfont_close (FRAME_PTR f
, struct font
*font
)
496 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
499 if (xftfont_info
->otf
)
500 OTF_close (xftfont_info
->otf
);
503 XftUnlockFace (xftfont_info
->xftfont
);
504 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
509 xftfont_prepare_face (FRAME_PTR 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
)
517 face
->extra
= face
->ascii_face
->extra
;
522 xftface_info
= malloc (sizeof (struct 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
;
532 xftfont_done_face (FRAME_PTR f
, struct face
*face
)
534 struct xftface_info
*xftface_info
;
537 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
538 if (face
!= face
->ascii_face
543 xftface_info
= (struct xftface_info
*) face
->extra
;
552 xftfont_has_char (Lisp_Object font
, int c
)
554 struct xftfont_info
*xftfont_info
;
555 struct charset
*cs
= NULL
;
557 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
558 && charset_jisx0208
>= 0)
559 cs
= CHARSET_FROM_ID (charset_jisx0208
);
560 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
561 && charset_ksc5601
>= 0)
562 cs
= CHARSET_FROM_ID (charset_ksc5601
);
564 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
566 if (FONT_ENTITY_P (font
))
567 return ftfont_driver
.has_char (font
, c
);
568 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
569 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
570 (FcChar32
) c
) == FcTrue
);
574 xftfont_encode_char (struct font
*font
, int c
)
576 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
577 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
580 return (code
? code
: FONT_INVALID_CODE
);
584 xftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
586 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
590 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
595 metrics
->lbearing
= - extents
.x
;
596 metrics
->rbearing
= - extents
.x
+ extents
.width
;
597 metrics
->width
= extents
.xOff
;
598 metrics
->ascent
= extents
.y
;
599 metrics
->descent
= extents
.height
- extents
.y
;
605 xftfont_get_xft_draw (FRAME_PTR f
)
607 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
612 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
615 FRAME_X_COLORMAP (f
));
619 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
625 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
, int with_background
)
628 struct face
*face
= s
->face
;
629 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
630 struct xftface_info
*xftface_info
= NULL
;
631 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
637 if (s
->font
== face
->font
)
638 xftface_info
= (struct xftface_info
*) face
->extra
;
639 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
640 &fg
, with_background
? &bg
: NULL
);
642 if (s
->num_clips
> 0)
643 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
645 XftDrawSetClip (xft_draw
, NULL
);
648 XftDrawRect (xft_draw
, &bg
,
649 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
650 code
= alloca (sizeof (FT_UInt
) * len
);
651 for (i
= 0; i
< len
; i
++)
652 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
653 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
656 for (i
= 0; i
< len
; i
++)
657 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
658 x
+ i
, y
, code
+ i
, 1);
660 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
668 xftfont_end_for_frame (FRAME_PTR f
)
672 /* Don't do anything if display is dead */
673 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
675 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
680 XftDrawDestroy (xft_draw
);
682 font_put_frame_data (f
, &xftfont_driver
, NULL
);
688 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
, Lisp_Object entity
)
690 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
691 FcPattern
*oldpat
= info
->xftfont
->pattern
;
692 Display
*display
= FRAME_X_DISPLAY (f
);
693 FcPattern
*pat
= FcPatternCreate ();
695 int ok
= 0, i1
, i2
, r1
, r2
;
697 xftfont_add_rendering_parameters (pat
, entity
);
698 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
700 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
701 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
702 if (r1
!= r2
|| b1
!= b2
) goto out
;
703 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
704 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
705 if (r1
!= r2
|| b1
!= b2
) goto out
;
706 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
707 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
708 if (r1
!= r2
|| b1
!= b2
) goto out
;
710 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
711 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
712 if (r1
!= r2
|| b1
!= b2
) goto out
;
714 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
715 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
716 if (r1
!= r2
|| i1
!= i2
) goto out
;
717 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
718 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
719 if (r1
!= r2
|| i1
!= i2
) goto out
;
720 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
721 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
722 if (r1
!= r2
|| i1
!= i2
) goto out
;
726 FcPatternDestroy (pat
);
731 syms_of_xftfont (void)
733 DEFSYM (Qxft
, "xft");
734 DEFSYM (QChinting
, ":hinting");
735 DEFSYM (QCautohint
, ":autohint");
736 DEFSYM (QChintstyle
, ":hintstyle");
737 DEFSYM (QCrgba
, ":rgba");
738 DEFSYM (QCembolden
, ":embolden");
739 DEFSYM (QClcdfilter
, ":lcdfilter");
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
;
757 register_font_driver (&xftfont_driver
, NULL
);
760 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
761 (do not change this comment) */