1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2016 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 (at
12 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
;
398 font
->height
= font
->ascent
+ font
->descent
;
400 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
402 int upEM
= ft_face
->units_per_EM
;
404 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
405 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
406 if (font
->underline_thickness
> 2)
407 font
->underline_position
-= font
->underline_thickness
/ 2;
411 font
->underline_position
= -1;
412 font
->underline_thickness
= 0;
415 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
416 xftfont_info
->otf
= NULL
;
417 #endif /* HAVE_LIBOTF */
418 xftfont_info
->ft_size
= ft_face
->size
;
420 font
->baseline_offset
= 0;
421 font
->relative_compose
= 0;
422 font
->default_ascent
= 0;
423 font
->vertical_centering
= false;
425 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
429 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
430 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
431 font
->baseline_offset
= rec
.u
.integer
;
432 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
433 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
434 font
->relative_compose
= rec
.u
.integer
;
435 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
436 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
437 font
->default_ascent
= rec
.u
.integer
;
445 xftfont_close (struct font
*font
)
447 struct x_display_info
*xdi
;
448 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
451 if (xftfont_info
->otf
)
453 OTF_close (xftfont_info
->otf
);
454 xftfont_info
->otf
= NULL
;
458 /* See comment in xfont_close. */
459 if (xftfont_info
->xftfont
460 && ((xdi
= x_display_info_for_display (xftfont_info
->display
))
461 && xftfont_info
->x_display_id
== xdi
->x_id
))
464 XftUnlockFace (xftfont_info
->xftfont
);
465 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
467 xftfont_info
->xftfont
= NULL
;
472 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
474 struct xftface_info
*xftface_info
;
477 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
478 if (face
!= face
->ascii_face
)
480 face
->extra
= face
->ascii_face
->extra
;
485 xftface_info
= xmalloc (sizeof *xftface_info
);
486 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
487 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
488 face
->extra
= xftface_info
;
492 xftfont_done_face (struct frame
*f
, struct face
*face
)
494 struct xftface_info
*xftface_info
;
497 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
498 if (face
!= face
->ascii_face
503 xftface_info
= (struct xftface_info
*) face
->extra
;
506 xfree (xftface_info
);
512 xftfont_has_char (Lisp_Object font
, int c
)
514 struct xftfont_info
*xftfont_info
;
515 struct charset
*cs
= NULL
;
517 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
518 && charset_jisx0208
>= 0)
519 cs
= CHARSET_FROM_ID (charset_jisx0208
);
520 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
521 && charset_ksc5601
>= 0)
522 cs
= CHARSET_FROM_ID (charset_ksc5601
);
524 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
526 if (FONT_ENTITY_P (font
))
527 return ftfont_driver
.has_char (font
, c
);
528 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
529 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
530 (FcChar32
) c
) == FcTrue
);
534 xftfont_encode_char (struct font
*font
, int c
)
536 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
537 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
540 return (code
? code
: FONT_INVALID_CODE
);
544 xftfont_text_extents (struct font
*font
, unsigned int *code
,
545 int nglyphs
, struct font_metrics
*metrics
)
547 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
551 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
555 metrics
->lbearing
= - extents
.x
;
556 metrics
->rbearing
= - extents
.x
+ extents
.width
;
557 metrics
->width
= extents
.xOff
;
558 metrics
->ascent
= extents
.y
;
559 metrics
->descent
= extents
.height
- extents
.y
;
563 xftfont_get_xft_draw (struct frame
*f
)
565 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
570 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
573 FRAME_X_COLORMAP (f
));
575 eassert (xft_draw
!= NULL
);
576 font_put_frame_data (f
, Qxft
, xft_draw
);
582 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
583 bool with_background
)
585 struct frame
*f
= s
->f
;
586 struct face
*face
= s
->face
;
587 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
588 struct xftface_info
*xftface_info
= NULL
;
589 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
595 if (s
->font
== face
->font
)
596 xftface_info
= (struct xftface_info
*) face
->extra
;
597 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
598 &fg
, with_background
? &bg
: NULL
);
600 if (s
->num_clips
> 0)
601 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
603 XftDrawSetClip (xft_draw
, NULL
);
607 int height
= FONT_HEIGHT (s
->font
), ascent
= FONT_BASE (s
->font
);
609 /* Font's global height and ascent values might be
610 preposterously large for some fonts. We fix here the case
611 when those fonts are used for display of glyphless
612 characters, because drawing background with font dimensions
613 in those cases makes the display illegible. There's only one
614 more call to the draw method with with_background set to
615 true, and that's in x_draw_glyph_string_foreground, when
616 drawing the cursor, where we have no such heuristics
618 if (s
->first_glyph
->type
== GLYPHLESS_GLYPH
619 && (s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
620 || s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
))
622 s
->first_glyph
->slice
.glyphless
.lower_yoff
623 - s
->first_glyph
->slice
.glyphless
.upper_yoff
;
624 XftDrawRect (xft_draw
, &bg
, x
, y
- ascent
, s
->width
, height
);
626 code
= alloca (sizeof (FT_UInt
) * len
);
627 for (i
= 0; i
< len
; i
++)
628 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
629 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
632 for (i
= 0; i
< len
; i
++)
633 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
634 x
+ i
, y
, code
+ i
, 1);
636 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
643 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
645 xftfont_shape (Lisp_Object lgstring
)
647 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
648 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
652 ft_face
= XftLockFace (xftfont_info
->xftfont
);
653 xftfont_info
->ft_size
= ft_face
->size
;
654 val
= ftfont_driver
.shape (lgstring
);
655 XftUnlockFace (xftfont_info
->xftfont
);
661 xftfont_end_for_frame (struct frame
*f
)
665 /* Don't do anything if display is dead */
666 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
668 xft_draw
= font_get_frame_data (f
, Qxft
);
673 XftDrawDestroy (xft_draw
);
675 font_put_frame_data (f
, Qxft
, NULL
);
681 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
684 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
685 FcPattern
*oldpat
= info
->xftfont
->pattern
;
686 Display
*display
= FRAME_X_DISPLAY (f
);
687 FcPattern
*pat
= FcPatternCreate ();
692 xftfont_add_rendering_parameters (pat
, entity
);
693 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
695 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
696 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
697 if (r1
!= r2
|| b1
!= b2
) goto out
;
698 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
699 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
700 if (r1
!= r2
|| b1
!= b2
) goto out
;
701 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
702 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
703 if (r1
!= r2
|| b1
!= b2
) goto out
;
705 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
706 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
707 if (r1
!= r2
|| b1
!= b2
) goto out
;
709 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
710 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
711 if (r1
!= r2
|| i1
!= i2
) goto out
;
712 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
713 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
714 if (r1
!= r2
|| i1
!= i2
) goto out
;
715 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
716 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
717 if (r1
!= r2
|| i1
!= i2
) goto out
;
721 FcPatternDestroy (pat
);
726 syms_of_xftfont (void)
728 DEFSYM (Qxft
, "xft");
729 DEFSYM (QChinting
, ":hinting");
730 DEFSYM (QCautohint
, ":autohint");
731 DEFSYM (QChintstyle
, ":hintstyle");
732 DEFSYM (QCrgba
, ":rgba");
733 DEFSYM (QCembolden
, ":embolden");
734 DEFSYM (QClcdfilter
, ":lcdfilter");
736 ascii_printable
[0] = 0;
738 xftfont_driver
= ftfont_driver
;
739 xftfont_driver
.type
= Qxft
;
740 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
741 xftfont_driver
.list
= xftfont_list
;
742 xftfont_driver
.match
= xftfont_match
;
743 xftfont_driver
.open
= xftfont_open
;
744 xftfont_driver
.close
= xftfont_close
;
745 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
746 xftfont_driver
.done_face
= xftfont_done_face
;
747 xftfont_driver
.has_char
= xftfont_has_char
;
748 xftfont_driver
.encode_char
= xftfont_encode_char
;
749 xftfont_driver
.text_extents
= xftfont_text_extents
;
750 xftfont_driver
.draw
= xftfont_draw
;
751 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
752 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
753 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
754 xftfont_driver
.shape
= xftfont_shape
;
757 register_font_driver (&xftfont_driver
, NULL
);