1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2013 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 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 bool 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 bool 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
))
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 struct font_driver xftfont_driver
;
142 xftfont_list (Lisp_Object frame
, Lisp_Object spec
)
144 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
146 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
147 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
152 xftfont_match (Lisp_Object frame
, Lisp_Object spec
)
154 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
157 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
161 static FcChar8 ascii_printable
[95];
164 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
166 /* These values are not used for matching (except antialias), but for
167 rendering, so make sure they are carried over to the match.
168 We also put antialias here because most fonts are antialiased, so
169 the match will have antialias true. */
175 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
178 FcPatternDel (match
, FC_ANTIALIAS
);
179 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
181 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
184 FcPatternDel (match
, FC_HINTING
);
185 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
187 #ifndef FC_HINT_STYLE
188 # define FC_HINT_STYLE "hintstyle"
190 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
192 FcPatternDel (match
, FC_HINT_STYLE
);
193 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
195 #ifndef FC_LCD_FILTER
196 /* Older fontconfig versions don't have FC_LCD_FILTER. */
197 #define FC_LCD_FILTER "lcdfilter"
199 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
201 FcPatternDel (match
, FC_LCD_FILTER
);
202 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
204 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
206 FcPatternDel (match
, FC_RGBA
);
207 FcPatternAddInteger (match
, FC_RGBA
, i
);
209 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
211 FcPatternDel (match
, FC_DPI
);
212 FcPatternAddDouble (match
, FC_DPI
, dpi
);
217 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
222 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
224 Lisp_Object key
= XCAR (XCAR (tail
));
225 Lisp_Object val
= XCDR (XCAR (tail
));
227 if (EQ (key
, QCantialias
))
228 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
229 else if (EQ (key
, QChinting
))
230 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
231 else if (EQ (key
, QCautohint
))
232 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
233 else if (EQ (key
, QChintstyle
))
236 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
237 else if (SYMBOLP (val
)
238 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
239 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
241 else if (EQ (key
, QCrgba
))
244 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
245 else if (SYMBOLP (val
)
246 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
247 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
249 else if (EQ (key
, QClcdfilter
))
252 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
253 else if (SYMBOLP (val
)
254 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
255 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
258 else if (EQ (key
, QCembolden
))
259 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
265 xftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
268 Display
*display
= FRAME_X_DISPLAY (f
);
269 Lisp_Object val
, filename
, idx
, font_object
;
270 FcPattern
*pat
= NULL
, *match
;
271 struct xftfont_info
*xftfont_info
= NULL
;
274 XftFont
*xftfont
= NULL
;
282 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
286 filename
= XCAR (val
);
288 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
291 pat
= FcPatternCreate ();
292 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
293 i
= FONT_SLANT_NUMERIC (entity
) - 100;
295 FcPatternAddInteger (pat
, FC_SLANT
, i
);
296 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
297 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
298 val
= AREF (entity
, FONT_FAMILY_INDEX
);
300 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
301 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
303 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
304 val
= AREF (entity
, FONT_SPACING_INDEX
);
306 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
307 val
= AREF (entity
, FONT_DPI_INDEX
);
310 double dbl
= XINT (val
);
312 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
314 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
315 if (INTEGERP (val
) && XINT (val
) == 0)
316 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
317 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
318 over 10x20-ISO8859-1.pcf.gz). */
319 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
321 xftfont_add_rendering_parameters (pat
, entity
);
323 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
324 FcPatternAddInteger (pat
, FC_INDEX
, XINT (idx
));
328 /* Make sure that the Xrender extension is added before the Xft one.
329 Otherwise, the close-display hook set by Xft is called after the
330 one for Xrender, and the former tries to re-add the latter. This
331 results in inconsistency of internal states and leads to X
332 protocol error when one reconnects to the same X server.
335 int event_base
, error_base
;
336 XRenderQueryExtension (display
, &event_base
, &error_base
);
339 /* Substitute in values from X resources and XftDefaultSet. */
340 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
341 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
342 xftfont_fix_match (pat
, match
);
344 FcPatternDestroy (pat
);
345 xftfont
= XftFontOpenPattern (display
, match
);
349 XftPatternDestroy (match
);
352 ft_face
= XftLockFace (xftfont
);
355 /* We should not destroy PAT here because it is kept in XFTFONT and
356 destroyed automatically when XFTFONT is closed. */
357 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
358 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
359 len
= font_unparse_xlfd (entity
, size
, name
, 256);
361 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
362 len
= font_unparse_fcname (entity
, size
, name
, 256);
364 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
366 ASET (font_object
, FONT_FULLNAME_INDEX
,
367 AREF (font_object
, FONT_NAME_INDEX
));
368 ASET (font_object
, FONT_FILE_INDEX
, filename
);
369 ASET (font_object
, FONT_FORMAT_INDEX
,
370 ftfont_font_format (xftfont
->pattern
, filename
));
371 font
= XFONT_OBJECT (font_object
);
372 font
->pixel_size
= size
;
373 font
->driver
= &xftfont_driver
;
374 font
->encoding_charset
= font
->repertory_charset
= -1;
376 xftfont_info
= (struct xftfont_info
*) font
;
377 xftfont_info
->display
= display
;
378 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
379 xftfont_info
->xftfont
= xftfont
;
380 /* This means that there's no need of transformation. */
381 xftfont_info
->matrix
.xx
= 0;
382 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
385 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
386 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
387 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
388 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
390 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
391 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
393 spacing
= FC_PROPORTIONAL
;
394 if (! ascii_printable
[0])
397 for (ch
= 0; ch
< 95; ch
++)
398 ascii_printable
[ch
] = ' ' + ch
;
402 /* Unfortunately Xft doesn't provide a way to get minimum char
403 width. So, we set min_width to space_width. */
405 if (spacing
!= FC_PROPORTIONAL
407 && spacing
!= FC_DUAL
411 font
->min_width
= font
->max_width
= font
->average_width
412 = font
->space_width
= xftfont
->max_advance_width
;
413 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
417 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
418 font
->min_width
= font
->max_width
= font
->space_width
420 if (font
->space_width
<= 0)
421 /* dirty workaround */
422 font
->space_width
= pixel_size
;
423 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
424 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
428 font
->ascent
= xftfont
->ascent
;
429 font
->descent
= xftfont
->descent
;
432 /* The above condition is a dirty workaround because
433 XftTextExtents8 behaves strangely for some fonts
434 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
435 if (font
->ascent
< extents
.y
)
436 font
->ascent
= extents
.y
;
437 if (font
->descent
< extents
.height
- extents
.y
)
438 font
->descent
= extents
.height
- extents
.y
;
440 font
->height
= font
->ascent
+ font
->descent
;
442 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
444 int upEM
= ft_face
->units_per_EM
;
446 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
447 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
448 if (font
->underline_thickness
> 2)
449 font
->underline_position
-= font
->underline_thickness
/ 2;
453 font
->underline_position
= -1;
454 font
->underline_thickness
= 0;
457 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
458 xftfont_info
->otf
= NULL
;
459 #endif /* HAVE_LIBOTF */
460 xftfont_info
->ft_size
= ft_face
->size
;
462 font
->baseline_offset
= 0;
463 font
->relative_compose
= 0;
464 font
->default_ascent
= 0;
465 font
->vertical_centering
= 0;
467 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
471 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
472 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
473 font
->baseline_offset
= rec
.u
.integer
;
474 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
475 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
476 font
->relative_compose
= rec
.u
.integer
;
477 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
478 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
479 font
->default_ascent
= rec
.u
.integer
;
487 xftfont_close (FRAME_PTR f
, struct font
*font
)
489 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
492 if (xftfont_info
->otf
)
493 OTF_close (xftfont_info
->otf
);
496 XftUnlockFace (xftfont_info
->xftfont
);
497 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
502 xftfont_prepare_face (FRAME_PTR 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
)
510 face
->extra
= face
->ascii_face
->extra
;
515 xftface_info
= malloc (sizeof *xftface_info
);
518 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
519 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
520 face
->extra
= xftface_info
;
525 xftfont_done_face (FRAME_PTR f
, struct face
*face
)
527 struct xftface_info
*xftface_info
;
530 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
531 if (face
!= face
->ascii_face
536 xftface_info
= (struct xftface_info
*) face
->extra
;
545 xftfont_has_char (Lisp_Object font
, int c
)
547 struct xftfont_info
*xftfont_info
;
548 struct charset
*cs
= NULL
;
550 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
551 && charset_jisx0208
>= 0)
552 cs
= CHARSET_FROM_ID (charset_jisx0208
);
553 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
554 && charset_ksc5601
>= 0)
555 cs
= CHARSET_FROM_ID (charset_ksc5601
);
557 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
559 if (FONT_ENTITY_P (font
))
560 return ftfont_driver
.has_char (font
, c
);
561 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
562 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
563 (FcChar32
) c
) == FcTrue
);
567 xftfont_encode_char (struct font
*font
, int c
)
569 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
570 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
573 return (code
? code
: FONT_INVALID_CODE
);
577 xftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
579 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
583 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
588 metrics
->lbearing
= - extents
.x
;
589 metrics
->rbearing
= - extents
.x
+ extents
.width
;
590 metrics
->width
= extents
.xOff
;
591 metrics
->ascent
= extents
.y
;
592 metrics
->descent
= extents
.height
- extents
.y
;
598 xftfont_get_xft_draw (FRAME_PTR f
)
600 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
605 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
608 FRAME_X_COLORMAP (f
));
610 eassert (xft_draw
!= NULL
);
611 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
617 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
618 bool with_background
)
621 struct face
*face
= s
->face
;
622 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
623 struct xftface_info
*xftface_info
= NULL
;
624 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
630 if (s
->font
== face
->font
)
631 xftface_info
= (struct xftface_info
*) face
->extra
;
632 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
633 &fg
, with_background
? &bg
: NULL
);
635 if (s
->num_clips
> 0)
636 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
638 XftDrawSetClip (xft_draw
, NULL
);
641 XftDrawRect (xft_draw
, &bg
,
642 x
, y
- s
->font
->ascent
, s
->width
, s
->font
->height
);
643 code
= alloca (sizeof (FT_UInt
) * len
);
644 for (i
= 0; i
< len
; i
++)
645 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
646 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
649 for (i
= 0; i
< len
; i
++)
650 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
651 x
+ i
, y
, code
+ i
, 1);
653 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
660 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
662 xftfont_shape (Lisp_Object lgstring
)
665 struct xftfont_info
*xftfont_info
;
669 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
670 xftfont_info
= (struct xftfont_info
*) font
;
671 ft_face
= XftLockFace (xftfont_info
->xftfont
);
672 xftfont_info
->ft_size
= ft_face
->size
;
673 val
= ftfont_driver
.shape (lgstring
);
674 XftUnlockFace (xftfont_info
->xftfont
);
680 xftfont_end_for_frame (FRAME_PTR f
)
684 /* Don't do anything if display is dead */
685 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
687 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
692 XftDrawDestroy (xft_draw
);
694 font_put_frame_data (f
, &xftfont_driver
, NULL
);
700 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
703 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
704 FcPattern
*oldpat
= info
->xftfont
->pattern
;
705 Display
*display
= FRAME_X_DISPLAY (f
);
706 FcPattern
*pat
= FcPatternCreate ();
711 xftfont_add_rendering_parameters (pat
, entity
);
712 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
714 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
715 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
716 if (r1
!= r2
|| b1
!= b2
) goto out
;
717 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
718 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
719 if (r1
!= r2
|| b1
!= b2
) goto out
;
720 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
721 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
722 if (r1
!= r2
|| b1
!= b2
) goto out
;
724 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
725 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
726 if (r1
!= r2
|| b1
!= b2
) goto out
;
728 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
729 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
730 if (r1
!= r2
|| i1
!= i2
) goto out
;
731 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
732 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
733 if (r1
!= r2
|| i1
!= i2
) goto out
;
734 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
735 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
736 if (r1
!= r2
|| i1
!= i2
) goto out
;
740 FcPatternDestroy (pat
);
745 syms_of_xftfont (void)
747 DEFSYM (Qxft
, "xft");
748 DEFSYM (QChinting
, ":hinting");
749 DEFSYM (QCautohint
, ":autohint");
750 DEFSYM (QChintstyle
, ":hintstyle");
751 DEFSYM (QCrgba
, ":rgba");
752 DEFSYM (QCembolden
, ":embolden");
753 DEFSYM (QClcdfilter
, ":lcdfilter");
755 ascii_printable
[0] = 0;
757 xftfont_driver
= ftfont_driver
;
758 xftfont_driver
.type
= Qxft
;
759 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
760 xftfont_driver
.list
= xftfont_list
;
761 xftfont_driver
.match
= xftfont_match
;
762 xftfont_driver
.open
= xftfont_open
;
763 xftfont_driver
.close
= xftfont_close
;
764 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
765 xftfont_driver
.done_face
= xftfont_done_face
;
766 xftfont_driver
.has_char
= xftfont_has_char
;
767 xftfont_driver
.encode_char
= xftfont_encode_char
;
768 xftfont_driver
.text_extents
= xftfont_text_extents
;
769 xftfont_driver
.draw
= xftfont_draw
;
770 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
771 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
772 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
773 xftfont_driver
.shape
= xftfont_shape
;
776 register_font_driver (&xftfont_driver
, NULL
);