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 /* The following workaround is unnecessary on most systems, and
399 causes annoying differences in glyph height between regular and
400 bold fonts (see bug#22383). However, with some fonts, such as
401 monaco, removing the workaround results in overlapping vertical
402 space of a line, see bug#23360. As long as the way to reconcile
403 these opposites is not known, we provide a user option to work
404 around the problem. */
406 && xft_font_ascent_descent_override
)
408 /* The above condition is a dirty workaround because
409 XftTextExtents8 behaves strangely for some fonts
410 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
411 if (font
->ascent
< extents
.y
)
412 font
->ascent
= extents
.y
;
413 if (font
->descent
< extents
.height
- extents
.y
)
414 font
->descent
= extents
.height
- extents
.y
;
416 font
->height
= font
->ascent
+ font
->descent
;
418 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
420 int upEM
= ft_face
->units_per_EM
;
422 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
423 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
424 if (font
->underline_thickness
> 2)
425 font
->underline_position
-= font
->underline_thickness
/ 2;
429 font
->underline_position
= -1;
430 font
->underline_thickness
= 0;
433 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
434 xftfont_info
->otf
= NULL
;
435 #endif /* HAVE_LIBOTF */
436 xftfont_info
->ft_size
= ft_face
->size
;
438 font
->baseline_offset
= 0;
439 font
->relative_compose
= 0;
440 font
->default_ascent
= 0;
441 font
->vertical_centering
= false;
443 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
447 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
448 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
449 font
->baseline_offset
= rec
.u
.integer
;
450 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
451 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
452 font
->relative_compose
= rec
.u
.integer
;
453 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
454 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
455 font
->default_ascent
= rec
.u
.integer
;
463 xftfont_close (struct font
*font
)
465 struct x_display_info
*xdi
;
466 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
469 if (xftfont_info
->otf
)
471 OTF_close (xftfont_info
->otf
);
472 xftfont_info
->otf
= NULL
;
476 /* See comment in xfont_close. */
477 if (xftfont_info
->xftfont
478 && ((xdi
= x_display_info_for_display (xftfont_info
->display
))
479 && xftfont_info
->x_display_id
== xdi
->x_id
))
482 XftUnlockFace (xftfont_info
->xftfont
);
483 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
485 xftfont_info
->xftfont
= NULL
;
490 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
492 struct xftface_info
*xftface_info
;
495 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
496 if (face
!= face
->ascii_face
)
498 face
->extra
= face
->ascii_face
->extra
;
503 xftface_info
= xmalloc (sizeof *xftface_info
);
504 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
505 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
506 face
->extra
= xftface_info
;
510 xftfont_done_face (struct frame
*f
, struct face
*face
)
512 struct xftface_info
*xftface_info
;
515 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
516 if (face
!= face
->ascii_face
521 xftface_info
= (struct xftface_info
*) face
->extra
;
524 xfree (xftface_info
);
530 xftfont_has_char (Lisp_Object font
, int c
)
532 struct xftfont_info
*xftfont_info
;
533 struct charset
*cs
= NULL
;
535 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
536 && charset_jisx0208
>= 0)
537 cs
= CHARSET_FROM_ID (charset_jisx0208
);
538 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
539 && charset_ksc5601
>= 0)
540 cs
= CHARSET_FROM_ID (charset_ksc5601
);
542 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
544 if (FONT_ENTITY_P (font
))
545 return ftfont_driver
.has_char (font
, c
);
546 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
547 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
548 (FcChar32
) c
) == FcTrue
);
552 xftfont_encode_char (struct font
*font
, int c
)
554 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
555 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
558 return (code
? code
: FONT_INVALID_CODE
);
562 xftfont_text_extents (struct font
*font
, unsigned int *code
,
563 int nglyphs
, struct font_metrics
*metrics
)
565 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
569 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
573 metrics
->lbearing
= - extents
.x
;
574 metrics
->rbearing
= - extents
.x
+ extents
.width
;
575 metrics
->width
= extents
.xOff
;
576 metrics
->ascent
= extents
.y
;
577 metrics
->descent
= extents
.height
- extents
.y
;
581 xftfont_get_xft_draw (struct frame
*f
)
583 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
588 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
591 FRAME_X_COLORMAP (f
));
593 eassert (xft_draw
!= NULL
);
594 font_put_frame_data (f
, Qxft
, xft_draw
);
600 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
601 bool with_background
)
603 struct frame
*f
= s
->f
;
604 struct face
*face
= s
->face
;
605 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
606 struct xftface_info
*xftface_info
= NULL
;
607 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
613 if (s
->font
== face
->font
)
614 xftface_info
= (struct xftface_info
*) face
->extra
;
615 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
616 &fg
, with_background
? &bg
: NULL
);
618 if (s
->num_clips
> 0)
619 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
621 XftDrawSetClip (xft_draw
, NULL
);
625 int height
= FONT_HEIGHT (s
->font
), ascent
= FONT_BASE (s
->font
);
627 /* Font's global height and ascent values might be
628 preposterously large for some fonts. We fix here the case
629 when those fonts are used for display of glyphless
630 characters, because drawing background with font dimensions
631 in those cases makes the display illegible. There's only one
632 more call to the draw method with with_background set to
633 true, and that's in x_draw_glyph_string_foreground, when
634 drawing the cursor, where we have no such heuristics
636 if (s
->first_glyph
->type
== GLYPHLESS_GLYPH
637 && (s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
638 || s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
))
640 s
->first_glyph
->slice
.glyphless
.lower_yoff
641 - s
->first_glyph
->slice
.glyphless
.upper_yoff
;
642 XftDrawRect (xft_draw
, &bg
, x
, y
- ascent
, s
->width
, height
);
644 code
= alloca (sizeof (FT_UInt
) * len
);
645 for (i
= 0; i
< len
; i
++)
646 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
647 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
650 for (i
= 0; i
< len
; i
++)
651 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
652 x
+ i
, y
, code
+ i
, 1);
654 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
661 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
663 xftfont_shape (Lisp_Object lgstring
)
665 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
666 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
670 ft_face
= XftLockFace (xftfont_info
->xftfont
);
671 xftfont_info
->ft_size
= ft_face
->size
;
672 val
= ftfont_driver
.shape (lgstring
);
673 XftUnlockFace (xftfont_info
->xftfont
);
679 xftfont_end_for_frame (struct frame
*f
)
683 /* Don't do anything if display is dead */
684 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
686 xft_draw
= font_get_frame_data (f
, Qxft
);
691 XftDrawDestroy (xft_draw
);
693 font_put_frame_data (f
, Qxft
, NULL
);
699 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
702 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
703 FcPattern
*oldpat
= info
->xftfont
->pattern
;
704 Display
*display
= FRAME_X_DISPLAY (f
);
705 FcPattern
*pat
= FcPatternCreate ();
710 xftfont_add_rendering_parameters (pat
, entity
);
711 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
713 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
714 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
715 if (r1
!= r2
|| b1
!= b2
) goto out
;
716 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
717 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
718 if (r1
!= r2
|| b1
!= b2
) goto out
;
719 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
720 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
721 if (r1
!= r2
|| b1
!= b2
) goto out
;
723 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
724 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
725 if (r1
!= r2
|| b1
!= b2
) goto out
;
727 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
728 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
729 if (r1
!= r2
|| i1
!= i2
) goto out
;
730 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
731 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
732 if (r1
!= r2
|| i1
!= i2
) goto out
;
733 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
734 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
735 if (r1
!= r2
|| i1
!= i2
) goto out
;
739 FcPatternDestroy (pat
);
744 syms_of_xftfont (void)
746 DEFSYM (Qxft
, "xft");
747 DEFSYM (QChinting
, ":hinting");
748 DEFSYM (QCautohint
, ":autohint");
749 DEFSYM (QChintstyle
, ":hintstyle");
750 DEFSYM (QCrgba
, ":rgba");
751 DEFSYM (QCembolden
, ":embolden");
752 DEFSYM (QClcdfilter
, ":lcdfilter");
754 DEFVAR_BOOL ("xft-font-ascent-descent-override",
755 xft_font_ascent_descent_override
,
756 doc
: /* Non-nil means override the ascent and descent values for Xft font driver.
757 This is needed with some fonts to correct vertical overlap of glyphs. */);
758 xft_font_ascent_descent_override
= 0;
760 ascii_printable
[0] = 0;
762 xftfont_driver
= ftfont_driver
;
763 xftfont_driver
.type
= Qxft
;
764 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
765 xftfont_driver
.list
= xftfont_list
;
766 xftfont_driver
.match
= xftfont_match
;
767 xftfont_driver
.open
= xftfont_open
;
768 xftfont_driver
.close
= xftfont_close
;
769 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
770 xftfont_driver
.done_face
= xftfont_done_face
;
771 xftfont_driver
.has_char
= xftfont_has_char
;
772 xftfont_driver
.encode_char
= xftfont_encode_char
;
773 xftfont_driver
.text_extents
= xftfont_text_extents
;
774 xftfont_driver
.draw
= xftfont_draw
;
775 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
776 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
777 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
778 xftfont_driver
.shape
= xftfont_shape
;
781 register_font_driver (&xftfont_driver
, NULL
);